Snap for 6439596 from 7696e800b89ca053010aeace2a8e6eae659a4104 to qt-aml-tzdata-release

Change-Id: Idd2d6970722561f86afd4e75646c9768a12b13ed
diff --git a/.gitignore b/.gitignore
index 655f094..94e335a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,4 @@
 .android_config
-.ccls-cache
 .cproject
 .deps_sha1
 .DS_Store
@@ -13,7 +12,6 @@
 *.iml
 *.pyc
 *.swp
-/bazel-*
 /out*
 TAGS
 /node_modules/
@@ -21,4 +19,3 @@
 .vscode
 *.code-workspace
 /fuzz_out/
-/bazel-*
diff --git a/.style.yapf b/.style.yapf
deleted file mode 100644
index de0c6a7..0000000
--- a/.style.yapf
+++ /dev/null
@@ -1,2 +0,0 @@
-[style]
-based_on_style = chromium
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..2d53e22
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,191 @@
+# Copyright (C) 2017 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.
+
+notifications:
+  email: false
+
+language: cpp
+
+# The |CFG| variable name is hooked up by the perfetto-ci.appspot.com frontend.
+# Please keep infra/perfetto-ci.appspot.com/ updated when adding/removing
+# entries below.
+matrix:
+  include:
+# OS X builds are processing too slow and block the queue.
+# Commenting out until the problem is resolved.
+#    - os: osx
+#      osx_image: xcode8.3
+#      compiler: clang
+#      env: CFG=mac-clang-x86_64-release GN_ARGS="is_debug=false"
+#    - os: osx
+#      osx_image: xcode8.3
+#      compiler: clang
+#      env: CFG=mac-clang-x86_64-debug GN_ARGS="is_debug=true"
+#    - os: osx
+#      osx_image: xcode8.3
+#      compiler: clang
+#      env: CFG=mac-clang-x86_64-asan GN_ARGS="is_debug=false is_asan=true"
+#    - os: osx
+#      osx_image: xcode8.3
+#      compiler: clang
+#      env: CFG=mac-clang-x86_64-tsan GN_ARGS="is_debug=false is_tsan=true"
+#    - os: osx
+#      osx_image: xcode8.3
+#      compiler: clang
+#      env: CFG=mac-clang-x86_64-ubsan GN_ARGS="is_debug=false is_ubsan=true"
+    - os: linux
+      dist: xenial
+      sudo: false
+      # Test the system-version of clang, not our own at least in this config.
+      addons:
+        apt:
+          packages:
+            - clang
+      env: CFG=linux_trusty-clang-x86_64-debug GN_ARGS="is_debug=true is_hermetic_clang=false"
+    - os: linux
+      dist: xenial
+      sudo: false
+      compiler: clang
+      env: CFG=linux_trusty-clang-x86_64-tsan GN_ARGS="is_debug=false is_tsan=true"
+    - os: linux
+      dist: xenial
+      sudo: false
+      compiler: clang
+      env: CFG=linux_trusty-clang-x86_64-msan GN_ARGS="is_debug=false is_msan=true"
+# TODO(b/117093687): ubsan always times out in Travis.
+# Re-enable once that is fixed.
+    - os: linux
+      dist: xenial
+      sudo: true
+      compiler: clang
+      env: CFG=linux_trusty-clang-x86_64-asan_lsan GN_ARGS="is_debug=false is_asan=true is_lsan=true"
+    - os: linux
+      dist: xenial
+      sudo: false
+      addons:
+        apt:
+          sources:
+            - ubuntu-toolchain-r-test
+          packages:
+            - g++-7
+      env: CFG=linux_trusty-gcc7-x86_64-release GN_ARGS="is_debug=false is_clang=false use_custom_libcxx=false cc=\"gcc-7\" cxx=\"g++-7\""
+    - os: linux
+      dist: xenial
+      sudo: false
+      compiler: clang
+      env: CFG=android-clang-arm-release GN_ARGS="is_debug=false target_os=\"android\" target_cpu=\"arm\""
+    - os: linux
+      dist: xenial
+      sudo: true
+      compiler: clang
+      env: CFG=android-clang-arm-asan GN_ARGS="is_debug=false target_os=\"android\" target_cpu=\"arm\" is_asan=true"
+    - os: linux
+      dist: xenial
+      sudo: true
+      compiler: clang
+      env: CFG=linux_trusty-clang-x86_64-libfuzzer GN_ARGS="is_clang=true is_debug=false is_fuzzer=true is_asan=true"
+    - os: linux
+      dist: xenial
+      sudo: false
+      compiler: clang
+      env: CFG=ui-clang-x86_64-release GN_ARGS="is_debug=false is_clang=true"
+    - os: linux
+      dist: xenial
+      sudo: false
+      compiler: clang
+      env: CFG=ui-clang-x86_64-debug GN_ARGS="is_debug=true is_clang=true"
+
+
+# Cache the deps that get git-pulled to avoid hitting quota limits (b/68252114).
+# Do not cache NDK/SDK and things that come from .zip files rather than git.
+# Doing that is discouraged (https://docs.travis-ci.com/user/caching/).
+cache:
+  timeout: 1800  # 30 mins
+  directories:
+    - buildtools/android-core
+    - buildtools/benchmark
+    - buildtools/bionic
+    - buildtools/emulator
+    - buildtools/googletest
+    - buildtools/jsoncpp
+    - buildtools/libbacktrace
+    - buildtools/libcxx
+    - buildtools/libcxxabi
+    - buildtools/libfuzzer
+    - buildtools/libunwind
+    - buildtools/linenoise
+    - buildtools/lzma
+
+before_install:
+  - set -e
+  - echo "$CFG" && echo "$GN_ARGS"
+  - export ASAN_SYMBOLIZER_PATH="$(which llvm-symbolizer
+      || echo /usr/bin/llvm-symbolizer-*)"
+  - pip install --user protobuf
+
+install:
+  - |
+    if [[ "$CFG" == android-* ]]; then
+      tools/install-build-deps
+    elif [[ "$CFG" == ui-* ]]; then
+      tools/install-build-deps --no-android --ui
+    else
+      tools/install-build-deps --no-android
+    fi
+  - |
+    if [[ -e buildtools/clang/bin/llvm-symbolizer ]]; then
+      export ASAN_SYMBOLIZER_PATH="buildtools/clang/bin/llvm-symbolizer"
+    fi
+
+script:
+  - tools/gn gen out/dist --args="${GN_ARGS}" --check
+  - |
+    if [[ "$CFG" == ui-* ]]; then
+      tools/ninja -C out/dist ui 2>&1 | grep -v "no version information"
+    elif [[ "$CFG" == *-libfuzzer ]]; then
+      tools/ninja -C out/dist fuzzers
+    else
+      tools/ninja -C out/dist
+    fi
+  - |
+    TEST_TARGETS="
+    perfetto_integrationtests
+    perfetto_unittests
+    "
+    if [[ "$CFG" == ui-* ]]; then
+      out/dist/ui_unittests --ci
+    elif [[ "$CFG" == *-libfuzzer ]]; then
+      # Run a single iteration each to make sure they are not crashing.
+      for fuzzer in $(find out/dist -name '*_fuzzer' -executable); do
+        $fuzzer -runs=1
+      done
+    elif [[ "$CFG" == android-* ]]; then
+      TARGET_ARCH=$(echo $CFG | cut -d- -f3)
+      tools/run_android_emulator --pid /tmp/emulator.pid -v &
+      for TEST_TARGET in $TEST_TARGETS; do
+        tools/run_android_test out/dist "$TEST_TARGET"
+      done
+      tools/run_android_test --env BENCHMARK_FUNCTIONAL_TEST_ONLY=true out/dist "perfetto_benchmarks"
+    else
+      for TEST_TARGET in $TEST_TARGETS; do
+        "out/dist/$TEST_TARGET"
+      done
+      BENCHMARK_FUNCTIONAL_TEST_ONLY=true out/dist/perfetto_benchmarks
+
+      tools/diff_test_trace_processor.py --test-type=queries out/dist/trace_processor_shell
+      tools/diff_test_trace_processor.py --test-type=metrics out/dist/trace_processor_shell
+    fi
+
+after_script:
+  - test -f /tmp/emulator.pid && kill -9 $(cat /tmp/emulator.pid); true
diff --git a/Android.bp b/Android.bp
index bad324b..a11041a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -14,33 +14,11 @@
 //
 // This file is automatically generated by tools/gen_android_bp. Do not edit.
 
-// GN: //src/trace_processor/metrics:gen_merged_sql_metrics
 genrule {
   name: "gen_merged_sql_metrics",
   srcs: [
-    "src/trace_processor/metrics/android/android_batt.sql",
-    "src/trace_processor/metrics/android/android_cpu.sql",
-    "src/trace_processor/metrics/android/android_cpu_agg.sql",
-    "src/trace_processor/metrics/android/android_ion.sql",
-    "src/trace_processor/metrics/android/android_lmk.sql",
     "src/trace_processor/metrics/android/android_mem.sql",
-    "src/trace_processor/metrics/android/android_mem_unagg.sql",
-    "src/trace_processor/metrics/android/android_package_list.sql",
-    "src/trace_processor/metrics/android/android_powrails.sql",
-    "src/trace_processor/metrics/android/android_process_growth.sql",
-    "src/trace_processor/metrics/android/android_startup.sql",
-    "src/trace_processor/metrics/android/android_startup_cpu.sql",
-    "src/trace_processor/metrics/android/android_startup_launches.sql",
-    "src/trace_processor/metrics/android/android_task_state.sql",
-    "src/trace_processor/metrics/android/heap_profile_callsites.sql",
-    "src/trace_processor/metrics/android/java_heap_stats.sql",
-    "src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql",
-    "src/trace_processor/metrics/android/process_mem.sql",
-    "src/trace_processor/metrics/android/process_unagg_mem_view.sql",
-    "src/trace_processor/metrics/android/span_view_stats.sql",
-    "src/trace_processor/metrics/android/unsymbolized_frames.sql",
-    "src/trace_processor/metrics/android/upid_span_view.sql",
-    "src/trace_processor/metrics/trace_metadata.sql",
+    "src/trace_processor/metrics/android/android_mem_lmk.sql",
   ],
   cmd: "$(location tools/gen_merged_sql_metrics.py) --cpp_out=$(out) $(in)",
   out: [
@@ -51,80 +29,96 @@
   ],
 }
 
-// GN: //src/profiling/memory:heapprofd
+// GN target: //:heapprofd
 cc_binary {
   name: "heapprofd",
   srcs: [
-    ":perfetto_include_perfetto_base_base",
-    ":perfetto_include_perfetto_ext_base_base",
-    ":perfetto_include_perfetto_ext_ipc_ipc",
-    ":perfetto_include_perfetto_ext_tracing_core_core",
-    ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
-    ":perfetto_include_perfetto_profiling_normalize",
-    ":perfetto_include_perfetto_protozero_protozero",
-    ":perfetto_include_perfetto_tracing_core_core",
-    ":perfetto_include_perfetto_tracing_tracing",
-    ":perfetto_protos_perfetto_common_cpp_gen",
     ":perfetto_protos_perfetto_common_lite_gen",
     ":perfetto_protos_perfetto_common_zero_gen",
-    ":perfetto_protos_perfetto_config_android_cpp_gen",
-    ":perfetto_protos_perfetto_config_android_lite_gen",
-    ":perfetto_protos_perfetto_config_android_zero_gen",
-    ":perfetto_protos_perfetto_config_cpp_gen",
-    ":perfetto_protos_perfetto_config_ftrace_cpp_gen",
-    ":perfetto_protos_perfetto_config_ftrace_lite_gen",
-    ":perfetto_protos_perfetto_config_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_config_gpu_cpp_gen",
-    ":perfetto_protos_perfetto_config_gpu_lite_gen",
-    ":perfetto_protos_perfetto_config_gpu_zero_gen",
-    ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
-    ":perfetto_protos_perfetto_config_inode_file_lite_gen",
-    ":perfetto_protos_perfetto_config_inode_file_zero_gen",
     ":perfetto_protos_perfetto_config_lite_gen",
-    ":perfetto_protos_perfetto_config_power_cpp_gen",
-    ":perfetto_protos_perfetto_config_power_lite_gen",
-    ":perfetto_protos_perfetto_config_power_zero_gen",
-    ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_process_stats_lite_gen",
-    ":perfetto_protos_perfetto_config_process_stats_zero_gen",
-    ":perfetto_protos_perfetto_config_profiling_cpp_gen",
-    ":perfetto_protos_perfetto_config_profiling_lite_gen",
-    ":perfetto_protos_perfetto_config_profiling_zero_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_lite_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_config_zero_gen",
     ":perfetto_protos_perfetto_ipc_ipc_gen",
-    ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
     ":perfetto_protos_perfetto_trace_android_zero_gen",
     ":perfetto_protos_perfetto_trace_chrome_zero_gen",
     ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
     ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_trace_gpu_zero_gen",
     ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
     ":perfetto_protos_perfetto_trace_minimal_lite_gen",
-    ":perfetto_protos_perfetto_trace_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
     ":perfetto_protos_perfetto_trace_power_zero_gen",
     ":perfetto_protos_perfetto_trace_profiling_zero_gen",
     ":perfetto_protos_perfetto_trace_ps_zero_gen",
     ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
     ":perfetto_protos_perfetto_trace_trusted_lite_gen",
-    ":perfetto_src_base_base",
-    ":perfetto_src_base_unix_socket",
-    ":perfetto_src_ipc_ipc",
-    ":perfetto_src_profiling_memory_daemon",
-    ":perfetto_src_profiling_memory_proc_utils",
-    ":perfetto_src_profiling_memory_ring_buffer",
-    ":perfetto_src_profiling_memory_scoped_spinlock",
-    ":perfetto_src_profiling_memory_wire_protocol",
-    ":perfetto_src_protozero_protozero",
-    ":perfetto_src_tracing_common",
-    ":perfetto_src_tracing_ipc",
-    ":perfetto_src_tracing_tracing",
+    ":perfetto_protos_perfetto_trace_zero_gen",
+    ":perfetto_src_ipc_wire_protocol_gen",
+    "src/base/event.cc",
+    "src/base/file_utils.cc",
+    "src/base/metatrace.cc",
+    "src/base/paged_memory.cc",
+    "src/base/pipe.cc",
+    "src/base/string_splitter.cc",
+    "src/base/string_utils.cc",
+    "src/base/string_view.cc",
+    "src/base/temp_file.cc",
+    "src/base/thread_checker.cc",
+    "src/base/thread_task_runner.cc",
+    "src/base/time.cc",
+    "src/base/unix_socket.cc",
+    "src/base/unix_task_runner.cc",
+    "src/base/virtual_destructors.cc",
+    "src/base/watchdog_posix.cc",
+    "src/ipc/buffered_frame_deserializer.cc",
+    "src/ipc/client_impl.cc",
+    "src/ipc/deferred.cc",
+    "src/ipc/host_impl.cc",
+    "src/ipc/service_proxy.cc",
+    "src/ipc/virtual_destructors.cc",
+    "src/profiling/memory/bookkeeping.cc",
+    "src/profiling/memory/heapprofd_producer.cc",
     "src/profiling/memory/main.cc",
+    "src/profiling/memory/proc_utils.cc",
+    "src/profiling/memory/scoped_spinlock.cc",
+    "src/profiling/memory/shared_ring_buffer.cc",
+    "src/profiling/memory/system_property.cc",
+    "src/profiling/memory/unwinding.cc",
+    "src/profiling/memory/wire_protocol.cc",
+    "src/protozero/message.cc",
+    "src/protozero/message_handle.cc",
+    "src/protozero/proto_decoder.cc",
+    "src/protozero/scattered_heap_buffer.cc",
+    "src/protozero/scattered_stream_null_delegate.cc",
+    "src/protozero/scattered_stream_writer.cc",
+    "src/tracing/core/android_log_config.cc",
+    "src/tracing/core/android_power_config.cc",
+    "src/tracing/core/chrome_config.cc",
+    "src/tracing/core/commit_data_request.cc",
+    "src/tracing/core/data_source_config.cc",
+    "src/tracing/core/data_source_descriptor.cc",
+    "src/tracing/core/ftrace_config.cc",
+    "src/tracing/core/heapprofd_config.cc",
+    "src/tracing/core/id_allocator.cc",
+    "src/tracing/core/inode_file_config.cc",
+    "src/tracing/core/null_trace_writer.cc",
+    "src/tracing/core/observable_events.cc",
+    "src/tracing/core/packages_list_config.cc",
+    "src/tracing/core/packet_stream_validator.cc",
+    "src/tracing/core/process_stats_config.cc",
+    "src/tracing/core/shared_memory_abi.cc",
+    "src/tracing/core/shared_memory_arbiter_impl.cc",
+    "src/tracing/core/sliced_protobuf_input_stream.cc",
+    "src/tracing/core/startup_trace_writer.cc",
+    "src/tracing/core/startup_trace_writer_registry.cc",
+    "src/tracing/core/sys_stats_config.cc",
+    "src/tracing/core/test_config.cc",
+    "src/tracing/core/trace_buffer.cc",
+    "src/tracing/core/trace_config.cc",
+    "src/tracing/core/trace_packet.cc",
+    "src/tracing/core/trace_stats.cc",
+    "src/tracing/core/trace_writer_impl.cc",
+    "src/tracing/core/tracing_service_impl.cc",
+    "src/tracing/core/tracing_service_state.cc",
+    "src/tracing/core/virtual_destructors.cc",
   ],
   shared_libs: [
     "libbase",
@@ -133,58 +127,33 @@
     "libprotobuf-cpp-lite",
     "libunwindstack",
   ],
+  static_libs: [
+    "libgtest_prod",
+    "perfetto_src_tracing_ipc",
+  ],
   init_rc: [
     "heapprofd.rc",
   ],
   generated_headers: [
-    "perfetto_protos_perfetto_common_cpp_gen_headers",
     "perfetto_protos_perfetto_common_lite_gen_headers",
     "perfetto_protos_perfetto_common_zero_gen_headers",
-    "perfetto_protos_perfetto_config_android_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_android_lite_gen_headers",
-    "perfetto_protos_perfetto_config_android_zero_gen_headers",
-    "perfetto_protos_perfetto_config_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
     "perfetto_protos_perfetto_config_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_power_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_zero_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_zero_gen_headers",
     "perfetto_protos_perfetto_ipc_ipc_gen_headers",
-    "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
     "perfetto_protos_perfetto_trace_android_zero_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
     "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
     "perfetto_protos_perfetto_trace_power_zero_gen_headers",
     "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
     "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
     "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_zero_gen_headers",
+    "perfetto_src_ipc_wire_protocol_gen_headers",
   ],
   defaults: [
     "perfetto_defaults",
@@ -192,24 +161,36 @@
   cflags: [
     "-DGOOGLE_PROTOBUF_NO_RTTI",
     "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+    "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
 }
 
-// GN: //src/profiling/memory:heapprofd_client
+// GN target: //:heapprofd_client
 cc_library_shared {
   name: "heapprofd_client",
   srcs: [
-    ":perfetto_include_perfetto_base_base",
-    ":perfetto_include_perfetto_ext_base_base",
-    ":perfetto_include_perfetto_profiling_normalize",
-    ":perfetto_src_base_base",
-    ":perfetto_src_base_unix_socket",
-    ":perfetto_src_profiling_memory_client",
-    ":perfetto_src_profiling_memory_malloc_hooks",
-    ":perfetto_src_profiling_memory_proc_utils",
-    ":perfetto_src_profiling_memory_ring_buffer",
-    ":perfetto_src_profiling_memory_scoped_spinlock",
-    ":perfetto_src_profiling_memory_wire_protocol",
+    "src/base/event.cc",
+    "src/base/file_utils.cc",
+    "src/base/metatrace.cc",
+    "src/base/paged_memory.cc",
+    "src/base/pipe.cc",
+    "src/base/string_splitter.cc",
+    "src/base/string_utils.cc",
+    "src/base/string_view.cc",
+    "src/base/temp_file.cc",
+    "src/base/thread_checker.cc",
+    "src/base/thread_task_runner.cc",
+    "src/base/time.cc",
+    "src/base/unix_socket.cc",
+    "src/base/unix_task_runner.cc",
+    "src/base/virtual_destructors.cc",
+    "src/base/watchdog_posix.cc",
+    "src/profiling/memory/client.cc",
+    "src/profiling/memory/malloc_hooks.cc",
+    "src/profiling/memory/proc_utils.cc",
+    "src/profiling/memory/scoped_spinlock.cc",
+    "src/profiling/memory/shared_ring_buffer.cc",
+    "src/profiling/memory/wire_protocol.cc",
   ],
   shared_libs: [
     "libbase",
@@ -218,191 +199,164 @@
   ],
   static_libs: [
     "libasync_safe",
-  ],
-  export_include_dirs: [
-    "include",
-    "include/perfetto/base/build_configs/android_tree",
+    "libgtest_prod",
   ],
   defaults: [
     "perfetto_defaults",
   ],
   cflags: [
     "-DPERFETTO_ANDROID_ASYNC_SAFE_LOG",
+    "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
   include_dirs: [
     "bionic/libc",
   ],
-  header_libs: [
-    "bionic_libc_platform_headers",
-  ],
 }
 
-// GN: //src/ipc/protoc_plugin:ipc_plugin
-cc_binary_host {
-  name: "ipc_plugin",
-  srcs: [
-    ":perfetto_include_perfetto_base_base",
-    ":perfetto_include_perfetto_ext_base_base",
-    ":perfetto_src_base_base",
-    "src/ipc/protoc_plugin/ipc_plugin.cc",
-  ],
-  static_libs: [
-    "libprotoc",
-  ],
-  defaults: [
-    "perfetto_defaults",
-  ],
-  cflags: [
-    "-DGOOGLE_PROTOBUF_NO_RTTI",
-    "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
-  ],
-}
-
-// GN: //:libperfetto
+// GN target: //:libperfetto
 cc_library_shared {
   name: "libperfetto",
   srcs: [
-    ":perfetto_include_perfetto_base_base",
-    ":perfetto_include_perfetto_ext_base_base",
-    ":perfetto_include_perfetto_ext_ipc_ipc",
-    ":perfetto_include_perfetto_ext_traced_sys_stats_counters",
-    ":perfetto_include_perfetto_ext_traced_traced",
-    ":perfetto_include_perfetto_ext_tracing_core_core",
-    ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
-    ":perfetto_include_perfetto_protozero_protozero",
-    ":perfetto_include_perfetto_public_public",
-    ":perfetto_include_perfetto_tracing_core_core",
-    ":perfetto_include_perfetto_tracing_tracing",
-    ":perfetto_protos_perfetto_common_cpp_gen",
     ":perfetto_protos_perfetto_common_lite_gen",
     ":perfetto_protos_perfetto_common_zero_gen",
-    ":perfetto_protos_perfetto_config_android_cpp_gen",
-    ":perfetto_protos_perfetto_config_android_lite_gen",
-    ":perfetto_protos_perfetto_config_android_zero_gen",
-    ":perfetto_protos_perfetto_config_cpp_gen",
-    ":perfetto_protos_perfetto_config_ftrace_cpp_gen",
-    ":perfetto_protos_perfetto_config_ftrace_lite_gen",
-    ":perfetto_protos_perfetto_config_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_config_gpu_cpp_gen",
-    ":perfetto_protos_perfetto_config_gpu_lite_gen",
-    ":perfetto_protos_perfetto_config_gpu_zero_gen",
-    ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
-    ":perfetto_protos_perfetto_config_inode_file_lite_gen",
-    ":perfetto_protos_perfetto_config_inode_file_zero_gen",
     ":perfetto_protos_perfetto_config_lite_gen",
-    ":perfetto_protos_perfetto_config_power_cpp_gen",
-    ":perfetto_protos_perfetto_config_power_lite_gen",
-    ":perfetto_protos_perfetto_config_power_zero_gen",
-    ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_process_stats_lite_gen",
-    ":perfetto_protos_perfetto_config_process_stats_zero_gen",
-    ":perfetto_protos_perfetto_config_profiling_cpp_gen",
-    ":perfetto_protos_perfetto_config_profiling_lite_gen",
-    ":perfetto_protos_perfetto_config_profiling_zero_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_lite_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_config_zero_gen",
     ":perfetto_protos_perfetto_ipc_ipc_gen",
-    ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
     ":perfetto_protos_perfetto_trace_android_zero_gen",
     ":perfetto_protos_perfetto_trace_chrome_zero_gen",
     ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
     ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_trace_gpu_zero_gen",
     ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
     ":perfetto_protos_perfetto_trace_minimal_lite_gen",
-    ":perfetto_protos_perfetto_trace_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
     ":perfetto_protos_perfetto_trace_power_zero_gen",
     ":perfetto_protos_perfetto_trace_profiling_zero_gen",
     ":perfetto_protos_perfetto_trace_ps_zero_gen",
     ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
     ":perfetto_protos_perfetto_trace_trusted_lite_gen",
-    ":perfetto_src_android_internal_headers",
-    ":perfetto_src_android_internal_lazy_library_loader",
-    ":perfetto_src_base_base",
-    ":perfetto_src_base_unix_socket",
-    ":perfetto_src_ipc_ipc",
-    ":perfetto_src_protozero_protozero",
-    ":perfetto_src_traced_probes_android_log_android_log",
-    ":perfetto_src_traced_probes_data_source",
-    ":perfetto_src_traced_probes_filesystem_filesystem",
-    ":perfetto_src_traced_probes_ftrace_format_parser",
-    ":perfetto_src_traced_probes_ftrace_ftrace",
-    ":perfetto_src_traced_probes_metatrace_metatrace",
-    ":perfetto_src_traced_probes_packages_list_packages_list",
-    ":perfetto_src_traced_probes_power_power",
-    ":perfetto_src_traced_probes_probes",
-    ":perfetto_src_traced_probes_probes_src",
-    ":perfetto_src_traced_probes_ps_ps",
-    ":perfetto_src_traced_probes_sys_stats_sys_stats",
-    ":perfetto_src_traced_service_service",
-    ":perfetto_src_tracing_common",
-    ":perfetto_src_tracing_consumer_api_deprecated",
-    ":perfetto_src_tracing_ipc",
-    ":perfetto_src_tracing_tracing",
+    ":perfetto_protos_perfetto_trace_zero_gen",
+    ":perfetto_src_ipc_wire_protocol_gen",
+    "src/android_internal/lazy_library_loader.cc",
+    "src/base/event.cc",
+    "src/base/file_utils.cc",
+    "src/base/metatrace.cc",
+    "src/base/paged_memory.cc",
+    "src/base/pipe.cc",
+    "src/base/string_splitter.cc",
+    "src/base/string_utils.cc",
+    "src/base/string_view.cc",
+    "src/base/temp_file.cc",
+    "src/base/thread_checker.cc",
+    "src/base/thread_task_runner.cc",
+    "src/base/time.cc",
+    "src/base/unix_socket.cc",
+    "src/base/unix_task_runner.cc",
+    "src/base/virtual_destructors.cc",
+    "src/base/watchdog_posix.cc",
+    "src/ipc/buffered_frame_deserializer.cc",
+    "src/ipc/client_impl.cc",
+    "src/ipc/deferred.cc",
+    "src/ipc/host_impl.cc",
+    "src/ipc/service_proxy.cc",
+    "src/ipc/virtual_destructors.cc",
+    "src/protozero/message.cc",
+    "src/protozero/message_handle.cc",
+    "src/protozero/proto_decoder.cc",
+    "src/protozero/scattered_heap_buffer.cc",
+    "src/protozero/scattered_stream_null_delegate.cc",
+    "src/protozero/scattered_stream_writer.cc",
+    "src/traced/probes/android_log/android_log_data_source.cc",
+    "src/traced/probes/filesystem/file_scanner.cc",
+    "src/traced/probes/filesystem/fs_mount.cc",
+    "src/traced/probes/filesystem/inode_file_data_source.cc",
+    "src/traced/probes/filesystem/lru_inode_cache.cc",
+    "src/traced/probes/filesystem/prefix_finder.cc",
+    "src/traced/probes/filesystem/range_tree.cc",
+    "src/traced/probes/ftrace/atrace_hal_wrapper.cc",
+    "src/traced/probes/ftrace/atrace_wrapper.cc",
+    "src/traced/probes/ftrace/cpu_reader.cc",
+    "src/traced/probes/ftrace/cpu_stats_parser.cc",
+    "src/traced/probes/ftrace/event_info.cc",
+    "src/traced/probes/ftrace/event_info_constants.cc",
+    "src/traced/probes/ftrace/format_parser.cc",
+    "src/traced/probes/ftrace/ftrace_config.cc",
+    "src/traced/probes/ftrace/ftrace_config_muxer.cc",
+    "src/traced/probes/ftrace/ftrace_controller.cc",
+    "src/traced/probes/ftrace/ftrace_data_source.cc",
+    "src/traced/probes/ftrace/ftrace_metadata.cc",
+    "src/traced/probes/ftrace/ftrace_procfs.cc",
+    "src/traced/probes/ftrace/ftrace_stats.cc",
+    "src/traced/probes/ftrace/page_pool.cc",
+    "src/traced/probes/ftrace/proto_translation_table.cc",
+    "src/traced/probes/packages_list/packages_list_data_source.cc",
+    "src/traced/probes/power/android_power_data_source.cc",
+    "src/traced/probes/probes.cc",
+    "src/traced/probes/probes_data_source.cc",
+    "src/traced/probes/probes_producer.cc",
+    "src/traced/probes/ps/process_stats_data_source.cc",
+    "src/traced/probes/sys_stats/sys_stats_data_source.cc",
+    "src/traced/service/lazy_producer.cc",
+    "src/traced/service/service.cc",
+    "src/tracing/api_impl/consumer_api.cc",
+    "src/tracing/core/android_log_config.cc",
+    "src/tracing/core/android_power_config.cc",
+    "src/tracing/core/chrome_config.cc",
+    "src/tracing/core/commit_data_request.cc",
+    "src/tracing/core/data_source_config.cc",
+    "src/tracing/core/data_source_descriptor.cc",
+    "src/tracing/core/ftrace_config.cc",
+    "src/tracing/core/heapprofd_config.cc",
+    "src/tracing/core/id_allocator.cc",
+    "src/tracing/core/inode_file_config.cc",
+    "src/tracing/core/null_trace_writer.cc",
+    "src/tracing/core/observable_events.cc",
+    "src/tracing/core/packages_list_config.cc",
+    "src/tracing/core/packet_stream_validator.cc",
+    "src/tracing/core/process_stats_config.cc",
+    "src/tracing/core/shared_memory_abi.cc",
+    "src/tracing/core/shared_memory_arbiter_impl.cc",
+    "src/tracing/core/sliced_protobuf_input_stream.cc",
+    "src/tracing/core/startup_trace_writer.cc",
+    "src/tracing/core/startup_trace_writer_registry.cc",
+    "src/tracing/core/sys_stats_config.cc",
+    "src/tracing/core/test_config.cc",
+    "src/tracing/core/trace_buffer.cc",
+    "src/tracing/core/trace_config.cc",
+    "src/tracing/core/trace_packet.cc",
+    "src/tracing/core/trace_stats.cc",
+    "src/tracing/core/trace_writer_impl.cc",
+    "src/tracing/core/tracing_service_impl.cc",
+    "src/tracing/core/tracing_service_state.cc",
+    "src/tracing/core/virtual_destructors.cc",
   ],
   shared_libs: [
     "liblog",
     "libprotobuf-cpp-lite",
   ],
-  host_supported: true,
-  export_include_dirs: [
-    "include",
-    "include/perfetto/base/build_configs/android_tree",
+  static_libs: [
+    "libgtest_prod",
+    "perfetto_src_tracing_ipc",
   ],
   generated_headers: [
-    "perfetto_protos_perfetto_common_cpp_gen_headers",
     "perfetto_protos_perfetto_common_lite_gen_headers",
     "perfetto_protos_perfetto_common_zero_gen_headers",
-    "perfetto_protos_perfetto_config_android_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_android_lite_gen_headers",
-    "perfetto_protos_perfetto_config_android_zero_gen_headers",
-    "perfetto_protos_perfetto_config_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
     "perfetto_protos_perfetto_config_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_power_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_zero_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_zero_gen_headers",
     "perfetto_protos_perfetto_ipc_ipc_gen_headers",
-    "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
     "perfetto_protos_perfetto_trace_android_zero_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
     "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
     "perfetto_protos_perfetto_trace_power_zero_gen_headers",
     "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
     "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
     "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_zero_gen_headers",
+    "perfetto_src_ipc_wire_protocol_gen_headers",
   ],
   defaults: [
     "perfetto_defaults",
@@ -410,15 +364,18 @@
   cflags: [
     "-DGOOGLE_PROTOBUF_NO_RTTI",
     "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+    "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
 }
 
-// GN: //src/android_internal:libperfetto_android_internal
+// GN target: //:libperfetto_android_internal
 cc_library_shared {
   name: "libperfetto_android_internal",
   srcs: [
-    ":perfetto_src_android_internal_android_internal",
-    ":perfetto_src_android_internal_headers",
+    "src/android_internal/atrace_hal.cc",
+    "src/android_internal/health_hal.cc",
+    "src/android_internal/incident_service.cc",
+    "src/android_internal/power_stats_hal.cc",
   ],
   shared_libs: [
     "android.hardware.atrace@1.0",
@@ -427,6 +384,8 @@
     "libbase",
     "libbinder",
     "libhidlbase",
+    "libhidltransport",
+    "libhwbinder",
     "libincident",
     "liblog",
     "libservices",
@@ -435,13 +394,12 @@
   static_libs: [
     "libhealthhalutils",
   ],
-  export_include_dirs: [
-    "include",
-    "include/perfetto/base/build_configs/android_tree",
-  ],
   defaults: [
     "perfetto_defaults",
   ],
+  cflags: [
+    "-DPERFETTO_BUILD_WITH_ANDROID",
+  ],
   product_variables: {
     pdk: {
       enabled: false,
@@ -449,321 +407,131 @@
   },
 }
 
-// GN: //:libperfetto_client_experimental
-cc_library_static {
-  name: "libperfetto_client_experimental",
-  srcs: [
-    ":perfetto_include_perfetto_base_base",
-    ":perfetto_include_perfetto_ext_base_base",
-    ":perfetto_include_perfetto_ext_ipc_ipc",
-    ":perfetto_include_perfetto_ext_tracing_core_core",
-    ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
-    ":perfetto_include_perfetto_protozero_protozero",
-    ":perfetto_include_perfetto_tracing_core_core",
-    ":perfetto_include_perfetto_tracing_tracing",
-    ":perfetto_protos_perfetto_common_cpp_gen",
-    ":perfetto_protos_perfetto_common_lite_gen",
-    ":perfetto_protos_perfetto_common_zero_gen",
-    ":perfetto_protos_perfetto_config_android_cpp_gen",
-    ":perfetto_protos_perfetto_config_android_lite_gen",
-    ":perfetto_protos_perfetto_config_android_zero_gen",
-    ":perfetto_protos_perfetto_config_cpp_gen",
-    ":perfetto_protos_perfetto_config_ftrace_cpp_gen",
-    ":perfetto_protos_perfetto_config_ftrace_lite_gen",
-    ":perfetto_protos_perfetto_config_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_config_gpu_cpp_gen",
-    ":perfetto_protos_perfetto_config_gpu_lite_gen",
-    ":perfetto_protos_perfetto_config_gpu_zero_gen",
-    ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
-    ":perfetto_protos_perfetto_config_inode_file_lite_gen",
-    ":perfetto_protos_perfetto_config_inode_file_zero_gen",
-    ":perfetto_protos_perfetto_config_lite_gen",
-    ":perfetto_protos_perfetto_config_power_cpp_gen",
-    ":perfetto_protos_perfetto_config_power_lite_gen",
-    ":perfetto_protos_perfetto_config_power_zero_gen",
-    ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_process_stats_lite_gen",
-    ":perfetto_protos_perfetto_config_process_stats_zero_gen",
-    ":perfetto_protos_perfetto_config_profiling_cpp_gen",
-    ":perfetto_protos_perfetto_config_profiling_lite_gen",
-    ":perfetto_protos_perfetto_config_profiling_zero_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_lite_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
-    ":perfetto_protos_perfetto_config_zero_gen",
-    ":perfetto_protos_perfetto_ipc_ipc_gen",
-    ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
-    ":perfetto_protos_perfetto_trace_android_zero_gen",
-    ":perfetto_protos_perfetto_trace_chrome_zero_gen",
-    ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
-    ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_trace_gpu_zero_gen",
-    ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
-    ":perfetto_protos_perfetto_trace_minimal_lite_gen",
-    ":perfetto_protos_perfetto_trace_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
-    ":perfetto_protos_perfetto_trace_power_zero_gen",
-    ":perfetto_protos_perfetto_trace_profiling_zero_gen",
-    ":perfetto_protos_perfetto_trace_ps_zero_gen",
-    ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
-    ":perfetto_protos_perfetto_trace_track_event_zero_gen",
-    ":perfetto_protos_perfetto_trace_trusted_lite_gen",
-    ":perfetto_src_base_base",
-    ":perfetto_src_base_unix_socket",
-    ":perfetto_src_ipc_ipc",
-    ":perfetto_src_protozero_protozero",
-    ":perfetto_src_tracing_client_api",
-    ":perfetto_src_tracing_common",
-    ":perfetto_src_tracing_ipc",
-    ":perfetto_src_tracing_platform_posix",
-    ":perfetto_src_tracing_tracing",
-  ],
-  shared_libs: [
-    "libprotobuf-cpp-lite",
-  ],
-  export_include_dirs: [
-    "include",
-    "include/perfetto/base/build_configs/android_tree",
-  ],
-  generated_headers: [
-    "perfetto_protos_perfetto_common_cpp_gen_headers",
-    "perfetto_protos_perfetto_common_lite_gen_headers",
-    "perfetto_protos_perfetto_common_zero_gen_headers",
-    "perfetto_protos_perfetto_config_android_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_android_lite_gen_headers",
-    "perfetto_protos_perfetto_config_android_zero_gen_headers",
-    "perfetto_protos_perfetto_config_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
-    "perfetto_protos_perfetto_config_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_power_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_zero_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
-    "perfetto_protos_perfetto_config_zero_gen_headers",
-    "perfetto_protos_perfetto_ipc_ipc_gen_headers",
-    "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
-    "perfetto_protos_perfetto_trace_android_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_power_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
-  ],
-  export_generated_headers: [
-    "perfetto_protos_perfetto_common_cpp_gen_headers",
-    "perfetto_protos_perfetto_common_lite_gen_headers",
-    "perfetto_protos_perfetto_common_zero_gen_headers",
-    "perfetto_protos_perfetto_config_android_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_android_lite_gen_headers",
-    "perfetto_protos_perfetto_config_android_zero_gen_headers",
-    "perfetto_protos_perfetto_config_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
-    "perfetto_protos_perfetto_config_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_power_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_zero_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
-    "perfetto_protos_perfetto_config_zero_gen_headers",
-    "perfetto_protos_perfetto_ipc_ipc_gen_headers",
-    "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
-    "perfetto_protos_perfetto_trace_android_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_power_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
-  ],
-  defaults: [
-    "perfetto_defaults",
-  ],
-  cflags: [
-    "-DGOOGLE_PROTOBUF_NO_RTTI",
-    "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
-  ],
-}
-
-// GN: //src/perfetto_cmd:perfetto
+// GN target: //:perfetto
 cc_binary {
   name: "perfetto",
   srcs: [
-    ":perfetto_include_perfetto_base_base",
-    ":perfetto_include_perfetto_ext_base_base",
-    ":perfetto_include_perfetto_ext_ipc_ipc",
-    ":perfetto_include_perfetto_ext_traced_traced",
-    ":perfetto_include_perfetto_ext_tracing_core_core",
-    ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
-    ":perfetto_include_perfetto_protozero_protozero",
-    ":perfetto_include_perfetto_tracing_core_core",
-    ":perfetto_include_perfetto_tracing_tracing",
-    ":perfetto_protos_perfetto_common_cpp_gen",
     ":perfetto_protos_perfetto_common_lite_gen",
     ":perfetto_protos_perfetto_common_zero_gen",
-    ":perfetto_protos_perfetto_config_android_cpp_gen",
-    ":perfetto_protos_perfetto_config_android_lite_gen",
-    ":perfetto_protos_perfetto_config_android_zero_gen",
-    ":perfetto_protos_perfetto_config_cpp_gen",
-    ":perfetto_protos_perfetto_config_ftrace_cpp_gen",
-    ":perfetto_protos_perfetto_config_ftrace_lite_gen",
-    ":perfetto_protos_perfetto_config_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_config_gpu_cpp_gen",
-    ":perfetto_protos_perfetto_config_gpu_lite_gen",
-    ":perfetto_protos_perfetto_config_gpu_zero_gen",
-    ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
-    ":perfetto_protos_perfetto_config_inode_file_lite_gen",
-    ":perfetto_protos_perfetto_config_inode_file_zero_gen",
     ":perfetto_protos_perfetto_config_lite_gen",
-    ":perfetto_protos_perfetto_config_power_cpp_gen",
-    ":perfetto_protos_perfetto_config_power_lite_gen",
-    ":perfetto_protos_perfetto_config_power_zero_gen",
-    ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_process_stats_lite_gen",
-    ":perfetto_protos_perfetto_config_process_stats_zero_gen",
-    ":perfetto_protos_perfetto_config_profiling_cpp_gen",
-    ":perfetto_protos_perfetto_config_profiling_lite_gen",
-    ":perfetto_protos_perfetto_config_profiling_zero_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_lite_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_config_zero_gen",
     ":perfetto_protos_perfetto_ipc_ipc_gen",
-    ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
     ":perfetto_protos_perfetto_trace_android_zero_gen",
     ":perfetto_protos_perfetto_trace_chrome_zero_gen",
     ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
     ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_trace_gpu_zero_gen",
     ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
     ":perfetto_protos_perfetto_trace_minimal_lite_gen",
-    ":perfetto_protos_perfetto_trace_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
     ":perfetto_protos_perfetto_trace_power_zero_gen",
     ":perfetto_protos_perfetto_trace_profiling_zero_gen",
     ":perfetto_protos_perfetto_trace_ps_zero_gen",
     ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
     ":perfetto_protos_perfetto_trace_trusted_lite_gen",
-    ":perfetto_src_android_internal_headers",
-    ":perfetto_src_android_internal_lazy_library_loader",
-    ":perfetto_src_base_base",
-    ":perfetto_src_base_unix_socket",
-    ":perfetto_src_ipc_ipc",
-    ":perfetto_src_perfetto_cmd_perfetto_cmd",
+    ":perfetto_protos_perfetto_trace_zero_gen",
+    ":perfetto_src_ipc_wire_protocol_gen",
     ":perfetto_src_perfetto_cmd_protos_gen",
-    ":perfetto_src_perfetto_cmd_trigger_producer",
-    ":perfetto_src_protozero_protozero",
-    ":perfetto_src_tracing_common",
-    ":perfetto_src_tracing_ipc",
-    ":perfetto_src_tracing_tracing",
+    "src/android_internal/lazy_library_loader.cc",
+    "src/base/android_task_runner.cc",
+    "src/base/event.cc",
+    "src/base/file_utils.cc",
+    "src/base/metatrace.cc",
+    "src/base/paged_memory.cc",
+    "src/base/pipe.cc",
+    "src/base/string_splitter.cc",
+    "src/base/string_utils.cc",
+    "src/base/string_view.cc",
+    "src/base/temp_file.cc",
+    "src/base/thread_checker.cc",
+    "src/base/thread_task_runner.cc",
+    "src/base/time.cc",
+    "src/base/unix_socket.cc",
+    "src/base/unix_task_runner.cc",
+    "src/base/virtual_destructors.cc",
+    "src/base/watchdog_posix.cc",
+    "src/ipc/buffered_frame_deserializer.cc",
+    "src/ipc/client_impl.cc",
+    "src/ipc/deferred.cc",
+    "src/ipc/host_impl.cc",
+    "src/ipc/service_proxy.cc",
+    "src/ipc/virtual_destructors.cc",
+    "src/perfetto_cmd/config.cc",
     "src/perfetto_cmd/main.cc",
+    "src/perfetto_cmd/packet_writer.cc",
+    "src/perfetto_cmd/pbtxt_to_pb.cc",
+    "src/perfetto_cmd/perfetto_cmd.cc",
+    "src/perfetto_cmd/rate_limiter.cc",
+    "src/perfetto_cmd/trigger_producer.cc",
+    "src/protozero/message.cc",
+    "src/protozero/message_handle.cc",
+    "src/protozero/proto_decoder.cc",
+    "src/protozero/scattered_heap_buffer.cc",
+    "src/protozero/scattered_stream_null_delegate.cc",
+    "src/protozero/scattered_stream_writer.cc",
+    "src/tracing/core/android_log_config.cc",
+    "src/tracing/core/android_power_config.cc",
+    "src/tracing/core/chrome_config.cc",
+    "src/tracing/core/commit_data_request.cc",
+    "src/tracing/core/data_source_config.cc",
+    "src/tracing/core/data_source_descriptor.cc",
+    "src/tracing/core/ftrace_config.cc",
+    "src/tracing/core/heapprofd_config.cc",
+    "src/tracing/core/id_allocator.cc",
+    "src/tracing/core/inode_file_config.cc",
+    "src/tracing/core/null_trace_writer.cc",
+    "src/tracing/core/observable_events.cc",
+    "src/tracing/core/packages_list_config.cc",
+    "src/tracing/core/packet_stream_validator.cc",
+    "src/tracing/core/process_stats_config.cc",
+    "src/tracing/core/shared_memory_abi.cc",
+    "src/tracing/core/shared_memory_arbiter_impl.cc",
+    "src/tracing/core/sliced_protobuf_input_stream.cc",
+    "src/tracing/core/startup_trace_writer.cc",
+    "src/tracing/core/startup_trace_writer_registry.cc",
+    "src/tracing/core/sys_stats_config.cc",
+    "src/tracing/core/test_config.cc",
+    "src/tracing/core/trace_buffer.cc",
+    "src/tracing/core/trace_config.cc",
+    "src/tracing/core/trace_packet.cc",
+    "src/tracing/core/trace_stats.cc",
+    "src/tracing/core/trace_writer_impl.cc",
+    "src/tracing/core/tracing_service_impl.cc",
+    "src/tracing/core/tracing_service_state.cc",
+    "src/tracing/core/virtual_destructors.cc",
   ],
   shared_libs: [
+    "libandroid",
+    "libbinder",
     "liblog",
     "libprotobuf-cpp-lite",
+    "libservices",
+    "libutils",
     "libz",
   ],
+  static_libs: [
+    "libgtest_prod",
+    "perfetto_src_tracing_ipc",
+  ],
   generated_headers: [
-    "perfetto_protos_perfetto_common_cpp_gen_headers",
     "perfetto_protos_perfetto_common_lite_gen_headers",
     "perfetto_protos_perfetto_common_zero_gen_headers",
-    "perfetto_protos_perfetto_config_android_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_android_lite_gen_headers",
-    "perfetto_protos_perfetto_config_android_zero_gen_headers",
-    "perfetto_protos_perfetto_config_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
     "perfetto_protos_perfetto_config_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_power_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_zero_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_zero_gen_headers",
     "perfetto_protos_perfetto_ipc_ipc_gen_headers",
-    "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
     "perfetto_protos_perfetto_trace_android_zero_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
     "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
     "perfetto_protos_perfetto_trace_power_zero_gen_headers",
     "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
     "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
     "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_zero_gen_headers",
+    "perfetto_src_ipc_wire_protocol_gen_headers",
     "perfetto_src_perfetto_cmd_protos_gen_headers",
   ],
   defaults: [
@@ -773,166 +541,46 @@
     "-DGOOGLE_PROTOBUF_NO_RTTI",
     "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
     "-DHAVE_HIDDEN",
+    "-DPERFETTO_BUILD_WITH_ANDROID",
+    "-DUSE_MMAP",
+    "-DZLIB_CONST",
   ],
+  product_variables: {
+    pdk: {
+      enabled: false,
+    },
+  },
 }
 
-// GN: //gn:default_deps
 cc_defaults {
   name: "perfetto_defaults",
   cflags: [
-    "-O2",
+    "-Oz",
     "-Wno-error=return-type",
     "-Wno-sign-compare",
     "-Wno-sign-promo",
     "-Wno-unused-parameter",
     "-fvisibility=hidden",
   ],
-  include_dirs: [
-    "external/perfetto",
-    "external/perfetto/include",
-    "external/perfetto/include/perfetto/base/build_configs/android_tree",
+  local_include_dirs: [
+    "include",
   ],
   product_variables: {
     debuggable: {
       cflags: ["-DPERFETTO_BUILD_WITH_ANDROID_USERDEBUG"],
     },
   },
-  target: {
-    android: {
-      lto: {
-        thin: true,
-      },
-    },
-  },
 }
 
-// GN: //include/perfetto/base:base
-filegroup {
-  name: "perfetto_include_perfetto_base_base",
-}
-
-// GN: //include/perfetto/ext/base:base
-filegroup {
-  name: "perfetto_include_perfetto_ext_base_base",
-}
-
-// GN: //include/perfetto/ext/ipc:ipc
-filegroup {
-  name: "perfetto_include_perfetto_ext_ipc_ipc",
-}
-
-// GN: //include/perfetto/ext/traced:sys_stats_counters
-filegroup {
-  name: "perfetto_include_perfetto_ext_traced_sys_stats_counters",
-}
-
-// GN: //include/perfetto/ext/traced:traced
-filegroup {
-  name: "perfetto_include_perfetto_ext_traced_traced",
-}
-
-// GN: //include/perfetto/ext/tracing/core:core
-filegroup {
-  name: "perfetto_include_perfetto_ext_tracing_core_core",
-}
-
-// GN: //include/perfetto/ext/tracing/ipc:ipc
-filegroup {
-  name: "perfetto_include_perfetto_ext_tracing_ipc_ipc",
-}
-
-// GN: //include/perfetto/profiling:normalize
-filegroup {
-  name: "perfetto_include_perfetto_profiling_normalize",
-}
-
-// GN: //include/perfetto/profiling:symbolizer
-filegroup {
-  name: "perfetto_include_perfetto_profiling_symbolizer",
-}
-
-// GN: //include/perfetto/protozero:protozero
-filegroup {
-  name: "perfetto_include_perfetto_protozero_protozero",
-}
-
-// GN: //include/perfetto/public:public
-filegroup {
-  name: "perfetto_include_perfetto_public_public",
-}
-
-// GN: //include/perfetto/trace_processor:basic_types
-filegroup {
-  name: "perfetto_include_perfetto_trace_processor_basic_types",
-}
-
-// GN: //include/perfetto/trace_processor:storage
-filegroup {
-  name: "perfetto_include_perfetto_trace_processor_storage",
-}
-
-// GN: //include/perfetto/trace_processor:trace_processor
-filegroup {
-  name: "perfetto_include_perfetto_trace_processor_trace_processor",
-}
-
-// GN: //include/perfetto/tracing/core:core
-filegroup {
-  name: "perfetto_include_perfetto_tracing_core_core",
-}
-
-// GN: //include/perfetto/tracing:tracing
-filegroup {
-  name: "perfetto_include_perfetto_tracing_tracing",
-}
-
-// GN: //:perfetto_integrationtests
+// GN target: //:perfetto_integrationtests
 cc_test {
   name: "perfetto_integrationtests",
   srcs: [
-    ":perfetto_include_perfetto_base_base",
-    ":perfetto_include_perfetto_ext_base_base",
-    ":perfetto_include_perfetto_ext_ipc_ipc",
-    ":perfetto_include_perfetto_ext_traced_sys_stats_counters",
-    ":perfetto_include_perfetto_ext_traced_traced",
-    ":perfetto_include_perfetto_ext_tracing_core_core",
-    ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
-    ":perfetto_include_perfetto_profiling_normalize",
-    ":perfetto_include_perfetto_protozero_protozero",
-    ":perfetto_include_perfetto_tracing_core_core",
-    ":perfetto_include_perfetto_tracing_tracing",
-    ":perfetto_protos_perfetto_common_cpp_gen",
     ":perfetto_protos_perfetto_common_lite_gen",
     ":perfetto_protos_perfetto_common_zero_gen",
-    ":perfetto_protos_perfetto_config_android_cpp_gen",
-    ":perfetto_protos_perfetto_config_android_lite_gen",
-    ":perfetto_protos_perfetto_config_android_zero_gen",
-    ":perfetto_protos_perfetto_config_cpp_gen",
-    ":perfetto_protos_perfetto_config_ftrace_cpp_gen",
-    ":perfetto_protos_perfetto_config_ftrace_lite_gen",
-    ":perfetto_protos_perfetto_config_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_config_gpu_cpp_gen",
-    ":perfetto_protos_perfetto_config_gpu_lite_gen",
-    ":perfetto_protos_perfetto_config_gpu_zero_gen",
-    ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
-    ":perfetto_protos_perfetto_config_inode_file_lite_gen",
-    ":perfetto_protos_perfetto_config_inode_file_zero_gen",
     ":perfetto_protos_perfetto_config_lite_gen",
-    ":perfetto_protos_perfetto_config_power_cpp_gen",
-    ":perfetto_protos_perfetto_config_power_lite_gen",
-    ":perfetto_protos_perfetto_config_power_zero_gen",
-    ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_process_stats_lite_gen",
-    ":perfetto_protos_perfetto_config_process_stats_zero_gen",
-    ":perfetto_protos_perfetto_config_profiling_cpp_gen",
-    ":perfetto_protos_perfetto_config_profiling_lite_gen",
-    ":perfetto_protos_perfetto_config_profiling_zero_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_lite_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_config_zero_gen",
     ":perfetto_protos_perfetto_ipc_ipc_gen",
-    ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
     ":perfetto_protos_perfetto_trace_android_lite_gen",
     ":perfetto_protos_perfetto_trace_android_zero_gen",
     ":perfetto_protos_perfetto_trace_chrome_lite_gen",
@@ -941,16 +589,10 @@
     ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
     ":perfetto_protos_perfetto_trace_ftrace_lite_gen",
     ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_trace_gpu_lite_gen",
-    ":perfetto_protos_perfetto_trace_gpu_zero_gen",
     ":perfetto_protos_perfetto_trace_interned_data_lite_gen",
     ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
+    ":perfetto_protos_perfetto_trace_lite_gen",
     ":perfetto_protos_perfetto_trace_minimal_lite_gen",
-    ":perfetto_protos_perfetto_trace_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_non_minimal_lite_gen",
-    ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_perfetto_lite_gen",
-    ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
     ":perfetto_protos_perfetto_trace_power_lite_gen",
     ":perfetto_protos_perfetto_trace_power_zero_gen",
     ":perfetto_protos_perfetto_trace_profiling_lite_gen",
@@ -962,46 +604,119 @@
     ":perfetto_protos_perfetto_trace_track_event_lite_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
     ":perfetto_protos_perfetto_trace_trusted_lite_gen",
-    ":perfetto_src_android_internal_headers",
-    ":perfetto_src_android_internal_lazy_library_loader",
-    ":perfetto_src_base_base",
-    ":perfetto_src_base_test_support",
-    ":perfetto_src_base_unix_socket",
-    ":perfetto_src_ipc_ipc",
-    ":perfetto_src_profiling_memory_client",
-    ":perfetto_src_profiling_memory_daemon",
-    ":perfetto_src_profiling_memory_end_to_end_tests",
-    ":perfetto_src_profiling_memory_proc_utils",
-    ":perfetto_src_profiling_memory_ring_buffer",
-    ":perfetto_src_profiling_memory_scoped_spinlock",
-    ":perfetto_src_profiling_memory_wire_protocol",
-    ":perfetto_src_protozero_protozero",
-    ":perfetto_src_traced_probes_android_log_android_log",
-    ":perfetto_src_traced_probes_data_source",
-    ":perfetto_src_traced_probes_filesystem_filesystem",
-    ":perfetto_src_traced_probes_ftrace_format_parser",
-    ":perfetto_src_traced_probes_ftrace_ftrace",
-    ":perfetto_src_traced_probes_ftrace_integrationtests",
-    ":perfetto_src_traced_probes_ftrace_test_support",
-    ":perfetto_src_traced_probes_metatrace_metatrace",
-    ":perfetto_src_traced_probes_packages_list_packages_list",
-    ":perfetto_src_traced_probes_power_power",
-    ":perfetto_src_traced_probes_probes_src",
-    ":perfetto_src_traced_probes_ps_ps",
-    ":perfetto_src_traced_probes_sys_stats_sys_stats",
-    ":perfetto_src_tracing_client_api",
-    ":perfetto_src_tracing_client_api_integrationtests",
-    ":perfetto_src_tracing_common",
-    ":perfetto_src_tracing_ipc",
-    ":perfetto_src_tracing_platform_posix",
-    ":perfetto_src_tracing_test_api_test_support",
-    ":perfetto_src_tracing_tracing",
-    ":perfetto_test_end_to_end_integrationtests",
-    ":perfetto_test_task_runner_thread",
-    ":perfetto_test_task_runner_thread_delegates",
-    ":perfetto_test_test_helper",
+    ":perfetto_protos_perfetto_trace_zero_gen",
+    ":perfetto_src_ipc_wire_protocol_gen",
+    "src/android_internal/lazy_library_loader.cc",
+    "src/base/android_task_runner.cc",
+    "src/base/event.cc",
+    "src/base/file_utils.cc",
+    "src/base/metatrace.cc",
+    "src/base/paged_memory.cc",
+    "src/base/pipe.cc",
+    "src/base/string_splitter.cc",
+    "src/base/string_utils.cc",
+    "src/base/string_view.cc",
+    "src/base/temp_file.cc",
+    "src/base/test/test_task_runner.cc",
+    "src/base/test/utils.cc",
+    "src/base/test/vm_test_utils.cc",
+    "src/base/thread_checker.cc",
+    "src/base/thread_task_runner.cc",
+    "src/base/time.cc",
+    "src/base/unix_socket.cc",
+    "src/base/unix_task_runner.cc",
+    "src/base/virtual_destructors.cc",
+    "src/base/watchdog_posix.cc",
+    "src/ipc/buffered_frame_deserializer.cc",
+    "src/ipc/client_impl.cc",
+    "src/ipc/deferred.cc",
+    "src/ipc/host_impl.cc",
+    "src/ipc/service_proxy.cc",
+    "src/ipc/virtual_destructors.cc",
+    "src/profiling/memory/bookkeeping.cc",
+    "src/profiling/memory/client.cc",
+    "src/profiling/memory/heapprofd_end_to_end_test.cc",
+    "src/profiling/memory/heapprofd_producer.cc",
+    "src/profiling/memory/proc_utils.cc",
+    "src/profiling/memory/scoped_spinlock.cc",
+    "src/profiling/memory/shared_ring_buffer.cc",
+    "src/profiling/memory/system_property.cc",
+    "src/profiling/memory/unwinding.cc",
+    "src/profiling/memory/wire_protocol.cc",
+    "src/protozero/message.cc",
+    "src/protozero/message_handle.cc",
+    "src/protozero/proto_decoder.cc",
+    "src/protozero/scattered_heap_buffer.cc",
+    "src/protozero/scattered_stream_null_delegate.cc",
+    "src/protozero/scattered_stream_writer.cc",
+    "src/traced/probes/android_log/android_log_data_source.cc",
+    "src/traced/probes/filesystem/file_scanner.cc",
+    "src/traced/probes/filesystem/fs_mount.cc",
+    "src/traced/probes/filesystem/inode_file_data_source.cc",
+    "src/traced/probes/filesystem/lru_inode_cache.cc",
+    "src/traced/probes/filesystem/prefix_finder.cc",
+    "src/traced/probes/filesystem/range_tree.cc",
+    "src/traced/probes/ftrace/atrace_hal_wrapper.cc",
+    "src/traced/probes/ftrace/atrace_wrapper.cc",
+    "src/traced/probes/ftrace/cpu_reader.cc",
+    "src/traced/probes/ftrace/cpu_stats_parser.cc",
+    "src/traced/probes/ftrace/event_info.cc",
+    "src/traced/probes/ftrace/event_info_constants.cc",
+    "src/traced/probes/ftrace/format_parser.cc",
+    "src/traced/probes/ftrace/ftrace_config.cc",
+    "src/traced/probes/ftrace/ftrace_config_muxer.cc",
+    "src/traced/probes/ftrace/ftrace_controller.cc",
+    "src/traced/probes/ftrace/ftrace_data_source.cc",
+    "src/traced/probes/ftrace/ftrace_metadata.cc",
+    "src/traced/probes/ftrace/ftrace_procfs.cc",
+    "src/traced/probes/ftrace/ftrace_procfs_integrationtest.cc",
+    "src/traced/probes/ftrace/ftrace_stats.cc",
+    "src/traced/probes/ftrace/page_pool.cc",
+    "src/traced/probes/ftrace/proto_translation_table.cc",
+    "src/traced/probes/ftrace/test/cpu_reader_support.cc",
+    "src/traced/probes/packages_list/packages_list_data_source.cc",
+    "src/traced/probes/power/android_power_data_source.cc",
+    "src/traced/probes/probes_data_source.cc",
+    "src/traced/probes/probes_producer.cc",
+    "src/traced/probes/ps/process_stats_data_source.cc",
+    "src/traced/probes/sys_stats/sys_stats_data_source.cc",
+    "src/tracing/core/android_log_config.cc",
+    "src/tracing/core/android_power_config.cc",
+    "src/tracing/core/chrome_config.cc",
+    "src/tracing/core/commit_data_request.cc",
+    "src/tracing/core/data_source_config.cc",
+    "src/tracing/core/data_source_descriptor.cc",
+    "src/tracing/core/ftrace_config.cc",
+    "src/tracing/core/heapprofd_config.cc",
+    "src/tracing/core/id_allocator.cc",
+    "src/tracing/core/inode_file_config.cc",
+    "src/tracing/core/null_trace_writer.cc",
+    "src/tracing/core/observable_events.cc",
+    "src/tracing/core/packages_list_config.cc",
+    "src/tracing/core/packet_stream_validator.cc",
+    "src/tracing/core/process_stats_config.cc",
+    "src/tracing/core/shared_memory_abi.cc",
+    "src/tracing/core/shared_memory_arbiter_impl.cc",
+    "src/tracing/core/sliced_protobuf_input_stream.cc",
+    "src/tracing/core/startup_trace_writer.cc",
+    "src/tracing/core/startup_trace_writer_registry.cc",
+    "src/tracing/core/sys_stats_config.cc",
+    "src/tracing/core/test_config.cc",
+    "src/tracing/core/trace_buffer.cc",
+    "src/tracing/core/trace_config.cc",
+    "src/tracing/core/trace_packet.cc",
+    "src/tracing/core/trace_stats.cc",
+    "src/tracing/core/trace_writer_impl.cc",
+    "src/tracing/core/tracing_service_impl.cc",
+    "src/tracing/core/tracing_service_state.cc",
+    "src/tracing/core/virtual_destructors.cc",
+    "test/end_to_end_integrationtest.cc",
+    "test/fake_producer.cc",
+    "test/task_runner_thread.cc",
+    "test/test_helper.cc",
   ],
   shared_libs: [
+    "libandroid",
     "libbase",
     "liblog",
     "libprocinfo",
@@ -1010,41 +725,15 @@
   ],
   static_libs: [
     "libgmock",
-    "libperfetto_client_experimental",
+    "libgtest_prod",
+    "perfetto_src_tracing_ipc",
   ],
   generated_headers: [
-    "perfetto_protos_perfetto_common_cpp_gen_headers",
     "perfetto_protos_perfetto_common_lite_gen_headers",
     "perfetto_protos_perfetto_common_zero_gen_headers",
-    "perfetto_protos_perfetto_config_android_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_android_lite_gen_headers",
-    "perfetto_protos_perfetto_config_android_zero_gen_headers",
-    "perfetto_protos_perfetto_config_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
     "perfetto_protos_perfetto_config_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_power_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_zero_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_zero_gen_headers",
     "perfetto_protos_perfetto_ipc_ipc_gen_headers",
-    "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
     "perfetto_protos_perfetto_trace_android_lite_gen_headers",
     "perfetto_protos_perfetto_trace_android_zero_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
@@ -1053,16 +742,10 @@
     "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_lite_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_gpu_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_lite_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_lite_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_non_minimal_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_perfetto_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
     "perfetto_protos_perfetto_trace_power_lite_gen_headers",
     "perfetto_protos_perfetto_trace_power_zero_gen_headers",
     "perfetto_protos_perfetto_trace_profiling_lite_gen_headers",
@@ -1074,6 +757,8 @@
     "perfetto_protos_perfetto_trace_track_event_lite_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
     "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_zero_gen_headers",
+    "perfetto_src_ipc_wire_protocol_gen_headers",
   ],
   defaults: [
     "perfetto_defaults",
@@ -1081,82 +766,16 @@
   cflags: [
     "-DGOOGLE_PROTOBUF_NO_RTTI",
     "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+    "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
+  product_variables: {
+    pdk: {
+      enabled: false,
+    },
+  },
 }
 
-// GN: //protos/perfetto/common:cpp
-genrule {
-  name: "perfetto_protos_perfetto_common_cpp_gen",
-  srcs: [
-    "protos/perfetto/common/android_log_constants.proto",
-    "protos/perfetto/common/commit_data_request.proto",
-    "protos/perfetto/common/data_source_descriptor.proto",
-    "protos/perfetto/common/descriptor.proto",
-    "protos/perfetto/common/gpu_counter_descriptor.proto",
-    "protos/perfetto/common/observable_events.proto",
-    "protos/perfetto/common/sys_stats_counters.proto",
-    "protos/perfetto/common/trace_stats.proto",
-    "protos/perfetto/common/tracing_service_state.proto",
-    "protos/perfetto/common/track_event_descriptor.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/common/android_log_constants.gen.cc",
-    "external/perfetto/protos/perfetto/common/commit_data_request.gen.cc",
-    "external/perfetto/protos/perfetto/common/data_source_descriptor.gen.cc",
-    "external/perfetto/protos/perfetto/common/descriptor.gen.cc",
-    "external/perfetto/protos/perfetto/common/gpu_counter_descriptor.gen.cc",
-    "external/perfetto/protos/perfetto/common/observable_events.gen.cc",
-    "external/perfetto/protos/perfetto/common/sys_stats_counters.gen.cc",
-    "external/perfetto/protos/perfetto/common/trace_stats.gen.cc",
-    "external/perfetto/protos/perfetto/common/tracing_service_state.gen.cc",
-    "external/perfetto/protos/perfetto/common/track_event_descriptor.gen.cc",
-  ],
-}
-
-// GN: //protos/perfetto/common:cpp
-genrule {
-  name: "perfetto_protos_perfetto_common_cpp_gen_headers",
-  srcs: [
-    "protos/perfetto/common/android_log_constants.proto",
-    "protos/perfetto/common/commit_data_request.proto",
-    "protos/perfetto/common/data_source_descriptor.proto",
-    "protos/perfetto/common/descriptor.proto",
-    "protos/perfetto/common/gpu_counter_descriptor.proto",
-    "protos/perfetto/common/observable_events.proto",
-    "protos/perfetto/common/sys_stats_counters.proto",
-    "protos/perfetto/common/trace_stats.proto",
-    "protos/perfetto/common/tracing_service_state.proto",
-    "protos/perfetto/common/track_event_descriptor.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/common/android_log_constants.gen.h",
-    "external/perfetto/protos/perfetto/common/commit_data_request.gen.h",
-    "external/perfetto/protos/perfetto/common/data_source_descriptor.gen.h",
-    "external/perfetto/protos/perfetto/common/descriptor.gen.h",
-    "external/perfetto/protos/perfetto/common/gpu_counter_descriptor.gen.h",
-    "external/perfetto/protos/perfetto/common/observable_events.gen.h",
-    "external/perfetto/protos/perfetto/common/sys_stats_counters.gen.h",
-    "external/perfetto/protos/perfetto/common/trace_stats.gen.h",
-    "external/perfetto/protos/perfetto/common/tracing_service_state.gen.h",
-    "external/perfetto/protos/perfetto/common/track_event_descriptor.gen.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/common:lite
+// GN target: //protos/perfetto/common:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_common_lite_gen",
   srcs: [
@@ -1164,32 +783,28 @@
     "protos/perfetto/common/commit_data_request.proto",
     "protos/perfetto/common/data_source_descriptor.proto",
     "protos/perfetto/common/descriptor.proto",
-    "protos/perfetto/common/gpu_counter_descriptor.proto",
     "protos/perfetto/common/observable_events.proto",
     "protos/perfetto/common/sys_stats_counters.proto",
     "protos/perfetto/common/trace_stats.proto",
     "protos/perfetto/common/tracing_service_state.proto",
-    "protos/perfetto/common/track_event_descriptor.proto",
   ],
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/common/android_log_constants.pb.cc",
     "external/perfetto/protos/perfetto/common/commit_data_request.pb.cc",
     "external/perfetto/protos/perfetto/common/data_source_descriptor.pb.cc",
     "external/perfetto/protos/perfetto/common/descriptor.pb.cc",
-    "external/perfetto/protos/perfetto/common/gpu_counter_descriptor.pb.cc",
     "external/perfetto/protos/perfetto/common/observable_events.pb.cc",
     "external/perfetto/protos/perfetto/common/sys_stats_counters.pb.cc",
     "external/perfetto/protos/perfetto/common/trace_stats.pb.cc",
     "external/perfetto/protos/perfetto/common/tracing_service_state.pb.cc",
-    "external/perfetto/protos/perfetto/common/track_event_descriptor.pb.cc",
   ],
 }
 
-// GN: //protos/perfetto/common:lite
+// GN target: //protos/perfetto/common:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_common_lite_gen_headers",
   srcs: [
@@ -1197,36 +812,31 @@
     "protos/perfetto/common/commit_data_request.proto",
     "protos/perfetto/common/data_source_descriptor.proto",
     "protos/perfetto/common/descriptor.proto",
-    "protos/perfetto/common/gpu_counter_descriptor.proto",
     "protos/perfetto/common/observable_events.proto",
     "protos/perfetto/common/sys_stats_counters.proto",
     "protos/perfetto/common/trace_stats.proto",
     "protos/perfetto/common/tracing_service_state.proto",
-    "protos/perfetto/common/track_event_descriptor.proto",
   ],
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/common/android_log_constants.pb.h",
     "external/perfetto/protos/perfetto/common/commit_data_request.pb.h",
     "external/perfetto/protos/perfetto/common/data_source_descriptor.pb.h",
     "external/perfetto/protos/perfetto/common/descriptor.pb.h",
-    "external/perfetto/protos/perfetto/common/gpu_counter_descriptor.pb.h",
     "external/perfetto/protos/perfetto/common/observable_events.pb.h",
     "external/perfetto/protos/perfetto/common/sys_stats_counters.pb.h",
     "external/perfetto/protos/perfetto/common/trace_stats.pb.h",
     "external/perfetto/protos/perfetto/common/tracing_service_state.pb.h",
-    "external/perfetto/protos/perfetto/common/track_event_descriptor.pb.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/common:zero
+// GN target: //protos/perfetto/common:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_common_zero_gen",
   srcs: [
@@ -1234,33 +844,29 @@
     "protos/perfetto/common/commit_data_request.proto",
     "protos/perfetto/common/data_source_descriptor.proto",
     "protos/perfetto/common/descriptor.proto",
-    "protos/perfetto/common/gpu_counter_descriptor.proto",
     "protos/perfetto/common/observable_events.proto",
     "protos/perfetto/common/sys_stats_counters.proto",
     "protos/perfetto/common/trace_stats.proto",
     "protos/perfetto/common/tracing_service_state.proto",
-    "protos/perfetto/common/track_event_descriptor.proto",
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/common/android_log_constants.pbzero.cc",
     "external/perfetto/protos/perfetto/common/commit_data_request.pbzero.cc",
     "external/perfetto/protos/perfetto/common/data_source_descriptor.pbzero.cc",
     "external/perfetto/protos/perfetto/common/descriptor.pbzero.cc",
-    "external/perfetto/protos/perfetto/common/gpu_counter_descriptor.pbzero.cc",
     "external/perfetto/protos/perfetto/common/observable_events.pbzero.cc",
     "external/perfetto/protos/perfetto/common/sys_stats_counters.pbzero.cc",
     "external/perfetto/protos/perfetto/common/trace_stats.pbzero.cc",
     "external/perfetto/protos/perfetto/common/tracing_service_state.pbzero.cc",
-    "external/perfetto/protos/perfetto/common/track_event_descriptor.pbzero.cc",
   ],
 }
 
-// GN: //protos/perfetto/common:zero
+// GN target: //protos/perfetto/common:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_common_zero_gen_headers",
   srcs: [
@@ -1268,1051 +874,188 @@
     "protos/perfetto/common/commit_data_request.proto",
     "protos/perfetto/common/data_source_descriptor.proto",
     "protos/perfetto/common/descriptor.proto",
-    "protos/perfetto/common/gpu_counter_descriptor.proto",
     "protos/perfetto/common/observable_events.proto",
     "protos/perfetto/common/sys_stats_counters.proto",
     "protos/perfetto/common/trace_stats.proto",
     "protos/perfetto/common/tracing_service_state.proto",
-    "protos/perfetto/common/track_event_descriptor.proto",
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/common/android_log_constants.pbzero.h",
     "external/perfetto/protos/perfetto/common/commit_data_request.pbzero.h",
     "external/perfetto/protos/perfetto/common/data_source_descriptor.pbzero.h",
     "external/perfetto/protos/perfetto/common/descriptor.pbzero.h",
-    "external/perfetto/protos/perfetto/common/gpu_counter_descriptor.pbzero.h",
     "external/perfetto/protos/perfetto/common/observable_events.pbzero.h",
     "external/perfetto/protos/perfetto/common/sys_stats_counters.pbzero.h",
     "external/perfetto/protos/perfetto/common/trace_stats.pbzero.h",
     "external/perfetto/protos/perfetto/common/tracing_service_state.pbzero.h",
-    "external/perfetto/protos/perfetto/common/track_event_descriptor.pbzero.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/config/android:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_android_cpp_gen",
-  srcs: [
-    "protos/perfetto/config/android/android_log_config.proto",
-    "protos/perfetto/config/android/packages_list_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/android/android_log_config.gen.cc",
-    "external/perfetto/protos/perfetto/config/android/packages_list_config.gen.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/android:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_android_cpp_gen_headers",
-  srcs: [
-    "protos/perfetto/config/android/android_log_config.proto",
-    "protos/perfetto/config/android/packages_list_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/android/android_log_config.gen.h",
-    "external/perfetto/protos/perfetto/config/android/packages_list_config.gen.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/android:lite
-genrule {
-  name: "perfetto_protos_perfetto_config_android_lite_gen",
-  srcs: [
-    "protos/perfetto/config/android/android_log_config.proto",
-    "protos/perfetto/config/android/packages_list_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/android/android_log_config.pb.cc",
-    "external/perfetto/protos/perfetto/config/android/packages_list_config.pb.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/android:lite
-genrule {
-  name: "perfetto_protos_perfetto_config_android_lite_gen_headers",
-  srcs: [
-    "protos/perfetto/config/android/android_log_config.proto",
-    "protos/perfetto/config/android/packages_list_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/android/android_log_config.pb.h",
-    "external/perfetto/protos/perfetto/config/android/packages_list_config.pb.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/android:zero
-genrule {
-  name: "perfetto_protos_perfetto_config_android_zero_gen",
-  srcs: [
-    "protos/perfetto/config/android/android_log_config.proto",
-    "protos/perfetto/config/android/packages_list_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/android/android_log_config.pbzero.cc",
-    "external/perfetto/protos/perfetto/config/android/packages_list_config.pbzero.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/android:zero
-genrule {
-  name: "perfetto_protos_perfetto_config_android_zero_gen_headers",
-  srcs: [
-    "protos/perfetto/config/android/android_log_config.proto",
-    "protos/perfetto/config/android/packages_list_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/android/android_log_config.pbzero.h",
-    "external/perfetto/protos/perfetto/config/android/packages_list_config.pbzero.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_cpp_gen",
-  srcs: [
-    "protos/perfetto/config/chrome/chrome_config.proto",
-    "protos/perfetto/config/data_source_config.proto",
-    "protos/perfetto/config/test_config.proto",
-    "protos/perfetto/config/trace_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/chrome/chrome_config.gen.cc",
-    "external/perfetto/protos/perfetto/config/data_source_config.gen.cc",
-    "external/perfetto/protos/perfetto/config/test_config.gen.cc",
-    "external/perfetto/protos/perfetto/config/trace_config.gen.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_cpp_gen_headers",
-  srcs: [
-    "protos/perfetto/config/chrome/chrome_config.proto",
-    "protos/perfetto/config/data_source_config.proto",
-    "protos/perfetto/config/test_config.proto",
-    "protos/perfetto/config/trace_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/chrome/chrome_config.gen.h",
-    "external/perfetto/protos/perfetto/config/data_source_config.gen.h",
-    "external/perfetto/protos/perfetto/config/test_config.gen.h",
-    "external/perfetto/protos/perfetto/config/trace_config.gen.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/ftrace:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_ftrace_cpp_gen",
-  srcs: [
-    "protos/perfetto/config/ftrace/ftrace_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.gen.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/ftrace:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
-  srcs: [
-    "protos/perfetto/config/ftrace/ftrace_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.gen.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/ftrace:lite
-genrule {
-  name: "perfetto_protos_perfetto_config_ftrace_lite_gen",
-  srcs: [
-    "protos/perfetto/config/ftrace/ftrace_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pb.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/ftrace:lite
-genrule {
-  name: "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
-  srcs: [
-    "protos/perfetto/config/ftrace/ftrace_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pb.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/ftrace:zero
-genrule {
-  name: "perfetto_protos_perfetto_config_ftrace_zero_gen",
-  srcs: [
-    "protos/perfetto/config/ftrace/ftrace_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pbzero.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/ftrace:zero
-genrule {
-  name: "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
-  srcs: [
-    "protos/perfetto/config/ftrace/ftrace_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pbzero.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/gpu:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_gpu_cpp_gen",
-  srcs: [
-    "protos/perfetto/config/gpu/gpu_counter_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/gpu/gpu_counter_config.gen.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/gpu:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
-  srcs: [
-    "protos/perfetto/config/gpu/gpu_counter_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/gpu/gpu_counter_config.gen.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/gpu:lite
-genrule {
-  name: "perfetto_protos_perfetto_config_gpu_lite_gen",
-  srcs: [
-    "protos/perfetto/config/gpu/gpu_counter_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/gpu/gpu_counter_config.pb.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/gpu:lite
-genrule {
-  name: "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
-  srcs: [
-    "protos/perfetto/config/gpu/gpu_counter_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/gpu/gpu_counter_config.pb.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/gpu:zero
-genrule {
-  name: "perfetto_protos_perfetto_config_gpu_zero_gen",
-  srcs: [
-    "protos/perfetto/config/gpu/gpu_counter_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/gpu/gpu_counter_config.pbzero.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/gpu:zero
-genrule {
-  name: "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
-  srcs: [
-    "protos/perfetto/config/gpu/gpu_counter_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/gpu/gpu_counter_config.pbzero.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/inode_file:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_inode_file_cpp_gen",
-  srcs: [
-    "protos/perfetto/config/inode_file/inode_file_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.gen.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/inode_file:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
-  srcs: [
-    "protos/perfetto/config/inode_file/inode_file_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.gen.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/inode_file:lite
-genrule {
-  name: "perfetto_protos_perfetto_config_inode_file_lite_gen",
-  srcs: [
-    "protos/perfetto/config/inode_file/inode_file_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pb.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/inode_file:lite
-genrule {
-  name: "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
-  srcs: [
-    "protos/perfetto/config/inode_file/inode_file_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pb.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/inode_file:zero
-genrule {
-  name: "perfetto_protos_perfetto_config_inode_file_zero_gen",
-  srcs: [
-    "protos/perfetto/config/inode_file/inode_file_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pbzero.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/inode_file:zero
-genrule {
-  name: "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
-  srcs: [
-    "protos/perfetto/config/inode_file/inode_file_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pbzero.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config:lite
+// GN target: //protos/perfetto/config:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_config_lite_gen",
   srcs: [
+    "protos/perfetto/config/android/android_log_config.proto",
+    "protos/perfetto/config/android/packages_list_config.proto",
     "protos/perfetto/config/chrome/chrome_config.proto",
     "protos/perfetto/config/data_source_config.proto",
+    "protos/perfetto/config/ftrace/ftrace_config.proto",
+    "protos/perfetto/config/inode_file/inode_file_config.proto",
+    "protos/perfetto/config/power/android_power_config.proto",
+    "protos/perfetto/config/process_stats/process_stats_config.proto",
+    "protos/perfetto/config/profiling/heapprofd_config.proto",
+    "protos/perfetto/config/sys_stats/sys_stats_config.proto",
     "protos/perfetto/config/test_config.proto",
     "protos/perfetto/config/trace_config.proto",
   ],
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
+    "external/perfetto/protos/perfetto/config/android/android_log_config.pb.cc",
+    "external/perfetto/protos/perfetto/config/android/packages_list_config.pb.cc",
     "external/perfetto/protos/perfetto/config/chrome/chrome_config.pb.cc",
     "external/perfetto/protos/perfetto/config/data_source_config.pb.cc",
+    "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pb.cc",
+    "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pb.cc",
+    "external/perfetto/protos/perfetto/config/power/android_power_config.pb.cc",
+    "external/perfetto/protos/perfetto/config/process_stats/process_stats_config.pb.cc",
+    "external/perfetto/protos/perfetto/config/profiling/heapprofd_config.pb.cc",
+    "external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.pb.cc",
     "external/perfetto/protos/perfetto/config/test_config.pb.cc",
     "external/perfetto/protos/perfetto/config/trace_config.pb.cc",
   ],
 }
 
-// GN: //protos/perfetto/config:lite
+// GN target: //protos/perfetto/config:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_config_lite_gen_headers",
   srcs: [
+    "protos/perfetto/config/android/android_log_config.proto",
+    "protos/perfetto/config/android/packages_list_config.proto",
     "protos/perfetto/config/chrome/chrome_config.proto",
     "protos/perfetto/config/data_source_config.proto",
+    "protos/perfetto/config/ftrace/ftrace_config.proto",
+    "protos/perfetto/config/inode_file/inode_file_config.proto",
+    "protos/perfetto/config/power/android_power_config.proto",
+    "protos/perfetto/config/process_stats/process_stats_config.proto",
+    "protos/perfetto/config/profiling/heapprofd_config.proto",
+    "protos/perfetto/config/sys_stats/sys_stats_config.proto",
     "protos/perfetto/config/test_config.proto",
     "protos/perfetto/config/trace_config.proto",
   ],
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
+    "external/perfetto/protos/perfetto/config/android/android_log_config.pb.h",
+    "external/perfetto/protos/perfetto/config/android/packages_list_config.pb.h",
     "external/perfetto/protos/perfetto/config/chrome/chrome_config.pb.h",
     "external/perfetto/protos/perfetto/config/data_source_config.pb.h",
+    "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pb.h",
+    "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pb.h",
+    "external/perfetto/protos/perfetto/config/power/android_power_config.pb.h",
+    "external/perfetto/protos/perfetto/config/process_stats/process_stats_config.pb.h",
+    "external/perfetto/protos/perfetto/config/profiling/heapprofd_config.pb.h",
+    "external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.pb.h",
     "external/perfetto/protos/perfetto/config/test_config.pb.h",
     "external/perfetto/protos/perfetto/config/trace_config.pb.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/config/power:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_power_cpp_gen",
-  srcs: [
-    "protos/perfetto/config/power/android_power_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/power/android_power_config.gen.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/power:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_power_cpp_gen_headers",
-  srcs: [
-    "protos/perfetto/config/power/android_power_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/power/android_power_config.gen.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/power:lite
-genrule {
-  name: "perfetto_protos_perfetto_config_power_lite_gen",
-  srcs: [
-    "protos/perfetto/config/power/android_power_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/power/android_power_config.pb.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/power:lite
-genrule {
-  name: "perfetto_protos_perfetto_config_power_lite_gen_headers",
-  srcs: [
-    "protos/perfetto/config/power/android_power_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/power/android_power_config.pb.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/power:zero
-genrule {
-  name: "perfetto_protos_perfetto_config_power_zero_gen",
-  srcs: [
-    "protos/perfetto/config/power/android_power_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/power/android_power_config.pbzero.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/power:zero
-genrule {
-  name: "perfetto_protos_perfetto_config_power_zero_gen_headers",
-  srcs: [
-    "protos/perfetto/config/power/android_power_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/power/android_power_config.pbzero.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/process_stats:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_process_stats_cpp_gen",
-  srcs: [
-    "protos/perfetto/config/process_stats/process_stats_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/process_stats/process_stats_config.gen.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/process_stats:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
-  srcs: [
-    "protos/perfetto/config/process_stats/process_stats_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/process_stats/process_stats_config.gen.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/process_stats:lite
-genrule {
-  name: "perfetto_protos_perfetto_config_process_stats_lite_gen",
-  srcs: [
-    "protos/perfetto/config/process_stats/process_stats_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/process_stats/process_stats_config.pb.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/process_stats:lite
-genrule {
-  name: "perfetto_protos_perfetto_config_process_stats_lite_gen_headers",
-  srcs: [
-    "protos/perfetto/config/process_stats/process_stats_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/process_stats/process_stats_config.pb.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/process_stats:zero
-genrule {
-  name: "perfetto_protos_perfetto_config_process_stats_zero_gen",
-  srcs: [
-    "protos/perfetto/config/process_stats/process_stats_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/process_stats/process_stats_config.pbzero.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/process_stats:zero
-genrule {
-  name: "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
-  srcs: [
-    "protos/perfetto/config/process_stats/process_stats_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/process_stats/process_stats_config.pbzero.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/profiling:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_profiling_cpp_gen",
-  srcs: [
-    "protos/perfetto/config/profiling/heapprofd_config.proto",
-    "protos/perfetto/config/profiling/java_hprof_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/profiling/heapprofd_config.gen.cc",
-    "external/perfetto/protos/perfetto/config/profiling/java_hprof_config.gen.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/profiling:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
-  srcs: [
-    "protos/perfetto/config/profiling/heapprofd_config.proto",
-    "protos/perfetto/config/profiling/java_hprof_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/profiling/heapprofd_config.gen.h",
-    "external/perfetto/protos/perfetto/config/profiling/java_hprof_config.gen.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/profiling:lite
-genrule {
-  name: "perfetto_protos_perfetto_config_profiling_lite_gen",
-  srcs: [
-    "protos/perfetto/config/profiling/heapprofd_config.proto",
-    "protos/perfetto/config/profiling/java_hprof_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/profiling/heapprofd_config.pb.cc",
-    "external/perfetto/protos/perfetto/config/profiling/java_hprof_config.pb.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/profiling:lite
-genrule {
-  name: "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
-  srcs: [
-    "protos/perfetto/config/profiling/heapprofd_config.proto",
-    "protos/perfetto/config/profiling/java_hprof_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/profiling/heapprofd_config.pb.h",
-    "external/perfetto/protos/perfetto/config/profiling/java_hprof_config.pb.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/profiling:zero
-genrule {
-  name: "perfetto_protos_perfetto_config_profiling_zero_gen",
-  srcs: [
-    "protos/perfetto/config/profiling/heapprofd_config.proto",
-    "protos/perfetto/config/profiling/java_hprof_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/profiling/heapprofd_config.pbzero.cc",
-    "external/perfetto/protos/perfetto/config/profiling/java_hprof_config.pbzero.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/profiling:zero
-genrule {
-  name: "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
-  srcs: [
-    "protos/perfetto/config/profiling/heapprofd_config.proto",
-    "protos/perfetto/config/profiling/java_hprof_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/profiling/heapprofd_config.pbzero.h",
-    "external/perfetto/protos/perfetto/config/profiling/java_hprof_config.pbzero.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/sys_stats:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_sys_stats_cpp_gen",
-  srcs: [
-    "protos/perfetto/config/sys_stats/sys_stats_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.gen.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/sys_stats:cpp
-genrule {
-  name: "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
-  srcs: [
-    "protos/perfetto/config/sys_stats/sys_stats_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_cppgen_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.gen.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/sys_stats:lite
-genrule {
-  name: "perfetto_protos_perfetto_config_sys_stats_lite_gen",
-  srcs: [
-    "protos/perfetto/config/sys_stats/sys_stats_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.pb.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/sys_stats:lite
-genrule {
-  name: "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
-  srcs: [
-    "protos/perfetto/config/sys_stats/sys_stats_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.pb.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config/sys_stats:zero
-genrule {
-  name: "perfetto_protos_perfetto_config_sys_stats_zero_gen",
-  srcs: [
-    "protos/perfetto/config/sys_stats/sys_stats_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.pbzero.cc",
-  ],
-}
-
-// GN: //protos/perfetto/config/sys_stats:zero
-genrule {
-  name: "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
-  srcs: [
-    "protos/perfetto/config/sys_stats/sys_stats_config.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.pbzero.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/config:zero
+// GN target: //protos/perfetto/config:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_config_zero_gen",
   srcs: [
+    "protos/perfetto/config/android/android_log_config.proto",
+    "protos/perfetto/config/android/packages_list_config.proto",
     "protos/perfetto/config/chrome/chrome_config.proto",
     "protos/perfetto/config/data_source_config.proto",
+    "protos/perfetto/config/ftrace/ftrace_config.proto",
+    "protos/perfetto/config/inode_file/inode_file_config.proto",
+    "protos/perfetto/config/power/android_power_config.proto",
+    "protos/perfetto/config/process_stats/process_stats_config.proto",
+    "protos/perfetto/config/profiling/heapprofd_config.proto",
+    "protos/perfetto/config/sys_stats/sys_stats_config.proto",
     "protos/perfetto/config/test_config.proto",
     "protos/perfetto/config/trace_config.proto",
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
+    "external/perfetto/protos/perfetto/config/android/android_log_config.pbzero.cc",
+    "external/perfetto/protos/perfetto/config/android/packages_list_config.pbzero.cc",
     "external/perfetto/protos/perfetto/config/chrome/chrome_config.pbzero.cc",
     "external/perfetto/protos/perfetto/config/data_source_config.pbzero.cc",
+    "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pbzero.cc",
+    "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pbzero.cc",
+    "external/perfetto/protos/perfetto/config/power/android_power_config.pbzero.cc",
+    "external/perfetto/protos/perfetto/config/process_stats/process_stats_config.pbzero.cc",
+    "external/perfetto/protos/perfetto/config/profiling/heapprofd_config.pbzero.cc",
+    "external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.pbzero.cc",
     "external/perfetto/protos/perfetto/config/test_config.pbzero.cc",
     "external/perfetto/protos/perfetto/config/trace_config.pbzero.cc",
   ],
 }
 
-// GN: //protos/perfetto/config:zero
+// GN target: //protos/perfetto/config:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_config_zero_gen_headers",
   srcs: [
+    "protos/perfetto/config/android/android_log_config.proto",
+    "protos/perfetto/config/android/packages_list_config.proto",
     "protos/perfetto/config/chrome/chrome_config.proto",
     "protos/perfetto/config/data_source_config.proto",
+    "protos/perfetto/config/ftrace/ftrace_config.proto",
+    "protos/perfetto/config/inode_file/inode_file_config.proto",
+    "protos/perfetto/config/power/android_power_config.proto",
+    "protos/perfetto/config/process_stats/process_stats_config.proto",
+    "protos/perfetto/config/profiling/heapprofd_config.proto",
+    "protos/perfetto/config/sys_stats/sys_stats_config.proto",
     "protos/perfetto/config/test_config.proto",
     "protos/perfetto/config/trace_config.proto",
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
+    "external/perfetto/protos/perfetto/config/android/android_log_config.pbzero.h",
+    "external/perfetto/protos/perfetto/config/android/packages_list_config.pbzero.h",
     "external/perfetto/protos/perfetto/config/chrome/chrome_config.pbzero.h",
     "external/perfetto/protos/perfetto/config/data_source_config.pbzero.h",
+    "external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pbzero.h",
+    "external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pbzero.h",
+    "external/perfetto/protos/perfetto/config/power/android_power_config.pbzero.h",
+    "external/perfetto/protos/perfetto/config/process_stats/process_stats_config.pbzero.h",
+    "external/perfetto/protos/perfetto/config/profiling/heapprofd_config.pbzero.h",
+    "external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.pbzero.h",
     "external/perfetto/protos/perfetto/config/test_config.pbzero.h",
     "external/perfetto/protos/perfetto/config/trace_config.pbzero.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/ipc:ipc
+// GN target: //protos/perfetto/ipc:ipc_gen
 genrule {
   name: "perfetto_protos_perfetto_ipc_ipc_gen",
   srcs: [
@@ -2321,9 +1064,9 @@
   ],
   tools: [
     "aprotoc",
-    "ipc_plugin",
+    "perfetto_src_ipc_protoc_plugin_ipc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location ipc_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_ipc_protoc_plugin_ipc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/ipc/consumer_port.ipc.cc",
     "external/perfetto/protos/perfetto/ipc/consumer_port.pb.cc",
@@ -2332,7 +1075,7 @@
   ],
 }
 
-// GN: //protos/perfetto/ipc:ipc
+// GN target: //protos/perfetto/ipc:ipc_gen
 genrule {
   name: "perfetto_protos_perfetto_ipc_ipc_gen_headers",
   srcs: [
@@ -2341,9 +1084,9 @@
   ],
   tools: [
     "aprotoc",
-    "ipc_plugin",
+    "perfetto_src_ipc_protoc_plugin_ipc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location ipc_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_ipc_protoc_plugin_ipc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/ipc/consumer_port.ipc.h",
     "external/perfetto/protos/perfetto/ipc/consumer_port.pb.h",
@@ -2351,130 +1094,46 @@
     "external/perfetto/protos/perfetto/ipc/producer_port.pb.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/ipc:wire_protocol
-genrule {
-  name: "perfetto_protos_perfetto_ipc_wire_protocol_gen",
-  srcs: [
-    "protos/perfetto/ipc/wire_protocol.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/ipc/wire_protocol.pb.cc",
-  ],
-}
-
-// GN: //protos/perfetto/ipc:wire_protocol
-genrule {
-  name: "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
-  srcs: [
-    "protos/perfetto/ipc/wire_protocol.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/ipc/wire_protocol.pb.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/metrics/android:zero
+// GN target: //protos/perfetto/metrics/android:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_metrics_android_zero_gen",
   srcs: [
-    "protos/perfetto/metrics/android/batt_metric.proto",
-    "protos/perfetto/metrics/android/cpu_metric.proto",
-    "protos/perfetto/metrics/android/heap_profile_callsites.proto",
-    "protos/perfetto/metrics/android/ion_metric.proto",
-    "protos/perfetto/metrics/android/java_heap_stats.proto",
-    "protos/perfetto/metrics/android/lmk_metric.proto",
     "protos/perfetto/metrics/android/mem_metric.proto",
-    "protos/perfetto/metrics/android/mem_unagg_metric.proto",
-    "protos/perfetto/metrics/android/package_list.proto",
-    "protos/perfetto/metrics/android/powrails_metric.proto",
-    "protos/perfetto/metrics/android/process_growth.proto",
-    "protos/perfetto/metrics/android/startup_metric.proto",
-    "protos/perfetto/metrics/android/unsymbolized_frames.proto",
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
-    "external/perfetto/protos/perfetto/metrics/android/batt_metric.pbzero.cc",
-    "external/perfetto/protos/perfetto/metrics/android/cpu_metric.pbzero.cc",
-    "external/perfetto/protos/perfetto/metrics/android/heap_profile_callsites.pbzero.cc",
-    "external/perfetto/protos/perfetto/metrics/android/ion_metric.pbzero.cc",
-    "external/perfetto/protos/perfetto/metrics/android/java_heap_stats.pbzero.cc",
-    "external/perfetto/protos/perfetto/metrics/android/lmk_metric.pbzero.cc",
     "external/perfetto/protos/perfetto/metrics/android/mem_metric.pbzero.cc",
-    "external/perfetto/protos/perfetto/metrics/android/mem_unagg_metric.pbzero.cc",
-    "external/perfetto/protos/perfetto/metrics/android/package_list.pbzero.cc",
-    "external/perfetto/protos/perfetto/metrics/android/powrails_metric.pbzero.cc",
-    "external/perfetto/protos/perfetto/metrics/android/process_growth.pbzero.cc",
-    "external/perfetto/protos/perfetto/metrics/android/startup_metric.pbzero.cc",
-    "external/perfetto/protos/perfetto/metrics/android/unsymbolized_frames.pbzero.cc",
   ],
 }
 
-// GN: //protos/perfetto/metrics/android:zero
+// GN target: //protos/perfetto/metrics/android:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_metrics_android_zero_gen_headers",
   srcs: [
-    "protos/perfetto/metrics/android/batt_metric.proto",
-    "protos/perfetto/metrics/android/cpu_metric.proto",
-    "protos/perfetto/metrics/android/heap_profile_callsites.proto",
-    "protos/perfetto/metrics/android/ion_metric.proto",
-    "protos/perfetto/metrics/android/java_heap_stats.proto",
-    "protos/perfetto/metrics/android/lmk_metric.proto",
     "protos/perfetto/metrics/android/mem_metric.proto",
-    "protos/perfetto/metrics/android/mem_unagg_metric.proto",
-    "protos/perfetto/metrics/android/package_list.proto",
-    "protos/perfetto/metrics/android/powrails_metric.proto",
-    "protos/perfetto/metrics/android/process_growth.proto",
-    "protos/perfetto/metrics/android/startup_metric.proto",
-    "protos/perfetto/metrics/android/unsymbolized_frames.proto",
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
-    "external/perfetto/protos/perfetto/metrics/android/batt_metric.pbzero.h",
-    "external/perfetto/protos/perfetto/metrics/android/cpu_metric.pbzero.h",
-    "external/perfetto/protos/perfetto/metrics/android/heap_profile_callsites.pbzero.h",
-    "external/perfetto/protos/perfetto/metrics/android/ion_metric.pbzero.h",
-    "external/perfetto/protos/perfetto/metrics/android/java_heap_stats.pbzero.h",
-    "external/perfetto/protos/perfetto/metrics/android/lmk_metric.pbzero.h",
     "external/perfetto/protos/perfetto/metrics/android/mem_metric.pbzero.h",
-    "external/perfetto/protos/perfetto/metrics/android/mem_unagg_metric.pbzero.h",
-    "external/perfetto/protos/perfetto/metrics/android/package_list.pbzero.h",
-    "external/perfetto/protos/perfetto/metrics/android/powrails_metric.pbzero.h",
-    "external/perfetto/protos/perfetto/metrics/android/process_growth.pbzero.h",
-    "external/perfetto/protos/perfetto/metrics/android/startup_metric.pbzero.h",
-    "external/perfetto/protos/perfetto/metrics/android/unsymbolized_frames.pbzero.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/metrics:zero
+// GN target: //protos/perfetto/metrics:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_metrics_zero_gen",
   srcs: [
@@ -2482,15 +1141,15 @@
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/metrics/metrics.pbzero.cc",
   ],
 }
 
-// GN: //protos/perfetto/metrics:zero
+// GN target: //protos/perfetto/metrics:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_metrics_zero_gen_headers",
   srcs: [
@@ -2498,191 +1157,162 @@
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/metrics/metrics.pbzero.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace/android:lite
+// GN target: //protos/perfetto/trace/android:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_android_lite_gen",
   srcs: [
     "protos/perfetto/trace/android/android_log.proto",
-    "protos/perfetto/trace/android/graphics_frame_event.proto",
     "protos/perfetto/trace/android/packages_list.proto",
   ],
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/android/android_log.pb.cc",
-    "external/perfetto/protos/perfetto/trace/android/graphics_frame_event.pb.cc",
     "external/perfetto/protos/perfetto/trace/android/packages_list.pb.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace/android:lite
+// GN target: //protos/perfetto/trace/android:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_android_lite_gen_headers",
   srcs: [
     "protos/perfetto/trace/android/android_log.proto",
-    "protos/perfetto/trace/android/graphics_frame_event.proto",
     "protos/perfetto/trace/android/packages_list.proto",
   ],
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/android/android_log.pb.h",
-    "external/perfetto/protos/perfetto/trace/android/graphics_frame_event.pb.h",
     "external/perfetto/protos/perfetto/trace/android/packages_list.pb.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace/android:zero
+// GN target: //protos/perfetto/trace/android:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_android_zero_gen",
   srcs: [
     "protos/perfetto/trace/android/android_log.proto",
-    "protos/perfetto/trace/android/graphics_frame_event.proto",
     "protos/perfetto/trace/android/packages_list.proto",
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/android/android_log.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/android/graphics_frame_event.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/android/packages_list.pbzero.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace/android:zero
+// GN target: //protos/perfetto/trace/android:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_android_zero_gen_headers",
   srcs: [
     "protos/perfetto/trace/android/android_log.proto",
-    "protos/perfetto/trace/android/graphics_frame_event.proto",
     "protos/perfetto/trace/android/packages_list.proto",
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/android/android_log.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/android/graphics_frame_event.pbzero.h",
     "external/perfetto/protos/perfetto/trace/android/packages_list.pbzero.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace/chrome:lite
+// GN target: //protos/perfetto/trace/chrome:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_chrome_lite_gen",
   srcs: [
-    "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
-    "protos/perfetto/trace/chrome/chrome_metadata.proto",
     "protos/perfetto/trace/chrome/chrome_trace_event.proto",
   ],
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/chrome/chrome_benchmark_metadata.pb.cc",
-    "external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pb.cc",
     "external/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pb.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace/chrome:lite
+// GN target: //protos/perfetto/trace/chrome:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
   srcs: [
-    "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
-    "protos/perfetto/trace/chrome/chrome_metadata.proto",
     "protos/perfetto/trace/chrome/chrome_trace_event.proto",
   ],
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/chrome/chrome_benchmark_metadata.pb.h",
-    "external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pb.h",
     "external/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pb.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace/chrome:zero
+// GN target: //protos/perfetto/trace/chrome:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_chrome_zero_gen",
   srcs: [
-    "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
-    "protos/perfetto/trace/chrome/chrome_metadata.proto",
     "protos/perfetto/trace/chrome/chrome_trace_event.proto",
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/chrome/chrome_benchmark_metadata.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pbzero.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace/chrome:zero
+// GN target: //protos/perfetto/trace/chrome:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
   srcs: [
-    "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
-    "protos/perfetto/trace/chrome/chrome_metadata.proto",
     "protos/perfetto/trace/chrome/chrome_trace_event.proto",
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/chrome/chrome_benchmark_metadata.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pbzero.h",
     "external/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pbzero.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace/filesystem:lite
+// GN target: //protos/perfetto/trace/filesystem:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_filesystem_lite_gen",
   srcs: [
@@ -2691,13 +1321,13 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/filesystem/inode_file_map.pb.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace/filesystem:lite
+// GN target: //protos/perfetto/trace/filesystem:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_filesystem_lite_gen_headers",
   srcs: [
@@ -2706,17 +1336,16 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/filesystem/inode_file_map.pb.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace/filesystem:zero
+// GN target: //protos/perfetto/trace/filesystem:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_filesystem_zero_gen",
   srcs: [
@@ -2724,15 +1353,15 @@
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/filesystem/inode_file_map.pbzero.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace/filesystem:zero
+// GN target: //protos/perfetto/trace/filesystem:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
   srcs: [
@@ -2740,19 +1369,18 @@
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/filesystem/inode_file_map.pbzero.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace/ftrace:lite
+// GN target: //protos/perfetto/trace/ftrace:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_ftrace_lite_gen",
   srcs: [
@@ -2793,7 +1421,7 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/ftrace/binder.pb.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/block.pb.cc",
@@ -2831,7 +1459,7 @@
   ],
 }
 
-// GN: //protos/perfetto/trace/ftrace:lite
+// GN target: //protos/perfetto/trace/ftrace:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_ftrace_lite_gen_headers",
   srcs: [
@@ -2872,7 +1500,7 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/ftrace/binder.pb.h",
     "external/perfetto/protos/perfetto/trace/ftrace/block.pb.h",
@@ -2909,12 +1537,11 @@
     "external/perfetto/protos/perfetto/trace/ftrace/workqueue.pb.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace/ftrace:zero
+// GN target: //protos/perfetto/trace/ftrace:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_ftrace_zero_gen",
   srcs: [
@@ -2954,9 +1581,9 @@
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/ftrace/binder.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ftrace/block.pbzero.cc",
@@ -2994,7 +1621,7 @@
   ],
 }
 
-// GN: //protos/perfetto/trace/ftrace:zero
+// GN target: //protos/perfetto/trace/ftrace:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
   srcs: [
@@ -3034,9 +1661,9 @@
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/ftrace/binder.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ftrace/block.pbzero.h",
@@ -3073,106 +1700,11 @@
     "external/perfetto/protos/perfetto/trace/ftrace/workqueue.pbzero.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace/gpu:lite
-genrule {
-  name: "perfetto_protos_perfetto_trace_gpu_lite_gen",
-  srcs: [
-    "protos/perfetto/trace/gpu/gpu_counter_event.proto",
-    "protos/perfetto/trace/gpu/gpu_log.proto",
-    "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
-    "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/trace/gpu/gpu_counter_event.pb.cc",
-    "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pb.cc",
-    "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pb.cc",
-    "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pb.cc",
-  ],
-}
-
-// GN: //protos/perfetto/trace/gpu:lite
-genrule {
-  name: "perfetto_protos_perfetto_trace_gpu_lite_gen_headers",
-  srcs: [
-    "protos/perfetto/trace/gpu/gpu_counter_event.proto",
-    "protos/perfetto/trace/gpu/gpu_log.proto",
-    "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
-    "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/trace/gpu/gpu_counter_event.pb.h",
-    "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pb.h",
-    "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pb.h",
-    "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pb.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/trace/gpu:zero
-genrule {
-  name: "perfetto_protos_perfetto_trace_gpu_zero_gen",
-  srcs: [
-    "protos/perfetto/trace/gpu/gpu_counter_event.proto",
-    "protos/perfetto/trace/gpu/gpu_log.proto",
-    "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
-    "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/trace/gpu/gpu_counter_event.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.cc",
-  ],
-}
-
-// GN: //protos/perfetto/trace/gpu:zero
-genrule {
-  name: "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
-  srcs: [
-    "protos/perfetto/trace/gpu/gpu_counter_event.proto",
-    "protos/perfetto/trace/gpu/gpu_log.proto",
-    "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
-    "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/trace/gpu/gpu_counter_event.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/gpu/gpu_log.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/trace/interned_data:lite
+// GN target: //protos/perfetto/trace/interned_data:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_interned_data_lite_gen",
   srcs: [
@@ -3181,13 +1713,13 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/interned_data/interned_data.pb.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace/interned_data:lite
+// GN target: //protos/perfetto/trace/interned_data:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_interned_data_lite_gen_headers",
   srcs: [
@@ -3196,17 +1728,16 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/interned_data/interned_data.pb.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace/interned_data:zero
+// GN target: //protos/perfetto/trace/interned_data:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_interned_data_zero_gen",
   srcs: [
@@ -3214,15 +1745,15 @@
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/interned_data/interned_data.pbzero.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace/interned_data:zero
+// GN target: //protos/perfetto/trace/interned_data:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
   srcs: [
@@ -3230,19 +1761,59 @@
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/interned_data/interned_data.pbzero.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace:minimal_lite
+// GN target: //protos/perfetto/trace:lite_gen
+genrule {
+  name: "perfetto_protos_perfetto_trace_lite_gen",
+  srcs: [
+    "protos/perfetto/trace/test_event.proto",
+    "protos/perfetto/trace/trace.proto",
+    "protos/perfetto/trace/trace_packet.proto",
+  ],
+  tools: [
+    "aprotoc",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/test_event.pb.cc",
+    "external/perfetto/protos/perfetto/trace/trace.pb.cc",
+    "external/perfetto/protos/perfetto/trace/trace_packet.pb.cc",
+  ],
+}
+
+// GN target: //protos/perfetto/trace:lite_gen
+genrule {
+  name: "perfetto_protos_perfetto_trace_lite_gen_headers",
+  srcs: [
+    "protos/perfetto/trace/test_event.proto",
+    "protos/perfetto/trace/trace.proto",
+    "protos/perfetto/trace/trace_packet.proto",
+  ],
+  tools: [
+    "aprotoc",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/test_event.pb.h",
+    "external/perfetto/protos/perfetto/trace/trace.pb.h",
+    "external/perfetto/protos/perfetto/trace/trace_packet.pb.h",
+  ],
+  export_include_dirs: [
+    "protos",
+  ],
+}
+
+// GN target: //protos/perfetto/trace:minimal_lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_minimal_lite_gen",
   srcs: [
@@ -3253,7 +1824,7 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/clock_snapshot.pb.cc",
     "external/perfetto/protos/perfetto/trace/system_info.pb.cc",
@@ -3261,7 +1832,7 @@
   ],
 }
 
-// GN: //protos/perfetto/trace:minimal_lite
+// GN target: //protos/perfetto/trace:minimal_lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
   srcs: [
@@ -3272,227 +1843,18 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/clock_snapshot.pb.h",
     "external/perfetto/protos/perfetto/trace/system_info.pb.h",
     "external/perfetto/protos/perfetto/trace/trigger.pb.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace:minimal_zero
-genrule {
-  name: "perfetto_protos_perfetto_trace_minimal_zero_gen",
-  srcs: [
-    "protos/perfetto/trace/clock_snapshot.proto",
-    "protos/perfetto/trace/system_info.proto",
-    "protos/perfetto/trace/trigger.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/trace/clock_snapshot.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/system_info.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/trigger.pbzero.cc",
-  ],
-}
-
-// GN: //protos/perfetto/trace:minimal_zero
-genrule {
-  name: "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
-  srcs: [
-    "protos/perfetto/trace/clock_snapshot.proto",
-    "protos/perfetto/trace/system_info.proto",
-    "protos/perfetto/trace/trigger.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/trace/clock_snapshot.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/system_info.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/trigger.pbzero.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/trace:non_minimal_lite
-genrule {
-  name: "perfetto_protos_perfetto_trace_non_minimal_lite_gen",
-  srcs: [
-    "protos/perfetto/trace/test_event.proto",
-    "protos/perfetto/trace/trace.proto",
-    "protos/perfetto/trace/trace_packet.proto",
-    "protos/perfetto/trace/trace_packet_defaults.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/trace/test_event.pb.cc",
-    "external/perfetto/protos/perfetto/trace/trace.pb.cc",
-    "external/perfetto/protos/perfetto/trace/trace_packet.pb.cc",
-    "external/perfetto/protos/perfetto/trace/trace_packet_defaults.pb.cc",
-  ],
-}
-
-// GN: //protos/perfetto/trace:non_minimal_lite
-genrule {
-  name: "perfetto_protos_perfetto_trace_non_minimal_lite_gen_headers",
-  srcs: [
-    "protos/perfetto/trace/test_event.proto",
-    "protos/perfetto/trace/trace.proto",
-    "protos/perfetto/trace/trace_packet.proto",
-    "protos/perfetto/trace/trace_packet_defaults.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/trace/test_event.pb.h",
-    "external/perfetto/protos/perfetto/trace/trace.pb.h",
-    "external/perfetto/protos/perfetto/trace/trace_packet.pb.h",
-    "external/perfetto/protos/perfetto/trace/trace_packet_defaults.pb.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/trace:non_minimal_zero
-genrule {
-  name: "perfetto_protos_perfetto_trace_non_minimal_zero_gen",
-  srcs: [
-    "protos/perfetto/trace/test_event.proto",
-    "protos/perfetto/trace/trace.proto",
-    "protos/perfetto/trace/trace_packet.proto",
-    "protos/perfetto/trace/trace_packet_defaults.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/trace/test_event.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/trace.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/trace_packet.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/trace_packet_defaults.pbzero.cc",
-  ],
-}
-
-// GN: //protos/perfetto/trace:non_minimal_zero
-genrule {
-  name: "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
-  srcs: [
-    "protos/perfetto/trace/test_event.proto",
-    "protos/perfetto/trace/trace.proto",
-    "protos/perfetto/trace/trace_packet.proto",
-    "protos/perfetto/trace/trace_packet_defaults.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/trace/test_event.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/trace.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/trace_packet.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/trace_packet_defaults.pbzero.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/trace/perfetto:lite
-genrule {
-  name: "perfetto_protos_perfetto_trace_perfetto_lite_gen",
-  srcs: [
-    "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/trace/perfetto/perfetto_metatrace.pb.cc",
-  ],
-}
-
-// GN: //protos/perfetto/trace/perfetto:lite
-genrule {
-  name: "perfetto_protos_perfetto_trace_perfetto_lite_gen_headers",
-  srcs: [
-    "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
-  ],
-  tools: [
-    "aprotoc",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/trace/perfetto/perfetto_metatrace.pb.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/trace/perfetto:zero
-genrule {
-  name: "perfetto_protos_perfetto_trace_perfetto_zero_gen",
-  srcs: [
-    "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/trace/perfetto/perfetto_metatrace.pbzero.cc",
-  ],
-}
-
-// GN: //protos/perfetto/trace/perfetto:zero
-genrule {
-  name: "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
-  srcs: [
-    "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/trace/perfetto/perfetto_metatrace.pbzero.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/trace/power:lite
+// GN target: //protos/perfetto/trace/power:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_power_lite_gen",
   srcs: [
@@ -3502,14 +1864,14 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/power/battery_counters.pb.cc",
     "external/perfetto/protos/perfetto/trace/power/power_rails.pb.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace/power:lite
+// GN target: //protos/perfetto/trace/power:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_power_lite_gen_headers",
   srcs: [
@@ -3519,18 +1881,17 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/power/battery_counters.pb.h",
     "external/perfetto/protos/perfetto/trace/power/power_rails.pb.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace/power:zero
+// GN target: //protos/perfetto/trace/power:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_power_zero_gen",
   srcs: [
@@ -3539,16 +1900,16 @@
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/power/battery_counters.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/power/power_rails.pbzero.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace/power:zero
+// GN target: //protos/perfetto/trace/power:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_power_zero_gen_headers",
   srcs: [
@@ -3557,142 +1918,87 @@
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/power/battery_counters.pbzero.h",
     "external/perfetto/protos/perfetto/trace/power/power_rails.pbzero.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace_processor:metrics_impl_zero
-genrule {
-  name: "perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen",
-  srcs: [
-    "protos/perfetto/trace_processor/metrics_impl.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/trace_processor/metrics_impl.pbzero.cc",
-  ],
-}
-
-// GN: //protos/perfetto/trace_processor:metrics_impl_zero
-genrule {
-  name: "perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen_headers",
-  srcs: [
-    "protos/perfetto/trace_processor/metrics_impl.proto",
-  ],
-  tools: [
-    "aprotoc",
-    "protozero_plugin",
-  ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
-  out: [
-    "external/perfetto/protos/perfetto/trace_processor/metrics_impl.pbzero.h",
-  ],
-  export_include_dirs: [
-    ".",
-    "protos",
-  ],
-}
-
-// GN: //protos/perfetto/trace/profiling:lite
+// GN target: //protos/perfetto/trace/profiling:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_profiling_lite_gen",
   srcs: [
-    "protos/perfetto/trace/profiling/heap_graph.proto",
-    "protos/perfetto/trace/profiling/profile_common.proto",
     "protos/perfetto/trace/profiling/profile_packet.proto",
   ],
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/profiling/heap_graph.pb.cc",
-    "external/perfetto/protos/perfetto/trace/profiling/profile_common.pb.cc",
     "external/perfetto/protos/perfetto/trace/profiling/profile_packet.pb.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace/profiling:lite
+// GN target: //protos/perfetto/trace/profiling:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_profiling_lite_gen_headers",
   srcs: [
-    "protos/perfetto/trace/profiling/heap_graph.proto",
-    "protos/perfetto/trace/profiling/profile_common.proto",
     "protos/perfetto/trace/profiling/profile_packet.proto",
   ],
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/profiling/heap_graph.pb.h",
-    "external/perfetto/protos/perfetto/trace/profiling/profile_common.pb.h",
     "external/perfetto/protos/perfetto/trace/profiling/profile_packet.pb.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace/profiling:zero
+// GN target: //protos/perfetto/trace/profiling:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_profiling_zero_gen",
   srcs: [
-    "protos/perfetto/trace/profiling/heap_graph.proto",
-    "protos/perfetto/trace/profiling/profile_common.proto",
     "protos/perfetto/trace/profiling/profile_packet.proto",
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/profiling/heap_graph.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/profiling/profile_common.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/profiling/profile_packet.pbzero.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace/profiling:zero
+// GN target: //protos/perfetto/trace/profiling:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
   srcs: [
-    "protos/perfetto/trace/profiling/heap_graph.proto",
-    "protos/perfetto/trace/profiling/profile_common.proto",
     "protos/perfetto/trace/profiling/profile_packet.proto",
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
-    "external/perfetto/protos/perfetto/trace/profiling/heap_graph.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/profiling/profile_common.pbzero.h",
     "external/perfetto/protos/perfetto/trace/profiling/profile_packet.pbzero.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace/ps:lite
+// GN target: //protos/perfetto/trace/ps:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_ps_lite_gen",
   srcs: [
@@ -3702,14 +2008,14 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/ps/process_stats.pb.cc",
     "external/perfetto/protos/perfetto/trace/ps/process_tree.pb.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace/ps:lite
+// GN target: //protos/perfetto/trace/ps:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_ps_lite_gen_headers",
   srcs: [
@@ -3719,18 +2025,17 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/ps/process_stats.pb.h",
     "external/perfetto/protos/perfetto/trace/ps/process_tree.pb.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace/ps:zero
+// GN target: //protos/perfetto/trace/ps:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_ps_zero_gen",
   srcs: [
@@ -3739,16 +2044,16 @@
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/ps/process_stats.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/ps/process_tree.pbzero.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace/ps:zero
+// GN target: //protos/perfetto/trace/ps:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
   srcs: [
@@ -3757,20 +2062,19 @@
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/ps/process_stats.pbzero.h",
     "external/perfetto/protos/perfetto/trace/ps/process_tree.pbzero.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace/sys_stats:lite
+// GN target: //protos/perfetto/trace/sys_stats:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_sys_stats_lite_gen",
   srcs: [
@@ -3779,13 +2083,13 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/sys_stats/sys_stats.pb.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace/sys_stats:lite
+// GN target: //protos/perfetto/trace/sys_stats:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_sys_stats_lite_gen_headers",
   srcs: [
@@ -3794,17 +2098,16 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/sys_stats/sys_stats.pb.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace/sys_stats:zero
+// GN target: //protos/perfetto/trace/sys_stats:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_sys_stats_zero_gen",
   srcs: [
@@ -3812,15 +2115,15 @@
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/sys_stats/sys_stats.pbzero.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace/sys_stats:zero
+// GN target: //protos/perfetto/trace/sys_stats:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
   srcs: [
@@ -3828,145 +2131,118 @@
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/sys_stats/sys_stats.pbzero.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace/track_event:lite
+// GN target: //protos/perfetto/trace/track_event:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_track_event_lite_gen",
   srcs: [
     "protos/perfetto/trace/track_event/debug_annotation.proto",
-    "protos/perfetto/trace/track_event/log_message.proto",
     "protos/perfetto/trace/track_event/process_descriptor.proto",
-    "protos/perfetto/trace/track_event/source_location.proto",
     "protos/perfetto/trace/track_event/task_execution.proto",
     "protos/perfetto/trace/track_event/thread_descriptor.proto",
-    "protos/perfetto/trace/track_event/track_descriptor.proto",
     "protos/perfetto/trace/track_event/track_event.proto",
   ],
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pb.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/log_message.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pb.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/source_location.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/task_execution.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.pb.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/track_descriptor.pb.cc",
     "external/perfetto/protos/perfetto/trace/track_event/track_event.pb.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace/track_event:lite
+// GN target: //protos/perfetto/trace/track_event:lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_track_event_lite_gen_headers",
   srcs: [
     "protos/perfetto/trace/track_event/debug_annotation.proto",
-    "protos/perfetto/trace/track_event/log_message.proto",
     "protos/perfetto/trace/track_event/process_descriptor.proto",
-    "protos/perfetto/trace/track_event/source_location.proto",
     "protos/perfetto/trace/track_event/task_execution.proto",
     "protos/perfetto/trace/track_event/thread_descriptor.proto",
-    "protos/perfetto/trace/track_event/track_descriptor.proto",
     "protos/perfetto/trace/track_event/track_event.proto",
   ],
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pb.h",
-    "external/perfetto/protos/perfetto/trace/track_event/log_message.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pb.h",
-    "external/perfetto/protos/perfetto/trace/track_event/source_location.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/task_execution.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.pb.h",
-    "external/perfetto/protos/perfetto/trace/track_event/track_descriptor.pb.h",
     "external/perfetto/protos/perfetto/trace/track_event/track_event.pb.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace/track_event:zero
+// GN target: //protos/perfetto/trace/track_event:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_track_event_zero_gen",
   srcs: [
     "protos/perfetto/trace/track_event/debug_annotation.proto",
-    "protos/perfetto/trace/track_event/log_message.proto",
     "protos/perfetto/trace/track_event/process_descriptor.proto",
-    "protos/perfetto/trace/track_event/source_location.proto",
     "protos/perfetto/trace/track_event/task_execution.proto",
     "protos/perfetto/trace/track_event/thread_descriptor.proto",
-    "protos/perfetto/trace/track_event/track_descriptor.proto",
     "protos/perfetto/trace/track_event/track_event.proto",
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/log_message.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/source_location.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/task_execution.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.pbzero.cc",
-    "external/perfetto/protos/perfetto/trace/track_event/track_descriptor.pbzero.cc",
     "external/perfetto/protos/perfetto/trace/track_event/track_event.pbzero.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace/track_event:zero
+// GN target: //protos/perfetto/trace/track_event:zero_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
   srcs: [
     "protos/perfetto/trace/track_event/debug_annotation.proto",
-    "protos/perfetto/trace/track_event/log_message.proto",
     "protos/perfetto/trace/track_event/process_descriptor.proto",
-    "protos/perfetto/trace/track_event/source_location.proto",
     "protos/perfetto/trace/track_event/task_execution.proto",
     "protos/perfetto/trace/track_event/thread_descriptor.proto",
-    "protos/perfetto/trace/track_event/track_descriptor.proto",
     "protos/perfetto/trace/track_event/track_event.proto",
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/track_event/log_message.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/process_descriptor.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/track_event/source_location.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/task_execution.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/thread_descriptor.pbzero.h",
-    "external/perfetto/protos/perfetto/trace/track_event/track_descriptor.pbzero.h",
     "external/perfetto/protos/perfetto/trace/track_event/track_event.pbzero.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/perfetto/trace:trusted_lite
+// GN target: //protos/perfetto/trace:trusted_lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_trusted_lite_gen",
   srcs: [
@@ -3975,13 +2251,13 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/trusted_packet.pb.cc",
   ],
 }
 
-// GN: //protos/perfetto/trace:trusted_lite
+// GN target: //protos/perfetto/trace:trusted_lite_gen
 genrule {
   name: "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
   srcs: [
@@ -3990,17 +2266,71 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/perfetto/trace/trusted_packet.pb.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //protos/third_party/pprof:lite
+// GN target: //protos/perfetto/trace:zero_gen
+genrule {
+  name: "perfetto_protos_perfetto_trace_zero_gen",
+  srcs: [
+    "protos/perfetto/trace/clock_snapshot.proto",
+    "protos/perfetto/trace/system_info.proto",
+    "protos/perfetto/trace/test_event.proto",
+    "protos/perfetto/trace/trace.proto",
+    "protos/perfetto/trace/trace_packet.proto",
+    "protos/perfetto/trace/trigger.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/clock_snapshot.pbzero.cc",
+    "external/perfetto/protos/perfetto/trace/system_info.pbzero.cc",
+    "external/perfetto/protos/perfetto/trace/test_event.pbzero.cc",
+    "external/perfetto/protos/perfetto/trace/trace.pbzero.cc",
+    "external/perfetto/protos/perfetto/trace/trace_packet.pbzero.cc",
+    "external/perfetto/protos/perfetto/trace/trigger.pbzero.cc",
+  ],
+}
+
+// GN target: //protos/perfetto/trace:zero_gen
+genrule {
+  name: "perfetto_protos_perfetto_trace_zero_gen_headers",
+  srcs: [
+    "protos/perfetto/trace/clock_snapshot.proto",
+    "protos/perfetto/trace/system_info.proto",
+    "protos/perfetto/trace/test_event.proto",
+    "protos/perfetto/trace/trace.proto",
+    "protos/perfetto/trace/trace_packet.proto",
+    "protos/perfetto/trace/trigger.proto",
+  ],
+  tools: [
+    "aprotoc",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/protos $(in)",
+  out: [
+    "external/perfetto/protos/perfetto/trace/clock_snapshot.pbzero.h",
+    "external/perfetto/protos/perfetto/trace/system_info.pbzero.h",
+    "external/perfetto/protos/perfetto/trace/test_event.pbzero.h",
+    "external/perfetto/protos/perfetto/trace/trace.pbzero.h",
+    "external/perfetto/protos/perfetto/trace/trace_packet.pbzero.h",
+    "external/perfetto/protos/perfetto/trace/trigger.pbzero.h",
+  ],
+  export_include_dirs: [
+    "protos",
+  ],
+}
+
+// GN target: //protos/third_party/pprof:lite_gen
 genrule {
   name: "perfetto_protos_third_party_pprof_lite_gen",
   srcs: [
@@ -4009,13 +2339,13 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/third_party/pprof/profile.pb.cc",
   ],
 }
 
-// GN: //protos/third_party/pprof:lite
+// GN target: //protos/third_party/pprof:lite_gen
 genrule {
   name: "perfetto_protos_third_party_pprof_lite_gen_headers",
   srcs: [
@@ -4024,124 +2354,36 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto/protos && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/protos --proto_path=external/perfetto/protos $(in)",
   out: [
     "external/perfetto/protos/third_party/pprof/profile.pb.h",
   ],
   export_include_dirs: [
-    ".",
     "protos",
   ],
 }
 
-// GN: //src/android_internal:android_internal
-filegroup {
-  name: "perfetto_src_android_internal_android_internal",
+// GN target: //src/ipc/protoc_plugin:ipc_plugin(//gn/standalone/toolchain:gcc_like_host)
+cc_binary_host {
+  name: "perfetto_src_ipc_protoc_plugin_ipc_plugin___gn_standalone_toolchain_gcc_like_host_",
   srcs: [
-    "src/android_internal/atrace_hal.cc",
-    "src/android_internal/dropbox_service.cc",
-    "src/android_internal/health_hal.cc",
-    "src/android_internal/incident_service.cc",
-    "src/android_internal/power_stats_hal.cc",
+    "src/ipc/protoc_plugin/ipc_generator.cc",
+    "src/ipc/protoc_plugin/ipc_plugin.cc",
+  ],
+  shared_libs: [
+    "libprotoc",
+  ],
+  defaults: [
+    "perfetto_defaults",
+  ],
+  cflags: [
+    "-DGOOGLE_PROTOBUF_NO_RTTI",
+    "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+    "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
 }
 
-// GN: //src/android_internal:headers
-filegroup {
-  name: "perfetto_src_android_internal_headers",
-}
-
-// GN: //src/android_internal:lazy_library_loader
-filegroup {
-  name: "perfetto_src_android_internal_lazy_library_loader",
-  srcs: [
-    "src/android_internal/lazy_library_loader.cc",
-  ],
-}
-
-// GN: //src/base:base
-filegroup {
-  name: "perfetto_src_base_base",
-  srcs: [
-    "src/base/event_fd.cc",
-    "src/base/file_utils.cc",
-    "src/base/metatrace.cc",
-    "src/base/paged_memory.cc",
-    "src/base/pipe.cc",
-    "src/base/string_splitter.cc",
-    "src/base/string_utils.cc",
-    "src/base/string_view.cc",
-    "src/base/temp_file.cc",
-    "src/base/thread_checker.cc",
-    "src/base/thread_task_runner.cc",
-    "src/base/time.cc",
-    "src/base/unix_task_runner.cc",
-    "src/base/uuid.cc",
-    "src/base/virtual_destructors.cc",
-    "src/base/waitable_event.cc",
-    "src/base/watchdog_posix.cc",
-  ],
-}
-
-// GN: //src/base:test_support
-filegroup {
-  name: "perfetto_src_base_test_support",
-  srcs: [
-    "src/base/test/test_task_runner.cc",
-    "src/base/test/utils.cc",
-    "src/base/test/vm_test_utils.cc",
-  ],
-}
-
-// GN: //src/base:unittests
-filegroup {
-  name: "perfetto_src_base_unittests",
-  srcs: [
-    "src/base/circular_queue_unittest.cc",
-    "src/base/metatrace_unittest.cc",
-    "src/base/no_destructor_unittest.cc",
-    "src/base/optional_unittest.cc",
-    "src/base/paged_memory_unittest.cc",
-    "src/base/scoped_file_unittest.cc",
-    "src/base/string_splitter_unittest.cc",
-    "src/base/string_utils_unittest.cc",
-    "src/base/string_view_unittest.cc",
-    "src/base/string_writer_unittest.cc",
-    "src/base/task_runner_unittest.cc",
-    "src/base/temp_file_unittest.cc",
-    "src/base/thread_checker_unittest.cc",
-    "src/base/thread_task_runner_unittest.cc",
-    "src/base/time_unittest.cc",
-    "src/base/unix_socket_unittest.cc",
-    "src/base/utils_unittest.cc",
-    "src/base/uuid_unittest.cc",
-    "src/base/watchdog_unittest.cc",
-    "src/base/weak_ptr_unittest.cc",
-  ],
-}
-
-// GN: //src/base:unix_socket
-filegroup {
-  name: "perfetto_src_base_unix_socket",
-  srcs: [
-    "src/base/unix_socket.cc",
-  ],
-}
-
-// GN: //src/ipc:ipc
-filegroup {
-  name: "perfetto_src_ipc_ipc",
-  srcs: [
-    "src/ipc/buffered_frame_deserializer.cc",
-    "src/ipc/client_impl.cc",
-    "src/ipc/deferred.cc",
-    "src/ipc/host_impl.cc",
-    "src/ipc/service_proxy.cc",
-    "src/ipc/virtual_destructors.cc",
-  ],
-}
-
-// GN: //src/ipc:test_messages
+// GN target: //src/ipc:test_messages_gen
 genrule {
   name: "perfetto_src_ipc_test_messages_gen",
   srcs: [
@@ -4151,9 +2393,9 @@
   ],
   tools: [
     "aprotoc",
-    "ipc_plugin",
+    "perfetto_src_ipc_protoc_plugin_ipc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location ipc_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto/ --plugin=protoc-gen-plugin=$(location perfetto_src_ipc_protoc_plugin_ipc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=:$(genDir)/external/perfetto $(in)",
   out: [
     "external/perfetto/src/ipc/test/client_unittest_messages.ipc.cc",
     "external/perfetto/src/ipc/test/client_unittest_messages.pb.cc",
@@ -4164,7 +2406,7 @@
   ],
 }
 
-// GN: //src/ipc:test_messages
+// GN target: //src/ipc:test_messages_gen
 genrule {
   name: "perfetto_src_ipc_test_messages_gen_headers",
   srcs: [
@@ -4174,9 +2416,9 @@
   ],
   tools: [
     "aprotoc",
-    "ipc_plugin",
+    "perfetto_src_ipc_protoc_plugin_ipc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location ipc_plugin) --plugin_out=:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto/ --plugin=protoc-gen-plugin=$(location perfetto_src_ipc_protoc_plugin_ipc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=:$(genDir)/external/perfetto $(in)",
   out: [
     "external/perfetto/src/ipc/test/client_unittest_messages.ipc.h",
     "external/perfetto/src/ipc/test/client_unittest_messages.pb.h",
@@ -4187,36 +2429,43 @@
   ],
   export_include_dirs: [
     ".",
-    "protos",
   ],
 }
 
-// GN: //src/ipc:unittests
-filegroup {
-  name: "perfetto_src_ipc_unittests",
+// GN target: //src/ipc:wire_protocol_gen
+genrule {
+  name: "perfetto_src_ipc_wire_protocol_gen",
   srcs: [
-    "src/ipc/buffered_frame_deserializer_unittest.cc",
-    "src/ipc/client_impl_unittest.cc",
-    "src/ipc/deferred_unittest.cc",
-    "src/ipc/host_impl_unittest.cc",
-    "src/ipc/test/ipc_integrationtest.cc",
+    "src/ipc/wire_protocol.proto",
+  ],
+  tools: [
+    "aprotoc",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/src/ipc/wire_protocol.pb.cc",
   ],
 }
 
-// GN: //src/perfetto_cmd:perfetto_cmd
-filegroup {
-  name: "perfetto_src_perfetto_cmd_perfetto_cmd",
+// GN target: //src/ipc:wire_protocol_gen
+genrule {
+  name: "perfetto_src_ipc_wire_protocol_gen_headers",
   srcs: [
-    "src/perfetto_cmd/config.cc",
-    "src/perfetto_cmd/packet_writer.cc",
-    "src/perfetto_cmd/pbtxt_to_pb.cc",
-    "src/perfetto_cmd/perfetto_cmd.cc",
-    "src/perfetto_cmd/perfetto_cmd_android.cc",
-    "src/perfetto_cmd/rate_limiter.cc",
+    "src/ipc/wire_protocol.proto",
+  ],
+  tools: [
+    "aprotoc",
+  ],
+  cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto/ $(in)",
+  out: [
+    "external/perfetto/src/ipc/wire_protocol.pb.h",
+  ],
+  export_include_dirs: [
+    ".",
   ],
 }
 
-// GN: //src/perfetto_cmd:protos
+// GN target: //src/perfetto_cmd:protos_gen
 genrule {
   name: "perfetto_src_perfetto_cmd_protos_gen",
   srcs: [
@@ -4225,13 +2474,13 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto/ $(in)",
   out: [
     "external/perfetto/src/perfetto_cmd/perfetto_cmd_state.pb.cc",
   ],
 }
 
-// GN: //src/perfetto_cmd:protos
+// GN target: //src/perfetto_cmd:protos_gen
 genrule {
   name: "perfetto_src_perfetto_cmd_protos_gen_headers",
   srcs: [
@@ -4240,149 +2489,23 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto/ $(in)",
   out: [
     "external/perfetto/src/perfetto_cmd/perfetto_cmd_state.pb.h",
   ],
   export_include_dirs: [
     ".",
-    "protos",
   ],
 }
 
-// GN: //src/perfetto_cmd:trigger_perfetto_cmd
-filegroup {
-  name: "perfetto_src_perfetto_cmd_trigger_perfetto_cmd",
-  srcs: [
-    "src/perfetto_cmd/trigger_perfetto.cc",
-  ],
-}
-
-// GN: //src/perfetto_cmd:trigger_producer
-filegroup {
-  name: "perfetto_src_perfetto_cmd_trigger_producer",
-  srcs: [
-    "src/perfetto_cmd/trigger_producer.cc",
-  ],
-}
-
-// GN: //src/perfetto_cmd:unittests
-filegroup {
-  name: "perfetto_src_perfetto_cmd_unittests",
-  srcs: [
-    "src/perfetto_cmd/config_unittest.cc",
-    "src/perfetto_cmd/packet_writer_unittest.cc",
-    "src/perfetto_cmd/pbtxt_to_pb_unittest.cc",
-    "src/perfetto_cmd/rate_limiter_unittest.cc",
-  ],
-}
-
-// GN: //src/profiling/memory:client
-filegroup {
-  name: "perfetto_src_profiling_memory_client",
-  srcs: [
-    "src/profiling/memory/client.cc",
-  ],
-}
-
-// GN: //src/profiling/memory:daemon
-filegroup {
-  name: "perfetto_src_profiling_memory_daemon",
-  srcs: [
-    "src/profiling/memory/bookkeeping.cc",
-    "src/profiling/memory/bookkeeping_dump.cc",
-    "src/profiling/memory/heapprofd_producer.cc",
-    "src/profiling/memory/java_hprof_producer.cc",
-    "src/profiling/memory/page_idle_checker.cc",
-    "src/profiling/memory/system_property.cc",
-    "src/profiling/memory/unwinding.cc",
-    "src/profiling/memory/utils.cc",
-  ],
-}
-
-// GN: //src/profiling/memory:end_to_end_tests
-filegroup {
-  name: "perfetto_src_profiling_memory_end_to_end_tests",
-  srcs: [
-    "src/profiling/memory/heapprofd_end_to_end_test.cc",
-  ],
-}
-
-// GN: //src/profiling/memory:malloc_hooks
-filegroup {
-  name: "perfetto_src_profiling_memory_malloc_hooks",
-  srcs: [
-    "src/profiling/memory/malloc_hooks.cc",
-  ],
-}
-
-// GN: //src/profiling/memory:proc_utils
-filegroup {
-  name: "perfetto_src_profiling_memory_proc_utils",
-  srcs: [
-    "src/profiling/memory/proc_utils.cc",
-  ],
-}
-
-// GN: //src/profiling/memory:ring_buffer
-filegroup {
-  name: "perfetto_src_profiling_memory_ring_buffer",
-  srcs: [
-    "src/profiling/memory/shared_ring_buffer.cc",
-  ],
-}
-
-// GN: //src/profiling/memory:ring_buffer_unittests
-filegroup {
-  name: "perfetto_src_profiling_memory_ring_buffer_unittests",
-  srcs: [
-    "src/profiling/memory/shared_ring_buffer_unittest.cc",
-  ],
-}
-
-// GN: //src/profiling/memory:scoped_spinlock
-filegroup {
-  name: "perfetto_src_profiling_memory_scoped_spinlock",
-  srcs: [
-    "src/profiling/memory/scoped_spinlock.cc",
-  ],
-}
-
-// GN: //src/profiling/memory:unittests
-filegroup {
-  name: "perfetto_src_profiling_memory_unittests",
-  srcs: [
-    "src/profiling/memory/bookkeeping_unittest.cc",
-    "src/profiling/memory/client_unittest.cc",
-    "src/profiling/memory/heapprofd_producer_unittest.cc",
-    "src/profiling/memory/interner_unittest.cc",
-    "src/profiling/memory/page_idle_checker_unittest.cc",
-    "src/profiling/memory/proc_utils_unittest.cc",
-    "src/profiling/memory/sampler_unittest.cc",
-    "src/profiling/memory/system_property_unittest.cc",
-    "src/profiling/memory/unwinding_unittest.cc",
-    "src/profiling/memory/wire_protocol_unittest.cc",
-  ],
-}
-
-// GN: //src/profiling/memory:wire_protocol
-filegroup {
-  name: "perfetto_src_profiling_memory_wire_protocol",
-  srcs: [
-    "src/profiling/memory/wire_protocol.cc",
-  ],
-}
-
-// GN: //src/protozero/protoc_plugin:cppgen_plugin
+// GN target: //src/protozero/protoc_plugin:protoc_plugin(//gn/standalone/toolchain:gcc_like_host)
 cc_binary_host {
-  name: "perfetto_src_protozero_protoc_plugin_cppgen_plugin",
+  name: "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   srcs: [
-    ":perfetto_include_perfetto_base_base",
-    ":perfetto_include_perfetto_ext_base_base",
-    ":perfetto_src_base_base",
-    "src/protozero/protoc_plugin/cppgen_plugin.cc",
+    "src/protozero/protoc_plugin/protozero_generator.cc",
+    "src/protozero/protoc_plugin/protozero_plugin.cc",
   ],
-  static_libs: [
+  shared_libs: [
     "libprotoc",
   ],
   defaults: [
@@ -4391,24 +2514,11 @@
   cflags: [
     "-DGOOGLE_PROTOBUF_NO_RTTI",
     "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+    "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
 }
 
-// GN: //src/protozero:protozero
-filegroup {
-  name: "perfetto_src_protozero_protozero",
-  srcs: [
-    "src/protozero/message.cc",
-    "src/protozero/message_handle.cc",
-    "src/protozero/packed_repeated_fields.cc",
-    "src/protozero/proto_decoder.cc",
-    "src/protozero/scattered_heap_buffer.cc",
-    "src/protozero/scattered_stream_null_delegate.cc",
-    "src/protozero/scattered_stream_writer.cc",
-  ],
-}
-
-// GN: //src/protozero:testing_messages_lite
+// GN target: //src/protozero:testing_messages_lite_gen
 genrule {
   name: "perfetto_src_protozero_testing_messages_lite_gen",
   srcs: [
@@ -4420,7 +2530,7 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto/ $(in)",
   out: [
     "external/perfetto/src/protozero/test/example_proto/library.pb.cc",
     "external/perfetto/src/protozero/test/example_proto/library_internals/galaxies.pb.cc",
@@ -4429,7 +2539,7 @@
   ],
 }
 
-// GN: //src/protozero:testing_messages_lite
+// GN target: //src/protozero:testing_messages_lite_gen
 genrule {
   name: "perfetto_src_protozero_testing_messages_lite_gen_headers",
   srcs: [
@@ -4441,7 +2551,7 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto/ $(in)",
   out: [
     "external/perfetto/src/protozero/test/example_proto/library.pb.h",
     "external/perfetto/src/protozero/test/example_proto/library_internals/galaxies.pb.h",
@@ -4450,11 +2560,10 @@
   ],
   export_include_dirs: [
     ".",
-    "protos",
   ],
 }
 
-// GN: //src/protozero:testing_messages_zero
+// GN target: //src/protozero:testing_messages_zero_gen
 genrule {
   name: "perfetto_src_protozero_testing_messages_zero_gen",
   srcs: [
@@ -4465,9 +2574,9 @@
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto/ --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto $(in)",
   out: [
     "external/perfetto/src/protozero/test/example_proto/library.pbzero.cc",
     "external/perfetto/src/protozero/test/example_proto/library_internals/galaxies.pbzero.cc",
@@ -4476,7 +2585,7 @@
   ],
 }
 
-// GN: //src/protozero:testing_messages_zero
+// GN target: //src/protozero:testing_messages_zero_gen
 genrule {
   name: "perfetto_src_protozero_testing_messages_zero_gen_headers",
   srcs: [
@@ -4487,9 +2596,9 @@
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto/ --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto $(in)",
   out: [
     "external/perfetto/src/protozero/test/example_proto/library.pbzero.h",
     "external/perfetto/src/protozero/test/example_proto/library_internals/galaxies.pbzero.h",
@@ -4498,303 +2607,10 @@
   ],
   export_include_dirs: [
     ".",
-    "protos",
   ],
 }
 
-// GN: //src/protozero:unittests
-filegroup {
-  name: "perfetto_src_protozero_unittests",
-  srcs: [
-    "src/protozero/copyable_ptr_unittest.cc",
-    "src/protozero/message_handle_unittest.cc",
-    "src/protozero/message_unittest.cc",
-    "src/protozero/proto_decoder_unittest.cc",
-    "src/protozero/proto_utils_unittest.cc",
-    "src/protozero/scattered_stream_writer_unittest.cc",
-    "src/protozero/test/fake_scattered_buffer.cc",
-    "src/protozero/test/protozero_conformance_unittest.cc",
-  ],
-}
-
-// GN: //src/trace_processor:common
-filegroup {
-  name: "perfetto_src_trace_processor_common",
-  srcs: [
-    "src/trace_processor/string_pool.cc",
-  ],
-}
-
-// GN: //src/trace_processor/db:lib
-filegroup {
-  name: "perfetto_src_trace_processor_db_lib",
-  srcs: [
-    "src/trace_processor/db/bit_vector.cc",
-    "src/trace_processor/db/bit_vector_iterators.cc",
-    "src/trace_processor/db/column.cc",
-    "src/trace_processor/db/row_map.cc",
-    "src/trace_processor/db/table.cc",
-  ],
-}
-
-// GN: //src/trace_processor/db:unittests
-filegroup {
-  name: "perfetto_src_trace_processor_db_unittests",
-  srcs: [
-    "src/trace_processor/db/bit_vector_unittest.cc",
-    "src/trace_processor/db/row_map_unittest.cc",
-    "src/trace_processor/db/sparse_vector_unittest.cc",
-  ],
-}
-
-// GN: //src/trace_processor:lib
-filegroup {
-  name: "perfetto_src_trace_processor_lib",
-  srcs: [
-    "src/trace_processor/android_logs_table.cc",
-    "src/trace_processor/args_table.cc",
-    "src/trace_processor/counter_values_table.cc",
-    "src/trace_processor/cpu_profile_stack_sample_table.cc",
-    "src/trace_processor/filtered_row_index.cc",
-    "src/trace_processor/heap_profile_allocation_table.cc",
-    "src/trace_processor/instants_table.cc",
-    "src/trace_processor/metadata_table.cc",
-    "src/trace_processor/process_table.cc",
-    "src/trace_processor/raw_table.cc",
-    "src/trace_processor/read_trace.cc",
-    "src/trace_processor/row_iterators.cc",
-    "src/trace_processor/sched_slice_table.cc",
-    "src/trace_processor/slice_table.cc",
-    "src/trace_processor/span_join_operator_table.cc",
-    "src/trace_processor/sql_stats_table.cc",
-    "src/trace_processor/stack_profile_frame_table.cc",
-    "src/trace_processor/stack_profile_mapping_table.cc",
-    "src/trace_processor/stats_table.cc",
-    "src/trace_processor/storage_columns.cc",
-    "src/trace_processor/storage_schema.cc",
-    "src/trace_processor/storage_table.cc",
-    "src/trace_processor/thread_table.cc",
-    "src/trace_processor/trace_processor.cc",
-    "src/trace_processor/trace_processor_impl.cc",
-    "src/trace_processor/window_operator_table.cc",
-  ],
-}
-
-// GN: //src/trace_processor/metrics:lib
-filegroup {
-  name: "perfetto_src_trace_processor_metrics_lib",
-  srcs: [
-    "src/trace_processor/metrics/descriptors.cc",
-    "src/trace_processor/metrics/metrics.cc",
-  ],
-}
-
-// GN: //src/trace_processor/metrics:unittests
-filegroup {
-  name: "perfetto_src_trace_processor_metrics_unittests",
-  srcs: [
-    "src/trace_processor/metrics/metrics_unittest.cc",
-  ],
-}
-
-// GN: //src/trace_processor/sqlite:sqlite
-filegroup {
-  name: "perfetto_src_trace_processor_sqlite_sqlite",
-  srcs: [
-    "src/trace_processor/sqlite/db_sqlite_table.cc",
-    "src/trace_processor/sqlite/query_constraints.cc",
-    "src/trace_processor/sqlite/sqlite3_str_split.cc",
-    "src/trace_processor/sqlite/sqlite_table.cc",
-  ],
-}
-
-// GN: //src/trace_processor/sqlite:unittests
-filegroup {
-  name: "perfetto_src_trace_processor_sqlite_unittests",
-  srcs: [
-    "src/trace_processor/sqlite/query_constraints_unittest.cc",
-    "src/trace_processor/sqlite/sqlite3_str_split_unittest.cc",
-  ],
-}
-
-// GN: //src/trace_processor:storage
-filegroup {
-  name: "perfetto_src_trace_processor_storage",
-  srcs: [
-    "src/trace_processor/args_tracker.cc",
-    "src/trace_processor/binder_tracker.cc",
-    "src/trace_processor/clock_tracker.cc",
-    "src/trace_processor/event_tracker.cc",
-    "src/trace_processor/forwarding_trace_parser.cc",
-    "src/trace_processor/ftrace_utils.cc",
-    "src/trace_processor/gzip_trace_parser.cc",
-    "src/trace_processor/heap_profile_tracker.cc",
-    "src/trace_processor/importers/ftrace/ftrace_descriptors.cc",
-    "src/trace_processor/importers/ftrace/ftrace_parser.cc",
-    "src/trace_processor/importers/ftrace/ftrace_tokenizer.cc",
-    "src/trace_processor/importers/ftrace/sched_event_tracker.cc",
-    "src/trace_processor/importers/fuchsia/fuchsia_provider_view.cc",
-    "src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc",
-    "src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc",
-    "src/trace_processor/importers/fuchsia/fuchsia_trace_utils.cc",
-    "src/trace_processor/importers/proto/android_probes_parser.cc",
-    "src/trace_processor/importers/proto/graphics_event_parser.cc",
-    "src/trace_processor/importers/proto/heap_graph_module.cc",
-    "src/trace_processor/importers/proto/heap_graph_tracker.cc",
-    "src/trace_processor/importers/proto/heap_graph_walker.cc",
-    "src/trace_processor/importers/proto/proto_trace_parser.cc",
-    "src/trace_processor/importers/proto/proto_trace_tokenizer.cc",
-    "src/trace_processor/importers/proto/system_probes_parser.cc",
-    "src/trace_processor/importers/proto/track_event_parser.cc",
-    "src/trace_processor/importers/proto/track_event_tokenizer.cc",
-    "src/trace_processor/importers/systrace/systrace_parser.cc",
-    "src/trace_processor/importers/systrace/systrace_trace_parser.cc",
-    "src/trace_processor/process_tracker.cc",
-    "src/trace_processor/slice_tracker.cc",
-    "src/trace_processor/stack_profile_tracker.cc",
-    "src/trace_processor/syscall_tracker.cc",
-    "src/trace_processor/trace_processor_context.cc",
-    "src/trace_processor/trace_processor_storage.cc",
-    "src/trace_processor/trace_processor_storage_impl.cc",
-    "src/trace_processor/trace_sorter.cc",
-    "src/trace_processor/trace_storage.cc",
-    "src/trace_processor/track_tracker.cc",
-    "src/trace_processor/virtual_destructors.cc",
-    "src/trace_processor/vulkan_memory_tracker.cc",
-  ],
-}
-
-// GN: //src/trace_processor/tables:tables
-filegroup {
-  name: "perfetto_src_trace_processor_tables_tables",
-}
-
-// GN: //src/trace_processor/tables:unittests
-filegroup {
-  name: "perfetto_src_trace_processor_tables_unittests",
-  srcs: [
-    "src/trace_processor/tables/macros_unittest.cc",
-  ],
-}
-
-// GN: //src/trace_processor:unittests
-filegroup {
-  name: "perfetto_src_trace_processor_unittests",
-  srcs: [
-    "src/trace_processor/args_table_unittest.cc",
-    "src/trace_processor/clock_tracker_unittest.cc",
-    "src/trace_processor/event_tracker_unittest.cc",
-    "src/trace_processor/filtered_row_index_unittest.cc",
-    "src/trace_processor/forwarding_trace_parser_unittest.cc",
-    "src/trace_processor/ftrace_utils_unittest.cc",
-    "src/trace_processor/heap_profile_tracker_unittest.cc",
-    "src/trace_processor/importers/fuchsia/fuchsia_trace_utils_unittest.cc",
-    "src/trace_processor/importers/proto/heap_graph_walker_unittest.cc",
-    "src/trace_processor/importers/proto/proto_trace_parser_unittest.cc",
-    "src/trace_processor/importers/systrace/systrace_parser_unittest.cc",
-    "src/trace_processor/metadata_table_unittest.cc",
-    "src/trace_processor/null_term_string_view_unittest.cc",
-    "src/trace_processor/process_table_unittest.cc",
-    "src/trace_processor/process_tracker_unittest.cc",
-    "src/trace_processor/sched_slice_table_unittest.cc",
-    "src/trace_processor/slice_tracker_unittest.cc",
-    "src/trace_processor/span_join_operator_table_unittest.cc",
-    "src/trace_processor/string_pool_unittest.cc",
-    "src/trace_processor/syscall_tracker_unittest.cc",
-    "src/trace_processor/thread_table_unittest.cc",
-    "src/trace_processor/trace_sorter_unittest.cc",
-  ],
-}
-
-// GN: //src/traced/probes/android_log:android_log
-filegroup {
-  name: "perfetto_src_traced_probes_android_log_android_log",
-  srcs: [
-    "src/traced/probes/android_log/android_log_data_source.cc",
-  ],
-}
-
-// GN: //src/traced/probes/android_log:unittests
-filegroup {
-  name: "perfetto_src_traced_probes_android_log_unittests",
-  srcs: [
-    "src/traced/probes/android_log/android_log_data_source_unittest.cc",
-  ],
-}
-
-// GN: //src/traced/probes:data_source
-filegroup {
-  name: "perfetto_src_traced_probes_data_source",
-  srcs: [
-    "src/traced/probes/probes_data_source.cc",
-  ],
-}
-
-// GN: //src/traced/probes/filesystem:filesystem
-filegroup {
-  name: "perfetto_src_traced_probes_filesystem_filesystem",
-  srcs: [
-    "src/traced/probes/filesystem/file_scanner.cc",
-    "src/traced/probes/filesystem/fs_mount.cc",
-    "src/traced/probes/filesystem/inode_file_data_source.cc",
-    "src/traced/probes/filesystem/lru_inode_cache.cc",
-    "src/traced/probes/filesystem/prefix_finder.cc",
-    "src/traced/probes/filesystem/range_tree.cc",
-  ],
-}
-
-// GN: //src/traced/probes/filesystem:unittests
-filegroup {
-  name: "perfetto_src_traced_probes_filesystem_unittests",
-  srcs: [
-    "src/traced/probes/filesystem/file_scanner_unittest.cc",
-    "src/traced/probes/filesystem/fs_mount_unittest.cc",
-    "src/traced/probes/filesystem/inode_file_data_source_unittest.cc",
-    "src/traced/probes/filesystem/lru_inode_cache_unittest.cc",
-    "src/traced/probes/filesystem/prefix_finder_unittest.cc",
-    "src/traced/probes/filesystem/range_tree_unittest.cc",
-  ],
-}
-
-// GN: //src/traced/probes/ftrace:format_parser
-filegroup {
-  name: "perfetto_src_traced_probes_ftrace_format_parser",
-  srcs: [
-    "src/traced/probes/ftrace/format_parser.cc",
-  ],
-}
-
-// GN: //src/traced/probes/ftrace:ftrace
-filegroup {
-  name: "perfetto_src_traced_probes_ftrace_ftrace",
-  srcs: [
-    "src/traced/probes/ftrace/atrace_hal_wrapper.cc",
-    "src/traced/probes/ftrace/atrace_wrapper.cc",
-    "src/traced/probes/ftrace/compact_sched.cc",
-    "src/traced/probes/ftrace/cpu_reader.cc",
-    "src/traced/probes/ftrace/cpu_stats_parser.cc",
-    "src/traced/probes/ftrace/event_info.cc",
-    "src/traced/probes/ftrace/event_info_constants.cc",
-    "src/traced/probes/ftrace/ftrace_config_muxer.cc",
-    "src/traced/probes/ftrace/ftrace_config_utils.cc",
-    "src/traced/probes/ftrace/ftrace_controller.cc",
-    "src/traced/probes/ftrace/ftrace_data_source.cc",
-    "src/traced/probes/ftrace/ftrace_metadata.cc",
-    "src/traced/probes/ftrace/ftrace_procfs.cc",
-    "src/traced/probes/ftrace/ftrace_stats.cc",
-    "src/traced/probes/ftrace/proto_translation_table.cc",
-  ],
-}
-
-// GN: //src/traced/probes/ftrace:integrationtests
-filegroup {
-  name: "perfetto_src_traced_probes_ftrace_integrationtests",
-  srcs: [
-    "src/traced/probes/ftrace/ftrace_procfs_integrationtest.cc",
-  ],
-}
-
-// GN: //src/traced/probes/ftrace:test_messages_lite
+// GN target: //src/traced/probes/ftrace:test_messages_lite_gen
 genrule {
   name: "perfetto_src_traced_probes_ftrace_test_messages_lite_gen",
   srcs: [
@@ -4803,13 +2619,13 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto/ $(in)",
   out: [
     "external/perfetto/src/traced/probes/ftrace/test/test_messages.pb.cc",
   ],
 }
 
-// GN: //src/traced/probes/ftrace:test_messages_lite
+// GN target: //src/traced/probes/ftrace:test_messages_lite_gen
 genrule {
   name: "perfetto_src_traced_probes_ftrace_test_messages_lite_gen_headers",
   srcs: [
@@ -4818,17 +2634,16 @@
   tools: [
     "aprotoc",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto/ $(in)",
   out: [
     "external/perfetto/src/traced/probes/ftrace/test/test_messages.pb.h",
   ],
   export_include_dirs: [
     ".",
-    "protos",
   ],
 }
 
-// GN: //src/traced/probes/ftrace:test_messages_zero
+// GN target: //src/traced/probes/ftrace:test_messages_zero_gen
 genrule {
   name: "perfetto_src_traced_probes_ftrace_test_messages_zero_gen",
   srcs: [
@@ -4836,15 +2651,15 @@
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto/ --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto $(in)",
   out: [
     "external/perfetto/src/traced/probes/ftrace/test/test_messages.pbzero.cc",
   ],
 }
 
-// GN: //src/traced/probes/ftrace:test_messages_zero
+// GN target: //src/traced/probes/ftrace:test_messages_zero_gen
 genrule {
   name: "perfetto_src_traced_probes_ftrace_test_messages_zero_gen_headers",
   srcs: [
@@ -4852,191 +2667,98 @@
   ],
   tools: [
     "aprotoc",
-    "protozero_plugin",
+    "perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_",
   ],
-  cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto/ --proto_path=external/perfetto --plugin=protoc-gen-plugin=$(location protozero_plugin) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto/ $(in)",
+  cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto/ --plugin=protoc-gen-plugin=$(location perfetto_src_protozero_protoc_plugin_protoc_plugin___gn_standalone_toolchain_gcc_like_host_) --plugin_out=wrapper_namespace=pbzero:$(genDir)/external/perfetto $(in)",
   out: [
     "external/perfetto/src/traced/probes/ftrace/test/test_messages.pbzero.h",
   ],
   export_include_dirs: [
     ".",
-    "protos",
   ],
 }
 
-// GN: //src/traced/probes/ftrace:test_support
-filegroup {
-  name: "perfetto_src_traced_probes_ftrace_test_support",
-  srcs: [
-    "src/traced/probes/ftrace/test/cpu_reader_support.cc",
-  ],
-}
-
-// GN: //src/traced/probes/ftrace:unittests
-filegroup {
-  name: "perfetto_src_traced_probes_ftrace_unittests",
-  srcs: [
-    "src/traced/probes/ftrace/cpu_reader_unittest.cc",
-    "src/traced/probes/ftrace/cpu_stats_parser_unittest.cc",
-    "src/traced/probes/ftrace/event_info_unittest.cc",
-    "src/traced/probes/ftrace/format_parser_unittest.cc",
-    "src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc",
-    "src/traced/probes/ftrace/ftrace_config_unittest.cc",
-    "src/traced/probes/ftrace/ftrace_controller_unittest.cc",
-    "src/traced/probes/ftrace/ftrace_procfs_unittest.cc",
-    "src/traced/probes/ftrace/proto_translation_table_unittest.cc",
-  ],
-}
-
-// GN: //src/traced/probes/metatrace:metatrace
-filegroup {
-  name: "perfetto_src_traced_probes_metatrace_metatrace",
-  srcs: [
-    "src/traced/probes/metatrace/metatrace_data_source.cc",
-  ],
-}
-
-// GN: //src/traced/probes/packages_list:packages_list
-filegroup {
-  name: "perfetto_src_traced_probes_packages_list_packages_list",
-  srcs: [
-    "src/traced/probes/packages_list/packages_list_data_source.cc",
-  ],
-}
-
-// GN: //src/traced/probes/packages_list:unittests
-filegroup {
-  name: "perfetto_src_traced_probes_packages_list_unittests",
-  srcs: [
-    "src/traced/probes/packages_list/packages_list_data_source_unittest.cc",
-  ],
-}
-
-// GN: //src/traced/probes/power:power
-filegroup {
-  name: "perfetto_src_traced_probes_power_power",
-  srcs: [
-    "src/traced/probes/power/android_power_data_source.cc",
-  ],
-}
-
-// GN: //src/traced/probes:probes
-filegroup {
-  name: "perfetto_src_traced_probes_probes",
-  srcs: [
-    "src/traced/probes/probes.cc",
-  ],
-}
-
-// GN: //src/traced/probes:probes_src
-filegroup {
-  name: "perfetto_src_traced_probes_probes_src",
-  srcs: [
-    "src/traced/probes/probes_producer.cc",
-  ],
-}
-
-// GN: //src/traced/probes/ps:ps
-filegroup {
-  name: "perfetto_src_traced_probes_ps_ps",
-  srcs: [
-    "src/traced/probes/ps/process_stats_data_source.cc",
-  ],
-}
-
-// GN: //src/traced/probes/ps:unittests
-filegroup {
-  name: "perfetto_src_traced_probes_ps_unittests",
-  srcs: [
-    "src/traced/probes/ps/process_stats_data_source_unittest.cc",
-  ],
-}
-
-// GN: //src/traced/probes/sys_stats:sys_stats
-filegroup {
-  name: "perfetto_src_traced_probes_sys_stats_sys_stats",
-  srcs: [
-    "src/traced/probes/sys_stats/sys_stats_data_source.cc",
-  ],
-}
-
-// GN: //src/traced/probes/sys_stats:unittests
-filegroup {
-  name: "perfetto_src_traced_probes_sys_stats_unittests",
-  srcs: [
-    "src/traced/probes/sys_stats/sys_stats_data_source_unittest.cc",
-  ],
-}
-
-// GN: //src/traced/probes:unittests
-filegroup {
-  name: "perfetto_src_traced_probes_unittests",
-}
-
-// GN: //src/traced/service:service
-filegroup {
-  name: "perfetto_src_traced_service_service",
-  srcs: [
-    "src/traced/service/builtin_producer.cc",
-    "src/traced/service/service.cc",
-  ],
-}
-
-// GN: //src/traced/service:unittests
-filegroup {
-  name: "perfetto_src_traced_service_unittests",
-  srcs: [
-    "src/traced/service/builtin_producer_unittest.cc",
-  ],
-}
-
-// GN: //src/tracing:client_api
-filegroup {
-  name: "perfetto_src_tracing_client_api",
-  srcs: [
-    "src/tracing/data_source.cc",
-    "src/tracing/internal/in_process_tracing_backend.cc",
-    "src/tracing/internal/system_tracing_backend.cc",
-    "src/tracing/internal/tracing_muxer_impl.cc",
-    "src/tracing/internal/track_event_internal.cc",
-    "src/tracing/platform.cc",
-    "src/tracing/tracing.cc",
-    "src/tracing/track_event_category_registry.cc",
-    "src/tracing/track_event_context.cc",
-    "src/tracing/virtual_destructors.cc",
-  ],
-}
-
-// GN: //src/tracing:client_api_integrationtests
-filegroup {
-  name: "perfetto_src_tracing_client_api_integrationtests",
-  srcs: [
-    "src/tracing/api_integrationtest.cc",
-    "src/tracing/test/tracing_module.cc",
-    "src/tracing/test/tracing_module2.cc",
-  ],
-}
-
-// GN: //src/tracing:common
-filegroup {
-  name: "perfetto_src_tracing_common",
-  srcs: [
-    "src/tracing/trace_writer_base.cc",
-  ],
-}
-
-// GN: //src/tracing:consumer_api_deprecated
-filegroup {
-  name: "perfetto_src_tracing_consumer_api_deprecated",
-  srcs: [
-    "src/tracing/api_impl/consumer_api.cc",
-  ],
-}
-
-// GN: //src/tracing:ipc
-filegroup {
+// GN target: //src/tracing:ipc
+cc_library_static {
   name: "perfetto_src_tracing_ipc",
   srcs: [
+    ":perfetto_protos_perfetto_common_lite_gen",
+    ":perfetto_protos_perfetto_common_zero_gen",
+    ":perfetto_protos_perfetto_config_lite_gen",
+    ":perfetto_protos_perfetto_config_zero_gen",
+    ":perfetto_protos_perfetto_ipc_ipc_gen",
+    ":perfetto_protos_perfetto_trace_android_zero_gen",
+    ":perfetto_protos_perfetto_trace_chrome_zero_gen",
+    ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
+    ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
+    ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
+    ":perfetto_protos_perfetto_trace_minimal_lite_gen",
+    ":perfetto_protos_perfetto_trace_power_zero_gen",
+    ":perfetto_protos_perfetto_trace_profiling_zero_gen",
+    ":perfetto_protos_perfetto_trace_ps_zero_gen",
+    ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
+    ":perfetto_protos_perfetto_trace_track_event_zero_gen",
+    ":perfetto_protos_perfetto_trace_trusted_lite_gen",
+    ":perfetto_protos_perfetto_trace_zero_gen",
+    ":perfetto_src_ipc_wire_protocol_gen",
+    "src/base/event.cc",
+    "src/base/file_utils.cc",
+    "src/base/metatrace.cc",
+    "src/base/paged_memory.cc",
+    "src/base/pipe.cc",
+    "src/base/string_splitter.cc",
+    "src/base/string_utils.cc",
+    "src/base/string_view.cc",
+    "src/base/temp_file.cc",
+    "src/base/thread_checker.cc",
+    "src/base/thread_task_runner.cc",
+    "src/base/time.cc",
+    "src/base/unix_socket.cc",
+    "src/base/unix_task_runner.cc",
+    "src/base/virtual_destructors.cc",
+    "src/base/watchdog_posix.cc",
+    "src/ipc/buffered_frame_deserializer.cc",
+    "src/ipc/client_impl.cc",
+    "src/ipc/deferred.cc",
+    "src/ipc/host_impl.cc",
+    "src/ipc/service_proxy.cc",
+    "src/ipc/virtual_destructors.cc",
+    "src/protozero/message.cc",
+    "src/protozero/message_handle.cc",
+    "src/protozero/proto_decoder.cc",
+    "src/protozero/scattered_heap_buffer.cc",
+    "src/protozero/scattered_stream_null_delegate.cc",
+    "src/protozero/scattered_stream_writer.cc",
+    "src/tracing/core/android_log_config.cc",
+    "src/tracing/core/android_power_config.cc",
+    "src/tracing/core/chrome_config.cc",
+    "src/tracing/core/commit_data_request.cc",
+    "src/tracing/core/data_source_config.cc",
+    "src/tracing/core/data_source_descriptor.cc",
+    "src/tracing/core/ftrace_config.cc",
+    "src/tracing/core/heapprofd_config.cc",
+    "src/tracing/core/id_allocator.cc",
+    "src/tracing/core/inode_file_config.cc",
+    "src/tracing/core/null_trace_writer.cc",
+    "src/tracing/core/observable_events.cc",
+    "src/tracing/core/packages_list_config.cc",
+    "src/tracing/core/packet_stream_validator.cc",
+    "src/tracing/core/process_stats_config.cc",
+    "src/tracing/core/shared_memory_abi.cc",
+    "src/tracing/core/shared_memory_arbiter_impl.cc",
+    "src/tracing/core/sliced_protobuf_input_stream.cc",
+    "src/tracing/core/startup_trace_writer.cc",
+    "src/tracing/core/startup_trace_writer_registry.cc",
+    "src/tracing/core/sys_stats_config.cc",
+    "src/tracing/core/test_config.cc",
+    "src/tracing/core/trace_buffer.cc",
+    "src/tracing/core/trace_config.cc",
+    "src/tracing/core/trace_packet.cc",
+    "src/tracing/core/trace_stats.cc",
+    "src/tracing/core/trace_writer_impl.cc",
+    "src/tracing/core/tracing_service_impl.cc",
+    "src/tracing/core/tracing_service_state.cc",
+    "src/tracing/core/virtual_destructors.cc",
     "src/tracing/ipc/consumer/consumer_ipc_client_impl.cc",
     "src/tracing/ipc/default_socket.cc",
     "src/tracing/ipc/posix_shared_memory.cc",
@@ -5045,196 +2767,80 @@
     "src/tracing/ipc/service/producer_ipc_service.cc",
     "src/tracing/ipc/service/service_ipc_host_impl.cc",
   ],
-}
-
-// GN: //src/tracing:platform_posix
-filegroup {
-  name: "perfetto_src_tracing_platform_posix",
-  srcs: [
-    "src/tracing/platform_posix.cc",
+  shared_libs: [
+    "libprotobuf-cpp-lite",
+  ],
+  static_libs: [
+    "libgtest_prod",
+  ],
+  export_include_dirs: [
+    "include",
+  ],
+  generated_headers: [
+    "perfetto_protos_perfetto_common_lite_gen_headers",
+    "perfetto_protos_perfetto_common_zero_gen_headers",
+    "perfetto_protos_perfetto_config_lite_gen_headers",
+    "perfetto_protos_perfetto_config_zero_gen_headers",
+    "perfetto_protos_perfetto_ipc_ipc_gen_headers",
+    "perfetto_protos_perfetto_trace_android_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_power_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_zero_gen_headers",
+    "perfetto_src_ipc_wire_protocol_gen_headers",
+  ],
+  export_generated_headers: [
+    "perfetto_protos_perfetto_common_lite_gen_headers",
+    "perfetto_protos_perfetto_common_zero_gen_headers",
+    "perfetto_protos_perfetto_config_lite_gen_headers",
+    "perfetto_protos_perfetto_config_zero_gen_headers",
+    "perfetto_protos_perfetto_ipc_ipc_gen_headers",
+    "perfetto_protos_perfetto_trace_android_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_power_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_zero_gen_headers",
+    "perfetto_src_ipc_wire_protocol_gen_headers",
+  ],
+  defaults: [
+    "perfetto_defaults",
+  ],
+  cflags: [
+    "-DGOOGLE_PROTOBUF_NO_RTTI",
+    "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+    "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
 }
 
-// GN: //src/tracing/test:api_test_support
-filegroup {
-  name: "perfetto_src_tracing_test_api_test_support",
-  srcs: [
-    "src/tracing/test/api_test_support.cc",
-  ],
-}
-
-// GN: //src/tracing:test_support
-filegroup {
-  name: "perfetto_src_tracing_test_support",
-  srcs: [
-    "src/tracing/core/trace_writer_for_testing.cc",
-  ],
-}
-
-// GN: //src/tracing:tracing
-filegroup {
-  name: "perfetto_src_tracing_tracing",
-  srcs: [
-    "src/tracing/core/id_allocator.cc",
-    "src/tracing/core/metatrace_writer.cc",
-    "src/tracing/core/null_trace_writer.cc",
-    "src/tracing/core/packet_stream_validator.cc",
-    "src/tracing/core/shared_memory_abi.cc",
-    "src/tracing/core/shared_memory_arbiter_impl.cc",
-    "src/tracing/core/sliced_protobuf_input_stream.cc",
-    "src/tracing/core/startup_trace_writer.cc",
-    "src/tracing/core/startup_trace_writer_registry.cc",
-    "src/tracing/core/trace_buffer.cc",
-    "src/tracing/core/trace_packet.cc",
-    "src/tracing/core/trace_writer_impl.cc",
-    "src/tracing/core/tracing_service_impl.cc",
-    "src/tracing/core/virtual_destructors.cc",
-  ],
-}
-
-// GN: //src/tracing:unittests
-filegroup {
-  name: "perfetto_src_tracing_unittests",
-  srcs: [
-    "src/tracing/core/id_allocator_unittest.cc",
-    "src/tracing/core/null_trace_writer_unittest.cc",
-    "src/tracing/core/packet_stream_validator_unittest.cc",
-    "src/tracing/core/patch_list_unittest.cc",
-    "src/tracing/core/shared_memory_abi_unittest.cc",
-    "src/tracing/core/shared_memory_arbiter_impl_unittest.cc",
-    "src/tracing/core/sliced_protobuf_input_stream_unittest.cc",
-    "src/tracing/core/startup_trace_writer_unittest.cc",
-    "src/tracing/core/trace_buffer_unittest.cc",
-    "src/tracing/core/trace_packet_unittest.cc",
-    "src/tracing/core/trace_writer_impl_unittest.cc",
-    "src/tracing/core/tracing_service_impl_unittest.cc",
-    "src/tracing/ipc/posix_shared_memory_unittest.cc",
-    "src/tracing/test/aligned_buffer_test.cc",
-    "src/tracing/test/fake_packet.cc",
-    "src/tracing/test/mock_consumer.cc",
-    "src/tracing/test/mock_producer.cc",
-    "src/tracing/test/test_shared_memory.cc",
-    "src/tracing/test/tracing_integration_test.cc",
-  ],
-}
-
-// GN: //test:end_to_end_integrationtests
-filegroup {
-  name: "perfetto_test_end_to_end_integrationtests",
-  srcs: [
-    "test/end_to_end_integrationtest.cc",
-  ],
-}
-
-// GN: //test:task_runner_thread
-filegroup {
-  name: "perfetto_test_task_runner_thread",
-  srcs: [
-    "test/task_runner_thread.cc",
-  ],
-}
-
-// GN: //test:task_runner_thread_delegates
-filegroup {
-  name: "perfetto_test_task_runner_thread_delegates",
-  srcs: [
-    "test/fake_producer.cc",
-    "test/task_runner_thread_delegates.cc",
-  ],
-}
-
-// GN: //test:test_helper
-filegroup {
-  name: "perfetto_test_test_helper",
-  srcs: [
-    "test/test_helper.cc",
-  ],
-}
-
-// GN: //tools/sanitizers_unittests:sanitizers_unittests
-filegroup {
-  name: "perfetto_tools_sanitizers_unittests_sanitizers_unittests",
-  srcs: [
-    "tools/sanitizers_unittests/sanitizers_unittest.cc",
-  ],
-}
-
-// GN: //tools/trace_to_text:common
-filegroup {
-  name: "perfetto_tools_trace_to_text_common",
-  srcs: [
-    "tools/trace_to_text/main.cc",
-    "tools/trace_to_text/symbolize_profile.cc",
-    "tools/trace_to_text/trace_to_json.cc",
-    "tools/trace_to_text/trace_to_profile.cc",
-    "tools/trace_to_text/trace_to_systrace.cc",
-  ],
-}
-
-// GN: //tools/trace_to_text:full
-filegroup {
-  name: "perfetto_tools_trace_to_text_full",
-  srcs: [
-    "tools/trace_to_text/proto_full_utils.cc",
-    "tools/trace_to_text/trace_to_text.cc",
-  ],
-}
-
-// GN: //tools/trace_to_text:local_symbolizer
-filegroup {
-  name: "perfetto_tools_trace_to_text_local_symbolizer",
-  srcs: [
-    "tools/trace_to_text/local_symbolizer.cc",
-  ],
-}
-
-// GN: //tools/trace_to_text:pprofbuilder
-filegroup {
-  name: "perfetto_tools_trace_to_text_pprofbuilder",
-  srcs: [
-    "tools/trace_to_text/pprof_builder.cc",
-  ],
-}
-
-// GN: //tools/trace_to_text:symbolizer
-filegroup {
-  name: "perfetto_tools_trace_to_text_symbolizer",
-  srcs: [
-    "tools/trace_to_text/symbolizer.cc",
-  ],
-}
-
-// GN: //tools/trace_to_text:utils
-filegroup {
-  name: "perfetto_tools_trace_to_text_utils",
-  srcs: [
-    "tools/trace_to_text/utils.cc",
-  ],
-}
-
-// GN: //protos/perfetto/trace:perfetto_trace_protos
+// GN target: //:perfetto_trace_protos
 cc_library_static {
   name: "perfetto_trace_protos",
   srcs: [
     ":perfetto_protos_perfetto_common_lite_gen",
-    ":perfetto_protos_perfetto_config_android_lite_gen",
-    ":perfetto_protos_perfetto_config_ftrace_lite_gen",
-    ":perfetto_protos_perfetto_config_gpu_lite_gen",
-    ":perfetto_protos_perfetto_config_inode_file_lite_gen",
     ":perfetto_protos_perfetto_config_lite_gen",
-    ":perfetto_protos_perfetto_config_power_lite_gen",
-    ":perfetto_protos_perfetto_config_process_stats_lite_gen",
-    ":perfetto_protos_perfetto_config_profiling_lite_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_lite_gen",
     ":perfetto_protos_perfetto_trace_android_lite_gen",
     ":perfetto_protos_perfetto_trace_chrome_lite_gen",
     ":perfetto_protos_perfetto_trace_filesystem_lite_gen",
     ":perfetto_protos_perfetto_trace_ftrace_lite_gen",
-    ":perfetto_protos_perfetto_trace_gpu_lite_gen",
     ":perfetto_protos_perfetto_trace_interned_data_lite_gen",
+    ":perfetto_protos_perfetto_trace_lite_gen",
     ":perfetto_protos_perfetto_trace_minimal_lite_gen",
-    ":perfetto_protos_perfetto_trace_non_minimal_lite_gen",
-    ":perfetto_protos_perfetto_trace_perfetto_lite_gen",
     ":perfetto_protos_perfetto_trace_power_lite_gen",
     ":perfetto_protos_perfetto_trace_profiling_lite_gen",
     ":perfetto_protos_perfetto_trace_ps_lite_gen",
@@ -5247,28 +2853,17 @@
   host_supported: true,
   export_include_dirs: [
     "include",
-    "include/perfetto/base/build_configs/android_tree",
   ],
   generated_headers: [
     "perfetto_protos_perfetto_common_lite_gen_headers",
-    "perfetto_protos_perfetto_config_android_lite_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
     "perfetto_protos_perfetto_config_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_lite_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
     "perfetto_protos_perfetto_trace_android_lite_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
     "perfetto_protos_perfetto_trace_filesystem_lite_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_gpu_lite_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_lite_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_non_minimal_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_perfetto_lite_gen_headers",
     "perfetto_protos_perfetto_trace_power_lite_gen_headers",
     "perfetto_protos_perfetto_trace_profiling_lite_gen_headers",
     "perfetto_protos_perfetto_trace_ps_lite_gen_headers",
@@ -5277,24 +2872,14 @@
   ],
   export_generated_headers: [
     "perfetto_protos_perfetto_common_lite_gen_headers",
-    "perfetto_protos_perfetto_config_android_lite_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
     "perfetto_protos_perfetto_config_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_lite_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
     "perfetto_protos_perfetto_trace_android_lite_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
     "perfetto_protos_perfetto_trace_filesystem_lite_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_gpu_lite_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_lite_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_non_minimal_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_perfetto_lite_gen_headers",
     "perfetto_protos_perfetto_trace_power_lite_gen_headers",
     "perfetto_protos_perfetto_trace_profiling_lite_gen_headers",
     "perfetto_protos_perfetto_trace_ps_lite_gen_headers",
@@ -5310,58 +2895,15 @@
   ],
 }
 
-// GN: //:perfetto_unittests
+// GN target: //:perfetto_unittests
 cc_test {
   name: "perfetto_unittests",
   srcs: [
-    ":perfetto_include_perfetto_base_base",
-    ":perfetto_include_perfetto_ext_base_base",
-    ":perfetto_include_perfetto_ext_ipc_ipc",
-    ":perfetto_include_perfetto_ext_traced_sys_stats_counters",
-    ":perfetto_include_perfetto_ext_traced_traced",
-    ":perfetto_include_perfetto_ext_tracing_core_core",
-    ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
-    ":perfetto_include_perfetto_profiling_normalize",
-    ":perfetto_include_perfetto_protozero_protozero",
-    ":perfetto_include_perfetto_trace_processor_basic_types",
-    ":perfetto_include_perfetto_trace_processor_storage",
-    ":perfetto_include_perfetto_trace_processor_trace_processor",
-    ":perfetto_include_perfetto_tracing_core_core",
-    ":perfetto_include_perfetto_tracing_tracing",
-    ":perfetto_protos_perfetto_common_cpp_gen",
     ":perfetto_protos_perfetto_common_lite_gen",
     ":perfetto_protos_perfetto_common_zero_gen",
-    ":perfetto_protos_perfetto_config_android_cpp_gen",
-    ":perfetto_protos_perfetto_config_android_lite_gen",
-    ":perfetto_protos_perfetto_config_android_zero_gen",
-    ":perfetto_protos_perfetto_config_cpp_gen",
-    ":perfetto_protos_perfetto_config_ftrace_cpp_gen",
-    ":perfetto_protos_perfetto_config_ftrace_lite_gen",
-    ":perfetto_protos_perfetto_config_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_config_gpu_cpp_gen",
-    ":perfetto_protos_perfetto_config_gpu_lite_gen",
-    ":perfetto_protos_perfetto_config_gpu_zero_gen",
-    ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
-    ":perfetto_protos_perfetto_config_inode_file_lite_gen",
-    ":perfetto_protos_perfetto_config_inode_file_zero_gen",
     ":perfetto_protos_perfetto_config_lite_gen",
-    ":perfetto_protos_perfetto_config_power_cpp_gen",
-    ":perfetto_protos_perfetto_config_power_lite_gen",
-    ":perfetto_protos_perfetto_config_power_zero_gen",
-    ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_process_stats_lite_gen",
-    ":perfetto_protos_perfetto_config_process_stats_zero_gen",
-    ":perfetto_protos_perfetto_config_profiling_cpp_gen",
-    ":perfetto_protos_perfetto_config_profiling_lite_gen",
-    ":perfetto_protos_perfetto_config_profiling_zero_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_lite_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_config_zero_gen",
     ":perfetto_protos_perfetto_ipc_ipc_gen",
-    ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
-    ":perfetto_protos_perfetto_metrics_android_zero_gen",
-    ":perfetto_protos_perfetto_metrics_zero_gen",
     ":perfetto_protos_perfetto_trace_android_lite_gen",
     ":perfetto_protos_perfetto_trace_android_zero_gen",
     ":perfetto_protos_perfetto_trace_chrome_lite_gen",
@@ -5370,19 +2912,12 @@
     ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
     ":perfetto_protos_perfetto_trace_ftrace_lite_gen",
     ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_trace_gpu_lite_gen",
-    ":perfetto_protos_perfetto_trace_gpu_zero_gen",
     ":perfetto_protos_perfetto_trace_interned_data_lite_gen",
     ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
+    ":perfetto_protos_perfetto_trace_lite_gen",
     ":perfetto_protos_perfetto_trace_minimal_lite_gen",
-    ":perfetto_protos_perfetto_trace_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_non_minimal_lite_gen",
-    ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_perfetto_lite_gen",
-    ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
     ":perfetto_protos_perfetto_trace_power_lite_gen",
     ":perfetto_protos_perfetto_trace_power_zero_gen",
-    ":perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen",
     ":perfetto_protos_perfetto_trace_profiling_lite_gen",
     ":perfetto_protos_perfetto_trace_profiling_zero_gen",
     ":perfetto_protos_perfetto_trace_ps_lite_gen",
@@ -5392,120 +2927,239 @@
     ":perfetto_protos_perfetto_trace_track_event_lite_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
     ":perfetto_protos_perfetto_trace_trusted_lite_gen",
-    ":perfetto_src_android_internal_headers",
-    ":perfetto_src_android_internal_lazy_library_loader",
-    ":perfetto_src_base_base",
-    ":perfetto_src_base_test_support",
-    ":perfetto_src_base_unittests",
-    ":perfetto_src_base_unix_socket",
-    ":perfetto_src_ipc_ipc",
+    ":perfetto_protos_perfetto_trace_zero_gen",
     ":perfetto_src_ipc_test_messages_gen",
-    ":perfetto_src_ipc_unittests",
-    ":perfetto_src_perfetto_cmd_perfetto_cmd",
+    ":perfetto_src_ipc_wire_protocol_gen",
     ":perfetto_src_perfetto_cmd_protos_gen",
-    ":perfetto_src_perfetto_cmd_trigger_producer",
-    ":perfetto_src_perfetto_cmd_unittests",
-    ":perfetto_src_profiling_memory_client",
-    ":perfetto_src_profiling_memory_daemon",
-    ":perfetto_src_profiling_memory_proc_utils",
-    ":perfetto_src_profiling_memory_ring_buffer",
-    ":perfetto_src_profiling_memory_ring_buffer_unittests",
-    ":perfetto_src_profiling_memory_scoped_spinlock",
-    ":perfetto_src_profiling_memory_unittests",
-    ":perfetto_src_profiling_memory_wire_protocol",
-    ":perfetto_src_protozero_protozero",
     ":perfetto_src_protozero_testing_messages_lite_gen",
     ":perfetto_src_protozero_testing_messages_zero_gen",
-    ":perfetto_src_protozero_unittests",
-    ":perfetto_src_trace_processor_common",
-    ":perfetto_src_trace_processor_db_lib",
-    ":perfetto_src_trace_processor_db_unittests",
-    ":perfetto_src_trace_processor_lib",
-    ":perfetto_src_trace_processor_metrics_lib",
-    ":perfetto_src_trace_processor_metrics_unittests",
-    ":perfetto_src_trace_processor_sqlite_sqlite",
-    ":perfetto_src_trace_processor_sqlite_unittests",
-    ":perfetto_src_trace_processor_storage",
-    ":perfetto_src_trace_processor_tables_tables",
-    ":perfetto_src_trace_processor_tables_unittests",
-    ":perfetto_src_trace_processor_unittests",
-    ":perfetto_src_traced_probes_android_log_android_log",
-    ":perfetto_src_traced_probes_android_log_unittests",
-    ":perfetto_src_traced_probes_data_source",
-    ":perfetto_src_traced_probes_filesystem_filesystem",
-    ":perfetto_src_traced_probes_filesystem_unittests",
-    ":perfetto_src_traced_probes_ftrace_format_parser",
-    ":perfetto_src_traced_probes_ftrace_ftrace",
     ":perfetto_src_traced_probes_ftrace_test_messages_lite_gen",
     ":perfetto_src_traced_probes_ftrace_test_messages_zero_gen",
-    ":perfetto_src_traced_probes_ftrace_test_support",
-    ":perfetto_src_traced_probes_ftrace_unittests",
-    ":perfetto_src_traced_probes_metatrace_metatrace",
-    ":perfetto_src_traced_probes_packages_list_packages_list",
-    ":perfetto_src_traced_probes_packages_list_unittests",
-    ":perfetto_src_traced_probes_power_power",
-    ":perfetto_src_traced_probes_probes_src",
-    ":perfetto_src_traced_probes_ps_ps",
-    ":perfetto_src_traced_probes_ps_unittests",
-    ":perfetto_src_traced_probes_sys_stats_sys_stats",
-    ":perfetto_src_traced_probes_sys_stats_unittests",
-    ":perfetto_src_traced_probes_unittests",
-    ":perfetto_src_traced_service_service",
-    ":perfetto_src_traced_service_unittests",
-    ":perfetto_src_tracing_common",
-    ":perfetto_src_tracing_ipc",
-    ":perfetto_src_tracing_test_support",
-    ":perfetto_src_tracing_tracing",
-    ":perfetto_src_tracing_unittests",
-    ":perfetto_tools_sanitizers_unittests_sanitizers_unittests",
+    "src/android_internal/lazy_library_loader.cc",
+    "src/base/android_task_runner.cc",
+    "src/base/circular_queue_unittest.cc",
+    "src/base/event.cc",
+    "src/base/file_utils.cc",
+    "src/base/metatrace.cc",
+    "src/base/no_destructor_unittest.cc",
+    "src/base/optional_unittest.cc",
+    "src/base/paged_memory.cc",
+    "src/base/paged_memory_unittest.cc",
+    "src/base/pipe.cc",
+    "src/base/scoped_file_unittest.cc",
+    "src/base/string_splitter.cc",
+    "src/base/string_splitter_unittest.cc",
+    "src/base/string_utils.cc",
+    "src/base/string_utils_unittest.cc",
+    "src/base/string_view.cc",
+    "src/base/string_view_unittest.cc",
+    "src/base/string_writer_unittest.cc",
+    "src/base/task_runner_unittest.cc",
+    "src/base/temp_file.cc",
+    "src/base/temp_file_unittest.cc",
+    "src/base/test/test_task_runner.cc",
+    "src/base/test/utils.cc",
+    "src/base/test/vm_test_utils.cc",
+    "src/base/thread_checker.cc",
+    "src/base/thread_checker_unittest.cc",
+    "src/base/thread_task_runner.cc",
+    "src/base/thread_task_runner_unittest.cc",
+    "src/base/time.cc",
+    "src/base/time_unittest.cc",
+    "src/base/unix_socket.cc",
+    "src/base/unix_socket_unittest.cc",
+    "src/base/unix_task_runner.cc",
+    "src/base/utils_unittest.cc",
+    "src/base/virtual_destructors.cc",
+    "src/base/watchdog_posix.cc",
+    "src/base/watchdog_unittest.cc",
+    "src/base/weak_ptr_unittest.cc",
+    "src/ipc/buffered_frame_deserializer.cc",
+    "src/ipc/buffered_frame_deserializer_unittest.cc",
+    "src/ipc/client_impl.cc",
+    "src/ipc/client_impl_unittest.cc",
+    "src/ipc/deferred.cc",
+    "src/ipc/deferred_unittest.cc",
+    "src/ipc/host_impl.cc",
+    "src/ipc/host_impl_unittest.cc",
+    "src/ipc/service_proxy.cc",
+    "src/ipc/test/ipc_integrationtest.cc",
+    "src/ipc/virtual_destructors.cc",
+    "src/perfetto_cmd/config.cc",
+    "src/perfetto_cmd/config_unittest.cc",
+    "src/perfetto_cmd/packet_writer.cc",
+    "src/perfetto_cmd/packet_writer_unittest.cc",
+    "src/perfetto_cmd/pbtxt_to_pb.cc",
+    "src/perfetto_cmd/pbtxt_to_pb_unittest.cc",
+    "src/perfetto_cmd/perfetto_cmd.cc",
+    "src/perfetto_cmd/rate_limiter.cc",
+    "src/perfetto_cmd/rate_limiter_unittest.cc",
+    "src/perfetto_cmd/trigger_producer.cc",
+    "src/profiling/memory/bookkeeping.cc",
+    "src/profiling/memory/bookkeeping_unittest.cc",
+    "src/profiling/memory/client.cc",
+    "src/profiling/memory/client_unittest.cc",
+    "src/profiling/memory/heapprofd_producer.cc",
+    "src/profiling/memory/heapprofd_producer_unittest.cc",
+    "src/profiling/memory/interner_unittest.cc",
+    "src/profiling/memory/proc_utils.cc",
+    "src/profiling/memory/proc_utils_unittest.cc",
+    "src/profiling/memory/sampler_unittest.cc",
+    "src/profiling/memory/scoped_spinlock.cc",
+    "src/profiling/memory/shared_ring_buffer.cc",
+    "src/profiling/memory/shared_ring_buffer_unittest.cc",
+    "src/profiling/memory/system_property.cc",
+    "src/profiling/memory/system_property_unittest.cc",
+    "src/profiling/memory/unwinding.cc",
+    "src/profiling/memory/unwinding_unittest.cc",
+    "src/profiling/memory/wire_protocol.cc",
+    "src/profiling/memory/wire_protocol_unittest.cc",
+    "src/protozero/message.cc",
+    "src/protozero/message_handle.cc",
+    "src/protozero/message_handle_unittest.cc",
+    "src/protozero/message_unittest.cc",
+    "src/protozero/proto_decoder.cc",
+    "src/protozero/proto_decoder_unittest.cc",
+    "src/protozero/proto_utils_unittest.cc",
+    "src/protozero/scattered_heap_buffer.cc",
+    "src/protozero/scattered_stream_null_delegate.cc",
+    "src/protozero/scattered_stream_writer.cc",
+    "src/protozero/scattered_stream_writer_unittest.cc",
+    "src/protozero/test/fake_scattered_buffer.cc",
+    "src/protozero/test/protozero_conformance_unittest.cc",
+    "src/traced/probes/android_log/android_log_data_source.cc",
+    "src/traced/probes/android_log/android_log_data_source_unittest.cc",
+    "src/traced/probes/filesystem/file_scanner.cc",
+    "src/traced/probes/filesystem/file_scanner_unittest.cc",
+    "src/traced/probes/filesystem/fs_mount.cc",
+    "src/traced/probes/filesystem/fs_mount_unittest.cc",
+    "src/traced/probes/filesystem/inode_file_data_source.cc",
+    "src/traced/probes/filesystem/inode_file_data_source_unittest.cc",
+    "src/traced/probes/filesystem/lru_inode_cache.cc",
+    "src/traced/probes/filesystem/lru_inode_cache_unittest.cc",
+    "src/traced/probes/filesystem/prefix_finder.cc",
+    "src/traced/probes/filesystem/prefix_finder_unittest.cc",
+    "src/traced/probes/filesystem/range_tree.cc",
+    "src/traced/probes/filesystem/range_tree_unittest.cc",
+    "src/traced/probes/ftrace/atrace_hal_wrapper.cc",
+    "src/traced/probes/ftrace/atrace_wrapper.cc",
+    "src/traced/probes/ftrace/cpu_reader.cc",
+    "src/traced/probes/ftrace/cpu_reader_unittest.cc",
+    "src/traced/probes/ftrace/cpu_stats_parser.cc",
+    "src/traced/probes/ftrace/cpu_stats_parser_unittest.cc",
+    "src/traced/probes/ftrace/event_info.cc",
+    "src/traced/probes/ftrace/event_info_constants.cc",
+    "src/traced/probes/ftrace/event_info_unittest.cc",
+    "src/traced/probes/ftrace/format_parser.cc",
+    "src/traced/probes/ftrace/format_parser_unittest.cc",
+    "src/traced/probes/ftrace/ftrace_config.cc",
+    "src/traced/probes/ftrace/ftrace_config_muxer.cc",
+    "src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc",
+    "src/traced/probes/ftrace/ftrace_config_unittest.cc",
+    "src/traced/probes/ftrace/ftrace_controller.cc",
+    "src/traced/probes/ftrace/ftrace_controller_unittest.cc",
+    "src/traced/probes/ftrace/ftrace_data_source.cc",
+    "src/traced/probes/ftrace/ftrace_metadata.cc",
+    "src/traced/probes/ftrace/ftrace_procfs.cc",
+    "src/traced/probes/ftrace/ftrace_procfs_unittest.cc",
+    "src/traced/probes/ftrace/ftrace_stats.cc",
+    "src/traced/probes/ftrace/page_pool.cc",
+    "src/traced/probes/ftrace/page_pool_unittest.cc",
+    "src/traced/probes/ftrace/proto_translation_table.cc",
+    "src/traced/probes/ftrace/proto_translation_table_unittest.cc",
+    "src/traced/probes/ftrace/test/cpu_reader_support.cc",
+    "src/traced/probes/packages_list/packages_list_data_source.cc",
+    "src/traced/probes/packages_list/packages_list_data_source_unittest.cc",
+    "src/traced/probes/power/android_power_data_source.cc",
+    "src/traced/probes/probes_data_source.cc",
+    "src/traced/probes/probes_producer.cc",
+    "src/traced/probes/ps/process_stats_data_source.cc",
+    "src/traced/probes/ps/process_stats_data_source_unittest.cc",
+    "src/traced/probes/sys_stats/sys_stats_data_source.cc",
+    "src/traced/probes/sys_stats/sys_stats_data_source_unittest.cc",
+    "src/traced/service/lazy_producer.cc",
+    "src/traced/service/lazy_producer_unittest.cc",
+    "src/traced/service/service.cc",
+    "src/tracing/core/android_log_config.cc",
+    "src/tracing/core/android_power_config.cc",
+    "src/tracing/core/chrome_config.cc",
+    "src/tracing/core/commit_data_request.cc",
+    "src/tracing/core/data_source_config.cc",
+    "src/tracing/core/data_source_descriptor.cc",
+    "src/tracing/core/ftrace_config.cc",
+    "src/tracing/core/heapprofd_config.cc",
+    "src/tracing/core/id_allocator.cc",
+    "src/tracing/core/id_allocator_unittest.cc",
+    "src/tracing/core/inode_file_config.cc",
+    "src/tracing/core/null_trace_writer.cc",
+    "src/tracing/core/null_trace_writer_unittest.cc",
+    "src/tracing/core/observable_events.cc",
+    "src/tracing/core/packages_list_config.cc",
+    "src/tracing/core/packet_stream_validator.cc",
+    "src/tracing/core/packet_stream_validator_unittest.cc",
+    "src/tracing/core/patch_list_unittest.cc",
+    "src/tracing/core/process_stats_config.cc",
+    "src/tracing/core/shared_memory_abi.cc",
+    "src/tracing/core/shared_memory_abi_unittest.cc",
+    "src/tracing/core/shared_memory_arbiter_impl.cc",
+    "src/tracing/core/shared_memory_arbiter_impl_unittest.cc",
+    "src/tracing/core/sliced_protobuf_input_stream.cc",
+    "src/tracing/core/sliced_protobuf_input_stream_unittest.cc",
+    "src/tracing/core/startup_trace_writer.cc",
+    "src/tracing/core/startup_trace_writer_registry.cc",
+    "src/tracing/core/startup_trace_writer_unittest.cc",
+    "src/tracing/core/sys_stats_config.cc",
+    "src/tracing/core/test_config.cc",
+    "src/tracing/core/trace_buffer.cc",
+    "src/tracing/core/trace_buffer_unittest.cc",
+    "src/tracing/core/trace_config.cc",
+    "src/tracing/core/trace_packet.cc",
+    "src/tracing/core/trace_packet_unittest.cc",
+    "src/tracing/core/trace_stats.cc",
+    "src/tracing/core/trace_writer_for_testing.cc",
+    "src/tracing/core/trace_writer_impl.cc",
+    "src/tracing/core/trace_writer_impl_unittest.cc",
+    "src/tracing/core/tracing_service_impl.cc",
+    "src/tracing/core/tracing_service_impl_unittest.cc",
+    "src/tracing/core/tracing_service_state.cc",
+    "src/tracing/core/virtual_destructors.cc",
+    "src/tracing/ipc/posix_shared_memory_unittest.cc",
+    "src/tracing/test/aligned_buffer_test.cc",
+    "src/tracing/test/fake_packet.cc",
+    "src/tracing/test/mock_consumer.cc",
+    "src/tracing/test/mock_producer.cc",
+    "src/tracing/test/test_shared_memory.cc",
+    "src/tracing/test/tracing_integration_test.cc",
+    "tools/ftrace_proto_gen/ftrace_descriptor_gen.cc",
+    "tools/ftrace_proto_gen/ftrace_proto_gen.cc",
+    "tools/ftrace_proto_gen/ftrace_proto_gen_unittest.cc",
+    "tools/ftrace_proto_gen/proto_gen_utils.cc",
+    "tools/sanitizers_unittests/sanitizers_unittest.cc",
   ],
   shared_libs: [
+    "libandroid",
     "libbase",
+    "libbinder",
     "liblog",
     "libprocinfo",
+    "libprotobuf-cpp-full",
     "libprotobuf-cpp-lite",
+    "libservices",
     "libunwindstack",
+    "libutils",
     "libz",
   ],
   static_libs: [
     "libgmock",
+    "libgtest_prod",
+    "perfetto_src_tracing_ipc",
   ],
   generated_headers: [
-    "gen_merged_sql_metrics",
-    "perfetto_protos_perfetto_common_cpp_gen_headers",
     "perfetto_protos_perfetto_common_lite_gen_headers",
     "perfetto_protos_perfetto_common_zero_gen_headers",
-    "perfetto_protos_perfetto_config_android_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_android_lite_gen_headers",
-    "perfetto_protos_perfetto_config_android_zero_gen_headers",
-    "perfetto_protos_perfetto_config_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
     "perfetto_protos_perfetto_config_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_power_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_zero_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_zero_gen_headers",
     "perfetto_protos_perfetto_ipc_ipc_gen_headers",
-    "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
-    "perfetto_protos_perfetto_metrics_android_zero_gen_headers",
-    "perfetto_protos_perfetto_metrics_zero_gen_headers",
     "perfetto_protos_perfetto_trace_android_lite_gen_headers",
     "perfetto_protos_perfetto_trace_android_zero_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_lite_gen_headers",
@@ -5514,19 +3168,12 @@
     "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_lite_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_gpu_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_lite_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_lite_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_non_minimal_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_perfetto_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
     "perfetto_protos_perfetto_trace_power_lite_gen_headers",
     "perfetto_protos_perfetto_trace_power_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen_headers",
     "perfetto_protos_perfetto_trace_profiling_lite_gen_headers",
     "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ps_lite_gen_headers",
@@ -5536,7 +3183,9 @@
     "perfetto_protos_perfetto_trace_track_event_lite_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
     "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_zero_gen_headers",
     "perfetto_src_ipc_test_messages_gen_headers",
+    "perfetto_src_ipc_wire_protocol_gen_headers",
     "perfetto_src_perfetto_cmd_protos_gen_headers",
     "perfetto_src_protozero_testing_messages_lite_gen_headers",
     "perfetto_src_protozero_testing_messages_zero_gen_headers",
@@ -5550,176 +3199,24 @@
     "-DGOOGLE_PROTOBUF_NO_RTTI",
     "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
     "-DHAVE_HIDDEN",
+    "-DPERFETTO_BUILD_WITH_ANDROID",
+    "-DUSE_MMAP",
+    "-DZLIB_CONST",
   ],
-  data: [
-    "src/traced/probes/filesystem/testdata/**/*",
-    "src/traced/probes/ftrace/test/data/**/*",
-  ],
-  target: {
-    android: {
-      shared_libs: [
-        "libandroidicu",
-        "liblog",
-        "libsqlite",
-        "libutils",
-      ],
-    },
-    host: {
-      static_libs: [
-        "libsqlite",
-      ],
+  product_variables: {
+    pdk: {
+      enabled: false,
     },
   },
 }
 
-// GN: //src/protozero/protoc_plugin:protozero_plugin
-cc_binary_host {
-  name: "protozero_plugin",
-  srcs: [
-    ":perfetto_include_perfetto_base_base",
-    ":perfetto_include_perfetto_ext_base_base",
-    ":perfetto_src_base_base",
-    "src/protozero/protoc_plugin/protozero_plugin.cc",
-  ],
-  static_libs: [
-    "libprotoc",
-  ],
-  defaults: [
-    "perfetto_defaults",
-  ],
-  cflags: [
-    "-DGOOGLE_PROTOBUF_NO_RTTI",
-    "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
-  ],
-}
-
-// GN: //src/trace_processor:trace_processor_shell
-cc_binary_host {
-  name: "trace_processor_shell",
-  srcs: [
-    ":perfetto_include_perfetto_base_base",
-    ":perfetto_include_perfetto_ext_base_base",
-    ":perfetto_include_perfetto_ext_traced_sys_stats_counters",
-    ":perfetto_include_perfetto_protozero_protozero",
-    ":perfetto_include_perfetto_trace_processor_basic_types",
-    ":perfetto_include_perfetto_trace_processor_storage",
-    ":perfetto_include_perfetto_trace_processor_trace_processor",
-    ":perfetto_protos_perfetto_common_zero_gen",
-    ":perfetto_protos_perfetto_config_android_zero_gen",
-    ":perfetto_protos_perfetto_config_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_config_gpu_zero_gen",
-    ":perfetto_protos_perfetto_config_inode_file_zero_gen",
-    ":perfetto_protos_perfetto_config_power_zero_gen",
-    ":perfetto_protos_perfetto_config_process_stats_zero_gen",
-    ":perfetto_protos_perfetto_config_profiling_zero_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
-    ":perfetto_protos_perfetto_config_zero_gen",
-    ":perfetto_protos_perfetto_metrics_android_zero_gen",
-    ":perfetto_protos_perfetto_metrics_zero_gen",
-    ":perfetto_protos_perfetto_trace_android_zero_gen",
-    ":perfetto_protos_perfetto_trace_chrome_zero_gen",
-    ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
-    ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_trace_gpu_zero_gen",
-    ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
-    ":perfetto_protos_perfetto_trace_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
-    ":perfetto_protos_perfetto_trace_power_zero_gen",
-    ":perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen",
-    ":perfetto_protos_perfetto_trace_profiling_zero_gen",
-    ":perfetto_protos_perfetto_trace_ps_zero_gen",
-    ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
-    ":perfetto_protos_perfetto_trace_track_event_zero_gen",
-    ":perfetto_src_base_base",
-    ":perfetto_src_protozero_protozero",
-    ":perfetto_src_trace_processor_common",
-    ":perfetto_src_trace_processor_db_lib",
-    ":perfetto_src_trace_processor_lib",
-    ":perfetto_src_trace_processor_metrics_lib",
-    ":perfetto_src_trace_processor_sqlite_sqlite",
-    ":perfetto_src_trace_processor_storage",
-    ":perfetto_src_trace_processor_tables_tables",
-    "src/trace_processor/proto_to_json.cc",
-    "src/trace_processor/trace_processor_shell.cc",
-  ],
-  static_libs: [
-    "libprotoc",
-    "libsqlite",
-    "libz",
-  ],
-  generated_headers: [
-    "gen_merged_sql_metrics",
-    "perfetto_protos_perfetto_common_zero_gen_headers",
-    "perfetto_protos_perfetto_config_android_zero_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
-    "perfetto_protos_perfetto_config_power_zero_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
-    "perfetto_protos_perfetto_config_zero_gen_headers",
-    "perfetto_protos_perfetto_metrics_android_zero_gen_headers",
-    "perfetto_protos_perfetto_metrics_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_android_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_power_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
-  ],
-  defaults: [
-    "perfetto_defaults",
-  ],
-  cflags: [
-    "-DGOOGLE_PROTOBUF_NO_RTTI",
-    "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
-    "-DHAVE_HIDDEN",
-  ],
-  static_executable: true,
-}
-
-// GN: //tools/trace_to_text:trace_to_text
+// GN target: //:trace_to_text
 cc_binary_host {
   name: "trace_to_text",
   srcs: [
-    ":perfetto_include_perfetto_base_base",
-    ":perfetto_include_perfetto_ext_base_base",
-    ":perfetto_include_perfetto_ext_traced_sys_stats_counters",
-    ":perfetto_include_perfetto_profiling_symbolizer",
-    ":perfetto_include_perfetto_protozero_protozero",
-    ":perfetto_include_perfetto_trace_processor_basic_types",
-    ":perfetto_include_perfetto_trace_processor_storage",
-    ":perfetto_include_perfetto_trace_processor_trace_processor",
     ":perfetto_protos_perfetto_common_lite_gen",
     ":perfetto_protos_perfetto_common_zero_gen",
-    ":perfetto_protos_perfetto_config_android_lite_gen",
-    ":perfetto_protos_perfetto_config_android_zero_gen",
-    ":perfetto_protos_perfetto_config_ftrace_lite_gen",
-    ":perfetto_protos_perfetto_config_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_config_gpu_lite_gen",
-    ":perfetto_protos_perfetto_config_gpu_zero_gen",
-    ":perfetto_protos_perfetto_config_inode_file_lite_gen",
-    ":perfetto_protos_perfetto_config_inode_file_zero_gen",
     ":perfetto_protos_perfetto_config_lite_gen",
-    ":perfetto_protos_perfetto_config_power_lite_gen",
-    ":perfetto_protos_perfetto_config_power_zero_gen",
-    ":perfetto_protos_perfetto_config_process_stats_lite_gen",
-    ":perfetto_protos_perfetto_config_process_stats_zero_gen",
-    ":perfetto_protos_perfetto_config_profiling_lite_gen",
-    ":perfetto_protos_perfetto_config_profiling_zero_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_lite_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_config_zero_gen",
     ":perfetto_protos_perfetto_metrics_android_zero_gen",
     ":perfetto_protos_perfetto_metrics_zero_gen",
@@ -5731,19 +3228,12 @@
     ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
     ":perfetto_protos_perfetto_trace_ftrace_lite_gen",
     ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_trace_gpu_lite_gen",
-    ":perfetto_protos_perfetto_trace_gpu_zero_gen",
     ":perfetto_protos_perfetto_trace_interned_data_lite_gen",
     ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
+    ":perfetto_protos_perfetto_trace_lite_gen",
     ":perfetto_protos_perfetto_trace_minimal_lite_gen",
-    ":perfetto_protos_perfetto_trace_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_non_minimal_lite_gen",
-    ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_perfetto_lite_gen",
-    ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
     ":perfetto_protos_perfetto_trace_power_lite_gen",
     ":perfetto_protos_perfetto_trace_power_zero_gen",
-    ":perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen",
     ":perfetto_protos_perfetto_trace_profiling_lite_gen",
     ":perfetto_protos_perfetto_trace_profiling_zero_gen",
     ":perfetto_protos_perfetto_trace_ps_lite_gen",
@@ -5752,52 +3242,96 @@
     ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_trace_track_event_lite_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
+    ":perfetto_protos_perfetto_trace_zero_gen",
     ":perfetto_protos_third_party_pprof_lite_gen",
-    ":perfetto_src_base_base",
-    ":perfetto_src_protozero_protozero",
-    ":perfetto_src_trace_processor_common",
-    ":perfetto_src_trace_processor_db_lib",
-    ":perfetto_src_trace_processor_lib",
-    ":perfetto_src_trace_processor_metrics_lib",
-    ":perfetto_src_trace_processor_sqlite_sqlite",
-    ":perfetto_src_trace_processor_storage",
-    ":perfetto_src_trace_processor_tables_tables",
-    ":perfetto_tools_trace_to_text_common",
-    ":perfetto_tools_trace_to_text_full",
-    ":perfetto_tools_trace_to_text_local_symbolizer",
-    ":perfetto_tools_trace_to_text_pprofbuilder",
-    ":perfetto_tools_trace_to_text_symbolizer",
-    ":perfetto_tools_trace_to_text_utils",
+    "src/base/event.cc",
+    "src/base/file_utils.cc",
+    "src/base/metatrace.cc",
+    "src/base/paged_memory.cc",
+    "src/base/pipe.cc",
+    "src/base/string_splitter.cc",
+    "src/base/string_utils.cc",
+    "src/base/string_view.cc",
+    "src/base/temp_file.cc",
+    "src/base/thread_checker.cc",
+    "src/base/thread_task_runner.cc",
+    "src/base/time.cc",
+    "src/base/unix_task_runner.cc",
+    "src/base/virtual_destructors.cc",
+    "src/base/watchdog_posix.cc",
+    "src/protozero/message.cc",
+    "src/protozero/message_handle.cc",
+    "src/protozero/proto_decoder.cc",
+    "src/protozero/scattered_heap_buffer.cc",
+    "src/protozero/scattered_stream_null_delegate.cc",
+    "src/protozero/scattered_stream_writer.cc",
+    "src/trace_processor/android_logs_table.cc",
+    "src/trace_processor/args_table.cc",
+    "src/trace_processor/args_tracker.cc",
+    "src/trace_processor/clock_tracker.cc",
+    "src/trace_processor/counter_definitions_table.cc",
+    "src/trace_processor/counter_values_table.cc",
+    "src/trace_processor/event_tracker.cc",
+    "src/trace_processor/filtered_row_index.cc",
+    "src/trace_processor/ftrace_descriptors.cc",
+    "src/trace_processor/ftrace_utils.cc",
+    "src/trace_processor/fuchsia_provider_view.cc",
+    "src/trace_processor/fuchsia_trace_parser.cc",
+    "src/trace_processor/fuchsia_trace_tokenizer.cc",
+    "src/trace_processor/fuchsia_trace_utils.cc",
+    "src/trace_processor/heap_profile_tracker.cc",
+    "src/trace_processor/instants_table.cc",
+    "src/trace_processor/metrics/metrics.cc",
+    "src/trace_processor/process_table.cc",
+    "src/trace_processor/process_tracker.cc",
+    "src/trace_processor/proto_trace_parser.cc",
+    "src/trace_processor/proto_trace_tokenizer.cc",
+    "src/trace_processor/query_constraints.cc",
+    "src/trace_processor/raw_table.cc",
+    "src/trace_processor/row_iterators.cc",
+    "src/trace_processor/sched_slice_table.cc",
+    "src/trace_processor/slice_table.cc",
+    "src/trace_processor/slice_tracker.cc",
+    "src/trace_processor/span_join_operator_table.cc",
+    "src/trace_processor/sql_stats_table.cc",
+    "src/trace_processor/sqlite3_str_split.cc",
+    "src/trace_processor/stats_table.cc",
+    "src/trace_processor/storage_columns.cc",
+    "src/trace_processor/storage_schema.cc",
+    "src/trace_processor/storage_table.cc",
+    "src/trace_processor/string_pool.cc",
+    "src/trace_processor/string_table.cc",
+    "src/trace_processor/syscall_tracker.cc",
+    "src/trace_processor/table.cc",
+    "src/trace_processor/thread_table.cc",
+    "src/trace_processor/trace_processor.cc",
+    "src/trace_processor/trace_processor_context.cc",
+    "src/trace_processor/trace_processor_impl.cc",
+    "src/trace_processor/trace_sorter.cc",
+    "src/trace_processor/trace_storage.cc",
+    "src/trace_processor/virtual_destructors.cc",
+    "src/trace_processor/window_operator_table.cc",
+    "tools/trace_to_text/main.cc",
+    "tools/trace_to_text/proto_full_utils.cc",
+    "tools/trace_to_text/trace_to_profile.cc",
+    "tools/trace_to_text/trace_to_systrace.cc",
+    "tools/trace_to_text/trace_to_text.cc",
+    "tools/trace_to_text/utils.cc",
   ],
   shared_libs: [
+    "liblog",
     "libprotobuf-cpp-full",
     "libprotobuf-cpp-lite",
   ],
   static_libs: [
+    "libgtest_prod",
     "libsqlite",
-    "libz",
   ],
   generated_headers: [
     "gen_merged_sql_metrics",
     "perfetto_protos_perfetto_common_lite_gen_headers",
     "perfetto_protos_perfetto_common_zero_gen_headers",
-    "perfetto_protos_perfetto_config_android_lite_gen_headers",
-    "perfetto_protos_perfetto_config_android_zero_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
     "perfetto_protos_perfetto_config_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_zero_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_zero_gen_headers",
     "perfetto_protos_perfetto_metrics_android_zero_gen_headers",
     "perfetto_protos_perfetto_metrics_zero_gen_headers",
@@ -5809,19 +3343,12 @@
     "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_lite_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_gpu_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_lite_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_lite_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_non_minimal_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_perfetto_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
     "perfetto_protos_perfetto_trace_power_lite_gen_headers",
     "perfetto_protos_perfetto_trace_power_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_processor_metrics_impl_zero_gen_headers",
     "perfetto_protos_perfetto_trace_profiling_lite_gen_headers",
     "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ps_lite_gen_headers",
@@ -5830,6 +3357,7 @@
     "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_lite_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
+    "perfetto_protos_perfetto_trace_zero_gen_headers",
     "perfetto_protos_third_party_pprof_lite_gen_headers",
   ],
   defaults: [
@@ -5838,15 +3366,14 @@
   cflags: [
     "-DGOOGLE_PROTOBUF_NO_RTTI",
     "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
-    "-DHAVE_HIDDEN",
+    "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
 }
 
-// GN: //src/traced/service:traced
+// GN target: //:traced
 cc_binary {
   name: "traced",
   srcs: [
-    ":perfetto_include_perfetto_ext_traced_traced",
     "src/traced/service/main.cc",
   ],
   shared_libs: [
@@ -5859,13 +3386,15 @@
   defaults: [
     "perfetto_defaults",
   ],
+  cflags: [
+    "-DPERFETTO_BUILD_WITH_ANDROID",
+  ],
 }
 
-// GN: //src/traced/probes:traced_probes
+// GN target: //:traced_probes
 cc_binary {
   name: "traced_probes",
   srcs: [
-    ":perfetto_include_perfetto_ext_traced_traced",
     "src/traced/probes/main.cc",
   ],
   shared_libs: [
@@ -5875,138 +3404,129 @@
   defaults: [
     "perfetto_defaults",
   ],
+  cflags: [
+    "-DPERFETTO_BUILD_WITH_ANDROID",
+  ],
   required: [
     "libperfetto_android_internal",
     "trigger_perfetto",
   ],
 }
 
-// GN: //src/perfetto_cmd:trigger_perfetto
+// GN target: //:trigger_perfetto
 cc_binary {
   name: "trigger_perfetto",
   srcs: [
-    ":perfetto_include_perfetto_base_base",
-    ":perfetto_include_perfetto_ext_base_base",
-    ":perfetto_include_perfetto_ext_ipc_ipc",
-    ":perfetto_include_perfetto_ext_traced_traced",
-    ":perfetto_include_perfetto_ext_tracing_core_core",
-    ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
-    ":perfetto_include_perfetto_protozero_protozero",
-    ":perfetto_include_perfetto_tracing_core_core",
-    ":perfetto_include_perfetto_tracing_tracing",
-    ":perfetto_protos_perfetto_common_cpp_gen",
     ":perfetto_protos_perfetto_common_lite_gen",
     ":perfetto_protos_perfetto_common_zero_gen",
-    ":perfetto_protos_perfetto_config_android_cpp_gen",
-    ":perfetto_protos_perfetto_config_android_lite_gen",
-    ":perfetto_protos_perfetto_config_android_zero_gen",
-    ":perfetto_protos_perfetto_config_cpp_gen",
-    ":perfetto_protos_perfetto_config_ftrace_cpp_gen",
-    ":perfetto_protos_perfetto_config_ftrace_lite_gen",
-    ":perfetto_protos_perfetto_config_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_config_gpu_cpp_gen",
-    ":perfetto_protos_perfetto_config_gpu_lite_gen",
-    ":perfetto_protos_perfetto_config_gpu_zero_gen",
-    ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
-    ":perfetto_protos_perfetto_config_inode_file_lite_gen",
-    ":perfetto_protos_perfetto_config_inode_file_zero_gen",
     ":perfetto_protos_perfetto_config_lite_gen",
-    ":perfetto_protos_perfetto_config_power_cpp_gen",
-    ":perfetto_protos_perfetto_config_power_lite_gen",
-    ":perfetto_protos_perfetto_config_power_zero_gen",
-    ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_process_stats_lite_gen",
-    ":perfetto_protos_perfetto_config_process_stats_zero_gen",
-    ":perfetto_protos_perfetto_config_profiling_cpp_gen",
-    ":perfetto_protos_perfetto_config_profiling_lite_gen",
-    ":perfetto_protos_perfetto_config_profiling_zero_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_cpp_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_lite_gen",
-    ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_config_zero_gen",
     ":perfetto_protos_perfetto_ipc_ipc_gen",
-    ":perfetto_protos_perfetto_ipc_wire_protocol_gen",
     ":perfetto_protos_perfetto_trace_android_zero_gen",
     ":perfetto_protos_perfetto_trace_chrome_zero_gen",
     ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
     ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
-    ":perfetto_protos_perfetto_trace_gpu_zero_gen",
     ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
     ":perfetto_protos_perfetto_trace_minimal_lite_gen",
-    ":perfetto_protos_perfetto_trace_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
-    ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
     ":perfetto_protos_perfetto_trace_power_zero_gen",
     ":perfetto_protos_perfetto_trace_profiling_zero_gen",
     ":perfetto_protos_perfetto_trace_ps_zero_gen",
     ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
     ":perfetto_protos_perfetto_trace_track_event_zero_gen",
     ":perfetto_protos_perfetto_trace_trusted_lite_gen",
-    ":perfetto_src_base_base",
-    ":perfetto_src_base_unix_socket",
-    ":perfetto_src_ipc_ipc",
+    ":perfetto_protos_perfetto_trace_zero_gen",
+    ":perfetto_src_ipc_wire_protocol_gen",
     ":perfetto_src_perfetto_cmd_protos_gen",
-    ":perfetto_src_perfetto_cmd_trigger_perfetto_cmd",
-    ":perfetto_src_perfetto_cmd_trigger_producer",
-    ":perfetto_src_protozero_protozero",
-    ":perfetto_src_tracing_common",
-    ":perfetto_src_tracing_ipc",
-    ":perfetto_src_tracing_tracing",
+    "src/base/event.cc",
+    "src/base/file_utils.cc",
+    "src/base/metatrace.cc",
+    "src/base/paged_memory.cc",
+    "src/base/pipe.cc",
+    "src/base/string_splitter.cc",
+    "src/base/string_utils.cc",
+    "src/base/string_view.cc",
+    "src/base/temp_file.cc",
+    "src/base/thread_checker.cc",
+    "src/base/thread_task_runner.cc",
+    "src/base/time.cc",
+    "src/base/unix_socket.cc",
+    "src/base/unix_task_runner.cc",
+    "src/base/virtual_destructors.cc",
+    "src/base/watchdog_posix.cc",
+    "src/ipc/buffered_frame_deserializer.cc",
+    "src/ipc/client_impl.cc",
+    "src/ipc/deferred.cc",
+    "src/ipc/host_impl.cc",
+    "src/ipc/service_proxy.cc",
+    "src/ipc/virtual_destructors.cc",
+    "src/perfetto_cmd/trigger_perfetto.cc",
     "src/perfetto_cmd/trigger_perfetto_main.cc",
+    "src/perfetto_cmd/trigger_producer.cc",
+    "src/protozero/message.cc",
+    "src/protozero/message_handle.cc",
+    "src/protozero/proto_decoder.cc",
+    "src/protozero/scattered_heap_buffer.cc",
+    "src/protozero/scattered_stream_null_delegate.cc",
+    "src/protozero/scattered_stream_writer.cc",
+    "src/tracing/core/android_log_config.cc",
+    "src/tracing/core/android_power_config.cc",
+    "src/tracing/core/chrome_config.cc",
+    "src/tracing/core/commit_data_request.cc",
+    "src/tracing/core/data_source_config.cc",
+    "src/tracing/core/data_source_descriptor.cc",
+    "src/tracing/core/ftrace_config.cc",
+    "src/tracing/core/heapprofd_config.cc",
+    "src/tracing/core/id_allocator.cc",
+    "src/tracing/core/inode_file_config.cc",
+    "src/tracing/core/null_trace_writer.cc",
+    "src/tracing/core/observable_events.cc",
+    "src/tracing/core/packages_list_config.cc",
+    "src/tracing/core/packet_stream_validator.cc",
+    "src/tracing/core/process_stats_config.cc",
+    "src/tracing/core/shared_memory_abi.cc",
+    "src/tracing/core/shared_memory_arbiter_impl.cc",
+    "src/tracing/core/sliced_protobuf_input_stream.cc",
+    "src/tracing/core/startup_trace_writer.cc",
+    "src/tracing/core/startup_trace_writer_registry.cc",
+    "src/tracing/core/sys_stats_config.cc",
+    "src/tracing/core/test_config.cc",
+    "src/tracing/core/trace_buffer.cc",
+    "src/tracing/core/trace_config.cc",
+    "src/tracing/core/trace_packet.cc",
+    "src/tracing/core/trace_stats.cc",
+    "src/tracing/core/trace_writer_impl.cc",
+    "src/tracing/core/tracing_service_impl.cc",
+    "src/tracing/core/tracing_service_state.cc",
+    "src/tracing/core/virtual_destructors.cc",
   ],
   shared_libs: [
     "liblog",
     "libprotobuf-cpp-lite",
   ],
+  static_libs: [
+    "libgtest_prod",
+    "perfetto_src_tracing_ipc",
+  ],
   generated_headers: [
-    "perfetto_protos_perfetto_common_cpp_gen_headers",
     "perfetto_protos_perfetto_common_lite_gen_headers",
     "perfetto_protos_perfetto_common_zero_gen_headers",
-    "perfetto_protos_perfetto_config_android_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_android_lite_gen_headers",
-    "perfetto_protos_perfetto_config_android_zero_gen_headers",
-    "perfetto_protos_perfetto_config_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_lite_gen_headers",
-    "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_lite_gen_headers",
-    "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_lite_gen_headers",
-    "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
     "perfetto_protos_perfetto_config_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_power_lite_gen_headers",
-    "perfetto_protos_perfetto_config_power_zero_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_lite_gen_headers",
-    "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_lite_gen_headers",
-    "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_config_zero_gen_headers",
     "perfetto_protos_perfetto_ipc_ipc_gen_headers",
-    "perfetto_protos_perfetto_ipc_wire_protocol_gen_headers",
     "perfetto_protos_perfetto_trace_android_zero_gen_headers",
     "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
     "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
     "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
     "perfetto_protos_perfetto_trace_minimal_lite_gen_headers",
-    "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
-    "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
     "perfetto_protos_perfetto_trace_power_zero_gen_headers",
     "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
     "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
     "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
     "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
     "perfetto_protos_perfetto_trace_trusted_lite_gen_headers",
+    "perfetto_protos_perfetto_trace_zero_gen_headers",
+    "perfetto_src_ipc_wire_protocol_gen_headers",
     "perfetto_src_perfetto_cmd_protos_gen_headers",
   ],
   defaults: [
@@ -6015,14 +3535,15 @@
   cflags: [
     "-DGOOGLE_PROTOBUF_NO_RTTI",
     "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+    "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
 }
 
 // These targets are appended to the autogenerated Android.bp by tools/gen_android_bp.
-
 cc_library_static {
   name: "perfetto_cts_deps",
   srcs: [
+    "src/base/android_task_runner.cc",
     "src/base/test/test_task_runner.cc",
     "src/traced/probes/ftrace/cpu_reader.cc",
     "src/traced/probes/ftrace/event_info.cc",
@@ -6034,39 +3555,44 @@
     "test/end_to_end_integrationtest.cc",
     "test/fake_producer.cc",
     "test/task_runner_thread.cc",
-    "test/task_runner_thread_delegates.cc",
     "test/test_helper.cc",
   ],
+  export_include_dirs: [
+    ".",
+  ],
   shared_libs: [
     "libprotobuf-cpp-lite",
   ],
   static_libs: [
     "libgmock",
     "libgtest",
-    "libperfetto_client_experimental",
+    "perfetto_src_tracing_ipc",
     "perfetto_trace_protos",
   ],
-  defaults: [
-    "perfetto_defaults",
+  cflags: [
+    "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
 }
 
 cc_library_static {
   name: "perfetto_cts_jni_deps",
   srcs: [
+    "src/base/android_task_runner.cc",
     "src/base/test/test_task_runner.cc",
     "test/fake_producer.cc",
-    "test/task_runner_thread_delegates.cc",
   ],
   shared_libs: [
     "libprotobuf-cpp-lite",
   ],
+  export_include_dirs: [
+    ".",
+  ],
   static_libs: [
     "libgtest",
-    "libperfetto_client_experimental",
+    "perfetto_src_tracing_ipc",
   ],
-  defaults: [
-    "perfetto_defaults",
+  cflags: [
+    "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
 }
 
@@ -6078,28 +3604,4 @@
   srcs: [
     "protos/perfetto/config/perfetto_config.proto",
   ],
-}
-
-// This sample target shows how to use the perfetto client API from within the
-// Android tree.
-cc_binary {
-  name: "libperfetto_client_example",
-  srcs: [
-    "test/client_api_example.cc",
-  ],
-  static_libs: [
-    "libperfetto_client_experimental",
-    "perfetto_trace_protos",
-  ],
-  shared_libs: [
-    "libprotobuf-cpp-lite",
-    "liblog",
-  ],
-  cflags: [
-    "-DGOOGLE_PROTOBUF_NO_RTTI",
-    "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
-  ],
-  defaults: [
-    "perfetto_defaults",
-  ],
 }
\ No newline at end of file
diff --git a/Android.bp.extras b/Android.bp.extras
index ef14e45..84c0f10 100644
--- a/Android.bp.extras
+++ b/Android.bp.extras
@@ -1,8 +1,8 @@
 // These targets are appended to the autogenerated Android.bp by tools/gen_android_bp.
-
 cc_library_static {
   name: "perfetto_cts_deps",
   srcs: [
+    "src/base/android_task_runner.cc",
     "src/base/test/test_task_runner.cc",
     "src/traced/probes/ftrace/cpu_reader.cc",
     "src/traced/probes/ftrace/event_info.cc",
@@ -14,39 +14,44 @@
     "test/end_to_end_integrationtest.cc",
     "test/fake_producer.cc",
     "test/task_runner_thread.cc",
-    "test/task_runner_thread_delegates.cc",
     "test/test_helper.cc",
   ],
+  export_include_dirs: [
+    ".",
+  ],
   shared_libs: [
     "libprotobuf-cpp-lite",
   ],
   static_libs: [
     "libgmock",
     "libgtest",
-    "libperfetto_client_experimental",
+    "perfetto_src_tracing_ipc",
     "perfetto_trace_protos",
   ],
-  defaults: [
-    "perfetto_defaults",
+  cflags: [
+    "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
 }
 
 cc_library_static {
   name: "perfetto_cts_jni_deps",
   srcs: [
+    "src/base/android_task_runner.cc",
     "src/base/test/test_task_runner.cc",
     "test/fake_producer.cc",
-    "test/task_runner_thread_delegates.cc",
   ],
   shared_libs: [
     "libprotobuf-cpp-lite",
   ],
+  export_include_dirs: [
+    ".",
+  ],
   static_libs: [
     "libgtest",
-    "libperfetto_client_experimental",
+    "perfetto_src_tracing_ipc",
   ],
-  defaults: [
-    "perfetto_defaults",
+  cflags: [
+    "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
 }
 
@@ -59,27 +64,3 @@
     "protos/perfetto/config/perfetto_config.proto",
   ],
 }
-
-// This sample target shows how to use the perfetto client API from within the
-// Android tree.
-cc_binary {
-  name: "libperfetto_client_example",
-  srcs: [
-    "test/client_api_example.cc",
-  ],
-  static_libs: [
-    "libperfetto_client_experimental",
-    "perfetto_trace_protos",
-  ],
-  shared_libs: [
-    "libprotobuf-cpp-lite",
-    "liblog",
-  ],
-  cflags: [
-    "-DGOOGLE_PROTOBUF_NO_RTTI",
-    "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
-  ],
-  defaults: [
-    "perfetto_defaults",
-  ],
-}
diff --git a/BUILD b/BUILD
index 8dd4ff4..0e0d03a 100644
--- a/BUILD
+++ b/BUILD
@@ -12,449 +12,35 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-# This file is automatically generated by tools/gen_bazel. Do not edit.
+# This file is automatically generated by tools/gen_build. Do not edit.
 
-load("@perfetto_cfg//:perfetto_cfg.bzl", "PERFETTO_CONFIG")
-load(
-    "@perfetto//bazel:rules.bzl",
-    "perfetto_cc_binary",
-    "perfetto_cc_ipc_library",
-    "perfetto_cc_library",
-    "perfetto_cc_proto_library",
-    "perfetto_cc_protocpp_library",
-    "perfetto_cc_protozero_library",
-    "perfetto_java_proto_library",
-    "perfetto_proto_library",
-    "perfetto_py_binary",
-    "perfetto_gensignature_internal_only",
-)
+package(default_visibility = ["//visibility:public"])
 
-package(default_visibility = ["//visibility:private"])
+licenses(["notice"])  # Apache 2.0
 
-licenses(["notice"])
+exports_files(["LICENSE"])
 
-exports_files(["NOTICE"])
-
-# ##############################################################################
-# Internal targets
-# ##############################################################################
-
-# GN target: //src/ipc/protoc_plugin:ipc_plugin
-perfetto_cc_binary(
-    name = "ipc_plugin",
+# GN target: //src/trace_processor/metrics:gen_merged_sql_metrics
+genrule(
+    name = "gen_merged_sql_metrics",
     srcs = [
-        "src/ipc/protoc_plugin/ipc_plugin.cc",
-        ":include_perfetto_base_base",
-        ":include_perfetto_ext_base_base",
-        ":src_base_base",
+        "src/trace_processor/metrics/android/android_mem.sql",
+        "src/trace_processor/metrics/android/android_mem_lmk.sql",
     ],
-    deps = [
-    ] + PERFETTO_CONFIG.deps.protoc_lib,
-)
-
-# GN target: //src/ipc:perfetto_ipc
-perfetto_cc_library(
-    name = "perfetto_ipc",
-    srcs = [
-        ":src_base_base",
-        ":src_base_unix_socket",
-        ":src_ipc_ipc",
+    outs = [
+        "src/trace_processor/metrics/sql_metrics.h",
     ],
-    hdrs = [
-        ":include_perfetto_base_base",
-        ":include_perfetto_ext_base_base",
-        ":include_perfetto_ext_ipc_ipc",
+    cmd = "$(location gen_merged_sql_metrics_py) --cpp_out=$@ $(SRCS)",
+    tools = [
+        "gen_merged_sql_metrics_py",
     ],
-    deps = [
-        ":protos_perfetto_ipc_wire_protocol",
-    ] + PERFETTO_CONFIG.deps.protobuf_lite,
-)
-
-# GN target: //src/protozero/protoc_plugin:cppgen_plugin
-perfetto_cc_binary(
-    name = "cppgen_plugin",
-    srcs = [
-        "src/protozero/protoc_plugin/cppgen_plugin.cc",
-        ":include_perfetto_base_base",
-        ":include_perfetto_ext_base_base",
-        ":src_base_base",
-    ],
-    deps = [
-    ] + PERFETTO_CONFIG.deps.protoc_lib,
-)
-
-# GN target: //src/protozero/protoc_plugin:protozero_plugin
-perfetto_cc_binary(
-    name = "protozero_plugin",
-    srcs = [
-        "src/protozero/protoc_plugin/protozero_plugin.cc",
-        ":include_perfetto_base_base",
-        ":include_perfetto_ext_base_base",
-        ":src_base_base",
-    ],
-    deps = [
-    ] + PERFETTO_CONFIG.deps.protoc_lib,
 )
 
 # GN target: //src/protozero:libprotozero
-perfetto_cc_library(
+cc_library(
     name = "libprotozero",
     srcs = [
-        ":src_protozero_protozero",
-    ],
-    hdrs = [
-        ":include_perfetto_base_base",
-        ":include_perfetto_ext_base_base",
-        ":include_perfetto_protozero_protozero",
-    ],
-)
-
-# GN target: //:libperfetto
-perfetto_cc_library(
-    name = "libperfetto",
-    srcs = [
-        ":src_android_internal_headers",
-        ":src_android_internal_lazy_library_loader",
-        ":src_base_base",
-        ":src_base_unix_socket",
-        ":src_ipc_ipc",
-        ":src_protozero_protozero",
-        ":src_traced_probes_android_log_android_log",
-        ":src_traced_probes_data_source",
-        ":src_traced_probes_filesystem_filesystem",
-        ":src_traced_probes_ftrace_format_parser",
-        ":src_traced_probes_ftrace_ftrace",
-        ":src_traced_probes_metatrace_metatrace",
-        ":src_traced_probes_packages_list_packages_list",
-        ":src_traced_probes_power_power",
-        ":src_traced_probes_probes",
-        ":src_traced_probes_probes_src",
-        ":src_traced_probes_ps_ps",
-        ":src_traced_probes_sys_stats_sys_stats",
-        ":src_traced_service_service",
-        ":src_tracing_common",
-        ":src_tracing_consumer_api_deprecated",
-        ":src_tracing_ipc",
-        ":src_tracing_tracing",
-    ],
-    hdrs = [
-        ":include_perfetto_base_base",
-        ":include_perfetto_ext_base_base",
-        ":include_perfetto_ext_ipc_ipc",
-        ":include_perfetto_ext_traced_sys_stats_counters",
-        ":include_perfetto_ext_traced_traced",
-        ":include_perfetto_ext_tracing_core_core",
-        ":include_perfetto_ext_tracing_ipc_ipc",
-        ":include_perfetto_protozero_protozero",
-        ":include_perfetto_public_public",
-        ":include_perfetto_tracing_core_core",
-        ":include_perfetto_tracing_tracing",
-    ],
-    deps = [
-        ":protos_perfetto_common_cpp",
-        ":protos_perfetto_common_lite",
-        ":protos_perfetto_common_zero",
-        ":protos_perfetto_config_android_cpp",
-        ":protos_perfetto_config_android_lite",
-        ":protos_perfetto_config_android_zero",
-        ":protos_perfetto_config_cpp",
-        ":protos_perfetto_config_ftrace_cpp",
-        ":protos_perfetto_config_ftrace_lite",
-        ":protos_perfetto_config_ftrace_zero",
-        ":protos_perfetto_config_gpu_cpp",
-        ":protos_perfetto_config_gpu_lite",
-        ":protos_perfetto_config_gpu_zero",
-        ":protos_perfetto_config_inode_file_cpp",
-        ":protos_perfetto_config_inode_file_lite",
-        ":protos_perfetto_config_inode_file_zero",
-        ":protos_perfetto_config_lite",
-        ":protos_perfetto_config_power_cpp",
-        ":protos_perfetto_config_power_lite",
-        ":protos_perfetto_config_power_zero",
-        ":protos_perfetto_config_process_stats_cpp",
-        ":protos_perfetto_config_process_stats_lite",
-        ":protos_perfetto_config_process_stats_zero",
-        ":protos_perfetto_config_profiling_cpp",
-        ":protos_perfetto_config_profiling_lite",
-        ":protos_perfetto_config_profiling_zero",
-        ":protos_perfetto_config_sys_stats_cpp",
-        ":protos_perfetto_config_sys_stats_lite",
-        ":protos_perfetto_config_sys_stats_zero",
-        ":protos_perfetto_config_zero",
-        ":protos_perfetto_ipc_ipc",
-        ":protos_perfetto_ipc_wire_protocol",
-        ":protos_perfetto_trace_android_zero",
-        ":protos_perfetto_trace_chrome_zero",
-        ":protos_perfetto_trace_filesystem_zero",
-        ":protos_perfetto_trace_ftrace_zero",
-        ":protos_perfetto_trace_gpu_zero",
-        ":protos_perfetto_trace_interned_data_zero",
-        ":protos_perfetto_trace_minimal_lite",
-        ":protos_perfetto_trace_minimal_zero",
-        ":protos_perfetto_trace_non_minimal_zero",
-        ":protos_perfetto_trace_perfetto_zero",
-        ":protos_perfetto_trace_power_zero",
-        ":protos_perfetto_trace_profiling_zero",
-        ":protos_perfetto_trace_ps_zero",
-        ":protos_perfetto_trace_sys_stats_zero",
-        ":protos_perfetto_trace_track_event_zero",
-        ":protos_perfetto_trace_trusted_lite",
-    ] + PERFETTO_CONFIG.deps.protobuf_lite,
-)
-
-# GN target: //include/perfetto/base:base
-filegroup(
-    name = "include_perfetto_base_base",
-    srcs = [
-        "include/perfetto/base/build_config.h",
-        "include/perfetto/base/compiler.h",
-        "include/perfetto/base/export.h",
-        "include/perfetto/base/logging.h",
-        "include/perfetto/base/task_runner.h",
-        "include/perfetto/base/time.h",
-    ],
-)
-
-# GN target: //include/perfetto/ext/base:base
-filegroup(
-    name = "include_perfetto_ext_base_base",
-    srcs = [
-        "include/perfetto/ext/base/circular_queue.h",
-        "include/perfetto/ext/base/container_annotations.h",
-        "include/perfetto/ext/base/event_fd.h",
-        "include/perfetto/ext/base/file_utils.h",
-        "include/perfetto/ext/base/hash.h",
-        "include/perfetto/ext/base/lookup_set.h",
-        "include/perfetto/ext/base/metatrace.h",
-        "include/perfetto/ext/base/metatrace_events.h",
-        "include/perfetto/ext/base/no_destructor.h",
-        "include/perfetto/ext/base/optional.h",
-        "include/perfetto/ext/base/paged_memory.h",
-        "include/perfetto/ext/base/pipe.h",
-        "include/perfetto/ext/base/proc_utils.h",
-        "include/perfetto/ext/base/scoped_file.h",
-        "include/perfetto/ext/base/small_set.h",
-        "include/perfetto/ext/base/string_splitter.h",
-        "include/perfetto/ext/base/string_utils.h",
-        "include/perfetto/ext/base/string_view.h",
-        "include/perfetto/ext/base/string_writer.h",
-        "include/perfetto/ext/base/temp_file.h",
-        "include/perfetto/ext/base/thread_annotations.h",
-        "include/perfetto/ext/base/thread_checker.h",
-        "include/perfetto/ext/base/thread_task_runner.h",
-        "include/perfetto/ext/base/thread_utils.h",
-        "include/perfetto/ext/base/unix_socket.h",
-        "include/perfetto/ext/base/unix_task_runner.h",
-        "include/perfetto/ext/base/utils.h",
-        "include/perfetto/ext/base/uuid.h",
-        "include/perfetto/ext/base/waitable_event.h",
-        "include/perfetto/ext/base/watchdog.h",
-        "include/perfetto/ext/base/watchdog_noop.h",
-        "include/perfetto/ext/base/watchdog_posix.h",
-        "include/perfetto/ext/base/weak_ptr.h",
-    ],
-)
-
-# GN target: //include/perfetto/ext/ipc:ipc
-filegroup(
-    name = "include_perfetto_ext_ipc_ipc",
-    srcs = [
-        "include/perfetto/ext/ipc/async_result.h",
-        "include/perfetto/ext/ipc/basic_types.h",
-        "include/perfetto/ext/ipc/client.h",
-        "include/perfetto/ext/ipc/client_info.h",
-        "include/perfetto/ext/ipc/codegen_helpers.h",
-        "include/perfetto/ext/ipc/deferred.h",
-        "include/perfetto/ext/ipc/host.h",
-        "include/perfetto/ext/ipc/service.h",
-        "include/perfetto/ext/ipc/service_descriptor.h",
-        "include/perfetto/ext/ipc/service_proxy.h",
-    ],
-)
-
-# GN target: //include/perfetto/ext/trace_processor:export_json
-filegroup(
-    name = "include_perfetto_ext_trace_processor_export_json",
-    srcs = [
-        "include/perfetto/ext/trace_processor/export_json.h",
-    ],
-)
-
-# GN target: //include/perfetto/ext/traced:sys_stats_counters
-filegroup(
-    name = "include_perfetto_ext_traced_sys_stats_counters",
-    srcs = [
-        "include/perfetto/ext/traced/sys_stats_counters.h",
-    ],
-)
-
-# GN target: //include/perfetto/ext/traced:traced
-filegroup(
-    name = "include_perfetto_ext_traced_traced",
-    srcs = [
-        "include/perfetto/ext/traced/data_source_types.h",
-        "include/perfetto/ext/traced/traced.h",
-    ],
-)
-
-# GN target: //include/perfetto/ext/tracing/core:core
-filegroup(
-    name = "include_perfetto_ext_tracing_core_core",
-    srcs = [
-        "include/perfetto/ext/tracing/core/basic_types.h",
-        "include/perfetto/ext/tracing/core/commit_data_request.h",
-        "include/perfetto/ext/tracing/core/consumer.h",
-        "include/perfetto/ext/tracing/core/observable_events.h",
-        "include/perfetto/ext/tracing/core/producer.h",
-        "include/perfetto/ext/tracing/core/shared_memory.h",
-        "include/perfetto/ext/tracing/core/shared_memory_abi.h",
-        "include/perfetto/ext/tracing/core/shared_memory_arbiter.h",
-        "include/perfetto/ext/tracing/core/slice.h",
-        "include/perfetto/ext/tracing/core/sliced_protobuf_input_stream.h",
-        "include/perfetto/ext/tracing/core/startup_trace_writer.h",
-        "include/perfetto/ext/tracing/core/startup_trace_writer_registry.h",
-        "include/perfetto/ext/tracing/core/trace_packet.h",
-        "include/perfetto/ext/tracing/core/trace_stats.h",
-        "include/perfetto/ext/tracing/core/trace_writer.h",
-        "include/perfetto/ext/tracing/core/tracing_service.h",
-    ],
-)
-
-# GN target: //include/perfetto/ext/tracing/ipc:ipc
-filegroup(
-    name = "include_perfetto_ext_tracing_ipc_ipc",
-    srcs = [
-        "include/perfetto/ext/tracing/ipc/consumer_ipc_client.h",
-        "include/perfetto/ext/tracing/ipc/default_socket.h",
-        "include/perfetto/ext/tracing/ipc/producer_ipc_client.h",
-        "include/perfetto/ext/tracing/ipc/service_ipc_host.h",
-    ],
-)
-
-# GN target: //include/perfetto/profiling:symbolizer
-filegroup(
-    name = "include_perfetto_profiling_symbolizer",
-    srcs = [
-        "include/perfetto/profiling/pprof_builder.h",
-        "include/perfetto/profiling/symbolizer.h",
-    ],
-)
-
-# GN target: //include/perfetto/protozero:protozero
-filegroup(
-    name = "include_perfetto_protozero_protozero",
-    srcs = [
-        "include/perfetto/protozero/contiguous_memory_range.h",
-        "include/perfetto/protozero/copyable_ptr.h",
-        "include/perfetto/protozero/field.h",
-        "include/perfetto/protozero/message.h",
-        "include/perfetto/protozero/message_handle.h",
-        "include/perfetto/protozero/packed_repeated_fields.h",
-        "include/perfetto/protozero/proto_decoder.h",
-        "include/perfetto/protozero/proto_utils.h",
-        "include/perfetto/protozero/scattered_heap_buffer.h",
-        "include/perfetto/protozero/scattered_stream_null_delegate.h",
-        "include/perfetto/protozero/scattered_stream_writer.h",
-    ],
-)
-
-# GN target: //include/perfetto/public:public
-filegroup(
-    name = "include_perfetto_public_public",
-    srcs = [
-        "include/perfetto/public/consumer_api.h",
-    ],
-)
-
-# GN target: //include/perfetto/trace_processor:basic_types
-filegroup(
-    name = "include_perfetto_trace_processor_basic_types",
-    srcs = [
-        "include/perfetto/trace_processor/basic_types.h",
-        "include/perfetto/trace_processor/status.h",
-    ],
-)
-
-# GN target: //include/perfetto/trace_processor:storage
-filegroup(
-    name = "include_perfetto_trace_processor_storage",
-    srcs = [
-        "include/perfetto/trace_processor/trace_processor_storage.h",
-    ],
-)
-
-# GN target: //include/perfetto/trace_processor:trace_processor
-filegroup(
-    name = "include_perfetto_trace_processor_trace_processor",
-    srcs = [
-        "include/perfetto/trace_processor/read_trace.h",
-        "include/perfetto/trace_processor/trace_processor.h",
-    ],
-)
-
-# GN target: //include/perfetto/tracing/core:core
-filegroup(
-    name = "include_perfetto_tracing_core_core",
-    srcs = [
-        "include/perfetto/tracing/core/chrome_config.h",
-        "include/perfetto/tracing/core/data_source_config.h",
-        "include/perfetto/tracing/core/data_source_descriptor.h",
-        "include/perfetto/tracing/core/trace_config.h",
-        "include/perfetto/tracing/core/tracing_service_state.h",
-    ],
-)
-
-# GN target: //include/perfetto/tracing:tracing
-filegroup(
-    name = "include_perfetto_tracing_tracing",
-    srcs = [
-        "include/perfetto/tracing/buffer_exhausted_policy.h",
-        "include/perfetto/tracing/data_source.h",
-        "include/perfetto/tracing/internal/basic_types.h",
-        "include/perfetto/tracing/internal/data_source_internal.h",
-        "include/perfetto/tracing/internal/tracing_muxer.h",
-        "include/perfetto/tracing/internal/tracing_tls.h",
-        "include/perfetto/tracing/internal/track_event_data_source.h",
-        "include/perfetto/tracing/internal/track_event_internal.h",
-        "include/perfetto/tracing/internal/track_event_macros.h",
-        "include/perfetto/tracing/locked_handle.h",
-        "include/perfetto/tracing/platform.h",
-        "include/perfetto/tracing/trace_writer_base.h",
-        "include/perfetto/tracing/tracing.h",
-        "include/perfetto/tracing/tracing_backend.h",
-        "include/perfetto/tracing/track_event.h",
-        "include/perfetto/tracing/track_event_category_registry.h",
-        "include/perfetto/tracing/track_event_context.h",
-        "include/perfetto/tracing/track_event_interned_data_index.h",
-    ],
-)
-
-# GN target: //src/android_internal:headers
-filegroup(
-    name = "src_android_internal_headers",
-    srcs = [
-        "src/android_internal/atrace_hal.h",
-        "src/android_internal/dropbox_service.h",
-        "src/android_internal/health_hal.h",
-        "src/android_internal/incident_service.h",
-        "src/android_internal/power_stats_hal.h",
-    ],
-)
-
-# GN target: //src/android_internal:lazy_library_loader
-filegroup(
-    name = "src_android_internal_lazy_library_loader",
-    srcs = [
-        "src/android_internal/lazy_library_loader.cc",
-        "src/android_internal/lazy_library_loader.h",
-    ],
-)
-
-# GN target: //src/base:base
-filegroup(
-    name = "src_base_base",
-    srcs = [
-        "src/base/event_fd.cc",
+        "src/base/event.cc",
         "src/base/file_utils.cc",
         "src/base/metatrace.cc",
         "src/base/paged_memory.cc",
@@ -467,250 +53,177 @@
         "src/base/thread_task_runner.cc",
         "src/base/time.cc",
         "src/base/unix_task_runner.cc",
-        "src/base/uuid.cc",
         "src/base/virtual_destructors.cc",
-        "src/base/waitable_event.cc",
         "src/base/watchdog_posix.cc",
-    ],
-)
-
-# GN target: //src/base:unix_socket
-filegroup(
-    name = "src_base_unix_socket",
-    srcs = [
-        "src/base/unix_socket.cc",
-    ],
-)
-
-# GN target: //src/ipc:ipc
-filegroup(
-    name = "src_ipc_ipc",
-    srcs = [
-        "src/ipc/buffered_frame_deserializer.cc",
-        "src/ipc/buffered_frame_deserializer.h",
-        "src/ipc/client_impl.cc",
-        "src/ipc/client_impl.h",
-        "src/ipc/deferred.cc",
-        "src/ipc/host_impl.cc",
-        "src/ipc/host_impl.h",
-        "src/ipc/service_proxy.cc",
-        "src/ipc/virtual_destructors.cc",
-    ],
-)
-
-# GN target: //src/perfetto_cmd:perfetto_cmd
-filegroup(
-    name = "src_perfetto_cmd_perfetto_cmd",
-    srcs = [
-        "src/perfetto_cmd/config.cc",
-        "src/perfetto_cmd/config.h",
-        "src/perfetto_cmd/packet_writer.cc",
-        "src/perfetto_cmd/packet_writer.h",
-        "src/perfetto_cmd/pbtxt_to_pb.cc",
-        "src/perfetto_cmd/pbtxt_to_pb.h",
-        "src/perfetto_cmd/perfetto_cmd.cc",
-        "src/perfetto_cmd/perfetto_cmd.h",
-        "src/perfetto_cmd/perfetto_config.descriptor.h",
-        "src/perfetto_cmd/rate_limiter.cc",
-        "src/perfetto_cmd/rate_limiter.h",
-    ],
-)
-
-# GN target: //src/perfetto_cmd:trigger_producer
-filegroup(
-    name = "src_perfetto_cmd_trigger_producer",
-    srcs = [
-        "src/perfetto_cmd/trigger_producer.cc",
-        "src/perfetto_cmd/trigger_producer.h",
-    ],
-)
-
-# GN target: //src/protozero:protozero
-filegroup(
-    name = "src_protozero_protozero",
-    srcs = [
         "src/protozero/message.cc",
         "src/protozero/message_handle.cc",
-        "src/protozero/packed_repeated_fields.cc",
         "src/protozero/proto_decoder.cc",
         "src/protozero/scattered_heap_buffer.cc",
         "src/protozero/scattered_stream_null_delegate.cc",
         "src/protozero/scattered_stream_writer.cc",
     ],
-)
-
-# GN target: //src/trace_processor/db:lib
-filegroup(
-    name = "src_trace_processor_db_lib",
-    srcs = [
-        "src/trace_processor/db/bit_vector.cc",
-        "src/trace_processor/db/bit_vector.h",
-        "src/trace_processor/db/bit_vector_iterators.cc",
-        "src/trace_processor/db/bit_vector_iterators.h",
-        "src/trace_processor/db/column.cc",
-        "src/trace_processor/db/column.h",
-        "src/trace_processor/db/row_map.cc",
-        "src/trace_processor/db/row_map.h",
-        "src/trace_processor/db/sparse_vector.h",
-        "src/trace_processor/db/table.cc",
-        "src/trace_processor/db/table.h",
-        "src/trace_processor/db/typed_column.h",
+    hdrs = [
+        "include/perfetto/base/build_config.h",
+        "include/perfetto/base/circular_queue.h",
+        "include/perfetto/base/container_annotations.h",
+        "include/perfetto/base/event.h",
+        "include/perfetto/base/export.h",
+        "include/perfetto/base/file_utils.h",
+        "include/perfetto/base/gtest_prod_util.h",
+        "include/perfetto/base/hash.h",
+        "include/perfetto/base/logging.h",
+        "include/perfetto/base/metatrace.h",
+        "include/perfetto/base/no_destructor.h",
+        "include/perfetto/base/optional.h",
+        "include/perfetto/base/paged_memory.h",
+        "include/perfetto/base/pipe.h",
+        "include/perfetto/base/scoped_file.h",
+        "include/perfetto/base/small_set.h",
+        "include/perfetto/base/string_splitter.h",
+        "include/perfetto/base/string_utils.h",
+        "include/perfetto/base/string_view.h",
+        "include/perfetto/base/string_writer.h",
+        "include/perfetto/base/task_runner.h",
+        "include/perfetto/base/temp_file.h",
+        "include/perfetto/base/thread_annotations.h",
+        "include/perfetto/base/thread_checker.h",
+        "include/perfetto/base/thread_task_runner.h",
+        "include/perfetto/base/thread_utils.h",
+        "include/perfetto/base/time.h",
+        "include/perfetto/base/unix_socket.h",
+        "include/perfetto/base/unix_task_runner.h",
+        "include/perfetto/base/utils.h",
+        "include/perfetto/base/watchdog.h",
+        "include/perfetto/base/watchdog_noop.h",
+        "include/perfetto/base/watchdog_posix.h",
+        "include/perfetto/base/weak_ptr.h",
+        "include/perfetto/protozero/contiguous_memory_range.h",
+        "include/perfetto/protozero/field.h",
+        "include/perfetto/protozero/message.h",
+        "include/perfetto/protozero/message_handle.h",
+        "include/perfetto/protozero/proto_decoder.h",
+        "include/perfetto/protozero/proto_utils.h",
+        "include/perfetto/protozero/scattered_heap_buffer.h",
+        "include/perfetto/protozero/scattered_stream_null_delegate.h",
+        "include/perfetto/protozero/scattered_stream_writer.h",
+    ],
+    deps = [
+        "//third_party/perfetto/google:gtest_prod",
     ],
 )
 
-genrule(
-    name = "src_trace_processor_metrics_gen_merged_sql_metrics",
+# GN target: //src/protozero/protoc_plugin:protoc_plugin
+cc_binary(
+    name = "src_protozero_protoc_plugin_protoc_plugin",
     srcs = [
-        "src/trace_processor/metrics/android/android_batt.sql",
-        "src/trace_processor/metrics/android/android_cpu.sql",
-        "src/trace_processor/metrics/android/android_cpu_agg.sql",
-        "src/trace_processor/metrics/android/android_ion.sql",
-        "src/trace_processor/metrics/android/android_lmk.sql",
-        "src/trace_processor/metrics/android/android_mem.sql",
-        "src/trace_processor/metrics/android/android_mem_unagg.sql",
-        "src/trace_processor/metrics/android/android_package_list.sql",
-        "src/trace_processor/metrics/android/android_powrails.sql",
-        "src/trace_processor/metrics/android/android_process_growth.sql",
-        "src/trace_processor/metrics/android/android_startup.sql",
-        "src/trace_processor/metrics/android/android_startup_cpu.sql",
-        "src/trace_processor/metrics/android/android_startup_launches.sql",
-        "src/trace_processor/metrics/android/android_task_state.sql",
-        "src/trace_processor/metrics/android/heap_profile_callsites.sql",
-        "src/trace_processor/metrics/android/java_heap_stats.sql",
-        "src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql",
-        "src/trace_processor/metrics/android/process_mem.sql",
-        "src/trace_processor/metrics/android/process_unagg_mem_view.sql",
-        "src/trace_processor/metrics/android/span_view_stats.sql",
-        "src/trace_processor/metrics/android/unsymbolized_frames.sql",
-        "src/trace_processor/metrics/android/upid_span_view.sql",
-        "src/trace_processor/metrics/trace_metadata.sql",
+        "src/protozero/protoc_plugin/protozero_generator.cc",
+        "src/protozero/protoc_plugin/protozero_generator.h",
+        "src/protozero/protoc_plugin/protozero_plugin.cc",
     ],
-    outs = [
-        "src/trace_processor/metrics/sql_metrics.h",
-    ],
-    cmd = "$(location gen_merged_sql_metrics_py) --cpp_out=$@ $(SRCS)",
-    tools = [
-        ":gen_merged_sql_metrics_py",
+    deps = [
+        "//third_party/protobuf",
+        "//third_party/protobuf:libprotoc",
     ],
 )
 
-# GN target: //src/trace_processor/metrics:lib
-filegroup(
-    name = "src_trace_processor_metrics_lib",
+# GN target: //src/trace_processor:trace_processor
+cc_library(
+    name = "trace_processor",
     srcs = [
-        "src/trace_processor/metrics/descriptors.cc",
-        "src/trace_processor/metrics/descriptors.h",
-        "src/trace_processor/metrics/metrics.cc",
-        "src/trace_processor/metrics/metrics.descriptor.h",
-        "src/trace_processor/metrics/metrics.h",
-    ],
-)
-
-# GN target: //src/trace_processor/rpc:httpd
-filegroup(
-    name = "src_trace_processor_rpc_httpd",
-    srcs = [
-        "src/trace_processor/rpc/httpd.cc",
-        "src/trace_processor/rpc/httpd.h",
-    ],
-)
-
-# GN target: //src/trace_processor/rpc:rpc
-filegroup(
-    name = "src_trace_processor_rpc_rpc",
-    srcs = [
-        "src/trace_processor/rpc/rpc.cc",
-        "src/trace_processor/rpc/rpc.h",
-    ],
-)
-
-# GN target: //src/trace_processor/sqlite:sqlite
-filegroup(
-    name = "src_trace_processor_sqlite_sqlite",
-    srcs = [
-        "src/trace_processor/sqlite/db_sqlite_table.cc",
-        "src/trace_processor/sqlite/db_sqlite_table.h",
-        "src/trace_processor/sqlite/query_constraints.cc",
-        "src/trace_processor/sqlite/query_constraints.h",
-        "src/trace_processor/sqlite/scoped_db.h",
-        "src/trace_processor/sqlite/sqlite3_str_split.cc",
-        "src/trace_processor/sqlite/sqlite3_str_split.h",
-        "src/trace_processor/sqlite/sqlite_table.cc",
-        "src/trace_processor/sqlite/sqlite_table.h",
-        "src/trace_processor/sqlite/sqlite_utils.h",
-    ],
-)
-
-# GN target: //src/trace_processor/tables:tables
-filegroup(
-    name = "src_trace_processor_tables_tables",
-    srcs = [
-        "src/trace_processor/tables/macros.h",
-        "src/trace_processor/tables/macros_internal.h",
-        "src/trace_processor/tables/profiler_tables.h",
-        "src/trace_processor/tables/slice_tables.h",
-        "src/trace_processor/tables/track_tables.h",
-    ],
-)
-
-# GN target: //src/trace_processor:common
-filegroup(
-    name = "src_trace_processor_common",
-    srcs = [
-        "src/trace_processor/null_term_string_view.h",
-        "src/trace_processor/string_pool.cc",
-        "src/trace_processor/string_pool.h",
-    ],
-)
-
-# GN target: //src/trace_processor:export_json
-filegroup(
-    name = "src_trace_processor_export_json",
-    srcs = [
-        "src/trace_processor/export_json.cc",
-        "src/trace_processor/export_json.h",
-    ],
-)
-
-# GN target: //src/trace_processor:lib
-filegroup(
-    name = "src_trace_processor_lib",
-    srcs = [
+        "src/base/event.cc",
+        "src/base/file_utils.cc",
+        "src/base/metatrace.cc",
+        "src/base/paged_memory.cc",
+        "src/base/pipe.cc",
+        "src/base/string_splitter.cc",
+        "src/base/string_utils.cc",
+        "src/base/string_view.cc",
+        "src/base/temp_file.cc",
+        "src/base/thread_checker.cc",
+        "src/base/thread_task_runner.cc",
+        "src/base/time.cc",
+        "src/base/unix_task_runner.cc",
+        "src/base/virtual_destructors.cc",
+        "src/base/watchdog_posix.cc",
+        "src/protozero/message.cc",
+        "src/protozero/message_handle.cc",
+        "src/protozero/proto_decoder.cc",
+        "src/protozero/scattered_heap_buffer.cc",
+        "src/protozero/scattered_stream_null_delegate.cc",
+        "src/protozero/scattered_stream_writer.cc",
         "src/trace_processor/android_logs_table.cc",
         "src/trace_processor/android_logs_table.h",
         "src/trace_processor/args_table.cc",
         "src/trace_processor/args_table.h",
+        "src/trace_processor/args_tracker.cc",
+        "src/trace_processor/args_tracker.h",
+        "src/trace_processor/chunked_trace_reader.h",
+        "src/trace_processor/clock_tracker.cc",
+        "src/trace_processor/clock_tracker.h",
+        "src/trace_processor/counter_definitions_table.cc",
+        "src/trace_processor/counter_definitions_table.h",
         "src/trace_processor/counter_values_table.cc",
         "src/trace_processor/counter_values_table.h",
-        "src/trace_processor/cpu_profile_stack_sample_table.cc",
-        "src/trace_processor/cpu_profile_stack_sample_table.h",
+        "src/trace_processor/event_tracker.cc",
+        "src/trace_processor/event_tracker.h",
         "src/trace_processor/filtered_row_index.cc",
         "src/trace_processor/filtered_row_index.h",
-        "src/trace_processor/heap_profile_allocation_table.cc",
-        "src/trace_processor/heap_profile_allocation_table.h",
+        "src/trace_processor/ftrace_descriptors.cc",
+        "src/trace_processor/ftrace_descriptors.h",
+        "src/trace_processor/ftrace_utils.cc",
+        "src/trace_processor/ftrace_utils.h",
+        "src/trace_processor/fuchsia_provider_view.cc",
+        "src/trace_processor/fuchsia_provider_view.h",
+        "src/trace_processor/fuchsia_trace_parser.cc",
+        "src/trace_processor/fuchsia_trace_parser.h",
+        "src/trace_processor/fuchsia_trace_tokenizer.cc",
+        "src/trace_processor/fuchsia_trace_tokenizer.h",
+        "src/trace_processor/fuchsia_trace_utils.cc",
+        "src/trace_processor/fuchsia_trace_utils.h",
+        "src/trace_processor/heap_profile_tracker.cc",
+        "src/trace_processor/heap_profile_tracker.h",
         "src/trace_processor/instants_table.cc",
         "src/trace_processor/instants_table.h",
-        "src/trace_processor/metadata_table.cc",
-        "src/trace_processor/metadata_table.h",
+        "src/trace_processor/json_trace_parser.cc",
+        "src/trace_processor/json_trace_parser.h",
+        "src/trace_processor/json_trace_tokenizer.cc",
+        "src/trace_processor/json_trace_tokenizer.h",
+        "src/trace_processor/json_trace_utils.cc",
+        "src/trace_processor/json_trace_utils.h",
+        "src/trace_processor/metrics/metrics.cc",
+        "src/trace_processor/metrics/metrics.h",
+        "src/trace_processor/metrics/sql_metrics.h",
+        "src/trace_processor/null_term_string_view.h",
         "src/trace_processor/process_table.cc",
         "src/trace_processor/process_table.h",
+        "src/trace_processor/process_tracker.cc",
+        "src/trace_processor/process_tracker.h",
+        "src/trace_processor/proto_incremental_state.h",
+        "src/trace_processor/proto_trace_parser.cc",
+        "src/trace_processor/proto_trace_parser.h",
+        "src/trace_processor/proto_trace_tokenizer.cc",
+        "src/trace_processor/proto_trace_tokenizer.h",
+        "src/trace_processor/query_constraints.cc",
+        "src/trace_processor/query_constraints.h",
         "src/trace_processor/raw_table.cc",
         "src/trace_processor/raw_table.h",
-        "src/trace_processor/read_trace.cc",
         "src/trace_processor/row_iterators.cc",
         "src/trace_processor/row_iterators.h",
         "src/trace_processor/sched_slice_table.cc",
         "src/trace_processor/sched_slice_table.h",
+        "src/trace_processor/scoped_db.h",
         "src/trace_processor/slice_table.cc",
         "src/trace_processor/slice_table.h",
+        "src/trace_processor/slice_tracker.cc",
+        "src/trace_processor/slice_tracker.h",
         "src/trace_processor/span_join_operator_table.cc",
         "src/trace_processor/span_join_operator_table.h",
         "src/trace_processor/sql_stats_table.cc",
         "src/trace_processor/sql_stats_table.h",
-        "src/trace_processor/stack_profile_frame_table.cc",
-        "src/trace_processor/stack_profile_frame_table.h",
-        "src/trace_processor/stack_profile_mapping_table.cc",
-        "src/trace_processor/stack_profile_mapping_table.h",
+        "src/trace_processor/sqlite3_str_split.cc",
+        "src/trace_processor/sqlite3_str_split.h",
+        "src/trace_processor/sqlite_utils.h",
+        "src/trace_processor/stats.h",
         "src/trace_processor/stats_table.cc",
         "src/trace_processor/stats_table.h",
         "src/trace_processor/storage_columns.cc",
@@ -719,2072 +232,550 @@
         "src/trace_processor/storage_schema.h",
         "src/trace_processor/storage_table.cc",
         "src/trace_processor/storage_table.h",
-        "src/trace_processor/thread_table.cc",
-        "src/trace_processor/thread_table.h",
-        "src/trace_processor/trace_processor.cc",
-        "src/trace_processor/trace_processor_impl.cc",
-        "src/trace_processor/trace_processor_impl.h",
-        "src/trace_processor/window_operator_table.cc",
-        "src/trace_processor/window_operator_table.h",
-    ],
-)
-
-# GN target: //src/trace_processor:storage
-filegroup(
-    name = "src_trace_processor_storage",
-    srcs = [
-        "src/trace_processor/args_tracker.cc",
-        "src/trace_processor/args_tracker.h",
-        "src/trace_processor/binder_tracker.cc",
-        "src/trace_processor/binder_tracker.h",
-        "src/trace_processor/chunked_trace_reader.h",
-        "src/trace_processor/clock_tracker.cc",
-        "src/trace_processor/clock_tracker.h",
-        "src/trace_processor/event_tracker.cc",
-        "src/trace_processor/event_tracker.h",
-        "src/trace_processor/forwarding_trace_parser.cc",
-        "src/trace_processor/forwarding_trace_parser.h",
-        "src/trace_processor/ftrace_utils.cc",
-        "src/trace_processor/ftrace_utils.h",
-        "src/trace_processor/gzip_trace_parser.cc",
-        "src/trace_processor/gzip_trace_parser.h",
-        "src/trace_processor/heap_profile_tracker.cc",
-        "src/trace_processor/heap_profile_tracker.h",
-        "src/trace_processor/importers/ftrace/ftrace_descriptors.cc",
-        "src/trace_processor/importers/ftrace/ftrace_descriptors.h",
-        "src/trace_processor/importers/ftrace/ftrace_module.h",
-        "src/trace_processor/importers/ftrace/ftrace_parser.cc",
-        "src/trace_processor/importers/ftrace/ftrace_parser.h",
-        "src/trace_processor/importers/ftrace/ftrace_tokenizer.cc",
-        "src/trace_processor/importers/ftrace/ftrace_tokenizer.h",
-        "src/trace_processor/importers/ftrace/sched_event_tracker.cc",
-        "src/trace_processor/importers/ftrace/sched_event_tracker.h",
-        "src/trace_processor/importers/fuchsia/fuchsia_provider_view.cc",
-        "src/trace_processor/importers/fuchsia/fuchsia_provider_view.h",
-        "src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc",
-        "src/trace_processor/importers/fuchsia/fuchsia_trace_parser.h",
-        "src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc",
-        "src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h",
-        "src/trace_processor/importers/fuchsia/fuchsia_trace_utils.cc",
-        "src/trace_processor/importers/fuchsia/fuchsia_trace_utils.h",
-        "src/trace_processor/importers/json/json_trace_parser.cc",
-        "src/trace_processor/importers/json/json_trace_parser.h",
-        "src/trace_processor/importers/json/json_trace_tokenizer.cc",
-        "src/trace_processor/importers/json/json_trace_tokenizer.h",
-        "src/trace_processor/importers/json/json_trace_utils.cc",
-        "src/trace_processor/importers/json/json_trace_utils.h",
-        "src/trace_processor/importers/proto/android_probes_module.h",
-        "src/trace_processor/importers/proto/android_probes_parser.cc",
-        "src/trace_processor/importers/proto/android_probes_parser.h",
-        "src/trace_processor/importers/proto/graphics_event_module.h",
-        "src/trace_processor/importers/proto/graphics_event_parser.cc",
-        "src/trace_processor/importers/proto/graphics_event_parser.h",
-        "src/trace_processor/importers/proto/heap_graph_module.cc",
-        "src/trace_processor/importers/proto/heap_graph_module.h",
-        "src/trace_processor/importers/proto/heap_graph_tracker.cc",
-        "src/trace_processor/importers/proto/heap_graph_tracker.h",
-        "src/trace_processor/importers/proto/heap_graph_walker.cc",
-        "src/trace_processor/importers/proto/heap_graph_walker.h",
-        "src/trace_processor/importers/proto/packet_sequence_state.h",
-        "src/trace_processor/importers/proto/proto_importer_module.h",
-        "src/trace_processor/importers/proto/proto_incremental_state.h",
-        "src/trace_processor/importers/proto/proto_trace_parser.cc",
-        "src/trace_processor/importers/proto/proto_trace_parser.h",
-        "src/trace_processor/importers/proto/proto_trace_tokenizer.cc",
-        "src/trace_processor/importers/proto/proto_trace_tokenizer.h",
-        "src/trace_processor/importers/proto/system_probes_module.h",
-        "src/trace_processor/importers/proto/system_probes_parser.cc",
-        "src/trace_processor/importers/proto/system_probes_parser.h",
-        "src/trace_processor/importers/proto/track_event_module.h",
-        "src/trace_processor/importers/proto/track_event_parser.cc",
-        "src/trace_processor/importers/proto/track_event_parser.h",
-        "src/trace_processor/importers/proto/track_event_tokenizer.cc",
-        "src/trace_processor/importers/proto/track_event_tokenizer.h",
-        "src/trace_processor/importers/systrace/systrace_parser.cc",
-        "src/trace_processor/importers/systrace/systrace_parser.h",
-        "src/trace_processor/importers/systrace/systrace_trace_parser.cc",
-        "src/trace_processor/importers/systrace/systrace_trace_parser.h",
-        "src/trace_processor/metadata.h",
-        "src/trace_processor/process_tracker.cc",
-        "src/trace_processor/process_tracker.h",
-        "src/trace_processor/slice_tracker.cc",
-        "src/trace_processor/slice_tracker.h",
-        "src/trace_processor/stack_profile_tracker.cc",
-        "src/trace_processor/stack_profile_tracker.h",
-        "src/trace_processor/stats.h",
+        "src/trace_processor/string_pool.cc",
+        "src/trace_processor/string_pool.h",
+        "src/trace_processor/string_table.cc",
+        "src/trace_processor/string_table.h",
         "src/trace_processor/syscall_tracker.cc",
         "src/trace_processor/syscall_tracker.h",
         "src/trace_processor/syscalls_aarch32.h",
         "src/trace_processor/syscalls_aarch64.h",
         "src/trace_processor/syscalls_armeabi.h",
         "src/trace_processor/syscalls_x86_64.h",
-        "src/trace_processor/timestamped_trace_piece.h",
+        "src/trace_processor/table.cc",
+        "src/trace_processor/table.h",
+        "src/trace_processor/thread_table.cc",
+        "src/trace_processor/thread_table.h",
         "src/trace_processor/trace_blob_view.h",
         "src/trace_processor/trace_parser.h",
+        "src/trace_processor/trace_processor.cc",
         "src/trace_processor/trace_processor_context.cc",
         "src/trace_processor/trace_processor_context.h",
-        "src/trace_processor/trace_processor_storage.cc",
-        "src/trace_processor/trace_processor_storage_impl.cc",
-        "src/trace_processor/trace_processor_storage_impl.h",
+        "src/trace_processor/trace_processor_impl.cc",
+        "src/trace_processor/trace_processor_impl.h",
         "src/trace_processor/trace_sorter.cc",
         "src/trace_processor/trace_sorter.h",
         "src/trace_processor/trace_storage.cc",
         "src/trace_processor/trace_storage.h",
-        "src/trace_processor/track_tracker.cc",
-        "src/trace_processor/track_tracker.h",
-        "src/trace_processor/variadic.h",
         "src/trace_processor/virtual_destructors.cc",
-        "src/trace_processor/vulkan_memory_tracker.cc",
-        "src/trace_processor/vulkan_memory_tracker.h",
+        "src/trace_processor/window_operator_table.cc",
+        "src/trace_processor/window_operator_table.h",
+    ],
+    hdrs = [
+        "include/perfetto/base/build_config.h",
+        "include/perfetto/base/circular_queue.h",
+        "include/perfetto/base/container_annotations.h",
+        "include/perfetto/base/event.h",
+        "include/perfetto/base/export.h",
+        "include/perfetto/base/file_utils.h",
+        "include/perfetto/base/gtest_prod_util.h",
+        "include/perfetto/base/hash.h",
+        "include/perfetto/base/logging.h",
+        "include/perfetto/base/metatrace.h",
+        "include/perfetto/base/no_destructor.h",
+        "include/perfetto/base/optional.h",
+        "include/perfetto/base/paged_memory.h",
+        "include/perfetto/base/pipe.h",
+        "include/perfetto/base/scoped_file.h",
+        "include/perfetto/base/small_set.h",
+        "include/perfetto/base/string_splitter.h",
+        "include/perfetto/base/string_utils.h",
+        "include/perfetto/base/string_view.h",
+        "include/perfetto/base/string_writer.h",
+        "include/perfetto/base/task_runner.h",
+        "include/perfetto/base/temp_file.h",
+        "include/perfetto/base/thread_annotations.h",
+        "include/perfetto/base/thread_checker.h",
+        "include/perfetto/base/thread_task_runner.h",
+        "include/perfetto/base/thread_utils.h",
+        "include/perfetto/base/time.h",
+        "include/perfetto/base/unix_socket.h",
+        "include/perfetto/base/unix_task_runner.h",
+        "include/perfetto/base/utils.h",
+        "include/perfetto/base/watchdog.h",
+        "include/perfetto/base/watchdog_noop.h",
+        "include/perfetto/base/watchdog_posix.h",
+        "include/perfetto/base/weak_ptr.h",
+        "include/perfetto/protozero/contiguous_memory_range.h",
+        "include/perfetto/protozero/field.h",
+        "include/perfetto/protozero/message.h",
+        "include/perfetto/protozero/message_handle.h",
+        "include/perfetto/protozero/proto_decoder.h",
+        "include/perfetto/protozero/proto_utils.h",
+        "include/perfetto/protozero/scattered_heap_buffer.h",
+        "include/perfetto/protozero/scattered_stream_null_delegate.h",
+        "include/perfetto/protozero/scattered_stream_writer.h",
+        "include/perfetto/trace_processor/basic_types.h",
+        "include/perfetto/trace_processor/trace_processor.h",
+        "include/perfetto/traced/sys_stats_counters.h",
+    ],
+    deps = [
+        "//third_party/perfetto:gen_merged_sql_metrics",
+        "//third_party/perfetto/google:gtest_prod",
+        "//third_party/perfetto/google:jsoncpp",
+        "//third_party/perfetto/protos:common_zero_cc_proto",
+        "//third_party/perfetto/protos:config_zero_cc_proto",
+        "//third_party/perfetto/protos:metrics_android_zero_cc_proto",
+        "//third_party/perfetto/protos:metrics_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_android_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_chrome_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_filesystem_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_ftrace_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_interned_data_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_power_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_profiling_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_ps_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_sys_stats_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_track_event_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_zero_cc_proto",
+        "//third_party/sqlite",
+        "//third_party/sqlite:sqlite_ext_percentile",
     ],
 )
 
-# GN target: //src/traced/probes/android_log:android_log
-filegroup(
-    name = "src_traced_probes_android_log_android_log",
+# GN target: //src/trace_processor:trace_processor_shell_host
+cc_binary(
+    name = "trace_processor_shell",
     srcs = [
-        "src/traced/probes/android_log/android_log_data_source.cc",
-        "src/traced/probes/android_log/android_log_data_source.h",
+        "include/perfetto/base/build_config.h",
+        "include/perfetto/base/circular_queue.h",
+        "include/perfetto/base/container_annotations.h",
+        "include/perfetto/base/event.h",
+        "include/perfetto/base/export.h",
+        "include/perfetto/base/file_utils.h",
+        "include/perfetto/base/gtest_prod_util.h",
+        "include/perfetto/base/hash.h",
+        "include/perfetto/base/logging.h",
+        "include/perfetto/base/metatrace.h",
+        "include/perfetto/base/no_destructor.h",
+        "include/perfetto/base/optional.h",
+        "include/perfetto/base/paged_memory.h",
+        "include/perfetto/base/pipe.h",
+        "include/perfetto/base/scoped_file.h",
+        "include/perfetto/base/small_set.h",
+        "include/perfetto/base/string_splitter.h",
+        "include/perfetto/base/string_utils.h",
+        "include/perfetto/base/string_view.h",
+        "include/perfetto/base/string_writer.h",
+        "include/perfetto/base/task_runner.h",
+        "include/perfetto/base/temp_file.h",
+        "include/perfetto/base/thread_annotations.h",
+        "include/perfetto/base/thread_checker.h",
+        "include/perfetto/base/thread_task_runner.h",
+        "include/perfetto/base/thread_utils.h",
+        "include/perfetto/base/time.h",
+        "include/perfetto/base/unix_socket.h",
+        "include/perfetto/base/unix_task_runner.h",
+        "include/perfetto/base/utils.h",
+        "include/perfetto/base/watchdog.h",
+        "include/perfetto/base/watchdog_noop.h",
+        "include/perfetto/base/watchdog_posix.h",
+        "include/perfetto/base/weak_ptr.h",
+        "include/perfetto/protozero/contiguous_memory_range.h",
+        "include/perfetto/protozero/field.h",
+        "include/perfetto/protozero/message.h",
+        "include/perfetto/protozero/message_handle.h",
+        "include/perfetto/protozero/proto_decoder.h",
+        "include/perfetto/protozero/proto_utils.h",
+        "include/perfetto/protozero/scattered_heap_buffer.h",
+        "include/perfetto/protozero/scattered_stream_null_delegate.h",
+        "include/perfetto/protozero/scattered_stream_writer.h",
+        "include/perfetto/trace_processor/basic_types.h",
+        "include/perfetto/trace_processor/trace_processor.h",
+        "include/perfetto/traced/sys_stats_counters.h",
+        "src/base/event.cc",
+        "src/base/file_utils.cc",
+        "src/base/metatrace.cc",
+        "src/base/paged_memory.cc",
+        "src/base/pipe.cc",
+        "src/base/string_splitter.cc",
+        "src/base/string_utils.cc",
+        "src/base/string_view.cc",
+        "src/base/temp_file.cc",
+        "src/base/thread_checker.cc",
+        "src/base/thread_task_runner.cc",
+        "src/base/time.cc",
+        "src/base/unix_task_runner.cc",
+        "src/base/virtual_destructors.cc",
+        "src/base/watchdog_posix.cc",
+        "src/protozero/message.cc",
+        "src/protozero/message_handle.cc",
+        "src/protozero/proto_decoder.cc",
+        "src/protozero/scattered_heap_buffer.cc",
+        "src/protozero/scattered_stream_null_delegate.cc",
+        "src/protozero/scattered_stream_writer.cc",
+        "src/trace_processor/android_logs_table.cc",
+        "src/trace_processor/android_logs_table.h",
+        "src/trace_processor/args_table.cc",
+        "src/trace_processor/args_table.h",
+        "src/trace_processor/args_tracker.cc",
+        "src/trace_processor/args_tracker.h",
+        "src/trace_processor/chunked_trace_reader.h",
+        "src/trace_processor/clock_tracker.cc",
+        "src/trace_processor/clock_tracker.h",
+        "src/trace_processor/counter_definitions_table.cc",
+        "src/trace_processor/counter_definitions_table.h",
+        "src/trace_processor/counter_values_table.cc",
+        "src/trace_processor/counter_values_table.h",
+        "src/trace_processor/event_tracker.cc",
+        "src/trace_processor/event_tracker.h",
+        "src/trace_processor/filtered_row_index.cc",
+        "src/trace_processor/filtered_row_index.h",
+        "src/trace_processor/ftrace_descriptors.cc",
+        "src/trace_processor/ftrace_descriptors.h",
+        "src/trace_processor/ftrace_utils.cc",
+        "src/trace_processor/ftrace_utils.h",
+        "src/trace_processor/fuchsia_provider_view.cc",
+        "src/trace_processor/fuchsia_provider_view.h",
+        "src/trace_processor/fuchsia_trace_parser.cc",
+        "src/trace_processor/fuchsia_trace_parser.h",
+        "src/trace_processor/fuchsia_trace_tokenizer.cc",
+        "src/trace_processor/fuchsia_trace_tokenizer.h",
+        "src/trace_processor/fuchsia_trace_utils.cc",
+        "src/trace_processor/fuchsia_trace_utils.h",
+        "src/trace_processor/heap_profile_tracker.cc",
+        "src/trace_processor/heap_profile_tracker.h",
+        "src/trace_processor/instants_table.cc",
+        "src/trace_processor/instants_table.h",
+        "src/trace_processor/json_trace_parser.cc",
+        "src/trace_processor/json_trace_parser.h",
+        "src/trace_processor/json_trace_tokenizer.cc",
+        "src/trace_processor/json_trace_tokenizer.h",
+        "src/trace_processor/json_trace_utils.cc",
+        "src/trace_processor/json_trace_utils.h",
+        "src/trace_processor/metrics/metrics.cc",
+        "src/trace_processor/metrics/metrics.h",
+        "src/trace_processor/metrics/sql_metrics.h",
+        "src/trace_processor/null_term_string_view.h",
+        "src/trace_processor/process_table.cc",
+        "src/trace_processor/process_table.h",
+        "src/trace_processor/process_tracker.cc",
+        "src/trace_processor/process_tracker.h",
+        "src/trace_processor/proto_incremental_state.h",
+        "src/trace_processor/proto_trace_parser.cc",
+        "src/trace_processor/proto_trace_parser.h",
+        "src/trace_processor/proto_trace_tokenizer.cc",
+        "src/trace_processor/proto_trace_tokenizer.h",
+        "src/trace_processor/query_constraints.cc",
+        "src/trace_processor/query_constraints.h",
+        "src/trace_processor/raw_table.cc",
+        "src/trace_processor/raw_table.h",
+        "src/trace_processor/row_iterators.cc",
+        "src/trace_processor/row_iterators.h",
+        "src/trace_processor/sched_slice_table.cc",
+        "src/trace_processor/sched_slice_table.h",
+        "src/trace_processor/scoped_db.h",
+        "src/trace_processor/slice_table.cc",
+        "src/trace_processor/slice_table.h",
+        "src/trace_processor/slice_tracker.cc",
+        "src/trace_processor/slice_tracker.h",
+        "src/trace_processor/span_join_operator_table.cc",
+        "src/trace_processor/span_join_operator_table.h",
+        "src/trace_processor/sql_stats_table.cc",
+        "src/trace_processor/sql_stats_table.h",
+        "src/trace_processor/sqlite3_str_split.cc",
+        "src/trace_processor/sqlite3_str_split.h",
+        "src/trace_processor/sqlite_utils.h",
+        "src/trace_processor/stats.h",
+        "src/trace_processor/stats_table.cc",
+        "src/trace_processor/stats_table.h",
+        "src/trace_processor/storage_columns.cc",
+        "src/trace_processor/storage_columns.h",
+        "src/trace_processor/storage_schema.cc",
+        "src/trace_processor/storage_schema.h",
+        "src/trace_processor/storage_table.cc",
+        "src/trace_processor/storage_table.h",
+        "src/trace_processor/string_pool.cc",
+        "src/trace_processor/string_pool.h",
+        "src/trace_processor/string_table.cc",
+        "src/trace_processor/string_table.h",
+        "src/trace_processor/syscall_tracker.cc",
+        "src/trace_processor/syscall_tracker.h",
+        "src/trace_processor/syscalls_aarch32.h",
+        "src/trace_processor/syscalls_aarch64.h",
+        "src/trace_processor/syscalls_armeabi.h",
+        "src/trace_processor/syscalls_x86_64.h",
+        "src/trace_processor/table.cc",
+        "src/trace_processor/table.h",
+        "src/trace_processor/thread_table.cc",
+        "src/trace_processor/thread_table.h",
+        "src/trace_processor/trace_blob_view.h",
+        "src/trace_processor/trace_parser.h",
+        "src/trace_processor/trace_processor.cc",
+        "src/trace_processor/trace_processor_context.cc",
+        "src/trace_processor/trace_processor_context.h",
+        "src/trace_processor/trace_processor_impl.cc",
+        "src/trace_processor/trace_processor_impl.h",
+        "src/trace_processor/trace_processor_shell.cc",
+        "src/trace_processor/trace_sorter.cc",
+        "src/trace_processor/trace_sorter.h",
+        "src/trace_processor/trace_storage.cc",
+        "src/trace_processor/trace_storage.h",
+        "src/trace_processor/virtual_destructors.cc",
+        "src/trace_processor/window_operator_table.cc",
+        "src/trace_processor/window_operator_table.h",
+    ],
+    deps = [
+        "//third_party/perfetto:gen_merged_sql_metrics",
+        "//third_party/perfetto/google:gtest_prod",
+        "//third_party/perfetto/google:jsoncpp",
+        "//third_party/perfetto/google:linenoise",
+        "//third_party/perfetto/google:perfetto_version",
+        "//third_party/perfetto/protos:common_zero_cc_proto",
+        "//third_party/perfetto/protos:config_zero_cc_proto",
+        "//third_party/perfetto/protos:metrics_android_zero_cc_proto",
+        "//third_party/perfetto/protos:metrics_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_android_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_chrome_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_filesystem_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_ftrace_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_interned_data_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_power_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_profiling_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_ps_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_sys_stats_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_track_event_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_zero_cc_proto",
+        "//third_party/sqlite",
+        "//third_party/sqlite:sqlite_ext_percentile",
     ],
 )
 
-# GN target: //src/traced/probes/filesystem:filesystem
-filegroup(
-    name = "src_traced_probes_filesystem_filesystem",
+# GN target: //tools/trace_to_text:trace_to_text_host
+cc_binary(
+    name = "trace_to_text",
     srcs = [
-        "src/traced/probes/filesystem/file_scanner.cc",
-        "src/traced/probes/filesystem/file_scanner.h",
-        "src/traced/probes/filesystem/fs_mount.cc",
-        "src/traced/probes/filesystem/fs_mount.h",
-        "src/traced/probes/filesystem/inode_file_data_source.cc",
-        "src/traced/probes/filesystem/inode_file_data_source.h",
-        "src/traced/probes/filesystem/lru_inode_cache.cc",
-        "src/traced/probes/filesystem/lru_inode_cache.h",
-        "src/traced/probes/filesystem/prefix_finder.cc",
-        "src/traced/probes/filesystem/prefix_finder.h",
-        "src/traced/probes/filesystem/range_tree.cc",
-        "src/traced/probes/filesystem/range_tree.h",
-    ],
-)
-
-# GN target: //src/traced/probes/ftrace:format_parser
-filegroup(
-    name = "src_traced_probes_ftrace_format_parser",
-    srcs = [
-        "src/traced/probes/ftrace/format_parser.cc",
-        "src/traced/probes/ftrace/format_parser.h",
-    ],
-)
-
-# GN target: //src/traced/probes/ftrace:ftrace
-filegroup(
-    name = "src_traced_probes_ftrace_ftrace",
-    srcs = [
-        "src/traced/probes/ftrace/atrace_hal_wrapper.cc",
-        "src/traced/probes/ftrace/atrace_hal_wrapper.h",
-        "src/traced/probes/ftrace/atrace_wrapper.cc",
-        "src/traced/probes/ftrace/atrace_wrapper.h",
-        "src/traced/probes/ftrace/compact_sched.cc",
-        "src/traced/probes/ftrace/compact_sched.h",
-        "src/traced/probes/ftrace/cpu_reader.cc",
-        "src/traced/probes/ftrace/cpu_reader.h",
-        "src/traced/probes/ftrace/cpu_stats_parser.cc",
-        "src/traced/probes/ftrace/cpu_stats_parser.h",
-        "src/traced/probes/ftrace/event_info.cc",
-        "src/traced/probes/ftrace/event_info.h",
-        "src/traced/probes/ftrace/event_info_constants.cc",
-        "src/traced/probes/ftrace/event_info_constants.h",
-        "src/traced/probes/ftrace/ftrace_config_muxer.cc",
-        "src/traced/probes/ftrace/ftrace_config_muxer.h",
-        "src/traced/probes/ftrace/ftrace_config_utils.cc",
-        "src/traced/probes/ftrace/ftrace_config_utils.h",
-        "src/traced/probes/ftrace/ftrace_controller.cc",
-        "src/traced/probes/ftrace/ftrace_controller.h",
-        "src/traced/probes/ftrace/ftrace_data_source.cc",
-        "src/traced/probes/ftrace/ftrace_data_source.h",
-        "src/traced/probes/ftrace/ftrace_metadata.cc",
-        "src/traced/probes/ftrace/ftrace_metadata.h",
-        "src/traced/probes/ftrace/ftrace_procfs.cc",
-        "src/traced/probes/ftrace/ftrace_procfs.h",
-        "src/traced/probes/ftrace/ftrace_stats.cc",
-        "src/traced/probes/ftrace/ftrace_stats.h",
-        "src/traced/probes/ftrace/proto_translation_table.cc",
-        "src/traced/probes/ftrace/proto_translation_table.h",
-    ],
-)
-
-# GN target: //src/traced/probes/metatrace:metatrace
-filegroup(
-    name = "src_traced_probes_metatrace_metatrace",
-    srcs = [
-        "src/traced/probes/metatrace/metatrace_data_source.cc",
-        "src/traced/probes/metatrace/metatrace_data_source.h",
-    ],
-)
-
-# GN target: //src/traced/probes/packages_list:packages_list
-filegroup(
-    name = "src_traced_probes_packages_list_packages_list",
-    srcs = [
-        "src/traced/probes/packages_list/packages_list_data_source.cc",
-        "src/traced/probes/packages_list/packages_list_data_source.h",
-    ],
-)
-
-# GN target: //src/traced/probes/power:power
-filegroup(
-    name = "src_traced_probes_power_power",
-    srcs = [
-        "src/traced/probes/power/android_power_data_source.cc",
-        "src/traced/probes/power/android_power_data_source.h",
-    ],
-)
-
-# GN target: //src/traced/probes/ps:ps
-filegroup(
-    name = "src_traced_probes_ps_ps",
-    srcs = [
-        "src/traced/probes/ps/process_stats_data_source.cc",
-        "src/traced/probes/ps/process_stats_data_source.h",
-    ],
-)
-
-# GN target: //src/traced/probes/sys_stats:sys_stats
-filegroup(
-    name = "src_traced_probes_sys_stats_sys_stats",
-    srcs = [
-        "src/traced/probes/sys_stats/sys_stats_data_source.cc",
-        "src/traced/probes/sys_stats/sys_stats_data_source.h",
-    ],
-)
-
-# GN target: //src/traced/probes:data_source
-filegroup(
-    name = "src_traced_probes_data_source",
-    srcs = [
-        "src/traced/probes/probes_data_source.cc",
-        "src/traced/probes/probes_data_source.h",
-    ],
-)
-
-# GN target: //src/traced/probes:probes
-filegroup(
-    name = "src_traced_probes_probes",
-    srcs = [
-        "src/traced/probes/probes.cc",
-    ],
-)
-
-# GN target: //src/traced/probes:probes_src
-filegroup(
-    name = "src_traced_probes_probes_src",
-    srcs = [
-        "src/traced/probes/probes_producer.cc",
-        "src/traced/probes/probes_producer.h",
-    ],
-)
-
-# GN target: //src/traced/service:service
-filegroup(
-    name = "src_traced_service_service",
-    srcs = [
-        "src/traced/service/builtin_producer.cc",
-        "src/traced/service/builtin_producer.h",
-        "src/traced/service/service.cc",
-    ],
-)
-
-# GN target: //src/tracing:client_api
-filegroup(
-    name = "src_tracing_client_api",
-    srcs = [
-        "src/tracing/data_source.cc",
-        "src/tracing/internal/in_process_tracing_backend.cc",
-        "src/tracing/internal/in_process_tracing_backend.h",
-        "src/tracing/internal/system_tracing_backend.cc",
-        "src/tracing/internal/system_tracing_backend.h",
-        "src/tracing/internal/tracing_muxer_impl.cc",
-        "src/tracing/internal/tracing_muxer_impl.h",
-        "src/tracing/internal/track_event_internal.cc",
-        "src/tracing/platform.cc",
-        "src/tracing/tracing.cc",
-        "src/tracing/track_event_category_registry.cc",
-        "src/tracing/track_event_context.cc",
-        "src/tracing/virtual_destructors.cc",
-    ],
-)
-
-# GN target: //src/tracing:common
-filegroup(
-    name = "src_tracing_common",
-    srcs = [
-        "src/tracing/trace_writer_base.cc",
-    ],
-)
-
-# GN target: //src/tracing:consumer_api_deprecated
-filegroup(
-    name = "src_tracing_consumer_api_deprecated",
-    srcs = [
-        "src/tracing/api_impl/consumer_api.cc",
-    ],
-)
-
-# GN target: //src/tracing:ipc
-filegroup(
-    name = "src_tracing_ipc",
-    srcs = [
-        "src/tracing/ipc/consumer/consumer_ipc_client_impl.cc",
-        "src/tracing/ipc/consumer/consumer_ipc_client_impl.h",
-        "src/tracing/ipc/default_socket.cc",
-        "src/tracing/ipc/posix_shared_memory.cc",
-        "src/tracing/ipc/posix_shared_memory.h",
-        "src/tracing/ipc/producer/producer_ipc_client_impl.cc",
-        "src/tracing/ipc/producer/producer_ipc_client_impl.h",
-        "src/tracing/ipc/service/consumer_ipc_service.cc",
-        "src/tracing/ipc/service/consumer_ipc_service.h",
-        "src/tracing/ipc/service/producer_ipc_service.cc",
-        "src/tracing/ipc/service/producer_ipc_service.h",
-        "src/tracing/ipc/service/service_ipc_host_impl.cc",
-        "src/tracing/ipc/service/service_ipc_host_impl.h",
-    ],
-)
-
-# GN target: //src/tracing:platform_posix
-filegroup(
-    name = "src_tracing_platform_posix",
-    srcs = [
-        "src/tracing/platform_posix.cc",
-    ],
-)
-
-# GN target: //src/tracing:tracing
-filegroup(
-    name = "src_tracing_tracing",
-    srcs = [
-        "src/tracing/core/id_allocator.cc",
-        "src/tracing/core/id_allocator.h",
-        "src/tracing/core/metatrace_writer.cc",
-        "src/tracing/core/metatrace_writer.h",
-        "src/tracing/core/null_trace_writer.cc",
-        "src/tracing/core/null_trace_writer.h",
-        "src/tracing/core/packet_stream_validator.cc",
-        "src/tracing/core/packet_stream_validator.h",
-        "src/tracing/core/patch_list.h",
-        "src/tracing/core/shared_memory_abi.cc",
-        "src/tracing/core/shared_memory_arbiter_impl.cc",
-        "src/tracing/core/shared_memory_arbiter_impl.h",
-        "src/tracing/core/sliced_protobuf_input_stream.cc",
-        "src/tracing/core/startup_trace_writer.cc",
-        "src/tracing/core/startup_trace_writer_registry.cc",
-        "src/tracing/core/trace_buffer.cc",
-        "src/tracing/core/trace_buffer.h",
-        "src/tracing/core/trace_packet.cc",
-        "src/tracing/core/trace_writer_impl.cc",
-        "src/tracing/core/trace_writer_impl.h",
-        "src/tracing/core/tracing_service_impl.cc",
-        "src/tracing/core/tracing_service_impl.h",
-        "src/tracing/core/virtual_destructors.cc",
-    ],
-)
-
-# GN target: //tools/trace_to_text:common
-filegroup(
-    name = "tools_trace_to_text_common",
-    srcs = [
+        "include/perfetto/base/build_config.h",
+        "include/perfetto/base/circular_queue.h",
+        "include/perfetto/base/container_annotations.h",
+        "include/perfetto/base/event.h",
+        "include/perfetto/base/export.h",
+        "include/perfetto/base/file_utils.h",
+        "include/perfetto/base/gtest_prod_util.h",
+        "include/perfetto/base/hash.h",
+        "include/perfetto/base/logging.h",
+        "include/perfetto/base/metatrace.h",
+        "include/perfetto/base/no_destructor.h",
+        "include/perfetto/base/optional.h",
+        "include/perfetto/base/paged_memory.h",
+        "include/perfetto/base/pipe.h",
+        "include/perfetto/base/scoped_file.h",
+        "include/perfetto/base/small_set.h",
+        "include/perfetto/base/string_splitter.h",
+        "include/perfetto/base/string_utils.h",
+        "include/perfetto/base/string_view.h",
+        "include/perfetto/base/string_writer.h",
+        "include/perfetto/base/task_runner.h",
+        "include/perfetto/base/temp_file.h",
+        "include/perfetto/base/thread_annotations.h",
+        "include/perfetto/base/thread_checker.h",
+        "include/perfetto/base/thread_task_runner.h",
+        "include/perfetto/base/thread_utils.h",
+        "include/perfetto/base/time.h",
+        "include/perfetto/base/unix_socket.h",
+        "include/perfetto/base/unix_task_runner.h",
+        "include/perfetto/base/utils.h",
+        "include/perfetto/base/watchdog.h",
+        "include/perfetto/base/watchdog_noop.h",
+        "include/perfetto/base/watchdog_posix.h",
+        "include/perfetto/base/weak_ptr.h",
+        "include/perfetto/protozero/contiguous_memory_range.h",
+        "include/perfetto/protozero/field.h",
+        "include/perfetto/protozero/message.h",
+        "include/perfetto/protozero/message_handle.h",
+        "include/perfetto/protozero/proto_decoder.h",
+        "include/perfetto/protozero/proto_utils.h",
+        "include/perfetto/protozero/scattered_heap_buffer.h",
+        "include/perfetto/protozero/scattered_stream_null_delegate.h",
+        "include/perfetto/protozero/scattered_stream_writer.h",
+        "include/perfetto/trace_processor/basic_types.h",
+        "include/perfetto/trace_processor/trace_processor.h",
+        "include/perfetto/traced/sys_stats_counters.h",
+        "src/base/event.cc",
+        "src/base/file_utils.cc",
+        "src/base/metatrace.cc",
+        "src/base/paged_memory.cc",
+        "src/base/pipe.cc",
+        "src/base/string_splitter.cc",
+        "src/base/string_utils.cc",
+        "src/base/string_view.cc",
+        "src/base/temp_file.cc",
+        "src/base/thread_checker.cc",
+        "src/base/thread_task_runner.cc",
+        "src/base/time.cc",
+        "src/base/unix_task_runner.cc",
+        "src/base/virtual_destructors.cc",
+        "src/base/watchdog_posix.cc",
+        "src/protozero/message.cc",
+        "src/protozero/message_handle.cc",
+        "src/protozero/proto_decoder.cc",
+        "src/protozero/scattered_heap_buffer.cc",
+        "src/protozero/scattered_stream_null_delegate.cc",
+        "src/protozero/scattered_stream_writer.cc",
+        "src/trace_processor/android_logs_table.cc",
+        "src/trace_processor/android_logs_table.h",
+        "src/trace_processor/args_table.cc",
+        "src/trace_processor/args_table.h",
+        "src/trace_processor/args_tracker.cc",
+        "src/trace_processor/args_tracker.h",
+        "src/trace_processor/chunked_trace_reader.h",
+        "src/trace_processor/clock_tracker.cc",
+        "src/trace_processor/clock_tracker.h",
+        "src/trace_processor/counter_definitions_table.cc",
+        "src/trace_processor/counter_definitions_table.h",
+        "src/trace_processor/counter_values_table.cc",
+        "src/trace_processor/counter_values_table.h",
+        "src/trace_processor/event_tracker.cc",
+        "src/trace_processor/event_tracker.h",
+        "src/trace_processor/filtered_row_index.cc",
+        "src/trace_processor/filtered_row_index.h",
+        "src/trace_processor/ftrace_descriptors.cc",
+        "src/trace_processor/ftrace_descriptors.h",
+        "src/trace_processor/ftrace_utils.cc",
+        "src/trace_processor/ftrace_utils.h",
+        "src/trace_processor/fuchsia_provider_view.cc",
+        "src/trace_processor/fuchsia_provider_view.h",
+        "src/trace_processor/fuchsia_trace_parser.cc",
+        "src/trace_processor/fuchsia_trace_parser.h",
+        "src/trace_processor/fuchsia_trace_tokenizer.cc",
+        "src/trace_processor/fuchsia_trace_tokenizer.h",
+        "src/trace_processor/fuchsia_trace_utils.cc",
+        "src/trace_processor/fuchsia_trace_utils.h",
+        "src/trace_processor/heap_profile_tracker.cc",
+        "src/trace_processor/heap_profile_tracker.h",
+        "src/trace_processor/instants_table.cc",
+        "src/trace_processor/instants_table.h",
+        "src/trace_processor/json_trace_parser.cc",
+        "src/trace_processor/json_trace_parser.h",
+        "src/trace_processor/json_trace_tokenizer.cc",
+        "src/trace_processor/json_trace_tokenizer.h",
+        "src/trace_processor/json_trace_utils.cc",
+        "src/trace_processor/json_trace_utils.h",
+        "src/trace_processor/metrics/metrics.cc",
+        "src/trace_processor/metrics/metrics.h",
+        "src/trace_processor/metrics/sql_metrics.h",
+        "src/trace_processor/null_term_string_view.h",
+        "src/trace_processor/process_table.cc",
+        "src/trace_processor/process_table.h",
+        "src/trace_processor/process_tracker.cc",
+        "src/trace_processor/process_tracker.h",
+        "src/trace_processor/proto_incremental_state.h",
+        "src/trace_processor/proto_trace_parser.cc",
+        "src/trace_processor/proto_trace_parser.h",
+        "src/trace_processor/proto_trace_tokenizer.cc",
+        "src/trace_processor/proto_trace_tokenizer.h",
+        "src/trace_processor/query_constraints.cc",
+        "src/trace_processor/query_constraints.h",
+        "src/trace_processor/raw_table.cc",
+        "src/trace_processor/raw_table.h",
+        "src/trace_processor/row_iterators.cc",
+        "src/trace_processor/row_iterators.h",
+        "src/trace_processor/sched_slice_table.cc",
+        "src/trace_processor/sched_slice_table.h",
+        "src/trace_processor/scoped_db.h",
+        "src/trace_processor/slice_table.cc",
+        "src/trace_processor/slice_table.h",
+        "src/trace_processor/slice_tracker.cc",
+        "src/trace_processor/slice_tracker.h",
+        "src/trace_processor/span_join_operator_table.cc",
+        "src/trace_processor/span_join_operator_table.h",
+        "src/trace_processor/sql_stats_table.cc",
+        "src/trace_processor/sql_stats_table.h",
+        "src/trace_processor/sqlite3_str_split.cc",
+        "src/trace_processor/sqlite3_str_split.h",
+        "src/trace_processor/sqlite_utils.h",
+        "src/trace_processor/stats.h",
+        "src/trace_processor/stats_table.cc",
+        "src/trace_processor/stats_table.h",
+        "src/trace_processor/storage_columns.cc",
+        "src/trace_processor/storage_columns.h",
+        "src/trace_processor/storage_schema.cc",
+        "src/trace_processor/storage_schema.h",
+        "src/trace_processor/storage_table.cc",
+        "src/trace_processor/storage_table.h",
+        "src/trace_processor/string_pool.cc",
+        "src/trace_processor/string_pool.h",
+        "src/trace_processor/string_table.cc",
+        "src/trace_processor/string_table.h",
+        "src/trace_processor/syscall_tracker.cc",
+        "src/trace_processor/syscall_tracker.h",
+        "src/trace_processor/syscalls_aarch32.h",
+        "src/trace_processor/syscalls_aarch64.h",
+        "src/trace_processor/syscalls_armeabi.h",
+        "src/trace_processor/syscalls_x86_64.h",
+        "src/trace_processor/table.cc",
+        "src/trace_processor/table.h",
+        "src/trace_processor/thread_table.cc",
+        "src/trace_processor/thread_table.h",
+        "src/trace_processor/trace_blob_view.h",
+        "src/trace_processor/trace_parser.h",
+        "src/trace_processor/trace_processor.cc",
+        "src/trace_processor/trace_processor_context.cc",
+        "src/trace_processor/trace_processor_context.h",
+        "src/trace_processor/trace_processor_impl.cc",
+        "src/trace_processor/trace_processor_impl.h",
+        "src/trace_processor/trace_sorter.cc",
+        "src/trace_processor/trace_sorter.h",
+        "src/trace_processor/trace_storage.cc",
+        "src/trace_processor/trace_storage.h",
+        "src/trace_processor/virtual_destructors.cc",
+        "src/trace_processor/window_operator_table.cc",
+        "src/trace_processor/window_operator_table.h",
         "tools/trace_to_text/main.cc",
-        "tools/trace_to_text/symbolize_profile.cc",
-        "tools/trace_to_text/symbolize_profile.h",
-        "tools/trace_to_text/trace_to_json.cc",
-        "tools/trace_to_text/trace_to_json.h",
+        "tools/trace_to_text/proto_full_utils.cc",
+        "tools/trace_to_text/proto_full_utils.h",
         "tools/trace_to_text/trace_to_profile.cc",
         "tools/trace_to_text/trace_to_profile.h",
         "tools/trace_to_text/trace_to_systrace.cc",
         "tools/trace_to_text/trace_to_systrace.h",
-        "tools/trace_to_text/trace_to_text.h",
-    ],
-)
-
-# GN target: //tools/trace_to_text:full
-filegroup(
-    name = "tools_trace_to_text_full",
-    srcs = [
-        "tools/trace_to_text/proto_full_utils.cc",
-        "tools/trace_to_text/proto_full_utils.h",
         "tools/trace_to_text/trace_to_text.cc",
-    ],
-)
-
-# GN target: //tools/trace_to_text:local_symbolizer
-filegroup(
-    name = "tools_trace_to_text_local_symbolizer",
-    srcs = [
-        "tools/trace_to_text/local_symbolizer.cc",
-        "tools/trace_to_text/local_symbolizer.h",
-    ],
-)
-
-# GN target: //tools/trace_to_text:pprofbuilder
-filegroup(
-    name = "tools_trace_to_text_pprofbuilder",
-    srcs = [
-        "tools/trace_to_text/pprof_builder.cc",
-    ],
-)
-
-# GN target: //tools/trace_to_text:symbolizer
-filegroup(
-    name = "tools_trace_to_text_symbolizer",
-    srcs = [
-        "tools/trace_to_text/symbolizer.cc",
-    ],
-)
-
-# GN target: //tools/trace_to_text:utils
-filegroup(
-    name = "tools_trace_to_text_utils",
-    srcs = [
+        "tools/trace_to_text/trace_to_text.h",
         "tools/trace_to_text/utils.cc",
         "tools/trace_to_text/utils.h",
     ],
-)
-
-# ##############################################################################
-# Proto libraries
-# ##############################################################################
-
-# GN target: //protos/perfetto/common:cpp
-perfetto_cc_protocpp_library(
-    name = "protos_perfetto_common_cpp",
     deps = [
-        ":protos_perfetto_common_protos",
-        ":protos_perfetto_common_lite",
+        "//third_party/perfetto:gen_merged_sql_metrics",
+        "//third_party/perfetto/google:gtest_prod",
+        "//third_party/perfetto/google:jsoncpp",
+        "//third_party/perfetto/google:perfetto_version",
+        "//third_party/perfetto/protos:common_cc_proto",
+        "//third_party/perfetto/protos:common_zero_cc_proto",
+        "//third_party/perfetto/protos:config_cc_proto",
+        "//third_party/perfetto/protos:config_zero_cc_proto",
+        "//third_party/perfetto/protos:metrics_android_zero_cc_proto",
+        "//third_party/perfetto/protos:metrics_zero_cc_proto",
+        "//third_party/perfetto/protos:protos_third_party_pprof_cc_proto",
+        "//third_party/perfetto/protos:trace_android_cc_proto",
+        "//third_party/perfetto/protos:trace_android_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_cc_proto",
+        "//third_party/perfetto/protos:trace_chrome_cc_proto",
+        "//third_party/perfetto/protos:trace_chrome_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_filesystem_cc_proto",
+        "//third_party/perfetto/protos:trace_filesystem_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_ftrace_cc_proto",
+        "//third_party/perfetto/protos:trace_ftrace_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_interned_data_cc_proto",
+        "//third_party/perfetto/protos:trace_interned_data_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_minimal_cc_proto",
+        "//third_party/perfetto/protos:trace_power_cc_proto",
+        "//third_party/perfetto/protos:trace_power_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_profiling_cc_proto",
+        "//third_party/perfetto/protos:trace_profiling_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_ps_cc_proto",
+        "//third_party/perfetto/protos:trace_ps_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_sys_stats_cc_proto",
+        "//third_party/perfetto/protos:trace_sys_stats_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_track_event_cc_proto",
+        "//third_party/perfetto/protos:trace_track_event_zero_cc_proto",
+        "//third_party/perfetto/protos:trace_zero_cc_proto",
+        "//third_party/protobuf",
+        "//third_party/protobuf:libprotoc",
+        "//third_party/sqlite",
+        "//third_party/sqlite:sqlite_ext_percentile",
     ],
 )
 
-# GN target: //protos/perfetto/common:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_common_lite",
-    deps = [
-        ":protos_perfetto_common_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/common:zero
-perfetto_proto_library(
-    name = "protos_perfetto_common_protos",
-    srcs = [
-        "protos/perfetto/common/android_log_constants.proto",
-        "protos/perfetto/common/commit_data_request.proto",
-        "protos/perfetto/common/data_source_descriptor.proto",
-        "protos/perfetto/common/descriptor.proto",
-        "protos/perfetto/common/gpu_counter_descriptor.proto",
-        "protos/perfetto/common/observable_events.proto",
-        "protos/perfetto/common/sys_stats_counters.proto",
-        "protos/perfetto/common/trace_stats.proto",
-        "protos/perfetto/common/tracing_service_state.proto",
-        "protos/perfetto/common/track_event_descriptor.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/common:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_common_zero",
-    deps = [
-        ":protos_perfetto_common_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/android:cpp
-perfetto_cc_protocpp_library(
-    name = "protos_perfetto_config_android_cpp",
-    deps = [
-        ":protos_perfetto_config_android_protos",
-        ":protos_perfetto_common_lite",
-        ":protos_perfetto_config_android_lite",
-        ":protos_perfetto_common_cpp",
-    ],
-)
-
-# GN target: //protos/perfetto/config/android:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_config_android_lite",
-    deps = [
-        ":protos_perfetto_config_android_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/android:zero
-perfetto_proto_library(
-    name = "protos_perfetto_config_android_protos",
-    srcs = [
-        "protos/perfetto/config/android/android_log_config.proto",
-        "protos/perfetto/config/android/packages_list_config.proto",
-    ],
-    deps = [
-        ":protos_perfetto_common_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/android:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_config_android_zero",
-    deps = [
-        ":protos_perfetto_config_android_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config:cpp
-perfetto_cc_protocpp_library(
-    name = "protos_perfetto_config_cpp",
-    deps = [
-        ":protos_perfetto_config_protos",
-        ":protos_perfetto_config_inode_file_cpp",
-        ":protos_perfetto_config_android_cpp",
-        ":protos_perfetto_config_lite",
-        ":protos_perfetto_config_android_lite",
-        ":protos_perfetto_common_cpp",
-        ":protos_perfetto_config_gpu_lite",
-        ":protos_perfetto_common_lite",
-        ":protos_perfetto_config_profiling_lite",
-        ":protos_perfetto_config_process_stats_cpp",
-        ":protos_perfetto_config_power_cpp",
-        ":protos_perfetto_config_process_stats_lite",
-        ":protos_perfetto_config_power_lite",
-        ":protos_perfetto_config_profiling_cpp",
-        ":protos_perfetto_config_inode_file_lite",
-        ":protos_perfetto_config_gpu_cpp",
-        ":protos_perfetto_config_ftrace_lite",
-        ":protos_perfetto_config_sys_stats_lite",
-        ":protos_perfetto_config_ftrace_cpp",
-        ":protos_perfetto_config_sys_stats_cpp",
-    ],
-)
-
-# GN target: //protos/perfetto/config/ftrace:cpp
-perfetto_cc_protocpp_library(
-    name = "protos_perfetto_config_ftrace_cpp",
-    deps = [
-        ":protos_perfetto_config_ftrace_protos",
-        ":protos_perfetto_config_ftrace_lite",
-    ],
-)
-
-# GN target: //protos/perfetto/config/ftrace:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_config_ftrace_lite",
-    deps = [
-        ":protos_perfetto_config_ftrace_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/ftrace:zero
-perfetto_proto_library(
-    name = "protos_perfetto_config_ftrace_protos",
-    srcs = [
-        "protos/perfetto/config/ftrace/ftrace_config.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/config/ftrace:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_config_ftrace_zero",
-    deps = [
-        ":protos_perfetto_config_ftrace_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/gpu:cpp
-perfetto_cc_protocpp_library(
-    name = "protos_perfetto_config_gpu_cpp",
-    deps = [
-        ":protos_perfetto_config_gpu_protos",
-        ":protos_perfetto_config_gpu_lite",
-    ],
-)
-
-# GN target: //protos/perfetto/config/gpu:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_config_gpu_lite",
-    deps = [
-        ":protos_perfetto_config_gpu_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/gpu:zero
-perfetto_proto_library(
-    name = "protos_perfetto_config_gpu_protos",
-    srcs = [
-        "protos/perfetto/config/gpu/gpu_counter_config.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/config/gpu:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_config_gpu_zero",
-    deps = [
-        ":protos_perfetto_config_gpu_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/inode_file:cpp
-perfetto_cc_protocpp_library(
-    name = "protos_perfetto_config_inode_file_cpp",
-    deps = [
-        ":protos_perfetto_config_inode_file_protos",
-        ":protos_perfetto_config_inode_file_lite",
-    ],
-)
-
-# GN target: //protos/perfetto/config/inode_file:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_config_inode_file_lite",
-    deps = [
-        ":protos_perfetto_config_inode_file_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/inode_file:zero
-perfetto_proto_library(
-    name = "protos_perfetto_config_inode_file_protos",
-    srcs = [
-        "protos/perfetto/config/inode_file/inode_file_config.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/config/inode_file:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_config_inode_file_zero",
-    deps = [
-        ":protos_perfetto_config_inode_file_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_config_lite",
-    deps = [
-        ":protos_perfetto_config_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config:merged_config
-perfetto_cc_proto_library(
-    name = "protos_perfetto_config_merged_config",
-    deps = [
-        ":protos_perfetto_config_merged_config_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config:merged_config
-perfetto_proto_library(
-    name = "protos_perfetto_config_merged_config_protos",
-    srcs = [
-        "protos/perfetto/config/perfetto_config.proto",
-    ],
-    visibility = [
-        "//visibility:public",
-    ],
-)
-
-# GN target: //protos/perfetto/config/power:cpp
-perfetto_cc_protocpp_library(
-    name = "protos_perfetto_config_power_cpp",
-    deps = [
-        ":protos_perfetto_config_power_protos",
-        ":protos_perfetto_config_power_lite",
-    ],
-)
-
-# GN target: //protos/perfetto/config/power:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_config_power_lite",
-    deps = [
-        ":protos_perfetto_config_power_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/power:zero
-perfetto_proto_library(
-    name = "protos_perfetto_config_power_protos",
-    srcs = [
-        "protos/perfetto/config/power/android_power_config.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/config/power:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_config_power_zero",
-    deps = [
-        ":protos_perfetto_config_power_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/process_stats:cpp
-perfetto_cc_protocpp_library(
-    name = "protos_perfetto_config_process_stats_cpp",
-    deps = [
-        ":protos_perfetto_config_process_stats_protos",
-        ":protos_perfetto_config_process_stats_lite",
-    ],
-)
-
-# GN target: //protos/perfetto/config/process_stats:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_config_process_stats_lite",
-    deps = [
-        ":protos_perfetto_config_process_stats_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/process_stats:zero
-perfetto_proto_library(
-    name = "protos_perfetto_config_process_stats_protos",
-    srcs = [
-        "protos/perfetto/config/process_stats/process_stats_config.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/config/process_stats:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_config_process_stats_zero",
-    deps = [
-        ":protos_perfetto_config_process_stats_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/profiling:cpp
-perfetto_cc_protocpp_library(
-    name = "protos_perfetto_config_profiling_cpp",
-    deps = [
-        ":protos_perfetto_config_profiling_protos",
-        ":protos_perfetto_config_profiling_lite",
-    ],
-)
-
-# GN target: //protos/perfetto/config/profiling:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_config_profiling_lite",
-    deps = [
-        ":protos_perfetto_config_profiling_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/profiling:zero
-perfetto_proto_library(
-    name = "protos_perfetto_config_profiling_protos",
-    srcs = [
-        "protos/perfetto/config/profiling/heapprofd_config.proto",
-        "protos/perfetto/config/profiling/java_hprof_config.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/config/profiling:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_config_profiling_zero",
-    deps = [
-        ":protos_perfetto_config_profiling_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config:zero
-perfetto_proto_library(
-    name = "protos_perfetto_config_protos",
-    srcs = [
-        "protos/perfetto/config/chrome/chrome_config.proto",
-        "protos/perfetto/config/data_source_config.proto",
-        "protos/perfetto/config/test_config.proto",
-        "protos/perfetto/config/trace_config.proto",
-    ],
-    deps = [
-        ":protos_perfetto_common_protos",
-        ":protos_perfetto_config_android_protos",
-        ":protos_perfetto_config_ftrace_protos",
-        ":protos_perfetto_config_gpu_protos",
-        ":protos_perfetto_config_inode_file_protos",
-        ":protos_perfetto_config_power_protos",
-        ":protos_perfetto_config_process_stats_protos",
-        ":protos_perfetto_config_profiling_protos",
-        ":protos_perfetto_config_sys_stats_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/sys_stats:cpp
-perfetto_cc_protocpp_library(
-    name = "protos_perfetto_config_sys_stats_cpp",
-    deps = [
-        ":protos_perfetto_config_sys_stats_protos",
-        ":protos_perfetto_common_lite",
-        ":protos_perfetto_config_sys_stats_lite",
-        ":protos_perfetto_common_cpp",
-    ],
-)
-
-# GN target: //protos/perfetto/config/sys_stats:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_config_sys_stats_lite",
-    deps = [
-        ":protos_perfetto_config_sys_stats_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/sys_stats:zero
-perfetto_proto_library(
-    name = "protos_perfetto_config_sys_stats_protos",
-    srcs = [
-        "protos/perfetto/config/sys_stats/sys_stats_config.proto",
-    ],
-    deps = [
-        ":protos_perfetto_common_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config/sys_stats:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_config_sys_stats_zero",
-    deps = [
-        ":protos_perfetto_config_sys_stats_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/config:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_config_zero",
-    deps = [
-        ":protos_perfetto_config_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/ipc:ipc
-perfetto_cc_ipc_library(
-    name = "protos_perfetto_ipc_ipc",
-    deps = [
-        ":protos_perfetto_ipc_ipc_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/ipc:ipc
-perfetto_proto_library(
-    name = "protos_perfetto_ipc_ipc_protos",
-    srcs = [
-        "protos/perfetto/ipc/consumer_port.proto",
-        "protos/perfetto/ipc/producer_port.proto",
-    ],
-    deps = [
-        ":protos_perfetto_common_protos",
-        ":protos_perfetto_config_android_protos",
-        ":protos_perfetto_config_ftrace_protos",
-        ":protos_perfetto_config_gpu_protos",
-        ":protos_perfetto_config_inode_file_protos",
-        ":protos_perfetto_config_power_protos",
-        ":protos_perfetto_config_process_stats_protos",
-        ":protos_perfetto_config_profiling_protos",
-        ":protos_perfetto_config_protos",
-        ":protos_perfetto_config_sys_stats_protos",
-        ":protos_perfetto_ipc_wire_protocol_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/ipc:wire_protocol
-perfetto_cc_proto_library(
-    name = "protos_perfetto_ipc_wire_protocol",
-    deps = [
-        ":protos_perfetto_ipc_wire_protocol_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/ipc:wire_protocol
-perfetto_proto_library(
-    name = "protos_perfetto_ipc_wire_protocol_protos",
-    srcs = [
-        "protos/perfetto/ipc/wire_protocol.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/metrics/android:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_metrics_android_lite",
-    deps = [
-        ":protos_perfetto_metrics_android_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/metrics/android:zero
-perfetto_proto_library(
-    name = "protos_perfetto_metrics_android_protos",
-    srcs = [
-        "protos/perfetto/metrics/android/batt_metric.proto",
-        "protos/perfetto/metrics/android/cpu_metric.proto",
-        "protos/perfetto/metrics/android/heap_profile_callsites.proto",
-        "protos/perfetto/metrics/android/ion_metric.proto",
-        "protos/perfetto/metrics/android/java_heap_stats.proto",
-        "protos/perfetto/metrics/android/lmk_metric.proto",
-        "protos/perfetto/metrics/android/mem_metric.proto",
-        "protos/perfetto/metrics/android/mem_unagg_metric.proto",
-        "protos/perfetto/metrics/android/package_list.proto",
-        "protos/perfetto/metrics/android/powrails_metric.proto",
-        "protos/perfetto/metrics/android/process_growth.proto",
-        "protos/perfetto/metrics/android/startup_metric.proto",
-        "protos/perfetto/metrics/android/unsymbolized_frames.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/metrics/android:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_metrics_android_zero",
-    deps = [
-        ":protos_perfetto_metrics_android_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/metrics:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_metrics_lite",
-    deps = [
-        ":protos_perfetto_metrics_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/metrics:zero
-perfetto_proto_library(
-    name = "protos_perfetto_metrics_protos",
-    srcs = [
-        "protos/perfetto/metrics/metrics.proto",
-    ],
-    deps = [
-        ":protos_perfetto_metrics_android_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/metrics:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_metrics_zero",
-    deps = [
-        ":protos_perfetto_metrics_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/android:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_trace_android_lite",
-    deps = [
-        ":protos_perfetto_trace_android_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/android:zero
-perfetto_proto_library(
-    name = "protos_perfetto_trace_android_protos",
-    srcs = [
-        "protos/perfetto/trace/android/android_log.proto",
-        "protos/perfetto/trace/android/graphics_frame_event.proto",
-        "protos/perfetto/trace/android/packages_list.proto",
-    ],
-    deps = [
-        ":protos_perfetto_common_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/android:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_trace_android_zero",
-    deps = [
-        ":protos_perfetto_trace_android_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/chrome:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_trace_chrome_lite",
-    deps = [
-        ":protos_perfetto_trace_chrome_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/chrome:zero
-perfetto_proto_library(
-    name = "protos_perfetto_trace_chrome_protos",
-    srcs = [
-        "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto",
-        "protos/perfetto/trace/chrome/chrome_metadata.proto",
-        "protos/perfetto/trace/chrome/chrome_trace_event.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/chrome:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_trace_chrome_zero",
-    deps = [
-        ":protos_perfetto_trace_chrome_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/filesystem:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_trace_filesystem_lite",
-    deps = [
-        ":protos_perfetto_trace_filesystem_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/filesystem:zero
-perfetto_proto_library(
-    name = "protos_perfetto_trace_filesystem_protos",
-    srcs = [
-        "protos/perfetto/trace/filesystem/inode_file_map.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/filesystem:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_trace_filesystem_zero",
-    deps = [
-        ":protos_perfetto_trace_filesystem_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/ftrace:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_trace_ftrace_lite",
-    deps = [
-        ":protos_perfetto_trace_ftrace_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/ftrace:zero
-perfetto_proto_library(
-    name = "protos_perfetto_trace_ftrace_protos",
-    srcs = [
-        "protos/perfetto/trace/ftrace/binder.proto",
-        "protos/perfetto/trace/ftrace/block.proto",
-        "protos/perfetto/trace/ftrace/cgroup.proto",
-        "protos/perfetto/trace/ftrace/clk.proto",
-        "protos/perfetto/trace/ftrace/compaction.proto",
-        "protos/perfetto/trace/ftrace/ext4.proto",
-        "protos/perfetto/trace/ftrace/f2fs.proto",
-        "protos/perfetto/trace/ftrace/fence.proto",
-        "protos/perfetto/trace/ftrace/filemap.proto",
-        "protos/perfetto/trace/ftrace/ftrace.proto",
-        "protos/perfetto/trace/ftrace/ftrace_event.proto",
-        "protos/perfetto/trace/ftrace/ftrace_event_bundle.proto",
-        "protos/perfetto/trace/ftrace/ftrace_stats.proto",
-        "protos/perfetto/trace/ftrace/generic.proto",
-        "protos/perfetto/trace/ftrace/i2c.proto",
-        "protos/perfetto/trace/ftrace/ipi.proto",
-        "protos/perfetto/trace/ftrace/irq.proto",
-        "protos/perfetto/trace/ftrace/kmem.proto",
-        "protos/perfetto/trace/ftrace/lowmemorykiller.proto",
-        "protos/perfetto/trace/ftrace/mdss.proto",
-        "protos/perfetto/trace/ftrace/mm_event.proto",
-        "protos/perfetto/trace/ftrace/oom.proto",
-        "protos/perfetto/trace/ftrace/power.proto",
-        "protos/perfetto/trace/ftrace/raw_syscalls.proto",
-        "protos/perfetto/trace/ftrace/regulator.proto",
-        "protos/perfetto/trace/ftrace/sched.proto",
-        "protos/perfetto/trace/ftrace/signal.proto",
-        "protos/perfetto/trace/ftrace/sync.proto",
-        "protos/perfetto/trace/ftrace/systrace.proto",
-        "protos/perfetto/trace/ftrace/task.proto",
-        "protos/perfetto/trace/ftrace/test_bundle_wrapper.proto",
-        "protos/perfetto/trace/ftrace/vmscan.proto",
-        "protos/perfetto/trace/ftrace/workqueue.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/ftrace:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_trace_ftrace_zero",
-    deps = [
-        ":protos_perfetto_trace_ftrace_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/gpu:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_trace_gpu_lite",
-    deps = [
-        ":protos_perfetto_trace_gpu_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/gpu:zero
-perfetto_proto_library(
-    name = "protos_perfetto_trace_gpu_protos",
-    srcs = [
-        "protos/perfetto/trace/gpu/gpu_counter_event.proto",
-        "protos/perfetto/trace/gpu/gpu_log.proto",
-        "protos/perfetto/trace/gpu/gpu_render_stage_event.proto",
-        "protos/perfetto/trace/gpu/vulkan_memory_event.proto",
-    ],
-    deps = [
-        ":protos_perfetto_common_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/gpu:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_trace_gpu_zero",
-    deps = [
-        ":protos_perfetto_trace_gpu_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/interned_data:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_trace_interned_data_lite",
-    deps = [
-        ":protos_perfetto_trace_interned_data_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/interned_data:zero
-perfetto_proto_library(
-    name = "protos_perfetto_trace_interned_data_protos",
-    srcs = [
-        "protos/perfetto/trace/interned_data/interned_data.proto",
-    ],
-    deps = [
-        ":protos_perfetto_trace_profiling_protos",
-        ":protos_perfetto_trace_track_event_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/interned_data:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_trace_interned_data_zero",
-    deps = [
-        ":protos_perfetto_trace_interned_data_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace:merged_trace
-perfetto_cc_proto_library(
-    name = "protos_perfetto_trace_merged_trace",
-    deps = [
-        ":protos_perfetto_trace_merged_trace_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace:merged_trace
-perfetto_proto_library(
-    name = "protos_perfetto_trace_merged_trace_protos",
-    srcs = [
-        "protos/perfetto/trace/perfetto_trace.proto",
-    ],
-    visibility = [
-        "//visibility:public",
-    ],
-)
-
-# GN target: //protos/perfetto/trace:minimal_lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_trace_minimal_lite",
-    deps = [
-        ":protos_perfetto_trace_minimal_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace:minimal_zero
-perfetto_proto_library(
-    name = "protos_perfetto_trace_minimal_protos",
-    srcs = [
-        "protos/perfetto/trace/clock_snapshot.proto",
-        "protos/perfetto/trace/system_info.proto",
-        "protos/perfetto/trace/trigger.proto",
-    ],
-    deps = [
-        ":protos_perfetto_common_protos",
-        ":protos_perfetto_config_android_protos",
-        ":protos_perfetto_config_ftrace_protos",
-        ":protos_perfetto_config_gpu_protos",
-        ":protos_perfetto_config_inode_file_protos",
-        ":protos_perfetto_config_power_protos",
-        ":protos_perfetto_config_process_stats_protos",
-        ":protos_perfetto_config_profiling_protos",
-        ":protos_perfetto_config_protos",
-        ":protos_perfetto_config_sys_stats_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace:minimal_zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_trace_minimal_zero",
-    deps = [
-        ":protos_perfetto_trace_minimal_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace:non_minimal_lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_trace_non_minimal_lite",
-    deps = [
-        ":protos_perfetto_trace_non_minimal_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace:non_minimal_zero
-perfetto_proto_library(
-    name = "protos_perfetto_trace_non_minimal_protos",
-    srcs = [
-        "protos/perfetto/trace/test_event.proto",
-        "protos/perfetto/trace/trace.proto",
-        "protos/perfetto/trace/trace_packet.proto",
-        "protos/perfetto/trace/trace_packet_defaults.proto",
-    ],
-    deps = [
-        ":protos_perfetto_common_protos",
-        ":protos_perfetto_config_android_protos",
-        ":protos_perfetto_config_ftrace_protos",
-        ":protos_perfetto_config_gpu_protos",
-        ":protos_perfetto_config_inode_file_protos",
-        ":protos_perfetto_config_power_protos",
-        ":protos_perfetto_config_process_stats_protos",
-        ":protos_perfetto_config_profiling_protos",
-        ":protos_perfetto_config_protos",
-        ":protos_perfetto_config_sys_stats_protos",
-        ":protos_perfetto_trace_android_protos",
-        ":protos_perfetto_trace_chrome_protos",
-        ":protos_perfetto_trace_filesystem_protos",
-        ":protos_perfetto_trace_ftrace_protos",
-        ":protos_perfetto_trace_gpu_protos",
-        ":protos_perfetto_trace_interned_data_protos",
-        ":protos_perfetto_trace_minimal_protos",
-        ":protos_perfetto_trace_perfetto_protos",
-        ":protos_perfetto_trace_power_protos",
-        ":protos_perfetto_trace_profiling_protos",
-        ":protos_perfetto_trace_ps_protos",
-        ":protos_perfetto_trace_sys_stats_protos",
-        ":protos_perfetto_trace_track_event_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace:non_minimal_zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_trace_non_minimal_zero",
-    deps = [
-        ":protos_perfetto_trace_non_minimal_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/perfetto:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_trace_perfetto_lite",
-    deps = [
-        ":protos_perfetto_trace_perfetto_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/perfetto:zero
-perfetto_proto_library(
-    name = "protos_perfetto_trace_perfetto_protos",
-    srcs = [
-        "protos/perfetto/trace/perfetto/perfetto_metatrace.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/perfetto:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_trace_perfetto_zero",
-    deps = [
-        ":protos_perfetto_trace_perfetto_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/power:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_trace_power_lite",
-    deps = [
-        ":protos_perfetto_trace_power_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/power:zero
-perfetto_proto_library(
-    name = "protos_perfetto_trace_power_protos",
-    srcs = [
-        "protos/perfetto/trace/power/battery_counters.proto",
-        "protos/perfetto/trace/power/power_rails.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/power:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_trace_power_zero",
-    deps = [
-        ":protos_perfetto_trace_power_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace_processor:metrics_impl_zero
-perfetto_proto_library(
-    name = "protos_perfetto_trace_processor_metrics_impl_protos",
-    srcs = [
-        "protos/perfetto/trace_processor/metrics_impl.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/trace_processor:metrics_impl_zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_trace_processor_metrics_impl_zero",
-    deps = [
-        ":protos_perfetto_trace_processor_metrics_impl_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace_processor:zero
-perfetto_proto_library(
-    name = "protos_perfetto_trace_processor_protos",
-    srcs = [
-        "protos/perfetto/trace_processor/trace_processor.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/trace_processor:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_trace_processor_zero",
-    deps = [
-        ":protos_perfetto_trace_processor_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/profiling:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_trace_profiling_lite",
-    deps = [
-        ":protos_perfetto_trace_profiling_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/profiling:zero
-perfetto_proto_library(
-    name = "protos_perfetto_trace_profiling_protos",
-    srcs = [
-        "protos/perfetto/trace/profiling/heap_graph.proto",
-        "protos/perfetto/trace/profiling/profile_common.proto",
-        "protos/perfetto/trace/profiling/profile_packet.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/profiling:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_trace_profiling_zero",
-    deps = [
-        ":protos_perfetto_trace_profiling_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/ps:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_trace_ps_lite",
-    deps = [
-        ":protos_perfetto_trace_ps_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/ps:zero
-perfetto_proto_library(
-    name = "protos_perfetto_trace_ps_protos",
-    srcs = [
-        "protos/perfetto/trace/ps/process_stats.proto",
-        "protos/perfetto/trace/ps/process_tree.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/ps:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_trace_ps_zero",
-    deps = [
-        ":protos_perfetto_trace_ps_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/sys_stats:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_trace_sys_stats_lite",
-    deps = [
-        ":protos_perfetto_trace_sys_stats_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/sys_stats:zero
-perfetto_proto_library(
-    name = "protos_perfetto_trace_sys_stats_protos",
-    srcs = [
-        "protos/perfetto/trace/sys_stats/sys_stats.proto",
-    ],
-    deps = [
-        ":protos_perfetto_common_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/sys_stats:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_trace_sys_stats_zero",
-    deps = [
-        ":protos_perfetto_trace_sys_stats_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/track_event:lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_trace_track_event_lite",
-    deps = [
-        ":protos_perfetto_trace_track_event_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/track_event:zero
-perfetto_proto_library(
-    name = "protos_perfetto_trace_track_event_protos",
-    srcs = [
-        "protos/perfetto/trace/track_event/debug_annotation.proto",
-        "protos/perfetto/trace/track_event/log_message.proto",
-        "protos/perfetto/trace/track_event/process_descriptor.proto",
-        "protos/perfetto/trace/track_event/source_location.proto",
-        "protos/perfetto/trace/track_event/task_execution.proto",
-        "protos/perfetto/trace/track_event/thread_descriptor.proto",
-        "protos/perfetto/trace/track_event/track_descriptor.proto",
-        "protos/perfetto/trace/track_event/track_event.proto",
-    ],
-)
-
-# GN target: //protos/perfetto/trace/track_event:zero
-perfetto_cc_protozero_library(
-    name = "protos_perfetto_trace_track_event_zero",
-    deps = [
-        ":protos_perfetto_trace_track_event_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace:trusted_lite
-perfetto_cc_proto_library(
-    name = "protos_perfetto_trace_trusted_lite",
-    deps = [
-        ":protos_perfetto_trace_trusted_protos",
-    ],
-)
-
-# GN target: //protos/perfetto/trace:trusted_lite
-perfetto_proto_library(
-    name = "protos_perfetto_trace_trusted_protos",
-    srcs = [
-        "protos/perfetto/trace/trusted_packet.proto",
-    ],
-    deps = [
-        ":protos_perfetto_common_protos",
-        ":protos_perfetto_config_android_protos",
-        ":protos_perfetto_config_ftrace_protos",
-        ":protos_perfetto_config_gpu_protos",
-        ":protos_perfetto_config_inode_file_protos",
-        ":protos_perfetto_config_power_protos",
-        ":protos_perfetto_config_process_stats_protos",
-        ":protos_perfetto_config_profiling_protos",
-        ":protos_perfetto_config_protos",
-        ":protos_perfetto_config_sys_stats_protos",
-        ":protos_perfetto_trace_minimal_protos",
-    ],
-)
-
-# GN target: //protos/third_party/pprof:lite
-perfetto_cc_proto_library(
-    name = "protos_third_party_pprof_lite",
-    deps = [
-        ":protos_third_party_pprof_protos",
-    ],
-)
-
-# GN target: //protos/third_party/pprof:lite
-perfetto_proto_library(
-    name = "protos_third_party_pprof_protos",
-    srcs = [
-        "protos/third_party/pprof/profile.proto",
-    ],
-)
-
-# GN target: //src/perfetto_cmd:protos
-perfetto_cc_proto_library(
-    name = "src_perfetto_cmd_protos",
-    deps = [
-        ":src_perfetto_cmd_protos_protos",
-    ],
-)
-
-# GN target: //src/perfetto_cmd:protos
-perfetto_proto_library(
-    name = "src_perfetto_cmd_protos_protos",
-    srcs = [
-        "src/perfetto_cmd/perfetto_cmd_state.proto",
-    ],
-)
-
-# ##############################################################################
-# Public targets
-# ##############################################################################
-
-# GN target: //:libperfetto_client_experimental
-perfetto_cc_library(
-    name = "libperfetto_client_experimental",
-    srcs = [
-        "include/perfetto/tracing.h",
-        ":src_base_base",
-        ":src_base_unix_socket",
-        ":src_ipc_ipc",
-        ":src_protozero_protozero",
-        ":src_tracing_client_api",
-        ":src_tracing_common",
-        ":src_tracing_ipc",
-        ":src_tracing_platform_posix",
-        ":src_tracing_tracing",
-    ],
-    hdrs = [
-        ":include_perfetto_base_base",
-        ":include_perfetto_ext_base_base",
-        ":include_perfetto_ext_ipc_ipc",
-        ":include_perfetto_ext_tracing_core_core",
-        ":include_perfetto_ext_tracing_ipc_ipc",
-        ":include_perfetto_protozero_protozero",
-        ":include_perfetto_tracing_core_core",
-        ":include_perfetto_tracing_tracing",
-    ],
-    visibility = [
-        "//visibility:public",
-    ],
-    deps = [
-        ":protos_perfetto_common_cpp",
-        ":protos_perfetto_common_lite",
-        ":protos_perfetto_common_zero",
-        ":protos_perfetto_config_android_cpp",
-        ":protos_perfetto_config_android_lite",
-        ":protos_perfetto_config_android_zero",
-        ":protos_perfetto_config_cpp",
-        ":protos_perfetto_config_ftrace_cpp",
-        ":protos_perfetto_config_ftrace_lite",
-        ":protos_perfetto_config_ftrace_zero",
-        ":protos_perfetto_config_gpu_cpp",
-        ":protos_perfetto_config_gpu_lite",
-        ":protos_perfetto_config_gpu_zero",
-        ":protos_perfetto_config_inode_file_cpp",
-        ":protos_perfetto_config_inode_file_lite",
-        ":protos_perfetto_config_inode_file_zero",
-        ":protos_perfetto_config_lite",
-        ":protos_perfetto_config_power_cpp",
-        ":protos_perfetto_config_power_lite",
-        ":protos_perfetto_config_power_zero",
-        ":protos_perfetto_config_process_stats_cpp",
-        ":protos_perfetto_config_process_stats_lite",
-        ":protos_perfetto_config_process_stats_zero",
-        ":protos_perfetto_config_profiling_cpp",
-        ":protos_perfetto_config_profiling_lite",
-        ":protos_perfetto_config_profiling_zero",
-        ":protos_perfetto_config_sys_stats_cpp",
-        ":protos_perfetto_config_sys_stats_lite",
-        ":protos_perfetto_config_sys_stats_zero",
-        ":protos_perfetto_config_zero",
-        ":protos_perfetto_ipc_ipc",
-        ":protos_perfetto_ipc_wire_protocol",
-        ":protos_perfetto_trace_android_zero",
-        ":protos_perfetto_trace_chrome_zero",
-        ":protos_perfetto_trace_filesystem_zero",
-        ":protos_perfetto_trace_ftrace_zero",
-        ":protos_perfetto_trace_gpu_zero",
-        ":protos_perfetto_trace_interned_data_zero",
-        ":protos_perfetto_trace_minimal_lite",
-        ":protos_perfetto_trace_minimal_zero",
-        ":protos_perfetto_trace_non_minimal_zero",
-        ":protos_perfetto_trace_perfetto_zero",
-        ":protos_perfetto_trace_power_zero",
-        ":protos_perfetto_trace_profiling_zero",
-        ":protos_perfetto_trace_ps_zero",
-        ":protos_perfetto_trace_sys_stats_zero",
-        ":protos_perfetto_trace_track_event_zero",
-        ":protos_perfetto_trace_trusted_lite",
-    ] + PERFETTO_CONFIG.deps.protobuf_lite,
-)
-
-# GN target: //src/perfetto_cmd:perfetto
-perfetto_cc_binary(
-    name = "perfetto",
-    srcs = [
-        "src/perfetto_cmd/main.cc",
-        ":include_perfetto_base_base",
-        ":include_perfetto_ext_base_base",
-        ":include_perfetto_ext_ipc_ipc",
-        ":include_perfetto_ext_traced_traced",
-        ":include_perfetto_ext_tracing_core_core",
-        ":include_perfetto_ext_tracing_ipc_ipc",
-        ":include_perfetto_protozero_protozero",
-        ":include_perfetto_tracing_core_core",
-        ":include_perfetto_tracing_tracing",
-        ":src_android_internal_headers",
-        ":src_android_internal_lazy_library_loader",
-        ":src_base_base",
-        ":src_base_unix_socket",
-        ":src_ipc_ipc",
-        ":src_perfetto_cmd_perfetto_cmd",
-        ":src_perfetto_cmd_trigger_producer",
-        ":src_protozero_protozero",
-        ":src_tracing_common",
-        ":src_tracing_ipc",
-        ":src_tracing_tracing",
-    ],
-    visibility = [
-        "//visibility:public",
-    ],
-    deps = [
-               ":protos_perfetto_common_cpp",
-               ":protos_perfetto_common_lite",
-               ":protos_perfetto_common_zero",
-               ":protos_perfetto_config_android_cpp",
-               ":protos_perfetto_config_android_lite",
-               ":protos_perfetto_config_android_zero",
-               ":protos_perfetto_config_cpp",
-               ":protos_perfetto_config_ftrace_cpp",
-               ":protos_perfetto_config_ftrace_lite",
-               ":protos_perfetto_config_ftrace_zero",
-               ":protos_perfetto_config_gpu_cpp",
-               ":protos_perfetto_config_gpu_lite",
-               ":protos_perfetto_config_gpu_zero",
-               ":protos_perfetto_config_inode_file_cpp",
-               ":protos_perfetto_config_inode_file_lite",
-               ":protos_perfetto_config_inode_file_zero",
-               ":protos_perfetto_config_lite",
-               ":protos_perfetto_config_power_cpp",
-               ":protos_perfetto_config_power_lite",
-               ":protos_perfetto_config_power_zero",
-               ":protos_perfetto_config_process_stats_cpp",
-               ":protos_perfetto_config_process_stats_lite",
-               ":protos_perfetto_config_process_stats_zero",
-               ":protos_perfetto_config_profiling_cpp",
-               ":protos_perfetto_config_profiling_lite",
-               ":protos_perfetto_config_profiling_zero",
-               ":protos_perfetto_config_sys_stats_cpp",
-               ":protos_perfetto_config_sys_stats_lite",
-               ":protos_perfetto_config_sys_stats_zero",
-               ":protos_perfetto_config_zero",
-               ":protos_perfetto_ipc_ipc",
-               ":protos_perfetto_ipc_wire_protocol",
-               ":protos_perfetto_trace_android_zero",
-               ":protos_perfetto_trace_chrome_zero",
-               ":protos_perfetto_trace_filesystem_zero",
-               ":protos_perfetto_trace_ftrace_zero",
-               ":protos_perfetto_trace_gpu_zero",
-               ":protos_perfetto_trace_interned_data_zero",
-               ":protos_perfetto_trace_minimal_lite",
-               ":protos_perfetto_trace_minimal_zero",
-               ":protos_perfetto_trace_non_minimal_zero",
-               ":protos_perfetto_trace_perfetto_zero",
-               ":protos_perfetto_trace_power_zero",
-               ":protos_perfetto_trace_profiling_zero",
-               ":protos_perfetto_trace_ps_zero",
-               ":protos_perfetto_trace_sys_stats_zero",
-               ":protos_perfetto_trace_track_event_zero",
-               ":protos_perfetto_trace_trusted_lite",
-               ":src_perfetto_cmd_protos",
-           ] + PERFETTO_CONFIG.deps.protobuf_lite +
-           PERFETTO_CONFIG.deps.zlib,
-)
-
-# GN target: //src/trace_processor:trace_processor
-perfetto_cc_library(
-    name = "trace_processor",
-    srcs = [
-        ":src_base_base",
-        ":src_protozero_protozero",
-        ":src_trace_processor_common",
-        ":src_trace_processor_db_lib",
-        ":src_trace_processor_export_json",
-        ":src_trace_processor_lib",
-        ":src_trace_processor_metrics_lib",
-        ":src_trace_processor_sqlite_sqlite",
-        ":src_trace_processor_storage",
-        ":src_trace_processor_tables_tables",
-    ],
-    hdrs = [
-        ":include_perfetto_base_base",
-        ":include_perfetto_ext_base_base",
-        ":include_perfetto_ext_trace_processor_export_json",
-        ":include_perfetto_ext_traced_sys_stats_counters",
-        ":include_perfetto_protozero_protozero",
-        ":include_perfetto_trace_processor_basic_types",
-        ":include_perfetto_trace_processor_storage",
-        ":include_perfetto_trace_processor_trace_processor",
-    ],
-    visibility = [
-        "//visibility:public",
-    ],
-    deps = [
-               ":protos_perfetto_common_zero",
-               ":protos_perfetto_config_android_zero",
-               ":protos_perfetto_config_ftrace_zero",
-               ":protos_perfetto_config_gpu_zero",
-               ":protos_perfetto_config_inode_file_zero",
-               ":protos_perfetto_config_power_zero",
-               ":protos_perfetto_config_process_stats_zero",
-               ":protos_perfetto_config_profiling_zero",
-               ":protos_perfetto_config_sys_stats_zero",
-               ":protos_perfetto_config_zero",
-               ":protos_perfetto_metrics_android_zero",
-               ":protos_perfetto_metrics_zero",
-               ":protos_perfetto_trace_android_zero",
-               ":protos_perfetto_trace_chrome_zero",
-               ":protos_perfetto_trace_filesystem_zero",
-               ":protos_perfetto_trace_ftrace_zero",
-               ":protos_perfetto_trace_gpu_zero",
-               ":protos_perfetto_trace_interned_data_zero",
-               ":protos_perfetto_trace_minimal_zero",
-               ":protos_perfetto_trace_non_minimal_zero",
-               ":protos_perfetto_trace_perfetto_zero",
-               ":protos_perfetto_trace_power_zero",
-               ":protos_perfetto_trace_processor_metrics_impl_zero",
-               ":protos_perfetto_trace_profiling_zero",
-               ":protos_perfetto_trace_ps_zero",
-               ":protos_perfetto_trace_sys_stats_zero",
-               ":protos_perfetto_trace_track_event_zero",
-           ] + PERFETTO_CONFIG.deps.jsoncpp +
-           PERFETTO_CONFIG.deps.sqlite +
-           PERFETTO_CONFIG.deps.sqlite_ext_percentile +
-           PERFETTO_CONFIG.deps.zlib + [
-        ":cc_merged_sql_metrics",
-    ],
-)
-
-# GN target: //src/trace_processor:trace_processor_shell
-perfetto_cc_binary(
-    name = "trace_processor_shell",
-    srcs = [
-        "src/trace_processor/proto_to_json.cc",
-        "src/trace_processor/proto_to_json.h",
-        "src/trace_processor/trace_processor_shell.cc",
-        ":include_perfetto_base_base",
-        ":include_perfetto_ext_base_base",
-        ":include_perfetto_ext_trace_processor_export_json",
-        ":include_perfetto_ext_traced_sys_stats_counters",
-        ":include_perfetto_protozero_protozero",
-        ":include_perfetto_trace_processor_basic_types",
-        ":include_perfetto_trace_processor_storage",
-        ":include_perfetto_trace_processor_trace_processor",
-        ":src_base_base",
-        ":src_base_unix_socket",
-        ":src_protozero_protozero",
-        ":src_trace_processor_common",
-        ":src_trace_processor_db_lib",
-        ":src_trace_processor_export_json",
-        ":src_trace_processor_lib",
-        ":src_trace_processor_metrics_lib",
-        ":src_trace_processor_rpc_httpd",
-        ":src_trace_processor_rpc_rpc",
-        ":src_trace_processor_sqlite_sqlite",
-        ":src_trace_processor_storage",
-        ":src_trace_processor_tables_tables",
-    ],
-    visibility = [
-        "//visibility:public",
-    ],
-    deps = [
-               ":protos_perfetto_common_zero",
-               ":protos_perfetto_config_android_zero",
-               ":protos_perfetto_config_ftrace_zero",
-               ":protos_perfetto_config_gpu_zero",
-               ":protos_perfetto_config_inode_file_zero",
-               ":protos_perfetto_config_power_zero",
-               ":protos_perfetto_config_process_stats_zero",
-               ":protos_perfetto_config_profiling_zero",
-               ":protos_perfetto_config_sys_stats_zero",
-               ":protos_perfetto_config_zero",
-               ":protos_perfetto_metrics_android_zero",
-               ":protos_perfetto_metrics_zero",
-               ":protos_perfetto_trace_android_zero",
-               ":protos_perfetto_trace_chrome_zero",
-               ":protos_perfetto_trace_filesystem_zero",
-               ":protos_perfetto_trace_ftrace_zero",
-               ":protos_perfetto_trace_gpu_zero",
-               ":protos_perfetto_trace_interned_data_zero",
-               ":protos_perfetto_trace_minimal_zero",
-               ":protos_perfetto_trace_non_minimal_zero",
-               ":protos_perfetto_trace_perfetto_zero",
-               ":protos_perfetto_trace_power_zero",
-               ":protos_perfetto_trace_processor_metrics_impl_zero",
-               ":protos_perfetto_trace_processor_zero",
-               ":protos_perfetto_trace_profiling_zero",
-               ":protos_perfetto_trace_ps_zero",
-               ":protos_perfetto_trace_sys_stats_zero",
-               ":protos_perfetto_trace_track_event_zero",
-           ] + PERFETTO_CONFIG.deps.jsoncpp +
-           PERFETTO_CONFIG.deps.linenoise +
-           PERFETTO_CONFIG.deps.protoc_lib +
-           PERFETTO_CONFIG.deps.sqlite +
-           PERFETTO_CONFIG.deps.sqlite_ext_percentile +
-           PERFETTO_CONFIG.deps.zlib + [
-        ":cc_merged_sql_metrics",
-    ],
-)
-
-# GN target: //src/traced/probes:traced_probes
-perfetto_cc_binary(
-    name = "traced_probes",
-    srcs = [
-        "src/traced/probes/main.cc",
-        ":include_perfetto_ext_traced_traced",
-    ],
-    visibility = [
-        "//visibility:public",
-    ],
-    deps = [
-        ":libperfetto",
-    ],
-)
-
-# GN target: //src/traced/service:traced
-perfetto_cc_binary(
-    name = "traced",
-    srcs = [
-        "src/traced/service/main.cc",
-        ":include_perfetto_ext_traced_traced",
-    ],
-    visibility = [
-        "//visibility:public",
-    ],
-    deps = [
-        ":libperfetto",
-    ],
-)
-
-# GN target: //tools/trace_to_text:libpprofbuilder
-perfetto_cc_library(
-    name = "libpprofbuilder",
-    srcs = [
-        ":src_base_base",
-        ":src_protozero_protozero",
-        ":src_trace_processor_common",
-        ":src_trace_processor_db_lib",
-        ":src_trace_processor_export_json",
-        ":src_trace_processor_lib",
-        ":src_trace_processor_metrics_lib",
-        ":src_trace_processor_sqlite_sqlite",
-        ":src_trace_processor_storage",
-        ":src_trace_processor_tables_tables",
-        ":tools_trace_to_text_pprofbuilder",
-        ":tools_trace_to_text_symbolizer",
-        ":tools_trace_to_text_utils",
-    ],
-    hdrs = [
-        ":include_perfetto_base_base",
-        ":include_perfetto_ext_base_base",
-        ":include_perfetto_ext_trace_processor_export_json",
-        ":include_perfetto_ext_traced_sys_stats_counters",
-        ":include_perfetto_profiling_symbolizer",
-        ":include_perfetto_protozero_protozero",
-        ":include_perfetto_trace_processor_basic_types",
-        ":include_perfetto_trace_processor_storage",
-        ":include_perfetto_trace_processor_trace_processor",
-    ],
-    visibility = [
-        "//visibility:public",
-    ],
-    deps = [
-               ":protos_perfetto_common_lite",
-               ":protos_perfetto_common_zero",
-               ":protos_perfetto_config_android_lite",
-               ":protos_perfetto_config_android_zero",
-               ":protos_perfetto_config_ftrace_lite",
-               ":protos_perfetto_config_ftrace_zero",
-               ":protos_perfetto_config_gpu_lite",
-               ":protos_perfetto_config_gpu_zero",
-               ":protos_perfetto_config_inode_file_lite",
-               ":protos_perfetto_config_inode_file_zero",
-               ":protos_perfetto_config_lite",
-               ":protos_perfetto_config_power_lite",
-               ":protos_perfetto_config_power_zero",
-               ":protos_perfetto_config_process_stats_lite",
-               ":protos_perfetto_config_process_stats_zero",
-               ":protos_perfetto_config_profiling_lite",
-               ":protos_perfetto_config_profiling_zero",
-               ":protos_perfetto_config_sys_stats_lite",
-               ":protos_perfetto_config_sys_stats_zero",
-               ":protos_perfetto_config_zero",
-               ":protos_perfetto_metrics_android_zero",
-               ":protos_perfetto_metrics_zero",
-               ":protos_perfetto_trace_android_lite",
-               ":protos_perfetto_trace_android_zero",
-               ":protos_perfetto_trace_chrome_lite",
-               ":protos_perfetto_trace_chrome_zero",
-               ":protos_perfetto_trace_filesystem_lite",
-               ":protos_perfetto_trace_filesystem_zero",
-               ":protos_perfetto_trace_ftrace_lite",
-               ":protos_perfetto_trace_ftrace_zero",
-               ":protos_perfetto_trace_gpu_lite",
-               ":protos_perfetto_trace_gpu_zero",
-               ":protos_perfetto_trace_interned_data_lite",
-               ":protos_perfetto_trace_interned_data_zero",
-               ":protos_perfetto_trace_minimal_lite",
-               ":protos_perfetto_trace_minimal_zero",
-               ":protos_perfetto_trace_non_minimal_lite",
-               ":protos_perfetto_trace_non_minimal_zero",
-               ":protos_perfetto_trace_perfetto_lite",
-               ":protos_perfetto_trace_perfetto_zero",
-               ":protos_perfetto_trace_power_lite",
-               ":protos_perfetto_trace_power_zero",
-               ":protos_perfetto_trace_processor_metrics_impl_zero",
-               ":protos_perfetto_trace_profiling_lite",
-               ":protos_perfetto_trace_profiling_zero",
-               ":protos_perfetto_trace_ps_lite",
-               ":protos_perfetto_trace_ps_zero",
-               ":protos_perfetto_trace_sys_stats_lite",
-               ":protos_perfetto_trace_sys_stats_zero",
-               ":protos_perfetto_trace_track_event_lite",
-               ":protos_perfetto_trace_track_event_zero",
-               ":protos_third_party_pprof_lite",
-           ] + PERFETTO_CONFIG.deps.jsoncpp +
-           PERFETTO_CONFIG.deps.sqlite +
-           PERFETTO_CONFIG.deps.sqlite_ext_percentile +
-           PERFETTO_CONFIG.deps.zlib + [
-        ":cc_merged_sql_metrics",
-    ],
-)
-
-# GN target: //tools/trace_to_text:trace_to_text
-perfetto_cc_binary(
-    name = "trace_to_text",
-    srcs = [
-        ":include_perfetto_base_base",
-        ":include_perfetto_ext_base_base",
-        ":include_perfetto_ext_trace_processor_export_json",
-        ":include_perfetto_ext_traced_sys_stats_counters",
-        ":include_perfetto_profiling_symbolizer",
-        ":include_perfetto_protozero_protozero",
-        ":include_perfetto_trace_processor_basic_types",
-        ":include_perfetto_trace_processor_storage",
-        ":include_perfetto_trace_processor_trace_processor",
-        ":src_base_base",
-        ":src_protozero_protozero",
-        ":src_trace_processor_common",
-        ":src_trace_processor_db_lib",
-        ":src_trace_processor_export_json",
-        ":src_trace_processor_lib",
-        ":src_trace_processor_metrics_lib",
-        ":src_trace_processor_sqlite_sqlite",
-        ":src_trace_processor_storage",
-        ":src_trace_processor_tables_tables",
-        ":tools_trace_to_text_common",
-        ":tools_trace_to_text_full",
-        ":tools_trace_to_text_local_symbolizer",
-        ":tools_trace_to_text_pprofbuilder",
-        ":tools_trace_to_text_symbolizer",
-        ":tools_trace_to_text_utils",
-    ],
-    visibility = [
-        "//visibility:public",
-    ],
-    deps = [
-               ":protos_perfetto_common_lite",
-               ":protos_perfetto_common_zero",
-               ":protos_perfetto_config_android_lite",
-               ":protos_perfetto_config_android_zero",
-               ":protos_perfetto_config_ftrace_lite",
-               ":protos_perfetto_config_ftrace_zero",
-               ":protos_perfetto_config_gpu_lite",
-               ":protos_perfetto_config_gpu_zero",
-               ":protos_perfetto_config_inode_file_lite",
-               ":protos_perfetto_config_inode_file_zero",
-               ":protos_perfetto_config_lite",
-               ":protos_perfetto_config_power_lite",
-               ":protos_perfetto_config_power_zero",
-               ":protos_perfetto_config_process_stats_lite",
-               ":protos_perfetto_config_process_stats_zero",
-               ":protos_perfetto_config_profiling_lite",
-               ":protos_perfetto_config_profiling_zero",
-               ":protos_perfetto_config_sys_stats_lite",
-               ":protos_perfetto_config_sys_stats_zero",
-               ":protos_perfetto_config_zero",
-               ":protos_perfetto_metrics_android_zero",
-               ":protos_perfetto_metrics_zero",
-               ":protos_perfetto_trace_android_lite",
-               ":protos_perfetto_trace_android_zero",
-               ":protos_perfetto_trace_chrome_lite",
-               ":protos_perfetto_trace_chrome_zero",
-               ":protos_perfetto_trace_filesystem_lite",
-               ":protos_perfetto_trace_filesystem_zero",
-               ":protos_perfetto_trace_ftrace_lite",
-               ":protos_perfetto_trace_ftrace_zero",
-               ":protos_perfetto_trace_gpu_lite",
-               ":protos_perfetto_trace_gpu_zero",
-               ":protos_perfetto_trace_interned_data_lite",
-               ":protos_perfetto_trace_interned_data_zero",
-               ":protos_perfetto_trace_minimal_lite",
-               ":protos_perfetto_trace_minimal_zero",
-               ":protos_perfetto_trace_non_minimal_lite",
-               ":protos_perfetto_trace_non_minimal_zero",
-               ":protos_perfetto_trace_perfetto_lite",
-               ":protos_perfetto_trace_perfetto_zero",
-               ":protos_perfetto_trace_power_lite",
-               ":protos_perfetto_trace_power_zero",
-               ":protos_perfetto_trace_processor_metrics_impl_zero",
-               ":protos_perfetto_trace_profiling_lite",
-               ":protos_perfetto_trace_profiling_zero",
-               ":protos_perfetto_trace_ps_lite",
-               ":protos_perfetto_trace_ps_zero",
-               ":protos_perfetto_trace_sys_stats_lite",
-               ":protos_perfetto_trace_sys_stats_zero",
-               ":protos_perfetto_trace_track_event_lite",
-               ":protos_perfetto_trace_track_event_zero",
-               ":protos_third_party_pprof_lite",
-           ] + PERFETTO_CONFIG.deps.jsoncpp +
-           PERFETTO_CONFIG.deps.protobuf_full +
-           PERFETTO_CONFIG.deps.sqlite +
-           PERFETTO_CONFIG.deps.sqlite_ext_percentile +
-           PERFETTO_CONFIG.deps.zlib + [
-        ":cc_merged_sql_metrics",
-    ],
-)
-
-# Content from BUILD.extras
-
-build_config_dir_ = "include/perfetto/base/build_configs/bazel"
-
-# Deliberately NOT a perfetto_cc_library, to avoid cyclic deps.
-# This is pulled as a default dep by all targets.
-cc_library(
-    name = "build_config_hdr",
-    hdrs = [build_config_dir_ + "/perfetto_build_flags.h"],
-    includes = [build_config_dir_],
-)
-
-perfetto_cc_library(
-    name = "cc_merged_sql_metrics",
-    hdrs = ["src/trace_processor/metrics/sql_metrics.h"],
-)
-
-perfetto_py_binary(
-    name = "gen_merged_sql_metrics_py",
-    srcs = [
-        "tools/gen_merged_sql_metrics.py",
-    ],
-    main = "tools/gen_merged_sql_metrics.py",
-    python_version = "PY2",
-)
-
-perfetto_java_proto_library(
-    name = "protos_perfetto_metrics_java",
-    deps = [
-        ":protos_perfetto_metrics_protos",
-    ],
-)
-
-perfetto_java_proto_library(
-    name = "protos_perfetto_metrics_android_java",
-    deps = [
-        ":protos_perfetto_metrics_android_protos",
-    ],
-)
-
-perfetto_java_proto_library(
-    name = "protos_perfetto_trace_merged_trace_java",
-    deps = [
-        ":protos_perfetto_trace_merged_trace_protos",
-    ],
-)
-
-perfetto_gensignature_internal_only(
+gensignature(
     name = "trace_processor_sig",
     srcs = [
         ":trace_processor_shell",
@@ -2795,3 +786,32 @@
         "__TRACE_PROCESSOR_SIG_TAG2",
     ],
 )
+
+py_binary(
+    name = "gen_merged_sql_metrics_py",
+    srcs = [
+        "tools/gen_merged_sql_metrics.py",
+    ],
+    main = "tools/gen_merged_sql_metrics.py",
+)
+
+load("//security/fuzzing/blaze:cc_fuzz_target.bzl", "cc_fuzz_target")
+
+cc_fuzz_target(
+    name = "trace_parsing_fuzzer",
+    srcs = ["src/trace_processor/trace_parsing_fuzzer.cc"],
+    componentid = 323270,
+    deps = [
+        ":trace_processor",
+        "//third_party/perfetto/protos:trace_processor_cc_proto",
+    ],
+)
+
+cc_fuzz_target(
+    name = "proto_decoder_fuzzer",
+    srcs = ["src/protozero/proto_decoder_fuzzer.cc"],
+    componentid = 323270,
+    deps = [
+        ":trace_processor",
+    ],
+)
diff --git a/BUILD.extras b/BUILD.extras
index 732f3f8..d18d9a2 100644
--- a/BUILD.extras
+++ b/BUILD.extras
@@ -1,49 +1,4 @@
-build_config_dir_ = "include/perfetto/base/build_configs/bazel"
-
-# Deliberately NOT a perfetto_cc_library, to avoid cyclic deps.
-# This is pulled as a default dep by all targets.
-cc_library(
-    name = "build_config_hdr",
-    hdrs = [build_config_dir_ + "/perfetto_build_flags.h"],
-    includes = [build_config_dir_],
-)
-
-perfetto_cc_library(
-    name = "cc_merged_sql_metrics",
-    hdrs = ["src/trace_processor/metrics/sql_metrics.h"],
-)
-
-perfetto_py_binary(
-    name = "gen_merged_sql_metrics_py",
-    srcs = [
-        "tools/gen_merged_sql_metrics.py",
-    ],
-    main = "tools/gen_merged_sql_metrics.py",
-    python_version = "PY2",
-)
-
-perfetto_java_proto_library(
-    name = "protos_perfetto_metrics_java",
-    deps = [
-        ":protos_perfetto_metrics_protos",
-    ],
-)
-
-perfetto_java_proto_library(
-    name = "protos_perfetto_metrics_android_java",
-    deps = [
-        ":protos_perfetto_metrics_android_protos",
-    ],
-)
-
-perfetto_java_proto_library(
-    name = "protos_perfetto_trace_merged_trace_java",
-    deps = [
-        ":protos_perfetto_trace_merged_trace_protos",
-    ],
-)
-
-perfetto_gensignature_internal_only(
+gensignature(
     name = "trace_processor_sig",
     srcs = [
         ":trace_processor_shell",
@@ -54,3 +9,32 @@
         "__TRACE_PROCESSOR_SIG_TAG2",
     ],
 )
+
+py_binary(
+    name = "gen_merged_sql_metrics_py",
+    srcs = [
+        "tools/gen_merged_sql_metrics.py",
+    ],
+    main = "tools/gen_merged_sql_metrics.py",
+)
+
+load("//security/fuzzing/blaze:cc_fuzz_target.bzl", "cc_fuzz_target")
+
+cc_fuzz_target(
+    name = "trace_parsing_fuzzer",
+    srcs = ["src/trace_processor/trace_parsing_fuzzer.cc"],
+    componentid = 323270,
+    deps = [
+        ":trace_processor",
+        "//third_party/perfetto/protos:trace_processor_cc_proto",
+    ],
+)
+
+cc_fuzz_target(
+    name = "proto_decoder_fuzzer",
+    srcs = ["src/protozero/proto_decoder_fuzzer.cc"],
+    componentid = 323270,
+    deps = [
+        ":trace_processor",
+    ],
+)
diff --git a/BUILD.gn b/BUILD.gn
index 965d68e..d23019f 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -15,200 +15,257 @@
 import("gn/perfetto.gni")
 import("gn/test.gni")
 
-# +----------------------------------------------------------------------------+
-# | "all" targets definition: defines targets reachable by the various configs |
-# +----------------------------------------------------------------------------+
-# There is a subtletly here related with chromium and other GN embedders.
-# When adding a dependency some_dir/:target_name, some_dir/BUILD.gn is
-# "discovered". As a side effect any *other* target defined in some_dir/BUILD.gn
-# (and its transitive dependencies) becomes implicitly part of the "default"
-# target, the one invoked running ninja -C out/xxx without further args.
-# Because of this, care must be taken to wrap dependencies to targets in other
-# build files with if (enable_xxx) flags. Accidentally including a harmless
-# target that happens to be defined in the same BUILD.gn that contains targets
-# incompatible with the chromium build will cause build/roll failures.
-
-all_targets = [ "protos/perfetto/trace:perfetto_trace_protos" ]
-
-if (enable_perfetto_platform_services) {
-  all_targets += [
-    "src/perfetto_cmd:perfetto",
-    "src/perfetto_cmd:trigger_perfetto",
-    "src/traced/service:traced",
-    "src/traced/probes:traced_probes",
-  ]
+if (perfetto_build_standalone || perfetto_build_with_android) {
+  import("//gn/standalone/android.gni")
+} else {
+  import("//build/config/android/config.gni")
 }
 
-if (enable_perfetto_trace_processor &&
-    enable_perfetto_trace_processor_metrics) {
-  all_targets += [ "src/trace_processor:trace_processor_shell" ]
+# For use_libfuzzer.
+if (perfetto_build_standalone || perfetto_build_with_android) {
+  import("//gn/standalone/sanitizers/vars.gni")
+} else {
+  import("//build/config/sanitizers/sanitizers.gni")
 }
 
-if (enable_perfetto_heapprofd) {
-  all_targets += [ "src/profiling/memory:heapprofd" ]
-  if (perfetto_build_with_android) {
-    all_targets += [ "src/profiling/memory:heapprofd_client" ]
-  }
+declare_args() {
+  # Only for local development. When true the binaries (perfetto, traced, ...)
+  # are monolithic and don't use a common shared library. This is mainly to
+  # avoid LD_LIBRARY_PATH dances when testing locally.
+  monolithic_binaries = false
+
+  # libunwindstack requires API level 26 or newer.
+  should_build_heapprofd =
+      (perfetto_build_standalone || perfetto_build_with_android) && is_clang &&
+      (is_linux || is_android) &&
+      (!is_android || android_api_level >= 26 || perfetto_build_with_android)
 }
-
-if (perfetto_build_with_android) {
-  all_targets += [ "src/android_internal/:libperfetto_android_internal" ]
-}
-
-if (enable_perfetto_tools) {
-  all_targets += [ "tools" ]
-}
-
-if (enable_perfetto_unittests) {
-  import("gn/perfetto_unittests.gni")
-  test("perfetto_unittests") {
-    deps = perfetto_unittests_targets
-  }
-  all_targets += [ ":perfetto_unittests" ]
-}
-
-if (enable_perfetto_integration_tests) {
-  import("gn/perfetto_integrationtests.gni")
-  test("perfetto_integrationtests") {
-    deps = perfetto_integrationtests_targets
-  }
-  all_targets += [
-    ":perfetto_integrationtests",
-    "test:client_api_example",
-  ]
-}
-
-if (enable_perfetto_benchmarks) {
-  import("gn/perfetto_benchmarks.gni")
-  executable("perfetto_benchmarks") {
-    testonly = true
-    deps = perfetto_benchmarks_targets
-  }
-  all_targets += [ ":perfetto_benchmarks" ]
-}
-
-if (enable_perfetto_fuzzers) {
-  import("gn/perfetto_fuzzers.gni")
-  group("fuzzers") {
-    testonly = true
-    deps = perfetto_fuzzers_targets
-  }
-  all_targets += [ ":fuzzers" ]
-}
-
-# Less interesting stuff that makes sense only in the standalone build, mainly
-# compile-time checks for the CI.
-if (perfetto_build_standalone) {
-  all_targets += [
-    "src/tracing:consumer_api_test",
-    "test/configs",
-
-    # For syntax-checking the proto.
-    "protos/perfetto/config:merged_config",
-    "protos/perfetto/trace:merged_trace",  # For syntax-checking the proto.
-
-    # For checking all generated xxx.gen.{cc,h} files without waiting for
-    # embedders to try to use them and fail.
-    "protos/perfetto/trace:cpp",
-    "protos/perfetto/config:cpp",
-    "protos/perfetto/common:cpp",
-
-    # The diff testing framework depends on these descriptors.
-    "protos/perfetto/metrics:descriptor($host_toolchain)",
-    "protos/perfetto/trace:descriptor($host_toolchain)",
-
-    # Used in the when updating the ftrace protos
-    "protos/perfetto/trace/ftrace:descriptor",
-  ]
-}
+assert(!monolithic_binaries || !perfetto_build_with_android)
 
 group("all") {
   testonly = true  # allow to build also test targets
-  deps = all_targets
+  deps = [
+    ":perfetto_unittests",
+    "src/protozero/protoc_plugin($host_toolchain)",
+  ]
+  if (perfetto_build_standalone || perfetto_build_with_android) {
+    deps += [
+      ":perfetto",
+      ":perfetto_integrationtests",
+      ":traced",
+      ":traced_probes",
+      ":trigger_perfetto",
+      "protos/perfetto/config:merged_config",  # For syntax-checking the proto.
+      "protos/perfetto/trace:merged_trace",  # For syntax-checking the proto.
+      "src/ipc/protoc_plugin:ipc_plugin($host_toolchain)",
+      "tools:protoc_helper",
+    ]
+    if (perfetto_build_standalone) {
+      deps += [
+        ":perfetto_benchmarks",
+        ":trace_processor",
+        "src/profiling/memory:ring_buffer",
+        "src/tracing:consumer_api_test",
+        "test/configs",
+        "tools/ftrace_proto_gen:ftrace_proto_gen",
+        "tools/proto_to_cpp",
+        "tools/trace_to_text",
+        "tools/trace_to_text:trace_to_text_lite_host($host_toolchain)",
+      ]
+      if (is_linux || is_android) {
+        deps += [ "tools/skippy" ]
+        deps += [ "tools/busy_threads" ]
+        deps += [ "tools/dump_ftrace_stats" ]
+      }
+      if (is_fuzzer) {
+        deps += [ ":fuzzers" ]
+      }
+    }
+  }
 }
 
-# This target is used when running ninja without any argument (by default would
-# build all reachable targets). This is mainly used to prevent the UI being
-# built when running ninja -C out/xxx.
-# This has effect only in standalone builds, no effect on chromium builds.
-# Chromium's "all" target depends on our "all" target above. However chromium's
-# "default" target depends on any target that we cause to be discovered by
-# depending on other GN files.
+# TODO(primiano): temporary workaround to:
+# 1) Prevent that the UI gets build automatically when doing ninja -C out/xx .
+# 2) Avoid breaking the chrome build, that right now depends on "all".
 group("default") {
-  testonly = true
+  testonly = true  # allow to build also test targets
   deps = [
     ":all",
   ]
 }
 
-# +----------------------------------------------------------------------------+
-# | Other definitions: root targets that don't belong to any other subdirectory|
-# +----------------------------------------------------------------------------+
-
-if (enable_perfetto_ui) {
+if (perfetto_build_standalone) {
   group("ui") {
     deps = [
       "ui",
     ]
   }
+
+  # The trace processor shell executable. An interactive shell that allows to
+  # make queries on the trace using the terminal.
+  group("trace_processor") {
+    deps = [
+      "src/trace_processor:trace_processor_shell",
+    ]
+  }
 }
 
-# In Android builds, we build the code of traced and traced_probes in one shared
-# library that exposes one xxx_main() for each. The executables themselves are
-# tiny shells that just invoke their own entry point into the library.
-# This is done merely for saving binary size, because the three binaries happen
-# to share a lot of code.
-# When setting monolithic_binaries=true (only supported in standalone builds)
-# it builds more conventional executables, where each binary has the full
-# implementation and no shared library dependency. This is to make dev cycles
-# on Android faster, avoiding all the LD_LIBRARY_PATH boilerplate.
-# libperfetto.so is also used for stuff that is exposed to the rest of the
-# Android tree.
-if (enable_perfetto_platform_services) {
+test("perfetto_unittests") {
+  deps = [
+    "gn:default_deps",
+    "gn:gtest_main",
+    "src/base:unittests",
+    "src/protozero:unittests",
+    "src/tracing:unittests",
+  ]
+
+  if (perfetto_build_standalone || perfetto_build_with_android) {
+    deps += [
+      "src/ipc:unittests",
+      "src/perfetto_cmd:unittests",
+      "src/profiling/memory:ring_buffer_unittests",
+      "src/traced/probes:unittests",
+      "src/traced/probes/filesystem:unittests",
+      "src/traced/probes/ftrace:unittests",
+      "src/traced/service:unittests",
+      "tools/ftrace_proto_gen:unittests",
+      "tools/sanitizers_unittests",
+    ]
+  }
+  if (should_build_heapprofd) {
+    # Restrict to clang, as libunwindstack and its dependencies is never
+    # built using GCC in the Android tree.
+    deps += [ "src/profiling/memory:unittests" ]
+  }
+  if (perfetto_build_standalone && !is_android) {
+    deps += [
+      "src/trace_processor:unittests",
+    ]
+  }
+}
+
+if (perfetto_build_standalone || perfetto_build_with_android) {
+  test("perfetto_integrationtests") {
+    deps = [
+      "gn:default_deps",
+      "gn:gtest_main",
+      "src/traced/probes/ftrace:integrationtests",
+      "test:end_to_end_integrationtests",
+    ]
+    if (perfetto_build_standalone && !is_android) {
+      deps += [ "src/trace_processor:integrationtests" ]
+    }
+
+    # TODO(fmayer): Fix in process daemons.
+    if (should_build_heapprofd && is_android && !start_daemons_for_testing) {
+      deps += [ "src/profiling/memory:end_to_end_tests" ]
+    }
+  }
+
   if (monolithic_binaries) {
-    libperfetto_target_type = "static_library"
+    libperfetto_target_type = "source_set"
   } else {
     libperfetto_target_type = "shared_library"
   }
 
   target(libperfetto_target_type, "libperfetto") {
-    if (libperfetto_target_type == "static_library") {
-      complete_static_lib = true
-    }
     deps = [
       "gn:default_deps",
       "src/traced/probes",
       "src/traced/service",
-      "src/tracing:consumer_api_deprecated",
+      "src/tracing:api",
     ]
   }
-}
 
-if (!build_with_chromium) {
-  # Client library target.
-  # Still in experimental stage and not API stable yet.
-  # See "libperfetto_client_example" (in Android.bp.extras) for an example
-  # on how to use the Perfetto Client API from the android tree.
-  static_library("libperfetto_client_experimental") {
-    complete_static_lib = true
+  # The unprivileged trace daemon that listens for Producer and Consumer
+  # connections, handles the coordination of the tracing sessions and owns the
+  # log buffers.
+  executable("traced") {
     deps = [
+      ":libperfetto",
       "gn:default_deps",
-      "src/tracing",
-      "src/tracing:client_api",
-      "src/tracing:platform_posix",
+      "include/perfetto/traced",
     ]
     sources = [
-      "include/perfetto/tracing.h",
+      "src/traced/service/main.cc",
     ]
   }
-}
 
-# TODO(primiano): there seem to be two "libperfetto" and one
-# "libperfetto_client_experimental" targets defined within this BUILD.gn file.
-# Rationalize them with eseckler@. For now seems this one is only used from
-# chromium and the other one only from the Android tree.
-if (build_with_chromium) {
-  component("libperfetto") {
+  # The unprivileged daemon that is allowed to access tracefs (for ftrace).
+  # Registers as a Producer on the traced daemon.
+  executable("traced_probes") {
+    deps = [
+      ":libperfetto",
+      "gn:default_deps",
+      "include/perfetto/traced",
+    ]
+    sources = [
+      "src/traced/probes/main.cc",
+    ]
+  }
+
+  # The command line client for Perfetto. Allows to configure / start / stop
+  # tracing, acting as a Consumer.
+  executable("perfetto") {
+    deps = [
+      "gn:default_deps",
+      "src/perfetto_cmd",
+    ]
+    sources = [
+      "src/perfetto_cmd/main.cc",
+    ]
+  }
+
+  # Tool to finalize long running traces.
+  # This connects to traced as a producer and sends the triggers passed on the
+  # commandline. This is a subset of what the perfetto binary can do but we
+  # need a separate binary for programs that cannot (for good reason) use the
+  # additional functionality (for example starting traces via consumer socket)
+  # due to selinux rules.
+  executable("trigger_perfetto") {
+    deps = [
+      "gn:default_deps",
+      "src/perfetto_cmd:trigger_perfetto_cmd",
+    ]
+    sources = [
+      "src/perfetto_cmd/trigger_perfetto_main.cc",
+    ]
+  }
+
+  if (perfetto_build_with_android) {
+    executable("trace_to_text") {
+      testonly = true
+      deps = [
+        "gn:default_deps",
+        "tools/trace_to_text:full",
+      ]
+    }
+
+    # This target exports perfetto trace protos in the Android build system,
+    # allowing both host and device targets to implement custom parsers based on
+    # our protos.
+    static_library("perfetto_trace_protos") {
+      deps = [
+        "protos/perfetto/trace:lite",
+      ]
+    }
+
+    shared_library("libperfetto_android_internal") {
+      deps = [
+        "gn:default_deps",
+        "src/android_internal",
+      ]
+    }
+  }  # if (perfetto_build_with_android)
+}  # if (perfetto_build_standalone || perfetto_build_with_android)
+
+if (perfetto_build_with_embedder) {
+  if (build_with_chromium) {
+    libperfetto_target_type = "component"
+  } else {
+    libperfetto_target_type = "source_set"
+  }
+  target(libperfetto_target_type, "libperfetto") {
     public_configs = [ "gn:public_config" ]
     deps = [
       "src/tracing",
@@ -216,39 +273,79 @@
     configs -= [ "//build/config/compiler:chromium_code" ]
     configs += [ "//build/config/compiler:no_chromium_code" ]
     public_deps = [
-      "include/perfetto/ext/tracing/core",
-      "protos/perfetto/common:zero",
+      "include/perfetto/tracing/core",
       "protos/perfetto/trace:zero",
       "protos/perfetto/trace/chrome:zero",
       "protos/perfetto/trace/interned_data:zero",
-      "protos/perfetto/trace/profiling:zero",
       "protos/perfetto/trace/track_event:zero",
     ]
   }
-  if (enable_perfetto_trace_processor_sqlite) {
-    component("libtrace_processor") {
-      public_configs = [ "gn:public_config" ]
-      deps = [
-        "src/trace_processor:lib",
-      ]
-      configs -= [ "//build/config/compiler:chromium_code" ]
-      configs += [ "//build/config/compiler:no_chromium_code" ]
-      public_deps = [
-        "include/perfetto/trace_processor",
-      ]
-    }
-  }
-  component("libproto_to_json") {
-    public_configs = [ "gn:public_config" ]
+}
+
+if (perfetto_build_standalone) {
+  executable("perfetto_benchmarks") {
+    testonly = true
     deps = [
-      "src/trace_processor:export_json",
-      "src/trace_processor:storage",
+      "gn:default_deps",
+      "src/traced/probes/ftrace:benchmarks",
+      "src/tracing:tracing_benchmarks",
+      "test:benchmark_main",
+      "test:end_to_end_benchmarks",
     ]
-    configs -= [ "//build/config/compiler:chromium_code" ]
-    configs += [ "//build/config/compiler:no_chromium_code" ]
-    public_deps = [
-      "include/perfetto/ext/trace_processor:export_json",
-      "include/perfetto/trace_processor:storage",
+  }
+
+  group("fuzzers") {
+    testonly = true
+    deps = [
+      "src/ipc:buffered_frame_deserializer_fuzzer",
+      "src/profiling/memory:shared_ring_buffer_fuzzer",
+      "src/profiling/memory:shared_ring_buffer_write_fuzzer",
+      "src/profiling/memory:unwinding_fuzzer",
+      "src/protozero:protozero_decoder_fuzzer",
+      "src/trace_processor:trace_processor_fuzzer",
+      "src/traced/probes/ftrace:cpu_reader_fuzzer",
+      "test:end_to_end_shared_memory_fuzzer",
+    ]
+  }
+}
+
+# WARNING: this builds correctly only when using the generated Android.bp.
+#
+# This library gets loaded into (and executes in) arbitrary android processes.
+# Logging must be non-allocating. This is achieved by defining
+# PERFETTO_ANDROID_ASYNC_SAFE_LOG, which needs to be set for all perfetto code
+# being compiled for this library. When generating Android.bp, the |cflags|
+# entry on this target is sufficient (as all sources are flattened into a
+# single bp target). However this is not correctly reflected in the gn
+# structure (which is a tree of targets) as the dependencies would not pick
+# up the flag (and thus use the wrong logging macro).
+#
+# This is deemed acceptable as, at the time of writing, there is no interest in
+# building this library standalone.
+if (perfetto_build_with_android) {
+  # TODO(fmayer): Investigate shared library for common pieces.
+  shared_library("heapprofd_client") {
+    configs -= [ "//gn/standalone:android_liblog" ]
+    cflags = [ "-DPERFETTO_ANDROID_ASYNC_SAFE_LOG" ]
+    deps = [
+      "src/profiling/memory:malloc_hooks",
+    ]
+  }
+}
+
+if (should_build_heapprofd) {
+  executable("heapprofd") {
+    deps = [
+      "gn:default_deps",
+      "protos/perfetto/trace:zero",
+      "src/base",
+      "src/base:unix_socket",
+      "src/profiling/memory:daemon",
+      "src/profiling/memory:wire_protocol",
+      "src/tracing:ipc",
+    ]
+    sources = [
+      "src/profiling/memory/main.cc",
     ]
   }
 }
diff --git a/OWNERS b/OWNERS
index 4ed8f1c..6054d1e 100644
--- a/OWNERS
+++ b/OWNERS
@@ -10,7 +10,6 @@
 oysteine@google.com
 eseckler@google.com
 nuskos@google.com
-ssid@google.com
 
 # TEAM: tracing@chromium.org
 # COMPONENT: Speed>Tracing
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index b25fed0..be520b0 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -15,145 +15,134 @@
 import itertools
 import subprocess
 
-
 def CheckChange(input, output):
-  # There apparently is no way to wrap strings in blueprints, so ignore long
-  # lines in them.
-  def long_line_sources(x):
-    return input.FilterSourceFile(
-        x,
-        white_list=".*",
-        black_list=[
-            'Android[.]bp', '.*[.]json$', '.*[.]sql$', '.*[.]out$',
-            'test/trace_processor/index$', '.*\bBUILD$', 'WORKSPACE',
-            '.*/Makefile$', '/perfetto_build_flags.h$'
-        ])
-
-  results = []
-  results += input.canned_checks.CheckDoNotSubmit(input, output)
-  results += input.canned_checks.CheckChangeHasNoTabs(input, output)
-  results += input.canned_checks.CheckLongLines(
-      input, output, 80, source_file_filter=long_line_sources)
-  results += input.canned_checks.CheckPatchFormatted(
-      input, output, check_js=True)
-  results += input.canned_checks.CheckGNFormatted(input, output)
-  results += CheckIncludeGuards(input, output)
-  results += CheckIncludeViolations(input, output)
-  results += CheckBuild(input, output)
-  results += CheckAndroidBlueprint(input, output)
-  results += CheckBinaryDescriptors(input, output)
-  results += CheckMergedTraceConfigProto(input, output)
-  results += CheckWhitelist(input, output)
-  return results
+    # There apparently is no way to wrap strings in blueprints, so ignore long
+    # lines in them.
+    long_line_sources = lambda x: input.FilterSourceFile(
+            x, white_list=".*",
+            black_list=['Android[.]bp', '.*[.]json$', '.*[.]sql$', '.*[.]out$',
+                        'test/trace_processor/index$', 'BUILD$', 'protos/BUILD$'])
+    results = []
+    results += input.canned_checks.CheckDoNotSubmit(input, output)
+    results += input.canned_checks.CheckChangeHasNoTabs(input, output)
+    results += input.canned_checks.CheckLongLines(
+            input, output, 80, source_file_filter=long_line_sources)
+    results += input.canned_checks.CheckPatchFormatted(
+            input, output, check_js=True)
+    results += input.canned_checks.CheckGNFormatted(input, output)
+    results += CheckIncludeGuards(input, output)
+    results += CheckBuild(input, output)
+    results += CheckAndroidBlueprint(input, output)
+    results += CheckBinaryDescriptors(input, output)
+    results += CheckMergedTraceConfigProto(input, output)
+    results += CheckWhitelist(input, output)
+    return results
 
 
 def CheckChangeOnUpload(input_api, output_api):
-  return CheckChange(input_api, output_api)
+    return CheckChange(input_api, output_api)
 
 
 def CheckChangeOnCommit(input_api, output_api):
-  return CheckChange(input_api, output_api)
+    return CheckChange(input_api, output_api)
 
 
 def CheckBuild(input_api, output_api):
-  tool = 'tools/gen_bazel'
+    # If no GN files were modified, bail out.
+    def build_file_filter(x): return input_api.FilterSourceFile(
+        x,
+        white_list=('.*BUILD[.]gn$', '.*[.]gni$', 'tools/gen_build'))
+    if not input_api.AffectedSourceFiles(build_file_filter):
+        return []
 
-  # If no GN files were modified, bail out.
-  def build_file_filter(x):
-    return input_api.FilterSourceFile(
-        x, white_list=('.*BUILD[.]gn$', '.*[.]gni$', 'BUILD\.extras', tool))
+    with open('BUILD') as f:
+        current_build = f.read()
 
-  if not input_api.AffectedSourceFiles(build_file_filter):
+    new_build = subprocess.check_output(
+        ['tools/gen_build', '--output', '/dev/stdout', '--output-proto', '/dev/null'])
+
+    with open('protos/BUILD') as f:
+        current_proto_build = f.read()
+
+    new_proto_build = subprocess.check_output(
+        ['tools/gen_build', '--output', '/dev/null', '--output-proto', '/dev/stdout'])
+
+    if current_build != new_build or current_proto_build != new_proto_build:
+        return [
+            output_api.PresubmitError(
+                'BUILD and/or protos/BUILD is out of date. Please run tools/gen_build '
+                'to update it.')
+        ]
     return []
-  if subprocess.call([tool, '--check-only']):
-    return [
-        output_api.PresubmitError('Bazel BUILD(s) are out of date. Run ' +
-                                  tool + ' to update them.')
-    ]
-  return []
 
 
 def CheckAndroidBlueprint(input_api, output_api):
-  tool = 'tools/gen_android_bp'
+    # If no GN files were modified, bail out.
+    build_file_filter = lambda x: input_api.FilterSourceFile(
+          x,
+          white_list=('.*BUILD[.]gn$', '.*[.]gni$', 'tools/gen_android_bp'))
+    if not input_api.AffectedSourceFiles(build_file_filter):
+        return []
 
-  # If no GN files were modified, bail out.
-  def build_file_filter(x):
-    return input_api.FilterSourceFile(
-        x, white_list=('.*BUILD[.]gn$', '.*[.]gni$', tool))
+    with open('Android.bp') as f:
+        current_blueprint = f.read()
 
-  if not input_api.AffectedSourceFiles(build_file_filter):
+    new_blueprint = subprocess.check_output(
+        ['tools/gen_android_bp', '--output', '/dev/stdout'])
+
+    if current_blueprint != new_blueprint:
+        return [
+            output_api.PresubmitError(
+                'Android.bp is out of date. Please run tools/gen_android_bp '
+                'to update it.')
+        ]
     return []
-  if subprocess.call([tool, '--check-only']):
-    return [
-        output_api.PresubmitError('Android build files are out of date. ' +
-                                  'Run ' + tool + ' to update them.')
-    ]
-  return []
 
 
 def CheckIncludeGuards(input_api, output_api):
-  tool = 'tools/fix_include_guards'
-
-  def file_filter(x):
-    return input_api.FilterSourceFile(
-        x, white_list=['.*[.]cc$', '.*[.]h$', tool])
-
-  if not input_api.AffectedSourceFiles(file_filter):
+    tool = 'tools/fix_include_guards'
+    file_filter = lambda x: input_api.FilterSourceFile(
+          x,
+          white_list=('.*[.]cc$', '.*[.]h$', tool))
+    if not input_api.AffectedSourceFiles(file_filter):
+        return []
+    if subprocess.call([tool, '--check-only']):
+        return [
+            output_api.PresubmitError(
+                'Please run ' + tool + ' to fix include guards.')
+        ]
     return []
-  if subprocess.call([tool, '--check-only']):
-    return [
-        output_api.PresubmitError('Please run ' + tool +
-                                  ' to fix include guards.')
-    ]
-  return []
-
-
-def CheckIncludeViolations(input_api, output_api):
-  tool = 'tools/check_include_violations'
-
-  def file_filter(x):
-    return input_api.FilterSourceFile(x, white_list=['include/.*[.]h$', tool])
-
-  if not input_api.AffectedSourceFiles(file_filter):
-    return []
-  if subprocess.call([tool]):
-    return [output_api.PresubmitError(tool + ' failed.')]
-  return []
 
 
 def CheckBinaryDescriptors(input_api, output_api):
-  tool = 'tools/gen_binary_descriptors'
-
-  def file_filter(x):
-    return input_api.FilterSourceFile(
-        x, white_list=['protos/perfetto/.*[.]proto$', '.*[.]h', tool])
-
-  if not input_api.AffectedSourceFiles(file_filter):
+    tool = 'tools/gen_binary_descriptors'
+    file_filter = lambda x: input_api.FilterSourceFile(
+          x,
+          white_list=('protos/perfetto/.*[.]proto$', '.*[.]h', tool))
+    if not input_api.AffectedSourceFiles(file_filter):
+        return []
+    if subprocess.call([tool, '--check-only']):
+        return [
+            output_api.PresubmitError(
+                'Please run ' + tool + ' to update binary descriptors.')
+        ]
     return []
-  if subprocess.call([tool, '--check-only']):
-    return [
-        output_api.PresubmitError('Please run ' + tool +
-                                  ' to update binary descriptors.')
-    ]
-  return []
 
 
 def CheckMergedTraceConfigProto(input_api, output_api):
-  tool = 'tools/gen_merged_protos'
-
-  def build_file_filter(x):
-    return input_api.FilterSourceFile(
-        x, white_list=['protos/perfetto/.*[.]proto$', tool])
-
-  if not input_api.AffectedSourceFiles(build_file_filter):
+    tool = 'tools/gen_merged_protos'
+    build_file_filter = lambda x: input_api.FilterSourceFile(
+          x,
+          white_list=('protos/perfetto/.*[.]proto$', tool))
+    if not input_api.AffectedSourceFiles(build_file_filter):
+        return []
+    if subprocess.call([tool, '--check-only']):
+        return [
+            output_api.PresubmitError(
+                'perfetto_config.proto or perfetto_trace.proto is out of ' +
+                'date. Please run ' + tool + ' to update it.')
+        ]
     return []
-  if subprocess.call([tool, '--check-only']):
-    return [
-        output_api.PresubmitError(
-            'perfetto_config.proto or perfetto_trace.proto is out of ' +
-            'date. Please run ' + tool + ' to update it.')
-    ]
-  return []
 
 
 # Prevent removing or changing lines in event_whitelist.
@@ -161,12 +150,13 @@
   for f in input_api.AffectedFiles():
     if f.LocalPath() != 'tools/ftrace_proto_gen/event_whitelist':
       continue
-    if any((not new_line.startswith('removed')) and new_line != old_line
-           for old_line, new_line in itertools.izip(f.OldContents(),
-                                                    f.NewContents())):
+    if any((not new_line.startswith('removed'))
+            and new_line != old_line for old_line, new_line
+           in itertools.izip(f.OldContents(), f.NewContents())):
       return [
-          output_api.PresubmitError(
-              'event_whitelist only has two supported changes: '
-              'appending a new line, and replacing a line with removed.')
+        output_api.PresubmitError(
+            'event_whitelist only has two supported changes: '
+            'appending a new line, and replacing a line with removed.'
+        )
       ]
   return []
diff --git a/README.md b/README.md
index 27f653a..88d5239 100644
--- a/README.md
+++ b/README.md
@@ -11,9 +11,3 @@
 bug tracker ([go/perfetto-bugs](http://goto.google.com/perfetto-bugs)).
 * For bugs affecting Chrome use http://crbug.com, Component:Speed>Tracing
 label:Perfetto.
-
-Community
----------
-You can reach us on our [Discord channel](https://discord.gg/35ShE3A).
-If you prefer using IRC we have an experimental Discord <> IRC bridge
-synced with `#perfetto-dev` on [Freenode](https://webchat.freenode.net/).
\ No newline at end of file
diff --git a/WORKSPACE b/WORKSPACE
deleted file mode 100644
index a933c67..0000000
--- a/WORKSPACE
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2019 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 file is used only in standalone builds. This file is ignored both in
-# embedder builds (i.e. when other projects pull perfetto under /third_party/
-# or similar) and in google internal builds.
-
-workspace(name = "perfetto")
-
-new_local_repository(
-    name = "perfetto_cfg",
-    path = "bazel/standalone",
-    build_file_content = ""
-)
-
-load("@perfetto//bazel:deps.bzl", "perfetto_deps")
-perfetto_deps()
-
-load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
-protobuf_deps()
diff --git a/bazel/BUILD b/bazel/BUILD
deleted file mode 100644
index 1bf33a4..0000000
--- a/bazel/BUILD
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2019 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.
-
-config_setting(
-    name = "os_osx",
-    values = {"cpu": "darwin"},
-    visibility = ["//visibility:public"],
-)
-
-config_setting(
-    name = "os_linux",
-    values = {"cpu": "k8"},
-    visibility = ["//visibility:public"],
-)
-
-# Note this config does not imply MSVC.
-config_setting(
-    name = "os_windows",
-    values = {"cpu": "x64_windows"},
-    visibility = ["//visibility:public"],
-)
diff --git a/bazel/deps.bzl b/bazel/deps.bzl
deleted file mode 100644
index 6f19f3d..0000000
--- a/bazel/deps.bzl
+++ /dev/null
@@ -1,88 +0,0 @@
-# Copyright (C) 2019 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.
-
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-load("@bazel_tools//tools/build_defs/repo:git.bzl", "new_git_repository")
-
-# This file must be kept in sync with tools/install-build-deps.
-
-def perfetto_deps():
-    # Note: this is more recent than the version of protobuf we use in the
-    # GN and Android builds. This is because older versions of protobuf don't
-    # support Bazel.
-    _add_repo_if_not_existing(
-        http_archive,
-        name = "com_google_protobuf",
-        strip_prefix = "protobuf-3.9.0",
-        url = "https://github.com/google/protobuf/archive/v3.9.0.tar.gz",
-        sha256 = "2ee9dcec820352671eb83e081295ba43f7a4157181dad549024d7070d079cf65",
-    )
-
-    _add_repo_if_not_existing(
-        http_archive,
-        name = "perfetto_dep_sqlite",
-        url = "https://storage.googleapis.com/perfetto/sqlite-amalgamation-3250300.zip",
-        sha256 = "2ad5379f3b665b60599492cc8a13ac480ea6d819f91b1ef32ed0e1ad152fafef",
-        strip_prefix = "sqlite-amalgamation-3250300",
-        build_file = "//bazel:sqlite.BUILD",
-    )
-
-    _add_repo_if_not_existing(
-        http_archive,
-        name = "perfetto_dep_sqlite_src",
-        url = "https://storage.googleapis.com/perfetto/sqlite-src-3250300.zip",
-        sha256 = "c7922bc840a799481050ee9a76e679462da131adba1814687f05aa5c93766421",
-        strip_prefix = "sqlite-src-3250300",
-        build_file = "//bazel:sqlite.BUILD",
-    )
-
-    _add_repo_if_not_existing(
-        new_git_repository,
-        name = "perfetto_dep_linenoise",
-        remote = "https://fuchsia.googlesource.com/third_party/linenoise.git",
-        commit = "c894b9e59f02203dbe4e2be657572cf88c4230c3",
-        build_file = "//bazel:linenoise.BUILD",
-        shallow_since = "1469784335 +0200",
-    )
-
-    _add_repo_if_not_existing(
-        new_git_repository,
-        name = "perfetto_dep_jsoncpp",
-        remote = "https://github.com/open-source-parsers/jsoncpp",
-        commit = "7165f6ac4c482e68475c9e1dac086f9e12fff0d0",  # v1.0.0
-        build_file = "//bazel:jsoncpp.BUILD",
-        shallow_since = "1416494758 -0600",
-    )
-
-    _add_repo_if_not_existing(
-        new_git_repository,
-        name = "perfetto_dep_zlib",
-        remote = "https://android.googlesource.com/platform/external/zlib.git",
-        commit = "dfa0646a03b4e1707469e04dc931b09774968fe6",
-        build_file = "//bazel:zlib.BUILD",
-        shallow_since = "1557160162 -0700",
-    )
-
-    # Without this protobuf.bzl fails. This seems a bug in protobuf_deps().
-    _add_repo_if_not_existing(
-        http_archive,
-        name = "bazel_skylib",
-        sha256 = "bbccf674aa441c266df9894182d80de104cabd19be98be002f6d478aaa31574d",
-        strip_prefix = "bazel-skylib-2169ae1c374aab4a09aa90e65efe1a3aad4e279b",
-        url = "https://github.com/bazelbuild/bazel-skylib/archive/2169ae1c374aab4a09aa90e65efe1a3aad4e279b.tar.gz",
-    )
-
-def _add_repo_if_not_existing(repo_rule, name, **kwargs):
-    if name not in native.existing_rules():
-        repo_rule(name = name, **kwargs)
diff --git a/bazel/jsoncpp.BUILD b/bazel/jsoncpp.BUILD
deleted file mode 100644
index bef06a1..0000000
--- a/bazel/jsoncpp.BUILD
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright (C) 2019 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.
-
-load("@perfetto_cfg//:perfetto_cfg.bzl", "PERFETTO_CONFIG")
-
-cc_library(
-    name = "jsoncpp",
-    srcs = [
-        "src/lib_json/json_batchallocator.h",
-        "src/lib_json/json_internalarray.inl",
-        "src/lib_json/json_internalmap.inl",
-        "src/lib_json/json_reader.cpp",
-        "src/lib_json/json_tool.h",
-        "src/lib_json/json_value.cpp",
-        "src/lib_json/json_valueiterator.inl",
-        "src/lib_json/json_writer.cpp",
-    ],
-    hdrs = [
-        "include/json/assertions.h",
-        "include/json/autolink.h",
-        "include/json/config.h",
-        "include/json/features.h",
-        "include/json/forwards.h",
-        "include/json/json.h",
-        "include/json/reader.h",
-        "include/json/value.h",
-        "include/json/version.h",
-        "include/json/writer.h",
-    ],
-    copts = [
-        "-Isrc/lib_json",
-    ] + PERFETTO_CONFIG.deps_copts.jsoncpp,
-    defines = [
-        "JSON_USE_EXCEPTION=0",
-    ],
-    includes = [
-        "include",
-    ],
-    visibility = ["//visibility:public"],
-)
diff --git a/bazel/linenoise.BUILD b/bazel/linenoise.BUILD
deleted file mode 100644
index 050e7c5..0000000
--- a/bazel/linenoise.BUILD
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (C) 2019 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.
-
-load("@perfetto_cfg//:perfetto_cfg.bzl", "PERFETTO_CONFIG")
-
-cc_library(
-    name = "linenoise",
-    srcs = [
-        "linenoise.c",
-    ],
-    hdrs = [
-        "linenoise.h",
-    ],
-    includes = [
-        ".",
-    ],
-    copts = PERFETTO_CONFIG.deps_copts.linenoise,
-    visibility = ["//visibility:public"],
-)
diff --git a/bazel/proto_gen.bzl b/bazel/proto_gen.bzl
deleted file mode 100644
index 82802a8..0000000
--- a/bazel/proto_gen.bzl
+++ /dev/null
@@ -1,118 +0,0 @@
-# Copyright (C) 2019 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 file defines the proto_gen() rule that is used for generating protos
-# with custom plugins (ipc and protozero).
-
-def _proto_gen_impl(ctx):
-    proto_src = [
-        f
-        for dep in ctx.attr.deps
-        for f in dep[ProtoInfo].direct_sources
-    ]
-    includes = [
-        f
-        for dep in ctx.attr.deps
-        for f in dep[ProtoInfo].transitive_imports.to_list()
-    ]
-
-    proto_path = "."
-
-    out_dir = str(ctx.genfiles_dir.path)
-    strip_base_path = ""
-    if ctx.attr.root != "//":
-        # This path is hit in Google internal builds, where root is typically
-        # //third_party/perfetto.
-        proto_path = "."
-
-        # The below will likely be //third_party/perfetto/ but may also be any
-        # subdir under //third_party/perfetto.
-        last_slash_idx = ctx.build_file_path.rfind("/")
-        strip_base_path = ctx.build_file_path[:last_slash_idx + 1]
-    elif ctx.label.workspace_root:
-        # This path is hit when proto targets are built as @perfetto//:xxx
-        # instead of //:xxx. This happens in embedder builds. In this case,
-        # workspace_root == "external/perfetto" and we need to rebase the paths
-        # passed to protoc.
-        proto_path = ctx.label.workspace_root
-        out_dir += "/" + ctx.label.workspace_root
-        strip_base_path = ctx.label.workspace_root + "/"
-
-    out_files = []
-    suffix = ctx.attr.suffix
-    for src in proto_src:
-        base_path = src.path[:-len(".proto")]
-        if base_path.startswith(strip_base_path):
-            base_path = base_path[len(strip_base_path):]
-        out_files += [ctx.actions.declare_file(base_path + ".%s.h" % suffix)]
-        out_files += [ctx.actions.declare_file(base_path + ".%s.cc" % suffix)]
-
-    arguments = [
-        "--proto_path=" + proto_path,
-    ]
-    plugin_deps = []
-    if ctx.attr.plugin:
-        arguments += [
-            "--plugin=protoc-gen-plugin=" + ctx.executable.plugin.path,
-            "--plugin_out=wrapper_namespace=pbzero:" + out_dir,
-        ]
-        plugin_deps += [ctx.executable.plugin]
-    else:
-        arguments += [
-            "--cpp_out=" + out_dir,
-        ]
-
-    arguments += [src.path for src in proto_src]
-    ctx.actions.run(
-        inputs = proto_src + includes + plugin_deps,
-        tools = plugin_deps,
-        outputs = out_files,
-        executable = ctx.executable.protoc,
-        arguments = arguments,
-    )
-    return [
-        DefaultInfo(files = depset(out_files)),
-        OutputGroupInfo(
-            cc = depset([f for f in out_files if f.path.endswith(".cc")]),
-            h = depset([f for f in out_files if f.path.endswith(".h")]),
-        ),
-    ]
-
-proto_gen = rule(
-    attrs = {
-        "deps": attr.label_list(
-            mandatory = True,
-            allow_empty = False,
-            providers = [ProtoInfo],
-        ),
-        "plugin": attr.label(
-            executable = True,
-            mandatory = False,
-            cfg = "host",
-        ),
-        "suffix": attr.string(
-            mandatory = True,
-        ),
-        "protoc": attr.label(
-            executable = True,
-            cfg = "host",
-        ),
-        "root": attr.string(
-            mandatory = False,
-            default = "//",
-        ),
-    },
-    output_to_genfiles = True,
-    implementation = _proto_gen_impl,
-)
diff --git a/bazel/rules.bzl b/bazel/rules.bzl
deleted file mode 100644
index 61941ad..0000000
--- a/bazel/rules.bzl
+++ /dev/null
@@ -1,216 +0,0 @@
-# Copyright (C) 2019 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.
-
-load("@perfetto_cfg//:perfetto_cfg.bzl", "PERFETTO_CONFIG")
-load("@perfetto//bazel:proto_gen.bzl", "proto_gen")
-
-# +----------------------------------------------------------------------------+
-# | Base C++ rules.                                                            |
-# +----------------------------------------------------------------------------+
-
-def default_cc_args():
-    return {
-        "deps": PERFETTO_CONFIG.deps.build_config,
-        "copts": [],
-        "includes": ["include"],
-        "linkopts": select({
-            "@perfetto//bazel:os_linux": ["-ldl", "-lrt"],
-            "@perfetto//bazel:os_osx": [],
-            "@perfetto//bazel:os_windows": [],
-            "//conditions:default": ["-ldl"],
-        }),
-    }
-
-def perfetto_cc_library(**kwargs):
-    args = _merge_dicts(default_cc_args(), kwargs)
-    if not _rule_override("cc_library", **args):
-        native.cc_library(**args)
-
-def perfetto_cc_binary(**kwargs):
-    args = _merge_dicts(default_cc_args(), kwargs)
-    if not _rule_override("cc_binary", **args):
-        native.cc_binary(**args)
-
-def perfetto_py_binary(**kwargs):
-    if not _rule_override("py_binary", **kwargs):
-        native.py_binary(**kwargs)
-
-# +----------------------------------------------------------------------------+
-# | Proto-related rules                                                        |
-# +----------------------------------------------------------------------------+
-
-def perfetto_proto_library(**kwargs):
-    if not _rule_override("proto_library", **kwargs):
-        native.proto_library(**kwargs)
-
-def perfetto_cc_proto_library(**kwargs):
-    if not _rule_override("cc_proto_library", **kwargs):
-        native.cc_proto_library(**kwargs)
-
-def perfetto_java_proto_library(**kwargs):
-    if not _rule_override("java_proto_library", **kwargs):
-        native.java_proto_library(**kwargs)
-
-# +----------------------------------------------------------------------------+
-# | Misc rules.                                                                |
-# +----------------------------------------------------------------------------+
-
-# Unlike all the other rules, this is an noop by default because Bazel does not
-# support gensignature.
-def perfetto_gensignature_internal_only(**kwargs):
-    _rule_override("gensignature_internal_only", **kwargs)
-
-# Generates .pbzero.{cc,h} from .proto(s). We deliberately do NOT generate
-# conventional .pb.{cc,h} from here as protozero gen sources do not have any
-# dependency on libprotobuf.
-def perfetto_cc_protozero_library(name, deps, **kwargs):
-    if _rule_override(
-        "cc_protozero_library",
-        name = name,
-        deps = deps,
-        **kwargs
-    ):
-        return
-
-    proto_gen(
-        name = name + "_src",
-        deps = deps,
-        suffix = "pbzero",
-        plugin = PERFETTO_CONFIG.root + ":protozero_plugin",
-        protoc = PERFETTO_CONFIG.deps.protoc[0],
-        root = PERFETTO_CONFIG.root,
-    )
-
-    native.filegroup(
-        name = name + "_h",
-        srcs = [":" + name + "_src"],
-        output_group = "h",
-    )
-
-    perfetto_cc_library(
-        name = name,
-        srcs = [":" + name + "_src"],
-        hdrs = [":" + name + "_h"],
-        deps = [PERFETTO_CONFIG.root + ":libprotozero"],
-        **kwargs
-    )
-
-# Generates .ipc.{cc,h} and .pb.{cc.h} from .proto(s). The IPC sources depend
-# on .pb.h so we need to generate also the standard protobuf sources here.
-def perfetto_cc_ipc_library(name, deps, **kwargs):
-    if _rule_override("cc_ipc_library", name = name, deps = deps, **kwargs):
-        return
-
-    # Takes care of generating .pb.{cc,h}.
-    perfetto_cc_proto_library(name = name + "_pb", deps = deps)
-
-    # Generates .ipc.{cc,h}.
-    proto_gen(
-        name = name + "_src",
-        deps = deps,
-        suffix = "ipc",
-        plugin = PERFETTO_CONFIG.root + ":ipc_plugin",
-        protoc = PERFETTO_CONFIG.deps.protoc[0],
-        root = PERFETTO_CONFIG.root,
-    )
-
-    native.filegroup(
-        name = name + "_h",
-        srcs = [":" + name + "_src"],
-        output_group = "h",
-    )
-
-    perfetto_cc_library(
-        name = name,
-        srcs = [":" + name + "_src"],
-        hdrs = [":" + name + "_h"],
-        deps = [
-            ":" + name + "_pb",
-
-            # Generated .ipc.{cc,h} depend on this.
-            PERFETTO_CONFIG.root + ":perfetto_ipc",
-
-            # Generated .pb.{cc,h} depend on this.
-        ] + PERFETTO_CONFIG.deps.protobuf_lite,
-        **kwargs
-    )
-
-
-# Generates .gen.{cc,h} from .proto(s).
-def perfetto_cc_protocpp_library(name, deps, **kwargs):
-    if _rule_override(
-        "cc_protocpp_library",
-        name = name,
-        deps = deps,
-        **kwargs
-    ):
-        return
-
-    # A perfetto_cc_protocpp_library has two types of dependencies:
-    # 1. Exactly one dependency on a proto_library target. This defines the
-    #    .proto sources for the target
-    # 2. Zero or more deps on other perfetto_cc_protocpp_library targets. This
-    #    to deal with the case of foo.proto including common.proto from another
-    #    target.
-    _proto_deps = [d for d in deps if d.endswith("_protos")]
-    _cc_deps = [d for d in deps if d not in _proto_deps]
-
-    proto_gen(
-        name = name + "_gen",
-        deps = _proto_deps,
-        suffix = "gen",
-        plugin = PERFETTO_CONFIG.root + ":cppgen_plugin",
-        protoc = PERFETTO_CONFIG.deps.protoc[0],
-        root = PERFETTO_CONFIG.root,
-    )
-
-    native.filegroup(
-        name = name + "_gen_h",
-        srcs = [":" + name + "_gen"],
-        output_group = "h",
-    )
-
-    perfetto_cc_library(
-        name = name,
-        srcs = [":" + name + "_gen"],
-        hdrs = [":" + name + "_gen_h"],
-        deps = [
-            PERFETTO_CONFIG.root + ":libprotozero"
-        ] + _cc_deps,
-        **kwargs
-    )
-
-# +----------------------------------------------------------------------------+
-# | Misc utility functions                                                     |
-# +----------------------------------------------------------------------------+
-
-def _rule_override(rule_name, **kwargs):
-    overrides = getattr(PERFETTO_CONFIG, "rule_overrides", struct())
-    overridden_rule = getattr(overrides, rule_name, None)
-    if overridden_rule:
-        overridden_rule(**kwargs)
-        return True
-    return False
-
-def _merge_dicts(*args):
-    res = {}
-    for arg in args:
-        for k, v in arg.items():
-            if type(v) == "string":
-                res[k] = v
-            elif type(v) == "list" or type(v) == "select":
-                res[k] = res.get(k, []) + v
-            else:
-                fail("key type not supported: " + type(v))
-    return res
diff --git a/bazel/sqlite.BUILD b/bazel/sqlite.BUILD
deleted file mode 100644
index 8b02c6d..0000000
--- a/bazel/sqlite.BUILD
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright (C) 2019 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 build file is used for both @perfetto_dep_sqlite and
-# @perfetto_dep_sqlite_src.
-
-load("@perfetto_cfg//:perfetto_cfg.bzl", "PERFETTO_CONFIG")
-
-# #############################
-# @perfetto_dep_sqlite section
-# #############################
-
-filegroup(
-    name = "headers",
-    srcs = [
-        "sqlite3.h",
-        "sqlite3ext.h",
-    ],
-    visibility = ["//visibility:public"],
-)
-
-include_sqlite = [
-    ".",
-]
-
-sqlite_copts = [
-    "-DSQLITE_THREADSAFE=0",
-    "-DQLITE_DEFAULT_MEMSTATUS=0",
-    "-DSQLITE_LIKE_DOESNT_MATCH_BLOBS",
-    "-DSQLITE_OMIT_DEPRECATED",
-    "-DSQLITE_OMIT_SHARED_CACHE",
-    "-DHAVE_USLEEP",
-    "-DHAVE_UTIME",
-    "-DSQLITE_BYTEORDER=1234",
-    "-DSQLITE_DEFAULT_AUTOVACUUM=0",
-    "-DSQLITE_DEFAULT_MMAP_SIZE=0",
-    "-DSQLITE_CORE",
-    "-DSQLITE_TEMP_STORE=3",
-    "-DSQLITE_OMIT_LOAD_EXTENSION",
-    "-DSQLITE_OMIT_RANDOMNESS",
-] + PERFETTO_CONFIG.deps_copts.sqlite
-
-cc_library(
-    name = "sqlite",
-    srcs = [
-        "sqlite3.c",
-        "sqlite3.h",
-    ],
-    hdrs = [":headers"],
-    copts = sqlite_copts,
-    includes = include_sqlite,
-    visibility = ["//visibility:public"],
-)
-
-# ################################
-# @perfetto_dep_sqlite_src section
-# ################################
-
-cc_library(
-    name = "percentile_ext",
-    srcs = [
-        "ext/misc/percentile.c",
-    ],
-    copts = sqlite_copts,
-    deps = PERFETTO_CONFIG.deps.sqlite,
-    visibility = ["//visibility:public"],
-)
diff --git a/bazel/standalone/README.md b/bazel/standalone/README.md
deleted file mode 100644
index 6b549b3..0000000
--- a/bazel/standalone/README.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# Perfetto standalone Bazel config
-
-This directory is only used in standalone builds.
-The WORKSPACE aliases this directory to @perfetto_cfg.
-
-Bazel-based embedders are supposed to:
-
-### 1. Have a (modified) copy of perfetto_cfg.bzl in their repo
-
-```
-myproject/
-  build/
-    perfetto_overrides/
-      perfetto_cfg.bzl
-```
-
-### 2. Have a repository rule that maps the directory to @perfetto_cfg
-
-E.g in myproject/WORKSPACE
-```
-local_repository(
-    name = "perfetto_cfg",
-    path = "build/perfetto_overrides",
-)
-```
diff --git a/bazel/standalone/perfetto_cfg.bzl b/bazel/standalone/perfetto_cfg.bzl
deleted file mode 100644
index 1ee8e52..0000000
--- a/bazel/standalone/perfetto_cfg.bzl
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Noop function used to override rules we don't want to support in standalone.
-def _noop_override(**kwargs):
-    pass
-
-PERFETTO_CONFIG = struct(
-    # This is used to refer to deps within perfetto's BUILD files.
-    # In standalone and bazel-based embedders use '//', because perfetto has its
-    # own repository, and //xxx would be relative to @perfetto//xxx.
-    # In Google internal builds, instead, this is set to //third_party/perfetto,
-    # because perfetto doesn't have its own repository there.
-    root = "//",
-
-    # These variables map dependencies to perfetto third-party projects. This is
-    # to allow perfetto embedders (e.g. gapid) and google internal builds to
-    # override paths and target names to their own third_party.
-    deps = struct(
-        # Target exposing the build config header. It should be a valid
-        # cc_library dependency as it will become a dependency of every
-        # perfetto_cc_library target. It needs to expose a
-        # "perfetto_build_flags.h" file that can be included via:
-        # #include "perfetto_build_flags.h".
-        build_config = ["//:build_config_hdr"],
-        zlib = ["@perfetto_dep_zlib//:zlib"],
-        jsoncpp = ["@perfetto_dep_jsoncpp//:jsoncpp"],
-        linenoise = ["@perfetto_dep_linenoise//:linenoise"],
-        sqlite = ["@perfetto_dep_sqlite//:sqlite"],
-        sqlite_ext_percentile = ["@perfetto_dep_sqlite_src//:percentile_ext"],
-        protoc = ["@com_google_protobuf//:protoc"],
-        protoc_lib = ["@com_google_protobuf//:protoc_lib"],
-        protobuf_lite = ["@com_google_protobuf//:protobuf_lite"],
-        protobuf_full = ["@com_google_protobuf//:protobuf"],
-    ),
-
-    # This struct allows embedders to customize the cc_opts for Perfetto
-    # 3rd party dependencies. They only have an effect if the dependencies are
-    # initialized with the Perfetto build files (i.e. via perfetto_deps()).
-    deps_copts = struct(
-        zlib = [],
-        jsoncpp = [],
-        linenoise = [],
-        sqlite = [],
-    ),
-
-    # This struct allows the embedder to customize copts and other args passed
-    # to rules like cc_binary. Prefixed rules (e.g. perfetto_cc_binary) will
-    # look into this struct before falling back on native.cc_binary().
-    # This field is completely optional, the embedder can omit the whole
-    # |rule_overrides| or invidivual keys. They are assigned to None or noop
-    # actions here just for documentation purposes.
-    rule_overrides = struct(
-        cc_binary = None,
-        cc_library = None,
-        cc_proto_library = None,
-        # Supporting java rules pulls in the JDK and generally is not something
-        # we need for most embedders.
-        java_proto_library = _noop_override,
-        proto_library = None,
-        py_binary = None,
-
-        # We only need this for internal binaries. No other embeedder should
-        # care about this.
-        gensignature_internal_only = None,
-    ),
-)
diff --git a/bazel/zlib.BUILD b/bazel/zlib.BUILD
deleted file mode 100644
index 5c723ce..0000000
--- a/bazel/zlib.BUILD
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright (C) 2019 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.
-
-load("@perfetto_cfg//:perfetto_cfg.bzl", "PERFETTO_CONFIG")
-
-cc_library(
-    name = "zlib",
-    srcs = [
-        "src/adler32.c",
-        "src/compress.c",
-        "src/crc32.c",
-        "src/crc32.h",
-        "src/deflate.c",
-        "src/deflate.h",
-        "src/gzclose.c",
-        "src/gzguts.h",
-        "src/gzlib.c",
-        "src/gzread.c",
-        "src/gzwrite.c",
-        "src/infback.c",
-        "src/inffast.c",
-        "src/inffast.h",
-        "src/inffixed.h",
-        "src/inflate.c",
-        "src/inflate.h",
-        "src/inftrees.c",
-        "src/inftrees.h",
-        "src/trees.c",
-        "src/trees.h",
-        "src/uncompr.c",
-        "src/zconf.h",
-        "src/zlib.h",
-        "src/zutil.c",
-        "src/zutil.h",
-    ],
-    hdrs = [
-        "zlib.h",
-    ],
-    copts = [
-        "-DHAVE_HIDDEN",
-        "-Isrc",
-    ] + PERFETTO_CONFIG.deps_copts.zlib,
-    includes = ["zlib"],
-    visibility = ["//visibility:public"],
-)
diff --git a/buildtools/BUILD.gn b/buildtools/BUILD.gn
index 507f296..c82d823 100644
--- a/buildtools/BUILD.gn
+++ b/buildtools/BUILD.gn
@@ -12,50 +12,41 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import("//gn/standalone/libc++/libc++.gni")
 import("../gn/perfetto.gni")
-import("../gn/standalone/libc++/libc++.gni")
-import("../gn/standalone/sanitizers/vars.gni")
-
-# We should never get here in embedder builds.
-assert(perfetto_build_standalone || is_perfetto_build_generator)
-
-# This is to make sure that we don't add accidental dependencies from build
-# files in src/ or include/ to buildtools. All deps (outside of /gn/*) should
-# go via the groups defined in gn/BUILD.gn, not directly into buildtools. This
-# is to allow embedders to re-route targets to their third_party directories.
-_buildtools_visibility = [
-  "./*",
-  "../gn:*",
-  "../gn/standalone:*",
-]
 
 # Used to suppress warnings coming from googletest macros expansions.
-# These suppressions apply both to gtest/gmock haders and to perfetto's
-# test translation units. See test/gtest_and_gmock.h for the subset of
-# suppressions that apply only to the gmock/gtest headers.
 config("test_warning_suppressions") {
-  visibility = _buildtools_visibility
-  if (is_clang) {
-    cflags = [
-      "-Wno-unknown-warning-option",
-      "-Wno-global-constructors",
-      "-Wno-covered-switch-default",
-      "-Wno-used-but-marked-unused",
-      "-Wno-inconsistent-missing-override",
-      "-Wno-unused-member-function",
-      "-Wno-zero-as-null-pointer-constant",
-      "-Wno-weak-vtables",
-    ]
-  } else {
-    cflags = [
-      "-Wno-unknown-warning-option",
-      "-Wno-deprecated-copy",
-    ]
-  }
+  cflags = [
+    "-Wno-unknown-warning-option",
+    "-Wno-global-constructors",
+    "-Wno-covered-switch-default",
+    "-Wno-used-but-marked-unused",
+    "-Wno-covered-switch-default",
+    "-Wno-global-constructors",
+    "-Wno-used-but-marked-unused",
+    "-Wno-inconsistent-missing-override",
+    "-Wno-unused-member-function",
+    "-Wno-zero-as-null-pointer-constant",
+    "-Wno-weak-vtables",
+  ]
+}
+
+# Mimimal config to be used in production (i.e. non-test) targets. This is
+# really just to allowing include "gtest/gtest_prod.h" for the FRIEND_TEST macro
+# and avoid to pull in warning suppressions that are not really necessary for
+# production code.
+config("googletest_prod_config") {
+  cflags = [
+    # Using -isystem instead of include_dirs (-I), so we don't need to suppress
+    # warnings coming from third-party headers. Doing so would mask warnings in
+    # our own code.
+    "-isystem",
+    rebase_path("googletest/googletest/include", root_build_dir),
+  ]
 }
 
 config("libunwindstack_config") {
-  visibility = _buildtools_visibility
   cflags = [
     # Using -isystem instead of include_dirs (-I), so we don't need to suppress
     # warnings coming from libunwindstack headers. Doing so would mask warnings
@@ -80,17 +71,20 @@
 
 # Config to include gtest.h in test targets.
 config("googletest_config") {
-  visibility = _buildtools_visibility
   defines = [ "GTEST_LANG_CXX11=1" ]
-  include_dirs = [
-    "googletest/googletest/include",
-    "googletest/googlemock/include",
+  cflags = [
+    # Using -isystem instead of include_dirs (-I), so we don't need to suppress
+    # warnings coming from third-party headers. Doing so would mask warnings in
+    # our own code.
+    "-isystem",
+    rebase_path("googletest/googletest/include", root_build_dir),
+    "-isystem",
+    rebase_path("googletest/googlemock/include", root_build_dir),
   ]
   configs = [ ":test_warning_suppressions" ]
 }
 
 source_set("gtest") {
-  visibility = _buildtools_visibility
   testonly = true
   include_dirs = [ "googletest/googletest" ]
   configs -= [ "//gn/standalone:extra_warnings" ]
@@ -99,26 +93,18 @@
   sources = [
     "googletest/googletest/src/gtest-all.cc",
   ]
-  deps = [
-    "//gn:default_deps",
-  ]
 }
 
 source_set("gtest_main") {
-  visibility = _buildtools_visibility
   testonly = true
   configs -= [ "//gn/standalone:extra_warnings" ]
   configs += [ ":googletest_config" ]
   sources = [
     "googletest/googletest/src/gtest_main.cc",
   ]
-  deps = [
-    "//gn:default_deps",
-  ]
 }
 
 source_set("gmock") {
-  visibility = _buildtools_visibility
   testonly = true
   include_dirs = [ "googletest/googlemock" ]
   configs -= [ "//gn/standalone:extra_warnings" ]
@@ -127,9 +113,6 @@
   sources = [
     "googletest/googlemock/src/gmock-all.cc",
   ]
-  deps = [
-    "//gn:default_deps",
-  ]
 }
 
 # This config is applied to the autogenerated .pb.{cc,h} files in
@@ -139,7 +122,6 @@
 # autogenerated .pb.h headers violate less warnings than the libprotobuf_*
 # library itself.
 config("protobuf_gen_config") {
-  visibility = [ "*" ]  # This is injected by standalone/proto_library.gni
   defines = [
     "GOOGLE_PROTOBUF_NO_RTTI",
     "GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
@@ -159,8 +141,6 @@
 
 # Configuration used to build libprotobuf_* and the protoc compiler.
 config("protobuf_config") {
-  visibility = _buildtools_visibility
-
   # Apply the lighter supressions and macro definitions from above.
   configs = [ ":protobuf_gen_config" ]
 
@@ -172,13 +152,10 @@
       "-Wno-user-defined-warnings",
       "-Wno-tautological-constant-compare",
     ]
-  } else {  # implies gcc
-    cflags = [ "-Wno-return-type" ]
   }
 }
 
 source_set("protobuf_lite") {
-  visibility = _buildtools_visibility
   sources = [
     "protobuf/src/google/protobuf/arena.cc",
     "protobuf/src/google/protobuf/arenastring.cc",
@@ -207,16 +184,11 @@
   configs -= [ "//gn/standalone:extra_warnings" ]
   configs += [ ":protobuf_config" ]
   public_configs = [ ":protobuf_gen_config" ]
-  deps = [
-    "//gn:default_deps",
-  ]
 }
 
 source_set("protobuf_full") {
-  visibility = _buildtools_visibility
   deps = [
     ":protobuf_lite",
-    "//gn:default_deps",
   ]
   sources = [
     "protobuf/src/google/protobuf/any.cc",
@@ -278,113 +250,110 @@
   public_configs = [ ":protobuf_gen_config" ]
 }
 
-source_set("protoc_lib") {
-  visibility = _buildtools_visibility
-  deps = [
-    ":protobuf_full",
-    "//gn:default_deps",
-  ]
-  sources = [
-    "protobuf/src/google/protobuf/compiler/code_generator.cc",
-    "protobuf/src/google/protobuf/compiler/command_line_interface.cc",
-    "protobuf/src/google/protobuf/compiler/cpp/cpp_enum.cc",
-    "protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.cc",
-    "protobuf/src/google/protobuf/compiler/cpp/cpp_extension.cc",
-    "protobuf/src/google/protobuf/compiler/cpp/cpp_field.cc",
-    "protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc",
-    "protobuf/src/google/protobuf/compiler/cpp/cpp_generator.cc",
-    "protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc",
-    "protobuf/src/google/protobuf/compiler/cpp/cpp_map_field.cc",
-    "protobuf/src/google/protobuf/compiler/cpp/cpp_message.cc",
-    "protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.cc",
-    "protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc",
-    "protobuf/src/google/protobuf/compiler/cpp/cpp_service.cc",
-    "protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.cc",
-    "protobuf/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc",
-    "protobuf/src/google/protobuf/compiler/csharp/csharp_enum.cc",
-    "protobuf/src/google/protobuf/compiler/csharp/csharp_enum_field.cc",
-    "protobuf/src/google/protobuf/compiler/csharp/csharp_field_base.cc",
-    "protobuf/src/google/protobuf/compiler/csharp/csharp_generator.cc",
-    "protobuf/src/google/protobuf/compiler/csharp/csharp_helpers.cc",
-    "protobuf/src/google/protobuf/compiler/csharp/csharp_map_field.cc",
-    "protobuf/src/google/protobuf/compiler/csharp/csharp_message.cc",
-    "protobuf/src/google/protobuf/compiler/csharp/csharp_message_field.cc",
-    "protobuf/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc",
-    "protobuf/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc",
-    "protobuf/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc",
-    "protobuf/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc",
-    "protobuf/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc",
-    "protobuf/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc",
-    "protobuf/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_context.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_enum.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_enum_field.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_enum_field_lite.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_enum_lite.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_extension.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_extension_lite.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_field.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_file.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_generator.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_generator_factory.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_helpers.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_lazy_message_field.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_map_field.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_map_field_lite.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_message.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_message_builder.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_message_builder_lite.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_message_field.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_message_field_lite.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_message_lite.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_name_resolver.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_primitive_field.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_primitive_field_lite.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_service.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_shared_code_generator.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_string_field.cc",
-    "protobuf/src/google/protobuf/compiler/java/java_string_field_lite.cc",
-    "protobuf/src/google/protobuf/compiler/javanano/javanano_enum.cc",
-    "protobuf/src/google/protobuf/compiler/javanano/javanano_enum_field.cc",
-    "protobuf/src/google/protobuf/compiler/javanano/javanano_extension.cc",
-    "protobuf/src/google/protobuf/compiler/javanano/javanano_field.cc",
-    "protobuf/src/google/protobuf/compiler/javanano/javanano_file.cc",
-    "protobuf/src/google/protobuf/compiler/javanano/javanano_generator.cc",
-    "protobuf/src/google/protobuf/compiler/javanano/javanano_helpers.cc",
-    "protobuf/src/google/protobuf/compiler/javanano/javanano_map_field.cc",
-    "protobuf/src/google/protobuf/compiler/javanano/javanano_message.cc",
-    "protobuf/src/google/protobuf/compiler/javanano/javanano_message_field.cc",
-    "protobuf/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc",
-    "protobuf/src/google/protobuf/compiler/js/js_generator.cc",
-    "protobuf/src/google/protobuf/compiler/objectivec/objectivec_enum.cc",
-    "protobuf/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc",
-    "protobuf/src/google/protobuf/compiler/objectivec/objectivec_extension.cc",
-    "protobuf/src/google/protobuf/compiler/objectivec/objectivec_field.cc",
-    "protobuf/src/google/protobuf/compiler/objectivec/objectivec_file.cc",
-    "protobuf/src/google/protobuf/compiler/objectivec/objectivec_generator.cc",
-    "protobuf/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc",
-    "protobuf/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc",
-    "protobuf/src/google/protobuf/compiler/objectivec/objectivec_message.cc",
-    "protobuf/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc",
-    "protobuf/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc",
-    "protobuf/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc",
-    "protobuf/src/google/protobuf/compiler/plugin.cc",
-    "protobuf/src/google/protobuf/compiler/plugin.pb.cc",
-    "protobuf/src/google/protobuf/compiler/python/python_generator.cc",
-    "protobuf/src/google/protobuf/compiler/ruby/ruby_generator.cc",
-    "protobuf/src/google/protobuf/compiler/subprocess.cc",
-    "protobuf/src/google/protobuf/compiler/zip_writer.cc",
-  ]
-  configs -= [ "//gn/standalone:extra_warnings" ]
-  configs += [ ":protobuf_config" ]
-  public_configs = [ ":protobuf_gen_config" ]
-}
-
 if (current_toolchain == host_toolchain) {
+  source_set("protoc_lib") {
+    deps = [
+      ":protobuf_full",
+    ]
+    sources = [
+      "protobuf/src/google/protobuf/compiler/code_generator.cc",
+      "protobuf/src/google/protobuf/compiler/command_line_interface.cc",
+      "protobuf/src/google/protobuf/compiler/cpp/cpp_enum.cc",
+      "protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.cc",
+      "protobuf/src/google/protobuf/compiler/cpp/cpp_extension.cc",
+      "protobuf/src/google/protobuf/compiler/cpp/cpp_field.cc",
+      "protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc",
+      "protobuf/src/google/protobuf/compiler/cpp/cpp_generator.cc",
+      "protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc",
+      "protobuf/src/google/protobuf/compiler/cpp/cpp_map_field.cc",
+      "protobuf/src/google/protobuf/compiler/cpp/cpp_message.cc",
+      "protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.cc",
+      "protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc",
+      "protobuf/src/google/protobuf/compiler/cpp/cpp_service.cc",
+      "protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.cc",
+      "protobuf/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc",
+      "protobuf/src/google/protobuf/compiler/csharp/csharp_enum.cc",
+      "protobuf/src/google/protobuf/compiler/csharp/csharp_enum_field.cc",
+      "protobuf/src/google/protobuf/compiler/csharp/csharp_field_base.cc",
+      "protobuf/src/google/protobuf/compiler/csharp/csharp_generator.cc",
+      "protobuf/src/google/protobuf/compiler/csharp/csharp_helpers.cc",
+      "protobuf/src/google/protobuf/compiler/csharp/csharp_map_field.cc",
+      "protobuf/src/google/protobuf/compiler/csharp/csharp_message.cc",
+      "protobuf/src/google/protobuf/compiler/csharp/csharp_message_field.cc",
+      "protobuf/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc",
+      "protobuf/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc",
+      "protobuf/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc",
+      "protobuf/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc",
+      "protobuf/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc",
+      "protobuf/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc",
+      "protobuf/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_context.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_enum.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_enum_field.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_enum_field_lite.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_enum_lite.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_extension.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_extension_lite.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_field.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_file.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_generator.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_generator_factory.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_helpers.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_lazy_message_field.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_map_field.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_map_field_lite.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_message.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_message_builder.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_message_builder_lite.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_message_field.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_message_field_lite.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_message_lite.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_name_resolver.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_primitive_field.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_primitive_field_lite.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_service.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_shared_code_generator.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_string_field.cc",
+      "protobuf/src/google/protobuf/compiler/java/java_string_field_lite.cc",
+      "protobuf/src/google/protobuf/compiler/javanano/javanano_enum.cc",
+      "protobuf/src/google/protobuf/compiler/javanano/javanano_enum_field.cc",
+      "protobuf/src/google/protobuf/compiler/javanano/javanano_extension.cc",
+      "protobuf/src/google/protobuf/compiler/javanano/javanano_field.cc",
+      "protobuf/src/google/protobuf/compiler/javanano/javanano_file.cc",
+      "protobuf/src/google/protobuf/compiler/javanano/javanano_generator.cc",
+      "protobuf/src/google/protobuf/compiler/javanano/javanano_helpers.cc",
+      "protobuf/src/google/protobuf/compiler/javanano/javanano_map_field.cc",
+      "protobuf/src/google/protobuf/compiler/javanano/javanano_message.cc",
+      "protobuf/src/google/protobuf/compiler/javanano/javanano_message_field.cc",
+      "protobuf/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc",
+      "protobuf/src/google/protobuf/compiler/js/js_generator.cc",
+      "protobuf/src/google/protobuf/compiler/objectivec/objectivec_enum.cc",
+      "protobuf/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc",
+      "protobuf/src/google/protobuf/compiler/objectivec/objectivec_extension.cc",
+      "protobuf/src/google/protobuf/compiler/objectivec/objectivec_field.cc",
+      "protobuf/src/google/protobuf/compiler/objectivec/objectivec_file.cc",
+      "protobuf/src/google/protobuf/compiler/objectivec/objectivec_generator.cc",
+      "protobuf/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc",
+      "protobuf/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc",
+      "protobuf/src/google/protobuf/compiler/objectivec/objectivec_message.cc",
+      "protobuf/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc",
+      "protobuf/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc",
+      "protobuf/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc",
+      "protobuf/src/google/protobuf/compiler/plugin.cc",
+      "protobuf/src/google/protobuf/compiler/plugin.pb.cc",
+      "protobuf/src/google/protobuf/compiler/python/python_generator.cc",
+      "protobuf/src/google/protobuf/compiler/ruby/ruby_generator.cc",
+      "protobuf/src/google/protobuf/compiler/subprocess.cc",
+      "protobuf/src/google/protobuf/compiler/zip_writer.cc",
+    ]
+    configs -= [ "//gn/standalone:extra_warnings" ]
+    configs += [ ":protobuf_config" ]
+    public_configs = [ ":protobuf_gen_config" ]
+  }
+
   executable("protoc") {
-    visibility = _buildtools_visibility
     deps = [
       ":protoc_lib",
       "//gn:default_deps",
@@ -399,7 +368,6 @@
 if (use_custom_libcxx) {
   # Config applied to both libc++ and libc++abi targets below.
   config("libc++config") {
-    visibility = _buildtools_visibility
     defines = [
       "LIBCXX_BUILDING_LIBCXXABI",
       "_LIBCXXABI_NO_EXCEPTIONS",
@@ -412,7 +380,6 @@
   }
 
   source_set("libunwind") {
-    visibility = _buildtools_visibility
     sources = [
       "libunwind/src/Unwind-EHABI.cpp",
       "libunwind/src/Unwind-sjlj.c",
@@ -440,7 +407,6 @@
   }
 
   source_set("libc++abi") {
-    visibility = _buildtools_visibility
     sources = [
       "libcxxabi/src/abort_message.cpp",
       "libcxxabi/src/cxa_aux_runtime.cpp",
@@ -487,8 +453,6 @@
   }
 
   target(libcxx_target_type, "libc++") {
-    visibility = _buildtools_visibility
-    visibility += [ "../gn/standalone/libc++:*" ]
     sources = [
       "libcxx/src/algorithm.cpp",
       "libcxx/src/any.cpp",
@@ -539,13 +503,11 @@
 }  # if (use_custom_libcxx)
 
 config("benchmark_config") {
-  visibility = _buildtools_visibility
   include_dirs = [ "benchmark/include" ]
   configs = [ ":test_warning_suppressions" ]
 }
 
 source_set("benchmark") {
-  visibility = _buildtools_visibility
   testonly = true
   sources = [
     "benchmark/include/benchmark/benchmark.h",
@@ -588,15 +550,11 @@
   public_configs = [ ":benchmark_config" ]
   all_dependent_configs = [ ":benchmark_config" ]
   configs -= [ "//gn/standalone:extra_warnings" ]
-  deps = [
-    "//gn:default_deps",
-  ]
 }
 
 # On Linux/Android use libbacktrace in debug builds for better stacktraces.
 if (is_linux || is_android) {
   config("libbacktrace_config") {
-    visibility = _buildtools_visibility
     include_dirs = [
       "libbacktrace_config",
       "libbacktrace",
@@ -611,7 +569,6 @@
   }
 
   source_set("libbacktrace") {
-    visibility = _buildtools_visibility
     sources = [
       "libbacktrace/dwarf.c",
       "libbacktrace/elf.c",
@@ -624,14 +581,10 @@
     ]
     configs -= [ "//gn/standalone:extra_warnings" ]
     public_configs = [ ":libbacktrace_config" ]
-    deps = [
-      "//gn:default_deps",
-    ]
   }
 }
 
 config("sqlite_config") {
-  visibility = _buildtools_visibility
   include_dirs = [ "sqlite" ]
   cflags = [
     "-DSQLITE_THREADSAFE=0",
@@ -652,7 +605,6 @@
 }
 
 source_set("sqlite") {
-  visibility = _buildtools_visibility
   sources = [
     "sqlite/sqlite3.c",
     "sqlite/sqlite3.h",
@@ -661,13 +613,9 @@
   ]
   configs -= [ "//gn/standalone:extra_warnings" ]
   public_configs = [ ":sqlite_config" ]
-  deps = [
-    "//gn:default_deps",
-  ]
 }
 
 source_set("sqlite_shell") {
-  visibility = _buildtools_visibility
   testonly = true
   sources = [
     "sqlite/shell.c",
@@ -675,12 +623,10 @@
   configs -= [ "//gn/standalone:extra_warnings" ]
   deps = [
     ":sqlite",
-    "//gn:default_deps",
   ]
 }
 
 source_set("lzma") {
-  visibility = _buildtools_visibility
   defines = [ "_7ZIP_ST" ]
   sources = [
     "lzma/C/7zAlloc.c",
@@ -726,13 +672,9 @@
     "-Wno-empty-body",
     "-Wno-enum-conversion",
   ]
-  deps = [
-    "//gn:default_deps",
-  ]
 }
 
 source_set("zlib") {
-  visibility = _buildtools_visibility
   sources = [
     "zlib/src/adler32.c",
     "zlib/src/compress.c",
@@ -753,14 +695,14 @@
   configs -= [ "//gn/standalone:extra_warnings" ]
   cflags = []
   public_configs = [ ":zlib_config" ]
-  deps = [
-    "//gn:default_deps",
-  ]
 }
 
 config("zlib_config") {
-  visibility = _buildtools_visibility
-  defines = [ "HAVE_HIDDEN" ]
+  defines = [
+    "ZLIB_CONST",
+    "USE_MMAP",
+    "HAVE_HIDDEN",
+  ]
   cflags = [
     # Using -isystem instead of include_dirs (-I), so we don't need to suppress
     # warnings coming from third-party headers. Doing so would mask warnings in
@@ -771,7 +713,6 @@
 }
 
 source_set("libunwindstack") {
-  visibility = _buildtools_visibility
   include_dirs = [
     "android-core/libunwindstack/include",
     "android-core/libunwindstack",
@@ -783,7 +724,6 @@
   ]
   deps = [
     ":lzma",
-    "//gn:default_deps",
   ]
   sources = [
     "android-core/base/file.cpp",
@@ -834,7 +774,6 @@
 }
 
 config("jsoncpp_config") {
-  visibility = _buildtools_visibility
   cflags = [
     "-DJSON_USE_EXCEPTION=0",
 
@@ -847,7 +786,6 @@
 }
 
 source_set("jsoncpp") {
-  visibility = _buildtools_visibility
   sources = [
     "jsoncpp/src/lib_json/json_reader.cpp",
     "jsoncpp/src/lib_json/json_value.cpp",
@@ -855,13 +793,9 @@
   ]
   configs -= [ "//gn/standalone:extra_warnings" ]
   public_configs = [ ":jsoncpp_config" ]
-  deps = [
-    "//gn:default_deps",
-  ]
 }
 
 config("linenoise_config") {
-  visibility = _buildtools_visibility
   cflags = [
     # Using -isystem instead of include_dirs (-I), so we don't need to suppress
     # warnings coming from third-party headers. Doing so would mask warnings in
@@ -872,22 +806,16 @@
 }
 
 source_set("linenoise") {
-  visibility = _buildtools_visibility
   sources = [
     "linenoise/linenoise.c",
     "linenoise/linenoise.h",
   ]
   configs -= [ "//gn/standalone:extra_warnings" ]
   public_configs = [ ":linenoise_config" ]
-  cflags = [ "-Wno-tautological-unsigned-zero-compare" ]
-  deps = [
-    "//gn:default_deps",
-  ]
 }
 
 if (use_libfuzzer) {
   source_set("libfuzzer") {
-    visibility = _buildtools_visibility
     configs -= [
       "//gn/standalone:extra_warnings",
       "//gn/standalone/sanitizers:sanitizers_cflags",
@@ -898,9 +826,8 @@
       "libfuzzer/FuzzerDriver.cpp",
       "libfuzzer/FuzzerExtFunctionsDlsym.cpp",
       "libfuzzer/FuzzerExtFunctionsWeak.cpp",
-      "libfuzzer/FuzzerExtFunctionsWindows.cpp",
+      "libfuzzer/FuzzerExtFunctionsWeakAlias.cpp",
       "libfuzzer/FuzzerExtraCounters.cpp",
-      "libfuzzer/FuzzerFork.cpp",
       "libfuzzer/FuzzerIO.cpp",
       "libfuzzer/FuzzerIOPosix.cpp",
       "libfuzzer/FuzzerIOWindows.cpp",
@@ -909,6 +836,7 @@
       "libfuzzer/FuzzerMerge.cpp",
       "libfuzzer/FuzzerMutate.cpp",
       "libfuzzer/FuzzerSHA1.cpp",
+      "libfuzzer/FuzzerShmemPosix.cpp",
       "libfuzzer/FuzzerTracePC.cpp",
       "libfuzzer/FuzzerUtil.cpp",
       "libfuzzer/FuzzerUtilDarwin.cpp",
@@ -917,8 +845,5 @@
       "libfuzzer/FuzzerUtilPosix.cpp",
       "libfuzzer/FuzzerUtilWindows.cpp",
     ]
-    deps = [
-      "//gn:default_deps",
-    ]
   }
 }
diff --git a/codereview.settings b/codereview.settings
index f6b44a5..4716bfe 100644
--- a/codereview.settings
+++ b/codereview.settings
@@ -1,4 +1,5 @@
 # For depot_tools / git cl upload workflow.
 GERRIT_HOST: True
+GERRIT_SQUASH_UPLOADS: True
 CODE_REVIEW_SERVER: https://android-review.googlesource.com
 PROJECT: platform/external/perfetto
diff --git a/docs/build-instructions.md b/docs/build-instructions.md
index f2bfe35..ec74c02 100644
--- a/docs/build-instructions.md
+++ b/docs/build-instructions.md
@@ -43,7 +43,6 @@
 target_os = "android"                 # Only when building for Android
 target_cpu = "arm" / "arm64" / "x64"  # Only when building for Android
 is_debug = true / false
-cc_wrapper = "ccache"                 # Optionally speed repeated builds with ccache
 ```
 
 (See the [Build Configurations](#build-configurations) section below for more)
@@ -126,11 +125,6 @@
 `cc = "gcc" / cxx = "g++"`:  
 Uses a different compiler binary (default: autodetected depending on is_clang).
 
-`cc_wrapper = "tool"`:  
-Prepends all build commands with a wrapper command. Using `"ccache"` here
-enables the [ccache](https://github.com/ccache/ccache) caching compiler,
-which can considerable speed up repeat builds.
-
 `is_asan = true`:  
 Enables [Address Sanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer)
 
diff --git a/docs/clock-sync.md b/docs/clock-sync.md
deleted file mode 100644
index 160f505..0000000
--- a/docs/clock-sync.md
+++ /dev/null
@@ -1,240 +0,0 @@
-# Synchronization of multiple clock domains
-
-As per [6756fb05][6756fb05] Perfetto allows to deal with events using different
-clock domains. On top of the default set of builtin clock domains, new clock
-domains can be dynamically created at trace-time.
-
-Clock domains are allowed to drift from each other.
-At import time, Perfetto's [Trace Processor](/docs/trace-processor.md) is able
-to rebuild the clock graph and use that to re-synchronize events on a global
-trace time, as long as [ClockSnapshot][clock_snapshot] packets are present in
-the trace.
-
-Problem statement
------------------
-In a complex multi-producer scenario, different data source can emit events
-using different clock domains.
-
-Some examples:
-
-* On Linux/Android, Ftrace events are emitted using the `CLOCK_BOOTTIME` clock,
-  but the Android event log uses `CLOCK_REALTIME`.
-  Some other data sources can use `CLOCK_MONOTONIC`.
-  These clocks can drift over time from each other due to suspend/resume.
-* Graphics-related events are typically timestamped by the GPU, which can use a
-  hardware clock source that drifts from the system clock.
-
-At trace-time, the data sources might not be able to use `CLOCK_BOOTTIME` (or
-even when possible, doing so might be prohibitively expensive).
-
-To solve this, we allow events to be recorded with different clock domains and
-re-synchronize them at import time using clock snapshots.
-
-Trace proto syntax
-------------------
-
-Clock synchronization is based on two elements of the trace:
-
-### 1. The [`timestamp_clock_id`][timestamp_clock_id] field of TracePacket
-
-```proto
-message TracePacket {
-  optional uint64 timestamp = 8;
-
-  // Specifies the ID of the clock used for the TracePacket |timestamp|. Can be
-  // one of the built-in types from ClockSnapshot::BuiltinClocks, or a
-  // producer-defined clock id.
-  // If unspecified it defaults to BuiltinClocks::BOOTTIME.
-  optional uint32 timestamp_clock_id = 58;
-
-```
-
-This (optional) field determines the clock domain for the packet.
-If omitted it refers to the default clock domain of the trace
-(`CLOCK_BOOTTIME` for Linux/Android).
-It present, this field can be set to either:
-
-* One of the [builtin clocks defined in clock_snapshot.proto][builtin_clocks]
-  (e.g., `CLOCK_BOOTTIME`, `CLOCK_REALTIME`, `CLOCK_MONOTONIC`). These clocks
-  have an ID <= 63.
-* A custom sequence-scoped clock, with 64 <= ID < 128
-* A custom globally-scoped clock, with 128 <= ID < 2**32
-
-#### Builtin clocks
-Builtin clocks cover the most common case of data sources using one of the
-POSIX clocks (see `man clock_gettime`). These clocks are periodically
-snapshotted by the `traced` service. The producer doesn't need to do anything
-else other than setting the `timestamp_clock_id` field in order to emit events
-that are use these clocks.
-
-#### Sequence-scoped clocks
-Sequence-scoped clocks are application-defined clock domains that are valid only
-within the sequence of TracePacket(s) written by the same `TraceWriter`
-(i.e. TracePacket that have the same `trusted_packet_sequence_id` field).
-In most cases this really means *"events emitted by the same data source on
-the same thread"*.
-
-This covers the most common use case of a clock domain that is used only within
-a data source and not shared across different data sources.
-The main advantage of sequence-scoped clocks is that avoids the ID
-disambiguation problem and JustWorks&trade; for the most simple cases.
-
-In order to make use of a custom sequence-scoped clock domain a data source
-must:
-
-* Emit its packets with a `timestamp_clock_id` in the range [64, 127]
-* Emit at least once a [`ClockSnapshot`][clock_snapshot] packet.
-
-Such `ClockSnapshot`:
-
-* Must be emitted on the same sequence (i.e. by the same `TraceWriter`) that is
-  used to emit other `TracePacket`(s) that refer to such `timestamp_clock_id`.
-* Must be emitted before the custom clock is referred to by any `TracePacket`
-  written by the same `TraceWriter`.
-* Must contain a snapshot of: (i) the custom clock id [64, 127] and (ii) another
-  clock domain that can be resolved, at import time, against the default trace
-  clock domain (`CLOCK_BOOTTIME`) (see the [Operation section](#operation)
-  below).
-
-Collisions of `timestamp_clock_id` across two different `TraceWriter` sequences
-are okay. E.g., two data sources, unaware of each other, can both use clock ID
-64 to refer to two different clock domains.
-
-#### Globally-scoped clocks
-Globally-scoped clock domains work similarly to sequence-scoped clock domains,
-with the only difference that their scope is global and applies to all
-`TracePacket`(s) of the trace.
-
-The same `ClockSnapshot` rules as above apply. The only difference is that once
-a `ClockSnapshot` defines a clock domain with ID >= 128, that clock domain can
-be referred to by any `TracePacket` written by any `TraceWriter` sequence.
-
-Care must be taken to avoid collisions between global clock domains defined by
-different data sources unaware of each other.
-
-As such, it is **strongly discouraged** to just use the ID 128 (or any other
-arbitrarily chosen value). Instead the recommended pattern is:
-
-* Chose a fully qualified name for the clock domain
-  (e.g. `com.example.my_subsystem`)
-* Chose the clock ID as `(HASH("com.example.my_subsystem") + 128) & 0xFFFFFFF`
-  where `HASH(x)` is the FNV-1a hash of the fully qualified clock domain name.
-
-### 2. The [`ClockSnapshot`][clock_snapshot] trace packet
-
-The [`ClockSnapshot`][clock_snapshot] packet defines sync points between two or
-more clock domains. It conveys the notion *"at this point in time, the timestamp
-of the clock domains X,Y,Z was 1000, 2000, 3000."*.
-
-The trace importer ([Trace Processor](/docs/trace-processor.md)) uses this
-information to establish a mapping between these clock domain. For instance,
-to realize that 1042 on clock domain X == 3042 on clock domain Z.
-
-The `traced` service automatically emits `ClockSnapshot` packets for the builtin
-clock domains on a regular basis.
-
-A data source should emit `ClockSnapshot` packets only when using custom clock
-domains, either sequence-scoped or globally-scoped.
-
-It is *not* mandatory that the `ClockSnapshot` for a custom clock domain
-contains also a snapshot of `CLOCK_BOOTTIME` (although it is advisable to do
-so when possible). The Trace Processor can deal with multi-path clock domain
-resolution based on graph traversal (see the [Operation](#operation) section).
-
-## Operation
-
-At import time Trace Processor will attempt to convert the timestamp of each
-TracePacket down to the trace clock domain (`CLOCK_BOOTTIME`) using the
-`ClockSnapshot` packets seen until then using nearest neighbor approximation.
-
-For instance, assume that the trace contains `ClockSnapshot` for
-`CLOCK_BOOTTIME` and `CLOCK_MONOTONIC` as follows:
-
-```python
-CLOCK_MONOTONIC     1000    1100   1200   1900  ...  2000   2100
-CLOCK_BOOTTIME      2000    2100   2200   2900  ...  3500   3600
-```
-
-In this example `CLOCK_MONOTONIC` is 1000 ns ahead of `CLOCK_BOOTTIME` until
-T=2900. Then the two clocks go out of sync (e.g. the device is suspended) and,
-on the next snapshot, the two clocks are 1500 ns apart.
-
-If a `TracePacket` with `timestamp_clock_id=CLOCK_MONOTONIC` and
-`timestamp=1104` is seen, the clock sync logic will:
-
-1. Find the latest snapshot for `CLOCK_MONOTONIC` <= 1104 (in the example above
-   the 2nd one with `CLOCK_MONOTONIC=1100`)
-2. Compute the clock domain conversion to `CLOCK_BOOTTIME` by applying the
-   delta (1104 - 1100) to the corresponding `CLOCK_BOOTTIME` snapshot
-   (2100, so 2100 + (1104 - 1100) -> 2104).
-
-The example above is rather simple, because the source clock domain  (i.e. the
-one specified by the `timestamp_clock_id` field) and the target clock domain
-(i.e. the trace time, `CLOCK_BOTTIME`) are snapshotted within the same
-`ClockSnapshot` packets.
-
-Clock domain conversion is possible also in more complex scenarios where the
-two domains are not directly connected, as long as a path exist between the two.
-
-In this sense `ClockSnapshot` packets define edges of an acyclic graph that is
-queried to perform clock domain conversions. All types of clock domains can be
-used in the graph search.
-
-In the more general case, the clock domain conversion logic operates as follows:
-
-* The shortest path between the source and target clock domains is identified,
-  using a breadth first search in the graph.
-* For each clock domain of the path identified, the timestamp is converted using
-  the aforementioned nearest neighbor resolution.
-
-This allows to deal with complex scenarios as follows:
-
-```python
-CUSTOM_CLOCK        1000                 3000
-CLOCK_MONOTONIC     1100       1200      3200          4000
-CLOCK_BOOTTIME                 5200                    9000
-```
-
-In the example above, there is no snapshot that directly links `CUSTOM_CLOCK`
-and `CLOCK_BOOTTIME`. However there is an indirect path that allows a conversion
-via `CUSTOM_CLOCK -> CLOCK_MONOTONIC -> CLOCK_BOOTTIME`.
-
-This allows to synchronize a hypothetical `TracePacket` that has
-`timestamp_clock_id=CUSTOM_CLOCK` and `timestamp=3503` as follows:
-
-```python
-#Step 1
-CUSTOM_CLOCK = 3503
-Nearest snapshot: {CUSTOM_CLOCK:3000, CLOCK_MONOTONIC:3200}
-CLOCK_MONOTONIC = (3503 - 3000) + 3200 = 3703
-
-#Step 2
-CLOCK_MONOTONIC = 3703
-Nearest snapshot: {CLOCK_MONOTONIC:1200, CLOCK_BOOTTIME:5200}
-CLOCK_BOOTTIME = (3703 - 1200) + 5200 = 7703
-```
-
-Caveats
--------
-Clock resolution between two domains (A,B) is allowed only as long as all the
-clock domains in the A -> B path are monotonic (or at least look so in the
-`ClockSnapshot` packets).
-If non-monotonicity is detected at import time, the clock domain is excluded as
-a source path in the graph search and is allowed only as a target path.
-
-For instance, imagine capturing a trace that has both `CLOCK_BOOTTIME`
-and `CLOCK_REALTIME` in the night when daylight saving is applied, when the
-real-time clock jumps back from 3AM to 2AM.
-
-Such a trace would contain several snapshots that break bijectivity between the
-two clock domains. In this case converting a `CLOCK_BOOTTIME` timestamp to
-`CLOCK_REALTIME` is always possible without ambiguities (eventually two distinct
-timestamps can be resolved against the same `CLOCK_REALTIME` timestamp).
-The opposite is not allowed, because `CLOCK_REALTIME` timestamps between 2AM
-and 3AM are ambiguous and could be resolved against two different
-`CLOCK_BOOTTIME` timestamps).
-
-[6756fb05]: https://android-review.googlesource.com/c/platform/external/perfetto/+/1101915/
-[clock_snapshot]: https://android.googlesource.com/platform/external/perfetto/+/refs/heads/master/protos/perfetto/trace/clock_snapshot.proto
-[timestamp_clock_id]: https://android.googlesource.com/platform/external/perfetto/+/3e7ca4f5893f7d762ec24a2eac9a47343b226c6c/protos/perfetto/trace/trace_packet.proto#68
-[builtin_clocks]: https://android.googlesource.com/platform/external/perfetto/+/3e7ca4f5893f7d762ec24a2eac9a47343b226c6c/protos/perfetto/trace/clock_snapshot.proto#25
diff --git a/docs/continuous-integration.md b/docs/continuous-integration.md
deleted file mode 100644
index 024db52..0000000
--- a/docs/continuous-integration.md
+++ /dev/null
@@ -1,357 +0,0 @@
-# Continuous Integration
-
-This CI is used on-top (not in replacement of) AOSP's TreeHugger.
-It gives early testing signals and coverage on other OSes and older Android
-devices not supported by TreeHugger.
-
-See the [Testing](testing.md) page for more details about the project testing
-strategy.
-
-## Architecture diagram
-
-![Architecture diagram](https://storage.googleapis.com/perfetto/markdown_img/continuous-integration.png)
-
-There are four major components:
-
-1. Frontend: AppEngine.
-2. Controller: AppEngine BG service.
-3. Workers: Compute Engine + Docker.
-4. Database: Firebase realtime database.
-
-They are coupled via the Firebase DB. The DB is the source of truth for the
-whole CI.
-
-## Controller
-
-The Controller orchestrates the CI. It's the most trusted piece of the system.
-
-It is based on a background AppEngine service. Such service is only
-triggered by deferred tasks and periodic Cron jobs.
-
-The Controller is the only entity which does authenticated access to Gerrit.
-It uses a non-privileged gmail account and has no meaningful voting power.
-
-The controller loop does mainly the following:
-
-- It periodically (every 5s) polls Gerrit for CLs updated in the last 24h.
-- It checks the list of CLs against the list of already known CLs in the DB.
-- For each new CL it enqueues `N` new jobs in the database, one for each
-  configuration defined in [config.py](/infra/ci/config.py) (e.g. `linux-debug`,
-  `android-release`, ...).
-- It monitors the state of jobs. When all jobs for a CL have been completed,
-  it posts a comment and adds the vote if the CL is marked as `Presubmit-Ready`.
-- It does some other less-relevant bookkeeping.
-- AppEngine is highly reliable and self-healing. If a task fails (e.g. because
-  of a Gerrit 500) it will be automatically re-tried with exponential backoff.
-
-## Frontend
-
-The frontend is an AppEngine service that hosts the CI website @
-[ci.perfetto.dev](https://ci.perfetto.dev).
-Conversely to the Controller, it is exposed to the public via HTTP.
-
-- It's an almost fully static website based on HTML and Javascript.
-- The only backend-side code ([frontend.py](/infra/ci/frontend/frontend.py))
-  is used to proxy XHR GET requests to Gerrit, due to the lack of Gerrit
-  CORS headers.
-- Such XHR requests are GET-only and anonymous.
-- The frontend python code also serves as a memcache layer for Gerrit requests
-  that return immutable data (e.g. revision logs) to reduce the likeliness of
-  hitting Gerrit errors / timeouts.
-
-## Worker GCE VM
-
-The actual testing job happens inside these Google Compute Engine VMs.
-The GCE instance is running a CrOS-based
-[Container-Optimized](https://cloud.google.com/container-optimized-os/docs/) OS.
-
-The whole system image is read-only. The VM itself is stateless. No state is
-persisted outside of the DB and Google Cloud Storage (only for UI artifacts).
-The SSD is used only as a scratch disk and is cleared on each reboot.
-
-VMs are dynamically spawned using the Google Cloud Autoscaler and use a
-Stackdriver Custom Metric pushed by the Controller as cost function.
-Such metric is the number of queued + running jobs.
-
-Each VM runs two types of Docker containers: _worker_ and the _sandbox_.
-They are in a 1:1 relationship, each worker controls at most one sandbox
-associated. Workers are always alive (they work in polling-mode), while
-sandboxes are started and stopped by the worker on-demand.
-
-On each GCE instance there are M (currently 10) worker containers running and
-hence up to M sandboxes.
-
-### Worker containers
-
-Worker containers are trusted entities. They can impersonate the GCE service
-account and have R/W access to the DB. They can also spawn sandbox containers.
-
-Their behavior depends only on code that is manually deployed and doesn't depend
-on the checkout under test. The reason why workers are Docker containers is NOT
-security but only reproducibility and maintenance.
-
-Each worker does the following:
-
-- Poll for an available job from the `/jobs_queued` sub-tree of the DB.
-- Move such job into `/jobs_running`.
-- Start the sandbox container, passing down the job config and the git revision
-  via env vars.
-- Stream the sandbox stdout to the `/logs` sub-tree of the DB.
-- Terminate the sandbox container prematurely in case of timeouts or job
-  cancellations requested by the Controller.
-- Upload UI artifacts to GCS.
-- Update the DB to reflect completion of jobs, removing the entry from
-  `/jobs_running` and updating the `/jobs/$jobId/status` fields.
-
-### Sandbox containers
-
-Sandbox containers are untrusted entities. They can access the internet
-(for git pull / install-build-deps) but they cannot impersonate the GCE service
-account, cannot write into the DB, cannot write into GCS buckets.
-Docker here is used both as an isolation boundary and for reproducibility /
-debugging.
-
-Each sandbox does the following:
-
-- Checkout the code at the revision specified in the job config.
-- Run one of the [test/ci/](/test/ci/) scripts which will build and run tests.
-- Return either a success (0) or fail (!= 0) exit code.
-
-A sandbox container is almost completely stateless with the only exception of
-the semi-ephemeral `/ci/cache` mount-point. This mount-point is tmpfs-based
-(hence cleared on reboot) but is shared across all sandboxes. It's used only to
-maintain the shared ccache.
-
-# Data model
-
-The whole CI is based on
-[Firebase Realtime DB](https://firebase.google.com/docs/database).
-It is a high-scale JSON object accessible via a simple REST API.
-Clients can GET/PUT/PATCH/DELETE individual sub-nodes without having a local
-full-copy of the DB.
-
-```bash
-/ci
-    # For post-submit jobs.
-    /branches
-        /master-20190626000853
-        # ┃     ┗━ Committer-date of the HEAD of the branch.
-        # ┗━ Branch name
-        {
-            author: "primiano@google.com"
-            rev: "0552edf491886d2bb6265326a28fef0f73025b6b"
-            subject: "Cloud-based CI"
-            time_committed: "2019-07-06T02:35:14Z"
-            jobs:
-            {
-                20190708153242--branches-master-20190626000853--android-...: 0
-                20190708153242--branches-master-20190626000853--linux-...:  0
-                ...
-            }
-        }
-        /master-20190701235742 {...}
-
-    # For pre-submit jobs.
-    /cls
-        /1000515-65
-        {
-            change_id:    "platform%2F...~I575be190"
-            time_queued:  "2019-07-08T15:32:42Z"
-            time_ended:   "2019-07-08T15:33:25Z"
-            revision_id:  "18c2e4d0a96..."
-            wants_vote:   true
-            voted:        true
-            jobs: {
-                20190708153242--cls-1000515-65--android-clang:  0
-                ...
-                20190708153242--cls-1000515-65--ui-clang:       0
-            }
-        }
-        /1000515-66 {...}
-        ...
-        /1011130-3 {...}
-
-    /cls_pending
-       # Effectively this is an array of pending CLs that we might need to
-       # vote on at the end. Only the keys matter, the values have no
-       # semantic and are always 0.
-       /1000515-65: 0
-
-    /jobs
-        /20190708153242--cls-1000515-65--android-clang-arm-debug:
-        #  ┃               ┃             ┗━ Job type.
-        #  ┃               ┗━ Path of the CL or branch object.
-        #  ┗━ Datetime when the job was created.
-        {
-            src:          "cls/1000515-66"
-            status:       "QUEUED"
-                          "STARTED"
-                          "COMPLETED"
-                          "FAILED"
-                          "TIMED_OUT"
-                          "CANCELLED"
-                          "INTERRUPTED"
-            time_ended:   "2019-07-07T12:47:22Z"
-            time_queued:  "2019-07-07T12:34:22Z"
-            time_started: "2019-07-07T12:34:25Z"
-            type:         "android-clang-arm-debug"
-            worker:       "zqz2-worker-2"
-        }
-        /20190707123422--cls-1000515-66--android-clang-arm-rel {..}
-
-    /jobs_queued
-        # Effectively this is an array. Only the keys matter, the values
-        # have no semantic and are always 0.
-        /20190708153242--cls-1000515-65--android-clang-arm-debug: 0
-
-    /jobs_running
-        # Effectively this is an array. Only the keys matter, the values
-        # have no semantic and are always 0.
-        /20190707123422--cls-1000515-66--android-clang-arm-rel
-
-    /logs
-        /20190707123422--cls-1000515-66--android-clang-arm-rel
-            /00a053-0000: "+ chmod 777 /ci/cache /ci/artifacts"
-            # ┃      ┗━ Monotonic counter to establish total order on log lines
-            # ┃         retrieved within the same read() batch.
-            # ┃
-            # ┗━ Hex-encoded timestamp, relative since start of test.
-            /00a053-0001: "+ chown perfetto.perfetto /ci/ramdisk"
-            ...
-
-```
-
-# Sequence Diagram
-
-This is what happens, in order, on a worker instance from boot to the test run.
-
-```bash
-make -C /infra/ci worker-start
-┗━ gcloud start ...
-
-[GCE] # From /infra/ci/worker/gce-startup-script.sh
-docker run worker-1 ...
-...
-docker run worker-N ...
-
-[worker-X] # From /infra/ci/worker/Dockerfile
-┗━ /infra/ci/worker/worker.py
-  ┗━ docker run sandbox-X ...
-
-[sandbox-X] # From /infra/ci/sandbox/Dockerfile
-┗━ /infra/ci/sandbox/init.sh
-  ┗━ /infra/ci/sandbox/testrunner.sh
-    ┣━ git fetch refs/changes/...
-    ┇  ...
-    ┇  # This env var is passed by the test definition
-    ┇  # specified in /infra/ci/config.py .
-    ┗━ $PERFETTO_TEST_SCRIPT
-       ┣━ # Which is one of these:
-       ┣━ /test/ci/android_tests.sh
-       ┣━ /test/ci/fuzzer_tests.sh
-       ┣━ /test/ci/linux_tests.sh
-       ┗━ /test/ci/ui_tests.sh
-          ┣━ ninja ...
-          ┗━ out/dist/{unit,integration,...}test
-```
-
-### [gce-startup-script.sh](/infra/ci/worker/gce-startup-script.sh)
-
-- Is ran once per GVE vm, at (re)boot.
-- It prepares the tmpfs mountpoint for the shared ccache.
-- It wipes the SSD scratch disk for the build artifacts
-- It pulls the latest {worker, sandbox} container images from
-  the Google Cloud Container registry.
-- Sets up Docker and `iptables` (for the sandboxed network).
-- Starts `N` worker containers in Docker.
-
-### [worker.py](/infra/ci/worker/worker.py)
-
-- It polls the DB to retrieve a job.
-- When a job is retrieved starts a sandbox container.
-- It streams the container stdout/stderr to the DB.
-- It upload the build artifacts to GCS.
-
-### [testrunner.sh](/infra/ci/sandbox/testrunner.sh)
-
-- It is pinned in the container image. Does NOT depend on the particular
-  revision being tested.
-- Checks out the repo at the revision specified (by the Controller) in the
-  job config pulled from the DB.
-- Sets up ccache
-- Deals with caching of buildtools/.
-- Runs the test script specified in the job config from the checkout.
-
-### [{android,fuzzer,linux,ui}_tests.sh](/test/ci/linux_tests.sh)
-
-- Are NOT pinned in the container and are ran from the checked out revision.
-- Finally build and run the test.
-
-## Playbook
-
-### Frontend (JS/HTML/CSS) changes
-
-Test-locally: `make -C infra/ci/frontend test`
-
-Deploy with `make -C infra/ci/frontend deploy`
-
-### Controller changes
-
-Deploy with `make -C infra/ci/controller deploy`
-
-It is possible to try locally via the `make -C infra/ci/controller test`
-but this involves:
-
-- Manually stopping the production AppEngine instance via the Cloud Console
-  (stopping via the `gcloud` cli doesn't seem to work, b/136828660)
-- Downloading the testing service credentials `test-credentials.json`
-  (they are in the internal Team drive).
-
-### Worker/Sandbox changes
-
-1. Build and push the new docker containers with:
-
-   `make -C infra/ci build push`
-
-2. Restart the GCE instances, either manually or via
-
-   `make -C infra/ci restart-workers`
-
-
-## Security considerations
-
-- Both the Firebase DB and the gs://perfetto-artifacts GCS bucket are
-  world-readable and writable by the GAE and GCE service accounts.
-
-- The GAE service account also has the ability to log into Gerrit using a
-  dedicated gmail.com account. The GCE service account doesn't.
-
-- Overall, no account in this project has any interesting privilege:
-  - The Gerrit account used for commenting on CLs is just a random gmail account
-    and has no special voting power.
-  - The service accounts of GAE and GCE don't have any special capabilities
-    outside of the CI project itself.
-
-- This CI deals only with functional and performance testing and doesn't deal
-  with any sort of continuous deployment.
-
-- Presubmit jobs are only triggered if at least one of the following is true:
-  - The owner of the CL is a @google.com account.
-  - The user that applied the Presubmit-Ready label is a @google.com account.
-
-- Sandboxes are not too hard to escape (Docker is the only boundary) and can
-  pollute each other via the shared ccache.
-
-- As such neither pre-submit nor post-submit build artifacts are considered
-  trusted. They are only used for establishing functional correctness and
-  performance regression testing.
-
-- Binaries built by the CI are not ran on any other machines outside of the
-  CI project. They are deliberately not downloadable.
-
-- The only build artifacts that are retained (for up to 30 days) and uploaded to
-  the GCS bucket are the UI artifacts. This is for the only sake of getting
-  visual previews of the HTML changes.
-
-- UI artifacts are served from a different origin (the GCS per-bucket API) than
-  the production UI.
diff --git a/docs/contributing.md b/docs/contributing.md
index ff70e62..d4da7bb 100644
--- a/docs/contributing.md
+++ b/docs/contributing.md
@@ -13,21 +13,11 @@
 ### Continuous integration
 
 Continuous build and test coverage is available at
-[ci.perfetto.dev](https://ci.perfetto.dev).
+[perfetto-ci.appspot.com](https://perfetto-ci.appspot.com).
 
-**Trybots**:  
-CLs uploaded to gerrit are automatically submitted to the CI and
-and available on the CI page.
-If the label `Presubmit-Ready: +1` is set, the CI will also publish a comment
-like [this][ci-example] on the CL.
-
-### Community
-
-You can reach us on our [Discord channel](https://discord.gg/35ShE3A).
-If you prefer using IRC we have an experimental Discord <> IRC bridge
-synced with `#perfetto-dev` on [Freenode](https://webchat.freenode.net/).
+**Trybots**: CLs uploaded to gerrit are automatically submitted to TravisCI
+within one minute and available on the CI page.
 
 [perfetto-gerrit]: https://android-review.googlesource.com/q/project:platform%252Fexternal%252Fperfetto+status:open
 [google-cpp-style]: https://google.github.io/styleguide/cppguide.html
 [depot-tools]: https://dev.chromium.org/developers/how-tos/depottools
-[ci-example]: https://android-review.googlesource.com/c/platform/external/perfetto/+/1108253/3#message-09fd27fb92ca8357abade3ec725919ac3445f3af
diff --git a/docs/embedder-guide.md b/docs/embedder-guide.md
index fbe3be3..226e086 100644
--- a/docs/embedder-guide.md
+++ b/docs/embedder-guide.md
@@ -20,7 +20,7 @@
   - [service.h](/include/perfetto/tracing/core/tracing_service.h)
 - Explain the ABI surface:
   - [shared_memory_abi.h](/include/perfetto/tracing/core/shared_memory_abi.h)
-  - IPC's [wire protocol](/protos/perfetto/ipc/wire_protocol.proto) (if used)
+  - IPC's [wire protocol](/src/ipc/wire_protocol.proto) (if used)
   - The input [config protos](/protos/perfetto/config)
   - The output [trace protos](/protos/perfetto/trace)
 
diff --git a/docs/ftrace.md b/docs/ftrace.md
index 6e29fc5..c35d95c 100644
--- a/docs/ftrace.md
+++ b/docs/ftrace.md
@@ -12,5 +12,41 @@
 - Describe how to generate ftrace protos (`tools/pull_ftrace_format_files.py`,
   `tools/udate_protos.py`)
 - Describe how session multiplexing works.
+- Describe the page-by-page scheduling algorithm that uses vmsplice()
 
 Code lives in [/src/traced/probes/ftrace](/src/traced/probes/ftrace/).
+
+From https://android-review.googlesource.com/c/platform/external/perfetto/+/603793/
+```
+
+  main thread                           [drain] [unblock]
+                                        /:              |
+                            post .-----' :              |
+                                /        :              v
+  worker #0  [splice ...] [wakeup] [block ............] [splice]
+                                         :
+  worker #1  [splice ...]     [wakeup] [block ........] [splice]
+                                         :
+  worker #2  [splice ..........................................]
+                                         :
+                                         :
+                                    drain period (100ms)
+
+In other words, the splice(2) system call is used to move data from
+the raw kernel ftrace pipe into an intermediate pipe at a page
+granularity. This call allows every per-cpu worker to sleep until there
+is at least one page of data available.
+
+When a worker wakes up, it will attempt to move as many pages as
+possible to its staging pipe (up to 64K, depending on the
+system's pipe buffer size) in a non-blocking way. After this, it
+will notify the main thread that data is available. This notification
+will block the calling worker until the main thread has drained the
+data.
+
+When at least one worker has woken up, we schedule a drain operation
+on the main thread for the next drain period (every 100ms by default).
+The drain operation parses ftrace data from the staging pipes of
+every worker having pending data. After this, each waiting worker is
+allowed to issue another call to splice(), restarting the cycle.
+```
diff --git a/docs/heapprofd.md b/docs/heapprofd.md
index 469ebac..a34334b 100644
--- a/docs/heapprofd.md
+++ b/docs/heapprofd.md
@@ -1,12 +1,14 @@
 # heapprofd - Android Heap Profiler
 
-**heapprofd requires Android 10.**
+Googlers, for design doc see: http://go/heapprofd-design
+
+**heapprofd requires Android Q.**
 
 heapprofd is a tool that tracks native heap allocations & deallocations of an
 Android process within a given time period. The resulting profile can be used
 to attribute memory usage to particular function callstacks, supporting a mix
-of both native and java code. The tool can be used by Android platform and app
-developers to investigate memory issues.
+of both native and java code. The tool should be useful to Android platform
+developers, and app developers investigating memory issues.
 
 On debug Android builds, you can profile all apps and most system services.
 On "user" builds, you can only use it on apps with the debuggable or
@@ -16,9 +18,8 @@
 
 <!-- This uses github because gitiles does not allow to get the raw file. -->
 
-On Linux / MacOS, use the `tools/heap_profile` script to heap profile a
-process. If you are having trouble make sure you are using the
-[latest version](
+Use the `tools/heap_profile` script to heap profile a process. If you are
+having trouble make sure you are using the [latest version](
 https://raw.githubusercontent.com/catapult-project/perfetto/master/tools/heap_profile).
 
 See all the arguments using `tools/heap_profile -h`, or use the defaults
@@ -37,29 +38,22 @@
 
 The resulting profile proto contains four views on the data
 
-* **space**: how many bytes were allocated but not freed at this callstack the
+* space: how many bytes were allocated but not freed at this callstack the
   moment the dump was created.
-* **alloc\_space**: how many bytes were allocated (including ones freed at the
+* alloc\_space: how many bytes were allocated (including ones freed at the
   moment of the dump) at this callstack
-* **idle\_space**: if [idle page tracking](#idle-page-tracking) is being used,
-  the number of bytes that were allocated at this callstack and are on pages
-  that have not been touched since the last dump.
-* **objects**: how many allocations without matching frees were done at this
+* objects: how many allocations without matching frees were done at this
   callstack.
-* **alloc\_objects**: how many allocations (including ones with matching frees)
-  were done at this callstack.
+* alloc\_objects: how many allocations (including ones with matching frees) were
+  done at this callstack.
 
 **Googlers:** Head to http://pprof/ and upload the gzipped protos to get a
 visualization. *Tip: you might want to put `libart.so` as a "Hide regex" when
 profiling apps.*
 
-You can use the [Perfetto UI](https://ui.perfetto.dev) to visualize heap dumps.
-Upload the `raw-trace` file in your output directory. You will see all heap
-dumps as diamonds on the timeline, click any of them to get a flamegraph.
-
-Alternatively [Speedscope](https://speedscope.app) can be used to visualize
-the gzipped protos, but will only show the space view.
-*Tip: Click Left Heavy on the top left for a good visualisation.*
+[Speedscope](https://speedscope.app) can also be used to visualize the heap
+dump, but will only show the space view. *Tip: Click Left Heavy on the top
+left for a good visualisation.*
 
 ## Sampling interval
 heapprofd samples heap allocations. Given a sampling interval of n bytes,
@@ -128,16 +122,13 @@
 are not be eligible to be profiled.
 
 On user builds, only Java applications with either the profileable or the
-debuggable manifest flag set can be profiled. Profiling requests for other
+debugable manifest flag set can be profiled. Profiling requests for other
 processes will result in an empty profile.
 
 On userdebug builds, all processes except for a small blacklist of critical
-services can be profiled (to find the blacklist, look for
-`never_profile_heap` in [heapprofd.te](
-https://android.googlesource.com/platform/system/sepolicy/+/refs/heads/master/private/heapprofd.te)).
-This restriction can be lifted by disabling SELinux by running
-`adb shell su root setenforce 0` or by passing `--disable-selinux` to the
-`heap_profile` script.
+services can be profiled. This restriction can be lifted by disabling
+SELinux by running `adb shell su root setenforce 0` or by passing
+`--disable-selinux` to the `heap_profile` script.
 
 |                         | userdebug setenforce 0 | userdebug | user |
 |-------------------------|------------------------|-----------|------|
@@ -145,72 +136,7 @@
 | native service          |            y           |     y     |  n   |
 | app                     |            y           |     y     |  n   |
 | profileable app         |            y           |     y     |  y   |
-| debuggable app          |            y           |     y     |  y   |
-
-## DEDUPED frames
-If the name of a Java method includes `[DEDUPED]`, this means that multiple
-methods share the same code. ART only stores the name of a single one in its
-metadata, which is displayed here. This is not necessarily the one that was
-called.
-
-## Manual dumping
-You can trigger a manual dump of all currently profiled processes by running
-`adb killall -USR1 heapprofd`. This can be useful for seeing the current memory
-usage of the target in a specific state.
-
-This dump will show up in addition to the dump at the end of the profile that is
-always produced. You can create multiple of these dumps, and they will be
-enumerated in the output directory.
-
-## Symbolization
-If the profiled binary or libraries do not have debug symbols, you can use
-pprof to symbolize offline.
-
-To do so, copy symbolized versions of your binary and/or libraries into a
-directory. Then run
-`PPROF_BINARY_PATH=thatdirectory pprof heap_profile.${n}.${pid}.gz`, and pprof
-will read symbol information from these files.
-
-You can save the symbolized version by issuing the `proto` command in pprof.
-
-## Idle page tracking
-This is only available in Android versions newer than 10.
-
-Idle page tracking allows you to analyze which allocations made by your
-program are being used by a workload. This can be useful for finding leaks
-as well as unused cached values.
-
-**Do not follow these instructions on devices containing valuable data.**
-They require you turn off SELinux on your device, significantly lowering
-your device's security level.
-
-Use the following command to profile the next startup of your program with idle
-tracking enabled.
-
-1. `$ adb root`
-2. `$ tools/heap_profile -n ${NAME} --no-running --disable-selinux
---idle-allocations`
-
-Then run the following commands in a separate shell.
-
-1. `$ adb shell killall ${ROOT}` to restart your program.
-2. Wait for your program to finish starting.
-3. `adb shell killall -USR1 heapprofd` to trigger the first dump (see
-[Manual Dumping](#manual-dumping) above). This will mark all allocations as
-idle.
-4. Interact with your program.
-
-Once you are done interacting, `Ctrl-C` the invokation of
-`tools/heap_profile`, and upload the `heap_dump.2.*.pb.gz` file to pprof.
-You can then see the memory that was idle in the `idle_space` tab.
-
-This will show allocations that are on pages that have not been touched since
-the last dump. Small allocations that are not touched might not show up, as
-they might share a page with an allocation that was.
-
-If heapprofd is operating in sampling mode (i.e. `--interval` is larger than 1),
-the values in `idle_space` will not correct for the sampling, so they are not
-comparable to values in `space` and `alloc_space`, which do.
+| debugable app           |            y           |     y     |  y   |
 
 ## Troubleshooting
 
@@ -226,22 +152,9 @@
 Check whether your target process is eligible to be profiled by consulting
 [Target processes](#target-processes) above.
 
-Also check the [Known Issues](#known-issues).
-
-
-### Impossible callstacks
-If you see a callstack that seems to impossible from looking at the code, make
-sure no [DEDUPED frames](#deduped-frames) are involved.
-
 ## Known Issues
 
-### Android 10
 * Does not work on x86 platforms (including the Android cuttlefish emulator).
-* If heapprofd is run standalone (by running `heapprofd` in a root shell, rather
-  than through init), `/dev/socket/heapprofd` get assigned an incorrect SELinux
-  domain. You will not be able to profile any processes unless you disable
-  SELinux enforcement.
-  Run `restorecon /dev/socket/heapprofd` in a root shell to resolve.
 
 ## Ways to count memory
 
@@ -252,7 +165,7 @@
 **heapprofd** gives you the number of bytes the target program
 requested from the allocator. If you are profiling a Java app from startup,
 allocations that happen early in the application's initialization will not be
-visible to heapprofd. Native services that do not fork from the Zygote
+visibile to heapprofd. Native services that do not fork from the Zygote
 are not affected by this.
 
 **malloc\_info** is a libc function that gives you information about the
diff --git a/docs/index.html b/docs/index.html
index 4db856e..05c1ffd 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -50,8 +50,6 @@
   <script src="/static/docsify-themeable.min.js"></script>
   <script src="/static/docsify-copy-code.min.js"></script>
   <script src="/static/prism-bash.min.js"></script>
-  <script src="/static/prism-protobuf.min.js"></script>
-  <script src="/static/prism-sql.min.js"></script>
 </body>
 
-</html>
+</html>
\ No newline at end of file
diff --git a/docs/ipc.md b/docs/ipc.md
index ac7c36a..33d3a5c 100644
--- a/docs/ipc.md
+++ b/docs/ipc.md
@@ -18,7 +18,7 @@
 - Allows to send file descriptors over the wire: for setting up shared memory
   and passing the FD for the output trace from a consumer to the service.
 - Service definition uses same protobuf rpc syntax of [gRPC](https://grpc.io)
-- Extremely simple [wire protocol](/protos/perfetto/ipc/wire_protocol.proto).
+- Extremely simple [wire protocol](/src/ipc/wire_protocol.proto).
 - C++11 friendly, allows to bind `std::function` to each request.
 - Leak (un)friendly: tries hard to guarantee that callbacks are left unresolved,
   using C++11 move semantics.
@@ -31,7 +31,7 @@
 - Debugging friendly: single-thread only, based on non-blocking socket I/O.
 - Binary size friendly: generates one protobuf per message, doesn't have any
   external dependency.
-- Safe:
+- Hopefully safe:
   - The rx buffer has guard regions around.
   - The wire protocol is based on protobuf.
   - [Fuzzed](/src/ipc/buffered_frame_deserializer_fuzzer.cc)
diff --git a/docs/life-of-a-tracing-session.md b/docs/life-of-a-tracing-session.md
index c645e41..3ed34df 100644
--- a/docs/life-of-a-tracing-session.md
+++ b/docs/life-of-a-tracing-session.md
@@ -44,7 +44,7 @@
     service, requesting it to move some chunks of the shared memory buffer into
     the final trace buffer.
 17. If one or more long `TracePacket` were fragmented over several chunks, it is
-    possible that some of these chunks are gone from the shared memory
+    possible that some of these chunks are gone from the the shared memory
     buffer and committed into the final trace buffer (step 16). In this case,
     the `SharedMemoryArbiter` will send an other `CommitDataRequest` IPC message
     to request the out-of-band patching of the chunk data into the final trace
diff --git a/docs/long-traces.md b/docs/long-traces.md
index 0907e24..57e5c2d 100644
--- a/docs/long-traces.md
+++ b/docs/long-traces.md
@@ -4,8 +4,7 @@
 destination file (passed with the `-o` cmdline argument) only at the end of the
 trace, to reduce the intrusiveness of the tracing system.
 That, however, limits the max size of the trace to the physical memory size of
-the device.
-
+the device.  
 In some cases (e.g., benchmarks, hard to repro cases) it is desirable to capture
 traces that are way larger than that.
 
@@ -17,7 +16,7 @@
 `bool write_into_file`  
 When true drains periodically the trace buffers into the output
 file. When this option is enabled, the userspace buffers need to be just
-big enough to hold tracing data between two periods.
+big enough to hold tracing data between two periods.  
 The buffer sizing depends on the activity of the device. A reasonable estimation
 is ~5-20 MB per second.
 
@@ -35,8 +34,7 @@
 
 ## Instructions
 These instructions assume you have a working standalone checkout (see
-[instructions here](/docs/build-instructions.md)).
-
+[instructions here](/docs/build-instructions.md)).  
 These instructions have been tested as non-root. Many of the steps below can be
 simplified when running as root and are required due to SELinux when running as
 `shell` rather than `root`.
@@ -48,14 +46,14 @@
 $ tools/install-build-deps --no-android
 $ tools/gn gen out/mac_release --args="is_debug=false"
 
-# Compiles the textual protobuf into binary format
+# Compiles the textual protobuf into binary format 
 # for /test/configs/long_trace.cfg.
 $ tools/ninja -C out/mac_release/ long_trace.cfg.protobuf
 
 # Alternatively, the more verbose variant:
 $ protoc=$(pwd)/out/mac_release/gcc_like_host/protoc
 $ protoc --encode=perfetto.protos.TraceConfig \
-        -I$(pwd) \
+        -I$(pwd)/protos \
         $(pwd)/protos/perfetto/config/perfetto_config.proto \
         < /test/configs/long_trace.cfg \
         > /tmp/long_trace.cfg.protobuf
diff --git a/docs/metrics.md b/docs/metrics.md
deleted file mode 100644
index 6f4079b..0000000
--- a/docs/metrics.md
+++ /dev/null
@@ -1,356 +0,0 @@
-Writing Perfetto-based metrics
-=============
-
-Contents
----------
-1. Background
-2. The Perfetto Metrics Platform
-3. Writing your first metric - step by step
-4. Breaking down and composing metrics (TBD)
-5. Adding a new metric or editing an existing metric (TBD)
-6. Running a metric over a set of traces (TBD)
-7. Metrics platform as an API (TBD)
-
-Background
----------
-Using traces allows computation of reproducible metrics in a wide range
-of situations; examples include benchmarks, lab tests and on
-large corpuses of traces. In these cases, these metrics allow for direct
-root-causing when a regression is detected.
-
-The Perfetto Metrics Platform
-----------
-The metrics platform (powered by the
-[trace processor](trace-processor.md)) allows metrics authors to write
-SQL queries to generate metrics in the form of protobuf messages or proto text.
-
-We strongly encourage all metrics derived on Perfetto traces to be added to the
-Perfetto repo unless there is a clear usecase (e.g. confidentiality) why these
-metrics should not be publicly available.
-
-In return for upstreaming metrics, authors will have first class support for
-running metrics locally and the confidence that their metrics will remain stable
-as trace processor is developed.
-
-For example, generating the full (human readable) set of Android memory
-metrics on a trace is as simple as:
-```shell
-trace_processor_shell --run-metrics android_mem <trace>
-```
-
-As well as scaling upwards while developing from running on a single trace
-locally to running on a large set of traces, the reverse is also very useful.
-When an anomaly is observed in the metrics of a lab benchmark, you can simply
-download a representative trace and run the same metric locally in shell.
-
-Since the same code is running locally and remotely, you can be confident in
-reproducing the issue and use the power of trace processor and/or the Perfetto
-UI to identify the problem!
-
-Writing your first metric: A Step by Step Guide
-----------
-To begin, all you need is some familiarity with SQL and you're ready to start!
-
-Suppose that want a write a metric which computes the CPU time for every process
-in the trace and lists the names of the top 5 processes (by CPU time)
-and the number of threads which were associated with those processes over its
-lifetime.
-
-*Note:*
-* If you want to jump straight to the code, at the end of this guide, your
-workspace should look something like this [GitHub gist](https://gist.github.com/tilal6991/c221cf0cae17e298dfa82b118edf9080). See Step 0 and 4
-below as to where to get trace processor and how to run it to output the
-metrics.
-
-### Step 0
-As a setup step, you'll want to create a folder to act as a scratch workspace;
-this folder will be referred to using the env variable `$WORKSPACE` in Step 4.
-
-The other thing you'll need is trace processor shell. You can download this
-[here](https://get.perfetto.dev/trace_processor) or you can build from source
-using the instructions [here](trace-processor.md). Whichever method is
-chosen, $TRACE_PROCESSOR env variable will be used to refer to the location of
-the binary in Step 4.
-
-### Step 1
-As all metrics in the metrics platform are defined using protos, the metric
-needs to be strctured as a proto. For this metric, there needs to be some notion
-of a process name along with its CPU time and number of threads.
-
-Starting off, in a file named `top_five_processes.proto` in our workspace,
-let's create a basic proto message called ProcessInfo with those three fields:
-```protobuf
-message ProcessInfo {
-  optional string process_name = 1;
-  optional uint64 cpu_time_ms = 2;
-  optional uint32 num_threads = 3;
-}
-```
-
-Next up is a wrapping message which will hold the repeated field containing
-the top 5 processes.
-```protobuf
-message TopProcesses {
-  repeated ProcessInfo process_info = 1;
-}
-```
-
-Finally, let's define an extension to the root proto for all metrics -
-the
-[TraceMetrics](https://android.googlesource.com/platform/external/perfetto/+/HEAD/protos/perfetto/metrics/metrics.proto#39)
-proto).
-```protobuf
-extend TraceMetrics {
-  optional TopProcesses top_processes = 450;
-}
-```
-Adding this extension field allows trace processor to link the newly defined
-metric to the `TraceMetrics` proto.
-
-*Notes:*
-* The field ids 450-500 are reserved for local development so you can use
-any of them as the field id for the extension field.
-* The choice of field name here is important as the SQL file and the final
-table generated in SQL will be based on this name.
-
-Putting everything together, along with some boilerplate header information
-gives:
-```protobuf
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-import "protos/perfetto/metrics/metrics.proto";
-
-message ProcessInfo {
-  optional string process_name = 1;
-  optional int64 cpu_time_ms = 2;
-  optional uint32 num_threads = 3;
-}
-
-message TopProcesses {
-  repeated ProcessInfo process_info = 1;
-}
-
-extend TraceMetrics {
-  optional TopProcesses top_processes = 450;
-}
-```
-
-### Step 2
-Let's write the SQL to generate the table of the top 5 processes ordered
-by the sum of the CPU time they ran for and the number of threads which were
-associated with the process. The following SQL should be to a file called
-`top_five_processes.sql` in your workspace:
-```sql
-CREATE VIEW top_five_processes_by_cpu
-SELECT
-  process.name as process_name,
-  CAST(SUM(sched.dur) / 1e6 as INT64) as cpu_time_ms,
-  COUNT(DISTINCT utid) as num_threads
-FROM sched
-INNER JOIN thread USING(utid)
-INNER JOIN process USING(upid)
-GROUP BY process.name
-ORDER BY cpu_time_ms DESC
-LIMIT 5;
-```
-Let's break this query down:
-1. The first table used is the `sched` table. This contains all the
-   scheduling data available in the trace. Each scheduling "slice" is associated
-   with a thread which is uniquely identified in Perfetto traces using its
-   `utid`. The two pieces of information which needed from the sched table
-   is the `dur` - short for duration, this is the amount of time the slice
-   lasted - and the `utid` which will be use to join with the thread table.
-2. The next table is the thread table. This gives us a lot of information which
-   are not particularly interested (including its thread name) but it does give
-   us the `upid`. Similar to `utid`, `upid` is the unique identifier for a
-   process in a Perfetto trace. In this case, `upid` will refer to the process
-   which hosts the thread given by `utid`.
-3. The final table is the process table. This gives the name of the
-   process associated with the original sched slice.
-4. With the process, thread and duration for each sched slice, all the slices
-   for a single processes are collected and their durations summed to get the
-   CPU time (dividing by 1e6 as sched's duration is in nanoseconds) and count
-   the number of distinct threads.
-5. Finally, we order by the cpu time and take limit to the top 5.
-
-### Step 3
-Now that the result of the metric has been expressed as an SQL table, it needs
-to be converted a proto. The metrics platform has built-in support for emitting
-protos using SQL functions; something which is used extensively in this step.
-
-Let's look at how it works for our table above.
-```sql
-CREATE VIEW top_processes_output AS
-SELECT TopProcesses(
-  'process_info', (
-    SELECT RepeatedField(
-      ProcessInfo(
-        'process_name', process_name,
-        'cpu_time_ms', cpu_time_ms,
-        'num_threads', num_threads
-      )
-    )
-    FROM top_five_processes_by_cpu
-  )
-);
-```
-Let's break this down again:
-1. Starting from the inner-most SELECT statement, there is
-   what looks like a function call to the ProcessInfo function; in face this is
-   no conincidence. For each proto that the metrics platform knows about,
-   it generates a SQL function with the same name as the proto. This function
-   takes key value pairs with the key as the name of the proto field to fill
-   and the value being the data to store in the field. The output is the proto
-   created by writing the fields described in the function! (*)
-
-   In this case, this function is called once for each row in
-   the `top_five_processes_by_cpu` table. The output of will be the fully filled
-   ProcessInfo proto.
-
-   The call to the `RepeatedField` function is the most interesting part and
-   also the most important. In technical terms, `RepeatedField` is an aggregate
-   function; practically, this means that it takes a full table of values and
-   generates a single array which contains all the values passed to it.
-
-   Therefore, the output of this whole SELECT statement is an array of
-   5 ProcessInfo protos.
-2. Next is creation of the `TopProcesses` proto. By now, the syntax should
-   already feel somewhat familiar; the proto builder function is called
-   to fill in the `process_info` field with the array of protos from the
-   inner funciton.
-
-   The output of this SELECT is a single `TopProcesses` proto containing
-   the ProcessInfos as a repeated field.
-3. Finally, the view is created. This view is specially named to allow the
-   metrics platform to query it to obtain the root proto for each metric (in
-   this case `TopProcesses`). See the note below as to the pattern behind
-   this view's name.
-
-(*) - side note: this is not strictly true. To type-check the protos, we
-also return some metadata about the type of the proto but this is unimportant
-for metric authors
-
-*Note:*
-* It is important that the views be named
-  {name of TraceMetrics extension field}_output. This is the pattern used
-  and expected by the metrics platform for all metrics.
-
-And that's all the SQL we need to write! Our final file should look like so:
-```sql
-CREATE VIEW top_five_processes_by_cpu AS
-SELECT
-  process.name as process_name,
-  CAST(SUM(sched.dur) / 1e6 as INT64) as cpu_time_ms,
-  COUNT(DISTINCT utid) as num_threads
-FROM sched
-INNER JOIN thread USING(utid)
-INNER JOIN process USING(upid)
-GROUP BY process.name
-ORDER BY cpu_time_ms DESC
-LIMIT 5;
-
-CREATE top_processes_output AS
-SELECT TopProcesses(
-  'process_info', (
-    SELECT RepeatedField(
-      ProcessInfo(
-        'process_name', process_name,
-        'cpu_time_ms', cpu_time_ms,
-        'num_threads', num_threads
-      )
-    )
-    FROM top_five_processes_by_cpu
-  )
-);
-```
-
-*Notes:*
-* The name of the SQL file should be the same as the name of TraceMetrics
-  extension field. This is to allow the metrics platform to associated the
-  proto extension field with the SQL which needs to be run to generate it.
-
-### Step 4
-This is the last step and where we get to see the results of our work!
-
-For this step, all we need is a one-liner, invoking trace processor
-shell (see Step 0 for downloading it):
-```shell
-$TRACE_PROCESSOR --run-metrics $WORKSPACE/top_five_processes.sql $TRACE 2> /dev/null
-```
-(If you want a example trace to test this on, see the Notes section below.)
-
-By passing the SQL file for the metric we want to compute, trace processor uses
-the name of this file to both find the proto and also to figure out the name
-of the output table for the proto and the name of the extension field for
-`TraceMetrics`; this is why it was important to choose the names of these other
-objects carefully.
-
-*Notes:*
-* If something doesn't work as intended, check that your workspace looks the
-  same as the contents of this [GitHub gist](https://gist.github.com/tilal6991/c221cf0cae17e298dfa82b118edf9080).
-* A good example trace for this metric is the Android example trace used by
-  the Perfetto UI found [here](https://storage.googleapis.com/perfetto-misc/example_android_trace_30s_1)
-* We're redirecting stderror to remove any noise from parsing the trace that
-  trace processor generates.
-
-If everything went successfully, you should see something like the following
-(this is specifically the output for the Android example trace linked above):
-```
-[perfetto.protos.top_five_processes] {
-  process_info {
-    process_name: "com.google.android.GoogleCamera"
-    cpu_time_ms: 15154
-    num_threads: 125
-  }
-  process_info {
-    process_name: "sugov:4"
-    cpu_time_ms: 6846
-    num_threads: 1
-  }
-  process_info {
-    process_name: "system_server"
-    cpu_time_ms: 6809
-    num_threads: 66
-  }
-  process_info {
-    process_name: "cds_ol_rx_threa"
-    cpu_time_ms: 6684
-    num_threads: 1
-  }
-  process_info {
-    process_name: "com.android.chrome"
-    cpu_time_ms: 5125
-    num_threads: 49
-  }
-}
-```
-
-### Conclusion
-That finishes the introductory guide to writing an metric using the Perfetto
-metrics platform! For more information about where to go next, the following
-links may be useful:
-* To understand what data is available to you and how the SQL tables are
-  structured see the [trace processor](trace-processor.md) docs.
-* To see how you can use the RUN_METRIC function to extract common snippets of
-  SQL and reuse them for writing bigger metrics, continue reading!
-* To see how you can add your own metrics to the platform or edit an existing
-  metric, continue reading!
-
-Breaking down and composing metrics
-----------
-Coming soon!
-
-Adding a new metric or editing an existing metric
-----------
-Coming soon!
-
-Running a metric over a set of traces
-----------
-Coming soon!
-
-Metrics platform as an API
-----------
-Coming soon!
diff --git a/docs/running.md b/docs/running.md
index 3d9d937..564283e 100644
--- a/docs/running.md
+++ b/docs/running.md
@@ -3,17 +3,17 @@
 In order to run Perfetto and get a meaningful trace you need to build
 (see [build instructions](build-instructions.md)) and run the following:
 
-`traced`:
+`traced`:  
 The unprivileged trace daemon that owns the log buffers and maintains
 a registry of Producers and Consumers connected.
 
-`traced_probes`:
+`traced_probes`:  
 The privileged daemon that has access to the Kernel tracefs
 (typically mounted under `/sys/kernel/debug/tracing`). It drives
 [Ftrace](https://source.android.com/devices/tech/debug/ftrace) and writes its
 protobuf-translated contents into `traced`.
 
-`perfetto`:
+`perfetto`:  
 A command line utility client that drive the trace and save back
 the results (either to a file or to [Android's Dropbox][dropbox])
 
@@ -29,12 +29,6 @@
 `CONFIG` variable (e.g., [this](https://android.googlesource.com/platform/external/perfetto/+/master/test/configs/ftrace.cfg)) into a protobuf and setup the right paths.
 Furthermore it will automatically rebuild if necessary.
 
-It is possible to push binaries to, and run on, a remote target over ssh (even
-when cross-compiling):
-```bash
-CONFIG=ftrace.cfg OUT=out/default SSH_TARGET=user@my-device-host ./tools/tmux
-```
-
 Running from an Android P+ in-tree build
 ----------------------------------------
 Make sure that Perfetto daemons (`traced` / `traced_probes`) are running.
@@ -79,23 +73,5 @@
 an arbitrary trace config. See instructions in the
 [trace config](trace-config.md) page.
 
-Trace UI
---------
-For building the trace UI see the [build instructions](build-instructions.md)
-page. To run the UI using your local build:
-
-```
-$ ui/run-dev-server out/[your_build_dir]
-```
-
-Documentation
--------------
-To run the documentation server using your local build:
-
-```
-$ make -C docs test
-```
-You might need to install `docsify` and `docsify-cli`
-(`$ npm i -g docsify docsify-cli`) before running the documentation server.
 
 [dropbox]: https://developer.android.com/reference/android/os/DropBoxManager.html
diff --git a/docs/security-model.md b/docs/security-model.md
index bff44a9..fa6cb13 100644
--- a/docs/security-model.md
+++ b/docs/security-model.md
@@ -16,7 +16,7 @@
 **Producers**  
 Producers are never trusted. We assume they will try their best to DoS / crash /
 exploit the tracing service. We do so at the
-[core/service_impl.cc](/src/tracing/core/service_impl.cc) so that the same
+[core/service_impl.cc](/src/tracing/core/service_impl.cc) so that the the same
 level of security and testing is applied regardless of the embedder and the IPC
 transport.
 
diff --git a/docs/testing.md b/docs/testing.md
index 5e6d8f3..ccb05fb 100644
--- a/docs/testing.md
+++ b/docs/testing.md
@@ -18,42 +18,38 @@
 
 Running tests on Linux / MacOS
 ------------------------------
-
-```bash
-tools/ninja -C out/default perfetto_{unittests,integrationtests,benchmarks}
-out/default/perfetto_unittests --gtest_help
+```
+$ tools/ninja -C out/default perfetto_{unittests,integrationtests,benchmarks}
+$ out/default/perfetto_unittests --gtest_help
 ```
 
 `perfetto_integrationtests` requires that the ftrace debugfs directory is
 is readable/writable by the current user on Linux:
-```bash
+```
 sudo chown  -R $USER /sys/kernel/debug/tracing
 ```
 
 Running tests on Android
 ------------------------
 1A) Connect a device through `adb`  
-1B) Start the build-in emulator (supported on Linux and MacOS):
-
-```bash
-tools/install-build-deps
-tools/run_android_emulator &
+1B) Start the build-in emulator (supported on Linux and MacOS):  
+```
+$ tools/install-build-deps
+$ tools/run_android_emulator &
 ```
 
 2) Run the tests (either on the emulator or physical device):  
-
-```bash
-tools/run_android_test out/default perfetto_unittests
 ```
+$ tools/run_android_test out/default perfetto_unittests
+```
+
 
 Continuous testing
 ------------------
 Perfetto is tested in a variety of locations:
 
-**Perfetto CI**: https:/ci.perfetto.dev/  
-Builds and runs perfetto_{unittests,integrationtests,benchmarks} from the
-standalone checkout. Benchmarks are ran in a reduced form for smoke testing.
-See [this doc](/docs/continuous-integration.md) for more details.
+**Travis CI**: https://perfetto-ci.appspot.com/  
+Builds and runs perfetto_{unittests,integrationtests,benchmarks} from then standalone checkout. Benchmarks are ran in a reduced form for smoke testing.
 
 **Android CI** (see go/apct and go/apct-guide):  
 runs only `perfetto_integrationtests`
@@ -61,10 +57,10 @@
 **Android presubmits (TreeHugger)**:  
 Runs before submission of every AOSP CL of `external/perfetto`.
 
-**Android CTS** (Android test suite used run to ensure API compatibility):   
-Rolling runs internally.
 
-Note that Perfetto CI uses the standalone build system and the others build as
+**Android CTS** (Android test suite used run to ensure API compatibility):   Rolling runs internally.
+
+Note that Travis uses the standalone build system and the others build as
 part of the Android tree.
 
 Unit tests
@@ -72,7 +68,7 @@
 Unit tests exist for most of the code in Perfetto on the class level. They
 ensure that each class broadly works as expected.
 
-Unit tests are currently ran on ci.perfetto.dev and build.chromium.org.
+Unit tests are currently ran only on  Travis.
 Running unit tests on APCT and Treehugger is WIP.
 
 Integration tests
@@ -103,8 +99,7 @@
 etc.) and Perfetto is not broken.
 
 The relevant targets are `CtsPerfettoProducerApp` and `CtsPerfettoTestCases`. Once these are built, the following commands should be run:
-
-```bash
+```
 adb push $ANDROID_HOST_OUT/cts/android-cts/testcases/CtsPerfettoTestCases64 /data/local/tmp/
 adb install -r $ANDROID_HOST_OUT/cts/android-cts/testcases/CtsPerfettoProducerApp.apk
 ```
@@ -112,17 +107,10 @@
 Next, the app named `android.perfetto.producer` should be run on the device.
 
 Finally, the following command should be run:
-
-```bash
+```
 adb shell /data/local/tmp/CtsPerfettoTestCases64
 ```
 
 Chromium waterfall
 ------------------
-Perfetto is constantly rolled into chromium's //third_party/perfetto via
-[this autoroller](https://autoroll.skia.org/r/perfetto-chromium-autoroll).
-
-The [Chromium CI](https://build.chromium.org) runs the `perfetto_unittests`
-target, as defined in the [buildbot config][chromium_buildbot].
-
-[chromium_buildbot]: https://cs.chromium.org/search/?q=perfetto_.*tests+f:%5Esrc/testing.*json$&sq=package:chromium&type=cs
+Coming soon!
diff --git a/docs/toc.md b/docs/toc.md
index 3aac647..7fb68f2 100644
--- a/docs/toc.md
+++ b/docs/toc.md
@@ -7,12 +7,10 @@
   * [Capturing long traces](long-traces.md)
   * [Advanced trace config](trace-config.md)
   * [Running in detached mode](detached-mode.md)
-  * [Native Heap Profiling](heapprofd.md)
+  * [Heap Profiling](heapprofd.md)
 * Trace analysis
   * [Trace processor](trace-processor.md)
-  * [Trace-based metrics](metrics.md)
   * [Trace conversion](traceconv.md)
-  * [Clock synchronization](clock-sync.md)
 * Architectural docs
   * [Key concepts](architecture.md)
   * [Life of a tracing session](life-of-a-tracing-session.md)
diff --git a/docs/trace-config.md b/docs/trace-config.md
index e7c0f80..e6b2294 100644
--- a/docs/trace-config.md
+++ b/docs/trace-config.md
@@ -69,7 +69,7 @@
 protoc=$(pwd)/out/android/gcc_like_host/protoc
 
 $protoc --encode=perfetto.protos.TraceConfig \
-        -I$(pwd)/external/perfetto \
+        -I$(pwd)/external/perfetto/protos \
         $(pwd)/external/perfetto/protos/perfetto/config/perfetto_config.proto \
         < /tmp/config.txpb \
         > /tmp/config.pb
diff --git a/gn/BUILD.gn b/gn/BUILD.gn
index 1fba09e..cdb88ee 100644
--- a/gn/BUILD.gn
+++ b/gn/BUILD.gn
@@ -14,165 +14,55 @@
 
 import("perfetto.gni")
 import("proto_library.gni")
-
-if (perfetto_root_path == "//") {
+if (perfetto_build_standalone || perfetto_build_with_android) {
   import("//gn/standalone/sanitizers/vars.gni")
 } else {
   import("//build/config/sanitizers/sanitizers.gni")
 }
 
-# Genereates a header files that contains a macro definition for each build flag
-# that is required by the codebase. This is to avoid sprinkling cflags all over
-# the places, which is very fragile especially for our codebase that needs to
-# deal with several build systems.
-# The way this works is the following:
-# - This rule generates a header that contains a bunch of lines like:
-#   #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_BUILD()
-# - The generated header is included by base/build_config.h
-# - Source files in the codebase #include base/build_config and use the
-#   pattern #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
-buildflag_gen_dir_ = "$root_gen_dir/$perfetto_root_path/build_config"
-action("gen_buildflags") {
-  script = "write_buildflag_header.py"
-  gen_header_path = "$buildflag_gen_dir_/perfetto_build_flags.h"
-
-  perfetto_component_build = false
-  if (defined(is_component_build) && is_component_build) {
-    perfetto_component_build = true
-  }
-  perfetto_force_dlog_on = perfetto_force_dlog == "on"
-  perfetto_force_dlog_off = perfetto_force_dlog == "off"
-
-  # We can't just use (is_linux || is_android) in perfetto.gni because that
-  # doesn't work in Android Mac host builds. We lose the GN notion of OS once
-  # we run the tools/gen_xxx generators.
-  if (enable_perfetto_watchdog) {
-    perfetto_watchdog = "PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() || " +
-                        "PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX()"
-  } else {
-    perfetto_watchdog = "0"
-  }
-  if (enable_perfetto_tools) {
-    perfetto_local_symbolizer = "PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX()"
-  } else {
-    perfetto_local_symbolizer = "0"
-  }
-  if (enable_perfetto_trace_processor_httpd) {
-    perfetto_tp_httpd = "PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() || " +
-                        "PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() || " +
-                        "PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MACOSX()"
-  } else {
-    perfetto_tp_httpd = "0"
-  }
-
-  response_file_contents = [
-    "--flags",  # Keep this marker first.
-    "PERFETTO_ANDROID_BUILD=$perfetto_build_with_android",
-    "PERFETTO_CHROMIUM_BUILD=$build_with_chromium",
-    "PERFETTO_STANDALONE_BUILD=$perfetto_build_standalone",
-    "PERFETTO_START_DAEMONS=$start_daemons_for_testing",
-    "PERFETTO_IPC=$enable_perfetto_ipc",
-    "PERFETTO_WATCHDOG=$perfetto_watchdog",
-    "PERFETTO_COMPONENT_BUILD=$perfetto_component_build",
-    "PERFETTO_FORCE_DLOG_ON=$perfetto_force_dlog_on",
-    "PERFETTO_FORCE_DLOG_OFF=$perfetto_force_dlog_off",
-    "PERFETTO_VERSION_GEN=$enable_perfetto_version_gen",
-    "PERFETTO_TP_SQLITE=$enable_perfetto_trace_processor_sqlite",
-    "PERFETTO_TP_PERCENTILE=$enable_perfetto_trace_processor_percentile",
-    "PERFETTO_TP_LINENOISE=$enable_perfetto_trace_processor_linenoise",
-    "PERFETTO_TP_METRICS=$enable_perfetto_trace_processor_metrics",
-    "PERFETTO_TP_FTRACE=$enable_perfetto_trace_processor_ftrace",
-    "PERFETTO_TP_HTTPD=$perfetto_tp_httpd",
-    "PERFETTO_TP_SYSTEM_PROBES=$enable_perfetto_trace_processor_system_probes",
-    "PERFETTO_TP_ANDROID_PROBES=$enable_perfetto_trace_processor_android_probes",
-    "PERFETTO_TP_HEAP_GRAPHS=$enable_perfetto_trace_processor_heap_graphs",
-    "PERFETTO_TP_GRAPHICS=$enable_perfetto_trace_processor_graphics",
-    "PERFETTO_TP_JSON=$enable_perfetto_trace_processor_json",
-    "PERFETTO_TP_JSON_IMPORT=$enable_perfetto_trace_processor_json_import",
-    "PERFETTO_TP_FUCHSIA=$enable_perfetto_trace_processor_fuchsia",
-    "PERFETTO_TP_SYSCALLS=$enable_perfetto_trace_processor_syscalls",
-    "PERFETTO_LOCAL_SYMBOLIZER=$perfetto_local_symbolizer",
-  ]
-
-  rel_out_path = rebase_path(gen_header_path, "$root_build_dir")
-  args = [
-    "--out",
-    rel_out_path,
-    "--rsp",
-    "{{response_file_name}}",
-  ]
-
-  outputs = [
-    gen_header_path,
-  ]
-}
-
-# All targets should depend on this target to inherit the right flags and
-# include directories.
-group("default_deps") {
-  public_configs = [ ":default_config" ]
-  deps = [
-    ":gen_buildflags",
-  ]
-  if (perfetto_build_standalone) {
-    public_deps = [
-      "//gn/standalone/libc++:deps",
-      "//gn/standalone/sanitizers:deps",
-    ]
-  }
-}
-
-# The config that all targets in the perfetto codebase inherit by virtue of
-# having explicit deps on //gn:default_deps. This config is NOT propagated up to
-# embedders that depend on perfetto (e.g. chrome). :public_config (see below) is
-# used for that.
-config("default_config") {
-  configs = [ ":public_config" ]
-  defines = [ "PERFETTO_IMPLEMENTATION" ]
-  include_dirs = [ ".." ]
-
-  if (build_with_chromium && is_android) {
-    # Included for __android_log_print
-    libs = [ "log" ]
-  }
-}
-
-# This config is propagated to embedders via libperfetto. It's also included in
-# the default_config above.
-config("public_config") {
-  include_dirs = [
-    "../include",
-
-    # For perfetto_build_flags.h
-    buildflag_gen_dir_,
-  ]
-}
-
 config("asan_instrumentation") {
   if (use_sanitizer_configs_without_instrumentation) {
     defines = [ "ADDRESS_SANITIZER_WITHOUT_INSTRUMENTATION" ]
   }
 }
 
-if (perfetto_root_path != "//") {
-  config("gtest_and_gmock_embedder_config") {
-    include_dirs = [
-      "//testing/gtest/include",
-      "//testing/gmock/include",
-    ]
+# Used by base/gtest_prod_util.h for the FRIEND_TEST_* macros. Note that other
+# production targets (i.e. testonly == false) should use base/gtest_prod_util.h
+# instead.
+group("gtest_prod_config") {
+  if (perfetto_build_standalone || perfetto_build_with_android) {
+    public_configs = [ "//buildtools:googletest_prod_config" ]
+  } else {
+    public_configs = [ ":gtest_config" ]
   }
 }
 
-group("gtest_and_gmock") {
+config("gtest_config") {
+  if (perfetto_build_with_embedder) {
+    include_dirs = [ "//testing/gtest/include" ]
+  }
+}
+
+config("gmock_config") {
+  if (perfetto_build_with_embedder) {
+    include_dirs = [ "//testing/gmock/include" ]
+  }
+}
+
+group("gtest_deps") {
   testonly = true
 
-  if (perfetto_root_path == "//") {
+  public_configs = [
+    ":gtest_config",
+    ":gmock_config",
+  ]
+
+  if (perfetto_build_standalone || perfetto_build_with_android) {
     public_deps = [
       "//buildtools:gmock",
       "//buildtools:gtest",
     ]
   } else {
-    public_configs = [ ":gtest_and_gmock_embedder_config" ]
     public_deps = [
       "//testing/gmock",
       "//testing/gtest",
@@ -183,7 +73,7 @@
 group("gtest_main") {
   testonly = true
 
-  if (perfetto_root_path == "//") {
+  if (perfetto_build_standalone || perfetto_build_with_android) {
     public_deps = [
       "//buildtools:gtest_main",
     ]
@@ -198,145 +88,101 @@
   }
 }
 
-# Full protobuf is just for host tools .No binary shipped on device should
-# depend on this.
-whitelisted_protobuf_full_deps = [
-  "../tools/*",
-  "../src/ipc/protoc_plugin:*",
-  "../src/protozero/protoc_plugin:*",
-  "../src/trace_processor:trace_processor_shell",
-]
-
-group("protoc") {
-  public_deps = [
-    "${perfetto_protobuf_target_prefix}:protoc($host_toolchain)",
-  ]
-}
-
-# protoc compiler library, it's used for building protoc plugins and by
-# trace_processor_shell to dynamically load .proto files for metrics.
-group("protoc_lib") {
-  visibility = whitelisted_protobuf_full_deps
-  if (current_toolchain == host_toolchain) {
+# protoc compiler library, for building protoc plugins on the host.
+if (current_toolchain == host_toolchain) {
+  group("protoc_lib_deps") {
     public_deps = [
       "${perfetto_protobuf_target_prefix}:protoc_lib",
     ]
   }
 }
 
-group("protobuf_full") {
-  visibility = whitelisted_protobuf_full_deps
-  if (current_toolchain == host_toolchain) {
-    public_deps = [
-      "${perfetto_protobuf_target_prefix}:protobuf_full",
-    ]
-  }
-}
-
-group("protobuf_lite") {
+group("protobuf_full_deps") {
+  testonly = true
   public_deps = [
-    "${perfetto_protobuf_target_prefix}:protobuf_lite",
+    "${perfetto_protobuf_target_prefix}:protobuf_full",
   ]
 }
 
-# The Google C++ Benchmark library.
-# Only available in standalone builds.
-if (enable_perfetto_benchmarks) {
-  group("benchmark") {
-    testonly = true
+# All targets should depend on this target to inherit the right flags and
+# include directories.
+group("default_deps") {
+  public_configs = [ ":default_config" ]
+  if (perfetto_build_standalone || perfetto_build_with_android) {
     public_deps = [
-      "//buildtools:benchmark",
+      "//gn/standalone/libc++:deps",
+      "//gn/standalone/sanitizers:deps",
     ]
   }
 }
 
-# Libbacktrace, used for printing stack traces from crash handler, only in
-# standalone debug builds.
-if (perfetto_build_standalone && (is_linux || is_android)) {
-  group("libbacktrace") {
+# The config that all targets in the perfetto codebase inherit by virtue of
+# having explicit deps on //gn:default_deps. This config is NOT propagated up to
+# embedders that depend on perfetto (e.g. chrome). :public_config (see below) is
+# used for that.
+config("default_config") {
+  configs = [ ":public_config" ]
+
+  defines = [ "PERFETTO_IMPLEMENTATION" ]
+
+  if (build_with_chromium && is_android) {
+    # Included for __android_log_print
+    libs = [ "log" ]
+  }
+
+  include_dirs = [ ".." ]
+}
+
+# This config is propagated to embedders via libperfetto. It's also included in
+# the default_config above.
+config("public_config") {
+  include_dirs = [
+    "../include",
+
+    # The below are needed due to generated protobuf headers including other
+    # headers with a path relative to the perfetto root.
+    "${root_gen_dir}/${perfetto_root_path}/protos",
+  ]
+
+  defines = []
+
+  if (perfetto_build_with_android) {
+    defines += [ "PERFETTO_BUILD_WITH_ANDROID" ]
+  } else if (perfetto_build_with_embedder) {
+    defines += [ "PERFETTO_BUILD_WITH_EMBEDDER" ]
+
+    if (build_with_chromium) {
+      defines += [ "PERFETTO_BUILD_WITH_CHROMIUM" ]
+
+      if (is_component_build) {
+        defines += [ "PERFETTO_SHARED_LIBRARY" ]
+      }
+    }  # if (build_with_chromium)
+  }  # if (build_with_embedder)
+
+  if (perfetto_force_dlog == "on") {
+    defines += [ "PERFETTO_FORCE_DLOG=1" ]
+  } else if (perfetto_force_dlog == "off") {
+    defines += [ "PERFETTO_FORCE_DLOG=0" ]
+  }
+}
+
+# For now JsonCpp is supported only in standalone builds outside of Android or
+# Chromium.
+group("jsoncpp_deps") {
+  if (perfetto_build_standalone) {
+    public_configs = [ "//buildtools:jsoncpp_config" ]
     public_deps = [
-      "//buildtools:libbacktrace",
+      "//buildtools:jsoncpp",
     ]
   }
 }
 
-if (enable_perfetto_trace_processor_sqlite) {
-  group("sqlite") {
-    if (perfetto_root_path == "//") {
-      public_deps = [
-        "//buildtools:sqlite",
-      ]
-    } else {
-      public_deps = [
-        "//third_party/sqlite:sqlite",
-      ]
-      public_configs = [ ":sqlite_third_party_include_path" ]
-    }
-  }
-
-  config("sqlite_third_party_include_path") {
-    include_dirs = [ "//third_party/sqlite" ]
-  }
-}  # if (enable_perfetto_trace_processor_sqlite)
-
-if (enable_perfetto_trace_processor_json) {
-  group("jsoncpp") {
-    if (perfetto_root_path == "//") {
-      public_configs = [ "//buildtools:jsoncpp_config" ]
-      public_deps = [
-        "//buildtools:jsoncpp",
-      ]
-    } else {
-      public_deps = [
-        "//third_party/jsoncpp:jsoncpp",
-      ]
-    }
-  }
-}
-
-if (enable_perfetto_trace_processor_linenoise) {
-  # Used by the trace_processor_shell for REPL history.
-  # Only available in standalone builds.
-  group("linenoise") {
+group("zlib_deps") {
+  if (perfetto_build_standalone || perfetto_build_with_android) {
+    public_configs = [ "//buildtools:zlib_config" ]
     public_deps = [
-      "//buildtools:linenoise",
-    ]
-  }
-}  # if (enable_perfetto_trace_processor_linenoise)
-
-# Only used by src/profiling in standalone and android builds.
-if (enable_perfetto_heapprofd) {
-  group("libunwindstack") {
-    public_configs = [ "//buildtools:libunwindstack_config" ]
-    public_deps = [
-      "//buildtools:libunwindstack",
-    ]
-  }
-}
-
-# Zlib is used both by trace_processor and by perfetto_cmd.
-if (enable_perfetto_trace_processor || enable_perfetto_platform_services) {
-  group("zlib") {
-    if (perfetto_root_path == "//") {
-      public_configs = [ "//buildtools:zlib_config" ]
-      public_deps = [
-        "//buildtools:zlib",
-      ]
-    } else {
-      public_configs = [ "//third_party/zlib:zlib_config" ]
-      public_deps = [
-        "//third_party/zlib",
-      ]
-    }
-  }
-}
-
-# Used by fuzzers.
-if (enable_perfetto_fuzzers && use_libfuzzer) {
-  group("libfuzzer") {
-    assert(perfetto_root_path == "//")
-    public_deps = [
-      "//buildtools:libfuzzer",
+      "//buildtools:zlib",
     ]
   }
 }
diff --git a/gn/fuzzer.gni b/gn/fuzzer.gni
index 6a4bc24..ace0356 100644
--- a/gn/fuzzer.gni
+++ b/gn/fuzzer.gni
@@ -14,7 +14,7 @@
 
 import("perfetto.gni")
 
-if (perfetto_root_path == "//") {
+if (perfetto_build_standalone) {
   import("//gn/standalone/fuzzer.gni")
 } else {
   # TODO: integrate fuzzer support for chromium builds.
diff --git a/gn/ipc_library.gni b/gn/ipc_library.gni
index 1ee9ed9..064f4eb 100644
--- a/gn/ipc_library.gni
+++ b/gn/ipc_library.gni
@@ -14,7 +14,7 @@
 
 import("perfetto.gni")
 
-if (perfetto_root_path == "//") {
+if (perfetto_build_standalone || perfetto_build_with_android) {
   import("//gn/standalone/proto_library.gni")
 } else {
   import("//third_party/protobuf/proto_library.gni")
diff --git a/gn/perfetto.gni b/gn/perfetto.gni
index 4dbcd42..9c62f42 100644
--- a/gn/perfetto.gni
+++ b/gn/perfetto.gni
@@ -13,263 +13,87 @@
 # limitations under the License.
 
 import("//build_overrides/build.gni")
-import("wasm_vars.gni")
 
-# Summary of our typical build configurations:
+# Summary of our build configurations:
 
 # 1. Standalone builds
-#    build_with_chromium = false
-#    is_perfetto_build_generator = false
 #    perfetto_build_standalone = true
-#    perfetto_build_with_android = false
 #    perfetto_build_with_embedder = false
+#    perfetto_build_with_android = false
+#    build_with_chromium = false
 
 # 2. Android tree builds
-#    build_with_chromium = false
-#    is_perfetto_build_generator = true
 #    perfetto_build_standalone = false
 #    perfetto_build_with_android = true
 #    perfetto_build_with_embedder = false
+#    build_with_chromium = false
 
 # 3. Chromium tree builds
+#    perfetto_build_standalone = false
+#    perfetto_build_with_android = false
+#    perfetto_build_with_embedder = true
 #    build_with_chromium = true
-#    is_perfetto_build_generator = false
+
+# 4. Builds in other embedder trees
 #    perfetto_build_standalone = false
 #    perfetto_build_with_android = false
 #    perfetto_build_with_embedder = true
-
-# 4. Builds in other embedder trees (e.g. V8 standalone)
 #    build_with_chromium = false
-#    is_perfetto_build_generator = false
-#    perfetto_build_standalone = false
-#    perfetto_build_with_android = false
-#    perfetto_build_with_embedder = true
-
-# 5. Amalgamated sources (Client library)
-#    build_with_chromium = false
-#    is_perfetto_build_generator = true
-#    perfetto_build_standalone = false
-#    perfetto_build_with_android = false
-#    perfetto_build_with_embedder = true
-
-# +----------------------------------------------------------------------------+
-# | Toolchain / environment related configuration                              |
-# +----------------------------------------------------------------------------+
-# This section contains a bunch of variables that are related with the toolchain
-# and the build environment. Only tools/gen_xxx should customize them.
 
 # Note that |build_with_chromium| is a global convention used by several
 # projects, set outside of our control.
 
-# Chromium sets this to true in its //build_overrides/build.gni.
+declare_args() {
+  # The Android blueprint file generator overrides this to true.
+  perfetto_build_with_android = false
+
+  # Whether the ftrace producer and the service should be started
+  # by the integration test or assumed to be running.
+  start_daemons_for_testing = true
+}
+
+# Chromium sets this to true.
 if (!defined(build_with_chromium)) {
   build_with_chromium = false
 }
 
-declare_args() {
-  # The Android blueprint file generator set this to true (as well as
-  # is_perfetto_build_generator). This is just about being built in the
-  # Android tree (AOSP and internal) and is NOT related with the target OS.
-  # In standalone Android builds and Chromium Android builds, this is false.
-  perfetto_build_with_android = false
-
-  # All the tools/gen_* scripts set this to true. This is mainly used to locate
-  # .gni files from //gn rather than //build.
-  is_perfetto_build_generator = false
-
-  # This is for override via `gn args` (e.g. for tools/gen_xxx). Embedders
-  # based on GN (e.g. v8) should NOT set this and instead directly sets
-  # perfetto_build_with_embedder=true in their GN files.
-  is_perfetto_embedder = false
-}
-
-# This can be overridden by embedders (e.g. v8) in their .gn(i) files. This must
-# be different from the GN args flag (is_perfetto_embedder) because of the way
-# GN works.
+# Embedders can override this to true.
 if (!defined(perfetto_build_with_embedder)) {
-  perfetto_build_with_embedder = build_with_chromium || is_perfetto_embedder
+  perfetto_build_with_embedder = build_with_chromium
 }
 
-perfetto_build_standalone =
-    !perfetto_build_with_android && !build_with_chromium &&
-    !perfetto_build_with_embedder
-
-# Only relevant for GN builds. Sets the path where perfetto lives. This is //
-# for standalone builds and //third_party/perfetto/ in embedders. The embedder
-# can ovverride it in its GN files.
-if (perfetto_build_standalone || is_perfetto_build_generator) {
-  perfetto_root_path = "//"
-  import("//gn/standalone/android.gni")  # For android_api_level
-  import("//gn/standalone/sanitizers/vars.gni")  # For is_fuzzer
-} else if (!defined(perfetto_root_path)) {
-  perfetto_root_path = "//third_party/perfetto/"
-  import("//build/config/android/config.gni")  # For android_api_level
-}
-
-# Whether the ftrace producer and the service should be started
-# by the integration test or assumed to be running.
-# If we're building in the Android tree, we expect that the testing infra
-# will start the binaries in the system image before the tests are run.
-# In all other cases (i.e. when true), a temporary in-process instance will be
-# brought up by our own integrationtest harness.
-start_daemons_for_testing = !perfetto_build_with_android
-
-# +----------------------------------------------------------------------------+
-# | Tunable build variables for embedders                                      |
-# +----------------------------------------------------------------------------+
-# The variables in this section allow embedders to enable/disable features
-# at the build-system level. This allows to opt-in into the various services
-# and tools.
-
 perfetto_force_dlog_default = ""
-if (build_with_chromium) {
+if (perfetto_build_with_embedder) {
   perfetto_force_dlog_default = "off"
 }
 
 declare_args() {
-  # Platform-wide tracing executables (traced, traced_probes, perfetto_cmd).
-  enable_perfetto_platform_services =
-      perfetto_build_standalone || perfetto_build_with_android
-
-  # Allow the embedder to use the IPC layer. In turn this allows to use the
-  # system backend in the client library.
-  # This includes building things that rely on POSIX sockets, this places
-  # limitations on the supported operating systems.
-  enable_perfetto_ipc = (is_android || is_linux || is_mac) &&
-                        (perfetto_build_standalone ||
-                         perfetto_build_with_android || build_with_chromium)
-
-  # Makes the heap profiling daemon target reachable. It works only on Android,
-  # but is built on Linux as well for test/compiler coverage.
-  # On Android, it requires API level 26 due to libunwindstack.
-  enable_perfetto_heapprofd =
-      perfetto_build_with_android ||
-      (perfetto_build_standalone && is_clang &&
-       (is_linux || (is_android && android_api_level >= 26)))
-
-  # The Trace Processor: offline analytical engine to process traces and compute
-  # metrics using a SQL engine.
-  enable_perfetto_trace_processor =
-      perfetto_build_standalone || build_with_chromium ||
-      is_perfetto_build_generator
-
-  # Enables base::Watchdog. Is supported only on Linux-based platforms.
-  # gn/BUILD.gn further restricts this to OS_LINUX || OS_ANDROID when generating
-  # the perfetto_build_flags.h header.
-  enable_perfetto_watchdog =
-      perfetto_build_with_android || perfetto_build_standalone
-
-  # Misc host executable under tools/.
-  enable_perfetto_tools =
-      perfetto_build_standalone || perfetto_build_with_android
-
-  enable_perfetto_unittests = perfetto_build_standalone ||
-                              build_with_chromium || perfetto_build_with_android
-
-  enable_perfetto_integration_tests =
-      perfetto_build_standalone || perfetto_build_with_android
-
-  enable_perfetto_benchmarks = perfetto_build_standalone
-
-  enable_perfetto_fuzzers =
-      perfetto_build_standalone && defined(is_fuzzer) && is_fuzzer
-
-  # Enables the gen_git_revision tool that generates a .h that contains a macro
-  # with the current git revision. Works only in standalone GN checkouts.
-  # If disabled, the version string will be "unknown".
-  enable_perfetto_version_gen =
-      perfetto_build_standalone && !is_perfetto_build_generator
-
-  # Only for local development. When true the binaries (perfetto, traced, ...)
-  # are monolithic and don't use a common shared library. This is mainly to
-  # avoid LD_LIBRARY_PATH dances when testing locally.
-  monolithic_binaries = false
-
   # Whether DLOG should be enabled on debug builds (""), all builds ("on"), or
   # none ("off"). We disable it by default for embedders to avoid spamming their
   # console.
   perfetto_force_dlog = perfetto_force_dlog_default
 }
 
-declare_args() {
-  # Enables the SQL query layer of trace processor.
-  enable_perfetto_trace_processor_sqlite =
-      enable_perfetto_trace_processor && !(build_with_chromium && is_android)
+assert(perfetto_force_dlog == "" || perfetto_force_dlog == "on" ||
+       perfetto_force_dlog == "off")
 
-  # Enables the optional SQLite percentile module.
-  enable_perfetto_trace_processor_percentile =
-      enable_perfetto_trace_processor && perfetto_build_standalone
+perfetto_build_standalone =
+    !perfetto_build_with_android && !build_with_chromium &&
+    !perfetto_build_with_embedder
 
-  # Enables the REPL interactive prompt in the trace processor.
-  enable_perfetto_trace_processor_linenoise =
-      perfetto_build_standalone && enable_perfetto_trace_processor &&
-      (is_linux || is_android || is_mac)
-
-  # Enables ftrace support in the trace processor.
-  enable_perfetto_trace_processor_ftrace =
-      enable_perfetto_trace_processor && !(build_with_chromium && is_android)
-
-  # Enables parsing support for system probes in trace processor.
-  enable_perfetto_trace_processor_system_probes =
-      enable_perfetto_trace_processor && !(build_with_chromium && is_android)
-
-  # Enables parsing support for android system probes in trace processor.
-  enable_perfetto_trace_processor_android_probes =
-      enable_perfetto_trace_processor && !(build_with_chromium && is_android)
-
-  # Enables parsing support for heap graphs in trace processor.
-  enable_perfetto_trace_processor_heap_graphs =
-      enable_perfetto_trace_processor && !(build_with_chromium && is_android)
-
-  # Enables graphics event support in the trace processor.
-  enable_perfetto_trace_processor_graphics =
-      enable_perfetto_trace_processor && !(build_with_chromium && is_android)
-
-  # Enables JSON support in the trace processor. Required for JSON trace import
-  # and export. Importer support can also be disabled using
-  # |enable_perfetto_trace_processor_json_import|.
-  enable_perfetto_trace_processor_json =
-      enable_perfetto_trace_processor && !perfetto_build_with_android
-
-  # Enables Fuchsia trace format support in trace processor.
-  enable_perfetto_trace_processor_fuchsia =
-      enable_perfetto_trace_processor && !(build_with_chromium && is_android)
-
-  # Enables httpd RPC support in the trace processor.
-  # Further per-OS conditionals are applied in gn/BUILD.gn.
-  enable_perfetto_trace_processor_httpd =
-      enable_perfetto_trace_processor && perfetto_build_standalone
+if (perfetto_build_standalone || perfetto_build_with_android) {
+  perfetto_root_path = "//"
+} else if (!defined(perfetto_root_path)) {
+  perfetto_root_path = "//third_party/perfetto/"
 }
 
-declare_args() {
-  # Enables importer support for JSON traces in the trace processor.
-  enable_perfetto_trace_processor_json_import =
-      enable_perfetto_trace_processor_json &&
-      !(build_with_chromium && is_android)
-
-  # Enables syscall support in trace processor. Required for ftrace, system
-  # probes, and android probes support.
-  enable_perfetto_trace_processor_syscalls =
-      enable_perfetto_trace_processor_ftrace ||
-      enable_perfetto_trace_processor_system_probes ||
-      enable_perfetto_trace_processor_android_probes
-
-  # Enables metrics support in the trace processor, which require SQL support.
-  enable_perfetto_trace_processor_metrics =
-      enable_perfetto_trace_processor_sqlite
-
-  # Enables the trace_to_text tool.
-  enable_perfetto_tools_trace_to_text =
-      enable_perfetto_tools && enable_perfetto_trace_processor_sqlite
-
-  # Allows to build the UI (TypeScript/ HTML / WASM)
-  enable_perfetto_ui =
-      perfetto_build_standalone && enable_perfetto_trace_processor_sqlite
+# If we're building in the Android tree, we expect that the testing infra
+# will start the binaries in the system image before the tests are run.
+if (perfetto_build_with_android) {
+  start_daemons_for_testing = false
 }
 
-# +---------------------------------------------------------------------------+
-# | Cross-checks                                                              |
-# +---------------------------------------------------------------------------+
+# Cross-checks.
 
 # Exactly one between build_with_android, build_standalone and
 # build_with_embedder must be true.
@@ -283,35 +107,12 @@
 # must be true
 assert(!build_with_chromium || perfetto_build_with_embedder)
 
-# If |perfetto_build_with_android| is true then also
-# |is_perfetto_build_generator| must be true.
-assert(!perfetto_build_with_android || is_perfetto_build_generator)
-
-# The IPC layer based on UNIX sockets can't be built on Win.
-assert(!enable_perfetto_ipc || !is_win)
-
-# We should never end up in a state where is_perfetto_embedder=true but
-# perfetto_build_with_embedder=false.
-assert(!is_perfetto_embedder || perfetto_build_with_embedder)
-
-# The monolithic binaries is not supported when building in the Android tree.
-assert(!monolithic_binaries || !perfetto_build_with_android)
-
-# Watchdog must be on in Android builds.
-assert(enable_perfetto_watchdog || !perfetto_build_with_android)
-
-assert(perfetto_force_dlog == "" || perfetto_force_dlog == "on" ||
-       perfetto_force_dlog == "off")
-
-# Metrics, the UI, and trace to text require SQLite support in trace processor.
-assert(!enable_perfetto_trace_processor_metrics ||
-       enable_perfetto_trace_processor_sqlite)
-assert(!enable_perfetto_tools_trace_to_text ||
-       enable_perfetto_trace_processor_sqlite)
-assert(!enable_perfetto_ui || enable_perfetto_trace_processor_sqlite)
-
-# Syscall support is required for ftrace, system probes, and android probes.
-assert(enable_perfetto_trace_processor_syscalls ||
-       (!enable_perfetto_trace_processor_ftrace &&
-        !enable_perfetto_trace_processor_system_probes &&
-        !enable_perfetto_trace_processor_android_probes))
+# Only perfetto itself (standalone or with android) and chromium should link
+# in the IPC layer.
+#
+# This includes building things that rely on POSIX sockets, this places
+# limitations on the supported operating systems.
+perfetto_build_with_ipc_layer =
+    (is_android || is_linux || is_mac) &&
+    (perfetto_build_standalone || perfetto_build_with_android ||
+     build_with_chromium)
diff --git a/gn/perfetto_benchmarks.gni b/gn/perfetto_benchmarks.gni
deleted file mode 100644
index f711222..0000000
--- a/gn/perfetto_benchmarks.gni
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("perfetto.gni")
-
-perfetto_benchmarks_targets = [
-  "gn:default_deps",
-  "src/traced/probes/ftrace:benchmarks",
-  "src/trace_processor/db:benchmarks",
-  "src/trace_processor/tables:benchmarks",
-  "src/tracing:benchmarks",
-  "test:benchmark_main",
-  "test:end_to_end_benchmarks",
-]
diff --git a/gn/perfetto_fuzzers.gni b/gn/perfetto_fuzzers.gni
deleted file mode 100644
index a82b74f..0000000
--- a/gn/perfetto_fuzzers.gni
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("perfetto.gni")
-
-perfetto_fuzzers_targets = [
-  "gn:default_deps",
-  "src/ipc:buffered_frame_deserializer_fuzzer",
-  "src/protozero:protozero_decoder_fuzzer",
-  "src/tracing:packet_stream_validator_fuzzer",
-  "src/trace_processor:trace_processor_fuzzer",
-  "src/traced/probes/ftrace:cpu_reader_fuzzer",
-  "test:end_to_end_shared_memory_fuzzer",
-  "test:producer_socket_fuzzer",
-]
-
-if (enable_perfetto_heapprofd) {
-  perfetto_fuzzers_targets += [
-    "src/profiling/memory:shared_ring_buffer_fuzzer",
-    "src/profiling/memory:shared_ring_buffer_write_fuzzer",
-    "src/profiling/memory:unwinding_fuzzer",
-  ]
-}
diff --git a/gn/perfetto_host_executable.gni b/gn/perfetto_host_executable.gni
deleted file mode 100644
index ccadc2e..0000000
--- a/gn/perfetto_host_executable.gni
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("perfetto.gni")
-
-# A template to make host tools handier. The main problem it solves is that when
-# building host toolchain tools on an Android build, the executables end up in
-# out/xxx/gcc_like_host, which is an inconvenient location. Our developers
-# (and also some of our scripts) expect them to live in out/xxx/.
-# This template takes care takes care of building the target only on the host
-# toolchain and copy it over in the root build directory.
-template("perfetto_host_executable") {
-  if (current_toolchain == host_toolchain) {
-    executable(target_name) {
-      forward_variables_from(invoker, "*")
-    }
-  } else {
-    not_needed(invoker, "*", [ "testonly" ])
-    _host_target = ":$target_name($host_toolchain)"
-    _testonly = defined(invoker.testonly) && invoker.testonly
-    if (perfetto_build_with_embedder || is_perfetto_build_generator) {
-      # Don't copy anythin in Chromium, just add a dependency to the host
-      # target. V8 and other GN embedder builds. This causes problems on
-      # some bot (see crbug.com/1002599).
-      group(target_name) {
-        testonly = _testonly
-        deps = [
-          _host_target,
-        ]
-      }
-    } else {
-      copy(target_name) {
-        testonly = _testonly
-        deps = [
-          _host_target,
-        ]
-        _host_out_dir = get_label_info(_host_target, "root_out_dir")
-        sources = [
-          "$_host_out_dir/$target_name",
-        ]
-        outputs = [
-          "$root_out_dir/$target_name",
-        ]
-      }
-    }
-  }
-}
diff --git a/gn/perfetto_integrationtests.gni b/gn/perfetto_integrationtests.gni
deleted file mode 100644
index 19b5189..0000000
--- a/gn/perfetto_integrationtests.gni
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("perfetto.gni")
-
-perfetto_integrationtests_targets = [
-  "gn:default_deps",
-  "gn:gtest_main",
-  "src/tracing:client_api_integrationtests",
-]
-
-if (enable_perfetto_platform_services) {
-  perfetto_integrationtests_targets += [
-    "src/traced/probes/ftrace:integrationtests",
-    "test:end_to_end_integrationtests",
-  ]
-}
-
-if (enable_perfetto_heapprofd) {
-  perfetto_integrationtests_targets +=
-      [ "src/profiling/memory:end_to_end_tests" ]
-}
-
-# This test requires extra data files that are not easily available in Android
-# builds.
-# TODO(lalitm): looks like they don't work on standalone Android either because
-# run_android_test doesn't push the test data.
-if (enable_perfetto_trace_processor && perfetto_build_standalone &&
-    !is_android) {
-  perfetto_integrationtests_targets +=
-      [ "src/trace_processor:integrationtests" ]
-}
diff --git a/gn/perfetto_unittests.gni b/gn/perfetto_unittests.gni
deleted file mode 100644
index bdcf82f..0000000
--- a/gn/perfetto_unittests.gni
+++ /dev/null
@@ -1,64 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("perfetto.gni")
-
-perfetto_unittests_targets = [
-  "gn:default_deps",
-  "gn:gtest_main",
-  "src/base:unittests",
-  "src/protozero:unittests",
-  "src/tracing:unittests",
-]
-
-if (enable_perfetto_tools && current_toolchain == host_toolchain) {
-  perfetto_unittests_targets += [ "tools/ftrace_proto_gen:unittests" ]
-}
-
-# TODO(primiano): sanitizers_unittests shouldn't really be under tools. It's
-# not a tool and it's intended to run on both host and targets to check that
-# sanitizers are actually working.
-if ((is_linux || is_android) && !perfetto_build_with_embedder) {
-  # This test depends on pthread and can't run on non-Linux-based OS.
-  perfetto_unittests_targets += [ "tools/sanitizers_unittests" ]
-}
-
-if (enable_perfetto_ipc) {
-  perfetto_unittests_targets += [ "src/ipc:unittests" ]
-}
-
-if (enable_perfetto_platform_services) {
-  perfetto_unittests_targets += [
-    "src/perfetto_cmd:unittests",
-    "src/traced/probes:unittests",
-    "src/traced/probes/filesystem:unittests",
-    "src/traced/probes/ftrace:unittests",
-    "src/traced/service:unittests",
-  ]
-}
-
-if (enable_perfetto_heapprofd) {
-  perfetto_unittests_targets += [
-    "src/profiling/memory:unittests",
-    "src/profiling/memory:ring_buffer_unittests",
-  ]
-}
-
-if (enable_perfetto_trace_processor) {
-  perfetto_unittests_targets += [ "src/trace_processor:unittests" ]
-
-  if (enable_perfetto_trace_processor_metrics) {
-    perfetto_unittests_targets += [ "src/trace_processor/metrics:unittests" ]
-  }
-}
diff --git a/gn/proto_library.gni b/gn/proto_library.gni
index c7af114..a34419d 100644
--- a/gn/proto_library.gni
+++ b/gn/proto_library.gni
@@ -14,201 +14,20 @@
 
 import("perfetto.gni")
 
-# This gni file defines rules for proto generation. There are various types of
-# proto targets that can be defined in our codebase:
-# "lite" targets: these use the standard libprotobuf library. They are used
-#     mainly for tests and readback.
-# "zero" targets: these use the protozero library and its protoc plugin. They
-#     are used pretty much everywhere.
-# "descriptor" targets: they are used to generate a proto-encoded reflection
-#     descriptor that describes the schema of the proto using protobuf itself.
-# All these targets can be generated using the perfetto_proto_library rule. It
-# wraps the instantiation of several proto targets using a convenience template.
-#
-# For instance:
-# perfetto_proto_library("xxx_@TYPE@") {
-#   proto_generators = [ "lite", "zero" ]  # lite+zero is the default value.
-#   sources = [ "one.proto", "two.proto" ]
-#   deps = [ "dep:@TYPE@" ]
-# }
-#
-# Is the equivalent of:
-# proto_library("xxx_lite")     { sources = [...], deps = [ "dep:lite"] }
-# protozero_library("xxx_zero") { sources = [...], deps = [ "dep:zero"] }
-
-# Load the protobuf's proto_library() definition.
 if (!defined(perfetto_protobuf_target_prefix)) {
-  if (perfetto_root_path == "//") {
+  if (perfetto_build_standalone || perfetto_build_with_android) {
     perfetto_protobuf_target_prefix = "//buildtools"
   } else {
     perfetto_protobuf_target_prefix = "//third_party/protobuf"
   }
 }
+
 if (!defined(perfetto_protobuf_gni)) {
-  if (perfetto_root_path == "//") {
+  if (perfetto_build_standalone || perfetto_build_with_android) {
     perfetto_protobuf_gni = "//gn/standalone/proto_library.gni"
   } else {
     perfetto_protobuf_gni = "//third_party/protobuf/proto_library.gni"
   }
 }
+
 import(perfetto_protobuf_gni)
-
-# Equivalent to proto_library (generation of .h/.cc from .proto files) but
-# enables also generation using the protozero plugin.
-# The generated files will have the .pbzero.{cc,h} suffix, as opposed to the
-# .pb.{cc,h} of the official proto library.
-# DO NOT use this target directly, use perfetto_proto_library() below.
-template("protozero_library") {
-  proto_library(target_name) {
-    perfetto_root_path = invoker.perfetto_root_path
-
-    generate_cc = false
-    generate_python = false
-    generator_plugin_label =
-        perfetto_root_path + "src/protozero/protoc_plugin:protozero_plugin"
-    generator_plugin_suffix = ".pbzero"
-    if (build_with_chromium) {
-      component_build_force_source_set = true
-    }
-
-    if (defined(invoker.deps)) {
-      deps = invoker.deps
-    } else {
-      deps = []
-    }
-
-    deps += [ perfetto_root_path + "src/protozero" ]
-
-    forward_variables_from(invoker,
-                           [
-                             "defines",
-                             "generator_plugin_options",
-                             "include_dirs",
-                             "proto_in_dir",
-                             "proto_out_dir",
-                             "sources",
-                             "testonly",
-                             "visibility",
-                             "generate_descriptor",
-                           ])
-  }
-}
-
-# This template generates .gen.cc/h files from .proto files. The generated
-# sources are actual C++ classes that can be moved and copied around, very
-# similar to the libprotobuf generated ones API-wise, but use protozero under
-# the hoods, without any zero-copy benefit though.
-# They are mainly used for the perfetto IPC layer and tests.
-template("protozero_cpp_library") {
-  proto_library(target_name) {
-    perfetto_root_path = invoker.perfetto_root_path
-
-    generate_cc = false
-    generate_python = false
-    generator_plugin_label =
-        perfetto_root_path + "src/protozero/protoc_plugin:cppgen_plugin"
-    generator_plugin_suffix = ".gen"
-    if (build_with_chromium) {
-      component_build_force_source_set = true
-    }
-
-    deps = [
-      "$perfetto_root_path/gn:default_deps",
-      "$perfetto_root_path/include/perfetto/base",
-    ]
-
-    if (defined(invoker.deps)) {
-      deps += invoker.deps
-    }
-
-    forward_variables_from(invoker,
-                           [
-                             "defines",
-                             "generator_plugin_options",
-                             "include_dirs",
-                             "proto_in_dir",
-                             "proto_out_dir",
-                             "sources",
-                             "testonly",
-                             "visibility",
-                             "generate_descriptor",
-                           ])
-  }
-}
-
-# The template used everywhere in the codebase.
-template("perfetto_proto_library") {
-  if (defined(invoker.proto_generators)) {
-    proto_generators = invoker.proto_generators
-  } else {
-    proto_generators = [
-      "zero",
-      "lite",
-      "cpp",
-    ]
-  }
-
-  # proto imports and C++ #includes are relative to this path.
-  if (defined(invoker.proto_path)) {
-    proto_path = invoker.proto_path
-  } else {
-    proto_path = perfetto_root_path
-  }
-
-  vars_to_forward = [
-    "sources",
-    "visibility",
-    "testonly",
-  ]
-  expansion_token = "@TYPE@"
-
-  foreach(gen_type, proto_generators) {
-    target_name_ = string_replace(target_name, expansion_token, gen_type)
-
-    # Translate deps from xxx:@TYPE@ to xxx:lite/zero.
-    deps_ = []
-    if (defined(invoker.deps)) {
-      foreach(dep, invoker.deps) {
-        deps_ += [ string_replace(dep, expansion_token, gen_type) ]
-      }
-    }
-
-    if (gen_type == "zero") {
-      protozero_library(target_name_) {
-        proto_in_dir = proto_path
-        proto_out_dir = proto_path
-        generator_plugin_options = "wrapper_namespace=pbzero"
-        deps = deps_
-        forward_variables_from(invoker, vars_to_forward)
-      }
-    } else if (gen_type == "cpp") {
-      lite_target_name_ = string_replace(target_name, expansion_token, "lite")
-      protozero_cpp_library(target_name_) {
-        proto_in_dir = proto_path
-        proto_out_dir = proto_path
-        deps = deps_ + [ ":$lite_target_name_" ]
-        forward_variables_from(invoker, vars_to_forward)
-      }
-    } else if (gen_type == "lite") {
-      proto_library(target_name_) {
-        proto_in_dir = proto_path
-        proto_out_dir = proto_path
-        generate_python = false
-        deps = deps_
-        forward_variables_from(invoker, vars_to_forward)
-      }
-    } else if (gen_type == "descriptor") {
-      proto_library(target_name_) {
-        proto_in_dir = proto_path
-        proto_out_dir = proto_path
-        generate_python = false
-        generate_cc = false
-        generate_descriptor = invoker.generate_descriptor
-        deps = deps_
-        forward_variables_from(invoker, vars_to_forward)
-      }
-    } else {
-      assert(false, "Invalid 'proto_generators' value.")
-    }
-  }
-}
diff --git a/gn/protozero_library.gni b/gn/protozero_library.gni
new file mode 100644
index 0000000..d2c01b9
--- /dev/null
+++ b/gn/protozero_library.gni
@@ -0,0 +1,55 @@
+# Copyright (C) 2017 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.
+
+import("perfetto.gni")
+import("proto_library.gni")
+
+# Equivalent to proto_library (generation of .h/.cc from .proto files) but
+# enables also generation using the protozero plugin.
+# The generated files will have the .pbzero.{cc,h} suffix, as opposed to the
+# .pb.{cc,h} of the official proto library.
+template("protozero_library") {
+  proto_library(target_name) {
+    perfetto_root_path = invoker.perfetto_root_path
+
+    generate_cc = false
+    generate_python = false
+    generator_plugin_label = perfetto_root_path + "src/protozero/protoc_plugin"
+    generator_plugin_suffix = ".pbzero"
+    if (build_with_chromium) {
+      component_build_force_source_set = true
+    }
+
+    if (defined(invoker.deps)) {
+      deps = invoker.deps
+    } else {
+      deps = []
+    }
+
+    deps += [ perfetto_root_path + "src/protozero" ]
+
+    forward_variables_from(invoker,
+                           [
+                             "defines",
+                             "generator_plugin_options",
+                             "include_dirs",
+                             "proto_in_dir",
+                             "proto_out_dir",
+                             "sources",
+                             "testonly",
+                             "visibility",
+                             "generate_descriptor",
+                           ])
+  }
+}
diff --git a/gn/standalone/BUILD.gn b/gn/standalone/BUILD.gn
index 0c77eca..e88053b 100644
--- a/gn/standalone/BUILD.gn
+++ b/gn/standalone/BUILD.gn
@@ -13,8 +13,8 @@
 # limitations under the License.
 
 import("//gn/standalone/android.gni")
-import("//gn/standalone/sanitizers/sanitizers.gni")
 import("//gn/standalone/wasm.gni")
+import("//gn/standalone/sanitizers/sanitizers.gni")
 
 config("extra_warnings") {
   cflags = [
@@ -76,10 +76,11 @@
     "-fPIC",
     "-g",
     "-Wformat",
+    "-Werror",
   ]
 
-  if (!is_fuzzer) {
-    cflags += [ "-Werror" ]
+  if (!is_wasm && !is_lto) {
+    cflags += [ "-Wa,--noexecstack" ]
   }
 
   if (is_clang) {
@@ -108,10 +109,7 @@
       "-msse2",
       "-mfpmath=sse",
     ]
-    ldflags += [
-      "-m32",
-      "-lgcc",
-    ]
+    ldflags += [ "-m32" ]
   } else if (current_cpu == "arm64") {
     cflags += [ "-fno-omit-frame-pointer" ]
   }
@@ -192,7 +190,7 @@
     "-ffunction-sections",
   ]
   if (is_android) {
-    cflags += [ "-O2" ]
+    cflags += [ "-Oz" ]
   } else if (is_fuzzer) {
     cflags += [ "-O1" ]
   } else {
@@ -202,6 +200,7 @@
     ldflags = [ "-dead_strip" ]
   } else {
     ldflags = [
+      "-fuse-ld=gold",
       "-Wl,--gc-sections",
       "-Wl,--icf=all",
       "-Wl,-O1",
diff --git a/gn/standalone/BUILDCONFIG.gn b/gn/standalone/BUILDCONFIG.gn
index d980a05..e1bc1c2 100644
--- a/gn/standalone/BUILDCONFIG.gn
+++ b/gn/standalone/BUILDCONFIG.gn
@@ -23,6 +23,10 @@
   extra_ldflags = ""
 }
 
+declare_args() {
+  ar = "ar"
+}
+
 # Platform detection
 if (target_os == "") {
   target_os = host_os
@@ -51,8 +55,6 @@
   current_cpu = target_cpu
 }
 
-is_cross_compiling = target_cpu != host_cpu || target_os != host_os
-
 default_configs = [
   "//gn/standalone:debug_symbols",
   "//gn/standalone:default",
@@ -97,11 +99,5 @@
   configs += [ "//gn/standalone:android_liblog" ]
 }
 
-_default_toolchain = "//gn/standalone/toolchain:gcc_like"
-set_default_toolchain(_default_toolchain)
-
-if (is_cross_compiling) {
-  host_toolchain = "//gn/standalone/toolchain:gcc_like_host"
-} else {
-  host_toolchain = _default_toolchain
-}
+set_default_toolchain("//gn/standalone/toolchain:gcc_like")
+host_toolchain = "//gn/standalone/toolchain:gcc_like_host"
diff --git a/gn/standalone/build_tool_wrapper.py b/gn/standalone/build_tool_wrapper.py
index e1abe19..966ab66 100644
--- a/gn/standalone/build_tool_wrapper.py
+++ b/gn/standalone/build_tool_wrapper.py
@@ -12,20 +12,18 @@
 # 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.
+
 """ Wrapper to invoke compiled build tools from the build system.
 
 This is just a workaround for GN assuming that all external scripts are
 python sources. It is used to invoke tools like the protoc compiler.
 """
 
-from __future__ import print_function
-
 import argparse
 import os
 import subprocess
 import sys
 
-
 def main():
   parser = argparse.ArgumentParser()
   parser.add_argument('--chdir', default=None)
@@ -41,8 +39,7 @@
     return 0
 
   if args.chdir and not os.path.exists(args.chdir):
-    print(
-        'Cannot chdir to %s from %s' % (workdir, os.getcwd()), file=sys.stderr)
+    print >> sys.stderr, 'Cannot chdir to %s from %s' % (workdir, os.getcwd())
     return 1
 
   exe = os.path.abspath(args.cmd[0]) if os.sep in args.cmd[0] else args.cmd[0]
@@ -67,10 +64,9 @@
         os.utime(args.stamp, None)
     return ret
   except OSError as e:
-    print('Error running: "%s" (%s)' % (args.cmd[0], e.strerror))
-    print('PATH=%s' % env.get('PATH'))
+    print 'Error running: "%s" (%s)' % (args.cmd[0], e.strerror)
+    print 'PATH=%s' % env.get('PATH')
     return 127
 
-
 if __name__ == '__main__':
   sys.exit(main())
diff --git a/gn/standalone/check_buildtool_exists.py b/gn/standalone/check_buildtool_exists.py
index f9f57bf..0b2ada5 100755
--- a/gn/standalone/check_buildtool_exists.py
+++ b/gn/standalone/check_buildtool_exists.py
@@ -12,6 +12,7 @@
 # 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.
+
 """ Script to check whether a given buildtool folder exists.
 
 Prints a user-friendly message if it doesn't.
@@ -21,7 +22,6 @@
 import sys
 import argparse
 
-
 def main():
   parser = argparse.ArgumentParser(description='Test path for existence')
   parser.add_argument('path', help='Path to test for existence')
@@ -30,7 +30,7 @@
 
   if not os.path.exists(args.path):
     err = '\x1b[31mCannot find %s/%s\nRun tools/install-build-deps --ui\x1b[0m'
-    print >> sys.stderr, err % (os.path.abspath('.'), sys.argv[1])
+    print >>sys.stderr,  err % (os.path.abspath('.'), sys.argv[1])
     return 127
 
   if args.touch:
@@ -39,6 +39,5 @@
 
   return 0
 
-
 if __name__ == '__main__':
   sys.exit(main())
diff --git a/gn/standalone/fuzzer.gni b/gn/standalone/fuzzer.gni
index 0b3f332..c6e3ed5 100644
--- a/gn/standalone/fuzzer.gni
+++ b/gn/standalone/fuzzer.gni
@@ -20,7 +20,7 @@
   if (is_fuzzer) {
     executable(target_name) {
       if (use_libfuzzer) {
-        deps += [ "//gn:libfuzzer" ]
+        deps += [ "//buildtools:libfuzzer" ]
       } else {
         ldflags = [ link_fuzzer ]
       }
diff --git a/gn/standalone/gen_git_revision.py b/gn/standalone/gen_git_revision.py
index a45262a..a5c161a 100755
--- a/gn/standalone/gen_git_revision.py
+++ b/gn/standalone/gen_git_revision.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # Copyright (C) 2019 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,14 +16,11 @@
 import subprocess
 import sys
 
-
 def main(argv):
   if len(argv) != 2:
-    print('Usage: %s output_file.h' % argv[0])
+    print 'Usage: %s output_file.h'
     return 1
-  script_dir = os.path.dirname(os.path.realpath(__file__))
-  revision = subprocess.check_output(
-      ['git', '-C', script_dir, 'rev-parse', 'HEAD']).strip()
+  revision = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip()
   new_contents = '#define PERFETTO_GET_GIT_REVISION() "%s"\n' % revision
   out_file = argv[1]
   old_contents = ''
@@ -37,6 +33,5 @@
     f.write(new_contents)
   return 0
 
-
 if __name__ == '__main__':
   sys.exit(main(sys.argv))
diff --git a/gn/standalone/glob.py b/gn/standalone/glob.py
index 1219ec7..eafcbc4 100755
--- a/gn/standalone/glob.py
+++ b/gn/standalone/glob.py
@@ -12,6 +12,7 @@
 # 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.
+
 """ Script to list all files in a directory filtering by pattern.
 
 Do NOT use this script to pull in sources for GN targets. Globbing inputs is
@@ -20,13 +21,12 @@
 output of the build but just cause spurious re-runs (e.g. as input section of
 an "action" target).
 """
-from __future__ import print_function
+from __future__ import print_function 
 import argparse
 import fnmatch
 import os
 import sys
 
-
 def main():
   parser = argparse.ArgumentParser()
   parser.add_argument('--filter', default=[], action='append')
@@ -37,7 +37,6 @@
   args = parser.parse_args()
 
   fout = open(args.output, 'w') if args.output else sys.stdout
-
   def writepath(path):
     if args.deps:
       path = '\t' + path
@@ -65,6 +64,5 @@
       if match:
         writepath(fpath)
 
-
 if __name__ == '__main__':
   sys.exit(main())
diff --git a/gn/standalone/libc++/libc++.gni b/gn/standalone/libc++/libc++.gni
index c4290b2..52c1dac 100644
--- a/gn/standalone/libc++/libc++.gni
+++ b/gn/standalone/libc++/libc++.gni
@@ -37,9 +37,9 @@
   # 2) The libstdc++ situation is too wild on Linux. Modern debian distros are
   #    fine but Ubuntu Trusty still ships a libstdc++ that doesn't fully
   #    support C++11. Hence we enable this flag on Linux by default.
-  #    We still retain libstdc++ coverage on the CI bots by overriding
+  #    We still retain libstdc++ coverage on the Travis bots by overriding
   #    use_custom_libcxx=false when we target a modern library (see the
-  #    GCC target in infra/ci/config.py).
+  #    GCC7 target in .travis.yml).
   use_custom_libcxx = is_linux && is_clang && !is_wasm
   custom_libcxx_is_static = !using_sanitizer
 }
diff --git a/gn/standalone/proto_library.gni b/gn/standalone/proto_library.gni
index 0180b2b..caa58d9 100644
--- a/gn/standalone/proto_library.gni
+++ b/gn/standalone/proto_library.gni
@@ -69,16 +69,11 @@
   cc_out_dir = "$root_gen_dir/" + proto_out_dir
   rel_cc_out_dir = rebase_path(cc_out_dir, root_build_dir)
 
-  # Prevent unused errors when generating descriptor only.
-  if (generate_descriptor != "") {
-    not_needed([ "rel_cc_out_dir" ])
-  }
-
   protos = rebase_path(proto_sources, proto_in_dir)
   protogens = []
 
   if (generate_descriptor != "") {
-    protogens += [ "$target_gen_dir/" + generate_descriptor ]
+    protogens += [ "$root_gen_dir/" + generate_descriptor ]
   }
 
   foreach(proto, protos) {
@@ -86,11 +81,6 @@
     proto_name = get_path_info(proto, "name")
     proto_path = proto_dir + "/" + proto_name
 
-    # Prevent unused errors when generating descriptor only.
-    if (generate_descriptor != "") {
-      not_needed([ "proto_path" ])
-    }
-
     if (generate_cc) {
       protogens += [
         "$cc_out_dir/$proto_path.pb.h",
@@ -105,12 +95,8 @@
   }
 
   config_name = "${target_name}_config"
-  if (generate_descriptor == "") {
-    action_name = "${target_name}_gen"
-    source_set_name = target_name
-  } else {
-    action_name = target_name
-  }
+  action_name = "${target_name}_gen"
+  source_set_name = target_name
 
   config(config_name) {
     include_dirs = [ cc_out_dir ]
@@ -118,19 +104,14 @@
 
   # The XXX_gen action that generates the .pb.{cc,h} files.
   action(action_name) {
-    if (generate_descriptor == "") {
-      visibility = [ ":$source_set_name" ]
-    }
+    visibility = [ ":$source_set_name" ]
     script = "//gn/standalone/build_tool_wrapper.py"
     sources = proto_sources
     outputs = get_path_info(protogens, "abspath")
 
-    protoc_script = "//gn/standalone/protoc.py"
-    protoc_label = "//gn:protoc($host_toolchain)"
+    protoc_label = "//buildtools:protoc($host_toolchain)"
     protoc_path = get_label_info(protoc_label, "root_out_dir") + "/protoc"
     args = [
-      "./" + rebase_path(protoc_script, root_build_dir),
-
       # Path should be rebased because |root_build_dir| for current toolchain
       # may be different from |root_out_dir| of protoc built on host toolchain.
       "./" + rebase_path(protoc_path, root_build_dir),
@@ -144,13 +125,10 @@
       ]
     }
     if (generate_descriptor != "") {
-      depfile = "$target_gen_dir/$generate_descriptor.d"
       args += [
         "--include_imports",
         "--descriptor_set_out",
-        rebase_path("$target_gen_dir/$generate_descriptor", root_build_dir),
-        "--dependency_out",
-        rebase_path(depfile, root_build_dir),
+        rebase_path("$root_gen_dir/" + generate_descriptor, root_build_dir),
       ]
     }
 
@@ -196,54 +174,52 @@
     if (defined(invoker.deps)) {
       deps += invoker.deps
     }
-  }  # action(action_name)
+  }  # action "${target_name}_gen"
 
   # The source_set that builds the generated .pb.cc files.
-  if (generate_descriptor == "") {
-    source_set(source_set_name) {
-      forward_variables_from(invoker,
-                             [
-                               "defines",
-                               "include_dirs",
-                               "public_configs",
-                               "testonly",
-                               "visibility",
-                             ])
+  source_set(target_name) {
+    forward_variables_from(invoker,
+                           [
+                             "defines",
+                             "include_dirs",
+                             "public_configs",
+                             "testonly",
+                             "visibility",
+                           ])
 
-      sources = get_target_outputs(":$action_name")
+    set_sources_assignment_filter([ "*\.descriptor" ])
+    sources = get_target_outputs(":$action_name")
+    set_sources_assignment_filter([])
 
-      configs -= [ "//gn/standalone:extra_warnings" ]
-      if (defined(invoker.extra_configs)) {
-        configs += invoker.extra_configs
-      }
+    configs -= [ "//gn/standalone:extra_warnings" ]
+    if (defined(invoker.extra_configs)) {
+      configs += invoker.extra_configs
+    }
 
-      if (!defined(invoker.public_configs)) {
-        public_configs = []
-      }
+    if (!defined(invoker.public_configs)) {
+      public_configs = []
+    }
 
-      public_configs += [
-        "//buildtools:protobuf_gen_config",
-        ":$config_name",
+    public_configs += [
+      "//buildtools:protobuf_gen_config",
+      ":$config_name",
+    ]
+
+    # Use protobuf_full only for tests.
+    if (defined(invoker.use_protobuf_full) &&
+        invoker.use_protobuf_full == true) {
+      deps = [
+        "//buildtools:protobuf_full",
       ]
+    } else {
+      deps = [
+        "//buildtools:protobuf_lite",
+      ]
+    }
 
-      # Use protobuf_full only for tests.
-      if (defined(invoker.use_protobuf_full) &&
-          invoker.use_protobuf_full == true) {
-        deps = [
-          "//gn:protobuf_full",
-        ]
-      } else if (generate_cc) {
-        deps = [
-          "//gn:protobuf_lite",
-        ]
-      } else {
-        deps = []
-      }
-
-      deps += [ ":$action_name" ]
-      if (defined(invoker.deps)) {
-        deps += invoker.deps
-      }
-    }  # source_set(source_set_name)
-  }
+    deps += [ ":$action_name" ]
+    if (defined(invoker.deps)) {
+      deps += invoker.deps
+    }
+  }  # source_set(target_name)
 }  # template
diff --git a/gn/standalone/protoc.py b/gn/standalone/protoc.py
deleted file mode 100755
index 723c35e..0000000
--- a/gn/standalone/protoc.py
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2019 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.
-"""Script to wrap protoc execution.
-
-This script exists to work-around the bad depfile generation by protoc when
-generating descriptors."""
-
-from __future__ import print_function
-import argparse
-import os
-import sys
-import subprocess
-import tempfile
-
-from codecs import open
-
-
-def main():
-  parser = argparse.ArgumentParser()
-  parser.add_argument('--descriptor_set_out', default=None)
-  parser.add_argument('--dependency_out', default=None)
-  parser.add_argument('protoc')
-  args, remaining = parser.parse_known_args()
-
-  if args.dependency_out and args.descriptor_set_out:
-    with tempfile.NamedTemporaryFile() as t:
-      custom = [
-          '--descriptor_set_out', args.descriptor_set_out, '--dependency_out',
-          t.name
-      ]
-      subprocess.check_call([args.protoc] + custom + remaining)
-
-      dependency_data = t.read().decode('utf-8')
-
-    with open(args.dependency_out, 'w', encoding='utf-8') as f:
-      f.write(args.descriptor_set_out + ":")
-      f.write(dependency_data)
-  else:
-    subprocess.check_call(sys.argv[1:])
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/gn/standalone/sanitizers/sanitizers.gni b/gn/standalone/sanitizers/sanitizers.gni
index 9b0ec00..95f40d1 100644
--- a/gn/standalone/sanitizers/sanitizers.gni
+++ b/gn/standalone/sanitizers/sanitizers.gni
@@ -54,3 +54,8 @@
     }
   }
 }
+
+using_sanitizer = is_asan || is_lsan || is_tsan || is_msan || is_ubsan
+assert(!using_sanitizer || is_clang, "is_*san requires is_clang=true'")
+assert(!is_msan || is_linux, "msan only supported on linux")
+assert(!is_tsan || (is_linux || is_mac), "tsan only supported on linux and mac")
diff --git a/gn/standalone/toolchain/BUILD.gn b/gn/standalone/toolchain/BUILD.gn
index 7394802..1ffb94f 100644
--- a/gn/standalone/toolchain/BUILD.gn
+++ b/gn/standalone/toolchain/BUILD.gn
@@ -12,118 +12,53 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("//gn/perfetto.gni")
 import("//gn/standalone/android.gni")
 import("//gn/standalone/wasm.gni")
 import("llvm.gni")
 
-# This file is evaluated once, within the context of the default toolchain,
-# which is the target toolchain.
-# Note: This means that is_android=true even on a mac when cross-compiling for
-# Android.
-assert(current_os == target_os && current_cpu == target_cpu,
-       "Assumptions on current_xxx in this file have been violated")
-
 declare_args() {
-  cc_wrapper = ""
-}
-
-# First of all determine the host toolchain. The user can override this by:
-# 1. setting ar/cc/cxx vars in args.gn.
-# 2. setting is_system_compiler=true in args.gn and the env vars AR/CC/CXX.
-#    This is used by OSSFuzz.
-declare_args() {
-  sysroot = ""
-  ar = "ar"
-  if (is_linux_host) {
-    linker = "gold"
-  } else {
-    linker = ""
-  }
-
-  if (is_system_compiler) {
-    ar = "\$AR"
-    cc = "\$CC"
-    cxx = "\$CXX"
-  } else if (is_clang) {
-    if (is_linux_host) {
+  if (is_clang) {
+    if (is_system_compiler) {
+      cc = "\$CC "
+      cxx = "\$CXX "
+    } else if (is_linux) {
       cc = linux_clang_bin
       cxx = linux_clangxx_bin
-      linker = linux_clang_linker
     } else {
       cc = "clang"
       cxx = "clang++"
-      linker = ""
     }
-  } else {  # GCC
+  } else {
     cc = "gcc"
     cxx = "g++"
   }
 }
 
-# Then determine the target toolchain.
-
 declare_args() {
-  target_sysroot = sysroot
-  if (!is_cross_compiling) {
-    target_triplet = ""
-  } else if (target_os == "mac" && target_cpu == "x64") {
-    target_triplet = "x86_64-apple-darwin"
-  } else if (target_os == "mac" && target_cpu == "x86") {
-    target_triplet = "i686-apple-darwin"
-  } else if (target_os == "linux" && target_cpu == "arm64") {
-    target_triplet = "aarch64-linux-gnu"
-  } else if (target_os == "linux" && target_cpu == "x64") {
-    target_triplet = "x86_64-linux-gnu"
-  } else if (target_os == "linux" && target_cpu == "x86") {
-    target_triplet = "i686-linux-gnu"
-  } else if (target_os == "android" && target_cpu == "arm64") {
-    target_triplet = "aarch64-linux-android"
-  } else if (target_os == "android" && target_cpu == "arm") {
-    target_triplet = "arm-linux-androideabi"
-  } else if (target_os == "android" && target_cpu == "x86") {
-    target_triplet = "i686-linux-android"
-  } else if (target_os == "android" && target_cpu == "x86_64") {
-    target_triplet = "x86_64-linux-android"
+  host_ar = ar
+  if (is_linux_host && is_clang) {
+    host_cc = linux_clang_bin
+    host_cxx = linux_clangxx_bin
   } else {
-    assert(false,
-           "Unsupported cross-compilation for ${target_os}-${target_cpu}")
+    host_cc = cc
+    host_cxx = cxx
   }
-}
 
-declare_args() {
-  if (!is_cross_compiling || is_perfetto_build_generator) {
+  if (is_android) {
+    target_ar = "$android_toolchain_root/bin/$android_abi_target-ar"
+    target_cc = "$android_llvm_dir/bin/clang"
+    target_cxx = "$android_llvm_dir/bin/clang++"
+  } else {
     target_ar = ar
     target_cc = cc
     target_cxx = cxx
-    target_linker = linker
-  } else {
-    target_ar = "ar"
-    if (is_linux || is_android) {
-      target_linker = "gold"
-    } else {
-      target_linker = ""
-    }
-    if (is_android) {
-      target_ar = "$android_toolchain_root/bin/$android_abi_target-ar"
-      target_cc = "$android_llvm_dir/bin/clang"
-      target_cxx = "$android_llvm_dir/bin/clang++"
-    } else {
-      assert(target_triplet != "",
-             "target_triplet must be non-empty when cross-compiling")
-      if (is_clang) {
-        target_cc = "${linux_clang_bin} --target=${target_triplet}"
-        target_cxx = "${linux_clangxx_bin} --target=${target_triplet}"
-        target_linker = "${linux_clang_linker} --target=${target_triplet}"
-      } else {  # GCC
-        target_ar = "${target_triplet}-ar"
-        target_cc = "${target_triplet}-gcc"
-        target_cxx = "${target_triplet}-g++"
-      }
-    }
   }
+  cc_wrapper = ""
 }
 
+python = "python"
+stamp = "touch"
+
 template("gcc_like_toolchain") {
   toolchain(target_name) {
     ar = invoker.ar
@@ -131,16 +66,6 @@
     cxx = invoker.cxx
     lib_switch = "-l"
     lib_dir_switch = "-L"
-    ld_arg = ""
-    if (defined(invoker.linker) && invoker.linker != "") {
-      _invoker_linker = invoker.linker
-      ld_arg = "-fuse-ld=$_invoker_linker"
-    }
-    if (defined(invoker.sysroot) && invoker.sysroot != "") {
-      _invoker_sysroot = invoker.sysroot
-      cc = "$cc --sysroot=$_invoker_sysroot"
-      cxx = "$cxx --sysroot=$_invoker_sysroot"
-    }
 
     tool("cc") {
       depfile = "{{output}}.d"
@@ -173,11 +98,10 @@
     }
 
     tool("alink") {
-      rspfile = "{{output}}.rsp"
       if (is_mac && ar != "suppress_unused_ar_variable_warning") {
-        rspfile_content = "{{inputs_newline}}"
-        command = "rm -f {{output}} && libtool -static {{arflags}} -o {{output}} -filelist $rspfile"
+        command = "rm -f {{output}} && libtool -static {{arflags}} -o {{output}} {{inputs}}"
       } else {
+        rspfile = "{{output}}.rsp"
         rspfile_content = "{{inputs}}"
         command = "$ar rcsD {{output}} @$rspfile"
       }
@@ -197,7 +121,7 @@
         rpath = "-Wl,-install_name,@rpath/$soname"
       }
 
-      command = "$cc_wrapper $cxx $ld_arg -shared {{ldflags}} ${extra_ldflags} {{inputs}} {{solibs}} {{libs}} $rpath -o {{output}}"
+      command = "$cc_wrapper $cxx -shared {{ldflags}} ${extra_ldflags} {{inputs}} {{solibs}} {{libs}} $rpath -o {{output}}"
       outputs = [
         "{{root_out_dir}}/$soname",
       ]
@@ -207,7 +131,7 @@
     }
 
     tool("link") {
-      command = "$cc_wrapper $cxx $ld_arg {{ldflags}} ${extra_ldflags} {{inputs}} {{solibs}} {{libs}} -o {{output}}"
+      command = "$cc_wrapper $cxx {{ldflags}} ${extra_ldflags} {{inputs}} {{solibs}} {{libs}} -o {{output}}"
       outputs = [
         "{{root_out_dir}}/{{target_output_name}}{{output_extension}}",
       ]
@@ -237,18 +161,14 @@
   ar = target_ar
   cc = target_cc
   cxx = target_cxx
-  linker = target_linker
-  sysroot = target_sysroot
 }
 
 gcc_like_toolchain("gcc_like_host") {
   cpu = host_cpu
   os = host_os
-  ar = ar
-  cc = cc
-  cxx = cxx
-  linker = linker
-  sysroot = sysroot
+  ar = host_ar
+  cc = host_cc
+  cxx = host_cxx
 }
 
 gcc_like_toolchain("wasm") {
diff --git a/gn/standalone/toolchain/linux_find_llvm.py b/gn/standalone/toolchain/linux_find_llvm.py
index 858185c..bccd17e 100644
--- a/gn/standalone/toolchain/linux_find_llvm.py
+++ b/gn/standalone/toolchain/linux_find_llvm.py
@@ -16,7 +16,6 @@
 import subprocess
 import sys
 
-
 def main():
   devnull = open(os.devnull, 'w')
   for clang in ('clang', 'clang-3.8', 'clang-3.5'):
@@ -37,6 +36,5 @@
   print 'Could not find the LLVM lib dir'
   return 1
 
-
 if __name__ == '__main__':
   sys.exit(main())
diff --git a/gn/standalone/toolchain/llvm.gni b/gn/standalone/toolchain/llvm.gni
index dda60ab..f6bd038 100644
--- a/gn/standalone/toolchain/llvm.gni
+++ b/gn/standalone/toolchain/llvm.gni
@@ -24,10 +24,10 @@
   if (is_linux_host) {
     if (is_hermetic_clang) {
       _hermetic_llvm_dir = rebase_path("//buildtools/clang", root_build_dir)
+      linux_llvm_dir = "$_hermetic_llvm_dir/lib/clang/6.0.0/"
       linux_clang_bin = "$_hermetic_llvm_dir/bin/clang"
       linux_clangxx_bin = "$_hermetic_llvm_dir/bin/clang++"
-      linux_clangrt_dir = "$_hermetic_llvm_dir/lib/clang/9.0.0/lib/linux"
-      linux_clang_linker = "lld"
+      linux_clangrt_dir = "$_hermetic_llvm_dir/lib/clang/6.0.0/lib/linux"
     } else if (is_clang) {
       # Guess the path for the system clang.
       find_llvm_out = exec_script("linux_find_llvm.py", [], "list lines")
@@ -35,7 +35,6 @@
       linux_clang_bin = find_llvm_out[1]
       linux_clangxx_bin = find_llvm_out[2]
       linux_clangrt_dir = "$linux_llvm_dir/lib/linux"
-      linux_clang_linker = "gold"
     }
   } else if (is_mac) {
     mac_toolchain_dirs_ = exec_script("mac_find_llvm.py", [], "list lines")
diff --git a/gn/standalone/toolchain/mac_find_llvm.py b/gn/standalone/toolchain/mac_find_llvm.py
index 3511f29..17d1ea1 100644
--- a/gn/standalone/toolchain/mac_find_llvm.py
+++ b/gn/standalone/toolchain/mac_find_llvm.py
@@ -17,7 +17,6 @@
 import subprocess
 import sys
 
-
 def main():
   job = subprocess.Popen(['xcrun', '-f', 'clang++'],
                          stdout=subprocess.PIPE,
@@ -29,8 +28,7 @@
     return job.returncode
   sdk_dir = os.path.dirname(os.path.dirname(out.rstrip()))
   print sdk_dir
-  clang_dir = glob.glob(
-      os.path.join(sdk_dir, 'lib', 'clang', '*', 'lib', 'darwin'))
+  clang_dir = glob.glob(os.path.join(sdk_dir, 'lib', 'clang', '*', 'lib', 'darwin'))
   print clang_dir[0] if clang_dir else 'CLANG_DIR_NOT_FOUND'
 
 
diff --git a/gn/standalone/wasm.gni b/gn/standalone/wasm.gni
index b3a6c1a..0100351 100644
--- a/gn/standalone/wasm.gni
+++ b/gn/standalone/wasm.gni
@@ -12,8 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../wasm_vars.gni")
-
+wasm_toolchain = "//gn/standalone/toolchain:wasm"
+is_wasm = current_toolchain == wasm_toolchain
 emsdk_dir = rebase_path("//buildtools/emsdk", "")
 nodejs_dir = rebase_path("//buildtools/nodejs", "")
 
diff --git a/gn/standalone/wasm_typescript_declaration.d.ts b/gn/standalone/wasm_typescript_declaration.d.ts
index 9fa3538..4ac92e9 100644
--- a/gn/standalone/wasm_typescript_declaration.d.ts
+++ b/gn/standalone/wasm_typescript_declaration.d.ts
@@ -52,7 +52,7 @@
         returnType: string,
         argTypes: string[],
         args: any[],
-        ): number;
+    ): void;
     HEAPU8: Uint8Array;
     FS: FileSystem;
   }
diff --git a/gn/test.gni b/gn/test.gni
index d177acb..81d38ac 100644
--- a/gn/test.gni
+++ b/gn/test.gni
@@ -14,7 +14,7 @@
 
 import("perfetto.gni")
 
-if (perfetto_root_path == "//") {
+if (perfetto_build_standalone || perfetto_build_with_android) {
   template("test") {
     executable(target_name) {
       forward_variables_from(invoker, "*")
@@ -32,18 +32,3 @@
     }
   }
 }
-
-# This is to avoid that unittest targets get discovered and built in the
-# "default" GN target of embedder builds. See notes in the comments of the
-# root BUILD.gn.
-template("perfetto_unittest_source_set") {
-  if (enable_perfetto_unittests) {
-    source_set(target_name) {
-      forward_variables_from(invoker, "*")
-    }
-  } else {
-    group(target_name) {
-      not_needed(invoker, "*")
-    }
-  }
-}
diff --git a/gn/wasm.gni b/gn/wasm.gni
index a8bc0a9..87326c9 100644
--- a/gn/wasm.gni
+++ b/gn/wasm.gni
@@ -12,12 +12,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import("//build_overrides/build.gni")
 import("perfetto.gni")
-import("wasm_vars.gni")
 
-if (perfetto_root_path == "//") {
+if (perfetto_build_standalone) {
   import("//gn/standalone/wasm.gni")
 } else {
+  is_wasm = false  # The WASM toolchain is supported only in standalone builds.
+
   # Create a dummy template to avoid GN warnings in non-standalone builds.
   template("wasm_lib") {
     source_set("${target_name}_${invoker.name}_unused") {
diff --git a/gn/wasm_vars.gni b/gn/wasm_vars.gni
deleted file mode 100644
index 39998f5..0000000
--- a/gn/wasm_vars.gni
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (C) 2019 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.
-
-wasm_toolchain = "//gn/standalone/toolchain:wasm"
-is_wasm = current_toolchain == wasm_toolchain
diff --git a/gn/write_buildflag_header.py b/gn/write_buildflag_header.py
deleted file mode 100644
index 6d92daa..0000000
--- a/gn/write_buildflag_header.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2019 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 writes headers for build flags. See the gen_buildflags target in
-# /gn/BUILD.gn for usage.
-#
-# The parameters are passed in a response file so we don't have to worry
-# about command line lengths. The name of the response file is passed on the
-# command line.
-#
-# The format of the response file is:
-#    [--flags <list of one or more flag values>]
-
-import argparse
-import os
-import shlex
-import sys
-
-
-def main():
-  parser = argparse.ArgumentParser()
-  parser.add_argument('--rsp', help='Input response file containing the flags.')
-  parser.add_argument('--out', help='Output path of the generated header file.')
-  args = parser.parse_args()
-
-  flags = []
-  with open(args.rsp, 'r') as def_file:
-    marker_seen = False
-    for flag in shlex.split(def_file.read()):
-      if not marker_seen:
-        marker_seen = flag == '--flags'
-        continue
-      key, value = flag.split('=', 1)
-      value = '1' if value == 'true' else '0' if value == 'false' else value
-      flags.append((key, value))
-
-  guard = '%s_' % args.out.upper()
-  guard = guard.replace('/', '_').replace('\\', '_').replace('.', '_')
-  lines = []
-  lines.append('// Generated by %s' % __file__)
-  lines.append('')
-  lines.append('// fix_include_guards: off')
-  lines.append('#ifndef %s' % guard)
-  lines.append('#define %s' % guard)
-  lines.append('')
-  lines.append('// clang-format off')
-  for kv in flags:
-    lines.append('#define PERFETTO_BUILDFLAG_DEFINE_%s() (%s)' % kv)
-  lines.append('')
-  lines.append('// clang-format on')
-  lines.append('#endif  // %s' % guard)
-  lines.append('')
-
-  with open(args.out, 'w') as out:
-    out.write('\n'.join(lines))
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/heapprofd.rc b/heapprofd.rc
index 56ca875..2e69f60 100644
--- a/heapprofd.rc
+++ b/heapprofd.rc
@@ -23,6 +23,7 @@
     onrestart exec_background - nobody shell -- /system/bin/heapprofd --cleanup-after-crash
     # DAC_READ_SEARCH is denied by SELinux on user builds because the SELinux
     # permission is userdebug_or_eng only.
+    # This is fine as this is not needed for central heapprofd in fork mode.
     capabilities KILL DAC_READ_SEARCH
 
 on property:persist.heapprofd.enable=1
diff --git a/include/README.md b/include/README.md
deleted file mode 100644
index 83a92f7..0000000
--- a/include/README.md
+++ /dev/null
@@ -1,111 +0,0 @@
-# Perfetto public API surface
-
-**This API surface is not stable yet, don't depend on it**
-
-This folder contains the public perfetto API headers. This allows an app to
-inject trace events into perfetto with ~10 lines of code (see
-api_usage_example.cc).
-
-The ext/ subdirectory expose the API-unstable classes and types that are
-exposed to emvbedders that have exceptional requirements in terms of interposing
-their own custom IPC layer. To the day the only case is chromium. Nothing else
-should depend on ext/. Contact perfetto-dev@ if you think you need to 
-depend on an ext/ header.
-
-Headers in this folder must be hermetic. No ext/ perfetto header must be
-leaked from the includes.
-
-What is a client supposed to do to use tracing? See example below in this page.
-
-
-Source code layout: what goes where?
-------------------------------------
-
-**include/perfetto (this folder):**
-Embedders are allowed to access and depend on any folder of this but ext/.
-This contains classes to: (i) use tracing; (ii) extend the tracing internals
-(i.e. implement the Platform).
-
-Rules:
-- This directory should contain only .h files and no .cc files.
-- Corresponding .cc files go into `src/`.
-- .h files in here can depend only on `include/perfetto/` but not on
-  `include/perfetto/ext/`,
-
-**include/perfetto/tracing/internal:**
-This directory contains headers that are required to implement the public-facing
-tracing API efficiently but that are not part of the API surface.
-In an ideal world there would be no need of these headers and everything would
-be handle via forward-declarations and PIMPL patterns. Unfortunately, however,
-PIMPL cannot be used for inline functions, where the implementation needs to be
-exposed in the public headers, which in turn need to depend on the memory layout
-of structs/classes.
-
-Rules:
-- All classes / types declared in this folder must be wrapped in the
-  ::perfetto::internal namespace.
-- Both public and internal .h headers must not pull other perfetto headers
-  from ext/.
-- .cc files instead can depend on other perfetto classes, as well as .h headers
-  located in src/.
-- Embedders must not depend on the perfetto::internal namespace.
-- Internal types cannot be used as input, output or return arguments of public
-  API functions.
-- Internal types cannot be directly exposed to virtual methods that are
-  intended to be called or overridden by the embedder (e.g. TracingBackend's
-  methods). For those the solution is to create a matching non-internal base
-  class with a static factory method.
-- We don't guarantee binary compatibility between versions (i.e. this client
-  library can only be statically linked) but we guarantee source-level
-  compatibility and ABI of the UNIX socket and shared memory buffers.
-
-
-Usage example
--------------
-1. Call `perfetto::Tracing::Initialize(...)` once, when starting the app.
-  While doing so the app can chose the tracing model:
-  - Fully in-process: the service runs in a thread within the same process.
-  - System: connects to the traced system daemon via a UNIX socket. This allows
-    the app to join system-wide tracing sessions. This is available only on
-    Linux/Android/MacOS for now.
-  - Private dedicated process: similar to the in-process case, but the service
-    runs in a dedicated process rather than a thread. This is for performance,
-    stability and security isolation. Also, this is not implemented yet.
-  - Custom backend: this is for peculiar cases (mainly chromium) where the
-    embedder is multi-process but wants to use a different IPC mechanism. The
-    embedder needs to deal with the larger and clunkier set of perfetto APIs.
-    Reach out to the team before using this mode. It's very unlikely you need
-    this unless you are a project rolled into chromium.
-
-2. Define and register one or more data sources, like this:
-```cpp
-  #include "perfetto/tracing.h"
-
-  class MyDataSource : public perfetto::DataSource<MyDataSource> {
-    void OnSetup(const SetupArgs&) override {}
-    void OnStart(const StartArgs&) override {}
-    void OnStop(const StopArgs&) override {}
-  };
-  ...
-  PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(MyDataSource);
-  ...
-  perfetto::DataSourceDescriptor dsd;
-  dsd.set_name("my_data_source");
-  MyDataSource::Register(dsd);
-```
-
-3. Optionally define a new proto schema in `trace_packet.proto`
-
-4. Emit trace events
-```cpp
-  MyDataSource::Trace([](MyDataSource::TraceContext ctx) {
-      auto trace_packet = ctx.NewTracePacket();
-      trace_packet->set_timestamp(...);
-      auto* my_custom_proto = trace_packet->set_my_custom_proto();
-  });
-```
-
-The passed labmda will be called only if tracing is enabled and the data source
-was enabled in the trace config. It might be called multiple times, one for each
-active tracing session, in case of concurrent tracing sessions (or even within a
-single tracing session, if the data source is listed twice in the trace config).
diff --git a/include/perfetto/README.md b/include/perfetto/README.md
deleted file mode 100644
index 06dc913..0000000
--- a/include/perfetto/README.md
+++ /dev/null
@@ -1 +0,0 @@
-See [/include/README.md](/include/README.md)
\ No newline at end of file
diff --git a/include/perfetto/base/BUILD.gn b/include/perfetto/base/BUILD.gn
index e490551..0540e0f 100644
--- a/include/perfetto/base/BUILD.gn
+++ b/include/perfetto/base/BUILD.gn
@@ -17,10 +17,47 @@
 source_set("base") {
   sources = [
     "build_config.h",
-    "compiler.h",
+    "circular_queue.h",
+    "container_annotations.h",
+    "event.h",
     "export.h",
+    "file_utils.h",
+    "gtest_prod_util.h",
+    "hash.h",
     "logging.h",
+    "metatrace.h",
+    "no_destructor.h",
+    "optional.h",
+    "paged_memory.h",
+    "pipe.h",
+    "scoped_file.h",
+    "small_set.h",
+    "string_splitter.h",
+    "string_utils.h",
+    "string_view.h",
+    "string_writer.h",
     "task_runner.h",
+    "temp_file.h",
+    "thread_annotations.h",
+    "thread_checker.h",
+    "thread_task_runner.h",
+    "thread_utils.h",
     "time.h",
+    "unix_task_runner.h",
+    "utils.h",
+    "watchdog.h",
+    "watchdog_noop.h",
+    "watchdog_posix.h",
+    "weak_ptr.h",
   ]
+  if (is_android) {
+    sources += [ "android_task_runner.h" ]
+  }
+  if (perfetto_build_with_ipc_layer) {
+    sources += [ "unix_socket.h" ]
+  }
+  public_deps = [
+    "../../../gn:gtest_prod_config",
+  ]
+  public_configs = [ "../../../gn:asan_instrumentation" ]
 }
diff --git a/include/perfetto/base/android_task_runner.h b/include/perfetto/base/android_task_runner.h
new file mode 100644
index 0000000..5986997
--- /dev/null
+++ b/include/perfetto/base/android_task_runner.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_BASE_ANDROID_TASK_RUNNER_H_
+#define INCLUDE_PERFETTO_BASE_ANDROID_TASK_RUNNER_H_
+
+#include "perfetto/base/event.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/task_runner.h"
+#include "perfetto/base/thread_checker.h"
+#include "perfetto/base/time.h"
+
+#include <poll.h>
+#include <chrono>
+#include <map>
+#include <mutex>
+#include <queue>
+
+#include <android/looper.h>
+
+namespace perfetto {
+namespace base {
+
+// Runs a task runner on a thread owned by an Android Looper (ALooper).
+class AndroidTaskRunner : public TaskRunner {
+ public:
+  AndroidTaskRunner();
+  ~AndroidTaskRunner() override;
+
+  // The following methods are only used in cases where the caller wants to take
+  // ownership of the current thread (e.g., tests and standalone tools).
+  // Normally the Android Framework runs the event loop on the thread. Run() can
+  // only be called from the main thread but Quit() can be called from any
+  // thread.
+  void Run();
+  void Quit();
+
+  // Checks whether there are any pending immediate tasks to run. Note that
+  // delayed tasks don't count even if they are due to run. Can only be called
+  // from the main thread.
+  bool IsIdleForTesting();
+
+  // TaskRunner implementation:
+  void PostTask(std::function<void()>) override;
+  void PostDelayedTask(std::function<void()>, uint32_t delay_ms) override;
+  void AddFileDescriptorWatch(int fd, std::function<void()>) override;
+  void RemoveFileDescriptorWatch(int fd) override;
+  bool RunsTasksOnCurrentThread() const override;
+
+ private:
+  bool OnFileDescriptorEvent(int signalled_fd, int events);
+  void RunImmediateTask();
+  void RunDelayedTask();
+
+  void GetNextDelayedTaskRunTimeLocked(struct itimerspec* runtime);
+
+  void ScheduleImmediateWakeUp();
+  void ScheduleDelayedWakeUp(TimeMillis time);
+
+  ALooper* const looper_;
+  Event immediate_event_;
+  ScopedFile delayed_timer_;
+
+  ThreadChecker thread_checker_;
+
+  // --- Begin lock-protected members.
+  std::mutex lock_;
+  // Note: std::deque allocates blocks of 4k in some implementations. Consider
+  // another data structure if we end up having many task runner instances.
+  std::deque<std::function<void()>> immediate_tasks_;
+  std::multimap<TimeMillis, std::function<void()>> delayed_tasks_;
+  std::map<int, std::function<void()>> watch_tasks_;
+  bool quit_ = false;
+  // --- End lock-protected members.
+};
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_ANDROID_TASK_RUNNER_H_
diff --git a/include/perfetto/base/build_config.h b/include/perfetto/base/build_config.h
index bb641f5..5f01088 100644
--- a/include/perfetto/base/build_config.h
+++ b/include/perfetto/base/build_config.h
@@ -88,22 +88,45 @@
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPILER_MSVC() 0
 #endif
 
+#if defined(PERFETTO_BUILD_WITH_ANDROID)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_BUILD() 1
+#else
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_BUILD() 0
+#endif
+
+#if defined(PERFETTO_BUILD_WITH_EMBEDDER)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_EMBEDDER_BUILD() 1
+#else
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_EMBEDDER_BUILD() 0
+#endif
+
+#if defined(PERFETTO_BUILD_WITH_CHROMIUM)
+#if !defined(PERFETTO_BUILD_WITH_EMBEDDER)
+#error PERFETTO_BUILD_WITH_EMBEDDER must be defined when \
+       PERFETTO_BUILD_WITH_CHROMIUM is defined
+#endif
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_CHROMIUM_BUILD() 1
+#else
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_CHROMIUM_BUILD() 0
+#endif
+
+#if !defined(PERFETTO_BUILD_WITH_EMBEDDER) && \
+    !defined(PERFETTO_BUILD_WITH_ANDROID)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_STANDALONE_BUILD() 1
+#else
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_STANDALONE_BUILD() 0
+#endif
+
+#if defined(PERFETTO_START_DAEMONS_FOR_TESTING)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_START_DAEMONS() 1
+#else
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_START_DAEMONS() 0
+#endif
+
 #if defined(PERFETTO_BUILD_WITH_ANDROID_USERDEBUG)
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_USERDEBUG_BUILD() 1
 #else
 #define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_USERDEBUG_BUILD() 0
 #endif
 
-// perfetto_build_flags.h contains the tweakable build flags defined via GN.
-// - In GN builds (e.g., standalone, chromium, v8) this file is generated at
-//   build time via the gen_rule //gn/gen_buildflags.
-// - In Android in-tree builds, this file is generated by tools/gen_android_bp
-//   and checked in into include/perfetto/base/build_configs/android_tree/. The
-//   default cflags add this path to the default include path.
-// - Similarly, in bazel builds, this file is generated by tools/gen_bazel and
-//   checked in into include/perfetto/base/build_configs/bazel/.
-// - In amaglamated builds, this file is generated by tools/gen_amalgamated and
-//   added to the amalgamated headers.
-#include "perfetto_build_flags.h"  // no-include-violation-check
-
 #endif  // INCLUDE_PERFETTO_BASE_BUILD_CONFIG_H_
diff --git a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
deleted file mode 100644
index 4edd028..0000000
--- a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Generated by ../../gn/write_buildflag_header.py
-
-// fix_include_guards: off
-#ifndef GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
-#define GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
-
-// clang-format off
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_BUILD() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_CHROMIUM_BUILD() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_STANDALONE_BUILD() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_START_DAEMONS() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_IPC() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_WATCHDOG() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() || PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX())
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPONENT_BUILD() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_ON() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_OFF() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_VERSION_GEN() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_SQLITE() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_PERCENTILE() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_LINENOISE() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_METRICS() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_FTRACE() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HTTPD() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_SYSTEM_PROBES() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_ANDROID_PROBES() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HEAP_GRAPHS() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_GRAPHICS() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON_IMPORT() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_FUCHSIA() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_SYSCALLS() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LOCAL_SYMBOLIZER() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX())
-
-// clang-format on
-#endif  // GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
diff --git a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
deleted file mode 100644
index 49f80f5..0000000
--- a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Generated by ../../gn/write_buildflag_header.py
-
-// fix_include_guards: off
-#ifndef GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
-#define GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
-
-// clang-format off
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ANDROID_BUILD() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_CHROMIUM_BUILD() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_STANDALONE_BUILD() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_START_DAEMONS() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_IPC() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_WATCHDOG() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() || PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX())
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_COMPONENT_BUILD() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_ON() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_FORCE_DLOG_OFF() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_VERSION_GEN() (0)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_SQLITE() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_PERCENTILE() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_LINENOISE() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_METRICS() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_FTRACE() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HTTPD() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() || PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() || PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MACOSX())
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_SYSTEM_PROBES() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_ANDROID_PROBES() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_HEAP_GRAPHS() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_GRAPHICS() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON_IMPORT() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_FUCHSIA() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_SYSCALLS() (1)
-#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LOCAL_SYMBOLIZER() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX())
-
-// clang-format on
-#endif  // GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
diff --git a/include/perfetto/base/circular_queue.h b/include/perfetto/base/circular_queue.h
new file mode 100644
index 0000000..6e8d917
--- /dev/null
+++ b/include/perfetto/base/circular_queue.h
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2019 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 INCLUDE_PERFETTO_BASE_CIRCULAR_QUEUE_H_
+#define INCLUDE_PERFETTO_BASE_CIRCULAR_QUEUE_H_
+
+#include <stdint.h>
+#include <iterator>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/base/utils.h"
+
+namespace perfetto {
+namespace base {
+
+// CircularQueue is a push-back-only / pop-front-only queue with the following
+// characteristics:
+// - The storage is based on a flat circular buffer. Beginning and end wrap
+//   as necessary, to keep pushes and pops O(1) as long as capacity expansion is
+//   not required.
+// - Capacity is automatically expanded like in a std::vector. Expansion has a
+//   O(N) cost.
+// - It allows random access, allowing in-place std::sort.
+// - Iterators are not stable. Mutating the container invalidates all iterators.
+// - It doesn't bother with const-correctness.
+//
+// Implementation details:
+// Internally, |begin|, |end| and iterators use 64-bit monotonic indexes, which
+// are incremented as if the queue was backed by unlimited storage.
+// Even assuming that elements are inserted and removed every nanosecond, 64 bit
+// is enough for 584 years.
+// Wrapping happens only when addressing elements in the underlying circular
+// storage. This limits the complexity and avoiding dealing with modular
+// arithmetic all over the places.
+template <class T>
+class CircularQueue {
+ public:
+  class Iterator {
+   public:
+    using difference_type = ptrdiff_t;
+    using value_type = T;
+    using pointer = const T*;
+    using reference = const T&;
+    using iterator_category = std::random_access_iterator_tag;
+
+    Iterator(CircularQueue* queue, uint64_t pos, uint32_t generation)
+        : queue_(queue),
+          pos_(pos)
+#if PERFETTO_DCHECK_IS_ON()
+          ,
+          generation_(generation)
+#endif
+    {
+      ignore_result(generation);
+    }
+
+    T* operator->() {
+#if PERFETTO_DCHECK_IS_ON()
+      PERFETTO_DCHECK(generation_ == queue_->generation());
+#endif
+      return queue_->Get(pos_);
+    }
+
+    T& operator*() { return *(operator->()); }
+
+    const value_type& operator[](difference_type i) const {
+      return *(*this + i);
+    }
+
+    Iterator& operator++() {
+      Add(1);
+      return *this;
+    }
+
+    Iterator operator++(int) {
+      Iterator ret = *this;
+      Add(1);
+      return ret;
+    }
+
+    Iterator& operator--() {
+      Add(-1);
+      return *this;
+    }
+
+    Iterator operator--(int) {
+      Iterator ret = *this;
+      Add(-1);
+      return ret;
+    }
+
+    friend Iterator operator+(const Iterator& iter, difference_type offset) {
+      Iterator ret = iter;
+      ret.Add(offset);
+      return ret;
+    }
+
+    Iterator& operator+=(difference_type offset) {
+      Add(offset);
+      return *this;
+    }
+
+    friend Iterator operator-(const Iterator& iter, difference_type offset) {
+      Iterator ret = iter;
+      ret.Add(-offset);
+      return ret;
+    }
+
+    Iterator& operator-=(difference_type offset) {
+      Add(-offset);
+      return *this;
+    }
+
+    friend ptrdiff_t operator-(const Iterator& lhs, const Iterator& rhs) {
+      return static_cast<ptrdiff_t>(lhs.pos_) -
+             static_cast<ptrdiff_t>(rhs.pos_);
+    }
+
+    friend bool operator==(const Iterator& lhs, const Iterator& rhs) {
+      return lhs.pos_ == rhs.pos_;
+    }
+
+    friend bool operator!=(const Iterator& lhs, const Iterator& rhs) {
+      return lhs.pos_ != rhs.pos_;
+    }
+
+    friend bool operator<(const Iterator& lhs, const Iterator& rhs) {
+      return lhs.pos_ < rhs.pos_;
+    }
+
+    friend bool operator<=(const Iterator& lhs, const Iterator& rhs) {
+      return lhs.pos_ <= rhs.pos_;
+    }
+
+    friend bool operator>(const Iterator& lhs, const Iterator& rhs) {
+      return lhs.pos_ > rhs.pos_;
+    }
+
+    friend bool operator>=(const Iterator& lhs, const Iterator& rhs) {
+      return lhs.pos_ >= rhs.pos_;
+    }
+
+   private:
+    inline void Add(difference_type offset) {
+      pos_ = static_cast<uint64_t>(static_cast<difference_type>(pos_) + offset);
+      PERFETTO_DCHECK(pos_ <= queue_->end_);
+    }
+
+    CircularQueue* queue_;
+    uint64_t pos_;
+
+#if PERFETTO_DCHECK_IS_ON()
+    uint32_t generation_;
+#endif
+  };
+
+  CircularQueue(size_t initial_capacity = 1024) { Grow(initial_capacity); }
+
+  CircularQueue(CircularQueue&& other) noexcept {
+    // Copy all fields using the (private) default copy assignment operator.
+    *this = other;
+    increment_generation();
+    new (&other) CircularQueue();  // Reset the old queue so it's still usable.
+  }
+
+  CircularQueue& operator=(CircularQueue&& other) {
+    this->~CircularQueue();                      // Destroy the current state.
+    new (this) CircularQueue(std::move(other));  // Use the move ctor above.
+    return *this;
+  }
+
+  ~CircularQueue() {
+    if (!entries_) {
+      PERFETTO_DCHECK(empty());
+      return;
+    }
+    erase_front(size());  // Invoke destructors on all alive entries.
+    PERFETTO_DCHECK(empty());
+    free(entries_);
+  }
+
+  template <typename... Args>
+  void emplace_back(Args&&... args) {
+    increment_generation();
+    if (PERFETTO_UNLIKELY(size() >= capacity_))
+      Grow();
+    T* slot = Get(end_++);
+    new (slot) T(std::forward<Args>(args)...);
+  }
+
+  void erase_front(size_t n) {
+    increment_generation();
+    for (; n && (begin_ < end_); --n) {
+      Get(begin_)->~T();
+      begin_++;  // This needs to be its own statement, Get() checks begin_.
+    }
+  }
+
+  void pop_front() { erase_front(1); }
+
+  T& at(size_t idx) {
+    PERFETTO_DCHECK(idx < size());
+    return *Get(begin_ + idx);
+  }
+
+  Iterator begin() { return Iterator(this, begin_, generation()); }
+  Iterator end() { return Iterator(this, end_, generation()); }
+  T& front() { return *begin(); }
+  T& back() { return *(end() - 1); }
+
+  bool empty() const { return size() == 0; }
+
+  size_t size() const {
+    PERFETTO_DCHECK(end_ - begin_ <= capacity_);
+    return static_cast<size_t>(end_ - begin_);
+  }
+
+  size_t capacity() const { return capacity_; }
+
+#if PERFETTO_DCHECK_IS_ON()
+  uint32_t generation() const { return generation_; }
+  void increment_generation() { ++generation_; }
+#else
+  uint32_t generation() const { return 0; }
+  void increment_generation() {}
+#endif
+
+ private:
+  CircularQueue(const CircularQueue&) = delete;
+  CircularQueue& operator=(const CircularQueue&) = default;
+
+  void Grow(size_t new_capacity = 0) {
+    // Capacity must be always a power of two. This allows Get() to use a simple
+    // bitwise-AND for handling the wrapping instead of a full division.
+    new_capacity = new_capacity ? new_capacity : capacity_ * 2;
+    PERFETTO_CHECK((new_capacity & (new_capacity - 1)) == 0);  // Must be pow2.
+
+    // On 32-bit systems this might hit the 4GB wall and overflow. We can't do
+    // anything other than crash in this case.
+    PERFETTO_CHECK(new_capacity > capacity_);
+    size_t malloc_size = new_capacity * sizeof(T);
+    PERFETTO_CHECK(malloc_size > new_capacity);
+    auto* new_vec = static_cast<T*>(malloc(malloc_size));
+
+    // Move all elements in the expanded array.
+    size_t new_size = 0;
+    for (uint64_t i = begin_; i < end_; i++)
+      new (&new_vec[new_size++]) T(std::move(*Get(i)));  // Placement move ctor.
+
+    // Even if all the elements are std::move()-d and likely empty, we are still
+    // required to call the dtor for them.
+    for (uint64_t i = begin_; i < end_; i++)
+      Get(i)->~T();
+    free(entries_);  // It's fine to free(nullptr) (for the ctor call case).
+
+    begin_ = 0;
+    end_ = new_size;
+    capacity_ = new_capacity;
+    entries_ = new_vec;
+  }
+
+  inline T* Get(uint64_t pos) {
+    PERFETTO_DCHECK(pos >= begin_ && pos < end_);
+    PERFETTO_DCHECK((capacity_ & (capacity_ - 1)) == 0);  // Must be a pow2.
+    auto index = static_cast<size_t>(pos & (capacity_ - 1));
+    return &entries_[index];
+  }
+
+  // Underlying storage. It's raw malloc-ed rather than being a unique_ptr<T[]>
+  // to allow having uninitialized entries inside it.
+  T* entries_ = nullptr;
+  size_t capacity_ = 0;  // Number of allocated slots (NOT bytes) in |entries_|.
+
+  // The |begin_| and |end_| indexes are monotonic and never wrap. Modular arith
+  // is used only when dereferencing entries in the vector.
+  uint64_t begin_ = 0;
+  uint64_t end_ = 0;
+
+// Generation is used in debug builds only for checking iterator validity.
+#if PERFETTO_DCHECK_IS_ON()
+  uint32_t generation_ = 0;
+#endif
+};
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_CIRCULAR_QUEUE_H_
diff --git a/include/perfetto/base/compiler.h b/include/perfetto/base/compiler.h
deleted file mode 100644
index 0b2efbf..0000000
--- a/include/perfetto/base/compiler.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_BASE_COMPILER_H_
-#define INCLUDE_PERFETTO_BASE_COMPILER_H_
-
-#include <type_traits>
-
-#define PERFETTO_LIKELY(_x) __builtin_expect(!!(_x), 1)
-#define PERFETTO_UNLIKELY(_x) __builtin_expect(!!(_x), 0)
-
-#if defined(__GNUC__) || defined(__clang__)
-#define PERFETTO_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
-#else
-#define PERFETTO_WARN_UNUSED_RESULT
-#endif
-
-#if defined(__clang__)
-#define PERFETTO_ALWAYS_INLINE __attribute__((__always_inline__))
-#define PERFETTO_NO_INLINE __attribute__((__noinline__))
-#else
-// GCC is too pedantic and often fails with the error:
-// "always_inline function might not be inlinable"
-#define PERFETTO_ALWAYS_INLINE
-#define PERFETTO_NO_INLINE
-#endif
-
-// TODO(lalitm): is_trivially_constructible is currently not available
-// in some environments we build in. Reenable when that environment supports
-// this.
-#if defined(__GLIBCXX__)
-#define PERFETTO_IS_TRIVIALLY_CONSTRUCTIBLE(T) true
-#else
-#define PERFETTO_IS_TRIVIALLY_CONSTRUCTIBLE(T) \
-  std::is_trivially_constructible<T>::value
-#endif
-
-// TODO(lalitm): is_trivially_copyable is currently not available
-// in some environments we build in. Reenable when that environment supports
-// this.
-#if defined(__GLIBCXX__)
-#define PERFETTO_IS_TRIVIALLY_COPYABLE(T) true
-#else
-#define PERFETTO_IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
-#endif
-
-#if defined(__GNUC__) || defined(__clang__)
-#define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() __PRETTY_FUNCTION__
-#elif defined(_MSC_VER)
-#define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() __FUNCSIG__
-#else
-#define PERFETTO_DEBUG_FUNCTION_IDENTIFIER() \
-  static_assert(false, "Not implemented for this compiler")
-#endif
-
-namespace perfetto {
-namespace base {
-
-template <typename... T>
-inline void ignore_result(const T&...) {}
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_BASE_COMPILER_H_
diff --git a/include/perfetto/base/container_annotations.h b/include/perfetto/base/container_annotations.h
new file mode 100644
index 0000000..615a0b3
--- /dev/null
+++ b/include/perfetto/base/container_annotations.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_CONTAINER_ANNOTATIONS_H_
+#define INCLUDE_PERFETTO_BASE_CONTAINER_ANNOTATIONS_H_
+
+#include "perfetto/base/build_config.h"
+
+// Windows ASAN doesn't currently support these annotations.
+#if defined(ADDRESS_SANITIZER) && !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+    !defined(ADDRESS_SANITIZER_WITHOUT_INSTRUMENTATION)
+
+#define ANNOTATE_NEW_BUFFER(buffer, capacity, new_size)                      \
+  if (buffer) {                                                              \
+    __sanitizer_annotate_contiguous_container(buffer, (buffer) + (capacity), \
+                                              (buffer) + (capacity),         \
+                                              (buffer) + (new_size));        \
+  }
+#define ANNOTATE_DELETE_BUFFER(buffer, capacity, old_size)                   \
+  if (buffer) {                                                              \
+    __sanitizer_annotate_contiguous_container(buffer, (buffer) + (capacity), \
+                                              (buffer) + (old_size),         \
+                                              (buffer) + (capacity));        \
+  }
+#define ANNOTATE_CHANGE_SIZE(buffer, capacity, old_size, new_size)           \
+  if (buffer) {                                                              \
+    __sanitizer_annotate_contiguous_container(buffer, (buffer) + (capacity), \
+                                              (buffer) + (old_size),         \
+                                              (buffer) + (new_size));        \
+  }
+#define ANNOTATE_CHANGE_CAPACITY(buffer, old_capacity, buffer_size, \
+                                 new_capacity)                      \
+  ANNOTATE_DELETE_BUFFER(buffer, old_capacity, buffer_size);        \
+  ANNOTATE_NEW_BUFFER(buffer, new_capacity, buffer_size);
+// Annotations require buffers to begin on an 8-byte boundary.
+#else  // defined(ADDRESS_SANITIZER)
+#define ANNOTATE_NEW_BUFFER(buffer, capacity, new_size)
+#define ANNOTATE_DELETE_BUFFER(buffer, capacity, old_size)
+#define ANNOTATE_CHANGE_SIZE(buffer, capacity, old_size, new_size)
+#define ANNOTATE_CHANGE_CAPACITY(buffer, old_capacity, buffer_size, \
+                                 new_capacity)
+#endif  // defined(ADDRESS_SANITIZER)
+
+#endif  // INCLUDE_PERFETTO_BASE_CONTAINER_ANNOTATIONS_H_
diff --git a/include/perfetto/base/event.h b/include/perfetto/base/event.h
new file mode 100644
index 0000000..bca6c00
--- /dev/null
+++ b/include/perfetto/base/event.h
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_EVENT_H_
+#define INCLUDE_PERFETTO_BASE_EVENT_H_
+
+#include "perfetto/base/build_config.h"
+#include "perfetto/base/scoped_file.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#define PERFETTO_USE_EVENTFD() 1
+#else
+#define PERFETTO_USE_EVENTFD() 0
+#endif
+
+namespace perfetto {
+namespace base {
+
+// A waitable event that can be used with poll/select.
+// This is really a wrapper around eventfd_create with a pipe-based fallback
+// for other platforms where eventfd is not supported.
+class Event {
+ public:
+  Event();
+  ~Event();
+  Event(Event&&) noexcept = default;
+  Event& operator=(Event&&) = default;
+
+  // The non-blocking file descriptor that can be polled to wait for the event.
+  int fd() const { return fd_.get(); }
+
+  // Can be called from any thread.
+  void Notify();
+
+  // Can be called from any thread. If more Notify() are queued a Clear() call
+  // can clear all of them (up to 16 per call).
+  void Clear();
+
+ private:
+  // The eventfd, when eventfd is supported, otherwise this is the read end of
+  // the pipe for fallback mode.
+  ScopedFile fd_;
+
+#if !PERFETTO_USE_EVENTFD()
+  // The write end of the wakeup pipe.
+  ScopedFile write_fd_;
+#endif
+};
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_EVENT_H_
diff --git a/include/perfetto/base/export.h b/include/perfetto/base/export.h
index 6904ada..15497e0 100644
--- a/include/perfetto/base/export.h
+++ b/include/perfetto/base/export.h
@@ -19,7 +19,7 @@
 
 #include "perfetto/base/build_config.h"
 
-#if PERFETTO_BUILDFLAG(PERFETTO_COMPONENT_BUILD)
+#if defined(PERFETTO_SHARED_LIBRARY)
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 
@@ -39,10 +39,10 @@
 
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 
-#else  // !PERFETTO_BUILDFLAG(PERFETTO_COMPONENT_BUILD)
+#else  // defined(PERFETTO_SHARED_LIBRARY)
 
 #define PERFETTO_EXPORT
 
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_COMPONENT_BUILD)
+#endif  // defined(PERFETTO_SHARED_LIBRARY)
 
 #endif  // INCLUDE_PERFETTO_BASE_EXPORT_H_
diff --git a/include/perfetto/base/file_utils.h b/include/perfetto/base/file_utils.h
new file mode 100644
index 0000000..8a600b2
--- /dev/null
+++ b/include/perfetto/base/file_utils.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_FILE_UTILS_H_
+#define INCLUDE_PERFETTO_BASE_FILE_UTILS_H_
+
+#include <stddef.h>
+
+#include <string>
+
+#include "perfetto/base/utils.h"  // For ssize_t on Windows.
+
+namespace perfetto {
+namespace base {
+
+bool ReadFileDescriptor(int fd, std::string* out);
+bool ReadFileStream(FILE* f, std::string* out);
+bool ReadFile(const std::string& path, std::string* out);
+
+// Call write until all data is written or an error is detected.
+//
+// man 2 write:
+//   If a write() is interrupted by a signal handler before any bytes are
+//   written, then the call fails with the error EINTR; if it is
+//   interrupted after at least one byte has been written, the call
+//   succeeds, and returns the number of bytes written.
+ssize_t WriteAll(int fd, const void* buf, size_t count);
+
+bool FlushFile(int fd);
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_FILE_UTILS_H_
diff --git a/include/perfetto/base/gtest_prod_util.h b/include/perfetto/base/gtest_prod_util.h
new file mode 100644
index 0000000..09b5f82
--- /dev/null
+++ b/include/perfetto/base/gtest_prod_util.h
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_GTEST_PROD_UTIL_H_
+#define INCLUDE_PERFETTO_BASE_GTEST_PROD_UTIL_H_
+
+#include "gtest/gtest_prod.h"  // nogncheck
+
+#endif  // INCLUDE_PERFETTO_BASE_GTEST_PROD_UTIL_H_
diff --git a/include/perfetto/base/hash.h b/include/perfetto/base/hash.h
new file mode 100644
index 0000000..e64778e
--- /dev/null
+++ b/include/perfetto/base/hash.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 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 INCLUDE_PERFETTO_BASE_HASH_H_
+#define INCLUDE_PERFETTO_BASE_HASH_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <type_traits>
+
+namespace perfetto {
+namespace base {
+
+// A helper class which computes a 64-bit hash of the input data.
+// The algorithm used is FNV-1a as it is fast and easy to implement and has
+// relatively few collisions.
+// WARNING: This hash function should not be used for any cryptographic purpose.
+class Hash {
+ public:
+  // Creates an empty hash object
+  Hash() {}
+
+  // Hashes a numeric value.
+  template <typename T,
+            typename std::enable_if<std::is_arithmetic<T>::value>* = nullptr>
+  void Update(T data) {
+    Update(reinterpret_cast<const char*>(&data), sizeof(data));
+  }
+
+  // Hashes a byte array.
+  void Update(const char* data, size_t size) {
+    for (size_t i = 0; i < size; i++) {
+      result_ ^= static_cast<uint8_t>(data[i]);
+      result_ *= kFnv1a64Prime;
+    }
+  }
+
+  uint64_t digest() { return result_; }
+
+ private:
+  static constexpr uint64_t kFnv1a64OffsetBasis = 0xcbf29ce484222325;
+  static constexpr uint64_t kFnv1a64Prime = 0x100000001b3;
+
+  uint64_t result_ = kFnv1a64OffsetBasis;
+};
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_HASH_H_
diff --git a/include/perfetto/base/logging.h b/include/perfetto/base/logging.h
index 2dda900..131f589 100644
--- a/include/perfetto/base/logging.h
+++ b/include/perfetto/base/logging.h
@@ -22,25 +22,21 @@
 #include <stdlib.h>
 #include <string.h>  // For strerror.
 
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/compiler.h"
-
-// TODO(primiano): movee this to base/build_config.h, turn into
-// PERFETTO_BUILDFLAG(DCHECK_IS_ON) and update call sites to use that instead.
 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
 #define PERFETTO_DCHECK_IS_ON() 0
 #else
 #define PERFETTO_DCHECK_IS_ON() 1
 #endif
 
-#if PERFETTO_BUILDFLAG(PERFETTO_FORCE_DLOG_ON)
-#define PERFETTO_DLOG_IS_ON() 1
-#elif PERFETTO_BUILDFLAG(PERFETTO_FORCE_DLOG_OFF)
-#define PERFETTO_DLOG_IS_ON() 0
-#else
+#if !defined(PERFETTO_FORCE_DLOG)
 #define PERFETTO_DLOG_IS_ON() PERFETTO_DCHECK_IS_ON()
+#else
+#define PERFETTO_DLOG_IS_ON() PERFETTO_FORCE_DLOG
 #endif
 
+#include "perfetto/base/build_config.h"
+#include "perfetto/base/utils.h"
+
 #if defined(PERFETTO_ANDROID_ASYNC_SAFE_LOG)
 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
     !PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
diff --git a/include/perfetto/base/lookup_set.h b/include/perfetto/base/lookup_set.h
new file mode 100644
index 0000000..a730dbe
--- /dev/null
+++ b/include/perfetto/base/lookup_set.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_LOOKUP_SET_H_
+#define INCLUDE_PERFETTO_BASE_LOOKUP_SET_H_
+
+#include <set>
+
+namespace perfetto {
+namespace base {
+
+// Set that allows lookup from const member of the object.
+template <typename T, typename U, U T::*p>
+class LookupSet {
+ public:
+  T* Get(const U& key) {
+    // This will be nicer with C++14 transparent comparators.
+    // Then we will be able to look up by just the key using a sutiable
+    // comparator.
+    //
+    // For now we need to allow to construct a T from the key.
+    T node(key);
+    auto it = set_.find(node);
+    if (it == set_.end())
+      return nullptr;
+    return const_cast<T*>(&(*it));
+  }
+
+  template <typename... P>
+  T* Emplace(P&&... args) {
+    auto r = set_.emplace(std::forward<P>(args)...);
+    return const_cast<T*>(&(*r.first));
+  }
+
+  bool Remove(const T& child) { return set_.erase(child); }
+
+  static_assert(std::is_const<U>::value, "key must be const");
+
+ private:
+  class Comparator {
+   public:
+    bool operator()(const T& one, const T& other) const {
+      return (&one)->*p < (&other)->*p;
+    }
+  };
+
+  std::set<T, Comparator> set_;
+};
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_LOOKUP_SET_H_
diff --git a/include/perfetto/base/metatrace.h b/include/perfetto/base/metatrace.h
new file mode 100644
index 0000000..116a160
--- /dev/null
+++ b/include/perfetto/base/metatrace.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_METATRACE_H_
+#define INCLUDE_PERFETTO_BASE_METATRACE_H_
+
+#include <string.h>
+
+#include <string>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/base/utils.h"
+
+namespace perfetto {
+namespace base {
+
+class MetaTrace {
+ public:
+  static constexpr uint32_t kMainThreadCpu = 255;
+
+  MetaTrace(const char* evt_name, size_t cpu) : evt_name_(evt_name), cpu_(cpu) {
+    WriteEvent('B', evt_name, cpu);
+  }
+
+  MetaTrace(const std::string& str, size_t cpu)
+      : str_copy_(str), evt_name_(str_copy_.c_str()), cpu_(cpu) {
+    WriteEvent('B', evt_name_, cpu);
+  }
+
+  ~MetaTrace() { WriteEvent('E', evt_name_, cpu_); }
+
+ private:
+  MetaTrace(const MetaTrace&) = delete;
+  MetaTrace& operator=(const MetaTrace&) = delete;
+
+  void WriteEvent(char type, const char* evt_name, size_t cpu);
+
+  std::string str_copy_;
+  const char* const evt_name_;
+  const size_t cpu_;
+};
+
+#define PERFETTO_METATRACE_UID2(a, b) a##b
+#define PERFETTO_METATRACE_UID(x) PERFETTO_METATRACE_UID2(metatrace_, x)
+#if PERFETTO_DCHECK_IS_ON() && PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD)
+
+#define PERFETTO_METATRACE(...) \
+  ::perfetto::base::MetaTrace PERFETTO_METATRACE_UID(__COUNTER__)(__VA_ARGS__)
+#else
+#define PERFETTO_METATRACE(...) ::perfetto::base::ignore_result(__VA_ARGS__)
+#endif
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_METATRACE_H_
diff --git a/include/perfetto/base/no_destructor.h b/include/perfetto/base/no_destructor.h
new file mode 100644
index 0000000..8009fc5
--- /dev/null
+++ b/include/perfetto/base/no_destructor.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 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 INCLUDE_PERFETTO_BASE_NO_DESTRUCTOR_H_
+#define INCLUDE_PERFETTO_BASE_NO_DESTRUCTOR_H_
+
+#include <new>
+#include <utility>
+
+namespace perfetto {
+namespace base {
+
+// Wrapper that can hold an object of type T, without invoking the contained
+// object's destructor when being destroyed. Useful for creating statics while
+// avoiding static destructors.
+//
+// Stores the object inline, and therefore doesn't incur memory allocation and
+// pointer indirection overheads.
+//
+// Example of use:
+//
+//   const std::string& GetStr() {
+//     static base::NoDestructor<std::string> s("hello");
+//     return s.ref();
+//   }
+//
+template <typename T>
+class NoDestructor {
+ public:
+  // Forward arguments to T's constructor. Note that this doesn't cover
+  // construction from initializer lists.
+  template <typename... Args>
+  explicit NoDestructor(Args&&... args) {
+    new (storage_) T(std::forward<Args>(args)...);
+  }
+
+  NoDestructor(const NoDestructor&) = delete;
+  NoDestructor& operator=(const NoDestructor&) = delete;
+  NoDestructor(NoDestructor&&) = delete;
+  NoDestructor& operator=(NoDestructor&&) = delete;
+
+  ~NoDestructor() = default;
+
+  const T& ref() const { return *reinterpret_cast<const T*>(storage_); }
+  T& ref() { return *reinterpret_cast<T*>(storage_); }
+
+ private:
+  alignas(T) char storage_[sizeof(T)];
+};
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_NO_DESTRUCTOR_H_
diff --git a/include/perfetto/base/optional.h b/include/perfetto/base/optional.h
new file mode 100644
index 0000000..c46d6ca
--- /dev/null
+++ b/include/perfetto/base/optional.h
@@ -0,0 +1,902 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_OPTIONAL_H_
+#define INCLUDE_PERFETTO_BASE_OPTIONAL_H_
+
+#include <functional>
+#include <type_traits>
+#include <utility>
+
+#include "perfetto/base/logging.h"
+
+namespace perfetto {
+namespace base {
+
+// Specification:
+// http://en.cppreference.com/w/cpp/utility/optional/in_place_t
+struct in_place_t {};
+
+// Specification:
+// http://en.cppreference.com/w/cpp/utility/optional/nullopt_t
+struct nullopt_t {
+  constexpr explicit nullopt_t(int) {}
+};
+
+// Specification:
+// http://en.cppreference.com/w/cpp/utility/optional/in_place
+constexpr in_place_t in_place = {};
+
+// Specification:
+// http://en.cppreference.com/w/cpp/utility/optional/nullopt
+constexpr nullopt_t nullopt(0);
+
+// Forward declaration, which is refered by following helpers.
+template <typename T>
+class Optional;
+
+namespace internal {
+
+template <typename T, bool = std::is_trivially_destructible<T>::value>
+struct OptionalStorageBase {
+  // Initializing |empty_| here instead of using default member initializing
+  // to avoid errors in g++ 4.8.
+  constexpr OptionalStorageBase() : empty_('\0') {}
+
+  template <class... Args>
+  constexpr explicit OptionalStorageBase(in_place_t, Args&&... args)
+      : is_populated_(true), value_(std::forward<Args>(args)...) {}
+
+  // When T is not trivially destructible we must call its
+  // destructor before deallocating its memory.
+  // Note that this hides the (implicitly declared) move constructor, which
+  // would be used for constexpr move constructor in OptionalStorage<T>.
+  // It is needed iff T is trivially move constructible. However, the current
+  // is_trivially_{copy,move}_constructible implementation requires
+  // is_trivially_destructible (which looks a bug, cf:
+  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452 and
+  // http://cplusplus.github.io/LWG/lwg-active.html#2116), so it is not
+  // necessary for this case at the moment. Please see also the destructor
+  // comment in "is_trivially_destructible = true" specialization below.
+  ~OptionalStorageBase() {
+    if (is_populated_)
+      value_.~T();
+  }
+
+  template <class... Args>
+  void Init(Args&&... args) {
+    PERFETTO_DCHECK(!is_populated_);
+    ::new (&value_) T(std::forward<Args>(args)...);
+    is_populated_ = true;
+  }
+
+  bool is_populated_ = false;
+  union {
+    // |empty_| exists so that the union will always be initialized, even when
+    // it doesn't contain a value. Union members must be initialized for the
+    // constructor to be 'constexpr'.
+    char empty_;
+    T value_;
+  };
+};
+
+template <typename T>
+struct OptionalStorageBase<T, true /* trivially destructible */> {
+  // Initializing |empty_| here instead of using default member initializing
+  // to avoid errors in g++ 4.8.
+  constexpr OptionalStorageBase() : empty_('\0') {}
+
+  template <class... Args>
+  constexpr explicit OptionalStorageBase(in_place_t, Args&&... args)
+      : is_populated_(true), value_(std::forward<Args>(args)...) {}
+
+  // When T is trivially destructible (i.e. its destructor does nothing) there
+  // is no need to call it. Implicitly defined destructor is trivial, because
+  // both members (bool and union containing only variants which are trivially
+  // destructible) are trivially destructible.
+  // Explicitly-defaulted destructor is also trivial, but do not use it here,
+  // because it hides the implicit move constructor. It is needed to implement
+  // constexpr move constructor in OptionalStorage iff T is trivially move
+  // constructible. Note that, if T is trivially move constructible, the move
+  // constructor of OptionalStorageBase<T> is also implicitly defined and it is
+  // trivially move constructor. If T is not trivially move constructible,
+  // "not declaring move constructor without destructor declaration" here means
+  // "delete move constructor", which works because any move constructor of
+  // OptionalStorage will not refer to it in that case.
+
+  template <class... Args>
+  void Init(Args&&... args) {
+    PERFETTO_DCHECK(!is_populated_);
+    ::new (&value_) T(std::forward<Args>(args)...);
+    is_populated_ = true;
+  }
+
+  bool is_populated_ = false;
+  union {
+    // |empty_| exists so that the union will always be initialized, even when
+    // it doesn't contain a value. Union members must be initialized for the
+    // constructor to be 'constexpr'.
+    char empty_;
+    T value_;
+  };
+};
+
+// Implement conditional constexpr copy and move constructors. These are
+// constexpr if is_trivially_{copy,move}_constructible<T>::value is true
+// respectively. If each is true, the corresponding constructor is defined as
+// "= default;", which generates a constexpr constructor (In this case,
+// the condition of constexpr-ness is satisfied because the base class also has
+// compiler generated constexpr {copy,move} constructors). Note that
+// placement-new is prohibited in constexpr.
+template <typename T, bool = std::is_trivially_copy_constructible<T>::value>
+struct OptionalStorage : OptionalStorageBase<T> {
+  // This is no trivially {copy,move} constructible case. Other cases are
+  // defined below as specializations.
+
+  // Accessing the members of template base class requires explicit
+  // declaration.
+  using OptionalStorageBase<T>::is_populated_;
+  using OptionalStorageBase<T>::value_;
+  using OptionalStorageBase<T>::Init;
+
+  // Inherit constructors (specifically, the in_place constructor).
+  using OptionalStorageBase<T>::OptionalStorageBase;
+
+  // User defined constructor deletes the default constructor.
+  // Define it explicitly.
+  OptionalStorage() = default;
+
+  OptionalStorage(const OptionalStorage& other) : OptionalStorageBase<T>() {
+    if (other.is_populated_)
+      Init(other.value_);
+  }
+
+  OptionalStorage(OptionalStorage&& other) noexcept(
+      std::is_nothrow_move_constructible<T>::value) {
+    if (other.is_populated_)
+      Init(std::move(other.value_));
+  }
+};
+
+template <typename T>
+struct OptionalStorage<T, true /* trivially copy constructible */>
+    : OptionalStorageBase<T> {
+  using OptionalStorageBase<T>::is_populated_;
+  using OptionalStorageBase<T>::value_;
+  using OptionalStorageBase<T>::Init;
+  using OptionalStorageBase<T>::OptionalStorageBase;
+
+  OptionalStorage() = default;
+  OptionalStorage(const OptionalStorage& other) = default;
+
+  OptionalStorage(OptionalStorage&& other) noexcept(
+      std::is_nothrow_move_constructible<T>::value) {
+    if (other.is_populated_)
+      Init(std::move(other.value_));
+  }
+};
+
+// Base class to support conditionally usable copy-/move- constructors
+// and assign operators.
+template <typename T>
+class OptionalBase {
+  // This class provides implementation rather than public API, so everything
+  // should be hidden. Often we use composition, but we cannot in this case
+  // because of C++ language restriction.
+ protected:
+  constexpr OptionalBase() = default;
+  constexpr OptionalBase(const OptionalBase& other) = default;
+  constexpr OptionalBase(OptionalBase&& other) = default;
+
+  template <class... Args>
+  constexpr explicit OptionalBase(in_place_t, Args&&... args)
+      : storage_(in_place, std::forward<Args>(args)...) {}
+
+  // Implementation of converting constructors.
+  template <typename U>
+  explicit OptionalBase(const OptionalBase<U>& other) {
+    if (other.storage_.is_populated_)
+      storage_.Init(other.storage_.value_);
+  }
+
+  template <typename U>
+  explicit OptionalBase(OptionalBase<U>&& other) {
+    if (other.storage_.is_populated_)
+      storage_.Init(std::move(other.storage_.value_));
+  }
+
+  ~OptionalBase() = default;
+
+  OptionalBase& operator=(const OptionalBase& other) {
+    CopyAssign(other);
+    return *this;
+  }
+
+  OptionalBase& operator=(OptionalBase&& other) noexcept(
+      std::is_nothrow_move_assignable<T>::value&&
+          std::is_nothrow_move_constructible<T>::value) {
+    MoveAssign(std::move(other));
+    return *this;
+  }
+
+  template <typename U>
+  void CopyAssign(const OptionalBase<U>& other) {
+    if (other.storage_.is_populated_)
+      InitOrAssign(other.storage_.value_);
+    else
+      FreeIfNeeded();
+  }
+
+  template <typename U>
+  void MoveAssign(OptionalBase<U>&& other) {
+    if (other.storage_.is_populated_)
+      InitOrAssign(std::move(other.storage_.value_));
+    else
+      FreeIfNeeded();
+  }
+
+  template <typename U>
+  void InitOrAssign(U&& value) {
+    if (storage_.is_populated_)
+      storage_.value_ = std::forward<U>(value);
+    else
+      storage_.Init(std::forward<U>(value));
+  }
+
+  void FreeIfNeeded() {
+    if (!storage_.is_populated_)
+      return;
+    storage_.value_.~T();
+    storage_.is_populated_ = false;
+  }
+
+  // For implementing conversion, allow access to other typed OptionalBase
+  // class.
+  template <typename U>
+  friend class OptionalBase;
+
+  OptionalStorage<T> storage_;
+};
+
+// The following {Copy,Move}{Constructible,Assignable} structs are helpers to
+// implement constructor/assign-operator overloading. Specifically, if T is
+// is not movable but copyable, Optional<T>'s move constructor should not
+// participate in overload resolution. This inheritance trick implements that.
+template <bool is_copy_constructible>
+struct CopyConstructible {};
+
+template <>
+struct CopyConstructible<false> {
+  constexpr CopyConstructible() = default;
+  constexpr CopyConstructible(const CopyConstructible&) = delete;
+  constexpr CopyConstructible(CopyConstructible&&) = default;
+  CopyConstructible& operator=(const CopyConstructible&) = default;
+  CopyConstructible& operator=(CopyConstructible&&) = default;
+};
+
+template <bool is_move_constructible>
+struct MoveConstructible {};
+
+template <>
+struct MoveConstructible<false> {
+  constexpr MoveConstructible() = default;
+  constexpr MoveConstructible(const MoveConstructible&) = default;
+  constexpr MoveConstructible(MoveConstructible&&) = delete;
+  MoveConstructible& operator=(const MoveConstructible&) = default;
+  MoveConstructible& operator=(MoveConstructible&&) = default;
+};
+
+template <bool is_copy_assignable>
+struct CopyAssignable {};
+
+template <>
+struct CopyAssignable<false> {
+  constexpr CopyAssignable() = default;
+  constexpr CopyAssignable(const CopyAssignable&) = default;
+  constexpr CopyAssignable(CopyAssignable&&) = default;
+  CopyAssignable& operator=(const CopyAssignable&) = delete;
+  CopyAssignable& operator=(CopyAssignable&&) = default;
+};
+
+template <bool is_move_assignable>
+struct MoveAssignable {};
+
+template <>
+struct MoveAssignable<false> {
+  constexpr MoveAssignable() = default;
+  constexpr MoveAssignable(const MoveAssignable&) = default;
+  constexpr MoveAssignable(MoveAssignable&&) = default;
+  MoveAssignable& operator=(const MoveAssignable&) = default;
+  MoveAssignable& operator=(MoveAssignable&&) = delete;
+};
+
+// Helper to conditionally enable converting constructors and assign operators.
+template <typename T, typename U>
+struct IsConvertibleFromOptional
+    : std::integral_constant<
+          bool,
+          std::is_constructible<T, Optional<U>&>::value ||
+              std::is_constructible<T, const Optional<U>&>::value ||
+              std::is_constructible<T, Optional<U>&&>::value ||
+              std::is_constructible<T, const Optional<U>&&>::value ||
+              std::is_convertible<Optional<U>&, T>::value ||
+              std::is_convertible<const Optional<U>&, T>::value ||
+              std::is_convertible<Optional<U>&&, T>::value ||
+              std::is_convertible<const Optional<U>&&, T>::value> {};
+
+template <typename T, typename U>
+struct IsAssignableFromOptional
+    : std::integral_constant<
+          bool,
+          IsConvertibleFromOptional<T, U>::value ||
+              std::is_assignable<T&, Optional<U>&>::value ||
+              std::is_assignable<T&, const Optional<U>&>::value ||
+              std::is_assignable<T&, Optional<U>&&>::value ||
+              std::is_assignable<T&, const Optional<U>&&>::value> {};
+
+// Forward compatibility for C++17.
+// Introduce one more deeper nested namespace to avoid leaking using std::swap.
+namespace swappable_impl {
+using std::swap;
+
+struct IsSwappableImpl {
+  // Tests if swap can be called. Check<T&>(0) returns true_type iff swap is
+  // available for T. Otherwise, Check's overload resolution falls back to
+  // Check(...) declared below thanks to SFINAE, so returns false_type.
+  template <typename T>
+  static auto Check(int)
+      -> decltype(swap(std::declval<T>(), std::declval<T>()), std::true_type());
+
+  template <typename T>
+  static std::false_type Check(...);
+};
+}  // namespace swappable_impl
+
+template <typename T>
+struct IsSwappable : decltype(swappable_impl::IsSwappableImpl::Check<T&>(0)) {};
+
+// Forward compatibility for C++20.
+template <typename T>
+using RemoveCvRefT =
+    typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+
+}  // namespace internal
+
+// On Windows, by default, empty-base class optimization does not work,
+// which means even if the base class is empty struct, it still consumes one
+// byte for its body. __declspec(empty_bases) enables the optimization.
+// cf)
+// https://blogs.msdn.microsoft.com/vcblog/2016/03/30/optimizing-the-layout-of-empty-base-classes-in-vs2015-update-2-3/
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+    !PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC)
+#define OPTIONAL_DECLSPEC_EMPTY_BASES __declspec(empty_bases)
+#else
+#define OPTIONAL_DECLSPEC_EMPTY_BASES
+#endif
+
+// base::Optional is a Chromium version of the C++17 optional class:
+// std::optional documentation:
+// http://en.cppreference.com/w/cpp/utility/optional
+// Chromium documentation:
+// https://chromium.googlesource.com/chromium/src/+/master/docs/optional.md
+//
+// These are the differences between the specification and the implementation:
+// - Constructors do not use 'constexpr' as it is a C++14 extension.
+// - 'constexpr' might be missing in some places for reasons specified locally.
+// - No exceptions are thrown, because they are banned from Chromium.
+//   Marked noexcept for only move constructor and move assign operators.
+// - All the non-members are in the 'base' namespace instead of 'std'.
+//
+// Note that T cannot have a constructor T(Optional<T>) etc. Optional<T>
+// PERFETTO_CHECKs T's constructor (specifically via IsConvertibleFromOptional),
+// and in the PERFETTO_CHECK whether T can be constructible from Optional<T>,
+// which is recursive so it does not work. As of Feb 2018, std::optional C++17
+// implementation in both clang and gcc has same limitation. MSVC SFINAE looks
+// to have different behavior, but anyway it reports an error, too.
+//
+// This file is a modified version of optional.h from Chromium at revision
+// 5e71bd454e60511c1293c0c686544aaa76094424. The changes remove C++14/C++17
+// specific code and replace with C++11 counterparts.
+template <typename T>
+class OPTIONAL_DECLSPEC_EMPTY_BASES Optional
+    : public internal::OptionalBase<T>,
+      public internal::CopyConstructible<std::is_copy_constructible<T>::value>,
+      public internal::MoveConstructible<std::is_move_constructible<T>::value>,
+      public internal::CopyAssignable<std::is_copy_constructible<T>::value &&
+                                      std::is_copy_assignable<T>::value>,
+      public internal::MoveAssignable<std::is_move_constructible<T>::value &&
+                                      std::is_move_assignable<T>::value> {
+ public:
+#undef OPTIONAL_DECLSPEC_EMPTY_BASES
+  using value_type = T;
+
+  // Defer default/copy/move constructor implementation to OptionalBase.
+  constexpr Optional() = default;
+  constexpr Optional(const Optional& other) = default;
+  constexpr Optional(Optional&& other) noexcept(
+      std::is_nothrow_move_constructible<T>::value) = default;
+
+  constexpr Optional(nullopt_t) {}  // NOLINT(runtime/explicit)
+
+  // Converting copy constructor. "explicit" only if
+  // std::is_convertible<const U&, T>::value is false. It is implemented by
+  // declaring two almost same constructors, but that condition in enable_if_t
+  // is different, so that either one is chosen, thanks to SFINAE.
+  template <typename U,
+            typename std::enable_if<
+                std::is_constructible<T, const U&>::value &&
+                    !internal::IsConvertibleFromOptional<T, U>::value &&
+                    std::is_convertible<const U&, T>::value,
+                bool>::type = false>
+  Optional(const Optional<U>& other) : internal::OptionalBase<T>(other) {}
+
+  template <typename U,
+            typename std::enable_if<
+                std::is_constructible<T, const U&>::value &&
+                    !internal::IsConvertibleFromOptional<T, U>::value &&
+                    !std::is_convertible<const U&, T>::value,
+                bool>::type = false>
+  explicit Optional(const Optional<U>& other)
+      : internal::OptionalBase<T>(other) {}
+
+  // Converting move constructor. Similar to converting copy constructor,
+  // declaring two (explicit and non-explicit) constructors.
+  template <typename U,
+            typename std::enable_if<
+                std::is_constructible<T, U&&>::value &&
+                    !internal::IsConvertibleFromOptional<T, U>::value &&
+                    std::is_convertible<U&&, T>::value,
+                bool>::type = false>
+  Optional(Optional<U>&& other) : internal::OptionalBase<T>(std::move(other)) {}
+
+  template <typename U,
+            typename std::enable_if<
+                std::is_constructible<T, U&&>::value &&
+                    !internal::IsConvertibleFromOptional<T, U>::value &&
+                    !std::is_convertible<U&&, T>::value,
+                bool>::type = false>
+  explicit Optional(Optional<U>&& other)
+      : internal::OptionalBase<T>(std::move(other)) {}
+
+  template <class... Args>
+  constexpr explicit Optional(in_place_t, Args&&... args)
+      : internal::OptionalBase<T>(in_place, std::forward<Args>(args)...) {}
+
+  template <class U,
+            class... Args,
+            class = typename std::enable_if<
+                std::is_constructible<value_type,
+                                      std::initializer_list<U>&,
+                                      Args...>::value>::type>
+  constexpr explicit Optional(in_place_t,
+                              std::initializer_list<U> il,
+                              Args&&... args)
+      : internal::OptionalBase<T>(in_place, il, std::forward<Args>(args)...) {}
+
+  // Forward value constructor. Similar to converting constructors,
+  // conditionally explicit.
+  template <
+      typename U = value_type,
+      typename std::enable_if<
+          std::is_constructible<T, U&&>::value &&
+              !std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value &&
+              !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
+              std::is_convertible<U&&, T>::value,
+          bool>::type = false>
+  constexpr Optional(U&& value)
+      : internal::OptionalBase<T>(in_place, std::forward<U>(value)) {}
+
+  template <
+      typename U = value_type,
+      typename std::enable_if<
+          std::is_constructible<T, U&&>::value &&
+              !std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value &&
+              !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
+              !std::is_convertible<U&&, T>::value,
+          bool>::type = false>
+  constexpr explicit Optional(U&& value)
+      : internal::OptionalBase<T>(in_place, std::forward<U>(value)) {}
+
+  ~Optional() = default;
+
+  // Defer copy-/move- assign operator implementation to OptionalBase.
+  Optional& operator=(const Optional& other) = default;
+  Optional& operator=(Optional&& other) noexcept(
+      std::is_nothrow_move_assignable<T>::value&&
+          std::is_nothrow_move_constructible<T>::value) = default;
+
+  Optional& operator=(nullopt_t) {
+    FreeIfNeeded();
+    return *this;
+  }
+
+  // Perfect-forwarded assignment.
+  template <typename U>
+  typename std::enable_if<
+      !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
+          std::is_constructible<T, U>::value &&
+          std::is_assignable<T&, U>::value &&
+          (!std::is_scalar<T>::value ||
+           !std::is_same<typename std::decay<U>::type, T>::value),
+      Optional&>::type
+  operator=(U&& value) {
+    InitOrAssign(std::forward<U>(value));
+    return *this;
+  }
+
+  // Copy assign the state of other.
+  template <typename U>
+  typename std::enable_if<!internal::IsAssignableFromOptional<T, U>::value &&
+                              std::is_constructible<T, const U&>::value &&
+                              std::is_assignable<T&, const U&>::value,
+                          Optional&>::type
+  operator=(const Optional<U>& other) {
+    CopyAssign(other);
+    return *this;
+  }
+
+  // Move assign the state of other.
+  template <typename U>
+  typename std::enable_if<!internal::IsAssignableFromOptional<T, U>::value &&
+                              std::is_constructible<T, U>::value &&
+                              std::is_assignable<T&, U>::value,
+                          Optional&>::type
+  operator=(Optional<U>&& other) {
+    MoveAssign(std::move(other));
+    return *this;
+  }
+
+  const T* operator->() const {
+    PERFETTO_DCHECK(storage_.is_populated_);
+    return &storage_.value_;
+  }
+
+  T* operator->() {
+    PERFETTO_DCHECK(storage_.is_populated_);
+    return &storage_.value_;
+  }
+
+  const T& operator*() const & {
+    PERFETTO_DCHECK(storage_.is_populated_);
+    return storage_.value_;
+  }
+
+  T& operator*() & {
+    PERFETTO_DCHECK(storage_.is_populated_);
+    return storage_.value_;
+  }
+
+  const T&& operator*() const && {
+    PERFETTO_DCHECK(storage_.is_populated_);
+    return std::move(storage_.value_);
+  }
+
+  T&& operator*() && {
+    PERFETTO_DCHECK(storage_.is_populated_);
+    return std::move(storage_.value_);
+  }
+
+  constexpr explicit operator bool() const { return storage_.is_populated_; }
+
+  constexpr bool has_value() const { return storage_.is_populated_; }
+
+  T& value() & {
+    PERFETTO_CHECK(storage_.is_populated_);
+    return storage_.value_;
+  }
+
+  const T& value() const & {
+    PERFETTO_CHECK(storage_.is_populated_);
+    return storage_.value_;
+  }
+
+  T&& value() && {
+    PERFETTO_CHECK(storage_.is_populated_);
+    return std::move(storage_.value_);
+  }
+
+  const T&& value() const && {
+    PERFETTO_CHECK(storage_.is_populated_);
+    return std::move(storage_.value_);
+  }
+
+  template <class U>
+  constexpr T value_or(U&& default_value) const & {
+    static_assert(std::is_convertible<U, T>::value,
+                  "U must be convertible to T");
+    return storage_.is_populated_
+               ? storage_.value_
+               : static_cast<T>(std::forward<U>(default_value));
+  }
+
+  template <class U>
+  T value_or(U&& default_value) && {
+    static_assert(std::is_convertible<U, T>::value,
+                  "U must be convertible to T");
+    return storage_.is_populated_
+               ? std::move(storage_.value_)
+               : static_cast<T>(std::forward<U>(default_value));
+  }
+
+  void swap(Optional& other) {
+    if (!storage_.is_populated_ && !other.storage_.is_populated_)
+      return;
+
+    if (storage_.is_populated_ != other.storage_.is_populated_) {
+      if (storage_.is_populated_) {
+        other.storage_.Init(std::move(storage_.value_));
+        FreeIfNeeded();
+      } else {
+        storage_.Init(std::move(other.storage_.value_));
+        other.FreeIfNeeded();
+      }
+      return;
+    }
+
+    PERFETTO_DCHECK(storage_.is_populated_ && other.storage_.is_populated_);
+    using std::swap;
+    swap(**this, *other);
+  }
+
+  void reset() { FreeIfNeeded(); }
+
+  template <class... Args>
+  T& emplace(Args&&... args) {
+    FreeIfNeeded();
+    storage_.Init(std::forward<Args>(args)...);
+    return storage_.value_;
+  }
+
+  template <class U, class... Args>
+  typename std::enable_if<
+      std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value,
+      T&>::type
+  emplace(std::initializer_list<U> il, Args&&... args) {
+    FreeIfNeeded();
+    storage_.Init(il, std::forward<Args>(args)...);
+    return storage_.value_;
+  }
+
+ private:
+  // Accessing template base class's protected member needs explicit
+  // declaration to do so.
+  using internal::OptionalBase<T>::CopyAssign;
+  using internal::OptionalBase<T>::FreeIfNeeded;
+  using internal::OptionalBase<T>::InitOrAssign;
+  using internal::OptionalBase<T>::MoveAssign;
+  using internal::OptionalBase<T>::storage_;
+};
+
+// Here after defines comparation operators. The definition follows
+// http://en.cppreference.com/w/cpp/utility/optional/operator_cmp
+// while bool() casting is replaced by has_value() to meet the chromium
+// style guide.
+template <class T, class U>
+bool operator==(const Optional<T>& lhs, const Optional<U>& rhs) {
+  if (lhs.has_value() != rhs.has_value())
+    return false;
+  if (!lhs.has_value())
+    return true;
+  return *lhs == *rhs;
+}
+
+template <class T, class U>
+bool operator!=(const Optional<T>& lhs, const Optional<U>& rhs) {
+  if (lhs.has_value() != rhs.has_value())
+    return true;
+  if (!lhs.has_value())
+    return false;
+  return *lhs != *rhs;
+}
+
+template <class T, class U>
+bool operator<(const Optional<T>& lhs, const Optional<U>& rhs) {
+  if (!rhs.has_value())
+    return false;
+  if (!lhs.has_value())
+    return true;
+  return *lhs < *rhs;
+}
+
+template <class T, class U>
+bool operator<=(const Optional<T>& lhs, const Optional<U>& rhs) {
+  if (!lhs.has_value())
+    return true;
+  if (!rhs.has_value())
+    return false;
+  return *lhs <= *rhs;
+}
+
+template <class T, class U>
+bool operator>(const Optional<T>& lhs, const Optional<U>& rhs) {
+  if (!lhs.has_value())
+    return false;
+  if (!rhs.has_value())
+    return true;
+  return *lhs > *rhs;
+}
+
+template <class T, class U>
+bool operator>=(const Optional<T>& lhs, const Optional<U>& rhs) {
+  if (!rhs.has_value())
+    return true;
+  if (!lhs.has_value())
+    return false;
+  return *lhs >= *rhs;
+}
+
+template <class T>
+constexpr bool operator==(const Optional<T>& opt, nullopt_t) {
+  return !opt;
+}
+
+template <class T>
+constexpr bool operator==(nullopt_t, const Optional<T>& opt) {
+  return !opt;
+}
+
+template <class T>
+constexpr bool operator!=(const Optional<T>& opt, nullopt_t) {
+  return opt.has_value();
+}
+
+template <class T>
+constexpr bool operator!=(nullopt_t, const Optional<T>& opt) {
+  return opt.has_value();
+}
+
+template <class T>
+constexpr bool operator<(const Optional<T>&, nullopt_t) {
+  return false;
+}
+
+template <class T>
+constexpr bool operator<(nullopt_t, const Optional<T>& opt) {
+  return opt.has_value();
+}
+
+template <class T>
+constexpr bool operator<=(const Optional<T>& opt, nullopt_t) {
+  return !opt;
+}
+
+template <class T>
+constexpr bool operator<=(nullopt_t, const Optional<T>&) {
+  return true;
+}
+
+template <class T>
+constexpr bool operator>(const Optional<T>& opt, nullopt_t) {
+  return opt.has_value();
+}
+
+template <class T>
+constexpr bool operator>(nullopt_t, const Optional<T>&) {
+  return false;
+}
+
+template <class T>
+constexpr bool operator>=(const Optional<T>&, nullopt_t) {
+  return true;
+}
+
+template <class T>
+constexpr bool operator>=(nullopt_t, const Optional<T>& opt) {
+  return !opt;
+}
+
+template <class T, class U>
+constexpr bool operator==(const Optional<T>& opt, const U& value) {
+  return opt.has_value() ? *opt == value : false;
+}
+
+template <class T, class U>
+constexpr bool operator==(const U& value, const Optional<T>& opt) {
+  return opt.has_value() ? value == *opt : false;
+}
+
+template <class T, class U>
+constexpr bool operator!=(const Optional<T>& opt, const U& value) {
+  return opt.has_value() ? *opt != value : true;
+}
+
+template <class T, class U>
+constexpr bool operator!=(const U& value, const Optional<T>& opt) {
+  return opt.has_value() ? value != *opt : true;
+}
+
+template <class T, class U>
+constexpr bool operator<(const Optional<T>& opt, const U& value) {
+  return opt.has_value() ? *opt < value : true;
+}
+
+template <class T, class U>
+constexpr bool operator<(const U& value, const Optional<T>& opt) {
+  return opt.has_value() ? value < *opt : false;
+}
+
+template <class T, class U>
+constexpr bool operator<=(const Optional<T>& opt, const U& value) {
+  return opt.has_value() ? *opt <= value : true;
+}
+
+template <class T, class U>
+constexpr bool operator<=(const U& value, const Optional<T>& opt) {
+  return opt.has_value() ? value <= *opt : false;
+}
+
+template <class T, class U>
+constexpr bool operator>(const Optional<T>& opt, const U& value) {
+  return opt.has_value() ? *opt > value : false;
+}
+
+template <class T, class U>
+constexpr bool operator>(const U& value, const Optional<T>& opt) {
+  return opt.has_value() ? value > *opt : true;
+}
+
+template <class T, class U>
+constexpr bool operator>=(const Optional<T>& opt, const U& value) {
+  return opt.has_value() ? *opt >= value : false;
+}
+
+template <class T, class U>
+constexpr bool operator>=(const U& value, const Optional<T>& opt) {
+  return opt.has_value() ? value >= *opt : true;
+}
+
+template <class T>
+constexpr Optional<typename std::decay<T>::type> make_optional(T&& value) {
+  return Optional<typename std::decay<T>::type>(std::forward<T>(value));
+}
+
+template <class T, class... Args>
+constexpr Optional<T> make_optional(Args&&... args) {
+  return Optional<T>(in_place, std::forward<Args>(args)...);
+}
+
+template <class T, class U, class... Args>
+constexpr Optional<T> make_optional(std::initializer_list<U> il,
+                                    Args&&... args) {
+  return Optional<T>(in_place, il, std::forward<Args>(args)...);
+}
+
+// Partial specialization for a function template is not allowed. Also, it is
+// not allowed to add overload function to std namespace, while it is allowed
+// to specialize the template in std. Thus, swap() (kind of) overloading is
+// defined in base namespace, instead.
+template <class T>
+typename std::enable_if<std::is_move_constructible<T>::value &&
+                        internal::IsSwappable<T>::value>::type
+swap(Optional<T>& lhs, Optional<T>& rhs) {
+  lhs.swap(rhs);
+}
+
+}  // namespace base
+}  // namespace perfetto
+
+namespace std {
+
+template <class T>
+struct hash<perfetto::base::Optional<T>> {
+  size_t operator()(const perfetto::base::Optional<T>& opt) const {
+    return opt == perfetto::base::nullopt ? 0 : std::hash<T>()(*opt);
+  }
+};
+
+}  // namespace std
+
+#endif  // INCLUDE_PERFETTO_BASE_OPTIONAL_H_
diff --git a/include/perfetto/base/paged_memory.h b/include/perfetto/base/paged_memory.h
new file mode 100644
index 0000000..f994ea5
--- /dev/null
+++ b/include/perfetto/base/paged_memory.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_BASE_PAGED_MEMORY_H_
+#define INCLUDE_PERFETTO_BASE_PAGED_MEMORY_H_
+
+#include <memory>
+
+#include "perfetto/base/build_config.h"
+#include "perfetto/base/container_annotations.h"
+
+// We need to track the committed size on windows and when ASAN is enabled.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) || defined(ADDRESS_SANITIZER)
+#define TRACK_COMMITTED_SIZE() 1
+#else
+#define TRACK_COMMITTED_SIZE() 0
+#endif
+
+namespace perfetto {
+namespace base {
+
+class PagedMemory {
+ public:
+  // Initializes an invalid PagedMemory pointing to nullptr.
+  PagedMemory();
+
+  ~PagedMemory();
+
+  PagedMemory(PagedMemory&& other) noexcept;
+  PagedMemory& operator=(PagedMemory&& other);
+
+  enum AllocationFlags {
+    // By default, Allocate() crashes if the underlying mmap fails (e.g., if out
+    // of virtual address space). When this flag is provided, an invalid
+    // PagedMemory pointing to nullptr is returned in this case instead.
+    kMayFail = 1 << 0,
+
+    // By default, Allocate() commits the allocated memory immediately. When
+    // this flag is provided, the memory virtual address space may only be
+    // reserved and the user should call EnsureCommitted() before writing to
+    // memory addresses.
+    kDontCommit = 1 << 1,
+  };
+
+  // Allocates |size| bytes using mmap(MAP_ANONYMOUS). The returned memory is
+  // guaranteed to be page-aligned and guaranteed to be zeroed. |size| must be a
+  // multiple of 4KB (a page size). For |flags|, see the AllocationFlags enum
+  // above.
+  static PagedMemory Allocate(size_t size, int flags = 0);
+
+  // Hint to the OS that the memory range is not needed and can be discarded.
+  // The memory remains accessible and its contents may be retained, or they
+  // may be zeroed. This function may be a NOP on some platforms. Returns true
+  // if implemented.
+  bool AdviseDontNeed(void* p, size_t size);
+
+  // Ensures that at least the first |committed_size| bytes of the allocated
+  // memory region are committed. The implementation may commit memory in larger
+  // chunks above |committed_size|. Crashes if the memory couldn't be committed.
+#if TRACK_COMMITTED_SIZE()
+  void EnsureCommitted(size_t committed_size);
+#else  // TRACK_COMMITTED_SIZE()
+  void EnsureCommitted(size_t /*committed_size*/) {}
+#endif  // TRACK_COMMITTED_SIZE()
+
+  inline void* Get() const noexcept { return p_; }
+  inline bool IsValid() const noexcept { return !!p_; }
+  inline size_t size() const noexcept { return size_; }
+
+ private:
+  PagedMemory(char* p, size_t size);
+
+  PagedMemory(const PagedMemory&) = delete;
+  // Defaulted for implementation of move constructor + assignment.
+  PagedMemory& operator=(const PagedMemory&) = default;
+
+  char* p_ = nullptr;
+  size_t size_ = 0;
+
+#if TRACK_COMMITTED_SIZE()
+  size_t committed_size_ = 0u;
+#endif  // TRACK_COMMITTED_SIZE()
+};
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_PAGED_MEMORY_H_
diff --git a/include/perfetto/base/pipe.h b/include/perfetto/base/pipe.h
new file mode 100644
index 0000000..a1fde3c
--- /dev/null
+++ b/include/perfetto/base/pipe.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_PIPE_H_
+#define INCLUDE_PERFETTO_BASE_PIPE_H_
+
+#include "perfetto/base/scoped_file.h"
+
+namespace perfetto {
+namespace base {
+
+class Pipe {
+ public:
+  enum Flags {
+    kBothBlock = 0,
+    kBothNonBlock,
+    kRdNonBlock,
+    kWrNonBlock,
+  };
+
+  static Pipe Create(Flags = kBothBlock);
+
+  Pipe();
+  Pipe(Pipe&&) noexcept;
+  Pipe& operator=(Pipe&&);
+
+  ScopedFile rd;
+  ScopedFile wr;
+};
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_PIPE_H_
diff --git a/include/perfetto/base/scoped_file.h b/include/perfetto/base/scoped_file.h
new file mode 100644
index 0000000..9981001
--- /dev/null
+++ b/include/perfetto/base/scoped_file.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_BASE_SCOPED_FILE_H_
+#define INCLUDE_PERFETTO_BASE_SCOPED_FILE_H_
+
+#include "perfetto/base/build_config.h"
+
+#include <fcntl.h>
+#include <stdio.h>
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+    !PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC)
+#include <corecrt_io.h>
+typedef int mode_t;
+#else
+#include <dirent.h>
+#include <unistd.h>
+#endif
+
+#include <string>
+
+#include "perfetto/base/logging.h"
+
+namespace perfetto {
+namespace base {
+
+constexpr mode_t kInvalidMode = static_cast<mode_t>(-1);
+
+// RAII classes for auto-releasing fds and dirs.
+template <typename T,
+          int (*CloseFunction)(T),
+          T InvalidValue,
+          bool CheckClose = true>
+class ScopedResource {
+ public:
+  explicit ScopedResource(T t = InvalidValue) : t_(t) {}
+  ScopedResource(ScopedResource&& other) noexcept {
+    t_ = other.t_;
+    other.t_ = InvalidValue;
+  }
+  ScopedResource& operator=(ScopedResource&& other) {
+    reset(other.t_);
+    other.t_ = InvalidValue;
+    return *this;
+  }
+  T get() const { return t_; }
+  T operator*() const { return t_; }
+  explicit operator bool() const { return t_ != InvalidValue; }
+  void reset(T r = InvalidValue) {
+    if (t_ != InvalidValue) {
+      int res = CloseFunction(t_);
+      if (CheckClose)
+        PERFETTO_CHECK(res == 0);
+    }
+    t_ = r;
+  }
+  T release() {
+    T t = t_;
+    t_ = InvalidValue;
+    return t;
+  }
+  ~ScopedResource() { reset(InvalidValue); }
+
+ private:
+  ScopedResource(const ScopedResource&) = delete;
+  ScopedResource& operator=(const ScopedResource&) = delete;
+
+  T t_;
+};
+
+using ScopedFile = ScopedResource<int, close, -1>;
+inline static ScopedFile OpenFile(const std::string& path,
+                                  int flags,
+                                  mode_t mode = kInvalidMode) {
+  PERFETTO_DCHECK((flags & O_CREAT) == 0 || mode != kInvalidMode);
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+  ScopedFile fd(open(path.c_str(), flags, mode));
+#else
+  // Always open a ScopedFile with O_CLOEXEC so we can safely fork and exec.
+  ScopedFile fd(open(path.c_str(), flags | O_CLOEXEC, mode));
+#endif
+  return fd;
+}
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+using ScopedDir = ScopedResource<DIR*, closedir, nullptr>;
+#endif
+
+using ScopedFstream = ScopedResource<FILE*, fclose, nullptr>;
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_SCOPED_FILE_H_
diff --git a/include/perfetto/base/small_set.h b/include/perfetto/base/small_set.h
new file mode 100644
index 0000000..94f2324
--- /dev/null
+++ b/include/perfetto/base/small_set.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_SMALL_SET_H_
+#define INCLUDE_PERFETTO_BASE_SMALL_SET_H_
+
+#include <array>
+
+namespace perfetto {
+
+// Set that can store up to Size items of DataType.
+// Lookup is O(Size), so it is only usable for very small sets.
+template <typename DataType, size_t Size>
+class SmallSet {
+  static_assert(Size < 16, "Do not use SmallSet for many items");
+
+ public:
+  // Name for consistency with STL.
+  using const_iterator = typename std::array<DataType, Size>::const_iterator;
+  bool Add(DataType n) {
+    if (Contains(n))
+      return true;
+    if (filled_ < Size) {
+      arr_[filled_++] = std::move(n);
+      return true;
+    }
+    return false;
+  }
+
+  bool Contains(const DataType& n) const {
+    for (size_t i = 0; i < filled_; ++i) {
+      if (arr_[i] == n)
+        return true;
+    }
+    return false;
+  }
+
+  const_iterator begin() const { return arr_.cbegin(); }
+  const_iterator end() const { return arr_.cbegin() + filled_; }
+  size_t size() const { return filled_; }
+
+ private:
+  std::array<DataType, Size> arr_;
+  size_t filled_ = 0;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_SMALL_SET_H_
diff --git a/include/perfetto/base/string_splitter.h b/include/perfetto/base/string_splitter.h
new file mode 100644
index 0000000..cee1a27
--- /dev/null
+++ b/include/perfetto/base/string_splitter.h
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_STRING_SPLITTER_H_
+#define INCLUDE_PERFETTO_BASE_STRING_SPLITTER_H_
+
+#include <string>
+
+namespace perfetto {
+namespace base {
+
+// C++ version of strtok(). Splits a string without making copies or any heap
+// allocations. Destructs the original string passed in input.
+// Supports the special case of using \0 as a delimiter.
+// The token returned in output are valid as long as the input string is valid.
+class StringSplitter {
+ public:
+  // Can take ownership of the string if passed via std::move(), e.g.:
+  // StringSplitter(std::move(str), '\n');
+  StringSplitter(std::string, char delimiter);
+
+  // Splits a C-string. The input string will be forcefully null-terminated (so
+  // str[size - 1] should be == '\0' or the last char will be truncated).
+  StringSplitter(char* str, size_t size, char delimiter);
+
+  // Splits the current token from an outer StringSplitter instance. This is to
+  // chain splitters as follows:
+  // for (base::StringSplitter lines(x, '\n'); ss.Next();)
+  //   for (base::StringSplitter words(&lines, ' '); words.Next();)
+  StringSplitter(StringSplitter*, char delimiter);
+
+  // Returns true if a token is found (in which case it will be stored in
+  // cur_token()), false if no more tokens are found.
+  bool Next();
+
+  // Returns the current token iff last call to Next() returned true. In this
+  // case it guarantees that the returned string is always null terminated.
+  // In all other cases (before the 1st call to Next() and after Next() returns
+  // false) returns nullptr.
+  char* cur_token() { return cur_; }
+
+  // Returns the length of the current token (excluding the null terminator).
+  size_t cur_token_size() const { return cur_size_; }
+
+ private:
+  StringSplitter(const StringSplitter&) = delete;
+  StringSplitter& operator=(const StringSplitter&) = delete;
+  void Initialize(char* str, size_t size);
+
+  std::string str_;
+  char* cur_;
+  size_t cur_size_;
+  char* next_;
+  char* end_;  // STL-style, points one past the last char.
+  const char delimiter_;
+};
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_STRING_SPLITTER_H_
diff --git a/include/perfetto/base/string_utils.h b/include/perfetto/base/string_utils.h
new file mode 100644
index 0000000..d2f9a36
--- /dev/null
+++ b/include/perfetto/base/string_utils.h
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_STRING_UTILS_H_
+#define INCLUDE_PERFETTO_BASE_STRING_UTILS_H_
+
+#include <string>
+#include <vector>
+
+namespace perfetto {
+namespace base {
+
+bool StartsWith(const std::string& str, const std::string& prefix);
+bool EndsWith(const std::string& str, const std::string& suffix);
+bool Contains(const std::string& haystack, const std::string& needle);
+std::string Join(const std::vector<std::string>& parts,
+                 const std::string& delim);
+std::vector<std::string> SplitString(const std::string& text,
+                                     const std::string& delimiter);
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_STRING_UTILS_H_
diff --git a/include/perfetto/base/string_view.h b/include/perfetto/base/string_view.h
new file mode 100644
index 0000000..55cbe0c
--- /dev/null
+++ b/include/perfetto/base/string_view.h
@@ -0,0 +1,155 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_STRING_VIEW_H_
+#define INCLUDE_PERFETTO_BASE_STRING_VIEW_H_
+
+#include <string.h>
+
+#include <algorithm>
+#include <string>
+
+#include "perfetto/base/hash.h"
+#include "perfetto/base/logging.h"
+
+namespace perfetto {
+namespace base {
+
+// A string-like object that refers to a non-owned piece of memory.
+// Strings are internally NOT null terminated.
+class StringView {
+ public:
+  static constexpr size_t npos = static_cast<size_t>(-1);
+
+  StringView() : data_(nullptr), size_(0) {}
+  StringView(const StringView&) = default;
+  StringView& operator=(const StringView&) = default;
+  StringView(const char* data, size_t size) : data_(data), size_(size) {
+    PERFETTO_DCHECK(data != nullptr);
+  }
+
+  // Allow implicit conversion from any class that has a |data| and |size| field
+  // and has the kConvertibleToStringView trait (e.g., protozero::ConstChars).
+  template <typename T, typename = std::enable_if<T::kConvertibleToStringView>>
+  StringView(const T& x) : StringView(x.data, x.size) {
+    PERFETTO_DCHECK(x.data != nullptr);
+  }
+
+  // Creates a StringView from a null-terminated C string.
+  // Deliberately not "explicit".
+  StringView(const char* cstr) : data_(cstr), size_(strlen(cstr)) {
+    PERFETTO_DCHECK(cstr != nullptr);
+  }
+
+  // This instead has to be explicit, as creating a StringView out of a
+  // std::string can be subtle.
+  explicit StringView(const std::string& str)
+      : data_(str.data()), size_(str.size()) {}
+
+  bool empty() const { return size_ == 0; }
+  size_t size() const { return size_; }
+  const char* data() const { return data_; }
+
+  char at(size_t pos) const {
+    PERFETTO_DCHECK(pos < size_);
+    return data_[pos];
+  }
+
+  size_t find(char c) const {
+    for (size_t i = 0; i < size_; ++i) {
+      if (data_[i] == c)
+        return i;
+    }
+    return npos;
+  }
+
+  size_t rfind(char c) const {
+    for (size_t i = size_; i > 0; --i) {
+      if (data_[i - 1] == c)
+        return i - 1;
+    }
+    return npos;
+  }
+
+  StringView substr(size_t pos, size_t count = npos) const {
+    if (pos >= size_)
+      return StringView("", 0);
+    size_t rcount = std::min(count, size_ - pos);
+    return StringView(data_ + pos, rcount);
+  }
+
+  std::string ToStdString() const {
+    return data_ == nullptr ? "" : std::string(data_, size_);
+  }
+
+  uint64_t Hash() const {
+    base::Hash hasher;
+    hasher.Update(data_, size_);
+    return hasher.digest();
+  }
+
+ private:
+  const char* data_ = nullptr;
+  size_t size_ = 0;
+};
+
+inline bool operator==(const StringView& x, const StringView& y) {
+  if (x.size() != y.size())
+    return false;
+  if (x.size() == 0)
+    return true;
+  return memcmp(x.data(), y.data(), x.size()) == 0;
+}
+
+inline bool operator!=(const StringView& x, const StringView& y) {
+  return !(x == y);
+}
+
+inline bool operator<(const StringView& x, const StringView& y) {
+  auto size = std::min(x.size(), y.size());
+  if (size == 0)
+    return x.size() < y.size();
+  int result = memcmp(x.data(), y.data(), size);
+  return result < 0 || (result == 0 && x.size() < y.size());
+}
+
+inline bool operator>=(const StringView& x, const StringView& y) {
+  return !(x < y);
+}
+
+inline bool operator>(const StringView& x, const StringView& y) {
+  return y < x;
+}
+
+inline bool operator<=(const StringView& x, const StringView& y) {
+  return !(y < x);
+}
+
+}  // namespace base
+}  // namespace perfetto
+
+namespace std {
+
+template <>
+struct hash<::perfetto::base::StringView> {
+  size_t operator()(const ::perfetto::base::StringView& sv) const {
+    return static_cast<size_t>(sv.Hash());
+  }
+};
+
+}  // namespace std
+
+#endif  // INCLUDE_PERFETTO_BASE_STRING_VIEW_H_
diff --git a/include/perfetto/base/string_writer.h b/include/perfetto/base/string_writer.h
new file mode 100644
index 0000000..5bc81bb
--- /dev/null
+++ b/include/perfetto/base/string_writer.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2019 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 INCLUDE_PERFETTO_BASE_STRING_WRITER_H_
+#define INCLUDE_PERFETTO_BASE_STRING_WRITER_H_
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/string_view.h"
+
+namespace perfetto {
+namespace base {
+
+// A helper class which writes formatted data to a string buffer.
+// This is used in the trace processor where we write O(GBs) of strings and
+// sprintf is too slow.
+class StringWriter {
+ public:
+  // Creates a string buffer from a char buffer and length.
+  StringWriter(char* buffer, size_t size) : buffer_(buffer), size_(size) {}
+
+  // Appends n instances of a char to the buffer.
+  void AppendChar(char in, size_t n = 1) {
+    PERFETTO_DCHECK(pos_ + n <= size_);
+    memset(&buffer_[pos_], in, n);
+    pos_ += n;
+  }
+
+  // Appends a length delimited string to the buffer.
+  void AppendString(const char* in, size_t n) {
+    PERFETTO_DCHECK(pos_ + n <= size_);
+    memcpy(&buffer_[pos_], in, n);
+    pos_ += n;
+  }
+
+  void AppendStringView(StringView sv) { AppendString(sv.data(), sv.size()); }
+
+  // Appends a null-terminated string literal to the buffer.
+  template <size_t N>
+  inline void AppendLiteral(const char (&in)[N]) {
+    AppendString(in, N - 1);
+  }
+
+  // Appends a StringView to the buffer.
+  void AppendString(StringView data) { AppendString(data.data(), data.size()); }
+
+  // Appends an integer to the buffer.
+  void AppendInt(int64_t value) { AppendPaddedInt<'0', 0>(value); }
+
+  // Appends an integer to the buffer, padding with |padchar| if the number of
+  // digits of the integer is less than |padding|.
+  template <char padchar, uint64_t padding>
+  void AppendPaddedInt(int64_t sign_value) {
+    // Need to add 2 to the number of digits to account for minus sign and
+    // rounding down of digits10.
+    constexpr auto kMaxDigits = std::numeric_limits<uint64_t>::digits10 + 2;
+    constexpr auto kSizeNeeded = kMaxDigits > padding ? kMaxDigits : padding;
+    PERFETTO_DCHECK(pos_ + kSizeNeeded <= size_);
+
+    char data[kSizeNeeded];
+    const bool negate = signbit(static_cast<double>(sign_value));
+    uint64_t value = static_cast<uint64_t>(std::abs(sign_value));
+
+    size_t idx;
+    for (idx = kSizeNeeded - 1; value >= 10;) {
+      char digit = value % 10;
+      value /= 10;
+      data[idx--] = digit + '0';
+    }
+    data[idx--] = static_cast<char>(value) + '0';
+
+    if (padding > 0) {
+      size_t num_digits = kSizeNeeded - 1 - idx;
+      for (size_t i = num_digits; i < padding; i++) {
+        data[idx--] = padchar;
+      }
+    }
+
+    if (negate)
+      buffer_[pos_++] = '-';
+    AppendString(&data[idx + 1], kSizeNeeded - idx - 1);
+  }
+
+  // Appends a hex integer to the buffer.
+  void AppendHexInt(uint32_t value) {
+    // TODO(lalitm): trying to optimize this is premature given we almost never
+    // print hex ints. Reevaluate this in the future if we do print them more.
+    size_t res = static_cast<size_t>(
+        snprintf(buffer_ + pos_, size_ - pos_, "%x", value));
+    PERFETTO_DCHECK(pos_ + res <= size_);
+    pos_ += res;
+  }
+
+  // Appends a double to the buffer.
+  void AppendDouble(double value) {
+    // TODO(lalitm): trying to optimize this is premature given we almost never
+    // print doubles. Reevaluate this in the future if we do print them more.
+    size_t res = static_cast<size_t>(
+        snprintf(buffer_ + pos_, size_ - pos_, "%lf", value));
+    PERFETTO_DCHECK(pos_ + res <= size_);
+    pos_ += res;
+  }
+
+  StringView GetStringView() {
+    PERFETTO_DCHECK(pos_ <= size_);
+    return StringView(buffer_, pos_);
+  }
+
+  char* CreateStringCopy() {
+    char* dup = reinterpret_cast<char*>(malloc(pos_ + 1));
+    if (dup) {
+      strncpy(dup, buffer_, pos_);
+      dup[pos_] = '\0';
+    }
+    return dup;
+  }
+
+  size_t pos() const { return pos_; }
+  size_t size() const { return size_; }
+  void reset() { pos_ = 0; }
+
+ private:
+  char* buffer_ = nullptr;
+  size_t size_ = 0;
+  size_t pos_ = 0;
+};
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_STRING_WRITER_H_
diff --git a/include/perfetto/base/task_runner.h b/include/perfetto/base/task_runner.h
index cf60401..3b80bbb 100644
--- a/include/perfetto/base/task_runner.h
+++ b/include/perfetto/base/task_runner.h
@@ -19,11 +19,18 @@
 
 #include <functional>
 
+#include "perfetto/base/build_config.h"
 #include "perfetto/base/export.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/base/watchdog.h"
 
 namespace perfetto {
 namespace base {
 
+// Maximum time a single task can take in a TaskRunner before the
+// program suicides.
+constexpr int64_t kWatchdogMillis = 30000;  // 30s
+
 // A generic interface to allow the library clients to interleave the execution
 // of the tracing internals in their runtime environment.
 // The expectation is that all tasks, which are queued either via PostTask() or
@@ -66,6 +73,13 @@
   // thread/sequence. This can allow some callers to skip PostTask and instead
   // directly execute the code. Can be called from any thread.
   virtual bool RunsTasksOnCurrentThread() const = 0;
+
+ protected:
+  static void RunTask(const std::function<void()>& task) {
+    Watchdog::Timer handle =
+        base::Watchdog::GetInstance()->CreateFatalTimer(kWatchdogMillis);
+    task();
+  }
 };
 
 }  // namespace base
diff --git a/include/perfetto/base/temp_file.h b/include/perfetto/base/temp_file.h
new file mode 100644
index 0000000..e862971
--- /dev/null
+++ b/include/perfetto/base/temp_file.h
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_TEMP_FILE_H_
+#define INCLUDE_PERFETTO_BASE_TEMP_FILE_H_
+
+#include <string>
+
+#include "perfetto/base/scoped_file.h"
+
+namespace perfetto {
+namespace base {
+
+class TempFile {
+ public:
+  static TempFile CreateUnlinked();
+  static TempFile Create();
+
+  TempFile(TempFile&&) noexcept;
+  TempFile& operator=(TempFile&&);
+  ~TempFile();
+
+  const std::string& path() const { return path_; }
+  int fd() const { return *fd_; }
+  int operator*() const { return *fd_; }
+
+  // Unlinks the file from the filesystem but keeps the fd() open.
+  // It is safe to call this multiple times.
+  void Unlink();
+
+  // Releases the underlying file descriptor. Will unlink the file from the
+  // filesystem if it was created via CreateUnlinked().
+  ScopedFile ReleaseFD();
+
+ private:
+  TempFile();
+  TempFile(const TempFile&) = delete;
+  TempFile& operator=(const TempFile&) = delete;
+
+  ScopedFile fd_;
+  std::string path_;
+};
+
+class TempDir {
+ public:
+  static TempDir Create();
+
+  TempDir(TempDir&&) noexcept;
+  TempDir& operator=(TempDir&&);
+  ~TempDir();
+
+  const std::string& path() const { return path_; }
+
+ private:
+  TempDir();
+  TempDir(const TempDir&) = delete;
+  TempDir& operator=(const TempDir&) = delete;
+
+  std::string path_;
+};
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_TEMP_FILE_H_
diff --git a/include/perfetto/base/thread_annotations.h b/include/perfetto/base/thread_annotations.h
new file mode 100644
index 0000000..b5d3671
--- /dev/null
+++ b/include/perfetto/base/thread_annotations.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 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 INCLUDE_PERFETTO_BASE_THREAD_ANNOTATIONS_H_
+#define INCLUDE_PERFETTO_BASE_THREAD_ANNOTATIONS_H_
+
+#include "perfetto/base/build_config.h"
+
+// Windows TSAN doesn't currently support these annotations.
+#if defined(THREAD_SANITIZER) && !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+extern "C" {
+void AnnotateBenignRaceSized(const char* file,
+                             int line,
+                             unsigned long address,
+                             unsigned long size,
+                             const char* description);
+}
+
+#define PERFETTO_ANNOTATE_BENIGN_RACE_SIZED(pointer, size, description)   \
+  AnnotateBenignRaceSized(__FILE__, __LINE__,                             \
+                          reinterpret_cast<unsigned long>(pointer), size, \
+                          description);
+#else  // defined(ADDRESS_SANITIZER)
+#define PERFETTO_ANNOTATE_BENIGN_RACE_SIZED(pointer, size, description)
+#endif  // defined(ADDRESS_SANITIZER)
+
+#endif  // INCLUDE_PERFETTO_BASE_THREAD_ANNOTATIONS_H_
diff --git a/include/perfetto/base/thread_checker.h b/include/perfetto/base/thread_checker.h
new file mode 100644
index 0000000..9b99e88
--- /dev/null
+++ b/include/perfetto/base/thread_checker.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_BASE_THREAD_CHECKER_H_
+#define INCLUDE_PERFETTO_BASE_THREAD_CHECKER_H_
+
+#include "perfetto/base/build_config.h"
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <pthread.h>
+#endif
+#include <atomic>
+
+#include "perfetto/base/export.h"
+#include "perfetto/base/logging.h"
+#include "perfetto/base/utils.h"
+
+namespace perfetto {
+namespace base {
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+using ThreadID = unsigned long;
+#else
+using ThreadID = pthread_t;
+#endif
+
+class PERFETTO_EXPORT ThreadChecker {
+ public:
+  ThreadChecker();
+  ~ThreadChecker();
+  ThreadChecker(const ThreadChecker&);
+  ThreadChecker& operator=(const ThreadChecker&);
+  bool CalledOnValidThread() const PERFETTO_WARN_UNUSED_RESULT;
+  void DetachFromThread();
+
+ private:
+  mutable std::atomic<ThreadID> thread_id_;
+};
+
+#if PERFETTO_DCHECK_IS_ON() && !defined(PERFETTO_BUILD_WITH_CHROMIUM)
+// TODO(primiano) Use Chromium's thread checker in Chromium.
+#define PERFETTO_THREAD_CHECKER(name) base::ThreadChecker name;
+#define PERFETTO_DCHECK_THREAD(name) \
+  PERFETTO_DCHECK((name).CalledOnValidThread())
+#define PERFETTO_DETACH_FROM_THREAD(name) (name).DetachFromThread()
+#else
+#define PERFETTO_THREAD_CHECKER(name)
+#define PERFETTO_DCHECK_THREAD(name)
+#define PERFETTO_DETACH_FROM_THREAD(name)
+#endif  // PERFETTO_DCHECK_IS_ON()
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_THREAD_CHECKER_H_
diff --git a/include/perfetto/base/thread_task_runner.h b/include/perfetto/base/thread_task_runner.h
new file mode 100644
index 0000000..db49a61
--- /dev/null
+++ b/include/perfetto/base/thread_task_runner.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 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 INCLUDE_PERFETTO_BASE_THREAD_TASK_RUNNER_H_
+#define INCLUDE_PERFETTO_BASE_THREAD_TASK_RUNNER_H_
+
+#include <functional>
+#include <thread>
+
+#include "perfetto/base/unix_task_runner.h"
+
+namespace perfetto {
+namespace base {
+
+// A UnixTaskRunner backed by a dedicated task thread. Shuts down the runner and
+// joins the thread upon destruction. Can be moved to transfer ownership.
+//
+// Guarantees that:
+// * the UnixTaskRunner will be constructed and destructed on the task thread.
+// * the task thread will live for the lifetime of the UnixTaskRunner.
+//
+class ThreadTaskRunner {
+ public:
+  static ThreadTaskRunner CreateAndStart() { return ThreadTaskRunner(); }
+
+  ThreadTaskRunner(const ThreadTaskRunner&) = delete;
+  ThreadTaskRunner& operator=(const ThreadTaskRunner&) = delete;
+
+  ThreadTaskRunner(ThreadTaskRunner&&) noexcept;
+  ThreadTaskRunner& operator=(ThreadTaskRunner&&);
+  ~ThreadTaskRunner();
+
+  // Returns a pointer to the UnixTaskRunner, which is valid for the lifetime of
+  // this ThreadTaskRunner object (unless this object is moved-from, in which
+  // case the pointer remains valid for the lifetime of the new owning
+  // ThreadTaskRunner).
+  //
+  // Warning: do not call Quit() on the returned runner pointer, the termination
+  // should be handled exclusively by this class' destructor.
+  UnixTaskRunner* get() const { return task_runner_; }
+
+ private:
+  ThreadTaskRunner();
+  void RunTaskThread(std::function<void(UnixTaskRunner*)> initializer);
+
+  std::thread thread_;
+  UnixTaskRunner* task_runner_ = nullptr;
+};
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_THREAD_TASK_RUNNER_H_
diff --git a/include/perfetto/base/thread_utils.h b/include/perfetto/base/thread_utils.h
new file mode 100644
index 0000000..3d7eac0
--- /dev/null
+++ b/include/perfetto/base/thread_utils.h
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_THREAD_UTILS_H_
+#define INCLUDE_PERFETTO_BASE_THREAD_UTILS_H_
+
+#include <stdint.h>
+
+#include "perfetto/base/build_config.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <processthreadsapi.h>
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
+#include <zircon/process.h>
+#include <zircon/types.h>
+#else
+#include <pthread.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+namespace perfetto {
+namespace base {
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+using PlatformThreadID = pid_t;
+inline PlatformThreadID GetThreadId() {
+  return gettid();
+}
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX)
+using PlatformThreadID = pid_t;
+inline PlatformThreadID GetThreadId() {
+  return static_cast<pid_t>(syscall(__NR_gettid));
+}
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
+using PlatformThreadID = zx_handle_t;
+inline PlatformThreadID GetThreadId() {
+  return static_cast<pid_t>(zx_thread_self());
+}
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
+using PlatformThreadID = uint64_t;
+inline PlatformThreadID GetThreadId() {
+  uint64_t tid;
+  pthread_threadid_np(nullptr, &tid);
+  return tid;
+}
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+using PlatformThreadID = uint64_t;
+inline PlatformThreadID GetThreadId() {
+  return static_cast<uint64_t>(GetCurrentThreadID());
+}
+#else  // Default to pthreads in case no OS is set.
+using PlatformThreadID = pthread_t;
+inline PlatformThreadID GetThreadId() {
+  return pthread_self();
+}
+#endif
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_THREAD_UTILS_H_
diff --git a/include/perfetto/base/unix_socket.h b/include/perfetto/base/unix_socket.h
new file mode 100644
index 0000000..f2b8003
--- /dev/null
+++ b/include/perfetto/base/unix_socket.h
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_BASE_UNIX_SOCKET_H_
+#define INCLUDE_PERFETTO_BASE_UNIX_SOCKET_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <memory>
+#include <string>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/base/weak_ptr.h"
+
+struct msghdr;
+
+namespace perfetto {
+namespace base {
+
+class TaskRunner;
+
+// Use arbitrarily high values to avoid that some code accidentally ends up
+// assuming that these enum values match the sysroot's SOCK_xxx defines rather
+// than using GetUnixSockType().
+enum class SockType { kStream = 100, kDgram, kSeqPacket };
+
+// UnixSocketRaw is a basic wrapper around UNIX sockets. It exposes wrapper
+// methods that take care of most common pitfalls (e.g., marking fd as
+// O_CLOEXEC, avoiding SIGPIPE, properly handling partial writes). It is used as
+// a building block for the more sophisticated UnixSocket class.
+class UnixSocketRaw {
+ public:
+  // Creates a new unconnected unix socket.
+  static UnixSocketRaw CreateMayFail(SockType t) { return UnixSocketRaw(t); }
+
+  // Crates a pair of connected sockets.
+  static std::pair<UnixSocketRaw, UnixSocketRaw> CreatePair(SockType);
+
+  // Creates an uninitialized unix socket.
+  UnixSocketRaw();
+
+  // Creates a unix socket adopting an existing file descriptor. This is
+  // typically used to inherit fds from init via environment variables.
+  UnixSocketRaw(ScopedFile, SockType);
+
+  ~UnixSocketRaw() = default;
+  UnixSocketRaw(UnixSocketRaw&&) noexcept = default;
+  UnixSocketRaw& operator=(UnixSocketRaw&&) = default;
+
+  bool Bind(const std::string& socket_name);
+  bool Listen();
+  bool Connect(const std::string& socket_name);
+  bool SetTxTimeout(uint32_t timeout_ms);
+  bool SetRxTimeout(uint32_t timeout_ms);
+  void Shutdown();
+  void SetBlocking(bool);
+  bool IsBlocking() const;
+  void RetainOnExec();
+  SockType type() const { return type_; }
+  int fd() const { return *fd_; }
+  explicit operator bool() const { return !!fd_; }
+
+  ScopedFile ReleaseFd() { return std::move(fd_); }
+
+  ssize_t Send(const void* msg,
+               size_t len,
+               const int* send_fds = nullptr,
+               size_t num_fds = 0);
+
+  // Re-enter sendmsg until all the data has been sent or an error occurs.
+  // TODO(fmayer): Figure out how to do timeouts here for heapprofd.
+  ssize_t SendMsgAll(struct msghdr* msg);
+
+  ssize_t Receive(void* msg,
+                  size_t len,
+                  ScopedFile* fd_vec = nullptr,
+                  size_t max_files = 0);
+
+  // Exposed for testing only.
+  // Update msghdr so subsequent sendmsg will send data that remains after n
+  // bytes have already been sent.
+  static void ShiftMsgHdr(size_t n, struct msghdr* msg);
+
+ private:
+  explicit UnixSocketRaw(SockType);
+
+  UnixSocketRaw(const UnixSocketRaw&) = delete;
+  UnixSocketRaw& operator=(const UnixSocketRaw&) = delete;
+
+  ScopedFile fd_;
+  SockType type_{SockType::kStream};
+};
+
+// A non-blocking UNIX domain socket. Allows also to transfer file descriptors.
+// None of the methods in this class are blocking.
+// The main design goal is making strong guarantees on the EventListener
+// callbacks, in order to avoid ending in some undefined state.
+// In case of any error it will aggressively just shut down the socket and
+// notify the failure with OnConnect(false) or OnDisconnect() depending on the
+// state of the socket (see below).
+// EventListener callbacks stop happening as soon as the instance is destroyed.
+//
+// Lifecycle of a client socket:
+//
+//                           Connect()
+//                               |
+//            +------------------+------------------+
+//            | (success)                           | (failure or Shutdown())
+//            V                                     V
+//     OnConnect(true)                         OnConnect(false)
+//            |
+//            V
+//    OnDataAvailable()
+//            |
+//            V
+//     OnDisconnect()  (failure or shutdown)
+//
+//
+// Lifecycle of a server socket:
+//
+//                          Listen()  --> returns false in case of errors.
+//                             |
+//                             V
+//              OnNewIncomingConnection(new_socket)
+//
+//          (|new_socket| inherits the same EventListener)
+//                             |
+//                             V
+//                     OnDataAvailable()
+//                             | (failure or Shutdown())
+//                             V
+//                       OnDisconnect()
+class UnixSocket {
+ public:
+  class EventListener {
+   public:
+    virtual ~EventListener();
+
+    // After Listen().
+    virtual void OnNewIncomingConnection(
+        UnixSocket* self,
+        std::unique_ptr<UnixSocket> new_connection);
+
+    // After Connect(), whether successful or not.
+    virtual void OnConnect(UnixSocket* self, bool connected);
+
+    // After a successful Connect() or OnNewIncomingConnection(). Either the
+    // other endpoint did disconnect or some other error happened.
+    virtual void OnDisconnect(UnixSocket* self);
+
+    // Whenever there is data available to Receive(). Note that spurious FD
+    // watch events are possible, so it is possible that Receive() soon after
+    // OnDataAvailable() returns 0 (just ignore those).
+    virtual void OnDataAvailable(UnixSocket* self);
+  };
+
+  enum class State {
+    kDisconnected = 0,  // Failed connection, peer disconnection or Shutdown().
+    kConnecting,  // Soon after Connect(), before it either succeeds or fails.
+    kConnected,   // After a successful Connect().
+    kListening    // After Listen(), until Shutdown().
+  };
+
+  enum class BlockingMode { kNonBlocking, kBlocking };
+
+  // Creates a Unix domain socket and starts listening. If |socket_name|
+  // starts with a '@', an abstract socket will be created (Linux/Android only).
+  // Returns always an instance. In case of failure (e.g., another socket
+  // with the same name is  already listening) the returned socket will have
+  // is_listening() == false and last_error() will contain the failure reason.
+  static std::unique_ptr<UnixSocket> Listen(const std::string& socket_name,
+                                            EventListener*,
+                                            TaskRunner*,
+                                            SockType = SockType::kStream);
+
+  // Attaches to a pre-existing socket. The socket must have been created in
+  // SOCK_STREAM mode and the caller must have called bind() on it.
+  static std::unique_ptr<UnixSocket> Listen(ScopedFile,
+                                            EventListener*,
+                                            TaskRunner*,
+                                            SockType = SockType::kStream);
+
+  // Creates a Unix domain socket and connects to the listening endpoint.
+  // Returns always an instance. EventListener::OnConnect(bool success) will
+  // be called always, whether the connection succeeded or not.
+  static std::unique_ptr<UnixSocket> Connect(const std::string& socket_name,
+                                             EventListener*,
+                                             TaskRunner*,
+                                             SockType = SockType::kStream);
+
+  // Constructs a UnixSocket using the given connected socket.
+  static std::unique_ptr<UnixSocket> AdoptConnected(
+      ScopedFile fd,
+      EventListener* event_listener,
+      TaskRunner* task_runner,
+      SockType sock_type);
+
+  UnixSocket(const UnixSocket&) = delete;
+  UnixSocket& operator=(const UnixSocket&) = delete;
+  // Cannot be easily moved because of tasks from the FileDescriptorWatch.
+  UnixSocket(UnixSocket&&) = delete;
+  UnixSocket& operator=(UnixSocket&&) = delete;
+
+  // This class gives the hard guarantee that no callback is called on the
+  // passed EventListener immediately after the object has been destroyed.
+  // Any queued callback will be silently dropped.
+  ~UnixSocket();
+
+  // Shuts down the current connection, if any. If the socket was Listen()-ing,
+  // stops listening. The socket goes back to kNotInitialized state, so it can
+  // be reused with Listen() or Connect().
+  void Shutdown(bool notify);
+
+  // Returns true is the message was queued, false if there was no space in the
+  // output buffer, in which case the client should retry or give up.
+  // If any other error happens the socket will be shutdown and
+  // EventListener::OnDisconnect() will be called.
+  // If the socket is not connected, Send() will just return false.
+  // Does not append a null string terminator to msg in any case.
+  //
+  // DO NOT PASS kNonBlocking, it is broken.
+  bool Send(const void* msg,
+            size_t len,
+            const int* send_fds,
+            size_t num_fds,
+            BlockingMode blocking = BlockingMode::kNonBlocking);
+
+  inline bool Send(const void* msg,
+                   size_t len,
+                   int send_fd = -1,
+                   BlockingMode blocking = BlockingMode::kNonBlocking) {
+    if (send_fd != -1)
+      return Send(msg, len, &send_fd, 1, blocking);
+    return Send(msg, len, nullptr, 0, blocking);
+  }
+
+  inline bool Send(const std::string& msg,
+                   BlockingMode blocking = BlockingMode::kNonBlocking) {
+    return Send(msg.c_str(), msg.size() + 1, -1, blocking);
+  }
+
+  // Returns the number of bytes (<= |len|) written in |msg| or 0 if there
+  // is no data in the buffer to read or an error occurs (in which case a
+  // EventListener::OnDisconnect() will follow).
+  // If the ScopedFile pointer is not null and a FD is received, it moves the
+  // received FD into that. If a FD is received but the ScopedFile pointer is
+  // null, the FD will be automatically closed.
+  size_t Receive(void* msg, size_t len, ScopedFile*, size_t max_files = 1);
+
+  inline size_t Receive(void* msg, size_t len) {
+    return Receive(msg, len, nullptr, 0);
+  }
+
+  // Only for tests. This is slower than Receive() as it requires a heap
+  // allocation and a copy for the std::string. Guarantees that the returned
+  // string is null terminated even if the underlying message sent by the peer
+  // is not.
+  std::string ReceiveString(size_t max_length = 1024);
+
+  bool is_connected() const { return state_ == State::kConnected; }
+  bool is_listening() const { return state_ == State::kListening; }
+  int fd() const { return sock_raw_.fd(); }
+  int last_error() const { return last_error_; }
+
+  // User ID of the peer, as returned by the kernel. If the client disconnects
+  // and the socket goes into the kDisconnected state, it retains the uid of
+  // the last peer.
+  uid_t peer_uid() const {
+    PERFETTO_DCHECK(!is_listening() && peer_uid_ != kInvalidUid);
+    return peer_uid_;
+  }
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+  // Process ID of the peer, as returned by the kernel. If the client
+  // disconnects and the socket goes into the kDisconnected state, it
+  // retains the pid of the last peer.
+  //
+  // This is only available on Linux / Android.
+  pid_t peer_pid() const {
+    PERFETTO_DCHECK(!is_listening() && peer_pid_ != kInvalidPid);
+    return peer_pid_;
+  }
+#endif
+
+  // This makes the UnixSocket unusable.
+  UnixSocketRaw ReleaseSocket();
+
+ private:
+  UnixSocket(EventListener*, TaskRunner*, SockType);
+  UnixSocket(EventListener*, TaskRunner*, ScopedFile, State, SockType);
+
+  // Called once by the corresponding public static factory methods.
+  void DoConnect(const std::string& socket_name);
+  void ReadPeerCredentials();
+
+  void OnEvent();
+  void NotifyConnectionState(bool success);
+
+  UnixSocketRaw sock_raw_;
+  State state_ = State::kDisconnected;
+  int last_error_ = 0;
+  uid_t peer_uid_ = kInvalidUid;
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+  pid_t peer_pid_ = kInvalidPid;
+#endif
+  EventListener* const event_listener_;
+  TaskRunner* const task_runner_;
+  WeakPtrFactory<UnixSocket> weak_ptr_factory_;  // Keep last.
+};
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_UNIX_SOCKET_H_
diff --git a/include/perfetto/base/unix_task_runner.h b/include/perfetto/base/unix_task_runner.h
new file mode 100644
index 0000000..98c9c7e
--- /dev/null
+++ b/include/perfetto/base/unix_task_runner.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_BASE_UNIX_TASK_RUNNER_H_
+#define INCLUDE_PERFETTO_BASE_UNIX_TASK_RUNNER_H_
+
+#include "perfetto/base/build_config.h"
+#include "perfetto/base/event.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/task_runner.h"
+#include "perfetto/base/thread_checker.h"
+#include "perfetto/base/thread_utils.h"
+#include "perfetto/base/time.h"
+
+#include <poll.h>
+#include <chrono>
+#include <deque>
+#include <map>
+#include <mutex>
+#include <vector>
+
+namespace perfetto {
+namespace base {
+
+// Runs a task runner on the current thread.
+//
+// Implementation note: we currently assume (and enforce in debug builds) that
+// Run() is called from the thread that constructed the UnixTaskRunner. This is
+// not strictly necessary, and we could instead track the thread that invokes
+// Run(). However, a related property that *might* be important to enforce is
+// that the destructor runs on the task-running thread. Otherwise, if there are
+// still-pending tasks at the time of destruction, we would destroy those
+// outside of the task thread (which might be unexpected to the caller). On the
+// other hand, the std::function task interface discourages use of any
+// resource-owning tasks (as the callable needs to be copyable), so this might
+// not be important in practice.
+//
+// TODO(rsavitski): consider adding a thread-check in the destructor, after
+// auditing existing usages.
+class UnixTaskRunner : public TaskRunner {
+ public:
+  UnixTaskRunner();
+  ~UnixTaskRunner() override;
+
+  // Start executing tasks. Doesn't return until Quit() is called. Run() may be
+  // called multiple times on the same task runner.
+  void Run();
+  void Quit();
+
+  // Checks whether there are any pending immediate tasks to run. Note that
+  // delayed tasks don't count even if they are due to run.
+  bool IsIdleForTesting();
+
+  // TaskRunner implementation:
+  void PostTask(std::function<void()>) override;
+  void PostDelayedTask(std::function<void()>, uint32_t delay_ms) override;
+  void AddFileDescriptorWatch(int fd, std::function<void()>) override;
+  void RemoveFileDescriptorWatch(int fd) override;
+  bool RunsTasksOnCurrentThread() const override;
+
+  // Returns true if the task runner is quitting, or has quit and hasn't been
+  // restarted since. Exposed primarily for ThreadTaskRunner, not necessary for
+  // normal use of this class.
+  bool QuitCalled();
+
+ private:
+  void WakeUp();
+
+  void UpdateWatchTasksLocked();
+
+  int GetDelayMsToNextTaskLocked() const;
+  void RunImmediateAndDelayedTask();
+  void PostFileDescriptorWatches();
+  void RunFileDescriptorWatch(int fd);
+
+  ThreadChecker thread_checker_;
+  PlatformThreadID created_thread_id_ = GetThreadId();
+
+  // On Linux, an eventfd(2) used to waking up the task runner when a new task
+  // is posted. Otherwise the read end of a pipe used for the same purpose.
+  Event event_;
+
+  std::vector<struct pollfd> poll_fds_;
+
+  // --- Begin lock-protected members ---
+
+  std::mutex lock_;
+
+  std::deque<std::function<void()>> immediate_tasks_;
+  std::multimap<TimeMillis, std::function<void()>> delayed_tasks_;
+  bool quit_ = false;
+
+  struct WatchTask {
+    std::function<void()> callback;
+    size_t poll_fd_index;  // Index into |poll_fds_|.
+  };
+
+  std::map<int, WatchTask> watch_tasks_;
+  bool watch_tasks_changed_ = false;
+
+  // --- End lock-protected members ---
+};
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_UNIX_TASK_RUNNER_H_
diff --git a/include/perfetto/base/utils.h b/include/perfetto/base/utils.h
new file mode 100644
index 0000000..3669cb1
--- /dev/null
+++ b/include/perfetto/base/utils.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_BASE_UTILS_H_
+#define INCLUDE_PERFETTO_BASE_UTILS_H_
+
+#include "perfetto/base/build_config.h"
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <sys/types.h>
+#endif
+
+#define PERFETTO_EINTR(x)                                   \
+  ({                                                        \
+    decltype(x) eintr_wrapper_result;                       \
+    do {                                                    \
+      eintr_wrapper_result = (x);                           \
+    } while (eintr_wrapper_result == -1 && errno == EINTR); \
+    eintr_wrapper_result;                                   \
+  })
+
+#define PERFETTO_LIKELY(_x) __builtin_expect(!!(_x), 1)
+#define PERFETTO_UNLIKELY(_x) __builtin_expect(!!(_x), 0)
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+// TODO(brucedawson) - create a ::perfetto::base::IOSize to replace this.
+#if defined(_WIN64)
+using ssize_t = __int64;
+#else
+using ssize_t = long;
+#endif
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#define PERFETTO_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#else
+#define PERFETTO_WARN_UNUSED_RESULT
+#endif
+
+#if defined(__clang__)
+#define PERFETTO_ALWAYS_INLINE __attribute__((__always_inline__))
+#else
+// GCC is too pedantic and often fails with the error:
+// "always_inline function might not be inlinable"
+#define PERFETTO_ALWAYS_INLINE
+#endif
+
+// TODO(lalitm): is_trivially_constructible is currently not available
+// in some environments we build in. Reenable when that environment supports
+// this.
+#if defined(__GLIBCXX__)
+#define PERFETTO_IS_TRIVIALLY_CONSTRUCTIBLE(T) true
+#else
+#define PERFETTO_IS_TRIVIALLY_CONSTRUCTIBLE(T) \
+  std::is_trivially_constructible<T>::value
+#endif
+
+// TODO(lalitm): is_trivially_copyable is currently not available
+// in some environments we build in. Reenable when that environment supports
+// this.
+#if defined(__GLIBCXX__)
+#define PERFETTO_IS_TRIVIALLY_COPYABLE(T) true
+#else
+#define PERFETTO_IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
+#endif
+
+namespace perfetto {
+namespace base {
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+constexpr uid_t kInvalidUid = static_cast<uid_t>(-1);
+constexpr pid_t kInvalidPid = static_cast<pid_t>(-1);
+#endif
+
+constexpr size_t kPageSize = 4096;
+constexpr size_t kMaxCpus = 128;
+
+template <typename T>
+constexpr size_t ArraySize(const T& array) {
+  return sizeof(array) / sizeof(array[0]);
+}
+
+template <typename... T>
+inline void ignore_result(const T&...) {}
+
+// Function object which invokes 'free' on its parameter, which must be
+// a pointer. Can be used to store malloc-allocated pointers in std::unique_ptr:
+//
+// std::unique_ptr<int, base::FreeDeleter> foo_ptr(
+//     static_cast<int*>(malloc(sizeof(int))));
+struct FreeDeleter {
+  inline void operator()(void* ptr) const { free(ptr); }
+};
+
+template <typename T>
+constexpr T AssumeLittleEndian(T value) {
+  static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__,
+                "Unimplemented on big-endian archs");
+  return value;
+}
+
+// Round up |size| to a multiple of |alignment| (must be a power of two).
+template <size_t alignment>
+constexpr size_t AlignUp(size_t size) {
+  static_assert((alignment & (alignment - 1)) == 0, "alignment must be a pow2");
+  return (size + alignment - 1) & ~(alignment - 1);
+}
+
+inline bool IsAgain(int err) {
+  return err == EAGAIN || err == EWOULDBLOCK;
+}
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_UTILS_H_
diff --git a/include/perfetto/base/watchdog.h b/include/perfetto/base/watchdog.h
new file mode 100644
index 0000000..77fde51
--- /dev/null
+++ b/include/perfetto/base/watchdog.h
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_WATCHDOG_H_
+#define INCLUDE_PERFETTO_BASE_WATCHDOG_H_
+
+#include "perfetto/base/build_config.h"
+
+#if (PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||    \
+     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)) && \
+    !PERFETTO_BUILDFLAG(PERFETTO_EMBEDDER_BUILD)
+#include "perfetto/base/watchdog_posix.h"
+#else
+#include "perfetto/base/watchdog_noop.h"
+#endif
+
+#endif  // INCLUDE_PERFETTO_BASE_WATCHDOG_H_
diff --git a/include/perfetto/base/watchdog_noop.h b/include/perfetto/base/watchdog_noop.h
new file mode 100644
index 0000000..e542aa6
--- /dev/null
+++ b/include/perfetto/base/watchdog_noop.h
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_WATCHDOG_NOOP_H_
+#define INCLUDE_PERFETTO_BASE_WATCHDOG_NOOP_H_
+
+#include <stdint.h>
+
+namespace perfetto {
+namespace base {
+
+class Watchdog {
+ public:
+  class Timer {
+   public:
+    // Define an empty dtor to avoid "unused variable" errors on the call site.
+    Timer() {}
+    Timer(const Timer&) {}
+    ~Timer() {}
+  };
+  static Watchdog* GetInstance() {
+    static Watchdog* watchdog = new Watchdog();
+    return watchdog;
+  }
+  Timer CreateFatalTimer(uint32_t /*ms*/) { return Timer(); }
+  void Start() {}
+  void SetMemoryLimit(uint32_t /*bytes*/, uint32_t /*window_ms*/) {}
+  void SetCpuLimit(uint32_t /*percentage*/, uint32_t /*window_ms*/) {}
+};
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_WATCHDOG_NOOP_H_
diff --git a/include/perfetto/base/watchdog_posix.h b/include/perfetto/base/watchdog_posix.h
new file mode 100644
index 0000000..a7080df
--- /dev/null
+++ b/include/perfetto/base/watchdog_posix.h
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_BASE_WATCHDOG_POSIX_H_
+#define INCLUDE_PERFETTO_BASE_WATCHDOG_POSIX_H_
+
+#include "perfetto/base/thread_checker.h"
+
+#include <atomic>
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+
+namespace perfetto {
+namespace base {
+
+// Ensures that the calling program does not exceed certain hard limits on
+// resource usage e.g. time, memory and CPU. If exceeded, the program is
+// crashed.
+class Watchdog {
+ public:
+  // Handle to the timer set to crash the program. If the handle is dropped,
+  // the timer is removed so the program does not crash.
+  class Timer {
+   public:
+    ~Timer();
+    Timer(Timer&&) noexcept;
+
+   private:
+    friend class Watchdog;
+
+    explicit Timer(uint32_t ms);
+    Timer(const Timer&) = delete;
+    Timer& operator=(const Timer&) = delete;
+
+    timer_t timerid_ = nullptr;
+  };
+  virtual ~Watchdog();
+
+  static Watchdog* GetInstance();
+
+  // Sets a timer which will crash the program in |ms| milliseconds if the
+  // returned handle is not destroyed before this point.
+  Timer CreateFatalTimer(uint32_t ms);
+
+  // Starts the watchdog thread which monitors the memory and CPU usage
+  // of the program.
+  void Start();
+
+  // Sets a limit on the memory (defined as the RSS) used by the program
+  // averaged over the last |window_ms| milliseconds. If |kb| is 0, any
+  // existing limit is removed.
+  // Note: |window_ms| has to be a multiple of |polling_interval_ms_|.
+  void SetMemoryLimit(uint64_t bytes, uint32_t window_ms);
+
+  // Sets a limit on the CPU usage used by the program averaged over the last
+  // |window_ms| milliseconds. If |percentage| is 0, any existing limit is
+  // removed.
+  // Note: |window_ms| has to be a multiple of |polling_interval_ms_|.
+  void SetCpuLimit(uint32_t percentage, uint32_t window_ms);
+
+ protected:
+  // Protected for testing.
+  Watchdog(uint32_t polling_interval_ms);
+
+ private:
+  // Represents a ring buffer in which integer values can be stored.
+  class WindowedInterval {
+   public:
+    // Pushes a new value into a ring buffer wrapping if necessary and returns
+    // whether the ring buffer is full.
+    bool Push(uint64_t sample);
+
+    // Returns the mean of the values in the buffer.
+    double Mean() const;
+
+    // Clears the ring buffer while keeping the existing size.
+    void Clear();
+
+    // Resets the size of the buffer as well as clearing it.
+    void Reset(size_t new_size);
+
+    // Gets the oldest value inserted in the buffer. The buffer must be full
+    // (i.e. Push returned true) before this method can be called.
+    uint64_t OldestWhenFull() const {
+      PERFETTO_CHECK(filled_);
+      return buffer_[position_];
+    }
+
+    // Gets the newest value inserted in the buffer. The buffer must be full
+    // (i.e. Push returned true) before this method can be called.
+    uint64_t NewestWhenFull() const {
+      PERFETTO_CHECK(filled_);
+      return buffer_[(position_ + size_ - 1) % size_];
+    }
+
+    // Returns the size of the ring buffer.
+    size_t size() const { return size_; }
+
+   private:
+    bool filled_ = false;
+    size_t position_ = 0;
+    size_t size_ = 0;
+    std::unique_ptr<uint64_t[]> buffer_;
+  };
+
+  explicit Watchdog(const Watchdog&) = delete;
+  Watchdog& operator=(const Watchdog&) = delete;
+
+  // Main method for the watchdog thread.
+  void ThreadMain();
+
+  // Check each type of resource every |polling_interval_ms_| miillis.
+  void CheckMemory(uint64_t rss_bytes);
+  void CheckCpu(uint64_t cpu_time);
+
+  // Computes the time interval spanned by a given ring buffer with respect
+  // to |polling_interval_ms_|.
+  uint32_t WindowTimeForRingBuffer(const WindowedInterval& window);
+
+  const uint32_t polling_interval_ms_;
+  std::atomic<bool> enabled_{false};
+  std::thread thread_;
+  std::condition_variable exit_signal_;
+
+  // --- Begin lock-protected members ---
+
+  std::mutex mutex_;
+
+  uint64_t memory_limit_bytes_ = 0;
+  WindowedInterval memory_window_bytes_;
+
+  uint32_t cpu_limit_percentage_ = 0;
+  WindowedInterval cpu_window_time_ticks_;
+
+  // --- End lock-protected members ---
+};
+
+}  // namespace base
+}  // namespace perfetto
+#endif  // INCLUDE_PERFETTO_BASE_WATCHDOG_POSIX_H_
diff --git a/include/perfetto/base/weak_ptr.h b/include/perfetto/base/weak_ptr.h
new file mode 100644
index 0000000..369b70e
--- /dev/null
+++ b/include/perfetto/base/weak_ptr.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_BASE_WEAK_PTR_H_
+#define INCLUDE_PERFETTO_BASE_WEAK_PTR_H_
+
+#include "perfetto/base/thread_checker.h"
+
+#include <memory>
+
+namespace perfetto {
+namespace base {
+
+// A simple WeakPtr for single-threaded cases.
+// Generally keep the WeakPtrFactory as last fields in classes: it makes the
+// WeakPtr(s) invalidate as first thing in the class dtor.
+// Usage:
+// class MyClass {
+//  MyClass() : weak_factory_(this) {}
+//  WeakPtr<MyClass> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
+//
+// private:
+//  WeakPtrFactory<MyClass> weak_factory_;
+// }
+//
+// int main() {
+//  std::unique_ptr<MyClass> foo(new MyClass);
+//  auto wptr = foo.GetWeakPtr();
+//  ASSERT_TRUE(wptr);
+//  ASSERT_EQ(foo.get(), wptr->get());
+//  foo.reset();
+//  ASSERT_FALSE(wptr);
+//  ASSERT_EQ(nullptr, wptr->get());
+// }
+
+template <typename T>
+class WeakPtrFactory;  // Forward declaration, defined below.
+
+template <typename T>
+class WeakPtr {
+ public:
+  WeakPtr() {}
+  WeakPtr(const WeakPtr&) = default;
+  WeakPtr& operator=(const WeakPtr&) = default;
+  WeakPtr(WeakPtr&&) = default;
+  WeakPtr& operator=(WeakPtr&&) = default;
+
+  T* get() const {
+    PERFETTO_DCHECK_THREAD(thread_checker);
+    return handle_ ? *handle_.get() : nullptr;
+  }
+  T* operator->() const { return get(); }
+  T& operator*() const { return *get(); }
+
+  explicit operator bool() const { return !!get(); }
+
+ private:
+  friend class WeakPtrFactory<T>;
+  explicit WeakPtr(const std::shared_ptr<T*>& handle) : handle_(handle) {}
+
+  std::shared_ptr<T*> handle_;
+  PERFETTO_THREAD_CHECKER(thread_checker)
+};
+
+template <typename T>
+class WeakPtrFactory {
+ public:
+  explicit WeakPtrFactory(T* owner)
+      : weak_ptr_(std::shared_ptr<T*>(new T* {owner})) {
+    PERFETTO_DCHECK_THREAD(thread_checker);
+  }
+
+  ~WeakPtrFactory() {
+    PERFETTO_DCHECK_THREAD(thread_checker);
+    *(weak_ptr_.handle_.get()) = nullptr;
+  }
+
+  // Can be safely called on any thread, since it simply copies |weak_ptr_|.
+  // Note that any accesses to the returned pointer need to be made on the
+  // thread that created the factory.
+  WeakPtr<T> GetWeakPtr() const { return weak_ptr_; }
+
+ private:
+  WeakPtrFactory(const WeakPtrFactory&) = delete;
+  WeakPtrFactory& operator=(const WeakPtrFactory&) = delete;
+
+  WeakPtr<T> weak_ptr_;
+  PERFETTO_THREAD_CHECKER(thread_checker)
+};
+
+}  // namespace base
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_BASE_WEAK_PTR_H_
diff --git a/include/perfetto/ext/base/BUILD.gn b/include/perfetto/ext/base/BUILD.gn
deleted file mode 100644
index db82b08..0000000
--- a/include/perfetto/ext/base/BUILD.gn
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../../../gn/perfetto.gni")
-
-source_set("base") {
-  sources = [
-    "circular_queue.h",
-    "container_annotations.h",
-    "event_fd.h",
-    "file_utils.h",
-    "hash.h",
-    "lookup_set.h",
-    "metatrace.h",
-    "metatrace_events.h",
-    "no_destructor.h",
-    "optional.h",
-    "paged_memory.h",
-    "pipe.h",
-    "proc_utils.h",
-    "scoped_file.h",
-    "small_set.h",
-    "string_splitter.h",
-    "string_utils.h",
-    "string_view.h",
-    "string_writer.h",
-    "temp_file.h",
-    "thread_annotations.h",
-    "thread_checker.h",
-    "thread_task_runner.h",
-    "thread_utils.h",
-    "unix_task_runner.h",
-    "utils.h",
-    "uuid.h",
-    "waitable_event.h",
-    "watchdog.h",
-    "watchdog_noop.h",
-    "watchdog_posix.h",
-    "weak_ptr.h",
-  ]
-  if (enable_perfetto_ipc) {
-    sources += [ "unix_socket.h" ]
-  }
-  public_configs = [ "../../../../gn:asan_instrumentation" ]
-  public_deps = [
-    "../../base",
-  ]
-}
diff --git a/include/perfetto/ext/base/circular_queue.h b/include/perfetto/ext/base/circular_queue.h
deleted file mode 100644
index 72f14d1..0000000
--- a/include/perfetto/ext/base/circular_queue.h
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_EXT_BASE_CIRCULAR_QUEUE_H_
-#define INCLUDE_PERFETTO_EXT_BASE_CIRCULAR_QUEUE_H_
-
-#include <stdint.h>
-#include <iterator>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
-
-namespace perfetto {
-namespace base {
-
-// CircularQueue is a push-back-only / pop-front-only queue with the following
-// characteristics:
-// - The storage is based on a flat circular buffer. Beginning and end wrap
-//   as necessary, to keep pushes and pops O(1) as long as capacity expansion is
-//   not required.
-// - Capacity is automatically expanded like in a std::vector. Expansion has a
-//   O(N) cost.
-// - It allows random access, allowing in-place std::sort.
-// - Iterators are not stable. Mutating the container invalidates all iterators.
-// - It doesn't bother with const-correctness.
-//
-// Implementation details:
-// Internally, |begin|, |end| and iterators use 64-bit monotonic indexes, which
-// are incremented as if the queue was backed by unlimited storage.
-// Even assuming that elements are inserted and removed every nanosecond, 64 bit
-// is enough for 584 years.
-// Wrapping happens only when addressing elements in the underlying circular
-// storage. This limits the complexity and avoiding dealing with modular
-// arithmetic all over the places.
-template <class T>
-class CircularQueue {
- public:
-  class Iterator {
-   public:
-    using difference_type = ptrdiff_t;
-    using value_type = T;
-    using pointer = const T*;
-    using reference = const T&;
-    using iterator_category = std::random_access_iterator_tag;
-
-    Iterator(CircularQueue* queue, uint64_t pos, uint32_t generation)
-        : queue_(queue),
-          pos_(pos)
-#if PERFETTO_DCHECK_IS_ON()
-          ,
-          generation_(generation)
-#endif
-    {
-      ignore_result(generation);
-    }
-
-    T* operator->() {
-#if PERFETTO_DCHECK_IS_ON()
-      PERFETTO_DCHECK(generation_ == queue_->generation());
-#endif
-      return queue_->Get(pos_);
-    }
-
-    T& operator*() { return *(operator->()); }
-
-    const value_type& operator[](difference_type i) const {
-      return *(*this + i);
-    }
-
-    Iterator& operator++() {
-      Add(1);
-      return *this;
-    }
-
-    Iterator operator++(int) {
-      Iterator ret = *this;
-      Add(1);
-      return ret;
-    }
-
-    Iterator& operator--() {
-      Add(-1);
-      return *this;
-    }
-
-    Iterator operator--(int) {
-      Iterator ret = *this;
-      Add(-1);
-      return ret;
-    }
-
-    friend Iterator operator+(const Iterator& iter, difference_type offset) {
-      Iterator ret = iter;
-      ret.Add(offset);
-      return ret;
-    }
-
-    Iterator& operator+=(difference_type offset) {
-      Add(offset);
-      return *this;
-    }
-
-    friend Iterator operator-(const Iterator& iter, difference_type offset) {
-      Iterator ret = iter;
-      ret.Add(-offset);
-      return ret;
-    }
-
-    Iterator& operator-=(difference_type offset) {
-      Add(-offset);
-      return *this;
-    }
-
-    friend ptrdiff_t operator-(const Iterator& lhs, const Iterator& rhs) {
-      return static_cast<ptrdiff_t>(lhs.pos_) -
-             static_cast<ptrdiff_t>(rhs.pos_);
-    }
-
-    friend bool operator==(const Iterator& lhs, const Iterator& rhs) {
-      return lhs.pos_ == rhs.pos_;
-    }
-
-    friend bool operator!=(const Iterator& lhs, const Iterator& rhs) {
-      return lhs.pos_ != rhs.pos_;
-    }
-
-    friend bool operator<(const Iterator& lhs, const Iterator& rhs) {
-      return lhs.pos_ < rhs.pos_;
-    }
-
-    friend bool operator<=(const Iterator& lhs, const Iterator& rhs) {
-      return lhs.pos_ <= rhs.pos_;
-    }
-
-    friend bool operator>(const Iterator& lhs, const Iterator& rhs) {
-      return lhs.pos_ > rhs.pos_;
-    }
-
-    friend bool operator>=(const Iterator& lhs, const Iterator& rhs) {
-      return lhs.pos_ >= rhs.pos_;
-    }
-
-   private:
-    inline void Add(difference_type offset) {
-      pos_ = static_cast<uint64_t>(static_cast<difference_type>(pos_) + offset);
-      PERFETTO_DCHECK(pos_ <= queue_->end_);
-    }
-
-    CircularQueue* queue_;
-    uint64_t pos_;
-
-#if PERFETTO_DCHECK_IS_ON()
-    uint32_t generation_;
-#endif
-  };
-
-  CircularQueue(size_t initial_capacity = 1024) { Grow(initial_capacity); }
-
-  CircularQueue(CircularQueue&& other) noexcept {
-    // Copy all fields using the (private) default copy assignment operator.
-    *this = other;
-    increment_generation();
-    new (&other) CircularQueue();  // Reset the old queue so it's still usable.
-  }
-
-  CircularQueue& operator=(CircularQueue&& other) {
-    this->~CircularQueue();                      // Destroy the current state.
-    new (this) CircularQueue(std::move(other));  // Use the move ctor above.
-    return *this;
-  }
-
-  ~CircularQueue() {
-    if (!entries_) {
-      PERFETTO_DCHECK(empty());
-      return;
-    }
-    erase_front(size());  // Invoke destructors on all alive entries.
-    PERFETTO_DCHECK(empty());
-    free(entries_);
-  }
-
-  template <typename... Args>
-  void emplace_back(Args&&... args) {
-    increment_generation();
-    if (PERFETTO_UNLIKELY(size() >= capacity_))
-      Grow();
-    T* slot = Get(end_++);
-    new (slot) T(std::forward<Args>(args)...);
-  }
-
-  void erase_front(size_t n) {
-    increment_generation();
-    for (; n && (begin_ < end_); --n) {
-      Get(begin_)->~T();
-      begin_++;  // This needs to be its own statement, Get() checks begin_.
-    }
-  }
-
-  void pop_front() { erase_front(1); }
-
-  T& at(size_t idx) {
-    PERFETTO_DCHECK(idx < size());
-    return *Get(begin_ + idx);
-  }
-
-  Iterator begin() { return Iterator(this, begin_, generation()); }
-  Iterator end() { return Iterator(this, end_, generation()); }
-  T& front() { return *begin(); }
-  T& back() { return *(end() - 1); }
-
-  bool empty() const { return size() == 0; }
-
-  size_t size() const {
-    PERFETTO_DCHECK(end_ - begin_ <= capacity_);
-    return static_cast<size_t>(end_ - begin_);
-  }
-
-  size_t capacity() const { return capacity_; }
-
-#if PERFETTO_DCHECK_IS_ON()
-  uint32_t generation() const { return generation_; }
-  void increment_generation() { ++generation_; }
-#else
-  uint32_t generation() const { return 0; }
-  void increment_generation() {}
-#endif
-
- private:
-  CircularQueue(const CircularQueue&) = delete;
-  CircularQueue& operator=(const CircularQueue&) = default;
-
-  void Grow(size_t new_capacity = 0) {
-    // Capacity must be always a power of two. This allows Get() to use a simple
-    // bitwise-AND for handling the wrapping instead of a full division.
-    new_capacity = new_capacity ? new_capacity : capacity_ * 2;
-    PERFETTO_CHECK((new_capacity & (new_capacity - 1)) == 0);  // Must be pow2.
-
-    // On 32-bit systems this might hit the 4GB wall and overflow. We can't do
-    // anything other than crash in this case.
-    PERFETTO_CHECK(new_capacity > capacity_);
-    size_t malloc_size = new_capacity * sizeof(T);
-    PERFETTO_CHECK(malloc_size > new_capacity);
-    auto* new_vec = static_cast<T*>(malloc(malloc_size));
-
-    // Move all elements in the expanded array.
-    size_t new_size = 0;
-    for (uint64_t i = begin_; i < end_; i++)
-      new (&new_vec[new_size++]) T(std::move(*Get(i)));  // Placement move ctor.
-
-    // Even if all the elements are std::move()-d and likely empty, we are still
-    // required to call the dtor for them.
-    for (uint64_t i = begin_; i < end_; i++)
-      Get(i)->~T();
-    free(entries_);  // It's fine to free(nullptr) (for the ctor call case).
-
-    begin_ = 0;
-    end_ = new_size;
-    capacity_ = new_capacity;
-    entries_ = new_vec;
-  }
-
-  inline T* Get(uint64_t pos) {
-    PERFETTO_DCHECK(pos >= begin_ && pos < end_);
-    PERFETTO_DCHECK((capacity_ & (capacity_ - 1)) == 0);  // Must be a pow2.
-    auto index = static_cast<size_t>(pos & (capacity_ - 1));
-    return &entries_[index];
-  }
-
-  // Underlying storage. It's raw malloc-ed rather than being a unique_ptr<T[]>
-  // to allow having uninitialized entries inside it.
-  T* entries_ = nullptr;
-  size_t capacity_ = 0;  // Number of allocated slots (NOT bytes) in |entries_|.
-
-  // The |begin_| and |end_| indexes are monotonic and never wrap. Modular arith
-  // is used only when dereferencing entries in the vector.
-  uint64_t begin_ = 0;
-  uint64_t end_ = 0;
-
-// Generation is used in debug builds only for checking iterator validity.
-#if PERFETTO_DCHECK_IS_ON()
-  uint32_t generation_ = 0;
-#endif
-};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_CIRCULAR_QUEUE_H_
diff --git a/include/perfetto/ext/base/container_annotations.h b/include/perfetto/ext/base/container_annotations.h
deleted file mode 100644
index 183e6e0..0000000
--- a/include/perfetto/ext/base/container_annotations.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_BASE_CONTAINER_ANNOTATIONS_H_
-#define INCLUDE_PERFETTO_EXT_BASE_CONTAINER_ANNOTATIONS_H_
-
-#include "perfetto/base/build_config.h"
-
-// Windows ASAN doesn't currently support these annotations.
-#if defined(ADDRESS_SANITIZER) && !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
-    !defined(ADDRESS_SANITIZER_WITHOUT_INSTRUMENTATION)
-
-#define ANNOTATE_NEW_BUFFER(buffer, capacity, new_size)                      \
-  if (buffer) {                                                              \
-    __sanitizer_annotate_contiguous_container(buffer, (buffer) + (capacity), \
-                                              (buffer) + (capacity),         \
-                                              (buffer) + (new_size));        \
-  }
-#define ANNOTATE_DELETE_BUFFER(buffer, capacity, old_size)                   \
-  if (buffer) {                                                              \
-    __sanitizer_annotate_contiguous_container(buffer, (buffer) + (capacity), \
-                                              (buffer) + (old_size),         \
-                                              (buffer) + (capacity));        \
-  }
-#define ANNOTATE_CHANGE_SIZE(buffer, capacity, old_size, new_size)           \
-  if (buffer) {                                                              \
-    __sanitizer_annotate_contiguous_container(buffer, (buffer) + (capacity), \
-                                              (buffer) + (old_size),         \
-                                              (buffer) + (new_size));        \
-  }
-#define ANNOTATE_CHANGE_CAPACITY(buffer, old_capacity, buffer_size, \
-                                 new_capacity)                      \
-  ANNOTATE_DELETE_BUFFER(buffer, old_capacity, buffer_size);        \
-  ANNOTATE_NEW_BUFFER(buffer, new_capacity, buffer_size);
-// Annotations require buffers to begin on an 8-byte boundary.
-#else  // defined(ADDRESS_SANITIZER)
-#define ANNOTATE_NEW_BUFFER(buffer, capacity, new_size)
-#define ANNOTATE_DELETE_BUFFER(buffer, capacity, old_size)
-#define ANNOTATE_CHANGE_SIZE(buffer, capacity, old_size, new_size)
-#define ANNOTATE_CHANGE_CAPACITY(buffer, old_capacity, buffer_size, \
-                                 new_capacity)
-#endif  // defined(ADDRESS_SANITIZER)
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_CONTAINER_ANNOTATIONS_H_
diff --git a/include/perfetto/ext/base/event_fd.h b/include/perfetto/ext/base/event_fd.h
deleted file mode 100644
index 9e1715b..0000000
--- a/include/perfetto/ext/base/event_fd.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_BASE_EVENT_FD_H_
-#define INCLUDE_PERFETTO_EXT_BASE_EVENT_FD_H_
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/scoped_file.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-#define PERFETTO_USE_EVENTFD() 1
-#else
-#define PERFETTO_USE_EVENTFD() 0
-#endif
-
-namespace perfetto {
-namespace base {
-
-// A waitable event that can be used with poll/select.
-// This is really a wrapper around eventfd_create with a pipe-based fallback
-// for other platforms where eventfd is not supported.
-class EventFd {
- public:
-  EventFd();
-  ~EventFd();
-  EventFd(EventFd&&) noexcept = default;
-  EventFd& operator=(EventFd&&) = default;
-
-  // The non-blocking file descriptor that can be polled to wait for the event.
-  int fd() const { return fd_.get(); }
-
-  // Can be called from any thread.
-  void Notify();
-
-  // Can be called from any thread. If more Notify() are queued a Clear() call
-  // can clear all of them (up to 16 per call).
-  void Clear();
-
- private:
-  // The eventfd, when eventfd is supported, otherwise this is the read end of
-  // the pipe for fallback mode.
-  ScopedFile fd_;
-
-#if !PERFETTO_USE_EVENTFD()
-  // The write end of the wakeup pipe.
-  ScopedFile write_fd_;
-#endif
-};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_EVENT_FD_H_
diff --git a/include/perfetto/ext/base/file_utils.h b/include/perfetto/ext/base/file_utils.h
deleted file mode 100644
index 9ff03b1..0000000
--- a/include/perfetto/ext/base/file_utils.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_BASE_FILE_UTILS_H_
-#define INCLUDE_PERFETTO_EXT_BASE_FILE_UTILS_H_
-
-#include <stddef.h>
-
-#include <string>
-
-#include "perfetto/ext/base/utils.h"
-
-namespace perfetto {
-namespace base {
-
-bool ReadFileDescriptor(int fd, std::string* out);
-bool ReadFileStream(FILE* f, std::string* out);
-bool ReadFile(const std::string& path, std::string* out);
-
-// Call write until all data is written or an error is detected.
-//
-// man 2 write:
-//   If a write() is interrupted by a signal handler before any bytes are
-//   written, then the call fails with the error EINTR; if it is
-//   interrupted after at least one byte has been written, the call
-//   succeeds, and returns the number of bytes written.
-ssize_t WriteAll(int fd, const void* buf, size_t count);
-
-bool FlushFile(int fd);
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_FILE_UTILS_H_
diff --git a/include/perfetto/ext/base/hash.h b/include/perfetto/ext/base/hash.h
deleted file mode 100644
index 87b1a54..0000000
--- a/include/perfetto/ext/base/hash.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_EXT_BASE_HASH_H_
-#define INCLUDE_PERFETTO_EXT_BASE_HASH_H_
-
-#include <stddef.h>
-#include <stdint.h>
-#include <type_traits>
-
-namespace perfetto {
-namespace base {
-
-// A helper class which computes a 64-bit hash of the input data.
-// The algorithm used is FNV-1a as it is fast and easy to implement and has
-// relatively few collisions.
-// WARNING: This hash function should not be used for any cryptographic purpose.
-class Hash {
- public:
-  // Creates an empty hash object
-  Hash() {}
-
-  // Hashes a numeric value.
-  template <typename T,
-            typename std::enable_if<std::is_arithmetic<T>::value>* = nullptr>
-  void Update(T data) {
-    Update(reinterpret_cast<const char*>(&data), sizeof(data));
-  }
-
-  // Hashes a byte array.
-  void Update(const char* data, size_t size) {
-    for (size_t i = 0; i < size; i++) {
-      result_ ^= static_cast<uint8_t>(data[i]);
-      result_ *= kFnv1a64Prime;
-    }
-  }
-
-  uint64_t digest() { return result_; }
-
- private:
-  static constexpr uint64_t kFnv1a64OffsetBasis = 0xcbf29ce484222325;
-  static constexpr uint64_t kFnv1a64Prime = 0x100000001b3;
-
-  uint64_t result_ = kFnv1a64OffsetBasis;
-};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_HASH_H_
diff --git a/include/perfetto/ext/base/lookup_set.h b/include/perfetto/ext/base/lookup_set.h
deleted file mode 100644
index 11bff8e..0000000
--- a/include/perfetto/ext/base/lookup_set.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_BASE_LOOKUP_SET_H_
-#define INCLUDE_PERFETTO_EXT_BASE_LOOKUP_SET_H_
-
-#include <set>
-
-namespace perfetto {
-namespace base {
-
-// Set that allows lookup from const member of the object.
-template <typename T, typename U, U T::*p>
-class LookupSet {
- public:
-  T* Get(const U& key) {
-    // This will be nicer with C++14 transparent comparators.
-    // Then we will be able to look up by just the key using a sutiable
-    // comparator.
-    //
-    // For now we need to allow to construct a T from the key.
-    T node(key);
-    auto it = set_.find(node);
-    if (it == set_.end())
-      return nullptr;
-    return const_cast<T*>(&(*it));
-  }
-
-  template <typename... P>
-  T* Emplace(P&&... args) {
-    auto r = set_.emplace(std::forward<P>(args)...);
-    return const_cast<T*>(&(*r.first));
-  }
-
-  bool Remove(const T& child) { return set_.erase(child); }
-
-  static_assert(std::is_const<U>::value, "key must be const");
-
- private:
-  class Comparator {
-   public:
-    bool operator()(const T& one, const T& other) const {
-      return (&one)->*p < (&other)->*p;
-    }
-  };
-
-  std::set<T, Comparator> set_;
-};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_LOOKUP_SET_H_
diff --git a/include/perfetto/ext/base/metatrace.h b/include/perfetto/ext/base/metatrace.h
deleted file mode 100644
index 2c587c3..0000000
--- a/include/perfetto/ext/base/metatrace.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_EXT_BASE_METATRACE_H_
-#define INCLUDE_PERFETTO_EXT_BASE_METATRACE_H_
-
-#include <array>
-#include <atomic>
-#include <functional>
-#include <string>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/base/time.h"
-#include "perfetto/ext/base/metatrace_events.h"
-#include "perfetto/ext/base/thread_annotations.h"
-#include "perfetto/ext/base/thread_utils.h"
-#include "perfetto/ext/base/utils.h"
-
-// A facility to trace execution of the perfetto codebase itself.
-// The meta-tracing framework is organized into three layers:
-//
-// 1. A static ring-buffer in base/ (this file) that supports concurrent writes
-//    and a single reader.
-//    The responsibility of this layer is to store events and counters as
-//    efficiently as possible without re-entering any tracing code.
-//    This is really a static-storage-based ring-buffer based on a POD array.
-//    This layer does NOT deal with serializing the meta-trace buffer.
-//    It posts a task when it's half full and expects something outside of
-//    base/ to drain the ring-buffer and serialize it, eventually writing it
-//    into the trace itself, before it gets 100% full.
-//
-// 2. A class in tracing/core which takes care of serializing the meta-trace
-//    buffer into the trace using a TraceWriter. See metatrace_writer.h .
-//
-// 3. A data source in traced_probes that, when be enabled via the trace config,
-//    injects metatrace events into the trace. See metatrace_data_source.h .
-//
-// The available events and tags are defined in metatrace_events.h .
-
-namespace perfetto {
-
-namespace base {
-class TaskRunner;
-}  // namespace base
-
-namespace metatrace {
-
-// Meta-tracing is organized in "tags" that can be selectively enabled. This is
-// to enable meta-tracing only of one sub-system. This word has one "enabled"
-// bit for each tag. 0 -> meta-tracing off.
-extern std::atomic<uint32_t> g_enabled_tags;
-
-// Time of the Enable() call. Used as a reference for keeping delta timestmaps
-// in Record.
-extern std::atomic<uint64_t> g_enabled_timestamp;
-
-// Enables meta-tracing for one or more tags. Once enabled it will discard any
-// further Enable() calls and return false until disabled,
-// |read_task| is a closure that will be called enqueued |task_runner| when the
-// meta-tracing ring buffer is half full. The task is expected to read the ring
-// buffer using RingBuffer::GetReadIterator() and serialize the contents onto a
-// file or into the trace itself.
-// Must be called on the |task_runner| passed.
-// |task_runner| must have static lifetime.
-bool Enable(std::function<void()> read_task, base::TaskRunner*, uint32_t tags);
-
-// Disables meta-tracing.
-// Must be called on the same |task_runner| as Enable().
-void Disable();
-
-inline uint64_t TraceTimeNowNs() {
-  return static_cast<uint64_t>(base::GetBootTimeNs().count());
-}
-
-// Returns a relaxed view of whether metatracing is enabled for the given tag.
-// Useful for skipping unnecessary argument computation if metatracing is off.
-inline bool IsEnabled(uint32_t tag) {
-  auto enabled_tags = g_enabled_tags.load(std::memory_order_relaxed);
-  if (PERFETTO_LIKELY((enabled_tags & tag) == 0))
-    return false;
-  else
-    return true;
-}
-
-// Holds the data for a metatrace event or counter.
-struct Record {
-  static constexpr uint16_t kTypeMask = 0x8000;
-  static constexpr uint16_t kTypeCounter = 0x8000;
-  static constexpr uint16_t kTypeEvent = 0;
-
-  uint64_t timestamp_ns() const {
-    auto base_ns = g_enabled_timestamp.load(std::memory_order_relaxed);
-    PERFETTO_DCHECK(base_ns);
-    return base_ns + ((static_cast<uint64_t>(timestamp_ns_high) << 32) |
-                      timestamp_ns_low);
-  }
-
-  void set_timestamp(uint64_t ts) {
-    auto t_start = g_enabled_timestamp.load(std::memory_order_relaxed);
-    uint64_t diff = ts - t_start;
-    PERFETTO_DCHECK(diff < (1ull << 48));
-    timestamp_ns_low = static_cast<uint32_t>(diff);
-    timestamp_ns_high = static_cast<uint16_t>(diff >> 32);
-  }
-
-  // We can't just memset() this class because on MSVC std::atomic<> is not
-  // trivially constructible anymore. Also std::atomic<> has a deleted copy
-  // constructor so we cant just do "*this = Record()" either.
-  // See http://bit.ly/339Jlzd .
-  void clear() {
-    this->~Record();
-    new (this) Record();
-  }
-
-  // This field holds the type (counter vs event) in the MSB and event ID (as
-  // defined in metatrace_events.h) in the lowest 15 bits. It is also used also
-  // as a linearization point: this is always written after all the other
-  // fields with a release-store. This is so the reader can determine whether it
-  // can safely process the other event fields after a load-acquire.
-  std::atomic<uint16_t> type_and_id{};
-
-  // Timestamp is stored as a 48-bits value diffed against g_enabled_timestamp.
-  // This gives us 78 hours from Enabled().
-  uint16_t timestamp_ns_high = 0;
-  uint32_t timestamp_ns_low = 0;
-
-  uint32_t thread_id = 0;
-
-  union {
-    // Only one of the two elements can be zero initialized, clang complains
-    // about "initializing multiple members of union" otherwise.
-    uint32_t duration_ns = 0;  // If type == event.
-    int32_t counter_value;  // If type == counter.
-  };
-};
-
-// Hold the meta-tracing data into a statically allocated array.
-// This class uses static storage (as opposite to being a singleton) to:
-// - Have the guarantee of always valid storage, so that meta-tracing can be
-//   safely used in any part of the codebase, including base/ itself.
-// - Avoid barriers that thread-safe static locals would require.
-class RingBuffer {
- public:
-  static constexpr size_t kCapacity = 4096;  // 4096 * 16 bytes = 64K.
-
-  // This iterator is not idempotent and will bump the read index in the buffer
-  // at the end of the reads. There can be only one reader at any time.
-  // Usage: for (auto it = RingBuffer::GetReadIterator(); it; ++it) { it->... }
-  class ReadIterator {
-   public:
-    ReadIterator(ReadIterator&& other) {
-      PERFETTO_DCHECK(other.valid_);
-      cur_ = other.cur_;
-      end_ = other.end_;
-      valid_ = other.valid_;
-      other.valid_ = false;
-    }
-
-    ~ReadIterator() {
-      if (!valid_)
-        return;
-      PERFETTO_DCHECK(cur_ >= RingBuffer::rd_index_);
-      PERFETTO_DCHECK(cur_ <= RingBuffer::wr_index_);
-      RingBuffer::rd_index_.store(cur_, std::memory_order_release);
-    }
-
-    explicit operator bool() const { return cur_ < end_; }
-    const Record* operator->() const { return RingBuffer::At(cur_); }
-    const Record& operator*() const { return *operator->(); }
-
-    // This is for ++it. it++ is deliberately not supported.
-    ReadIterator& operator++() {
-      PERFETTO_DCHECK(cur_ < end_);
-      // Once a record has been read, mark it as free clearing its type_and_id,
-      // so if we encounter it in another read iteration while being written
-      // we know it's not fully written yet.
-      // The memory_order_relaxed below is enough because:
-      // - The reader is single-threaded and doesn't re-read the same records.
-      // - Before starting a read batch, the reader has an acquire barrier on
-      //   |rd_index_|.
-      // - After terminating a read batch, the ~ReadIterator dtor updates the
-      //   |rd_index_| with a release-store.
-      // - Reader and writer are typically kCapacity/2 apart. So unless an
-      //   overrun happens a writer won't reuse a newly released record any time
-      //   soon. If an overrun happens, everything is busted regardless.
-      At(cur_)->type_and_id.store(0, std::memory_order_relaxed);
-      ++cur_;
-      return *this;
-    }
-
-   private:
-    friend class RingBuffer;
-    ReadIterator(uint64_t begin, uint64_t end)
-        : cur_(begin), end_(end), valid_(true) {}
-    ReadIterator& operator=(const ReadIterator&) = delete;
-    ReadIterator(const ReadIterator&) = delete;
-
-    uint64_t cur_;
-    uint64_t end_;
-    bool valid_;
-  };
-
-  static Record* At(uint64_t index) {
-    // Doesn't really have to be pow2, but if not the compiler will emit
-    // arithmetic operations to compute the modulo instead of a bitwise AND.
-    static_assert(!(kCapacity & (kCapacity - 1)), "kCapacity must be pow2");
-    PERFETTO_DCHECK(index >= rd_index_);
-    PERFETTO_DCHECK(index <= wr_index_);
-    return &records_[index % kCapacity];
-  }
-
-  // Must be called on the same task runner passed to Enable()
-  static ReadIterator GetReadIterator() {
-    PERFETTO_DCHECK(RingBuffer::IsOnValidTaskRunner());
-    return ReadIterator(rd_index_.load(std::memory_order_acquire),
-                        wr_index_.load(std::memory_order_acquire));
-  }
-
-  static Record* AppendNewRecord();
-  static void Reset();
-
-  static bool has_overruns() {
-    return has_overruns_.load(std::memory_order_acquire);
-  }
-
-  // Can temporarily return a value >= kCapacity but is eventually consistent.
-  // This would happen in case of overruns until threads hit the --wr_index_
-  // in AppendNewRecord().
-  static uint64_t GetSizeForTesting() {
-    auto wr_index = wr_index_.load(std::memory_order_relaxed);
-    auto rd_index = rd_index_.load(std::memory_order_relaxed);
-    PERFETTO_DCHECK(wr_index >= rd_index);
-    return wr_index - rd_index;
-  }
-
- private:
-  friend class ReadIterator;
-
-  // Returns true if the caller is on the task runner passed to Enable().
-  // Used only for DCHECKs.
-  static bool IsOnValidTaskRunner();
-
-  static std::array<Record, kCapacity> records_;
-  static std::atomic<bool> read_task_queued_;
-  static std::atomic<uint64_t> wr_index_;
-  static std::atomic<uint64_t> rd_index_;
-  static std::atomic<bool> has_overruns_;
-  static Record bankruptcy_record_;  // Used in case of overruns.
-};
-
-inline void TraceCounter(uint32_t tag, uint16_t id, int32_t value) {
-  // memory_order_relaxed is okay because the storage has static lifetime.
-  // It is safe to accidentally log an event soon after disabling.
-  auto enabled_tags = g_enabled_tags.load(std::memory_order_relaxed);
-  if (PERFETTO_LIKELY((enabled_tags & tag) == 0))
-    return;
-  Record* record = RingBuffer::AppendNewRecord();
-  record->thread_id = static_cast<uint32_t>(base::GetThreadId());
-  record->set_timestamp(TraceTimeNowNs());
-  record->counter_value = value;
-  record->type_and_id.store(Record::kTypeCounter | id,
-                            std::memory_order_release);
-}
-
-class ScopedEvent {
- public:
-  ScopedEvent(uint32_t tag, uint16_t event_id) {
-    auto enabled_tags = g_enabled_tags.load(std::memory_order_relaxed);
-    if (PERFETTO_LIKELY((enabled_tags & tag) == 0))
-      return;
-    event_id_ = event_id;
-    record_ = RingBuffer::AppendNewRecord();
-    record_->thread_id = static_cast<uint32_t>(base::GetThreadId());
-    record_->set_timestamp(TraceTimeNowNs());
-  }
-
-  ~ScopedEvent() {
-    if (PERFETTO_LIKELY(!record_))
-      return;
-    auto now = TraceTimeNowNs();
-    record_->duration_ns = static_cast<uint32_t>(now - record_->timestamp_ns());
-    record_->type_and_id.store(Record::kTypeEvent | event_id_,
-                               std::memory_order_release);
-  }
-
- private:
-  Record* record_ = nullptr;
-  uint16_t event_id_ = 0;
-  ScopedEvent(const ScopedEvent&) = delete;
-  ScopedEvent& operator=(const ScopedEvent&) = delete;
-};
-
-// Boilerplate to derive a unique variable name for the event.
-#define PERFETTO_METATRACE_UID2(a, b) a##b
-#define PERFETTO_METATRACE_UID(x) PERFETTO_METATRACE_UID2(metatrace_, x)
-
-#define PERFETTO_METATRACE_SCOPED(TAG, ID)                                \
-  ::perfetto::metatrace::ScopedEvent PERFETTO_METATRACE_UID(__COUNTER__)( \
-      ::perfetto::metatrace::TAG, ::perfetto::metatrace::ID)
-
-#define PERFETTO_METATRACE_COUNTER(TAG, ID, VALUE)                \
-  ::perfetto::metatrace::TraceCounter(::perfetto::metatrace::TAG, \
-                                      ::perfetto::metatrace::ID,  \
-                                      static_cast<int32_t>(VALUE))
-
-}  // namespace metatrace
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_METATRACE_H_
diff --git a/include/perfetto/ext/base/metatrace_events.h b/include/perfetto/ext/base/metatrace_events.h
deleted file mode 100644
index e1d8b9c..0000000
--- a/include/perfetto/ext/base/metatrace_events.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_EXT_BASE_METATRACE_EVENTS_H_
-#define INCLUDE_PERFETTO_EXT_BASE_METATRACE_EVENTS_H_
-
-#include <stdint.h>
-
-namespace perfetto {
-namespace metatrace {
-
-enum Tags : uint32_t {
-  TAG_NONE = 0,
-  TAG_ANY = uint32_t(-1),
-  TAG_FTRACE = 1 << 0,
-  TAG_PROC_POLLERS = 1 << 1,
-  TAG_TRACE_WRITER = 1 << 2,
-  TAG_TRACE_SERVICE = 1 << 3,
-};
-
-// The macros below generate matching enums and arrays of string literals.
-// This is to avoid maintaining string maps manually.
-
-// clang-format off
-
-// DO NOT remove or reshuffle items in this list, only append. The ID of these
-// events are an ABI, the trace processor relies on these to open old traces.
-#define PERFETTO_METATRACE_EVENTS(F) \
-  F(EVENT_ZERO_UNUSED), \
-  F(FTRACE_CPU_READER_READ), /*unused*/ \
-  F(FTRACE_DRAIN_CPUS), /*unused*/ \
-  F(FTRACE_UNBLOCK_READERS), /*unused*/ \
-  F(FTRACE_CPU_READ_NONBLOCK), /*unused*/ \
-  F(FTRACE_CPU_READ_BLOCK), /*unused*/ \
-  F(FTRACE_CPU_SPLICE_NONBLOCK), /*unused*/ \
-  F(FTRACE_CPU_SPLICE_BLOCK), /*unused*/ \
-  F(FTRACE_CPU_WAIT_CMD), /*unused*/ \
-  F(FTRACE_CPU_RUN_CYCLE), /*unused*/ \
-  F(FTRACE_CPU_FLUSH), \
-  F(FTRACE_CPU_DRAIN), /*unused*/ \
-  F(READ_SYS_STATS), \
-  F(PS_WRITE_ALL_PROCESSES), \
-  F(PS_ON_PIDS), \
-  F(PS_ON_RENAME_PIDS), \
-  F(PS_WRITE_ALL_PROCESS_STATS), \
-  F(TRACE_WRITER_COMMIT_STARTUP_WRITER_BATCH), \
-  F(FTRACE_READ_TICK), \
-  F(FTRACE_CPU_READ_CYCLE), \
-  F(FTRACE_CPU_READ_BATCH)
-
-// Append only, see above.
-//
-// FTRACE_SERVICE_COMMIT_DATA is a bit-packed representation of an event, see
-// tracing_service_impl.cc for the format.
-//
-#define PERFETTO_METATRACE_COUNTERS(F) \
-  F(COUNTER_ZERO_UNUSED),\
-  F(FTRACE_PAGES_DRAINED), \
-  F(PS_PIDS_SCANNED), \
-  F(TRACE_SERVICE_COMMIT_DATA)
-
-// clang-format on
-
-#define PERFETTO_METATRACE_IDENTITY(name) name
-#define PERFETTO_METATRACE_TOSTRING(name) #name
-
-enum Events : uint16_t {
-  PERFETTO_METATRACE_EVENTS(PERFETTO_METATRACE_IDENTITY),
-  EVENTS_MAX
-};
-constexpr char const* kEventNames[] = {
-    PERFETTO_METATRACE_EVENTS(PERFETTO_METATRACE_TOSTRING)};
-
-enum Counters : uint16_t {
-  PERFETTO_METATRACE_COUNTERS(PERFETTO_METATRACE_IDENTITY),
-  COUNTERS_MAX
-};
-constexpr char const* kCounterNames[] = {
-    PERFETTO_METATRACE_COUNTERS(PERFETTO_METATRACE_TOSTRING)};
-
-}  // namespace metatrace
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_METATRACE_EVENTS_H_
diff --git a/include/perfetto/ext/base/no_destructor.h b/include/perfetto/ext/base/no_destructor.h
deleted file mode 100644
index b4e72f2..0000000
--- a/include/perfetto/ext/base/no_destructor.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_EXT_BASE_NO_DESTRUCTOR_H_
-#define INCLUDE_PERFETTO_EXT_BASE_NO_DESTRUCTOR_H_
-
-#include <new>
-#include <utility>
-
-namespace perfetto {
-namespace base {
-
-// Wrapper that can hold an object of type T, without invoking the contained
-// object's destructor when being destroyed. Useful for creating statics while
-// avoiding static destructors.
-//
-// Stores the object inline, and therefore doesn't incur memory allocation and
-// pointer indirection overheads.
-//
-// Example of use:
-//
-//   const std::string& GetStr() {
-//     static base::NoDestructor<std::string> s("hello");
-//     return s.ref();
-//   }
-//
-template <typename T>
-class NoDestructor {
- public:
-  // Forward arguments to T's constructor. Note that this doesn't cover
-  // construction from initializer lists.
-  template <typename... Args>
-  explicit NoDestructor(Args&&... args) {
-    new (storage_) T(std::forward<Args>(args)...);
-  }
-
-  NoDestructor(const NoDestructor&) = delete;
-  NoDestructor& operator=(const NoDestructor&) = delete;
-  NoDestructor(NoDestructor&&) = delete;
-  NoDestructor& operator=(NoDestructor&&) = delete;
-
-  ~NoDestructor() = default;
-
-  /* To avoid type-punned pointer strict aliasing warnings on GCC6 and below
-   * these need to be split over two lines. If they are collapsed onto one line.
-   *   return reinterpret_cast<const T*>(storage_);
-   * The error fires.
-   */
-  const T& ref() const {
-    auto* const cast = reinterpret_cast<const T*>(storage_);
-    return *cast;
-  }
-  T& ref() {
-    auto* const cast = reinterpret_cast<T*>(storage_);
-    return *cast;
-  }
-
- private:
-  alignas(T) char storage_[sizeof(T)];
-};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_NO_DESTRUCTOR_H_
diff --git a/include/perfetto/ext/base/optional.h b/include/perfetto/ext/base/optional.h
deleted file mode 100644
index b093510..0000000
--- a/include/perfetto/ext/base/optional.h
+++ /dev/null
@@ -1,902 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_BASE_OPTIONAL_H_
-#define INCLUDE_PERFETTO_EXT_BASE_OPTIONAL_H_
-
-#include <functional>
-#include <type_traits>
-#include <utility>
-
-#include "perfetto/base/logging.h"
-
-namespace perfetto {
-namespace base {
-
-// Specification:
-// http://en.cppreference.com/w/cpp/utility/optional/in_place_t
-struct in_place_t {};
-
-// Specification:
-// http://en.cppreference.com/w/cpp/utility/optional/nullopt_t
-struct nullopt_t {
-  constexpr explicit nullopt_t(int) {}
-};
-
-// Specification:
-// http://en.cppreference.com/w/cpp/utility/optional/in_place
-constexpr in_place_t in_place = {};
-
-// Specification:
-// http://en.cppreference.com/w/cpp/utility/optional/nullopt
-constexpr nullopt_t nullopt(0);
-
-// Forward declaration, which is referred by following helpers.
-template <typename T>
-class Optional;
-
-namespace internal {
-
-template <typename T, bool = std::is_trivially_destructible<T>::value>
-struct OptionalStorageBase {
-  // Initializing |empty_| here instead of using default member initializing
-  // to avoid errors in g++ 4.8.
-  constexpr OptionalStorageBase() : empty_('\0') {}
-
-  template <class... Args>
-  constexpr explicit OptionalStorageBase(in_place_t, Args&&... args)
-      : is_populated_(true), value_(std::forward<Args>(args)...) {}
-
-  // When T is not trivially destructible we must call its
-  // destructor before deallocating its memory.
-  // Note that this hides the (implicitly declared) move constructor, which
-  // would be used for constexpr move constructor in OptionalStorage<T>.
-  // It is needed iff T is trivially move constructible. However, the current
-  // is_trivially_{copy,move}_constructible implementation requires
-  // is_trivially_destructible (which looks a bug, cf:
-  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452 and
-  // http://cplusplus.github.io/LWG/lwg-active.html#2116), so it is not
-  // necessary for this case at the moment. Please see also the destructor
-  // comment in "is_trivially_destructible = true" specialization below.
-  ~OptionalStorageBase() {
-    if (is_populated_)
-      value_.~T();
-  }
-
-  template <class... Args>
-  void Init(Args&&... args) {
-    PERFETTO_DCHECK(!is_populated_);
-    ::new (&value_) T(std::forward<Args>(args)...);
-    is_populated_ = true;
-  }
-
-  bool is_populated_ = false;
-  union {
-    // |empty_| exists so that the union will always be initialized, even when
-    // it doesn't contain a value. Union members must be initialized for the
-    // constructor to be 'constexpr'.
-    char empty_;
-    T value_;
-  };
-};
-
-template <typename T>
-struct OptionalStorageBase<T, true /* trivially destructible */> {
-  // Initializing |empty_| here instead of using default member initializing
-  // to avoid errors in g++ 4.8.
-  constexpr OptionalStorageBase() : empty_('\0') {}
-
-  template <class... Args>
-  constexpr explicit OptionalStorageBase(in_place_t, Args&&... args)
-      : is_populated_(true), value_(std::forward<Args>(args)...) {}
-
-  // When T is trivially destructible (i.e. its destructor does nothing) there
-  // is no need to call it. Implicitly defined destructor is trivial, because
-  // both members (bool and union containing only variants which are trivially
-  // destructible) are trivially destructible.
-  // Explicitly-defaulted destructor is also trivial, but do not use it here,
-  // because it hides the implicit move constructor. It is needed to implement
-  // constexpr move constructor in OptionalStorage iff T is trivially move
-  // constructible. Note that, if T is trivially move constructible, the move
-  // constructor of OptionalStorageBase<T> is also implicitly defined and it is
-  // trivially move constructor. If T is not trivially move constructible,
-  // "not declaring move constructor without destructor declaration" here means
-  // "delete move constructor", which works because any move constructor of
-  // OptionalStorage will not refer to it in that case.
-
-  template <class... Args>
-  void Init(Args&&... args) {
-    PERFETTO_DCHECK(!is_populated_);
-    ::new (&value_) T(std::forward<Args>(args)...);
-    is_populated_ = true;
-  }
-
-  bool is_populated_ = false;
-  union {
-    // |empty_| exists so that the union will always be initialized, even when
-    // it doesn't contain a value. Union members must be initialized for the
-    // constructor to be 'constexpr'.
-    char empty_;
-    T value_;
-  };
-};
-
-// Implement conditional constexpr copy and move constructors. These are
-// constexpr if is_trivially_{copy,move}_constructible<T>::value is true
-// respectively. If each is true, the corresponding constructor is defined as
-// "= default;", which generates a constexpr constructor (In this case,
-// the condition of constexpr-ness is satisfied because the base class also has
-// compiler generated constexpr {copy,move} constructors). Note that
-// placement-new is prohibited in constexpr.
-template <typename T, bool = std::is_trivially_copy_constructible<T>::value>
-struct OptionalStorage : OptionalStorageBase<T> {
-  // This is no trivially {copy,move} constructible case. Other cases are
-  // defined below as specializations.
-
-  // Accessing the members of template base class requires explicit
-  // declaration.
-  using OptionalStorageBase<T>::is_populated_;
-  using OptionalStorageBase<T>::value_;
-  using OptionalStorageBase<T>::Init;
-
-  // Inherit constructors (specifically, the in_place constructor).
-  using OptionalStorageBase<T>::OptionalStorageBase;
-
-  // User defined constructor deletes the default constructor.
-  // Define it explicitly.
-  OptionalStorage() = default;
-
-  OptionalStorage(const OptionalStorage& other) : OptionalStorageBase<T>() {
-    if (other.is_populated_)
-      Init(other.value_);
-  }
-
-  OptionalStorage(OptionalStorage&& other) noexcept(
-      std::is_nothrow_move_constructible<T>::value) {
-    if (other.is_populated_)
-      Init(std::move(other.value_));
-  }
-};
-
-template <typename T>
-struct OptionalStorage<T, true /* trivially copy constructible */>
-    : OptionalStorageBase<T> {
-  using OptionalStorageBase<T>::is_populated_;
-  using OptionalStorageBase<T>::value_;
-  using OptionalStorageBase<T>::Init;
-  using OptionalStorageBase<T>::OptionalStorageBase;
-
-  OptionalStorage() = default;
-  OptionalStorage(const OptionalStorage& other) = default;
-
-  OptionalStorage(OptionalStorage&& other) noexcept(
-      std::is_nothrow_move_constructible<T>::value) {
-    if (other.is_populated_)
-      Init(std::move(other.value_));
-  }
-};
-
-// Base class to support conditionally usable copy-/move- constructors
-// and assign operators.
-template <typename T>
-class OptionalBase {
-  // This class provides implementation rather than public API, so everything
-  // should be hidden. Often we use composition, but we cannot in this case
-  // because of C++ language restriction.
- protected:
-  constexpr OptionalBase() = default;
-  constexpr OptionalBase(const OptionalBase& other) = default;
-  constexpr OptionalBase(OptionalBase&& other) = default;
-
-  template <class... Args>
-  constexpr explicit OptionalBase(in_place_t, Args&&... args)
-      : storage_(in_place, std::forward<Args>(args)...) {}
-
-  // Implementation of converting constructors.
-  template <typename U>
-  explicit OptionalBase(const OptionalBase<U>& other) {
-    if (other.storage_.is_populated_)
-      storage_.Init(other.storage_.value_);
-  }
-
-  template <typename U>
-  explicit OptionalBase(OptionalBase<U>&& other) {
-    if (other.storage_.is_populated_)
-      storage_.Init(std::move(other.storage_.value_));
-  }
-
-  ~OptionalBase() = default;
-
-  OptionalBase& operator=(const OptionalBase& other) {
-    CopyAssign(other);
-    return *this;
-  }
-
-  OptionalBase& operator=(OptionalBase&& other) noexcept(
-      std::is_nothrow_move_assignable<T>::value&&
-          std::is_nothrow_move_constructible<T>::value) {
-    MoveAssign(std::move(other));
-    return *this;
-  }
-
-  template <typename U>
-  void CopyAssign(const OptionalBase<U>& other) {
-    if (other.storage_.is_populated_)
-      InitOrAssign(other.storage_.value_);
-    else
-      FreeIfNeeded();
-  }
-
-  template <typename U>
-  void MoveAssign(OptionalBase<U>&& other) {
-    if (other.storage_.is_populated_)
-      InitOrAssign(std::move(other.storage_.value_));
-    else
-      FreeIfNeeded();
-  }
-
-  template <typename U>
-  void InitOrAssign(U&& value) {
-    if (storage_.is_populated_)
-      storage_.value_ = std::forward<U>(value);
-    else
-      storage_.Init(std::forward<U>(value));
-  }
-
-  void FreeIfNeeded() {
-    if (!storage_.is_populated_)
-      return;
-    storage_.value_.~T();
-    storage_.is_populated_ = false;
-  }
-
-  // For implementing conversion, allow access to other typed OptionalBase
-  // class.
-  template <typename U>
-  friend class OptionalBase;
-
-  OptionalStorage<T> storage_;
-};
-
-// The following {Copy,Move}{Constructible,Assignable} structs are helpers to
-// implement constructor/assign-operator overloading. Specifically, if T is
-// is not movable but copyable, Optional<T>'s move constructor should not
-// participate in overload resolution. This inheritance trick implements that.
-template <bool is_copy_constructible>
-struct CopyConstructible {};
-
-template <>
-struct CopyConstructible<false> {
-  constexpr CopyConstructible() = default;
-  constexpr CopyConstructible(const CopyConstructible&) = delete;
-  constexpr CopyConstructible(CopyConstructible&&) = default;
-  CopyConstructible& operator=(const CopyConstructible&) = default;
-  CopyConstructible& operator=(CopyConstructible&&) = default;
-};
-
-template <bool is_move_constructible>
-struct MoveConstructible {};
-
-template <>
-struct MoveConstructible<false> {
-  constexpr MoveConstructible() = default;
-  constexpr MoveConstructible(const MoveConstructible&) = default;
-  constexpr MoveConstructible(MoveConstructible&&) = delete;
-  MoveConstructible& operator=(const MoveConstructible&) = default;
-  MoveConstructible& operator=(MoveConstructible&&) = default;
-};
-
-template <bool is_copy_assignable>
-struct CopyAssignable {};
-
-template <>
-struct CopyAssignable<false> {
-  constexpr CopyAssignable() = default;
-  constexpr CopyAssignable(const CopyAssignable&) = default;
-  constexpr CopyAssignable(CopyAssignable&&) = default;
-  CopyAssignable& operator=(const CopyAssignable&) = delete;
-  CopyAssignable& operator=(CopyAssignable&&) = default;
-};
-
-template <bool is_move_assignable>
-struct MoveAssignable {};
-
-template <>
-struct MoveAssignable<false> {
-  constexpr MoveAssignable() = default;
-  constexpr MoveAssignable(const MoveAssignable&) = default;
-  constexpr MoveAssignable(MoveAssignable&&) = default;
-  MoveAssignable& operator=(const MoveAssignable&) = default;
-  MoveAssignable& operator=(MoveAssignable&&) = delete;
-};
-
-// Helper to conditionally enable converting constructors and assign operators.
-template <typename T, typename U>
-struct IsConvertibleFromOptional
-    : std::integral_constant<
-          bool,
-          std::is_constructible<T, Optional<U>&>::value ||
-              std::is_constructible<T, const Optional<U>&>::value ||
-              std::is_constructible<T, Optional<U>&&>::value ||
-              std::is_constructible<T, const Optional<U>&&>::value ||
-              std::is_convertible<Optional<U>&, T>::value ||
-              std::is_convertible<const Optional<U>&, T>::value ||
-              std::is_convertible<Optional<U>&&, T>::value ||
-              std::is_convertible<const Optional<U>&&, T>::value> {};
-
-template <typename T, typename U>
-struct IsAssignableFromOptional
-    : std::integral_constant<
-          bool,
-          IsConvertibleFromOptional<T, U>::value ||
-              std::is_assignable<T&, Optional<U>&>::value ||
-              std::is_assignable<T&, const Optional<U>&>::value ||
-              std::is_assignable<T&, Optional<U>&&>::value ||
-              std::is_assignable<T&, const Optional<U>&&>::value> {};
-
-// Forward compatibility for C++17.
-// Introduce one more deeper nested namespace to avoid leaking using std::swap.
-namespace swappable_impl {
-using std::swap;
-
-struct IsSwappableImpl {
-  // Tests if swap can be called. Check<T&>(0) returns true_type iff swap is
-  // available for T. Otherwise, Check's overload resolution falls back to
-  // Check(...) declared below thanks to SFINAE, so returns false_type.
-  template <typename T>
-  static auto Check(int)
-      -> decltype(swap(std::declval<T>(), std::declval<T>()), std::true_type());
-
-  template <typename T>
-  static std::false_type Check(...);
-};
-}  // namespace swappable_impl
-
-template <typename T>
-struct IsSwappable : decltype(swappable_impl::IsSwappableImpl::Check<T&>(0)) {};
-
-// Forward compatibility for C++20.
-template <typename T>
-using RemoveCvRefT =
-    typename std::remove_cv<typename std::remove_reference<T>::type>::type;
-
-}  // namespace internal
-
-// On Windows, by default, empty-base class optimization does not work,
-// which means even if the base class is empty struct, it still consumes one
-// byte for its body. __declspec(empty_bases) enables the optimization.
-// cf)
-// https://blogs.msdn.microsoft.com/vcblog/2016/03/30/optimizing-the-layout-of-empty-base-classes-in-vs2015-update-2-3/
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
-    !PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC)
-#define OPTIONAL_DECLSPEC_EMPTY_BASES __declspec(empty_bases)
-#else
-#define OPTIONAL_DECLSPEC_EMPTY_BASES
-#endif
-
-// base::Optional is a Chromium version of the C++17 optional class:
-// std::optional documentation:
-// http://en.cppreference.com/w/cpp/utility/optional
-// Chromium documentation:
-// https://chromium.googlesource.com/chromium/src/+/master/docs/optional.md
-//
-// These are the differences between the specification and the implementation:
-// - Constructors do not use 'constexpr' as it is a C++14 extension.
-// - 'constexpr' might be missing in some places for reasons specified locally.
-// - No exceptions are thrown, because they are banned from Chromium.
-//   Marked noexcept for only move constructor and move assign operators.
-// - All the non-members are in the 'base' namespace instead of 'std'.
-//
-// Note that T cannot have a constructor T(Optional<T>) etc. Optional<T>
-// PERFETTO_CHECKs T's constructor (specifically via IsConvertibleFromOptional),
-// and in the PERFETTO_CHECK whether T can be constructible from Optional<T>,
-// which is recursive so it does not work. As of Feb 2018, std::optional C++17
-// implementation in both clang and gcc has same limitation. MSVC SFINAE looks
-// to have different behavior, but anyway it reports an error, too.
-//
-// This file is a modified version of optional.h from Chromium at revision
-// 5e71bd454e60511c1293c0c686544aaa76094424. The changes remove C++14/C++17
-// specific code and replace with C++11 counterparts.
-template <typename T>
-class OPTIONAL_DECLSPEC_EMPTY_BASES Optional
-    : public internal::OptionalBase<T>,
-      public internal::CopyConstructible<std::is_copy_constructible<T>::value>,
-      public internal::MoveConstructible<std::is_move_constructible<T>::value>,
-      public internal::CopyAssignable<std::is_copy_constructible<T>::value &&
-                                      std::is_copy_assignable<T>::value>,
-      public internal::MoveAssignable<std::is_move_constructible<T>::value &&
-                                      std::is_move_assignable<T>::value> {
- public:
-#undef OPTIONAL_DECLSPEC_EMPTY_BASES
-  using value_type = T;
-
-  // Defer default/copy/move constructor implementation to OptionalBase.
-  constexpr Optional() = default;
-  constexpr Optional(const Optional& other) = default;
-  constexpr Optional(Optional&& other) noexcept(
-      std::is_nothrow_move_constructible<T>::value) = default;
-
-  constexpr Optional(nullopt_t) {}  // NOLINT(runtime/explicit)
-
-  // Converting copy constructor. "explicit" only if
-  // std::is_convertible<const U&, T>::value is false. It is implemented by
-  // declaring two almost same constructors, but that condition in enable_if_t
-  // is different, so that either one is chosen, thanks to SFINAE.
-  template <typename U,
-            typename std::enable_if<
-                std::is_constructible<T, const U&>::value &&
-                    !internal::IsConvertibleFromOptional<T, U>::value &&
-                    std::is_convertible<const U&, T>::value,
-                bool>::type = false>
-  Optional(const Optional<U>& other) : internal::OptionalBase<T>(other) {}
-
-  template <typename U,
-            typename std::enable_if<
-                std::is_constructible<T, const U&>::value &&
-                    !internal::IsConvertibleFromOptional<T, U>::value &&
-                    !std::is_convertible<const U&, T>::value,
-                bool>::type = false>
-  explicit Optional(const Optional<U>& other)
-      : internal::OptionalBase<T>(other) {}
-
-  // Converting move constructor. Similar to converting copy constructor,
-  // declaring two (explicit and non-explicit) constructors.
-  template <typename U,
-            typename std::enable_if<
-                std::is_constructible<T, U&&>::value &&
-                    !internal::IsConvertibleFromOptional<T, U>::value &&
-                    std::is_convertible<U&&, T>::value,
-                bool>::type = false>
-  Optional(Optional<U>&& other) : internal::OptionalBase<T>(std::move(other)) {}
-
-  template <typename U,
-            typename std::enable_if<
-                std::is_constructible<T, U&&>::value &&
-                    !internal::IsConvertibleFromOptional<T, U>::value &&
-                    !std::is_convertible<U&&, T>::value,
-                bool>::type = false>
-  explicit Optional(Optional<U>&& other)
-      : internal::OptionalBase<T>(std::move(other)) {}
-
-  template <class... Args>
-  constexpr explicit Optional(in_place_t, Args&&... args)
-      : internal::OptionalBase<T>(in_place, std::forward<Args>(args)...) {}
-
-  template <class U,
-            class... Args,
-            class = typename std::enable_if<
-                std::is_constructible<value_type,
-                                      std::initializer_list<U>&,
-                                      Args...>::value>::type>
-  constexpr explicit Optional(in_place_t,
-                              std::initializer_list<U> il,
-                              Args&&... args)
-      : internal::OptionalBase<T>(in_place, il, std::forward<Args>(args)...) {}
-
-  // Forward value constructor. Similar to converting constructors,
-  // conditionally explicit.
-  template <
-      typename U = value_type,
-      typename std::enable_if<
-          std::is_constructible<T, U&&>::value &&
-              !std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value &&
-              !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
-              std::is_convertible<U&&, T>::value,
-          bool>::type = false>
-  constexpr Optional(U&& value)
-      : internal::OptionalBase<T>(in_place, std::forward<U>(value)) {}
-
-  template <
-      typename U = value_type,
-      typename std::enable_if<
-          std::is_constructible<T, U&&>::value &&
-              !std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value &&
-              !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
-              !std::is_convertible<U&&, T>::value,
-          bool>::type = false>
-  constexpr explicit Optional(U&& value)
-      : internal::OptionalBase<T>(in_place, std::forward<U>(value)) {}
-
-  ~Optional() = default;
-
-  // Defer copy-/move- assign operator implementation to OptionalBase.
-  Optional& operator=(const Optional& other) = default;
-  Optional& operator=(Optional&& other) noexcept(
-      std::is_nothrow_move_assignable<T>::value&&
-          std::is_nothrow_move_constructible<T>::value) = default;
-
-  Optional& operator=(nullopt_t) {
-    FreeIfNeeded();
-    return *this;
-  }
-
-  // Perfect-forwarded assignment.
-  template <typename U>
-  typename std::enable_if<
-      !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value &&
-          std::is_constructible<T, U>::value &&
-          std::is_assignable<T&, U>::value &&
-          (!std::is_scalar<T>::value ||
-           !std::is_same<typename std::decay<U>::type, T>::value),
-      Optional&>::type
-  operator=(U&& value) {
-    InitOrAssign(std::forward<U>(value));
-    return *this;
-  }
-
-  // Copy assign the state of other.
-  template <typename U>
-  typename std::enable_if<!internal::IsAssignableFromOptional<T, U>::value &&
-                              std::is_constructible<T, const U&>::value &&
-                              std::is_assignable<T&, const U&>::value,
-                          Optional&>::type
-  operator=(const Optional<U>& other) {
-    CopyAssign(other);
-    return *this;
-  }
-
-  // Move assign the state of other.
-  template <typename U>
-  typename std::enable_if<!internal::IsAssignableFromOptional<T, U>::value &&
-                              std::is_constructible<T, U>::value &&
-                              std::is_assignable<T&, U>::value,
-                          Optional&>::type
-  operator=(Optional<U>&& other) {
-    MoveAssign(std::move(other));
-    return *this;
-  }
-
-  const T* operator->() const {
-    PERFETTO_DCHECK(storage_.is_populated_);
-    return &storage_.value_;
-  }
-
-  T* operator->() {
-    PERFETTO_DCHECK(storage_.is_populated_);
-    return &storage_.value_;
-  }
-
-  const T& operator*() const& {
-    PERFETTO_DCHECK(storage_.is_populated_);
-    return storage_.value_;
-  }
-
-  T& operator*() & {
-    PERFETTO_DCHECK(storage_.is_populated_);
-    return storage_.value_;
-  }
-
-  const T&& operator*() const&& {
-    PERFETTO_DCHECK(storage_.is_populated_);
-    return std::move(storage_.value_);
-  }
-
-  T&& operator*() && {
-    PERFETTO_DCHECK(storage_.is_populated_);
-    return std::move(storage_.value_);
-  }
-
-  constexpr explicit operator bool() const { return storage_.is_populated_; }
-
-  constexpr bool has_value() const { return storage_.is_populated_; }
-
-  T& value() & {
-    PERFETTO_CHECK(storage_.is_populated_);
-    return storage_.value_;
-  }
-
-  const T& value() const& {
-    PERFETTO_CHECK(storage_.is_populated_);
-    return storage_.value_;
-  }
-
-  T&& value() && {
-    PERFETTO_CHECK(storage_.is_populated_);
-    return std::move(storage_.value_);
-  }
-
-  const T&& value() const&& {
-    PERFETTO_CHECK(storage_.is_populated_);
-    return std::move(storage_.value_);
-  }
-
-  template <class U>
-  constexpr T value_or(U&& default_value) const& {
-    static_assert(std::is_convertible<U, T>::value,
-                  "U must be convertible to T");
-    return storage_.is_populated_
-               ? storage_.value_
-               : static_cast<T>(std::forward<U>(default_value));
-  }
-
-  template <class U>
-  T value_or(U&& default_value) && {
-    static_assert(std::is_convertible<U, T>::value,
-                  "U must be convertible to T");
-    return storage_.is_populated_
-               ? std::move(storage_.value_)
-               : static_cast<T>(std::forward<U>(default_value));
-  }
-
-  void swap(Optional& other) {
-    if (!storage_.is_populated_ && !other.storage_.is_populated_)
-      return;
-
-    if (storage_.is_populated_ != other.storage_.is_populated_) {
-      if (storage_.is_populated_) {
-        other.storage_.Init(std::move(storage_.value_));
-        FreeIfNeeded();
-      } else {
-        storage_.Init(std::move(other.storage_.value_));
-        other.FreeIfNeeded();
-      }
-      return;
-    }
-
-    PERFETTO_DCHECK(storage_.is_populated_ && other.storage_.is_populated_);
-    using std::swap;
-    swap(**this, *other);
-  }
-
-  void reset() { FreeIfNeeded(); }
-
-  template <class... Args>
-  T& emplace(Args&&... args) {
-    FreeIfNeeded();
-    storage_.Init(std::forward<Args>(args)...);
-    return storage_.value_;
-  }
-
-  template <class U, class... Args>
-  typename std::enable_if<
-      std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value,
-      T&>::type
-  emplace(std::initializer_list<U> il, Args&&... args) {
-    FreeIfNeeded();
-    storage_.Init(il, std::forward<Args>(args)...);
-    return storage_.value_;
-  }
-
- private:
-  // Accessing template base class's protected member needs explicit
-  // declaration to do so.
-  using internal::OptionalBase<T>::CopyAssign;
-  using internal::OptionalBase<T>::FreeIfNeeded;
-  using internal::OptionalBase<T>::InitOrAssign;
-  using internal::OptionalBase<T>::MoveAssign;
-  using internal::OptionalBase<T>::storage_;
-};
-
-// Here after defines comparation operators. The definition follows
-// http://en.cppreference.com/w/cpp/utility/optional/operator_cmp
-// while bool() casting is replaced by has_value() to meet the chromium
-// style guide.
-template <class T, class U>
-bool operator==(const Optional<T>& lhs, const Optional<U>& rhs) {
-  if (lhs.has_value() != rhs.has_value())
-    return false;
-  if (!lhs.has_value())
-    return true;
-  return *lhs == *rhs;
-}
-
-template <class T, class U>
-bool operator!=(const Optional<T>& lhs, const Optional<U>& rhs) {
-  if (lhs.has_value() != rhs.has_value())
-    return true;
-  if (!lhs.has_value())
-    return false;
-  return *lhs != *rhs;
-}
-
-template <class T, class U>
-bool operator<(const Optional<T>& lhs, const Optional<U>& rhs) {
-  if (!rhs.has_value())
-    return false;
-  if (!lhs.has_value())
-    return true;
-  return *lhs < *rhs;
-}
-
-template <class T, class U>
-bool operator<=(const Optional<T>& lhs, const Optional<U>& rhs) {
-  if (!lhs.has_value())
-    return true;
-  if (!rhs.has_value())
-    return false;
-  return *lhs <= *rhs;
-}
-
-template <class T, class U>
-bool operator>(const Optional<T>& lhs, const Optional<U>& rhs) {
-  if (!lhs.has_value())
-    return false;
-  if (!rhs.has_value())
-    return true;
-  return *lhs > *rhs;
-}
-
-template <class T, class U>
-bool operator>=(const Optional<T>& lhs, const Optional<U>& rhs) {
-  if (!rhs.has_value())
-    return true;
-  if (!lhs.has_value())
-    return false;
-  return *lhs >= *rhs;
-}
-
-template <class T>
-constexpr bool operator==(const Optional<T>& opt, nullopt_t) {
-  return !opt;
-}
-
-template <class T>
-constexpr bool operator==(nullopt_t, const Optional<T>& opt) {
-  return !opt;
-}
-
-template <class T>
-constexpr bool operator!=(const Optional<T>& opt, nullopt_t) {
-  return opt.has_value();
-}
-
-template <class T>
-constexpr bool operator!=(nullopt_t, const Optional<T>& opt) {
-  return opt.has_value();
-}
-
-template <class T>
-constexpr bool operator<(const Optional<T>&, nullopt_t) {
-  return false;
-}
-
-template <class T>
-constexpr bool operator<(nullopt_t, const Optional<T>& opt) {
-  return opt.has_value();
-}
-
-template <class T>
-constexpr bool operator<=(const Optional<T>& opt, nullopt_t) {
-  return !opt;
-}
-
-template <class T>
-constexpr bool operator<=(nullopt_t, const Optional<T>&) {
-  return true;
-}
-
-template <class T>
-constexpr bool operator>(const Optional<T>& opt, nullopt_t) {
-  return opt.has_value();
-}
-
-template <class T>
-constexpr bool operator>(nullopt_t, const Optional<T>&) {
-  return false;
-}
-
-template <class T>
-constexpr bool operator>=(const Optional<T>&, nullopt_t) {
-  return true;
-}
-
-template <class T>
-constexpr bool operator>=(nullopt_t, const Optional<T>& opt) {
-  return !opt;
-}
-
-template <class T, class U>
-constexpr bool operator==(const Optional<T>& opt, const U& value) {
-  return opt.has_value() ? *opt == value : false;
-}
-
-template <class T, class U>
-constexpr bool operator==(const U& value, const Optional<T>& opt) {
-  return opt.has_value() ? value == *opt : false;
-}
-
-template <class T, class U>
-constexpr bool operator!=(const Optional<T>& opt, const U& value) {
-  return opt.has_value() ? *opt != value : true;
-}
-
-template <class T, class U>
-constexpr bool operator!=(const U& value, const Optional<T>& opt) {
-  return opt.has_value() ? value != *opt : true;
-}
-
-template <class T, class U>
-constexpr bool operator<(const Optional<T>& opt, const U& value) {
-  return opt.has_value() ? *opt < value : true;
-}
-
-template <class T, class U>
-constexpr bool operator<(const U& value, const Optional<T>& opt) {
-  return opt.has_value() ? value < *opt : false;
-}
-
-template <class T, class U>
-constexpr bool operator<=(const Optional<T>& opt, const U& value) {
-  return opt.has_value() ? *opt <= value : true;
-}
-
-template <class T, class U>
-constexpr bool operator<=(const U& value, const Optional<T>& opt) {
-  return opt.has_value() ? value <= *opt : false;
-}
-
-template <class T, class U>
-constexpr bool operator>(const Optional<T>& opt, const U& value) {
-  return opt.has_value() ? *opt > value : false;
-}
-
-template <class T, class U>
-constexpr bool operator>(const U& value, const Optional<T>& opt) {
-  return opt.has_value() ? value > *opt : true;
-}
-
-template <class T, class U>
-constexpr bool operator>=(const Optional<T>& opt, const U& value) {
-  return opt.has_value() ? *opt >= value : false;
-}
-
-template <class T, class U>
-constexpr bool operator>=(const U& value, const Optional<T>& opt) {
-  return opt.has_value() ? value >= *opt : true;
-}
-
-template <class T>
-constexpr Optional<typename std::decay<T>::type> make_optional(T&& value) {
-  return Optional<typename std::decay<T>::type>(std::forward<T>(value));
-}
-
-template <class T, class... Args>
-constexpr Optional<T> make_optional(Args&&... args) {
-  return Optional<T>(in_place, std::forward<Args>(args)...);
-}
-
-template <class T, class U, class... Args>
-constexpr Optional<T> make_optional(std::initializer_list<U> il,
-                                    Args&&... args) {
-  return Optional<T>(in_place, il, std::forward<Args>(args)...);
-}
-
-// Partial specialization for a function template is not allowed. Also, it is
-// not allowed to add overload function to std namespace, while it is allowed
-// to specialize the template in std. Thus, swap() (kind of) overloading is
-// defined in base namespace, instead.
-template <class T>
-typename std::enable_if<std::is_move_constructible<T>::value &&
-                        internal::IsSwappable<T>::value>::type
-swap(Optional<T>& lhs, Optional<T>& rhs) {
-  lhs.swap(rhs);
-}
-
-}  // namespace base
-}  // namespace perfetto
-
-namespace std {
-
-template <class T>
-struct hash<perfetto::base::Optional<T>> {
-  size_t operator()(const perfetto::base::Optional<T>& opt) const {
-    return opt == perfetto::base::nullopt ? 0 : std::hash<T>()(*opt);
-  }
-};
-
-}  // namespace std
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_OPTIONAL_H_
diff --git a/include/perfetto/ext/base/paged_memory.h b/include/perfetto/ext/base/paged_memory.h
deleted file mode 100644
index f0ed568..0000000
--- a/include/perfetto/ext/base/paged_memory.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_BASE_PAGED_MEMORY_H_
-#define INCLUDE_PERFETTO_EXT_BASE_PAGED_MEMORY_H_
-
-#include <memory>
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/container_annotations.h"
-
-// We need to track the committed size on windows and when ASAN is enabled.
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) || defined(ADDRESS_SANITIZER)
-#define TRACK_COMMITTED_SIZE() 1
-#else
-#define TRACK_COMMITTED_SIZE() 0
-#endif
-
-namespace perfetto {
-namespace base {
-
-class PagedMemory {
- public:
-  // Initializes an invalid PagedMemory pointing to nullptr.
-  PagedMemory();
-
-  ~PagedMemory();
-
-  PagedMemory(PagedMemory&& other) noexcept;
-  PagedMemory& operator=(PagedMemory&& other);
-
-  enum AllocationFlags {
-    // By default, Allocate() crashes if the underlying mmap fails (e.g., if out
-    // of virtual address space). When this flag is provided, an invalid
-    // PagedMemory pointing to nullptr is returned in this case instead.
-    kMayFail = 1 << 0,
-
-    // By default, Allocate() commits the allocated memory immediately. When
-    // this flag is provided, the memory virtual address space may only be
-    // reserved and the user should call EnsureCommitted() before writing to
-    // memory addresses.
-    kDontCommit = 1 << 1,
-  };
-
-  // Allocates |size| bytes using mmap(MAP_ANONYMOUS). The returned memory is
-  // guaranteed to be page-aligned and guaranteed to be zeroed. |size| must be a
-  // multiple of 4KB (a page size). For |flags|, see the AllocationFlags enum
-  // above.
-  static PagedMemory Allocate(size_t size, int flags = 0);
-
-  // Hint to the OS that the memory range is not needed and can be discarded.
-  // The memory remains accessible and its contents may be retained, or they
-  // may be zeroed. This function may be a NOP on some platforms. Returns true
-  // if implemented.
-  bool AdviseDontNeed(void* p, size_t size);
-
-  // Ensures that at least the first |committed_size| bytes of the allocated
-  // memory region are committed. The implementation may commit memory in larger
-  // chunks above |committed_size|. Crashes if the memory couldn't be committed.
-#if TRACK_COMMITTED_SIZE()
-  void EnsureCommitted(size_t committed_size);
-#else   // TRACK_COMMITTED_SIZE()
-  void EnsureCommitted(size_t /*committed_size*/) {}
-#endif  // TRACK_COMMITTED_SIZE()
-
-  inline void* Get() const noexcept { return p_; }
-  inline bool IsValid() const noexcept { return !!p_; }
-  inline size_t size() const noexcept { return size_; }
-
- private:
-  PagedMemory(char* p, size_t size);
-
-  PagedMemory(const PagedMemory&) = delete;
-  // Defaulted for implementation of move constructor + assignment.
-  PagedMemory& operator=(const PagedMemory&) = default;
-
-  char* p_ = nullptr;
-  size_t size_ = 0;
-
-#if TRACK_COMMITTED_SIZE()
-  size_t committed_size_ = 0u;
-#endif  // TRACK_COMMITTED_SIZE()
-};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_PAGED_MEMORY_H_
diff --git a/include/perfetto/ext/base/pipe.h b/include/perfetto/ext/base/pipe.h
deleted file mode 100644
index ba22729..0000000
--- a/include/perfetto/ext/base/pipe.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_BASE_PIPE_H_
-#define INCLUDE_PERFETTO_EXT_BASE_PIPE_H_
-
-#include "perfetto/ext/base/scoped_file.h"
-
-namespace perfetto {
-namespace base {
-
-class Pipe {
- public:
-  enum Flags {
-    kBothBlock = 0,
-    kBothNonBlock,
-    kRdNonBlock,
-    kWrNonBlock,
-  };
-
-  static Pipe Create(Flags = kBothBlock);
-
-  Pipe();
-  Pipe(Pipe&&) noexcept;
-  Pipe& operator=(Pipe&&);
-
-  ScopedFile rd;
-  ScopedFile wr;
-};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_PIPE_H_
diff --git a/include/perfetto/ext/base/proc_utils.h b/include/perfetto/ext/base/proc_utils.h
deleted file mode 100644
index d5bacb9..0000000
--- a/include/perfetto/ext/base/proc_utils.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_EXT_BASE_PROC_UTILS_H_
-#define INCLUDE_PERFETTO_EXT_BASE_PROC_UTILS_H_
-
-#include <stdint.h>
-
-#include "perfetto/base/build_config.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <Windows.h>
-#include <processthreadsapi.h>
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
-#include <zircon/process.h>
-#include <zircon/types.h>
-#else
-#include <unistd.h>
-#endif
-
-namespace perfetto {
-namespace base {
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
-using PlatformProcessId = zx_handle_t;
-inline PlatformProcessId GetProcessId() {
-  return zx_process_self();
-}
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-using PlatformProcessId = uint64_t;
-inline PlatformProcessId GetProcessId() {
-  return static_cast<uint64_t>(GetCurrentProcessId());
-}
-#else
-using PlatformProcessId = pid_t;
-inline PlatformProcessId GetProcessId() {
-  return getpid();
-}
-#endif
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_PROC_UTILS_H_
diff --git a/include/perfetto/ext/base/scoped_file.h b/include/perfetto/ext/base/scoped_file.h
deleted file mode 100644
index 24c8970..0000000
--- a/include/perfetto/ext/base/scoped_file.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_BASE_SCOPED_FILE_H_
-#define INCLUDE_PERFETTO_EXT_BASE_SCOPED_FILE_H_
-
-#include "perfetto/base/build_config.h"
-
-#include <fcntl.h>
-#include <stdio.h>
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
-    !PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC)
-#include <corecrt_io.h>
-typedef int mode_t;
-#else
-#include <dirent.h>
-#include <unistd.h>
-#endif
-
-#include <string>
-
-#include "perfetto/base/logging.h"
-
-namespace perfetto {
-namespace base {
-
-constexpr mode_t kInvalidMode = static_cast<mode_t>(-1);
-
-// RAII classes for auto-releasing fds and dirs.
-template <typename T,
-          int (*CloseFunction)(T),
-          T InvalidValue,
-          bool CheckClose = true>
-class ScopedResource {
- public:
-  explicit ScopedResource(T t = InvalidValue) : t_(t) {}
-  ScopedResource(ScopedResource&& other) noexcept {
-    t_ = other.t_;
-    other.t_ = InvalidValue;
-  }
-  ScopedResource& operator=(ScopedResource&& other) {
-    reset(other.t_);
-    other.t_ = InvalidValue;
-    return *this;
-  }
-  T get() const { return t_; }
-  T operator*() const { return t_; }
-  explicit operator bool() const { return t_ != InvalidValue; }
-  void reset(T r = InvalidValue) {
-    if (t_ != InvalidValue) {
-      int res = CloseFunction(t_);
-      if (CheckClose)
-        PERFETTO_CHECK(res == 0);
-    }
-    t_ = r;
-  }
-  T release() {
-    T t = t_;
-    t_ = InvalidValue;
-    return t;
-  }
-  ~ScopedResource() { reset(InvalidValue); }
-
- private:
-  ScopedResource(const ScopedResource&) = delete;
-  ScopedResource& operator=(const ScopedResource&) = delete;
-
-  T t_;
-};
-
-using ScopedFile = ScopedResource<int, close, -1>;
-inline static ScopedFile OpenFile(const std::string& path,
-                                  int flags,
-                                  mode_t mode = kInvalidMode) {
-  PERFETTO_DCHECK((flags & O_CREAT) == 0 || mode != kInvalidMode);
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  // Always use O_BINARY on Windows, to avoid silly EOL translations.
-  ScopedFile fd(open(path.c_str(), flags | O_BINARY, mode));
-#else
-  // Always open a ScopedFile with O_CLOEXEC so we can safely fork and exec.
-  ScopedFile fd(open(path.c_str(), flags | O_CLOEXEC, mode));
-#endif
-  return fd;
-}
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-using ScopedDir = ScopedResource<DIR*, closedir, nullptr>;
-#endif
-
-using ScopedFstream = ScopedResource<FILE*, fclose, nullptr>;
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_SCOPED_FILE_H_
diff --git a/include/perfetto/ext/base/small_set.h b/include/perfetto/ext/base/small_set.h
deleted file mode 100644
index db057a0..0000000
--- a/include/perfetto/ext/base/small_set.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_BASE_SMALL_SET_H_
-#define INCLUDE_PERFETTO_EXT_BASE_SMALL_SET_H_
-
-#include <array>
-
-namespace perfetto {
-
-// Set that can store up to Size items of DataType.
-// Lookup is O(Size), so it is only usable for very small sets.
-template <typename DataType, size_t Size>
-class SmallSet {
-  static_assert(Size < 16, "Do not use SmallSet for many items");
-
- public:
-  // Name for consistency with STL.
-  using const_iterator = typename std::array<DataType, Size>::const_iterator;
-  bool Add(DataType n) {
-    if (Contains(n))
-      return true;
-    if (filled_ < Size) {
-      arr_[filled_++] = std::move(n);
-      return true;
-    }
-    return false;
-  }
-
-  bool Contains(const DataType& n) const {
-    for (size_t i = 0; i < filled_; ++i) {
-      if (arr_[i] == n)
-        return true;
-    }
-    return false;
-  }
-
-  const_iterator begin() const { return arr_.cbegin(); }
-  const_iterator end() const { return arr_.cbegin() + filled_; }
-  size_t size() const { return filled_; }
-
- private:
-  std::array<DataType, Size> arr_;
-  size_t filled_ = 0;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_SMALL_SET_H_
diff --git a/include/perfetto/ext/base/string_splitter.h b/include/perfetto/ext/base/string_splitter.h
deleted file mode 100644
index c68506c..0000000
--- a/include/perfetto/ext/base/string_splitter.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_BASE_STRING_SPLITTER_H_
-#define INCLUDE_PERFETTO_EXT_BASE_STRING_SPLITTER_H_
-
-#include <string>
-
-namespace perfetto {
-namespace base {
-
-// C++ version of strtok(). Splits a string without making copies or any heap
-// allocations. Destructs the original string passed in input.
-// Supports the special case of using \0 as a delimiter.
-// The token returned in output are valid as long as the input string is valid.
-class StringSplitter {
- public:
-  // Can take ownership of the string if passed via std::move(), e.g.:
-  // StringSplitter(std::move(str), '\n');
-  StringSplitter(std::string, char delimiter);
-
-  // Splits a C-string. The input string will be forcefully null-terminated (so
-  // str[size - 1] should be == '\0' or the last char will be truncated).
-  StringSplitter(char* str, size_t size, char delimiter);
-
-  // Splits the current token from an outer StringSplitter instance. This is to
-  // chain splitters as follows:
-  // for (base::StringSplitter lines(x, '\n'); ss.Next();)
-  //   for (base::StringSplitter words(&lines, ' '); words.Next();)
-  StringSplitter(StringSplitter*, char delimiter);
-
-  // Returns true if a token is found (in which case it will be stored in
-  // cur_token()), false if no more tokens are found.
-  bool Next();
-
-  // Returns the current token iff last call to Next() returned true. In this
-  // case it guarantees that the returned string is always null terminated.
-  // In all other cases (before the 1st call to Next() and after Next() returns
-  // false) returns nullptr.
-  char* cur_token() { return cur_; }
-
-  // Returns the length of the current token (excluding the null terminator).
-  size_t cur_token_size() const { return cur_size_; }
-
- private:
-  StringSplitter(const StringSplitter&) = delete;
-  StringSplitter& operator=(const StringSplitter&) = delete;
-  void Initialize(char* str, size_t size);
-
-  std::string str_;
-  char* cur_;
-  size_t cur_size_;
-  char* next_;
-  char* end_;  // STL-style, points one past the last char.
-  const char delimiter_;
-};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_STRING_SPLITTER_H_
diff --git a/include/perfetto/ext/base/string_utils.h b/include/perfetto/ext/base/string_utils.h
deleted file mode 100644
index 22c69ee..0000000
--- a/include/perfetto/ext/base/string_utils.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_BASE_STRING_UTILS_H_
-#define INCLUDE_PERFETTO_EXT_BASE_STRING_UTILS_H_
-
-#include <string>
-#include <vector>
-
-#include <inttypes.h>
-#include <stdlib.h>
-
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/string_view.h"
-
-namespace perfetto {
-namespace base {
-
-inline char Lowercase(char c) {
-  return ('A' <= c && c <= 'Z') ? static_cast<char>(c - ('A' - 'a')) : c;
-}
-
-inline char Uppercase(char c) {
-  return ('a' <= c && c <= 'z') ? static_cast<char>(c + ('A' - 'a')) : c;
-}
-
-inline Optional<uint32_t> CStringToUInt32(const char* s) {
-  char* endptr = nullptr;
-  uint64_t value = strtoul(s, &endptr, 10);
-  Optional<uint32_t> result(base::nullopt);
-  if (*s != '\0' && *endptr == '\0')
-    result = static_cast<uint32_t>(value);
-  return result;
-}
-
-inline Optional<int32_t> CStringToInt32(const char* s) {
-  char* endptr = nullptr;
-  int64_t value = strtol(s, &endptr, 10);
-  Optional<int32_t> result(base::nullopt);
-  if (*s != '\0' && *endptr == '\0')
-    result = static_cast<int32_t>(value);
-  return result;
-}
-
-inline Optional<double> CStringToDouble(const char* s) {
-  char* endptr = nullptr;
-  double value = strtod(s, &endptr);
-  Optional<double> result(base::nullopt);
-  if (*s != '\0' && *endptr == '\0')
-    result = value;
-  return result;
-}
-
-inline Optional<uint32_t> StringToUInt32(const std::string& s) {
-  return CStringToUInt32(s.c_str());
-}
-
-inline Optional<int32_t> StringToInt32(const std::string& s) {
-  return CStringToInt32(s.c_str());
-}
-
-inline Optional<double> StringToDouble(const std::string& s) {
-  return CStringToDouble(s.c_str());
-}
-
-bool StartsWith(const std::string& str, const std::string& prefix);
-bool EndsWith(const std::string& str, const std::string& suffix);
-bool Contains(const std::string& haystack, const std::string& needle);
-size_t Find(const StringView& needle, const StringView& haystack);
-bool CaseInsensitiveEqual(const std::string& first, const std::string& second);
-std::string Join(const std::vector<std::string>& parts,
-                 const std::string& delim);
-std::vector<std::string> SplitString(const std::string& text,
-                                     const std::string& delimiter);
-std::string StripPrefix(const std::string& str, const std::string& prefix);
-std::string StripSuffix(const std::string& str, const std::string& suffix);
-std::string ToLower(const std::string& str);
-std::string ToUpper(const std::string& str);
-std::string StripChars(const std::string& str,
-                       const std::string& chars,
-                       char replacement);
-std::string ToHex(const char* data, size_t size);
-inline std::string ToHex(const std::string& s) {
-  return ToHex(s.c_str(), s.size());
-}
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_STRING_UTILS_H_
diff --git a/include/perfetto/ext/base/string_view.h b/include/perfetto/ext/base/string_view.h
deleted file mode 100644
index cd8ef61..0000000
--- a/include/perfetto/ext/base/string_view.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_BASE_STRING_VIEW_H_
-#define INCLUDE_PERFETTO_EXT_BASE_STRING_VIEW_H_
-
-#include <string.h>
-
-#include <algorithm>
-#include <string>
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/hash.h"
-
-namespace perfetto {
-namespace base {
-
-// A string-like object that refers to a non-owned piece of memory.
-// Strings are internally NOT null terminated.
-class StringView {
- public:
-  static constexpr size_t npos = static_cast<size_t>(-1);
-
-  StringView() : data_(nullptr), size_(0) {}
-  StringView(const StringView&) = default;
-  StringView& operator=(const StringView&) = default;
-  StringView(const char* data, size_t size) : data_(data), size_(size) {
-    PERFETTO_DCHECK(size == 0 || data != nullptr);
-  }
-
-  // Allow implicit conversion from any class that has a |data| and |size| field
-  // and has the kConvertibleToStringView trait (e.g., protozero::ConstChars).
-  template <typename T, typename = std::enable_if<T::kConvertibleToStringView>>
-  StringView(const T& x) : StringView(x.data, x.size) {
-    PERFETTO_DCHECK(x.size == 0 || x.data != nullptr);
-  }
-
-  // Creates a StringView from a null-terminated C string.
-  // Deliberately not "explicit".
-  StringView(const char* cstr) : data_(cstr), size_(strlen(cstr)) {
-    PERFETTO_DCHECK(cstr != nullptr);
-  }
-
-  // This instead has to be explicit, as creating a StringView out of a
-  // std::string can be subtle.
-  explicit StringView(const std::string& str)
-      : data_(str.data()), size_(str.size()) {}
-
-  bool empty() const { return size_ == 0; }
-  size_t size() const { return size_; }
-  const char* data() const { return data_; }
-  const char* begin() const { return data_; }
-  const char* end() const { return data_ + size_; }
-
-  char at(size_t pos) const {
-    PERFETTO_DCHECK(pos < size_);
-    return data_[pos];
-  }
-
-  size_t find(char c, size_t start_pos = 0) const {
-    for (size_t i = start_pos; i < size_; ++i) {
-      if (data_[i] == c)
-        return i;
-    }
-    return npos;
-  }
-
-  size_t find(const StringView& str, size_t start_pos = 0) const {
-    if (start_pos > size())
-      return npos;
-    auto it = std::search(begin() + start_pos, end(), str.begin(), str.end());
-    size_t pos = static_cast<size_t>(it - begin());
-    return pos + str.size() <= size() ? pos : npos;
-  }
-
-  size_t find(const char* str, size_t start_pos = 0) const {
-    return find(StringView(str), start_pos);
-  }
-
-  size_t rfind(char c) const {
-    for (size_t i = size_; i > 0; --i) {
-      if (data_[i - 1] == c)
-        return i - 1;
-    }
-    return npos;
-  }
-
-  StringView substr(size_t pos, size_t count = npos) const {
-    if (pos >= size_)
-      return StringView("", 0);
-    size_t rcount = std::min(count, size_ - pos);
-    return StringView(data_ + pos, rcount);
-  }
-
-  bool CaseInsensitiveEq(const StringView& other) {
-    if (size() != other.size())
-      return false;
-    if (size() == 0)
-      return true;
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-    return _strnicmp(data(), other.data(), size()) == 0;
-#else
-    return strncasecmp(data(), other.data(), size()) == 0;
-#endif
-  }
-
-  std::string ToStdString() const {
-    return data_ == nullptr ? "" : std::string(data_, size_);
-  }
-
-  uint64_t Hash() const {
-    base::Hash hasher;
-    hasher.Update(data_, size_);
-    return hasher.digest();
-  }
-
- private:
-  const char* data_ = nullptr;
-  size_t size_ = 0;
-};
-
-inline bool operator==(const StringView& x, const StringView& y) {
-  if (x.size() != y.size())
-    return false;
-  if (x.size() == 0)
-    return true;
-  return memcmp(x.data(), y.data(), x.size()) == 0;
-}
-
-inline bool operator!=(const StringView& x, const StringView& y) {
-  return !(x == y);
-}
-
-inline bool operator<(const StringView& x, const StringView& y) {
-  auto size = std::min(x.size(), y.size());
-  if (size == 0)
-    return x.size() < y.size();
-  int result = memcmp(x.data(), y.data(), size);
-  return result < 0 || (result == 0 && x.size() < y.size());
-}
-
-inline bool operator>=(const StringView& x, const StringView& y) {
-  return !(x < y);
-}
-
-inline bool operator>(const StringView& x, const StringView& y) {
-  return y < x;
-}
-
-inline bool operator<=(const StringView& x, const StringView& y) {
-  return !(y < x);
-}
-
-}  // namespace base
-}  // namespace perfetto
-
-namespace std {
-
-template <>
-struct hash<::perfetto::base::StringView> {
-  size_t operator()(const ::perfetto::base::StringView& sv) const {
-    return static_cast<size_t>(sv.Hash());
-  }
-};
-
-}  // namespace std
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_STRING_VIEW_H_
diff --git a/include/perfetto/ext/base/string_writer.h b/include/perfetto/ext/base/string_writer.h
deleted file mode 100644
index 681324f..0000000
--- a/include/perfetto/ext/base/string_writer.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_EXT_BASE_STRING_WRITER_H_
-#define INCLUDE_PERFETTO_EXT_BASE_STRING_WRITER_H_
-
-#include <inttypes.h>
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_view.h"
-
-namespace perfetto {
-namespace base {
-
-// A helper class which writes formatted data to a string buffer.
-// This is used in the trace processor where we write O(GBs) of strings and
-// sprintf is too slow.
-class StringWriter {
- public:
-  // Creates a string buffer from a char buffer and length.
-  StringWriter(char* buffer, size_t size) : buffer_(buffer), size_(size) {}
-
-  // Appends n instances of a char to the buffer.
-  void AppendChar(char in, size_t n = 1) {
-    PERFETTO_DCHECK(pos_ + n <= size_);
-    memset(&buffer_[pos_], in, n);
-    pos_ += n;
-  }
-
-  // Appends a length delimited string to the buffer.
-  void AppendString(const char* in, size_t n) {
-    PERFETTO_DCHECK(pos_ + n <= size_);
-    memcpy(&buffer_[pos_], in, n);
-    pos_ += n;
-  }
-
-  void AppendStringView(StringView sv) { AppendString(sv.data(), sv.size()); }
-
-  // Appends a null-terminated string literal to the buffer.
-  template <size_t N>
-  inline void AppendLiteral(const char (&in)[N]) {
-    AppendString(in, N - 1);
-  }
-
-  // Appends a StringView to the buffer.
-  void AppendString(StringView data) { AppendString(data.data(), data.size()); }
-
-  // Appends an integer to the buffer.
-  void AppendInt(int64_t value) { AppendPaddedInt<'0', 0>(value); }
-
-  // Appends an integer to the buffer, padding with |padchar| if the number of
-  // digits of the integer is less than |padding|.
-  template <char padchar, uint64_t padding>
-  void AppendPaddedInt(int64_t sign_value) {
-    const bool negate = signbit(static_cast<double>(sign_value));
-    uint64_t absolute_value = static_cast<uint64_t>(std::abs(sign_value));
-    AppendPaddedInt<padchar, padding>(absolute_value, negate);
-  }
-
-  void AppendUnsignedInt(uint64_t value) {
-    AppendPaddedUnsignedInt<'0', 0>(value);
-  }
-
-  // Appends an unsigned integer to the buffer, padding with |padchar| if the
-  // number of digits of the integer is less than |padding|.
-  template <char padchar, uint64_t padding>
-  void AppendPaddedUnsignedInt(uint64_t value) {
-    AppendPaddedInt<padchar, padding>(value, false);
-  }
-
-  // Appends a hex integer to the buffer.
-  template <typename IntType>
-  void AppendHexInt(IntType value) {
-    // TODO(lalitm): trying to optimize this is premature given we almost never
-    // print hex ints. Reevaluate this in the future if we do print them more.
-    size_t res = static_cast<size_t>(
-        snprintf(buffer_ + pos_, size_ - pos_, "%" PRIx64, value));
-    PERFETTO_DCHECK(pos_ + res <= size_);
-    pos_ += res;
-  }
-
-  // Appends a double to the buffer.
-  void AppendDouble(double value) {
-    // TODO(lalitm): trying to optimize this is premature given we almost never
-    // print doubles. Reevaluate this in the future if we do print them more.
-    size_t res = static_cast<size_t>(
-        snprintf(buffer_ + pos_, size_ - pos_, "%lf", value));
-    PERFETTO_DCHECK(pos_ + res <= size_);
-    pos_ += res;
-  }
-
-  void AppendBool(bool value) {
-    if (value) {
-      AppendLiteral("true");
-      return;
-    }
-    AppendLiteral("false");
-  }
-
-  StringView GetStringView() {
-    PERFETTO_DCHECK(pos_ <= size_);
-    return StringView(buffer_, pos_);
-  }
-
-  char* CreateStringCopy() {
-    char* dup = reinterpret_cast<char*>(malloc(pos_ + 1));
-    if (dup) {
-      strncpy(dup, buffer_, pos_);
-      dup[pos_] = '\0';
-    }
-    return dup;
-  }
-
-  size_t pos() const { return pos_; }
-  size_t size() const { return size_; }
-  void reset() { pos_ = 0; }
-
- private:
-  template <char padchar, uint64_t padding>
-  void AppendPaddedInt(uint64_t absolute_value, bool negate) {
-    // Need to add 2 to the number of digits to account for minus sign and
-    // rounding down of digits10.
-    constexpr auto kMaxDigits = std::numeric_limits<uint64_t>::digits10 + 2;
-    constexpr auto kSizeNeeded = kMaxDigits > padding ? kMaxDigits : padding;
-    PERFETTO_DCHECK(pos_ + kSizeNeeded <= size_);
-
-    char data[kSizeNeeded];
-
-    size_t idx;
-    for (idx = kSizeNeeded - 1; absolute_value >= 10;) {
-      char digit = absolute_value % 10;
-      absolute_value /= 10;
-      data[idx--] = digit + '0';
-    }
-    data[idx--] = static_cast<char>(absolute_value) + '0';
-
-    if (padding > 0) {
-      size_t num_digits = kSizeNeeded - 1 - idx;
-      for (size_t i = num_digits; i < padding; i++) {
-        data[idx--] = padchar;
-      }
-    }
-
-    if (negate)
-      buffer_[pos_++] = '-';
-    AppendString(&data[idx + 1], kSizeNeeded - idx - 1);
-  }
-
-  char* buffer_ = nullptr;
-  size_t size_ = 0;
-  size_t pos_ = 0;
-};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_STRING_WRITER_H_
diff --git a/include/perfetto/ext/base/temp_file.h b/include/perfetto/ext/base/temp_file.h
deleted file mode 100644
index da7e1bf..0000000
--- a/include/perfetto/ext/base/temp_file.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_BASE_TEMP_FILE_H_
-#define INCLUDE_PERFETTO_EXT_BASE_TEMP_FILE_H_
-
-#include <string>
-
-#include "perfetto/ext/base/scoped_file.h"
-
-namespace perfetto {
-namespace base {
-
-class TempFile {
- public:
-  static TempFile CreateUnlinked();
-  static TempFile Create();
-
-  TempFile(TempFile&&) noexcept;
-  TempFile& operator=(TempFile&&);
-  ~TempFile();
-
-  const std::string& path() const { return path_; }
-  int fd() const { return *fd_; }
-  int operator*() const { return *fd_; }
-
-  // Unlinks the file from the filesystem but keeps the fd() open.
-  // It is safe to call this multiple times.
-  void Unlink();
-
-  // Releases the underlying file descriptor. Will unlink the file from the
-  // filesystem if it was created via CreateUnlinked().
-  ScopedFile ReleaseFD();
-
- private:
-  TempFile();
-  TempFile(const TempFile&) = delete;
-  TempFile& operator=(const TempFile&) = delete;
-
-  ScopedFile fd_;
-  std::string path_;
-};
-
-class TempDir {
- public:
-  static TempDir Create();
-
-  TempDir(TempDir&&) noexcept;
-  TempDir& operator=(TempDir&&);
-  ~TempDir();
-
-  const std::string& path() const { return path_; }
-
- private:
-  TempDir();
-  TempDir(const TempDir&) = delete;
-  TempDir& operator=(const TempDir&) = delete;
-
-  std::string path_;
-};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_TEMP_FILE_H_
diff --git a/include/perfetto/ext/base/thread_annotations.h b/include/perfetto/ext/base/thread_annotations.h
deleted file mode 100644
index beb8c45..0000000
--- a/include/perfetto/ext/base/thread_annotations.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_EXT_BASE_THREAD_ANNOTATIONS_H_
-#define INCLUDE_PERFETTO_EXT_BASE_THREAD_ANNOTATIONS_H_
-
-#include "perfetto/base/build_config.h"
-
-// Windows TSAN doesn't currently support these annotations.
-#if defined(THREAD_SANITIZER) && !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-extern "C" {
-void AnnotateBenignRaceSized(const char* file,
-                             int line,
-                             unsigned long address,
-                             unsigned long size,
-                             const char* description);
-}
-
-#define PERFETTO_ANNOTATE_BENIGN_RACE_SIZED(pointer, size, description)   \
-  AnnotateBenignRaceSized(__FILE__, __LINE__,                             \
-                          reinterpret_cast<unsigned long>(pointer), size, \
-                          description);
-#else  // defined(ADDRESS_SANITIZER)
-#define PERFETTO_ANNOTATE_BENIGN_RACE_SIZED(pointer, size, description)
-#endif  // defined(ADDRESS_SANITIZER)
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_THREAD_ANNOTATIONS_H_
diff --git a/include/perfetto/ext/base/thread_checker.h b/include/perfetto/ext/base/thread_checker.h
deleted file mode 100644
index 2b341b5..0000000
--- a/include/perfetto/ext/base/thread_checker.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_BASE_THREAD_CHECKER_H_
-#define INCLUDE_PERFETTO_EXT_BASE_THREAD_CHECKER_H_
-
-#include "perfetto/base/build_config.h"
-
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <pthread.h>
-#endif
-#include <atomic>
-
-#include "perfetto/base/export.h"
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
-
-namespace perfetto {
-namespace base {
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-using ThreadID = unsigned long;
-#else
-using ThreadID = pthread_t;
-#endif
-
-class PERFETTO_EXPORT ThreadChecker {
- public:
-  ThreadChecker();
-  ~ThreadChecker();
-  ThreadChecker(const ThreadChecker&);
-  ThreadChecker& operator=(const ThreadChecker&);
-  bool CalledOnValidThread() const PERFETTO_WARN_UNUSED_RESULT;
-  void DetachFromThread();
-
- private:
-  mutable std::atomic<ThreadID> thread_id_;
-};
-
-#if PERFETTO_DCHECK_IS_ON() && !PERFETTO_BUILDFLAG(PERFETTO_CHROMIUM_BUILD)
-// TODO(primiano) Use Chromium's thread checker in Chromium.
-#define PERFETTO_THREAD_CHECKER(name) base::ThreadChecker name;
-#define PERFETTO_DCHECK_THREAD(name) \
-  PERFETTO_DCHECK((name).CalledOnValidThread())
-#define PERFETTO_DETACH_FROM_THREAD(name) (name).DetachFromThread()
-#else
-#define PERFETTO_THREAD_CHECKER(name)
-#define PERFETTO_DCHECK_THREAD(name)
-#define PERFETTO_DETACH_FROM_THREAD(name)
-#endif  // PERFETTO_DCHECK_IS_ON()
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_THREAD_CHECKER_H_
diff --git a/include/perfetto/ext/base/thread_task_runner.h b/include/perfetto/ext/base/thread_task_runner.h
deleted file mode 100644
index fac4553..0000000
--- a/include/perfetto/ext/base/thread_task_runner.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_EXT_BASE_THREAD_TASK_RUNNER_H_
-#define INCLUDE_PERFETTO_EXT_BASE_THREAD_TASK_RUNNER_H_
-
-#include <functional>
-#include <thread>
-
-#include "perfetto/ext/base/unix_task_runner.h"
-
-namespace perfetto {
-namespace base {
-
-// A UnixTaskRunner backed by a dedicated task thread. Shuts down the runner and
-// joins the thread upon destruction. Can be moved to transfer ownership.
-//
-// Guarantees that:
-// * the UnixTaskRunner will be constructed and destructed on the task thread.
-// * the task thread will live for the lifetime of the UnixTaskRunner.
-//
-class ThreadTaskRunner {
- public:
-  static ThreadTaskRunner CreateAndStart() { return ThreadTaskRunner(); }
-
-  ThreadTaskRunner(const ThreadTaskRunner&) = delete;
-  ThreadTaskRunner& operator=(const ThreadTaskRunner&) = delete;
-
-  ThreadTaskRunner(ThreadTaskRunner&&) noexcept;
-  ThreadTaskRunner& operator=(ThreadTaskRunner&&);
-  ~ThreadTaskRunner();
-
-  // Returns a pointer to the UnixTaskRunner, which is valid for the lifetime of
-  // this ThreadTaskRunner object (unless this object is moved-from, in which
-  // case the pointer remains valid for the lifetime of the new owning
-  // ThreadTaskRunner).
-  //
-  // Warning: do not call Quit() on the returned runner pointer, the termination
-  // should be handled exclusively by this class' destructor.
-  UnixTaskRunner* get() const { return task_runner_; }
-
- private:
-  ThreadTaskRunner();
-  void RunTaskThread(std::function<void(UnixTaskRunner*)> initializer);
-
-  std::thread thread_;
-  UnixTaskRunner* task_runner_ = nullptr;
-};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_THREAD_TASK_RUNNER_H_
diff --git a/include/perfetto/ext/base/thread_utils.h b/include/perfetto/ext/base/thread_utils.h
deleted file mode 100644
index 4ad1825..0000000
--- a/include/perfetto/ext/base/thread_utils.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_BASE_THREAD_UTILS_H_
-#define INCLUDE_PERFETTO_EXT_BASE_THREAD_UTILS_H_
-
-#include <stdint.h>
-
-#include "perfetto/base/build_config.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <Windows.h>
-#include <processthreadsapi.h>
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
-#include <zircon/process.h>
-#include <zircon/types.h>
-#else
-#include <pthread.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <unistd.h>
-#endif
-
-namespace perfetto {
-namespace base {
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-using PlatformThreadID = pid_t;
-inline PlatformThreadID GetThreadId() {
-  return gettid();
-}
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX)
-using PlatformThreadID = pid_t;
-inline PlatformThreadID GetThreadId() {
-  return static_cast<pid_t>(syscall(__NR_gettid));
-}
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
-using PlatformThreadID = zx_handle_t;
-inline PlatformThreadID GetThreadId() {
-  return static_cast<pid_t>(zx_thread_self());
-}
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
-using PlatformThreadID = uint64_t;
-inline PlatformThreadID GetThreadId() {
-  uint64_t tid;
-  pthread_threadid_np(nullptr, &tid);
-  return tid;
-}
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-using PlatformThreadID = uint64_t;
-inline PlatformThreadID GetThreadId() {
-  return static_cast<uint64_t>(GetCurrentThreadId());
-}
-#else  // Default to pthreads in case no OS is set.
-using PlatformThreadID = pthread_t;
-inline PlatformThreadID GetThreadId() {
-  return pthread_self();
-}
-#endif
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_THREAD_UTILS_H_
diff --git a/include/perfetto/ext/base/unix_socket.h b/include/perfetto/ext/base/unix_socket.h
deleted file mode 100644
index 4bb9b04..0000000
--- a/include/perfetto/ext/base/unix_socket.h
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_BASE_UNIX_SOCKET_H_
-#define INCLUDE_PERFETTO_EXT_BASE_UNIX_SOCKET_H_
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <memory>
-#include <string>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/base/weak_ptr.h"
-
-struct msghdr;
-
-namespace perfetto {
-namespace base {
-
-class TaskRunner;
-
-// Use arbitrarily high values to avoid that some code accidentally ends up
-// assuming that these enum values match the sysroot's SOCK_xxx defines rather
-// than using GetSockType() / GetSockFamily().
-enum class SockType { kStream = 100, kDgram, kSeqPacket };
-enum class SockFamily { kUnix = 200, kInet };
-
-// UnixSocketRaw is a basic wrapper around UNIX sockets. It exposes wrapper
-// methods that take care of most common pitfalls (e.g., marking fd as
-// O_CLOEXEC, avoiding SIGPIPE, properly handling partial writes). It is used as
-// a building block for the more sophisticated UnixSocket class.
-class UnixSocketRaw {
- public:
-  // Creates a new unconnected unix socket.
-  static UnixSocketRaw CreateMayFail(SockFamily family, SockType type) {
-    return UnixSocketRaw(family, type);
-  }
-
-  // Crates a pair of connected sockets.
-  static std::pair<UnixSocketRaw, UnixSocketRaw> CreatePair(SockFamily,
-                                                            SockType);
-
-  // Creates an uninitialized unix socket.
-  UnixSocketRaw();
-
-  // Creates a unix socket adopting an existing file descriptor. This is
-  // typically used to inherit fds from init via environment variables.
-  UnixSocketRaw(ScopedFile, SockFamily, SockType);
-
-  ~UnixSocketRaw() = default;
-  UnixSocketRaw(UnixSocketRaw&&) noexcept = default;
-  UnixSocketRaw& operator=(UnixSocketRaw&&) = default;
-
-  bool Bind(const std::string& socket_name);
-  bool Listen();
-  bool Connect(const std::string& socket_name);
-  bool SetTxTimeout(uint32_t timeout_ms);
-  bool SetRxTimeout(uint32_t timeout_ms);
-  void Shutdown();
-  void SetBlocking(bool);
-  bool IsBlocking() const;
-  void RetainOnExec();
-  SockType type() const { return type_; }
-  SockFamily family() const { return family_; }
-  int fd() const { return *fd_; }
-  explicit operator bool() const { return !!fd_; }
-
-  ScopedFile ReleaseFd() { return std::move(fd_); }
-
-  ssize_t Send(const void* msg,
-               size_t len,
-               const int* send_fds = nullptr,
-               size_t num_fds = 0);
-
-  // Re-enter sendmsg until all the data has been sent or an error occurs.
-  // TODO(fmayer): Figure out how to do timeouts here for heapprofd.
-  ssize_t SendMsgAll(struct msghdr* msg);
-
-  ssize_t Receive(void* msg,
-                  size_t len,
-                  ScopedFile* fd_vec = nullptr,
-                  size_t max_files = 0);
-
-  // Exposed for testing only.
-  // Update msghdr so subsequent sendmsg will send data that remains after n
-  // bytes have already been sent.
-  static void ShiftMsgHdr(size_t n, struct msghdr* msg);
-
- private:
-  UnixSocketRaw(SockFamily, SockType);
-
-  UnixSocketRaw(const UnixSocketRaw&) = delete;
-  UnixSocketRaw& operator=(const UnixSocketRaw&) = delete;
-
-  ScopedFile fd_;
-  SockFamily family_ = SockFamily::kUnix;
-  SockType type_ = SockType::kStream;
-};
-
-// A non-blocking UNIX domain socket. Allows also to transfer file descriptors.
-// None of the methods in this class are blocking.
-// The main design goal is making strong guarantees on the EventListener
-// callbacks, in order to avoid ending in some undefined state.
-// In case of any error it will aggressively just shut down the socket and
-// notify the failure with OnConnect(false) or OnDisconnect() depending on the
-// state of the socket (see below).
-// EventListener callbacks stop happening as soon as the instance is destroyed.
-//
-// Lifecycle of a client socket:
-//
-//                           Connect()
-//                               |
-//            +------------------+------------------+
-//            | (success)                           | (failure or Shutdown())
-//            V                                     V
-//     OnConnect(true)                         OnConnect(false)
-//            |
-//            V
-//    OnDataAvailable()
-//            |
-//            V
-//     OnDisconnect()  (failure or shutdown)
-//
-//
-// Lifecycle of a server socket:
-//
-//                          Listen()  --> returns false in case of errors.
-//                             |
-//                             V
-//              OnNewIncomingConnection(new_socket)
-//
-//          (|new_socket| inherits the same EventListener)
-//                             |
-//                             V
-//                     OnDataAvailable()
-//                             | (failure or Shutdown())
-//                             V
-//                       OnDisconnect()
-class UnixSocket {
- public:
-  class EventListener {
-   public:
-    virtual ~EventListener();
-
-    // After Listen().
-    virtual void OnNewIncomingConnection(
-        UnixSocket* self,
-        std::unique_ptr<UnixSocket> new_connection);
-
-    // After Connect(), whether successful or not.
-    virtual void OnConnect(UnixSocket* self, bool connected);
-
-    // After a successful Connect() or OnNewIncomingConnection(). Either the
-    // other endpoint did disconnect or some other error happened.
-    virtual void OnDisconnect(UnixSocket* self);
-
-    // Whenever there is data available to Receive(). Note that spurious FD
-    // watch events are possible, so it is possible that Receive() soon after
-    // OnDataAvailable() returns 0 (just ignore those).
-    virtual void OnDataAvailable(UnixSocket* self);
-  };
-
-  enum class State {
-    kDisconnected = 0,  // Failed connection, peer disconnection or Shutdown().
-    kConnecting,  // Soon after Connect(), before it either succeeds or fails.
-    kConnected,   // After a successful Connect().
-    kListening    // After Listen(), until Shutdown().
-  };
-
-  enum class BlockingMode { kNonBlocking, kBlocking };
-
-  // Creates a socket and starts listening. If SockFamily::kUnix and
-  // |socket_name| starts with a '@', an abstract UNIX dmoain socket will be
-  // created instead of a filesystem-linked UNIX socket (Linux/Android only).
-  // If SockFamily::kInet, |socket_name| is host:port (e.g., "1.2.3.4:8000").
-  // Returns always an instance. In case of failure (e.g., another socket
-  // with the same name is  already listening) the returned socket will have
-  // is_listening() == false and last_error() will contain the failure reason.
-  static std::unique_ptr<UnixSocket> Listen(const std::string& socket_name,
-                                            EventListener*,
-                                            TaskRunner*,
-                                            SockFamily,
-                                            SockType);
-
-  // Attaches to a pre-existing socket. The socket must have been created in
-  // SOCK_STREAM mode and the caller must have called bind() on it.
-  static std::unique_ptr<UnixSocket> Listen(ScopedFile,
-                                            EventListener*,
-                                            TaskRunner*,
-                                            SockFamily,
-                                            SockType);
-
-  // Creates a Unix domain socket and connects to the listening endpoint.
-  // Returns always an instance. EventListener::OnConnect(bool success) will
-  // be called always, whether the connection succeeded or not.
-  static std::unique_ptr<UnixSocket> Connect(const std::string& socket_name,
-                                             EventListener*,
-                                             TaskRunner*,
-                                             SockFamily,
-                                             SockType);
-
-  // Constructs a UnixSocket using the given connected socket.
-  static std::unique_ptr<UnixSocket> AdoptConnected(ScopedFile,
-                                                    EventListener*,
-                                                    TaskRunner*,
-                                                    SockFamily,
-                                                    SockType);
-
-  UnixSocket(const UnixSocket&) = delete;
-  UnixSocket& operator=(const UnixSocket&) = delete;
-  // Cannot be easily moved because of tasks from the FileDescriptorWatch.
-  UnixSocket(UnixSocket&&) = delete;
-  UnixSocket& operator=(UnixSocket&&) = delete;
-
-  // This class gives the hard guarantee that no callback is called on the
-  // passed EventListener immediately after the object has been destroyed.
-  // Any queued callback will be silently dropped.
-  ~UnixSocket();
-
-  // Shuts down the current connection, if any. If the socket was Listen()-ing,
-  // stops listening. The socket goes back to kNotInitialized state, so it can
-  // be reused with Listen() or Connect().
-  void Shutdown(bool notify);
-
-  // Returns true is the message was queued, false if there was no space in the
-  // output buffer, in which case the client should retry or give up.
-  // If any other error happens the socket will be shutdown and
-  // EventListener::OnDisconnect() will be called.
-  // If the socket is not connected, Send() will just return false.
-  // Does not append a null string terminator to msg in any case.
-  //
-  // DO NOT PASS kNonBlocking, it is broken.
-  bool Send(const void* msg,
-            size_t len,
-            const int* send_fds,
-            size_t num_fds,
-            BlockingMode blocking = BlockingMode::kNonBlocking);
-
-  inline bool Send(const void* msg,
-                   size_t len,
-                   int send_fd = -1,
-                   BlockingMode blocking = BlockingMode::kNonBlocking) {
-    if (send_fd != -1)
-      return Send(msg, len, &send_fd, 1, blocking);
-    return Send(msg, len, nullptr, 0, blocking);
-  }
-
-  inline bool Send(const std::string& msg,
-                   BlockingMode blocking = BlockingMode::kNonBlocking) {
-    return Send(msg.c_str(), msg.size() + 1, -1, blocking);
-  }
-
-  // Returns the number of bytes (<= |len|) written in |msg| or 0 if there
-  // is no data in the buffer to read or an error occurs (in which case a
-  // EventListener::OnDisconnect() will follow).
-  // If the ScopedFile pointer is not null and a FD is received, it moves the
-  // received FD into that. If a FD is received but the ScopedFile pointer is
-  // null, the FD will be automatically closed.
-  size_t Receive(void* msg, size_t len, ScopedFile*, size_t max_files = 1);
-
-  inline size_t Receive(void* msg, size_t len) {
-    return Receive(msg, len, nullptr, 0);
-  }
-
-  // Only for tests. This is slower than Receive() as it requires a heap
-  // allocation and a copy for the std::string. Guarantees that the returned
-  // string is null terminated even if the underlying message sent by the peer
-  // is not.
-  std::string ReceiveString(size_t max_length = 1024);
-
-  bool is_connected() const { return state_ == State::kConnected; }
-  bool is_listening() const { return state_ == State::kListening; }
-  int fd() const { return sock_raw_.fd(); }
-  int last_error() const { return last_error_; }
-
-  // User ID of the peer, as returned by the kernel. If the client disconnects
-  // and the socket goes into the kDisconnected state, it retains the uid of
-  // the last peer.
-  uid_t peer_uid() const {
-    PERFETTO_DCHECK(!is_listening() && peer_uid_ != kInvalidUid);
-    return peer_uid_;
-  }
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  // Process ID of the peer, as returned by the kernel. If the client
-  // disconnects and the socket goes into the kDisconnected state, it
-  // retains the pid of the last peer.
-  //
-  // This is only available on Linux / Android.
-  pid_t peer_pid() const {
-    PERFETTO_DCHECK(!is_listening() && peer_pid_ != kInvalidPid);
-    return peer_pid_;
-  }
-#endif
-
-  // This makes the UnixSocket unusable.
-  UnixSocketRaw ReleaseSocket();
-
- private:
-  UnixSocket(EventListener*, TaskRunner*, SockFamily, SockType);
-  UnixSocket(EventListener*,
-             TaskRunner*,
-             ScopedFile,
-             State,
-             SockFamily,
-             SockType);
-
-  // Called once by the corresponding public static factory methods.
-  void DoConnect(const std::string& socket_name);
-  void ReadPeerCredentials();
-
-  void OnEvent();
-  void NotifyConnectionState(bool success);
-
-  UnixSocketRaw sock_raw_;
-  State state_ = State::kDisconnected;
-  int last_error_ = 0;
-  uid_t peer_uid_ = kInvalidUid;
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  pid_t peer_pid_ = kInvalidPid;
-#endif
-  EventListener* const event_listener_;
-  TaskRunner* const task_runner_;
-  WeakPtrFactory<UnixSocket> weak_ptr_factory_;  // Keep last.
-};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_UNIX_SOCKET_H_
diff --git a/include/perfetto/ext/base/unix_task_runner.h b/include/perfetto/ext/base/unix_task_runner.h
deleted file mode 100644
index 9ced3b9..0000000
--- a/include/perfetto/ext/base/unix_task_runner.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_BASE_UNIX_TASK_RUNNER_H_
-#define INCLUDE_PERFETTO_EXT_BASE_UNIX_TASK_RUNNER_H_
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/task_runner.h"
-#include "perfetto/base/time.h"
-#include "perfetto/ext/base/event_fd.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/thread_checker.h"
-#include "perfetto/ext/base/thread_utils.h"
-
-#include <poll.h>
-#include <chrono>
-#include <deque>
-#include <map>
-#include <mutex>
-#include <vector>
-
-namespace perfetto {
-namespace base {
-
-// Runs a task runner on the current thread.
-//
-// Implementation note: we currently assume (and enforce in debug builds) that
-// Run() is called from the thread that constructed the UnixTaskRunner. This is
-// not strictly necessary, and we could instead track the thread that invokes
-// Run(). However, a related property that *might* be important to enforce is
-// that the destructor runs on the task-running thread. Otherwise, if there are
-// still-pending tasks at the time of destruction, we would destroy those
-// outside of the task thread (which might be unexpected to the caller). On the
-// other hand, the std::function task interface discourages use of any
-// resource-owning tasks (as the callable needs to be copyable), so this might
-// not be important in practice.
-//
-// TODO(rsavitski): consider adding a thread-check in the destructor, after
-// auditing existing usages.
-class UnixTaskRunner : public TaskRunner {
- public:
-  UnixTaskRunner();
-  ~UnixTaskRunner() override;
-
-  // Start executing tasks. Doesn't return until Quit() is called. Run() may be
-  // called multiple times on the same task runner.
-  void Run();
-  void Quit();
-
-  // Checks whether there are any pending immediate tasks to run. Note that
-  // delayed tasks don't count even if they are due to run.
-  bool IsIdleForTesting();
-
-  // TaskRunner implementation:
-  void PostTask(std::function<void()>) override;
-  void PostDelayedTask(std::function<void()>, uint32_t delay_ms) override;
-  void AddFileDescriptorWatch(int fd, std::function<void()>) override;
-  void RemoveFileDescriptorWatch(int fd) override;
-  bool RunsTasksOnCurrentThread() const override;
-
-  // Returns true if the task runner is quitting, or has quit and hasn't been
-  // restarted since. Exposed primarily for ThreadTaskRunner, not necessary for
-  // normal use of this class.
-  bool QuitCalled();
-
- private:
-  void WakeUp();
-
-  void UpdateWatchTasksLocked();
-
-  int GetDelayMsToNextTaskLocked() const;
-  void RunImmediateAndDelayedTask();
-  void PostFileDescriptorWatches();
-  void RunFileDescriptorWatch(int fd);
-
-  ThreadChecker thread_checker_;
-  PlatformThreadID created_thread_id_ = GetThreadId();
-
-  // On Linux, an eventfd(2) used to waking up the task runner when a new task
-  // is posted. Otherwise the read end of a pipe used for the same purpose.
-  EventFd event_;
-
-  std::vector<struct pollfd> poll_fds_;
-
-  // --- Begin lock-protected members ---
-
-  std::mutex lock_;
-
-  std::deque<std::function<void()>> immediate_tasks_;
-  std::multimap<TimeMillis, std::function<void()>> delayed_tasks_;
-  bool quit_ = false;
-
-  struct WatchTask {
-    std::function<void()> callback;
-    size_t poll_fd_index;  // Index into |poll_fds_|.
-  };
-
-  std::map<int, WatchTask> watch_tasks_;
-  bool watch_tasks_changed_ = false;
-
-  // --- End lock-protected members ---
-};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_UNIX_TASK_RUNNER_H_
diff --git a/include/perfetto/ext/base/utils.h b/include/perfetto/ext/base/utils.h
deleted file mode 100644
index 884ee5e..0000000
--- a/include/perfetto/ext/base/utils.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_BASE_UTILS_H_
-#define INCLUDE_PERFETTO_EXT_BASE_UTILS_H_
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/compiler.h"
-
-#include <errno.h>
-#include <stddef.h>
-#include <stdlib.h>
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <sys/types.h>
-#endif
-
-#define PERFETTO_EINTR(x)                                   \
-  ({                                                        \
-    decltype(x) eintr_wrapper_result;                       \
-    do {                                                    \
-      eintr_wrapper_result = (x);                           \
-    } while (eintr_wrapper_result == -1 && errno == EINTR); \
-    eintr_wrapper_result;                                   \
-  })
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-// TODO(brucedawson) - create a ::perfetto::base::IOSize to replace this.
-#if defined(_WIN64)
-using ssize_t = __int64;
-#else
-using ssize_t = long;
-#endif
-#endif
-
-namespace perfetto {
-namespace base {
-
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-constexpr uid_t kInvalidUid = static_cast<uid_t>(-1);
-constexpr pid_t kInvalidPid = static_cast<pid_t>(-1);
-#endif
-
-constexpr size_t kPageSize = 4096;
-constexpr size_t kMaxCpus = 128;
-
-template <typename T>
-constexpr size_t ArraySize(const T& array) {
-  return sizeof(array) / sizeof(array[0]);
-}
-
-// Function object which invokes 'free' on its parameter, which must be
-// a pointer. Can be used to store malloc-allocated pointers in std::unique_ptr:
-//
-// std::unique_ptr<int, base::FreeDeleter> foo_ptr(
-//     static_cast<int*>(malloc(sizeof(int))));
-struct FreeDeleter {
-  inline void operator()(void* ptr) const { free(ptr); }
-};
-
-template <typename T>
-constexpr T AssumeLittleEndian(T value) {
-  static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__,
-                "Unimplemented on big-endian archs");
-  return value;
-}
-
-// Round up |size| to a multiple of |alignment| (must be a power of two).
-template <size_t alignment>
-constexpr size_t AlignUp(size_t size) {
-  static_assert((alignment & (alignment - 1)) == 0, "alignment must be a pow2");
-  return (size + alignment - 1) & ~(alignment - 1);
-}
-
-inline bool IsAgain(int err) {
-  return err == EAGAIN || err == EWOULDBLOCK;
-}
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_UTILS_H_
diff --git a/include/perfetto/ext/base/uuid.h b/include/perfetto/ext/base/uuid.h
deleted file mode 100644
index 3a3d200..0000000
--- a/include/perfetto/ext/base/uuid.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_EXT_BASE_UUID_H_
-#define INCLUDE_PERFETTO_EXT_BASE_UUID_H_
-
-#include <array>
-#include <string>
-
-#include "perfetto/ext/base/optional.h"
-
-namespace perfetto {
-namespace base {
-
-using Uuid = std::array<uint8_t, 16>;
-Uuid Uuidv4();
-
-Uuid StringToUuid(const std::string&);
-std::string UuidToString(const Uuid&);
-std::string UuidToPrettyString(const Uuid&);
-Optional<Uuid> BytesToUuid(const uint8_t* data, size_t size);
-inline Optional<Uuid> BytesToUuid(const char* data, size_t size) {
-  return BytesToUuid(reinterpret_cast<const uint8_t*>(data), size);
-}
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_UUID_H_
diff --git a/include/perfetto/ext/base/waitable_event.h b/include/perfetto/ext/base/waitable_event.h
deleted file mode 100644
index 15fa6a2..0000000
--- a/include/perfetto/ext/base/waitable_event.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_EXT_BASE_WAITABLE_EVENT_H_
-#define INCLUDE_PERFETTO_EXT_BASE_WAITABLE_EVENT_H_
-
-#include <condition_variable>
-#include <mutex>
-
-namespace perfetto {
-namespace base {
-
-// A waitable event for cross-thread synchronization.
-// All methods on this class can be called from any thread.
-class WaitableEvent {
- public:
-  WaitableEvent();
-  ~WaitableEvent();
-  WaitableEvent(const WaitableEvent&) = delete;
-  WaitableEvent operator=(const WaitableEvent&) = delete;
-
-  // Synchronously block until the event is notified.
-  void Wait();
-
-  // Signal the event, waking up blocked waiters.
-  void Notify();
-
- private:
-  std::mutex mutex_;
-  std::condition_variable event_;
-  bool notified_ = false;
-};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_WAITABLE_EVENT_H_
diff --git a/include/perfetto/ext/base/watchdog.h b/include/perfetto/ext/base/watchdog.h
deleted file mode 100644
index d248dd2..0000000
--- a/include/perfetto/ext/base/watchdog.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_BASE_WATCHDOG_H_
-#define INCLUDE_PERFETTO_EXT_BASE_WATCHDOG_H_
-
-#include <functional>
-
-#include "perfetto/base/build_config.h"
-
-// The POSIX watchdog is only supported on Linux and Android in non-embedder
-// builds.
-#if PERFETTO_BUILDFLAG(PERFETTO_WATCHDOG)
-#include "perfetto/ext/base/watchdog_posix.h"
-#else
-#include "perfetto/ext/base/watchdog_noop.h"
-#endif
-
-namespace perfetto {
-namespace base {
-
-inline void RunTaskWithWatchdogGuard(const std::function<void()>& task) {
-  // Maximum time a single task can take in a TaskRunner before the
-  // program suicides.
-  constexpr int64_t kWatchdogMillis = 30000;  // 30s
-
-  Watchdog::Timer handle =
-      base::Watchdog::GetInstance()->CreateFatalTimer(kWatchdogMillis);
-  task();
-}
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_WATCHDOG_H_
diff --git a/include/perfetto/ext/base/watchdog_noop.h b/include/perfetto/ext/base/watchdog_noop.h
deleted file mode 100644
index d678063..0000000
--- a/include/perfetto/ext/base/watchdog_noop.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_BASE_WATCHDOG_NOOP_H_
-#define INCLUDE_PERFETTO_EXT_BASE_WATCHDOG_NOOP_H_
-
-#include <stdint.h>
-
-namespace perfetto {
-namespace base {
-
-class Watchdog {
- public:
-  class Timer {
-   public:
-    // Define an empty dtor to avoid "unused variable" errors on the call site.
-    Timer() {}
-    Timer(const Timer&) {}
-    ~Timer() {}
-  };
-  static Watchdog* GetInstance() {
-    static Watchdog* watchdog = new Watchdog();
-    return watchdog;
-  }
-  Timer CreateFatalTimer(uint32_t /*ms*/) { return Timer(); }
-  void Start() {}
-  void SetMemoryLimit(uint32_t /*bytes*/, uint32_t /*window_ms*/) {}
-  void SetCpuLimit(uint32_t /*percentage*/, uint32_t /*window_ms*/) {}
-};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_WATCHDOG_NOOP_H_
diff --git a/include/perfetto/ext/base/watchdog_posix.h b/include/perfetto/ext/base/watchdog_posix.h
deleted file mode 100644
index 40e3289..0000000
--- a/include/perfetto/ext/base/watchdog_posix.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_BASE_WATCHDOG_POSIX_H_
-#define INCLUDE_PERFETTO_EXT_BASE_WATCHDOG_POSIX_H_
-
-#include "perfetto/ext/base/thread_checker.h"
-
-#include <atomic>
-#include <condition_variable>
-#include <mutex>
-#include <thread>
-
-namespace perfetto {
-namespace base {
-
-// Ensures that the calling program does not exceed certain hard limits on
-// resource usage e.g. time, memory and CPU. If exceeded, the program is
-// crashed.
-class Watchdog {
- public:
-  // Handle to the timer set to crash the program. If the handle is dropped,
-  // the timer is removed so the program does not crash.
-  class Timer {
-   public:
-    ~Timer();
-    Timer(Timer&&) noexcept;
-
-   private:
-    friend class Watchdog;
-
-    explicit Timer(uint32_t ms);
-    Timer(const Timer&) = delete;
-    Timer& operator=(const Timer&) = delete;
-
-    timer_t timerid_ = nullptr;
-  };
-  virtual ~Watchdog();
-
-  static Watchdog* GetInstance();
-
-  // Sets a timer which will crash the program in |ms| milliseconds if the
-  // returned handle is not destroyed before this point.
-  Timer CreateFatalTimer(uint32_t ms);
-
-  // Starts the watchdog thread which monitors the memory and CPU usage
-  // of the program.
-  void Start();
-
-  // Sets a limit on the memory (defined as the RSS) used by the program
-  // averaged over the last |window_ms| milliseconds. If |kb| is 0, any
-  // existing limit is removed.
-  // Note: |window_ms| has to be a multiple of |polling_interval_ms_|.
-  void SetMemoryLimit(uint64_t bytes, uint32_t window_ms);
-
-  // Sets a limit on the CPU usage used by the program averaged over the last
-  // |window_ms| milliseconds. If |percentage| is 0, any existing limit is
-  // removed.
-  // Note: |window_ms| has to be a multiple of |polling_interval_ms_|.
-  void SetCpuLimit(uint32_t percentage, uint32_t window_ms);
-
- protected:
-  // Protected for testing.
-  Watchdog(uint32_t polling_interval_ms);
-
- private:
-  // Represents a ring buffer in which integer values can be stored.
-  class WindowedInterval {
-   public:
-    // Pushes a new value into a ring buffer wrapping if necessary and returns
-    // whether the ring buffer is full.
-    bool Push(uint64_t sample);
-
-    // Returns the mean of the values in the buffer.
-    double Mean() const;
-
-    // Clears the ring buffer while keeping the existing size.
-    void Clear();
-
-    // Resets the size of the buffer as well as clearing it.
-    void Reset(size_t new_size);
-
-    // Gets the oldest value inserted in the buffer. The buffer must be full
-    // (i.e. Push returned true) before this method can be called.
-    uint64_t OldestWhenFull() const {
-      PERFETTO_CHECK(filled_);
-      return buffer_[position_];
-    }
-
-    // Gets the newest value inserted in the buffer. The buffer must be full
-    // (i.e. Push returned true) before this method can be called.
-    uint64_t NewestWhenFull() const {
-      PERFETTO_CHECK(filled_);
-      return buffer_[(position_ + size_ - 1) % size_];
-    }
-
-    // Returns the size of the ring buffer.
-    size_t size() const { return size_; }
-
-   private:
-    bool filled_ = false;
-    size_t position_ = 0;
-    size_t size_ = 0;
-    std::unique_ptr<uint64_t[]> buffer_;
-  };
-
-  explicit Watchdog(const Watchdog&) = delete;
-  Watchdog& operator=(const Watchdog&) = delete;
-
-  // Main method for the watchdog thread.
-  void ThreadMain();
-
-  // Check each type of resource every |polling_interval_ms_| miillis.
-  void CheckMemory(uint64_t rss_bytes);
-  void CheckCpu(uint64_t cpu_time);
-
-  // Computes the time interval spanned by a given ring buffer with respect
-  // to |polling_interval_ms_|.
-  uint32_t WindowTimeForRingBuffer(const WindowedInterval& window);
-
-  const uint32_t polling_interval_ms_;
-  std::atomic<bool> enabled_{false};
-  std::thread thread_;
-  std::condition_variable exit_signal_;
-
-  // --- Begin lock-protected members ---
-
-  std::mutex mutex_;
-
-  uint64_t memory_limit_bytes_ = 0;
-  WindowedInterval memory_window_bytes_;
-
-  uint32_t cpu_limit_percentage_ = 0;
-  WindowedInterval cpu_window_time_ticks_;
-
-  // --- End lock-protected members ---
-};
-
-}  // namespace base
-}  // namespace perfetto
-#endif  // INCLUDE_PERFETTO_EXT_BASE_WATCHDOG_POSIX_H_
diff --git a/include/perfetto/ext/base/weak_ptr.h b/include/perfetto/ext/base/weak_ptr.h
deleted file mode 100644
index 7ba4ca3..0000000
--- a/include/perfetto/ext/base/weak_ptr.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_BASE_WEAK_PTR_H_
-#define INCLUDE_PERFETTO_EXT_BASE_WEAK_PTR_H_
-
-#include "perfetto/ext/base/thread_checker.h"
-
-#include <memory>
-
-namespace perfetto {
-namespace base {
-
-// A simple WeakPtr for single-threaded cases.
-// Generally keep the WeakPtrFactory as last fields in classes: it makes the
-// WeakPtr(s) invalidate as first thing in the class dtor.
-// Usage:
-// class MyClass {
-//  MyClass() : weak_factory_(this) {}
-//  WeakPtr<MyClass> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
-//
-// private:
-//  WeakPtrFactory<MyClass> weak_factory_;
-// }
-//
-// int main() {
-//  std::unique_ptr<MyClass> foo(new MyClass);
-//  auto wptr = foo.GetWeakPtr();
-//  ASSERT_TRUE(wptr);
-//  ASSERT_EQ(foo.get(), wptr->get());
-//  foo.reset();
-//  ASSERT_FALSE(wptr);
-//  ASSERT_EQ(nullptr, wptr->get());
-// }
-
-template <typename T>
-class WeakPtrFactory;  // Forward declaration, defined below.
-
-template <typename T>
-class WeakPtr {
- public:
-  WeakPtr() {}
-  WeakPtr(const WeakPtr&) = default;
-  WeakPtr& operator=(const WeakPtr&) = default;
-  WeakPtr(WeakPtr&&) = default;
-  WeakPtr& operator=(WeakPtr&&) = default;
-
-  T* get() const {
-    PERFETTO_DCHECK_THREAD(thread_checker);
-    return handle_ ? *handle_.get() : nullptr;
-  }
-  T* operator->() const { return get(); }
-  T& operator*() const { return *get(); }
-
-  explicit operator bool() const { return !!get(); }
-
- private:
-  friend class WeakPtrFactory<T>;
-  explicit WeakPtr(const std::shared_ptr<T*>& handle) : handle_(handle) {}
-
-  std::shared_ptr<T*> handle_;
-  PERFETTO_THREAD_CHECKER(thread_checker)
-};
-
-template <typename T>
-class WeakPtrFactory {
- public:
-  explicit WeakPtrFactory(T* owner)
-      : weak_ptr_(std::shared_ptr<T*>(new T* {owner})) {
-    PERFETTO_DCHECK_THREAD(thread_checker);
-  }
-
-  ~WeakPtrFactory() {
-    PERFETTO_DCHECK_THREAD(thread_checker);
-    *(weak_ptr_.handle_.get()) = nullptr;
-  }
-
-  // Can be safely called on any thread, since it simply copies |weak_ptr_|.
-  // Note that any accesses to the returned pointer need to be made on the
-  // thread that created the factory.
-  WeakPtr<T> GetWeakPtr() const { return weak_ptr_; }
-
- private:
-  WeakPtrFactory(const WeakPtrFactory&) = delete;
-  WeakPtrFactory& operator=(const WeakPtrFactory&) = delete;
-
-  WeakPtr<T> weak_ptr_;
-  PERFETTO_THREAD_CHECKER(thread_checker)
-};
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_BASE_WEAK_PTR_H_
diff --git a/include/perfetto/ext/ipc/BUILD.gn b/include/perfetto/ext/ipc/BUILD.gn
deleted file mode 100644
index 53a39ee..0000000
--- a/include/perfetto/ext/ipc/BUILD.gn
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2017 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.
-
-source_set("ipc") {
-  public_deps = [
-    "../../../../gn:protobuf_lite",
-    "../base",
-  ]
-  sources = [
-    "async_result.h",
-    "basic_types.h",
-    "client.h",
-    "client_info.h",
-    "codegen_helpers.h",
-    "deferred.h",
-    "host.h",
-    "service.h",
-    "service_descriptor.h",
-    "service_proxy.h",
-  ]
-}
diff --git a/include/perfetto/ext/ipc/async_result.h b/include/perfetto/ext/ipc/async_result.h
deleted file mode 100644
index 5cb6140..0000000
--- a/include/perfetto/ext/ipc/async_result.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_IPC_ASYNC_RESULT_H_
-#define INCLUDE_PERFETTO_EXT_IPC_ASYNC_RESULT_H_
-
-#include <memory>
-#include <type_traits>
-#include <utility>
-
-#include "perfetto/ext/ipc/basic_types.h"
-
-namespace perfetto {
-namespace ipc {
-
-// Wraps the result of an asynchronous invocation. This is the equivalent of a
-// std::pair<unique_ptr<T>, bool> with syntactic sugar. It is used as callback
-// argument by Deferred<T>. T is a ProtoMessage subclass (i.e. generated .pb.h).
-template <typename T>
-class AsyncResult {
- public:
-  static AsyncResult Create() {
-    return AsyncResult(std::unique_ptr<T>(new T()));
-  }
-
-  AsyncResult(std::unique_ptr<T> msg = nullptr,
-              bool has_more = false,
-              int fd = -1)
-      : msg_(std::move(msg)), has_more_(has_more), fd_(fd) {
-    static_assert(std::is_base_of<ProtoMessage, T>::value, "T->ProtoMessage");
-  }
-  AsyncResult(AsyncResult&&) noexcept = default;
-  AsyncResult& operator=(AsyncResult&&) = default;
-
-  bool success() const { return !!msg_; }
-  explicit operator bool() const { return success(); }
-
-  bool has_more() const { return has_more_; }
-  void set_has_more(bool has_more) { has_more_ = has_more; }
-
-  void set_msg(std::unique_ptr<T> msg) { msg_ = std::move(msg); }
-  T* release_msg() { return msg_.release(); }
-  T* operator->() { return msg_.get(); }
-  T& operator*() { return *msg_; }
-
-  void set_fd(int fd) { fd_ = fd; }
-  int fd() const { return fd_; }
-
- private:
-  std::unique_ptr<T> msg_;
-  bool has_more_ = false;
-
-  // Optional. Only for messages that convey a file descriptor, for sharing
-  // memory across processes.
-  int fd_ = -1;
-};
-
-}  // namespace ipc
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_IPC_ASYNC_RESULT_H_
diff --git a/include/perfetto/ext/ipc/basic_types.h b/include/perfetto/ext/ipc/basic_types.h
deleted file mode 100644
index f9e330c..0000000
--- a/include/perfetto/ext/ipc/basic_types.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_IPC_BASIC_TYPES_H_
-#define INCLUDE_PERFETTO_EXT_IPC_BASIC_TYPES_H_
-
-#include <stddef.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <google/protobuf/message_lite.h>
-
-namespace perfetto {
-namespace ipc {
-
-using ProtoMessage = ::google::protobuf::MessageLite;
-using ServiceID = uint32_t;
-using MethodID = uint32_t;
-using ClientID = uint64_t;
-using RequestID = uint64_t;
-
-// This determines the maximum size allowed for an IPC message. Trying to send
-// or receive a larger message will hit DCHECK(s) and auto-disconnect.
-constexpr size_t kIPCBufferSize = 128 * 1024;
-
-constexpr uid_t kInvalidUid = static_cast<uid_t>(-1);
-constexpr pid_t kInvalidPid = static_cast<pid_t>(-1);
-
-}  // namespace ipc
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_IPC_BASIC_TYPES_H_
diff --git a/include/perfetto/ext/ipc/client.h b/include/perfetto/ext/ipc/client.h
deleted file mode 100644
index 72c3e73..0000000
--- a/include/perfetto/ext/ipc/client.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_IPC_CLIENT_H_
-#define INCLUDE_PERFETTO_EXT_IPC_CLIENT_H_
-
-#include <functional>
-#include <memory>
-
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/ipc/basic_types.h"
-
-namespace perfetto {
-
-namespace base {
-class TaskRunner;
-}  // namespace base
-
-namespace ipc {
-class ServiceProxy;
-
-// The client-side class that talks to the host over the socket and multiplexes
-// requests coming from the various autogenerated ServiceProxy stubs.
-// This is meant to be used by the user code as follows:
-// auto client = Client::CreateInstance("socket_name", task_runner);
-// std::unique_ptr<GreeterService> svc(new GreeterService());
-// client.BindService(svc);
-// svc.OnConnect([] () {
-//    svc.SayHello(..., ...);
-// });
-class Client {
- public:
-  static std::unique_ptr<Client> CreateInstance(const char* socket_name,
-                                                base::TaskRunner*);
-  virtual ~Client();
-
-  virtual void BindService(base::WeakPtr<ServiceProxy>) = 0;
-
-  // There is no need to call this method explicitly. Destroying the
-  // ServiceProxy instance is sufficient and will automatically unbind it. This
-  // method is exposed only for the ServiceProxy destructor.
-  virtual void UnbindService(ServiceID) = 0;
-
-  // Returns (with move semantics) the last file descriptor received on the IPC
-  // channel. No buffering is performed: if a service sends two file descriptors
-  // and the caller doesn't read them immediately, the first one will be
-  // automatically closed when the second is received (and will hit a DCHECK in
-  // debug builds).
-  virtual base::ScopedFile TakeReceivedFD() = 0;
-};
-
-}  // namespace ipc
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_IPC_CLIENT_H_
diff --git a/include/perfetto/ext/ipc/client_info.h b/include/perfetto/ext/ipc/client_info.h
deleted file mode 100644
index 0b43f9a..0000000
--- a/include/perfetto/ext/ipc/client_info.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_IPC_CLIENT_INFO_H_
-#define INCLUDE_PERFETTO_EXT_IPC_CLIENT_INFO_H_
-
-#include <unistd.h>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/ipc/basic_types.h"
-
-namespace perfetto {
-namespace ipc {
-
-// Passed to Service(s) to identify remote clients.
-class ClientInfo {
- public:
-  ClientInfo() = default;
-  ClientInfo(ClientID client_id, uid_t uid)
-      : client_id_(client_id), uid_(uid) {}
-
-  bool operator==(const ClientInfo& other) const {
-    return (client_id_ == other.client_id_ && uid_ == other.uid_);
-  }
-  bool operator!=(const ClientInfo& other) const { return !(*this == other); }
-
-  // For map<> and other sorted containers.
-  bool operator<(const ClientInfo& other) const {
-    PERFETTO_DCHECK(client_id_ != other.client_id_ || *this == other);
-    return client_id_ < other.client_id_;
-  }
-
-  bool is_valid() const { return client_id_ != 0; }
-
-  // A monotonic counter.
-  ClientID client_id() const { return client_id_; }
-
-  // Posix User ID. Comes from the kernel, can be trusted.
-  uid_t uid() const { return uid_; }
-
- private:
-  ClientID client_id_ = 0;
-  uid_t uid_ = kInvalidUid;
-};
-
-}  // namespace ipc
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_IPC_CLIENT_INFO_H_
diff --git a/include/perfetto/ext/ipc/codegen_helpers.h b/include/perfetto/ext/ipc/codegen_helpers.h
deleted file mode 100644
index c0235a2..0000000
--- a/include/perfetto/ext/ipc/codegen_helpers.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2017 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 file is only meant to be included in autogenerated .cc files.
-
-#ifndef INCLUDE_PERFETTO_EXT_IPC_CODEGEN_HELPERS_H_
-#define INCLUDE_PERFETTO_EXT_IPC_CODEGEN_HELPERS_H_
-
-#include <memory>
-
-#include "perfetto/ext/ipc/basic_types.h"
-#include "perfetto/ext/ipc/deferred.h"
-#include "perfetto/ext/ipc/service.h"
-
-// A templated protobuf message decoder. Returns nullptr in case of failure.
-template <typename T>
-::std::unique_ptr<::perfetto::ipc::ProtoMessage> _IPC_Decoder(
-    const std::string& proto_data) {
-  ::std::unique_ptr<::perfetto::ipc::ProtoMessage> msg(new T());
-  if (msg->ParseFromString(proto_data))
-    return msg;
-  return nullptr;
-}
-
-// Templated method dispatcher. Used to obtain a function pointer to a given
-// IPC method (Method) of a given service (TSvc) that can be invoked by the
-// host-side machinery starting from a generic Service pointer and a generic
-// ProtoMessage request argument.
-template <typename TSvc,    // Type of the actual Service subclass.
-          typename TReq,    // Type of the request argument.
-          typename TReply,  // Type of the reply argument.
-          void (TSvc::*Method)(const TReq&, ::perfetto::ipc::Deferred<TReply>)>
-void _IPC_Invoker(::perfetto::ipc::Service* s,
-                  const ::perfetto::ipc::ProtoMessage& req,
-                  ::perfetto::ipc::DeferredBase reply) {
-  (*static_cast<TSvc*>(s).*Method)(
-      static_cast<const TReq&>(req),
-      ::perfetto::ipc::Deferred<TReply>(::std::move(reply)));
-}
-
-#endif  // INCLUDE_PERFETTO_EXT_IPC_CODEGEN_HELPERS_H_
diff --git a/include/perfetto/ext/ipc/deferred.h b/include/perfetto/ext/ipc/deferred.h
deleted file mode 100644
index aa4cbbd..0000000
--- a/include/perfetto/ext/ipc/deferred.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_IPC_DEFERRED_H_
-#define INCLUDE_PERFETTO_EXT_IPC_DEFERRED_H_
-
-#include <functional>
-#include <memory>
-#include <utility>
-
-#include "perfetto/ext/ipc/async_result.h"
-#include "perfetto/ext/ipc/basic_types.h"
-
-namespace perfetto {
-namespace ipc {
-
-// This class is a wrapper for a callback handling async results.
-// The problem this is solving is the following: For each result argument of the
-// methods generated from the .proto file:
-// - The client wants to see something on which it can Bind() a callback, which
-//   is invoked asynchronously once reply is received from the host.
-// - The host wants to expose something to user code that implements the IPC
-//   methods to allow them to provide an asynchronous reply back to the client.
-//   Eventually even more than once, for the case streaming replies.
-//
-// In both cases we want to make sure that callbacks don't get lost along the
-// way. To address this, this class will automatically reject the callbacks
-// if they are not resolved at destructor time (or the object is std::move()'d).
-//
-// The client is supposed to use this class as follows:
-//   class GreeterProxy {
-//      void SayHello(const HelloRequest&, Deferred<HelloReply> reply)
-//   }
-//  ...
-//  Deferred<HelloReply> reply;
-//  reply.Bind([] (AsyncResult<HelloReply> reply) {
-//    std::cout << reply.success() ? reply->message : "failure";
-//  });
-//  host_proxy_instance.SayHello(req, std::move(reply));
-//
-// The host instead is supposed to use this as follows:
-//   class GreeterImpl : public Greeter {
-//     void SayHello(const HelloRequest& req, Deferred<HelloReply> reply) {
-//        AsyncResult<HelloReply> reply = AsyncResult<HelloReply>::Create();
-//        reply->set_greeting("Hello " + req.name)
-//        reply.Resolve(std::move(reply));
-//     }
-//   }
-// Or for more complex cases, the deferred object can be std::move()'d outside
-// and the reply can continue asynchronously later.
-
-template <typename T>
-class Deferred;
-
-class DeferredBase {
- public:
-  explicit DeferredBase(
-      std::function<void(AsyncResult<ProtoMessage>)> callback = nullptr);
-
-  template <typename T>
-  explicit DeferredBase(Deferred<T> other)
-      : callback_(std::move(other.callback_)) {}
-
-  ~DeferredBase();
-  DeferredBase(DeferredBase&&) noexcept;
-  DeferredBase& operator=(DeferredBase&&);
-  void Bind(std::function<void(AsyncResult<ProtoMessage>)> callback);
-  bool IsBound() const;
-  void Resolve(AsyncResult<ProtoMessage>);
-  void Reject();
-
- protected:
-  template <typename T>
-  friend class Deferred;
-  void Move(DeferredBase&);
-
-  std::function<void(AsyncResult<ProtoMessage>)> callback_;
-};
-
-template <typename T>  // T : ProtoMessage subclass
-class Deferred : public DeferredBase {
- public:
-  explicit Deferred(std::function<void(AsyncResult<T>)> callback = nullptr) {
-    Bind(std::move(callback));
-  }
-
-  // This move constructor (and the similar one in DeferredBase) is meant to be
-  // called only by the autogenerated code. The caller has to guarantee that the
-  // moved-from and moved-to types match. The behavior is otherwise undefined.
-  explicit Deferred(DeferredBase&& other) {
-    callback_ = std::move(other.callback_);
-    other.callback_ = nullptr;
-  }
-
-  void Bind(std::function<void(AsyncResult<T>)> callback) {
-    if (!callback)
-      return;
-
-    // Here we need a callback adapter to downcast the callback to a generic
-    // callback that takes an AsyncResult<ProtoMessage>, so that it can be
-    // stored in the base class |callback_|.
-    auto callback_adapter = [callback](
-                                AsyncResult<ProtoMessage> async_result_base) {
-      // Upcast the async_result from <ProtoMessage> -> <T : ProtoMessage>.
-      static_assert(std::is_base_of<ProtoMessage, T>::value, "T:ProtoMessage");
-      AsyncResult<T> async_result(
-          std::unique_ptr<T>(static_cast<T*>(async_result_base.release_msg())),
-          async_result_base.has_more(), async_result_base.fd());
-      callback(std::move(async_result));
-    };
-    DeferredBase::Bind(callback_adapter);
-  }
-
-  // If no more messages are expected, |callback_| is released.
-  void Resolve(AsyncResult<T> async_result) {
-    // Convert the |async_result| to the generic base one (T -> ProtoMessage).
-    AsyncResult<ProtoMessage> async_result_base(
-        std::unique_ptr<ProtoMessage>(async_result.release_msg()),
-        async_result.has_more(), async_result.fd());
-    DeferredBase::Resolve(std::move(async_result_base));
-  }
-};
-
-}  // namespace ipc
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_IPC_DEFERRED_H_
diff --git a/include/perfetto/ext/ipc/host.h b/include/perfetto/ext/ipc/host.h
deleted file mode 100644
index bbf3657..0000000
--- a/include/perfetto/ext/ipc/host.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_IPC_HOST_H_
-#define INCLUDE_PERFETTO_EXT_IPC_HOST_H_
-
-#include <memory>
-
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/ipc/basic_types.h"
-
-namespace perfetto {
-
-namespace base {
-class TaskRunner;
-}  // namespace base
-
-namespace ipc {
-
-class Service;
-
-// The host-side of the IPC layer. This class acts as a registry and request
-// dispatcher. It listen on the UnixSocket |socket_name| for incoming requests
-// (coming Client instances) and dispatches their requests to the various
-// Services exposed.
-class Host {
- public:
-  // Creates an instance and starts listening on the given |socket_name|.
-  // Returns nullptr if listening on the socket fails.
-  static std::unique_ptr<Host> CreateInstance(const char* socket_name,
-                                              base::TaskRunner*);
-
-  // Like the above but takes a file descriptor to a pre-bound unix socket.
-  // Returns nullptr if listening on the socket fails.
-  static std::unique_ptr<Host> CreateInstance(base::ScopedFile socket_fd,
-                                              base::TaskRunner*);
-
-  virtual ~Host();
-
-  // Registers a new service and makes it available to remote IPC peers.
-  // All the exposed Service instances will be destroyed when destroying the
-  // Host instance if ExposeService succeeds and returns true, or immediately
-  // after the call in case of failure.
-  // Returns true if the register has been successfully registered, false in
-  // case of errors (e.g., another service with the same name is already
-  // registered).
-  virtual bool ExposeService(std::unique_ptr<Service>) = 0;
-};
-
-}  // namespace ipc
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_IPC_HOST_H_
diff --git a/include/perfetto/ext/ipc/service.h b/include/perfetto/ext/ipc/service.h
deleted file mode 100644
index ea49834..0000000
--- a/include/perfetto/ext/ipc/service.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_IPC_SERVICE_H_
-#define INCLUDE_PERFETTO_EXT_IPC_SERVICE_H_
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/ipc/client_info.h"
-
-namespace perfetto {
-namespace ipc {
-
-class ServiceDescriptor;
-
-// The base class for all the autogenerated host-side service interfaces.
-class Service {
- public:
-  virtual ~Service();
-
-  // Overridden by the auto-generated class. Provides the list of methods and
-  // the protobuf (de)serialization functions for their arguments.
-  virtual const ServiceDescriptor& GetDescriptor() = 0;
-
-  // Invoked when a remote client disconnects. Use client_info() to obtain
-  // details about the client that disconnected.
-  virtual void OnClientDisconnected() {}
-
-  // Returns the ClientInfo for the current IPC request. Returns an invalid
-  // ClientInfo if called outside the scope of an IPC method.
-  const ClientInfo& client_info() {
-    PERFETTO_DCHECK(client_info_.is_valid());
-    return client_info_;
-  }
-
-  base::ScopedFile TakeReceivedFD() {
-    if (received_fd_)
-      return std::move(*received_fd_);
-    return base::ScopedFile();
-  }
-
- private:
-  friend class HostImpl;
-  ClientInfo client_info_;
-  // This is a pointer because the received fd needs to remain owned by the
-  // ClientConnection, as we will provide it to all method invocations
-  // for that client until one of them calls Service::TakeReceivedFD.
-  //
-  // Different clients might have sent different FDs so this cannot be owned
-  // here.
-  //
-  // Note that this means that there can always only be one outstanding
-  // invocation per client that supplies an FD and the client needs to
-  // wait for this one to return before calling another one.
-  base::ScopedFile* received_fd_;
-};
-
-}  // namespace ipc
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_IPC_SERVICE_H_
diff --git a/include/perfetto/ext/ipc/service_descriptor.h b/include/perfetto/ext/ipc/service_descriptor.h
deleted file mode 100644
index 97eb9bf..0000000
--- a/include/perfetto/ext/ipc/service_descriptor.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_IPC_SERVICE_DESCRIPTOR_H_
-#define INCLUDE_PERFETTO_EXT_IPC_SERVICE_DESCRIPTOR_H_
-
-#include <functional>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "perfetto/ext/ipc/basic_types.h"
-#include "perfetto/ext/ipc/deferred.h"
-
-namespace perfetto {
-namespace ipc {
-
-class Service;
-
-// This is a pure data structure which holds factory methods and strings for the
-// services and their methods that get generated in the .h/.cc files.
-// Each autogenerated class has a GetDescriptor() method that returns one
-// instance of these and allows both client and hosts to map service and method
-// names to IDs and provide function pointers to the protobuf decoder fuctions.
-class ServiceDescriptor {
- public:
-  struct Method {
-    const char* name;
-
-    // DecoderFunc is pointer to a function that takes a string in input
-    // containing protobuf encoded data and returns a decoded protobuf message.
-    using DecoderFunc = std::unique_ptr<ProtoMessage> (*)(const std::string&);
-
-    // Function pointer to decode the request argument of the method.
-    DecoderFunc request_proto_decoder;
-
-    // Function pointer to decoded the reply argument of the method.
-    DecoderFunc reply_proto_decoder;
-
-    // Function pointer that dispatches the generic request to the corresponding
-    // method implementation.
-    using InvokerFunc = void (*)(Service*,
-                                 const ProtoMessage& /* request_args */,
-                                 DeferredBase /* deferred_reply */);
-    InvokerFunc invoker;
-  };
-
-  const char* service_name = nullptr;
-
-  // Note that methods order is not stable. Client and Host might have different
-  // method indexes, depending on their versions. The Client can't just rely
-  // on the indexes and has to keep a [string -> remote index] translation map.
-  std::vector<Method> methods;
-};
-
-}  // namespace ipc
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_IPC_SERVICE_DESCRIPTOR_H_
diff --git a/include/perfetto/ext/ipc/service_proxy.h b/include/perfetto/ext/ipc/service_proxy.h
deleted file mode 100644
index 98f111c..0000000
--- a/include/perfetto/ext/ipc/service_proxy.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_IPC_SERVICE_PROXY_H_
-#define INCLUDE_PERFETTO_EXT_IPC_SERVICE_PROXY_H_
-
-#include "perfetto/ext/ipc/basic_types.h"
-
-#include <assert.h>
-
-#include <functional>
-#include <map>
-#include <memory>
-#include <string>
-
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/ipc/deferred.h"
-
-namespace perfetto {
-namespace ipc {
-
-class Client;
-class ServiceDescriptor;
-
-// The base class for the client-side autogenerated stubs that forward method
-// invocations to the host. All the methods of this class are meant to be called
-// only by the autogenerated code.
-class ServiceProxy {
- public:
-  class EventListener {
-   public:
-    virtual ~EventListener();
-
-    // Called once after Client::BindService() if the ServiceProxy has been
-    // successfully bound to the host. It is possible to start sending IPC
-    // requests soon after this.
-    virtual void OnConnect() {}
-
-    // Called if the connection fails to be established or drops after having
-    // been established.
-    virtual void OnDisconnect() {}
-  };
-
-  // Guarantees that no callback will happen after this object has been
-  // destroyed. The caller has to guarantee that the |event_listener| stays
-  // alive at least as long as the ServiceProxy instance.
-  explicit ServiceProxy(EventListener*);
-  virtual ~ServiceProxy();
-
-  void InitializeBinding(base::WeakPtr<Client>,
-                         ServiceID,
-                         std::map<std::string, MethodID>);
-
-  // Called by the IPC methods in the autogenerated classes.
-  void BeginInvoke(const std::string& method_name,
-                   const ProtoMessage& request,
-                   DeferredBase reply,
-                   int fd = -1);
-
-  // Called by ClientImpl.
-  // |reply_args| == nullptr means request failure.
-  void EndInvoke(RequestID,
-                 std::unique_ptr<ProtoMessage> reply_arg,
-                 bool has_more);
-
-  // Called by ClientImpl.
-  void OnConnect(bool success);
-  void OnDisconnect();
-  bool connected() const { return service_id_ != 0; }
-
-  base::WeakPtr<ServiceProxy> GetWeakPtr() const;
-
-  // Implemented by the autogenerated class.
-  virtual const ServiceDescriptor& GetDescriptor() = 0;
-
- private:
-  base::WeakPtr<Client> client_;
-  ServiceID service_id_ = 0;
-  std::map<std::string, MethodID> remote_method_ids_;
-  std::map<RequestID, DeferredBase> pending_callbacks_;
-  EventListener* const event_listener_;
-  base::WeakPtrFactory<ServiceProxy> weak_ptr_factory_;  // Keep last.
-};
-
-}  // namespace ipc
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_IPC_SERVICE_PROXY_H_
diff --git a/include/perfetto/ext/trace_processor/BUILD.gn b/include/perfetto/ext/trace_processor/BUILD.gn
deleted file mode 100644
index a2fd7fa..0000000
--- a/include/perfetto/ext/trace_processor/BUILD.gn
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../../../gn/perfetto.gni")
-
-# Exposed for Chromium only. May be removed in the future.
-source_set("export_json") {
-  sources = []
-  if (enable_perfetto_trace_processor_json) {
-    sources += [ "export_json.h" ]
-  }
-}
diff --git a/include/perfetto/ext/trace_processor/export_json.h b/include/perfetto/ext/trace_processor/export_json.h
deleted file mode 100644
index d5c5dac..0000000
--- a/include/perfetto/ext/trace_processor/export_json.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_EXPORT_JSON_H_
-#define INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_EXPORT_JSON_H_
-
-#include <stdio.h>
-
-#include <functional>
-
-#include "perfetto/base/export.h"
-#include "perfetto/trace_processor/status.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorStorage;
-
-namespace json {
-
-using ArgumentNameFilterPredicate = std::function<bool(const char* arg_name)>;
-using ArgumentFilterPredicate =
-    std::function<bool(const char* category_group_name,
-                       const char* event_name,
-                       ArgumentNameFilterPredicate*)>;
-using MetadataFilterPredicate = std::function<bool(const char* metadata_name)>;
-using LabelFilterPredicate = std::function<bool(const char* label_name)>;
-
-class PERFETTO_EXPORT OutputWriter {
- public:
-  OutputWriter();
-  virtual ~OutputWriter();
-
-  virtual util::Status AppendString(const std::string&) = 0;
-};
-
-// Public for Chrome. Exports the trace loaded in TraceProcessorStorage to json,
-// applying argument, metadata and label filtering using the callbacks.
-util::Status PERFETTO_EXPORT ExportJson(TraceProcessorStorage*,
-                                        OutputWriter*,
-                                        ArgumentFilterPredicate = nullptr,
-                                        MetadataFilterPredicate = nullptr,
-                                        LabelFilterPredicate = nullptr);
-
-}  // namespace json
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_EXPORT_JSON_H_
diff --git a/include/perfetto/ext/traced/BUILD.gn b/include/perfetto/ext/traced/BUILD.gn
deleted file mode 100644
index 1f58ac2..0000000
--- a/include/perfetto/ext/traced/BUILD.gn
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2017 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.
-
-source_set("traced") {
-  sources = [
-    "data_source_types.h",
-    "traced.h",
-  ]
-}
-
-source_set("sys_stats_counters") {
-  public_deps = [
-    "../../../../gn:default_deps",
-    "../../../../protos/perfetto/common:zero",
-    "../base",
-  ]
-  sources = [
-    "sys_stats_counters.h",
-  ]
-}
diff --git a/include/perfetto/ext/traced/data_source_types.h b/include/perfetto/ext/traced/data_source_types.h
deleted file mode 100644
index 103fd41..0000000
--- a/include/perfetto/ext/traced/data_source_types.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_TRACED_DATA_SOURCE_TYPES_H_
-#define INCLUDE_PERFETTO_EXT_TRACED_DATA_SOURCE_TYPES_H_
-
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <set>
-#include <string>
-
-namespace perfetto {
-
-// On ARM, st_ino is not ino_t but unsigned long long.
-using Inode = decltype(stat::st_ino);
-
-// On ARM, st_dev is not dev_t but unsigned long long.
-using BlockDeviceID = decltype(stat::st_dev);
-
-// From inode_file_map.pbzero.h
-using InodeFileMap_Entry_Type = int32_t;
-
-class InodeMapValue {
- public:
-  InodeMapValue(InodeFileMap_Entry_Type entry_type, std::set<std::string> paths)
-      : entry_type_(entry_type), paths_(std::move(paths)) {}
-
-  InodeMapValue() {}
-
-  InodeFileMap_Entry_Type type() const { return entry_type_; }
-  const std::set<std::string>& paths() const { return paths_; }
-  void SetType(InodeFileMap_Entry_Type entry_type) { entry_type_ = entry_type; }
-  void SetPaths(std::set<std::string> paths) { paths_ = std::move(paths); }
-  void AddPath(std::string path) { paths_.emplace(std::move(path)); }
-
-  bool operator==(const perfetto::InodeMapValue& rhs) const {
-    return type() == rhs.type() && paths() == rhs.paths();
-  }
-
- private:
-  InodeFileMap_Entry_Type entry_type_;
-  std::set<std::string> paths_;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACED_DATA_SOURCE_TYPES_H_
diff --git a/include/perfetto/ext/traced/sys_stats_counters.h b/include/perfetto/ext/traced/sys_stats_counters.h
deleted file mode 100644
index f4ba962..0000000
--- a/include/perfetto/ext/traced/sys_stats_counters.h
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_TRACED_SYS_STATS_COUNTERS_H_
-#define INCLUDE_PERFETTO_EXT_TRACED_SYS_STATS_COUNTERS_H_
-
-#include "perfetto/ext/base/utils.h"
-#include "protos/perfetto/common/sys_stats_counters.pbzero.h"
-
-#include <vector>
-
-namespace perfetto {
-
-struct KeyAndId {
-  const char* str;
-  int id;
-};
-
-constexpr KeyAndId kMeminfoKeys[] = {
-    {"MemUnspecified", protos::pbzero::MeminfoCounters::MEMINFO_UNSPECIFIED},
-    {"MemTotal", protos::pbzero::MeminfoCounters::MEMINFO_MEM_TOTAL},
-    {"MemFree", protos::pbzero::MeminfoCounters::MEMINFO_MEM_FREE},
-    {"MemAvailable", protos::pbzero::MeminfoCounters::MEMINFO_MEM_AVAILABLE},
-    {"Buffers", protos::pbzero::MeminfoCounters::MEMINFO_BUFFERS},
-    {"Cached", protos::pbzero::MeminfoCounters::MEMINFO_CACHED},
-    {"SwapCached", protos::pbzero::MeminfoCounters::MEMINFO_SWAP_CACHED},
-    {"Active", protos::pbzero::MeminfoCounters::MEMINFO_ACTIVE},
-    {"Inactive", protos::pbzero::MeminfoCounters::MEMINFO_INACTIVE},
-    {"Active(anon)", protos::pbzero::MeminfoCounters::MEMINFO_ACTIVE_ANON},
-    {"Inactive(anon)", protos::pbzero::MeminfoCounters::MEMINFO_INACTIVE_ANON},
-    {"Active(file)", protos::pbzero::MeminfoCounters::MEMINFO_ACTIVE_FILE},
-    {"Inactive(file)", protos::pbzero::MeminfoCounters::MEMINFO_INACTIVE_FILE},
-    {"Unevictable", protos::pbzero::MeminfoCounters::MEMINFO_UNEVICTABLE},
-    {"Mlocked", protos::pbzero::MeminfoCounters::MEMINFO_MLOCKED},
-    {"SwapTotal", protos::pbzero::MeminfoCounters::MEMINFO_SWAP_TOTAL},
-    {"SwapFree", protos::pbzero::MeminfoCounters::MEMINFO_SWAP_FREE},
-    {"Dirty", protos::pbzero::MeminfoCounters::MEMINFO_DIRTY},
-    {"Writeback", protos::pbzero::MeminfoCounters::MEMINFO_WRITEBACK},
-    {"AnonPages", protos::pbzero::MeminfoCounters::MEMINFO_ANON_PAGES},
-    {"Mapped", protos::pbzero::MeminfoCounters::MEMINFO_MAPPED},
-    {"Shmem", protos::pbzero::MeminfoCounters::MEMINFO_SHMEM},
-    {"Slab", protos::pbzero::MeminfoCounters::MEMINFO_SLAB},
-    {"SReclaimable", protos::pbzero::MeminfoCounters::MEMINFO_SLAB_RECLAIMABLE},
-    {"SUnreclaim", protos::pbzero::MeminfoCounters::MEMINFO_SLAB_UNRECLAIMABLE},
-    {"KernelStack", protos::pbzero::MeminfoCounters::MEMINFO_KERNEL_STACK},
-    {"PageTables", protos::pbzero::MeminfoCounters::MEMINFO_PAGE_TABLES},
-    {"CommitLimit", protos::pbzero::MeminfoCounters::MEMINFO_COMMIT_LIMIT},
-    {"Committed_AS", protos::pbzero::MeminfoCounters::MEMINFO_COMMITED_AS},
-    {"VmallocTotal", protos::pbzero::MeminfoCounters::MEMINFO_VMALLOC_TOTAL},
-    {"VmallocUsed", protos::pbzero::MeminfoCounters::MEMINFO_VMALLOC_USED},
-    {"VmallocChunk", protos::pbzero::MeminfoCounters::MEMINFO_VMALLOC_CHUNK},
-    {"CmaTotal", protos::pbzero::MeminfoCounters::MEMINFO_CMA_TOTAL},
-    {"CmaFree", protos::pbzero::MeminfoCounters::MEMINFO_CMA_FREE},
-};
-
-const KeyAndId kVmstatKeys[] = {
-    {"VmstatUnspecified", protos::pbzero::VmstatCounters::VMSTAT_UNSPECIFIED},
-    {"nr_free_pages", protos::pbzero::VmstatCounters::VMSTAT_NR_FREE_PAGES},
-    {"nr_alloc_batch", protos::pbzero::VmstatCounters::VMSTAT_NR_ALLOC_BATCH},
-    {"nr_inactive_anon",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_INACTIVE_ANON},
-    {"nr_active_anon", protos::pbzero::VmstatCounters::VMSTAT_NR_ACTIVE_ANON},
-    {"nr_inactive_file",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_INACTIVE_FILE},
-    {"nr_active_file", protos::pbzero::VmstatCounters::VMSTAT_NR_ACTIVE_FILE},
-    {"nr_unevictable", protos::pbzero::VmstatCounters::VMSTAT_NR_UNEVICTABLE},
-    {"nr_mlock", protos::pbzero::VmstatCounters::VMSTAT_NR_MLOCK},
-    {"nr_anon_pages", protos::pbzero::VmstatCounters::VMSTAT_NR_ANON_PAGES},
-    {"nr_mapped", protos::pbzero::VmstatCounters::VMSTAT_NR_MAPPED},
-    {"nr_file_pages", protos::pbzero::VmstatCounters::VMSTAT_NR_FILE_PAGES},
-    {"nr_dirty", protos::pbzero::VmstatCounters::VMSTAT_NR_DIRTY},
-    {"nr_writeback", protos::pbzero::VmstatCounters::VMSTAT_NR_WRITEBACK},
-    {"nr_slab_reclaimable",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_SLAB_RECLAIMABLE},
-    {"nr_slab_unreclaimable",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_SLAB_UNRECLAIMABLE},
-    {"nr_page_table_pages",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_PAGE_TABLE_PAGES},
-    {"nr_kernel_stack", protos::pbzero::VmstatCounters::VMSTAT_NR_KERNEL_STACK},
-    {"nr_overhead", protos::pbzero::VmstatCounters::VMSTAT_NR_OVERHEAD},
-    {"nr_unstable", protos::pbzero::VmstatCounters::VMSTAT_NR_UNSTABLE},
-    {"nr_bounce", protos::pbzero::VmstatCounters::VMSTAT_NR_BOUNCE},
-    {"nr_vmscan_write", protos::pbzero::VmstatCounters::VMSTAT_NR_VMSCAN_WRITE},
-    {"nr_vmscan_immediate_reclaim",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_VMSCAN_IMMEDIATE_RECLAIM},
-    {"nr_writeback_temp",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_WRITEBACK_TEMP},
-    {"nr_isolated_anon",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_ISOLATED_ANON},
-    {"nr_isolated_file",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_ISOLATED_FILE},
-    {"nr_shmem", protos::pbzero::VmstatCounters::VMSTAT_NR_SHMEM},
-    {"nr_dirtied", protos::pbzero::VmstatCounters::VMSTAT_NR_DIRTIED},
-    {"nr_written", protos::pbzero::VmstatCounters::VMSTAT_NR_WRITTEN},
-    {"nr_pages_scanned",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_PAGES_SCANNED},
-    {"workingset_refault",
-     protos::pbzero::VmstatCounters::VMSTAT_WORKINGSET_REFAULT},
-    {"workingset_activate",
-     protos::pbzero::VmstatCounters::VMSTAT_WORKINGSET_ACTIVATE},
-    {"workingset_nodereclaim",
-     protos::pbzero::VmstatCounters::VMSTAT_WORKINGSET_NODERECLAIM},
-    {"nr_anon_transparent_hugepages",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_ANON_TRANSPARENT_HUGEPAGES},
-    {"nr_free_cma", protos::pbzero::VmstatCounters::VMSTAT_NR_FREE_CMA},
-    {"nr_swapcache", protos::pbzero::VmstatCounters::VMSTAT_NR_SWAPCACHE},
-    {"nr_dirty_threshold",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_DIRTY_THRESHOLD},
-    {"nr_dirty_background_threshold",
-     protos::pbzero::VmstatCounters::VMSTAT_NR_DIRTY_BACKGROUND_THRESHOLD},
-    {"pgpgin", protos::pbzero::VmstatCounters::VMSTAT_PGPGIN},
-    {"pgpgout", protos::pbzero::VmstatCounters::VMSTAT_PGPGOUT},
-    {"pgpgoutclean", protos::pbzero::VmstatCounters::VMSTAT_PGPGOUTCLEAN},
-    {"pswpin", protos::pbzero::VmstatCounters::VMSTAT_PSWPIN},
-    {"pswpout", protos::pbzero::VmstatCounters::VMSTAT_PSWPOUT},
-    {"pgalloc_dma", protos::pbzero::VmstatCounters::VMSTAT_PGALLOC_DMA},
-    {"pgalloc_normal", protos::pbzero::VmstatCounters::VMSTAT_PGALLOC_NORMAL},
-    {"pgalloc_movable", protos::pbzero::VmstatCounters::VMSTAT_PGALLOC_MOVABLE},
-    {"pgfree", protos::pbzero::VmstatCounters::VMSTAT_PGFREE},
-    {"pgactivate", protos::pbzero::VmstatCounters::VMSTAT_PGACTIVATE},
-    {"pgdeactivate", protos::pbzero::VmstatCounters::VMSTAT_PGDEACTIVATE},
-    {"pgfault", protos::pbzero::VmstatCounters::VMSTAT_PGFAULT},
-    {"pgmajfault", protos::pbzero::VmstatCounters::VMSTAT_PGMAJFAULT},
-    {"pgrefill_dma", protos::pbzero::VmstatCounters::VMSTAT_PGREFILL_DMA},
-    {"pgrefill_normal", protos::pbzero::VmstatCounters::VMSTAT_PGREFILL_NORMAL},
-    {"pgrefill_movable",
-     protos::pbzero::VmstatCounters::VMSTAT_PGREFILL_MOVABLE},
-    {"pgsteal_kswapd_dma",
-     protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_KSWAPD_DMA},
-    {"pgsteal_kswapd_normal",
-     protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_KSWAPD_NORMAL},
-    {"pgsteal_kswapd_movable",
-     protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_KSWAPD_MOVABLE},
-    {"pgsteal_direct_dma",
-     protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_DIRECT_DMA},
-    {"pgsteal_direct_normal",
-     protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_DIRECT_NORMAL},
-    {"pgsteal_direct_movable",
-     protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_DIRECT_MOVABLE},
-    {"pgscan_kswapd_dma",
-     protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_KSWAPD_DMA},
-    {"pgscan_kswapd_normal",
-     protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_KSWAPD_NORMAL},
-    {"pgscan_kswapd_movable",
-     protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_KSWAPD_MOVABLE},
-    {"pgscan_direct_dma",
-     protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_DIRECT_DMA},
-    {"pgscan_direct_normal",
-     protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_DIRECT_NORMAL},
-    {"pgscan_direct_movable",
-     protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_DIRECT_MOVABLE},
-    {"pgscan_direct_throttle",
-     protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_DIRECT_THROTTLE},
-    {"pginodesteal", protos::pbzero::VmstatCounters::VMSTAT_PGINODESTEAL},
-    {"slabs_scanned", protos::pbzero::VmstatCounters::VMSTAT_SLABS_SCANNED},
-    {"kswapd_inodesteal",
-     protos::pbzero::VmstatCounters::VMSTAT_KSWAPD_INODESTEAL},
-    {"kswapd_low_wmark_hit_quickly",
-     protos::pbzero::VmstatCounters::VMSTAT_KSWAPD_LOW_WMARK_HIT_QUICKLY},
-    {"kswapd_high_wmark_hit_quickly",
-     protos::pbzero::VmstatCounters::VMSTAT_KSWAPD_HIGH_WMARK_HIT_QUICKLY},
-    {"pageoutrun", protos::pbzero::VmstatCounters::VMSTAT_PAGEOUTRUN},
-    {"allocstall", protos::pbzero::VmstatCounters::VMSTAT_ALLOCSTALL},
-    {"pgrotated", protos::pbzero::VmstatCounters::VMSTAT_PGROTATED},
-    {"drop_pagecache", protos::pbzero::VmstatCounters::VMSTAT_DROP_PAGECACHE},
-    {"drop_slab", protos::pbzero::VmstatCounters::VMSTAT_DROP_SLAB},
-    {"pgmigrate_success",
-     protos::pbzero::VmstatCounters::VMSTAT_PGMIGRATE_SUCCESS},
-    {"pgmigrate_fail", protos::pbzero::VmstatCounters::VMSTAT_PGMIGRATE_FAIL},
-    {"compact_migrate_scanned",
-     protos::pbzero::VmstatCounters::VMSTAT_COMPACT_MIGRATE_SCANNED},
-    {"compact_free_scanned",
-     protos::pbzero::VmstatCounters::VMSTAT_COMPACT_FREE_SCANNED},
-    {"compact_isolated",
-     protos::pbzero::VmstatCounters::VMSTAT_COMPACT_ISOLATED},
-    {"compact_stall", protos::pbzero::VmstatCounters::VMSTAT_COMPACT_STALL},
-    {"compact_fail", protos::pbzero::VmstatCounters::VMSTAT_COMPACT_FAIL},
-    {"compact_success", protos::pbzero::VmstatCounters::VMSTAT_COMPACT_SUCCESS},
-    {"compact_daemon_wake",
-     protos::pbzero::VmstatCounters::VMSTAT_COMPACT_DAEMON_WAKE},
-    {"unevictable_pgs_culled",
-     protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_CULLED},
-    {"unevictable_pgs_scanned",
-     protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_SCANNED},
-    {"unevictable_pgs_rescued",
-     protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_RESCUED},
-    {"unevictable_pgs_mlocked",
-     protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_MLOCKED},
-    {"unevictable_pgs_munlocked",
-     protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_MUNLOCKED},
-    {"unevictable_pgs_cleared",
-     protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_CLEARED},
-    {"unevictable_pgs_stranded",
-     protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_STRANDED},
-    {"nr_zspages", protos::pbzero::VmstatCounters::VMSTAT_NR_ZSPAGES},
-    {"nr_ion_heap", protos::pbzero::VmstatCounters::VMSTAT_NR_ION_HEAP},
-    {"nr_gpu_heap", protos::pbzero::VmstatCounters::VMSTAT_NR_GPU_HEAP},
-};
-
-// Returns a lookup table of meminfo counter names addressable by counter id.
-inline std::vector<const char*> BuildMeminfoCounterNames() {
-  int max_id = 0;
-  for (size_t i = 0; i < base::ArraySize(kMeminfoKeys); i++)
-    max_id = std::max(max_id, kMeminfoKeys[i].id);
-  std::vector<const char*> v;
-  v.resize(static_cast<size_t>(max_id) + 1);
-  for (size_t i = 0; i < base::ArraySize(kMeminfoKeys); i++)
-    v[static_cast<size_t>(kMeminfoKeys[i].id)] = kMeminfoKeys[i].str;
-  return v;
-}
-
-inline std::vector<const char*> BuildVmstatCounterNames() {
-  int max_id = 0;
-  for (size_t i = 0; i < base::ArraySize(kVmstatKeys); i++)
-    max_id = std::max(max_id, kVmstatKeys[i].id);
-  std::vector<const char*> v;
-  v.resize(static_cast<size_t>(max_id) + 1);
-  for (size_t i = 0; i < base::ArraySize(kVmstatKeys); i++)
-    v[static_cast<size_t>(kVmstatKeys[i].id)] = kVmstatKeys[i].str;
-  return v;
-}
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACED_SYS_STATS_COUNTERS_H_
diff --git a/include/perfetto/ext/traced/traced.h b/include/perfetto/ext/traced/traced.h
deleted file mode 100644
index 042f9ec..0000000
--- a/include/perfetto/ext/traced/traced.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_TRACED_TRACED_H_
-#define INCLUDE_PERFETTO_EXT_TRACED_TRACED_H_
-
-namespace perfetto {
-
-int ServiceMain(int argc, char** argv);
-int ProbesMain(int argc, char** argv);
-int PerfettoCmdMain(int argc, char** argv);
-int TriggerPerfettoMain(int argc, char** argv);
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACED_TRACED_H_
diff --git a/include/perfetto/ext/tracing/core/BUILD.gn b/include/perfetto/ext/tracing/core/BUILD.gn
deleted file mode 100644
index e88fd768..0000000
--- a/include/perfetto/ext/tracing/core/BUILD.gn
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (C) 2017 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.
-
-source_set("core") {
-  public_deps = [
-    "../../../../../protos/perfetto/common:cpp",
-    "../../../tracing/core",
-    "../../base",
-  ]
-  sources = [
-    "basic_types.h",
-    "commit_data_request.h",
-    "consumer.h",
-    "observable_events.h",
-    "producer.h",
-    "shared_memory.h",
-    "shared_memory_abi.h",
-    "shared_memory_arbiter.h",
-    "slice.h",
-    "sliced_protobuf_input_stream.h",
-    "startup_trace_writer.h",
-    "startup_trace_writer_registry.h",
-    "trace_packet.h",
-    "trace_stats.h",
-    "trace_writer.h",
-    "tracing_service.h",
-  ]
-}
diff --git a/include/perfetto/ext/tracing/core/basic_types.h b/include/perfetto/ext/tracing/core/basic_types.h
deleted file mode 100644
index cf05dd4..0000000
--- a/include/perfetto/ext/tracing/core/basic_types.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_TRACING_CORE_BASIC_TYPES_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_CORE_BASIC_TYPES_H_
-
-#include "perfetto/base/build_config.h"
-
-#include <stddef.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-using uid_t = unsigned int;
-#endif
-
-namespace perfetto {
-
-// Unique within the scope of the tracing service.
-using TracingSessionID = uint64_t;
-
-// Unique within the scope of the tracing service.
-using ProducerID = uint16_t;
-
-// Unique within the scope of the tracing service.
-using DataSourceInstanceID = uint64_t;
-
-// Unique within the scope of a Producer.
-using WriterID = uint16_t;
-
-// Unique within the scope of the tracing service.
-using FlushRequestID = uint64_t;
-
-// We need one FD per producer and we are not going to be able to keep > 64k FDs
-// open in the service.
-static constexpr ProducerID kMaxProducerID = static_cast<ProducerID>(-1);
-
-// 1024 Writers per producer seems a resonable bound. This reduces the ability
-// to memory-DoS the service by having to keep track of too many writer IDs.
-static constexpr WriterID kMaxWriterID = static_cast<WriterID>((1 << 10) - 1);
-
-// Unique within the scope of a {ProducerID, WriterID} tuple.
-using ChunkID = uint32_t;
-static constexpr ChunkID kMaxChunkID = static_cast<ChunkID>(-1);
-
-// Unique within the scope of the tracing service.
-using BufferID = uint16_t;
-
-// Keep this in sync with SharedMemoryABI::PageHeader::target_buffer.
-static constexpr BufferID kMaxTraceBufferID = static_cast<BufferID>(-1);
-
-// Unique within the scope of a tracing session.
-using PacketSequenceID = uint32_t;
-// Used for extra packets emitted by the service, such as statistics.
-static constexpr PacketSequenceID kInvalidPacketSequenceID = 0;
-static constexpr PacketSequenceID kServicePacketSequenceID = 1;
-static constexpr PacketSequenceID kMaxPacketSequenceID =
-    static_cast<PacketSequenceID>(-1);
-
-// TODO(primiano): temporary. The buffer page size should be configurable by
-// consumers.
-static constexpr size_t kBufferPageSize = 8192;
-
-constexpr uid_t kInvalidUid = static_cast<uid_t>(-1);
-
-constexpr uint32_t kDefaultFlushTimeoutMs = 5000;
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_BASIC_TYPES_H_
diff --git a/include/perfetto/ext/tracing/core/commit_data_request.h b/include/perfetto/ext/tracing/core/commit_data_request.h
deleted file mode 100644
index baff757..0000000
--- a/include/perfetto/ext/tracing/core/commit_data_request.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_TRACING_CORE_COMMIT_DATA_REQUEST_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_CORE_COMMIT_DATA_REQUEST_H_
-
-// This header exists only for legacy code that used to refer to the
-// checked-in auto-generated code, before it was moved to be a build-time gen
-// rule. DO NOT add any new includes to this header, instead directly include
-// the one below.
-// TODO(primiano): cleanup call-sites and remove this header.
-#include "protos/perfetto/common/commit_data_request.gen.h"
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_COMMIT_DATA_REQUEST_H_
diff --git a/include/perfetto/ext/tracing/core/consumer.h b/include/perfetto/ext/tracing/core/consumer.h
deleted file mode 100644
index ccbd072..0000000
--- a/include/perfetto/ext/tracing/core/consumer.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_TRACING_CORE_CONSUMER_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_CORE_CONSUMER_H_
-
-#include <vector>
-
-#include "perfetto/base/export.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/observable_events.h"
-
-namespace perfetto {
-
-class TraceConfig;
-class TracePacket;
-class TraceStats;
-class TracingServiceState;
-
-class PERFETTO_EXPORT Consumer {
- public:
-  virtual ~Consumer();
-
-  // Called by Service (or more typically by the transport layer, on behalf of
-  // the remote Service), once the Consumer <> Service connection has been
-  // established.
-  virtual void OnConnect() = 0;
-
-  // Called by the Service or by the transport layer if the connection with the
-  // service drops, either voluntarily (e.g., by destroying the ConsumerEndpoint
-  // obtained through Service::ConnectConsumer()) or involuntarily (e.g., if the
-  // Service process crashes).
-  virtual void OnDisconnect() = 0;
-
-  // Called by the Service after the tracing session has ended. This can happen
-  // for a variety of reasons:
-  // - The consumer explicitly called DisableTracing()
-  // - The TraceConfig's |duration_ms| has been reached.
-  // - The TraceConfig's |max_file_size_bytes| has been reached.
-  // - An error occurred while trying to enable tracing.
-  virtual void OnTracingDisabled() = 0;
-
-  // Called back by the Service (or transport layer) after invoking
-  // TracingService::ConsumerEndpoint::ReadBuffers(). This function can be
-  // called more than once. Each invocation can carry one or more
-  // TracePacket(s). Upon the last call, |has_more| is set to true (i.e.
-  // |has_more| is a !EOF).
-  virtual void OnTraceData(std::vector<TracePacket>, bool has_more) = 0;
-
-  // Called back by the Service (or transport layer) after invoking
-  // TracingService::ConsumerEndpoint::Detach().
-  // The consumer can disconnect at this point and the trace session will keep
-  // on going. A new consumer can later re-attach passing back the same |key|
-  // passed to Detach(), but only if the two requests come from the same uid.
-  virtual void OnDetach(bool success) = 0;
-
-  // Called back by the Service (or transport layer) after invoking
-  // TracingService::ConsumerEndpoint::Attach().
-  virtual void OnAttach(bool success, const TraceConfig&) = 0;
-
-  // Called back by the Service (or transport layer) after invoking
-  // TracingService::ConsumerEndpoint::GetTraceStats().
-  virtual void OnTraceStats(bool success, const TraceStats&) = 0;
-
-  // Called back by the Service (or transport layer) after invoking
-  // TracingService::ConsumerEndpoint::ObserveEvents() whenever one or more
-  // ObservableEvents of enabled event types occur.
-  virtual void OnObservableEvents(const ObservableEvents&) = 0;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_CONSUMER_H_
diff --git a/include/perfetto/ext/tracing/core/observable_events.h b/include/perfetto/ext/tracing/core/observable_events.h
deleted file mode 100644
index abf408d..0000000
--- a/include/perfetto/ext/tracing/core/observable_events.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_TRACING_CORE_OBSERVABLE_EVENTS_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_CORE_OBSERVABLE_EVENTS_H_
-
-// This header exists only for legacy code that used to refer to the
-// checked-in auto-generated code, before it was moved to be a build-time gen
-// rule. DO NOT add any new includes to this header, instead directly include
-// the one below.
-// TODO(primiano): cleanup call-sites and remove this header.
-#include "protos/perfetto/common/observable_events.gen.h"
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_OBSERVABLE_EVENTS_H_
diff --git a/include/perfetto/ext/tracing/core/producer.h b/include/perfetto/ext/tracing/core/producer.h
deleted file mode 100644
index 30775f7..0000000
--- a/include/perfetto/ext/tracing/core/producer.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_TRACING_CORE_PRODUCER_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_CORE_PRODUCER_H_
-
-#include "perfetto/base/export.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-
-namespace perfetto {
-
-class DataSourceConfig;
-class SharedMemory;
-
-// A Producer is an entity that connects to the write-only port of the Service
-// and exposes the ability to produce performance data on-demand. The lifecycle
-// of a Producer is as follows:
-// 1. The producer connects to the service and advertises its data sources
-//    (e.g., the ability to get kernel ftraces, to list process stats).
-// 2. The service acknowledges the connection and sends over the SharedMemory
-//    region that will be used to exchange data (together with the signalling
-//    API TracingService::ProducerEndpoint::OnPageAcquired()/OnPageReleased()).
-// 3. At some point later on, the Service asks the Producer to turn on some of
-//    the previously registered data sources, together with some configuration
-//    parameters. This happens via the StartDataSource() callback.
-// 4. In response to that the Producer will spawn an instance of the given data
-//    source and inject its data into the shared memory buffer (obtained during
-//    OnConnect).
-// This interface is subclassed by:
-//  1. The actual producer code in the clients e.g., the ftrace reader process.
-//  2. The transport layer when interposing RPC between service and producers.
-class PERFETTO_EXPORT Producer {
- public:
-  virtual ~Producer();
-
-  // Called by Service (or more typically by the transport layer, on behalf of
-  // the remote Service), once the Producer <> Service connection has been
-  // established.
-  virtual void OnConnect() = 0;
-
-  // Called by the Service or by the transport layer if the connection with the
-  // service drops, either voluntarily (e.g., by destroying the ProducerEndpoint
-  // obtained through Service::ConnectProducer()) or involuntarily (e.g., if the
-  // Service process crashes).
-  // The Producer is expected to tear down all its data sources if this happens.
-  // Once this call returns it is possible to safely destroy the Producer
-  // instance.
-  virtual void OnDisconnect() = 0;
-
-  // Called by the Service after OnConnect but before the first DataSource is
-  // created. Can be used for any setup required before tracing begins.
-  virtual void OnTracingSetup() = 0;
-
-  // The lifecycle methods below are always called in the following sequence:
-  // SetupDataSource  -> StartDataSource -> StopDataSource.
-  // Or, in the edge case where a trace is aborted immediately:
-  // SetupDataSource  -> StopDataSource.
-  // The Setup+Start call sequence is always guaranateed, regardless of the
-  // TraceConfig.deferred_start flags.
-  // Called by the Service to configure one of the data sources previously
-  // registered through TracingService::ProducerEndpoint::RegisterDataSource().
-  // This method is always called before StartDataSource. There is always a
-  // SetupDataSource() call before each StartDataSource() call.
-  // Args:
-  // - DataSourceInstanceID is an identifier chosen by the Service that should
-  //   be assigned to the newly created data source instance. It is used to
-  //   match the StopDataSource() request below.
-  // - DataSourceConfig is the configuration for the new data source (e.g.,
-  //   tells which trace categories to enable).
-  virtual void SetupDataSource(DataSourceInstanceID,
-                               const DataSourceConfig&) = 0;
-
-  // Called by the Service to turn on one of the data sources previously
-  // registered through TracingService::ProducerEndpoint::RegisterDataSource()
-  // and initialized through SetupDataSource().
-  // Both arguments are guaranteed to be identical to the ones passed to the
-  // prior SetupDataSource() call.
-  virtual void StartDataSource(DataSourceInstanceID,
-                               const DataSourceConfig&) = 0;
-
-  // Called by the Service to shut down an existing data source instance.
-  virtual void StopDataSource(DataSourceInstanceID) = 0;
-
-  // Called by the service to request the Producer to commit the data of the
-  // given data sources and return their chunks into the shared memory buffer.
-  // The Producer is expected to invoke NotifyFlushComplete(FlushRequestID) on
-  // the Service after the data has been committed. The producer has to either
-  // reply to the flush requests in order, or can just reply to the latest one
-  // Upon seeing a NotifyFlushComplete(N), the service will assume that all
-  // flushes < N have also been committed.
-  virtual void Flush(FlushRequestID,
-                     const DataSourceInstanceID* data_source_ids,
-                     size_t num_data_sources) = 0;
-
-  // Called by the service to instruct the given data sources to stop referring
-  // to any trace contents emitted so far. The intent is that after processing
-  // this call, the rest of the trace should be parsable even if all of the
-  // packets emitted so far have been lost (for example due to ring buffer
-  // overwrites).
-  //
-  // Called only for Producers with active data sources that have opted in by
-  // setting |handles_incremental_state_clear| in their DataSourceDescriptor.
-  //
-  // The way this call is handled is up to the individual Producer
-  // implementation. Some might wish to emit invalidation markers in the trace
-  // (see TracePacket.incremental_state_cleared for an existing field), and
-  // handle them when parsing the trace.
-  virtual void ClearIncrementalState(
-      const DataSourceInstanceID* data_source_ids,
-      size_t num_data_sources) = 0;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_PRODUCER_H_
diff --git a/include/perfetto/ext/tracing/core/shared_memory.h b/include/perfetto/ext/tracing/core/shared_memory.h
deleted file mode 100644
index 3c77e07..0000000
--- a/include/perfetto/ext/tracing/core/shared_memory.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_H_
-
-#include <stddef.h>
-
-#include <memory>
-
-#include "perfetto/base/export.h"
-
-namespace perfetto {
-
-// An abstract interface that models the shared memory region shared between
-// Service and Producer. The concrete implementation of this is up to the
-// transport layer. This can be as simple as a malloc()-ed buffer, if both
-// Producer and Service are hosted in the same process, or some posix shared
-// memory for the out-of-process case (see src/unix_rpc).
-// Both this class and the Factory are subclassed by the transport layer, which
-// will attach platform specific fields to it (e.g., a unix file descriptor).
-class PERFETTO_EXPORT SharedMemory {
- public:
-  class PERFETTO_EXPORT Factory {
-   public:
-    virtual ~Factory();
-    virtual std::unique_ptr<SharedMemory> CreateSharedMemory(size_t) = 0;
-  };
-
-  // The transport layer is expected to tear down the resource associated to
-  // this object region when destroyed.
-  virtual ~SharedMemory();
-
-  virtual void* start() const = 0;
-  virtual size_t size() const = 0;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_H_
diff --git a/include/perfetto/ext/tracing/core/shared_memory_abi.h b/include/perfetto/ext/tracing/core/shared_memory_abi.h
deleted file mode 100644
index 9d17850..0000000
--- a/include/perfetto/ext/tracing/core/shared_memory_abi.h
+++ /dev/null
@@ -1,588 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_ABI_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_ABI_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <array>
-#include <atomic>
-#include <bitset>
-#include <thread>
-#include <type_traits>
-#include <utility>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/protozero/proto_utils.h"
-
-namespace perfetto {
-
-// This file defines the binary interface of the memory buffers shared between
-// Producer and Service. This is a long-term stable ABI and has to be backwards
-// compatible to deal with mismatching Producer and Service versions.
-//
-// Overview
-// --------
-// SMB := "Shared Memory Buffer".
-// In the most typical case of a multi-process architecture (i.e. Producer and
-// Service are hosted by different processes), a Producer means almost always
-// a "client process producing data" (almost: in some cases a process might host
-// > 1 Producer, if it links two libraries, independent of each other, that both
-// use Perfetto tracing).
-// The Service has one SMB for each Producer.
-// A producer has one or (typically) more data sources. They all share the same
-// SMB.
-// The SMB is a staging area to decouple data sources living in the Producer
-// and allow them to do non-blocking async writes.
-// The SMB is *not* the ultimate logging buffer seen by the Consumer. That one
-// is larger (~MBs) and not shared with Producers.
-// Each SMB is small, typically few KB. Its size is configurable by the producer
-// within a max limit of ~MB (see kMaxShmSize in tracing_service_impl.cc).
-// The SMB is partitioned into fixed-size Page(s). The size of the Pages are
-// determined by each Producer at connection time and cannot be changed.
-// Hence, different producers can have SMB(s) that have a different Page size
-// from each other, but the page size will be constant throughout all the
-// lifetime of the SMB.
-// Page(s) are partitioned by the Producer into variable size Chunk(s):
-//
-// +------------+      +--------------------------+
-// | Producer 1 |  <-> |      SMB 1 [~32K - 1MB]  |
-// +------------+      +--------+--------+--------+
-//                     |  Page  |  Page  |  Page  |
-//                     +--------+--------+--------+
-//                     | Chunk  |        | Chunk  |
-//                     +--------+  Chunk +--------+ <----+
-//                     | Chunk  |        | Chunk  |      |
-//                     +--------+--------+--------+      +---------------------+
-//                                                       |       Service       |
-// +------------+      +--------------------------+      +---------------------+
-// | Producer 2 |  <-> |      SMB 2 [~32K - 1MB]  |     /| large ring buffers  |
-// +------------+      +--------+--------+--------+ <--+ | (100K - several MB) |
-//                     |  Page  |  Page  |  Page  |      +---------------------+
-//                     +--------+--------+--------+
-//                     | Chunk  |        | Chunk  |
-//                     +--------+  Chunk +--------+
-//                     | Chunk  |        | Chunk  |
-//                     +--------+--------+--------+
-//
-// * Sizes of both SMB and ring buffers are purely indicative and decided at
-// configuration time by the Producer (for SMB sizes) and the Consumer (for the
-// final ring buffer size).
-
-// Page
-// ----
-// A page is a portion of the shared memory buffer and defines the granularity
-// of the interaction between the Producer and tracing Service. When scanning
-// the shared memory buffer to determine if something should be moved to the
-// central logging buffers, the Service most of the times looks at and moves
-// whole pages. Similarly, the Producer sends an IPC to invite the Service to
-// drain the shared memory buffer only when a whole page is filled.
-// Having fixed the total SMB size (hence the total memory overhead), the page
-// size is a triangular tradeoff between:
-// 1) IPC traffic: smaller pages -> more IPCs.
-// 2) Producer lock freedom: larger pages -> larger chunks -> data sources can
-//    write more data without needing to swap chunks and synchronize.
-// 3) Risk of write-starving the SMB: larger pages -> higher chance that the
-//    Service won't manage to drain them and the SMB remains full.
-// The page size, on the other side, has no implications on wasted memory due to
-// fragmentations (see Chunk below).
-// The size of the page is chosen by the Service at connection time and stays
-// fixed throughout all the lifetime of the Producer. Different producers (i.e.
-// ~ different client processes) can use different page sizes.
-// The page size must be an integer multiple of 4k (this is to allow VM page
-// stealing optimizations) and obviously has to be an integer divisor of the
-// total SMB size.
-
-// Chunk
-// -----
-// A chunk is a portion of a Page which is written and handled by a Producer.
-// A chunk contains a linear sequence of TracePacket(s) (the root proto).
-// A chunk cannot be written concurrently by two data sources. Protobufs must be
-// encoded as contiguous byte streams and cannot be interleaved. Therefore, on
-// the Producer side, a chunk is almost always owned exclusively by one thread
-// (% extremely peculiar slow-path cases).
-// Chunks are essentially single-writer single-thread lock-free arenas. Locking
-// happens only when a Chunk is full and a new one needs to be acquired.
-// Locking happens only within the scope of a Producer process. There is no
-// inter-process locking. The Producer cannot lock the Service and viceversa.
-// In the worst case, any of the two can starve the SMB, by marking all chunks
-// as either being read or written. But that has the only side effect of
-// losing the trace data.
-// The Producer can decide to partition each page into a number of limited
-// configurations (e.g., 1 page == 1 chunk, 1 page == 2 chunks and so on).
-
-// TracePacket
-// -----------
-// Is the atom of tracing. Putting aside pages and chunks a trace is merely a
-// sequence of TracePacket(s). TracePacket is the root protobuf message.
-// A TracePacket can span across several chunks (hence even across several
-// pages). A TracePacket can therefore be >> chunk size, >> page size and even
-// >> SMB size. The Chunk header carries metadata to deal with the TracePacket
-// splitting case.
-
-// Use only explicitly-sized types below. DO NOT use size_t or any architecture
-// dependent size (e.g. size_t) in the struct fields. This buffer will be read
-// and written by processes that have a different bitness in the same OS.
-// Instead it's fine to assume little-endianess. Big-endian is a dream we are
-// not currently pursuing.
-
-class SharedMemoryABI {
- public:
-  // This is due to Chunk::size being 16 bits.
-  static constexpr size_t kMaxPageSize = 64 * 1024;
-
-  // "14" is the max number that can be encoded in a 32 bit atomic word using
-  // 2 state bits per Chunk and leaving 4 bits for the page layout.
-  // See PageLayout below.
-  static constexpr size_t kMaxChunksPerPage = 14;
-
-  // Each TracePacket in the Chunk is prefixed by a 4 bytes redundant VarInt
-  // (see proto_utils.h) stating its size.
-  static constexpr size_t kPacketHeaderSize = 4;
-
-  // TraceWriter specifies this invalid packet/fragment size to signal to the
-  // service that a packet should be discarded, because the TraceWriter couldn't
-  // write its remaining fragments (e.g. because the SMB was exhausted).
-  static constexpr size_t kPacketSizeDropPacket =
-      protozero::proto_utils::kMaxMessageLength;
-
-  // Chunk states and transitions:
-  //    kChunkFree  <----------------+
-  //         |  (Producer)           |
-  //         V                       |
-  //  kChunkBeingWritten             |
-  //         |  (Producer)           |
-  //         V                       |
-  //  kChunkComplete                 |
-  //         |  (Service)            |
-  //         V                       |
-  //  kChunkBeingRead                |
-  //        |   (Service)            |
-  //        +------------------------+
-  enum ChunkState : uint32_t {
-    // The Chunk is free. The Service shall never touch it, the Producer can
-    // acquire it and transition it into kChunkBeingWritten.
-    kChunkFree = 0,
-
-    // The Chunk is being used by the Producer and is not complete yet.
-    // The Service shall never touch kChunkBeingWritten pages.
-    kChunkBeingWritten = 1,
-
-    // The Service is moving the page into its non-shared ring buffer. The
-    // Producer shall never touch kChunkBeingRead pages.
-    kChunkBeingRead = 2,
-
-    // The Producer is done writing the page and won't touch it again. The
-    // Service can now move it to its non-shared ring buffer.
-    // kAllChunksComplete relies on this being == 3.
-    kChunkComplete = 3,
-  };
-  static constexpr const char* kChunkStateStr[] = {"Free", "BeingWritten",
-                                                   "BeingRead", "Complete"};
-
-  enum PageLayout : uint32_t {
-    // The page is fully free and has not been partitioned yet.
-    kPageNotPartitioned = 0,
-
-    // TODO(primiano): Aligning a chunk @ 16 bytes could allow to use faster
-    // intrinsics based on quad-word moves. Do the math and check what is the
-    // fragmentation loss.
-
-    // align4(X) := the largest integer N s.t. (N % 4) == 0 && N <= X.
-    // 8 == sizeof(PageHeader).
-    kPageDiv1 = 1,   // Only one chunk of size: PAGE_SIZE - 8.
-    kPageDiv2 = 2,   // Two chunks of size: align4((PAGE_SIZE - 8) / 2).
-    kPageDiv4 = 3,   // Four chunks of size: align4((PAGE_SIZE - 8) / 4).
-    kPageDiv7 = 4,   // Seven chunks of size: align4((PAGE_SIZE - 8) / 7).
-    kPageDiv14 = 5,  // Fourteen chunks of size: align4((PAGE_SIZE - 8) / 14).
-
-    // The rationale for 7 and 14 above is to maximize the page usage for the
-    // likely case of |page_size| == 4096:
-    // (((4096 - 8) / 14) % 4) == 0, while (((4096 - 8) / 16 % 4)) == 3. So
-    // Div16 would waste 3 * 16 = 48 bytes per page for chunk alignment gaps.
-
-    kPageDivReserved1 = 6,
-    kPageDivReserved2 = 7,
-    kNumPageLayouts = 8,
-  };
-
-  // Keep this consistent with the PageLayout enum above.
-  static constexpr uint32_t kNumChunksForLayout[] = {0, 1, 2, 4, 7, 14, 0, 0};
-
-  // Layout of a Page.
-  // +===================================================+
-  // | Page header [8 bytes]                             |
-  // | Tells how many chunks there are, how big they are |
-  // | and their state (free, read, write, complete).    |
-  // +===================================================+
-  // +***************************************************+
-  // | Chunk #0 header [8 bytes]                         |
-  // | Tells how many packets there are and whether the  |
-  // | whether the 1st and last ones are fragmented.     |
-  // | Also has a chunk id to reassemble fragments.    |
-  // +***************************************************+
-  // +---------------------------------------------------+
-  // | Packet #0 size [varint, up to 4 bytes]            |
-  // + - - - - - - - - - - - - - - - - - - - - - - - - - +
-  // | Packet #0 payload                                 |
-  // | A TracePacket protobuf message                    |
-  // +---------------------------------------------------+
-  //                         ...
-  // + . . . . . . . . . . . . . . . . . . . . . . . . . +
-  // |      Optional padding to maintain aligment        |
-  // + . . . . . . . . . . . . . . . . . . . . . . . . . +
-  // +---------------------------------------------------+
-  // | Packet #N size [varint, up to 4 bytes]            |
-  // + - - - - - - - - - - - - - - - - - - - - - - - - - +
-  // | Packet #N payload                                 |
-  // | A TracePacket protobuf message                    |
-  // +---------------------------------------------------+
-  //                         ...
-  // +***************************************************+
-  // | Chunk #M header [8 bytes]                         |
-  //                         ...
-
-  // Alignment applies to start offset only. The Chunk size is *not* aligned.
-  static constexpr uint32_t kChunkAlignment = 4;
-  static constexpr uint32_t kChunkShift = 2;
-  static constexpr uint32_t kChunkMask = 0x3;
-  static constexpr uint32_t kLayoutMask = 0x70000000;
-  static constexpr uint32_t kLayoutShift = 28;
-  static constexpr uint32_t kAllChunksMask = 0x0FFFFFFF;
-
-  // This assumes that kChunkComplete == 3.
-  static constexpr uint32_t kAllChunksComplete = 0x0FFFFFFF;
-  static constexpr uint32_t kAllChunksFree = 0;
-  static constexpr size_t kInvalidPageIdx = static_cast<size_t>(-1);
-
-  // There is one page header per page, at the beginning of the page.
-  struct PageHeader {
-    // |layout| bits:
-    // [31] [30:28] [27:26] ... [1:0]
-    //  |      |       |     |    |
-    //  |      |       |     |    +---------- ChunkState[0]
-    //  |      |       |     +--------------- ChunkState[12..1]
-    //  |      |       +--------------------- ChunkState[13]
-    //  |      +----------------------------- PageLayout (0 == page fully free)
-    //  +------------------------------------ Reserved for future use
-    std::atomic<uint32_t> layout;
-
-    // If we'll ever going to use this in the future it might come handy
-    // reviving the kPageBeingPartitioned logic (look in git log, it was there
-    // at some point in the past).
-    uint32_t reserved;
-  };
-
-  // There is one Chunk header per chunk (hence PageLayout per page) at the
-  // beginning of each chunk.
-  struct ChunkHeader {
-    enum Flags : uint8_t {
-      // If set, the first TracePacket in the chunk is partial and continues
-      // from |chunk_id| - 1 (within the same |writer_id|).
-      kFirstPacketContinuesFromPrevChunk = 1 << 0,
-
-      // If set, the last TracePacket in the chunk is partial and continues on
-      // |chunk_id| + 1 (within the same |writer_id|).
-      kLastPacketContinuesOnNextChunk = 1 << 1,
-
-      // If set, the last (fragmented) TracePacket in the chunk has holes (even
-      // if the chunk is marked as kChunkComplete) that need to be patched
-      // out-of-band before the chunk can be read.
-      kChunkNeedsPatching = 1 << 2,
-    };
-
-    struct Packets {
-      // Number of valid TracePacket protobuf messages contained in the chunk.
-      // Each TracePacket is prefixed by its own size. This field is
-      // monotonically updated by the Producer with release store semantic when
-      // the packet at position |count| is started. This last packet may not be
-      // considered complete until |count| is incremented for the subsequent
-      // packet or the chunk is completed.
-      uint16_t count : 10;
-      static constexpr size_t kMaxCount = (1 << 10) - 1;
-
-      // See Flags above.
-      uint16_t flags : 6;
-    };
-
-    // A monotonic counter of the chunk within the scoped of a |writer_id|.
-    // The tuple (ProducerID, WriterID, ChunkID) allows to figure out if two
-    // chunks are contiguous (and hence a trace packets spanning across them can
-    // be glued) or we had some holes due to the ring buffer wrapping.
-    // This is set only when transitioning from kChunkFree to kChunkBeingWritten
-    // and remains unchanged throughout the remaining lifetime of the chunk.
-    std::atomic<uint32_t> chunk_id;
-
-    // ID of the writer, unique within the producer.
-    // Like |chunk_id|, this is set only when transitioning from kChunkFree to
-    // kChunkBeingWritten.
-    std::atomic<uint16_t> writer_id;
-
-    // There is no ProducerID here. The service figures that out from the IPC
-    // channel, which is unspoofable.
-
-    // Updated with release-store semantics.
-    std::atomic<Packets> packets;
-  };
-
-  class Chunk {
-   public:
-    Chunk();  // Constructs an invalid chunk.
-
-    // Chunk is move-only, to document the scope of the Acquire/Release
-    // TryLock operations below.
-    Chunk(const Chunk&) = delete;
-    Chunk operator=(const Chunk&) = delete;
-    Chunk(Chunk&&) noexcept;
-    Chunk& operator=(Chunk&&);
-
-    uint8_t* begin() const { return begin_; }
-    uint8_t* end() const { return begin_ + size_; }
-
-    // Size, including Chunk header.
-    size_t size() const { return size_; }
-
-    // Begin of the first packet (or packet fragment).
-    uint8_t* payload_begin() const { return begin_ + sizeof(ChunkHeader); }
-    size_t payload_size() const {
-      PERFETTO_DCHECK(size_ >= sizeof(ChunkHeader));
-      return size_ - sizeof(ChunkHeader);
-    }
-
-    bool is_valid() const { return begin_ && size_; }
-
-    // Index of the chunk within the page [0..13] (13 comes from kPageDiv14).
-    uint8_t chunk_idx() const { return chunk_idx_; }
-
-    ChunkHeader* header() { return reinterpret_cast<ChunkHeader*>(begin_); }
-
-    uint16_t writer_id() {
-      return header()->writer_id.load(std::memory_order_relaxed);
-    }
-
-    // Returns the count of packets and the flags with acquire-load semantics.
-    std::pair<uint16_t, uint8_t> GetPacketCountAndFlags() {
-      auto packets = header()->packets.load(std::memory_order_acquire);
-      const uint16_t packets_count = packets.count;
-      const uint8_t packets_flags = packets.flags;
-      return std::make_pair(packets_count, packets_flags);
-    }
-
-    // Increases |packets.count| with release semantics (note, however, that the
-    // packet count is incremented *before* starting writing a packet). Returns
-    // the new packet count. The increment is atomic but NOT race-free (i.e. no
-    // CAS). Only the Producer is supposed to perform this increment, and it's
-    // supposed to do that in a thread-safe way (holding a lock). A Chunk cannot
-    // be shared by multiple Producer threads without locking. The packet count
-    // is cleared by TryAcquireChunk(), when passing the new header for the
-    // chunk.
-    uint16_t IncrementPacketCount() {
-      ChunkHeader* chunk_header = header();
-      auto packets = chunk_header->packets.load(std::memory_order_relaxed);
-      packets.count++;
-      chunk_header->packets.store(packets, std::memory_order_release);
-      return packets.count;
-    }
-
-    // Increases |packets.count| to the given |packet_count|, but only if
-    // |packet_count| is larger than the current value of |packets.count|.
-    // Returns the new packet count. Same atomicity guarantees as
-    // IncrementPacketCount().
-    uint16_t IncreasePacketCountTo(uint16_t packet_count) {
-      ChunkHeader* chunk_header = header();
-      auto packets = chunk_header->packets.load(std::memory_order_relaxed);
-      if (packets.count < packet_count)
-        packets.count = packet_count;
-      chunk_header->packets.store(packets, std::memory_order_release);
-      return packets.count;
-    }
-
-    // Flags are cleared by TryAcquireChunk(), by passing the new header for
-    // the chunk.
-    void SetFlag(ChunkHeader::Flags flag) {
-      ChunkHeader* chunk_header = header();
-      auto packets = chunk_header->packets.load(std::memory_order_relaxed);
-      packets.flags |= flag;
-      chunk_header->packets.store(packets, std::memory_order_release);
-    }
-
-   private:
-    friend class SharedMemoryABI;
-    Chunk(uint8_t* begin, uint16_t size, uint8_t chunk_idx);
-
-    // Don't add extra fields, keep the move operator fast.
-    uint8_t* begin_ = nullptr;
-    uint16_t size_ = 0;
-    uint8_t chunk_idx_ = 0;
-  };
-
-  // Construct an instance from an existing shared memory buffer.
-  SharedMemoryABI(uint8_t* start, size_t size, size_t page_size);
-  SharedMemoryABI();
-
-  void Initialize(uint8_t* start, size_t size, size_t page_size);
-
-  uint8_t* start() const { return start_; }
-  uint8_t* end() const { return start_ + size_; }
-  size_t size() const { return size_; }
-  size_t page_size() const { return page_size_; }
-  size_t num_pages() const { return num_pages_; }
-  bool is_valid() { return num_pages() > 0; }
-
-  uint8_t* page_start(size_t page_idx) {
-    PERFETTO_DCHECK(page_idx < num_pages_);
-    return start_ + page_size_ * page_idx;
-  }
-
-  PageHeader* page_header(size_t page_idx) {
-    return reinterpret_cast<PageHeader*>(page_start(page_idx));
-  }
-
-  // Returns true if the page is fully clear and has not been partitioned yet.
-  // The state of the page can change at any point after this returns (or even
-  // before). The Producer should use this only as a hint to decide out whether
-  // it should TryPartitionPage() or acquire an individual chunk.
-  bool is_page_free(size_t page_idx) {
-    return page_header(page_idx)->layout.load(std::memory_order_relaxed) == 0;
-  }
-
-  // Returns true if all chunks in the page are kChunkComplete. As above, this
-  // is advisory only. The Service is supposed to use this only to decide
-  // whether to TryAcquireAllChunksForReading() or not.
-  bool is_page_complete(size_t page_idx) {
-    auto layout = page_header(page_idx)->layout.load(std::memory_order_relaxed);
-    const uint32_t num_chunks = GetNumChunksForLayout(layout);
-    if (num_chunks == 0)
-      return false;  // Non partitioned pages cannot be complete.
-    return (layout & kAllChunksMask) ==
-           (kAllChunksComplete & ((1 << (num_chunks * kChunkShift)) - 1));
-  }
-
-  // For testing / debugging only.
-  std::string page_header_dbg(size_t page_idx) {
-    uint32_t x = page_header(page_idx)->layout.load(std::memory_order_relaxed);
-    return std::bitset<32>(x).to_string();
-  }
-
-  // Returns the page layout, which is a bitmap that specifies the chunking
-  // layout of the page and each chunk's current state. Reads with an
-  // acquire-load semantic to ensure a producer's writes corresponding to an
-  // update of the layout (e.g. clearing a chunk's header) are observed
-  // consistently.
-  uint32_t GetPageLayout(size_t page_idx) {
-    return page_header(page_idx)->layout.load(std::memory_order_acquire);
-  }
-
-  // Returns a bitmap in which each bit is set if the corresponding Chunk exists
-  // in the page (according to the page layout) and is free. If the page is not
-  // partitioned it returns 0 (as if the page had no free chunks).
-  uint32_t GetFreeChunks(size_t page_idx);
-
-  // Tries to atomically partition a page with the given |layout|. Returns true
-  // if the page was free and has been partitioned with the given |layout|,
-  // false if the page wasn't free anymore by the time we got there.
-  // If succeeds all the chunks are atomically set in the kChunkFree state.
-  bool TryPartitionPage(size_t page_idx, PageLayout layout);
-
-  // Tries to atomically mark a single chunk within the page as
-  // kChunkBeingWritten. Returns an invalid chunk if the page is not partitioned
-  // or the chunk is not in the kChunkFree state. If succeeds sets the chunk
-  // header to |header|.
-  Chunk TryAcquireChunkForWriting(size_t page_idx,
-                                  size_t chunk_idx,
-                                  const ChunkHeader* header) {
-    return TryAcquireChunk(page_idx, chunk_idx, kChunkBeingWritten, header);
-  }
-
-  // Similar to TryAcquireChunkForWriting. Fails if the chunk isn't in the
-  // kChunkComplete state.
-  Chunk TryAcquireChunkForReading(size_t page_idx, size_t chunk_idx) {
-    return TryAcquireChunk(page_idx, chunk_idx, kChunkBeingRead, nullptr);
-  }
-
-  // The caller must have successfully TryAcquireAllChunksForReading().
-  Chunk GetChunkUnchecked(size_t page_idx,
-                          uint32_t page_layout,
-                          size_t chunk_idx);
-
-  // Puts a chunk into the kChunkComplete state. Returns the page index.
-  size_t ReleaseChunkAsComplete(Chunk chunk) {
-    return ReleaseChunk(std::move(chunk), kChunkComplete);
-  }
-
-  // Puts a chunk into the kChunkFree state. Returns the page index.
-  size_t ReleaseChunkAsFree(Chunk chunk) {
-    return ReleaseChunk(std::move(chunk), kChunkFree);
-  }
-
-  ChunkState GetChunkState(size_t page_idx, size_t chunk_idx) {
-    PageHeader* phdr = page_header(page_idx);
-    uint32_t layout = phdr->layout.load(std::memory_order_relaxed);
-    return GetChunkStateFromLayout(layout, chunk_idx);
-  }
-
-  std::pair<size_t, size_t> GetPageAndChunkIndex(const Chunk& chunk);
-
-  uint16_t GetChunkSizeForLayout(uint32_t page_layout) const {
-    return chunk_sizes_[(page_layout & kLayoutMask) >> kLayoutShift];
-  }
-
-  static ChunkState GetChunkStateFromLayout(uint32_t page_layout,
-                                            size_t chunk_idx) {
-    return static_cast<ChunkState>((page_layout >> (chunk_idx * kChunkShift)) &
-                                   kChunkMask);
-  }
-
-  static constexpr uint32_t GetNumChunksForLayout(uint32_t page_layout) {
-    return kNumChunksForLayout[(page_layout & kLayoutMask) >> kLayoutShift];
-  }
-
-  // Returns a bitmap in which each bit is set if the corresponding Chunk exists
-  // in the page (according to the page layout) and is not free. If the page is
-  // not partitioned it returns 0 (as if the page had no used chunks). Bit N
-  // corresponds to Chunk N.
-  static uint32_t GetUsedChunks(uint32_t page_layout) {
-    const uint32_t num_chunks = GetNumChunksForLayout(page_layout);
-    uint32_t res = 0;
-    for (uint32_t i = 0; i < num_chunks; i++) {
-      res |= ((page_layout & kChunkMask) != kChunkFree) ? (1 << i) : 0;
-      page_layout >>= kChunkShift;
-    }
-    return res;
-  }
-
- private:
-  SharedMemoryABI(const SharedMemoryABI&) = delete;
-  SharedMemoryABI& operator=(const SharedMemoryABI&) = delete;
-
-  Chunk TryAcquireChunk(size_t page_idx,
-                        size_t chunk_idx,
-                        ChunkState,
-                        const ChunkHeader*);
-  size_t ReleaseChunk(Chunk chunk, ChunkState);
-
-  uint8_t* start_ = nullptr;
-  size_t size_ = 0;
-  size_t page_size_ = 0;
-  size_t num_pages_ = 0;
-  std::array<uint16_t, kNumPageLayouts> chunk_sizes_;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_ABI_H_
diff --git a/include/perfetto/ext/tracing/core/shared_memory_arbiter.h b/include/perfetto/ext/tracing/core/shared_memory_arbiter.h
deleted file mode 100644
index 2465d43..0000000
--- a/include/perfetto/ext/tracing/core/shared_memory_arbiter.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_ARBITER_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_ARBITER_H_
-
-#include <stddef.h>
-
-#include <functional>
-#include <memory>
-#include <vector>
-
-#include "perfetto/base/export.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
-#include "perfetto/tracing/buffer_exhausted_policy.h"
-
-namespace perfetto {
-
-namespace base {
-class TaskRunner;
-}
-
-class CommitDataRequest;
-class StartupTraceWriter;
-class StartupTraceWriterRegistry;
-class SharedMemory;
-class TraceWriter;
-
-// Used by the Producer-side of the transport layer to vend TraceWriters
-// from the SharedMemory it receives from the Service-side.
-class PERFETTO_EXPORT SharedMemoryArbiter {
- public:
-  virtual ~SharedMemoryArbiter();
-
-  // Creates a new TraceWriter and assigns it a new WriterID. The WriterID is
-  // written in each chunk header owned by a given TraceWriter and is used by
-  // the Service to reconstruct TracePackets written by the same TraceWriter.
-  // Returns null impl of TraceWriter if all WriterID slots are exhausted.
-  virtual std::unique_ptr<TraceWriter> CreateTraceWriter(
-      BufferID target_buffer,
-      BufferExhaustedPolicy buffer_exhausted_policy =
-          BufferExhaustedPolicy::kDefault) = 0;
-
-  // Binds the provided unbound StartupTraceWriterRegistry to the arbiter's SMB.
-  // Normally this happens when the perfetto service has been initialized and we
-  // want to rebind all the writers created in the early startup phase.
-  //
-  // All StartupTraceWriters created by the registry are bound to the arbiter
-  // and the given target buffer. The writers may not be bound immediately if
-  // they are concurrently being written to or if this method isn't called on
-  // the arbiter's TaskRunner. The registry will retry on the arbiter's
-  // TaskRunner until all writers were bound successfully.
-  //
-  // The commit of the StartupTraceWriters' locally buffered data to the SMB is
-  // rate limited to avoid exhausting the SMB, and may continue asynchronously
-  // even after all writers were bound.
-  //
-  // By calling this method, the registry's ownership is transferred to the
-  // arbiter. The arbiter will delete the registry once all writers were bound.
-  //
-  // TODO(eseckler): Make target buffer assignment more flexible (i.e. per
-  // writer). For now, embedders can use multiple registries instead.
-  virtual void BindStartupTraceWriterRegistry(
-      std::unique_ptr<StartupTraceWriterRegistry>,
-      BufferID target_buffer) = 0;
-
-  // Notifies the service that all data for the given FlushRequestID has been
-  // committed in the shared memory buffer.
-  virtual void NotifyFlushComplete(FlushRequestID) = 0;
-
-  // Implemented in src/core/shared_memory_arbiter_impl.cc.
-  // Args:
-  // |SharedMemory|: the shared memory buffer to use.
-  // |page_size|: a multiple of 4KB that defines the granularity of tracing
-  // pages. See tradeoff considerations in shared_memory_abi.h.
-  // |ProducerEndpoint|: The service's producer endpoint used e.g. to commit
-  // chunks and register trace writers.
-  // |TaskRunner|: Task runner for perfetto's main thread, which executes the
-  // OnPagesCompleteCallback and IPC calls to the |ProducerEndpoint|.
-  static std::unique_ptr<SharedMemoryArbiter> CreateInstance(
-      SharedMemory*,
-      size_t page_size,
-      TracingService::ProducerEndpoint*,
-      base::TaskRunner*);
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_SHARED_MEMORY_ARBITER_H_
diff --git a/include/perfetto/ext/tracing/core/slice.h b/include/perfetto/ext/tracing/core/slice.h
deleted file mode 100644
index b2db3d0..0000000
--- a/include/perfetto/ext/tracing/core/slice.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_TRACING_CORE_SLICE_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_CORE_SLICE_H_
-
-#include <stddef.h>
-#include <string.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "perfetto/base/logging.h"
-
-namespace perfetto {
-
-// A simple wrapper around a virtually contiguous memory range that contains a
-// TracePacket, or just a portion of it.
-struct Slice {
-  Slice() : start(nullptr), size(0) {}
-  Slice(const void* st, size_t sz) : start(st), size(sz) {}
-
-  // Used to inherit ownership of a buffer from a protobuf via release_str().
-  explicit Slice(std::unique_ptr<std::string> str)
-      : start(&(*str)[0]), size(str->size()), moved_str_data_(std::move(str)) {}
-
-  Slice(Slice&& other) noexcept = default;
-
-  // Create a Slice which owns |size| bytes of memory.
-  static Slice Allocate(size_t size) {
-    Slice slice;
-    slice.own_data_.reset(new uint8_t[size]);
-    slice.start = &slice.own_data_[0];
-    slice.size = size;
-    return slice;
-  }
-
-  uint8_t* own_data() {
-    PERFETTO_DCHECK(own_data_);
-    return own_data_.get();
-  }
-
-  const void* start;
-  size_t size;
-
- private:
-  Slice(const Slice&) = delete;
-  void operator=(const Slice&) = delete;
-
-  std::unique_ptr<uint8_t[]> own_data_;
-  std::unique_ptr<std::string> moved_str_data_;
-};
-
-// TODO(primiano): most TracePacket(s) fit in a slice or two. We need something
-// a bit more clever here that has inline capacity for 2 slices and then uses a
-// std::forward_list or a std::vector for the less likely cases.
-using Slices = std::vector<Slice>;
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_SLICE_H_
diff --git a/include/perfetto/ext/tracing/core/sliced_protobuf_input_stream.h b/include/perfetto/ext/tracing/core/sliced_protobuf_input_stream.h
deleted file mode 100644
index 1a1029c..0000000
--- a/include/perfetto/ext/tracing/core/sliced_protobuf_input_stream.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_TRACING_CORE_SLICED_PROTOBUF_INPUT_STREAM_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_CORE_SLICED_PROTOBUF_INPUT_STREAM_H_
-
-#include "perfetto/ext/tracing/core/slice.h"
-
-#include <stdint.h>
-#include <utility>
-
-#include <google/protobuf/io/zero_copy_stream.h>
-
-#include "perfetto/base/export.h"
-
-namespace perfetto {
-
-using ZeroCopyInputStream = google::protobuf::io::ZeroCopyInputStream;
-
-// Wraps a sequence of Slice(s) in a protobuf ZeroCopyInputStream that can be
-// passed to protobuf::Message::ParseFromZeroCopyStream().
-class PERFETTO_EXPORT SlicedProtobufInputStream : public ZeroCopyInputStream {
- public:
-  // This indirection deals with the fact that the public protobuf library and
-  // the internal one diverged on this type. The internal doesn's use a custom
-  // defined type. The public one uses a typedef that isn't compatible with
-  // stdint's int64_t (long long vs long). So insted of trying to use
-  // google::protobuf::int64, infer the type from the return value of the
-  // ByteCount().
-  using int64 = decltype(std::declval<ZeroCopyInputStream>().ByteCount());
-
-  explicit SlicedProtobufInputStream(const Slices*);
-  ~SlicedProtobufInputStream() override;
-
-  // ZeroCopyInputStream implementation. See zero_copy_stream.h for the API
-  // contract of the methods below.
-  bool Next(const void** data, int* size) override;
-  void BackUp(int count) override;
-  bool Skip(int count) override;
-  int64 ByteCount() const override;
-
- private:
-  bool Validate() const;
-
-  const Slices* const slices_;
-  Slices::const_iterator cur_slice_;
-  size_t pos_in_cur_slice_ = 0;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_SLICED_PROTOBUF_INPUT_STREAM_H_
diff --git a/include/perfetto/ext/tracing/core/startup_trace_writer.h b/include/perfetto/ext/tracing/core/startup_trace_writer.h
deleted file mode 100644
index 021eb35..0000000
--- a/include/perfetto/ext/tracing/core/startup_trace_writer.h
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_EXT_TRACING_CORE_STARTUP_TRACE_WRITER_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_CORE_STARTUP_TRACE_WRITER_H_
-
-#include <memory>
-#include <mutex>
-#include <set>
-#include <vector>
-
-#include "perfetto/base/export.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/thread_checker.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/shared_memory_abi.h"
-#include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "perfetto/protozero/message_handle.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "perfetto/protozero/scattered_stream_writer.h"
-#include "perfetto/tracing/buffer_exhausted_policy.h"
-
-namespace perfetto {
-
-class SharedMemoryArbiterImpl;
-class StartupTraceWriterRegistryHandle;
-
-namespace protos {
-namespace pbzero {
-class TracePacket;
-}  // namespace pbzero
-}  // namespace protos
-
-// Facilitates writing trace events in early phases of an application's startup
-// when the perfetto service is not available yet.
-//
-// Until the service is available, producer threads instantiate an unbound
-// StartupTraceWriter instance (via a StartupTraceWriterRegistry) and use it to
-// emit trace events. Each writer will record the serialized trace events into a
-// temporary local memory buffer.
-//
-// Once the service is available, the producer binds each StartupTraceWriter to
-// the SMB by calling SharedMemoryArbiter::BindStartupTraceWriter(). The data in
-// the writer's local buffer will then be copied into the SMB and the any future
-// writes will proxy directly to a new SMB-backed TraceWriter.
-//
-// Writing to the temporary local trace buffer is guarded by a lock and flag to
-// allow binding the writer from a different thread. When the writer starts
-// writing data by calling NewTracePacket(), the writer thread acquires the lock
-// to set a flag indicating that a write is in progress. Once the packet is
-// finalized, the flag is reset. To bind the writer, the lock is acquired while
-// the flag is unset and released only once binding completed, thereby blocking
-// the writer thread from starting a write concurrently.
-//
-// While unbound, the writer thread should finalize each TracePacket as soon as
-// possible to ensure that it doesn't block binding the writer.
-class PERFETTO_EXPORT StartupTraceWriter
-    : public TraceWriter,
-      public protozero::MessageHandleBase::FinalizationListener {
- public:
-  // Create a StartupTraceWriter bound to |trace_writer|. Should only be called
-  // on the writer thread.
-  explicit StartupTraceWriter(std::unique_ptr<TraceWriter> trace_writer);
-
-  ~StartupTraceWriter() override;
-
-  // Return the given writer back to its registry if it is associated with a
-  // registry and the registry was not yet deleted. Otherwise, the writer is
-  // destroyed synchronously.
-  //
-  // Usually called when the writer's thread is destroyed. Can be called on any
-  // thread. The passed writer may still be unbound or already be bound. If
-  // unbound, the registry will ensure that it is bound before destroying it,
-  // keeping it alive until the registry is bound if necessary. This way, its
-  // buffered data is retained.
-  //
-  // All packets written to the passed writer should have been completed and it
-  // should no longer be used to write data after calling this method.
-  static void ReturnToRegistry(std::unique_ptr<StartupTraceWriter> writer);
-
-  // TraceWriter implementation. These methods should only be called on the
-  // writer thread.
-  TracePacketHandle NewTracePacket() override;
-  void Flush(std::function<void()> callback = {}) override;
-
-  // Note that this will return 0 until the first TracePacket was started after
-  // binding.
-  WriterID writer_id() const override;
-
-  uint64_t written() const override;
-
-  // Returns |true| if the writer thread has observed that the writer was bound
-  // to an SMB. Should only be called on the writer thread.
-  //
-  // The writer thread can use the return value to determine whether it needs to
-  // finalize the current TracePacket as soon as possible. It is only safe for
-  // the writer to batch data into a single TracePacket over a longer time
-  // period when this returns |true|.
-  bool was_bound() const {
-    PERFETTO_DCHECK_THREAD(writer_thread_checker_);
-    return was_bound_;
-  }
-
-  // Should only be called on the writer thread.
-  size_t used_buffer_size();
-
- private:
-  friend class StartupTraceWriterRegistry;
-  friend class StartupTraceWriterTest;
-
-  // Create an unbound StartupTraceWriter associated with the registry pointed
-  // to by the handle. The writer can later be bound by calling
-  // BindToTraceWriter(). The registry handle may be nullptr in tests.
-  StartupTraceWriter(std::shared_ptr<StartupTraceWriterRegistryHandle>,
-                     BufferExhaustedPolicy,
-                     size_t max_buffer_size_bytes);
-
-  StartupTraceWriter(const StartupTraceWriter&) = delete;
-  StartupTraceWriter& operator=(const StartupTraceWriter&) = delete;
-
-  // Bind this StartupTraceWriter to the provided SharedMemoryArbiterImpl.
-  // Called by StartupTraceWriterRegistry::BindToArbiter().
-  //
-  // This method should be called on the arbiter's task runner. If any data was
-  // written locally before the writer was bound, BindToArbiter() will copy this
-  // data into chunks in the provided target buffer via the SMB. The commit of
-  // this data to the SMB is rate limited to avoid exhausting the SMB
-  // (|chunks_per_batch|), and may continue asynchronously on the arbiter's task
-  // runner even if binding was successful, provided the SharedMemoryArbiterImpl
-  // is not destroyed. Passing value 0 for |chunks_per_batch| disables rate
-  // limiting. Any future packets will be directly written into the SMB via a
-  // newly obtained TraceWriter from the arbiter.
-  //
-  // Will fail and return |false| if a concurrent write is in progress. Returns
-  // |true| if successfully bound and should then not be called again.
-  bool BindToArbiter(SharedMemoryArbiterImpl*,
-                     BufferID target_buffer,
-                     size_t chunks_per_batch) PERFETTO_WARN_UNUSED_RESULT;
-
-  // protozero::MessageHandleBase::FinalizationListener implementation.
-  void OnMessageFinalized(protozero::Message* message) override;
-
-  void OnTracePacketCompleted();
-  ChunkID CommitLocalBufferChunks(SharedMemoryArbiterImpl*,
-                                  WriterID,
-                                  BufferID,
-                                  size_t chunks_per_batch,
-                                  SharedMemoryABI::Chunk first_chunk);
-
-  PERFETTO_THREAD_CHECKER(writer_thread_checker_)
-
-  std::shared_ptr<StartupTraceWriterRegistryHandle> registry_handle_;
-
-  // Only set and accessed from the writer thread. The writer thread flips this
-  // bit when it sees that trace_writer_ is set (while holding the lock).
-  // Caching this fact in this variable avoids the need to acquire the lock to
-  // check on later calls to NewTracePacket().
-  bool was_bound_ = false;
-
-  const BufferExhaustedPolicy buffer_exhausted_policy_ =
-      BufferExhaustedPolicy::kDefault;
-  const size_t max_buffer_size_bytes_ = 0;
-
-  // Only accessed on the writer thread.
-  std::unique_ptr<TraceWriter> null_trace_writer_ = nullptr;
-
-  // All variables below this point are protected by |lock_|.
-  std::mutex lock_;
-
-  // Never reset once it is changed from |nullptr|.
-  std::unique_ptr<TraceWriter> trace_writer_ = nullptr;
-
-  // Local memory buffer for trace packets written before the writer is bound.
-  std::unique_ptr<protozero::ScatteredHeapBuffer> memory_buffer_;
-  std::unique_ptr<protozero::ScatteredStreamWriter> memory_stream_writer_;
-
-  std::unique_ptr<std::vector<uint32_t>> packet_sizes_;
-
-  // Whether the writer thread is currently writing a TracePacket.
-  bool write_in_progress_ = false;
-
-  // The packet returned via NewTracePacket() while the writer is unbound. Reset
-  // to |nullptr| once bound. Owned by this class, TracePacketHandle has just a
-  // pointer to it.
-  std::unique_ptr<protos::pbzero::TracePacket> cur_packet_;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_STARTUP_TRACE_WRITER_H_
diff --git a/include/perfetto/ext/tracing/core/startup_trace_writer_registry.h b/include/perfetto/ext/tracing/core/startup_trace_writer_registry.h
deleted file mode 100644
index 0896f32..0000000
--- a/include/perfetto/ext/tracing/core/startup_trace_writer_registry.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_EXT_TRACING_CORE_STARTUP_TRACE_WRITER_REGISTRY_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_CORE_STARTUP_TRACE_WRITER_REGISTRY_H_
-
-#include <functional>
-#include <memory>
-#include <mutex>
-#include <vector>
-
-#include "perfetto/base/export.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
-#include "perfetto/tracing/buffer_exhausted_policy.h"
-
-namespace perfetto {
-
-class SharedMemoryArbiterImpl;
-class StartupTraceWriter;
-class StartupTraceWriterRegistry;
-
-namespace base {
-class TaskRunner;
-}  // namespace base
-
-// Used to return a StartupTraceWriter back to its registry when the writer's
-// thread is destroyed, provided the registry itself wasn't deleted yet. The
-// indirection via the handle is necessary to avoid potential deadlocks caused
-// by lock order inversion. These issues are avoided by locking on the handle's
-// common lock.
-class StartupTraceWriterRegistryHandle {
- public:
-  explicit StartupTraceWriterRegistryHandle(StartupTraceWriterRegistry*);
-
-  // Called by StartupTraceWriterRegistry destructor.
-  void OnRegistryDestroyed();
-
-  // Called by StartupTraceWriter::ReturnToRegistry.
-  void ReturnWriterToRegistry(std::unique_ptr<StartupTraceWriter> writer);
-
- private:
-  StartupTraceWriterRegistryHandle(const StartupTraceWriterRegistryHandle&) =
-      delete;
-  StartupTraceWriterRegistryHandle& operator=(
-      const StartupTraceWriterRegistryHandle&) = delete;
-
-  std::mutex lock_;
-  StartupTraceWriterRegistry* registry_;
-};
-
-// Embedders can use this registry to create unbound StartupTraceWriters during
-// startup, and later bind them all safely to an arbiter and target buffer.
-class PERFETTO_EXPORT StartupTraceWriterRegistry {
- public:
-  StartupTraceWriterRegistry();
-  ~StartupTraceWriterRegistry();
-
-  // Buffer size defaults to 1 mB per writer.
-  static constexpr size_t kDefaultMaxBufferSizeBytes = 1024 * 1024;
-
-  // Returns a new unbound StartupTraceWriter. Should only be called while
-  // unbound. Usually called on a writer thread. The writer should never be
-  // destroyed by the caller directly, but instead returned to the registry by
-  // calling StartupTraceWriter::ReturnToRegistry.
-  std::unique_ptr<StartupTraceWriter> CreateUnboundTraceWriter(
-      BufferExhaustedPolicy = BufferExhaustedPolicy::kDefault,
-      size_t max_buffer_size_bytes = kDefaultMaxBufferSizeBytes);
-
-  // Binds all StartupTraceWriters created by this registry to the given arbiter
-  // and target buffer. Should only be called once and on the passed
-  // TaskRunner's sequence. See
-  // SharedMemoryArbiter::BindStartupTraceWriterRegistry() for details.
-  //
-  // Note that the writers may not be bound synchronously if they are
-  // concurrently being written to. The registry will retry on the passed
-  // TaskRunner until all writers were bound successfully.
-  //
-  // Calls |on_bound_callback| asynchronously on the passed TaskRunner once all
-  // writers were bound.
-  //
-  // The commit of the StartupTraceWriters' locally buffered data to the SMB is
-  // rate limited to avoid exhausting the SMB, and may continue asynchronously
-  // even after |on_bound_callback| was called.
-  void BindToArbiter(
-      SharedMemoryArbiterImpl*,
-      BufferID target_buffer,
-      base::TaskRunner*,
-      std::function<void(StartupTraceWriterRegistry*)> on_bound_callback);
-
- private:
-  friend class StartupTraceWriterRegistryHandle;
-  friend class StartupTraceWriterTest;
-
-  StartupTraceWriterRegistry(const StartupTraceWriterRegistry&) = delete;
-  StartupTraceWriterRegistry& operator=(const StartupTraceWriterRegistry&) =
-      delete;
-
-  // Try to bind the remaining unbound writers and post a continuation to
-  // |task_runner_| if any writers could not be bound.
-  void TryBindWriters();
-
-  // Notifies the arbiter when we have bound all writers. May delete |this|.
-  void OnUnboundWritersRemovedLocked();
-
-  // Return a StartupTraceWriter back to the registry, see
-  // StartupTraceWriter::ReturnToRegistry.
-  void ReturnTraceWriter(std::unique_ptr<StartupTraceWriter>);
-
-  std::shared_ptr<StartupTraceWriterRegistryHandle> handle_;
-
-  // Begin lock-protected members.
-  std::mutex lock_;
-
-  // Unbound writers that we handed out to writer threads. These writers may be
-  // concurrently written to by the writer threads.
-  std::vector<StartupTraceWriter*> unbound_writers_;
-
-  // Unbound writers that writer threads returned to the registry by calling
-  // ReturnUnboundTraceWriter(). Writers are removed from |unbound_writers_|
-  // when they are added to |unbound_owned_writers_|. No new data can be written
-  // to these writers.
-  std::vector<std::unique_ptr<StartupTraceWriter>> unbound_owned_writers_;
-
-  SharedMemoryArbiterImpl* arbiter_ = nullptr;  // |nullptr| while unbound.
-  BufferID target_buffer_ = 0;
-  base::TaskRunner* task_runner_;
-  size_t chunks_per_batch_ = 0;
-  std::function<void(StartupTraceWriterRegistry*)> on_bound_callback_ = nullptr;
-
-  // Keep at the end. Initialized during |BindToArbiter()|, like |task_runner_|.
-  // Weak pointers are only valid on |task_runner_|'s thread/sequence.
-  std::unique_ptr<base::WeakPtrFactory<StartupTraceWriterRegistry>>
-      weak_ptr_factory_;
-  // End lock-protected members.
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_STARTUP_TRACE_WRITER_REGISTRY_H_
diff --git a/include/perfetto/ext/tracing/core/trace_packet.h b/include/perfetto/ext/tracing/core/trace_packet.h
deleted file mode 100644
index 452c5b3..0000000
--- a/include/perfetto/ext/tracing/core/trace_packet.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_PACKET_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_PACKET_H_
-
-#include <stddef.h>
-#include <memory>
-#include <tuple>
-
-#include "perfetto/base/export.h"
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/tracing/core/slice.h"
-
-namespace perfetto {
-
-namespace protos {
-class TracePacket;  // From protos/trace_packet.pb.h.
-}  // namespace protos
-
-// A wrapper around a byte buffer that contains a protobuf-encoded TracePacket
-// (see trace_packet.proto). The TracePacket is decoded only if the Consumer
-// requests that. This is to allow Consumer(s) to just stream the packet over
-// the network or save it to a file without wasting time decoding it and without
-// needing to depend on libprotobuf or the trace_packet.pb.h header.
-// If the packets are saved / streamed and not just consumed locally, consumers
-// should ensure to preserve the unknown fields in the proto. A consumer, in
-// fact, might have an older version .proto which is newer on the producer.
-class PERFETTO_EXPORT TracePacket {
- public:
-  using const_iterator = Slices::const_iterator;
-
-  // The field id of protos::Trace::packet, static_assert()-ed in the unittest.
-  static constexpr uint32_t kPacketFieldNumber = 1;
-
-  // Maximum size of the preamble returned by GetProtoPreamble().
-  static constexpr size_t kMaxPreambleBytes = 8;
-
-  TracePacket();
-  ~TracePacket();
-  TracePacket(TracePacket&&) noexcept;
-  TracePacket& operator=(TracePacket&&);
-
-  // Accesses all the raw slices in the packet, for saving them to file/network.
-  const Slices& slices() const { return slices_; }
-
-  // Mutator, used only by the service and tests.
-  void AddSlice(Slice);
-
-  // Does not copy / take ownership of the memory of the slice. The TracePacket
-  // will be valid only as long as the original buffer is valid.
-  void AddSlice(const void* start, size_t size);
-
-  // Total size of all slices.
-  size_t size() const { return size_; }
-
-  // Generates a protobuf preamble suitable to represent this packet as a
-  // repeated field within a root trace.proto message.
-  // Returns a pointer to a buffer, owned by this class, containing the preamble
-  // and its size.
-  std::tuple<char*, size_t> GetProtoPreamble();
-
-  // Returns the raw protobuf bytes of the slices, all stitched together into
-  // a string. Only for testing.
-  std::string GetRawBytesForTesting();
-
- private:
-  TracePacket(const TracePacket&) = delete;
-  TracePacket& operator=(const TracePacket&) = delete;
-
-  Slices slices_;     // Not owned.
-  size_t size_ = 0;   // SUM(slice.size for slice in slices_).
-  char preamble_[kMaxPreambleBytes];  // Deliberately not initialized.
-
-  // Remember to update the move operators and their unittest if adding new
-  // fields. ConsumerIPCClientImpl::OnReadBuffersResponse() relies on
-  // std::move(TracePacket) to clear up the moved-from instance.
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_PACKET_H_
diff --git a/include/perfetto/ext/tracing/core/trace_stats.h b/include/perfetto/ext/tracing/core/trace_stats.h
deleted file mode 100644
index c4f9930..0000000
--- a/include/perfetto/ext/tracing/core/trace_stats.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_STATS_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_STATS_H_
-
-// This header exists only for legacy code that used to refer to the
-// checked-in auto-generated code, before it was moved to be a build-time gen
-// rule. DO NOT add any new includes to this header, instead directly include
-// the one below.
-// TODO(primiano): cleanup call-sites and remove this header.
-#include "protos/perfetto/common/trace_stats.gen.h"
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_STATS_H_
diff --git a/include/perfetto/ext/tracing/core/trace_writer.h b/include/perfetto/ext/tracing/core/trace_writer.h
deleted file mode 100644
index 99662b2..0000000
--- a/include/perfetto/ext/tracing/core/trace_writer.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_WRITER_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_WRITER_H_
-
-#include <functional>
-
-#include "perfetto/base/export.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/protozero/message_handle.h"
-#include "perfetto/tracing/trace_writer_base.h"
-
-namespace perfetto {
-
-namespace protos {
-namespace pbzero {
-class TracePacket;
-}  // namespace pbzero
-}  // namespace protos
-
-// This is a single-thread write interface that allows to write protobufs
-// directly into the tracing shared buffer without making any copies.
-// It takes care of acquiring and releasing chunks from the
-// SharedMemoryArbiter and splitting protos over chunks.
-// The idea is that each data source creates one (or more) TraceWriter for each
-// thread it wants to write from. Each TraceWriter will get its own dedicated
-// chunk and will write into the shared buffer without any locking most of the
-// time. Locking will happen only when a chunk is exhausted and a new one is
-// acquired from the arbiter.
-
-// TODO: TraceWriter needs to keep the shared memory buffer alive (refcount?).
-// Otherwise if the shared memory buffer goes away (e.g. the Service crashes)
-// the TraceWriter will keep writing into unmapped memory.
-
-class PERFETTO_EXPORT TraceWriter : public TraceWriterBase {
- public:
-  using TracePacketHandle =
-      protozero::MessageHandle<protos::pbzero::TracePacket>;
-
-  TraceWriter();
-  ~TraceWriter() override;
-
-  // Returns a handle to the root proto message for the trace. The message will
-  // be finalized either by calling directly handle.Finalize() or by letting the
-  // handle go out of scope. The returned handle can be std::move()'d but cannot
-  // be used after either: (i) the TraceWriter instance is destroyed, (ii) a
-  // subsequence NewTracePacket() call is made on the same TraceWriter instance.
-  TracePacketHandle NewTracePacket() override = 0;
-
-  // Commits the data pending for the current chunk into the shared memory
-  // buffer and sends a CommitDataRequest() to the service. This can be called
-  // only if the handle returned by NewTracePacket() has been destroyed (i.e. we
-  // cannot Flush() while writing a TracePacket).
-  // Note: Flush() also happens implicitly when destroying the TraceWriter.
-  // |callback| is an optional callback. When non-null it will request the
-  // service to ACK the flush and will be invoked after the service has
-  // acknowledged it. The callback might be NEVER INVOKED if the service crashes
-  // or the IPC connection is dropped. The callback should be used only by tests
-  // and best-effort features (logging).
-  // TODO(primiano): right now the |callback| will be called on the IPC thread.
-  // This is fine in the current single-thread scenario, but long-term
-  // trace_writer_impl.cc should be smarter and post it on the right thread.
-  void Flush(std::function<void()> callback = {}) override = 0;
-
-  virtual WriterID writer_id() const = 0;
-
-  // Bytes written since creation. Is not reset when new chunks are acquired.
-  virtual uint64_t written() const = 0;
-
-  // Set the id of the first chunk the writer will emit. Returns |false| if not
-  // implemented or if the first chunk was already emitted by the writer.
-  //
-  // StartupTraceWriter will call this if it committed buffered data on
-  // behalf of the TraceWriter.
-  virtual bool SetFirstChunkId(ChunkID);
-
- private:
-  TraceWriter(const TraceWriter&) = delete;
-  TraceWriter& operator=(const TraceWriter&) = delete;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACE_WRITER_H_
diff --git a/include/perfetto/ext/tracing/core/tracing_service.h b/include/perfetto/ext/tracing/core/tracing_service.h
deleted file mode 100644
index c39d2e2..0000000
--- a/include/perfetto/ext/tracing/core/tracing_service.h
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACING_SERVICE_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACING_SERVICE_H_
-
-#include <stdint.h>
-
-#include <functional>
-#include <memory>
-#include <vector>
-
-#include "perfetto/base/export.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/shared_memory.h"
-#include "perfetto/tracing/buffer_exhausted_policy.h"
-
-namespace perfetto {
-
-namespace base {
-class TaskRunner;
-}  // namespace base
-
-class CommitDataRequest;
-class Consumer;
-class DataSourceDescriptor;
-class Producer;
-class SharedMemoryArbiter;
-class TracingServiceState;
-class TraceConfig;
-class TraceWriter;
-
-// TODO: for the moment this assumes that all the calls happen on the same
-// thread/sequence. Not sure this will be the case long term in Chrome.
-
-// The API for the Producer port of the Service.
-// Subclassed by:
-// 1. The tracing_service_impl.cc business logic when returning it in response
-//    to the ConnectProducer() method.
-// 2. The transport layer (e.g., src/ipc) when the producer and
-//    the service don't talk locally but via some IPC mechanism.
-class PERFETTO_EXPORT ProducerEndpoint {
- public:
-  virtual ~ProducerEndpoint();
-
-  // Called by the Producer to (un)register data sources. Data sources are
-  // identified by their name (i.e. DataSourceDescriptor.name)
-  virtual void RegisterDataSource(const DataSourceDescriptor&) = 0;
-  virtual void UnregisterDataSource(const std::string& name) = 0;
-
-  // Associate the trace writer with the given |writer_id| with
-  // |target_buffer|. The service may use this information to retrieve and
-  // copy uncommitted chunks written by the trace writer into its associated
-  // buffer, e.g. when a producer process crashes or when a flush is
-  // necessary.
-  virtual void RegisterTraceWriter(uint32_t writer_id,
-                                   uint32_t target_buffer) = 0;
-
-  // Remove the association of the trace writer previously created via
-  // RegisterTraceWriter.
-  virtual void UnregisterTraceWriter(uint32_t writer_id) = 0;
-
-  // Called by the Producer to signal that some pages in the shared memory
-  // buffer (shared between Service and Producer) have changed.
-  // When the Producer and the Service are hosted in the same process and
-  // hence potentially live on the same task runner, This method must call
-  // TracingServiceImpl's CommitData synchronously, without any PostTask()s,
-  // if on the same thread. This is to avoid a deadlock where the Producer
-  // exhausts its SMB and stalls waiting for the service to catch up with
-  // reads, but the Service never gets to that because it lives on the same
-  // thread.
-  using CommitDataCallback = std::function<void()>;
-  virtual void CommitData(const CommitDataRequest&,
-                          CommitDataCallback callback = {}) = 0;
-
-  virtual SharedMemory* shared_memory() const = 0;
-
-  // Size of shared memory buffer pages. It's always a multiple of 4K.
-  // See shared_memory_abi.h
-  virtual size_t shared_buffer_page_size_kb() const = 0;
-
-  // Creates a trace writer, which allows to create events, handling the
-  // underying shared memory buffer and signalling to the Service. This method
-  // is thread-safe but the returned object is not. A TraceWriter should be
-  // used only from a single thread, or the caller has to handle sequencing
-  // via a mutex or equivalent. This method can only be called if
-  // TracingService::ConnectProducer was called with |in_process=true|.
-  // Args:
-  // |target_buffer| is the target buffer ID where the data produced by the
-  // writer should be stored by the tracing service. This value is passed
-  // upon creation of the data source (StartDataSource()) in the
-  // DataSourceConfig.target_buffer().
-  virtual std::unique_ptr<TraceWriter> CreateTraceWriter(
-      BufferID target_buffer,
-      BufferExhaustedPolicy buffer_exhausted_policy =
-          BufferExhaustedPolicy::kDefault) = 0;
-
-  // If TracingService::ConnectProducer is called with |in_process=true|,
-  // this returns the producer's SharedMemoryArbiter which can be used
-  // to create TraceWriters which is able to directly commit chunks
-  // without going through an IPC layer.
-  virtual SharedMemoryArbiter* GetInProcessShmemArbiter() = 0;
-
-  // Called in response to a Producer::Flush(request_id) call after all data
-  // for the flush request has been committed.
-  virtual void NotifyFlushComplete(FlushRequestID) = 0;
-
-  // Called in response to one or more Producer::StartDataSource(),
-  // if the data source registered setting the flag
-  // DataSourceDescriptor.will_notify_on_start.
-  virtual void NotifyDataSourceStarted(DataSourceInstanceID) = 0;
-
-  // Called in response to one or more Producer::StopDataSource(),
-  // if the data source registered setting the flag
-  // DataSourceDescriptor.will_notify_on_stop.
-  virtual void NotifyDataSourceStopped(DataSourceInstanceID) = 0;
-
-  // This informs the service to activate any of these triggers if any tracing
-  // session was waiting for them.
-  virtual void ActivateTriggers(const std::vector<std::string>&) = 0;
-};  // class ProducerEndpoint.
-
-// The API for the Consumer port of the Service.
-// Subclassed by:
-// 1. The tracing_service_impl.cc business logic when returning it in response
-// to
-//    the ConnectConsumer() method.
-// 2. The transport layer (e.g., src/ipc) when the consumer and
-//    the service don't talk locally but via some IPC mechanism.
-class ConsumerEndpoint {
- public:
-  virtual ~ConsumerEndpoint();
-
-  // Enables tracing with the given TraceConfig. The ScopedFile argument is
-  // used only when TraceConfig.write_into_file == true.
-  // If TraceConfig.deferred_start == true data sources are configured via
-  // SetupDataSource() but are not started until StartTracing() is called.
-  // This is to support pre-initialization and fast triggering of traces.
-  // The ScopedFile argument is used only when TraceConfig.write_into_file
-  // == true.
-  virtual void EnableTracing(const TraceConfig&,
-                             base::ScopedFile = base::ScopedFile()) = 0;
-
-  // Update the trace config of an existing tracing session; only a subset
-  // of options can be changed mid-session. Currently the only
-  // supported functionality is expanding the list of producer_name_filters()
-  // (or removing the filter entirely) for existing data sources.
-  virtual void ChangeTraceConfig(const TraceConfig&) = 0;
-
-  // Starts all data sources configured in the trace config. This is used only
-  // after calling EnableTracing() with TraceConfig.deferred_start=true.
-  // It's a no-op if called after a regular EnableTracing(), without setting
-  // deferred_start.
-  virtual void StartTracing() = 0;
-
-  virtual void DisableTracing() = 0;
-
-  // Requests all data sources to flush their data immediately and invokes the
-  // passed callback once all of them have acked the flush (in which case
-  // the callback argument |success| will be true) or |timeout_ms| are elapsed
-  // (in which case |success| will be false).
-  // If |timeout_ms| is 0 the TraceConfig's flush_timeout_ms is used, or,
-  // if that one is not set (or is set to 0), kDefaultFlushTimeoutMs (5s) is
-  // used.
-  using FlushCallback = std::function<void(bool /*success*/)>;
-  virtual void Flush(uint32_t timeout_ms, FlushCallback) = 0;
-
-  // Tracing data will be delivered invoking Consumer::OnTraceData().
-  virtual void ReadBuffers() = 0;
-
-  virtual void FreeBuffers() = 0;
-
-  // Will call OnDetach().
-  virtual void Detach(const std::string& key) = 0;
-
-  // Will call OnAttach().
-  virtual void Attach(const std::string& key) = 0;
-
-  // Will call OnTraceStats().
-  virtual void GetTraceStats() = 0;
-
-  enum ObservableEventType : uint32_t {
-    kNone = 0,
-    kDataSourceInstances = 1 << 0
-  };
-
-  // Start or stop observing events of selected types. |enabled_event_types|
-  // specifies the types of events to observe in a bitmask (see
-  // ObservableEventType enum). To disable observing, pass
-  // ObservableEventType::kNone. Will call OnObservableEvents() repeatedly
-  // whenever an event of an enabled ObservableEventType occurs.
-  //
-  // TODO(eseckler): Extend this to support producers & data sources.
-  virtual void ObserveEvents(uint32_t enabled_event_types) = 0;
-
-  // Used to obtain the list of connected data sources and other info about
-  // the tracing service.
-  using QueryServiceStateCallback =
-      std::function<void(bool success, const TracingServiceState&)>;
-  virtual void QueryServiceState(QueryServiceStateCallback) = 0;
-};  // class ConsumerEndpoint.
-
-// The public API of the tracing Service business logic.
-//
-// Exposed to:
-// 1. The transport layer (e.g., src/unix_rpc/unix_service_host.cc),
-//    which forwards commands received from a remote producer or consumer to
-//    the actual service implementation.
-// 2. Tests.
-//
-// Subclassed by:
-//   The service business logic in src/core/tracing_service_impl.cc.
-class PERFETTO_EXPORT TracingService {
- public:
-  using ProducerEndpoint = perfetto::ProducerEndpoint;
-  using ConsumerEndpoint = perfetto::ConsumerEndpoint;
-
-  enum class ProducerSMBScrapingMode {
-    // Use service's default setting for SMB scraping. Currently, the default
-    // mode is to disable SMB scraping, but this may change in the future.
-    kDefault,
-
-    // Enable scraping of uncommitted chunks in producers' shared memory
-    // buffers.
-    kEnabled,
-
-    // Disable scraping of uncommitted chunks in producers' shared memory
-    // buffers.
-    kDisabled
-  };
-
-  // Implemented in src/core/tracing_service_impl.cc .
-  static std::unique_ptr<TracingService> CreateInstance(
-      std::unique_ptr<SharedMemory::Factory>,
-      base::TaskRunner*);
-
-  virtual ~TracingService();
-
-  // Connects a Producer instance and obtains a ProducerEndpoint, which is
-  // essentially a 1:1 channel between one Producer and the Service.
-  // The caller has to guarantee that the passed Producer will be alive as long
-  // as the returned ProducerEndpoint is alive.
-  // Both the passed Prodcer and the returned ProducerEndpint must live on the
-  // same task runner of the service, specifically:
-  // 1) The Service will call Producer::* methods on the Service's task runner.
-  // 2) The Producer should call ProducerEndpoint::* methods only on the
-  //    service's task runner, except for ProducerEndpoint::CreateTraceWriter(),
-  //    which can be called on any thread.
-  // To disconnect just destroy the returned ProducerEndpoint object. It is safe
-  // to destroy the Producer once the Producer::OnDisconnect() has been invoked.
-  // |uid| is the trusted user id of the producer process, used by the consumers
-  // for validating the origin of trace data.
-  // |shared_memory_size_hint_bytes| and |shared_memory_page_size_hint_bytes|
-  // are optional hints on the size of the shared memory buffer and its pages.
-  // The service can ignore the hints (e.g., if the hints are unreasonably
-  // large or other sizes were configured in a tracing session's config).
-  // |in_process| enables the ProducerEndpoint to manage its own shared memory
-  // and enables use of |ProducerEndpoint::CreateTraceWriter|.
-  // Can return null in the unlikely event that service has too many producers
-  // connected.
-  virtual std::unique_ptr<ProducerEndpoint> ConnectProducer(
-      Producer*,
-      uid_t uid,
-      const std::string& name,
-      size_t shared_memory_size_hint_bytes = 0,
-      bool in_process = false,
-      ProducerSMBScrapingMode smb_scraping_mode =
-          ProducerSMBScrapingMode::kDefault,
-      size_t shared_memory_page_size_hint_bytes = 0) = 0;
-
-  // Connects a Consumer instance and obtains a ConsumerEndpoint, which is
-  // essentially a 1:1 channel between one Consumer and the Service.
-  // The caller has to guarantee that the passed Consumer will be alive as long
-  // as the returned ConsumerEndpoint is alive.
-  // To disconnect just destroy the returned ConsumerEndpoint object. It is safe
-  // to destroy the Consumer once the Consumer::OnDisconnect() has been invoked.
-  virtual std::unique_ptr<ConsumerEndpoint> ConnectConsumer(Consumer*,
-                                                            uid_t) = 0;
-
-  // Enable/disable scraping of chunks in the shared memory buffer. If enabled,
-  // the service will copy uncommitted but non-empty chunks from the SMB when
-  // flushing (e.g. to handle unresponsive producers or producers unable to
-  // flush their active chunks), on producer disconnect (e.g. to recover data
-  // from crashed producers), and after disabling a tracing session (e.g. to
-  // gather data from producers that didn't stop their data sources in time).
-  //
-  // This feature is currently used by Chrome.
-  virtual void SetSMBScrapingEnabled(bool enabled) = 0;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_CORE_TRACING_SERVICE_H_
diff --git a/include/perfetto/ext/tracing/ipc/BUILD.gn b/include/perfetto/ext/tracing/ipc/BUILD.gn
deleted file mode 100644
index 1e6b4b4..0000000
--- a/include/perfetto/ext/tracing/ipc/BUILD.gn
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (C) 2017 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.
-
-source_set("ipc") {
-  public_deps = [
-    "../../base",
-    "../core",
-  ]
-  sources = [
-    "consumer_ipc_client.h",
-    "default_socket.h",
-    "producer_ipc_client.h",
-    "service_ipc_host.h",
-  ]
-}
diff --git a/include/perfetto/ext/tracing/ipc/consumer_ipc_client.h b/include/perfetto/ext/tracing/ipc/consumer_ipc_client.h
deleted file mode 100644
index b39d17c..0000000
--- a/include/perfetto/ext/tracing/ipc/consumer_ipc_client.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_TRACING_IPC_CONSUMER_IPC_CLIENT_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_IPC_CONSUMER_IPC_CLIENT_H_
-
-#include <memory>
-#include <string>
-
-#include "perfetto/ext/tracing/core/tracing_service.h"
-
-namespace perfetto {
-
-class Consumer;
-
-// Allows to connect to a remote Service through a UNIX domain socket.
-// Exposed to:
-//   Consumer(s) of the tracing library.
-// Implemented in:
-//   src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
-class ConsumerIPCClient {
- public:
-  // Connects to the producer port of the Service listening on the given
-  // |service_sock_name|. If the connection is successful, the OnConnect()
-  // method will be invoked asynchronously on the passed Consumer interface.
-  // If the connection fails, OnDisconnect() will be invoked instead.
-  // The returned ConsumerEndpoint serves also to delimit the scope of the
-  // callbacks invoked on the Consumer interface: no more Consumer callbacks are
-  // invoked immediately after its destruction and any pending callback will be
-  // dropped.
-  static std::unique_ptr<TracingService::ConsumerEndpoint>
-  Connect(const char* service_sock_name, Consumer*, base::TaskRunner*);
-
- protected:
-  ConsumerIPCClient() = delete;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_IPC_CONSUMER_IPC_CLIENT_H_
diff --git a/include/perfetto/ext/tracing/ipc/default_socket.h b/include/perfetto/ext/tracing/ipc/default_socket.h
deleted file mode 100644
index 85a1de0..0000000
--- a/include/perfetto/ext/tracing/ipc/default_socket.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef INCLUDE_PERFETTO_EXT_TRACING_IPC_DEFAULT_SOCKET_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_IPC_DEFAULT_SOCKET_H_
-
-namespace perfetto {
-
-const char* GetConsumerSocket();
-const char* GetProducerSocket();
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_IPC_DEFAULT_SOCKET_H_
diff --git a/include/perfetto/ext/tracing/ipc/producer_ipc_client.h b/include/perfetto/ext/tracing/ipc/producer_ipc_client.h
deleted file mode 100644
index e6092e8..0000000
--- a/include/perfetto/ext/tracing/ipc/producer_ipc_client.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_TRACING_IPC_PRODUCER_IPC_CLIENT_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_IPC_PRODUCER_IPC_CLIENT_H_
-
-#include <memory>
-#include <string>
-
-#include "perfetto/ext/tracing/core/tracing_service.h"
-
-namespace perfetto {
-
-class Producer;
-
-// Allows to connect to a remote Service through a UNIX domain socket.
-// Exposed to:
-//   Producer(s) of the tracing library.
-// Implemented in:
-//   src/tracing/ipc/producer/producer_ipc_client_impl.cc
-class ProducerIPCClient {
- public:
-  // Connects to the producer port of the Service listening on the given
-  // |service_sock_name|. If the connection is successful, the OnConnect()
-  // method will be invoked asynchronously on the passed Producer interface.
-  // If the connection fails, OnDisconnect() will be invoked instead.
-  // The returned ProducerEndpoint serves also to delimit the scope of the
-  // callbacks invoked on the Producer interface: no more Producer callbacks are
-  // invoked immediately after its destruction and any pending callback will be
-  // dropped.
-  static std::unique_ptr<TracingService::ProducerEndpoint> Connect(
-      const char* service_sock_name,
-      Producer*,
-      const std::string& producer_name,
-      base::TaskRunner*,
-      TracingService::ProducerSMBScrapingMode smb_scraping_mode =
-          TracingService::ProducerSMBScrapingMode::kDefault,
-      size_t shared_memory_size_hint_bytes = 0,
-      size_t shared_memory_page_size_hint_bytes = 0);
-
- protected:
-  ProducerIPCClient() = delete;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_IPC_PRODUCER_IPC_CLIENT_H_
diff --git a/include/perfetto/ext/tracing/ipc/service_ipc_host.h b/include/perfetto/ext/tracing/ipc/service_ipc_host.h
deleted file mode 100644
index 86915af..0000000
--- a/include/perfetto/ext/tracing/ipc/service_ipc_host.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2017 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 INCLUDE_PERFETTO_EXT_TRACING_IPC_SERVICE_IPC_HOST_H_
-#define INCLUDE_PERFETTO_EXT_TRACING_IPC_SERVICE_IPC_HOST_H_
-
-#include <memory>
-
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-
-namespace perfetto {
-namespace base {
-class TaskRunner;
-}  // namespace base.
-
-class TracingService;
-
-// Creates an instance of the service (business logic + UNIX socket transport).
-// Exposed to:
-//   The code in the tracing client that will host the service e.g., traced.
-// Implemented in:
-//   src/tracing/ipc/service/service_ipc_host_impl.cc
-class ServiceIPCHost {
- public:
-  static std::unique_ptr<ServiceIPCHost> CreateInstance(base::TaskRunner*);
-  virtual ~ServiceIPCHost();
-
-  // Start listening on the Producer & Consumer ports. Returns false in case of
-  // failure (e.g., something else is listening on |socket_name|).
-  virtual bool Start(const char* producer_socket_name,
-                     const char* consumer_socket_name) = 0;
-
-  // Like the above, but takes two file descriptors to already bound sockets.
-  // This is used when building as part of the Android tree, where init opens
-  // and binds the socket beore exec()-ing us.
-  virtual bool Start(base::ScopedFile producer_socket_fd,
-                     base::ScopedFile consumer_socket_fd) = 0;
-
-  virtual TracingService* service() const = 0;
-
- protected:
-  ServiceIPCHost();
-
- private:
-  ServiceIPCHost(const ServiceIPCHost&) = delete;
-  ServiceIPCHost& operator=(const ServiceIPCHost&) = delete;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_EXT_TRACING_IPC_SERVICE_IPC_HOST_H_
diff --git a/include/perfetto/ipc/BUILD.gn b/include/perfetto/ipc/BUILD.gn
new file mode 100644
index 0000000..a8aa17e
--- /dev/null
+++ b/include/perfetto/ipc/BUILD.gn
@@ -0,0 +1,31 @@
+# Copyright (C) 2017 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.
+
+source_set("ipc") {
+  public_deps = [
+    "../base",
+  ]
+  sources = [
+    "async_result.h",
+    "basic_types.h",
+    "client.h",
+    "client_info.h",
+    "codegen_helpers.h",
+    "deferred.h",
+    "host.h",
+    "service.h",
+    "service_descriptor.h",
+    "service_proxy.h",
+  ]
+}
diff --git a/include/perfetto/ipc/async_result.h b/include/perfetto/ipc/async_result.h
new file mode 100644
index 0000000..e3178c3
--- /dev/null
+++ b/include/perfetto/ipc/async_result.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_IPC_ASYNC_RESULT_H_
+#define INCLUDE_PERFETTO_IPC_ASYNC_RESULT_H_
+
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+#include "perfetto/ipc/basic_types.h"
+
+namespace perfetto {
+namespace ipc {
+
+// Wraps the result of an asynchronous invocation. This is the equivalent of a
+// std::pair<unique_ptr<T>, bool> with syntactic sugar. It is used as callback
+// argument by Deferred<T>.
+template <typename T = ProtoMessage>
+class AsyncResult {
+ public:
+  static AsyncResult Create() {
+    return AsyncResult(std::unique_ptr<T>(new T()));
+  }
+
+  AsyncResult(std::unique_ptr<T> msg = nullptr,
+              bool has_more = false,
+              int fd = -1)
+      : msg_(std::move(msg)), has_more_(has_more), fd_(fd) {
+    static_assert(std::is_base_of<ProtoMessage, T>::value, "T->ProtoMessage");
+  }
+  AsyncResult(AsyncResult&&) noexcept = default;
+  AsyncResult& operator=(AsyncResult&&) = default;
+
+  bool success() const { return !!msg_; }
+  explicit operator bool() const { return success(); }
+
+  bool has_more() const { return has_more_; }
+  void set_has_more(bool has_more) { has_more_ = has_more; }
+
+  void set_msg(std::unique_ptr<T> msg) { msg_ = std::move(msg); }
+  T* release_msg() { return msg_.release(); }
+  T* operator->() { return msg_.get(); }
+  T& operator*() { return *msg_; }
+
+  void set_fd(int fd) { fd_ = fd; }
+  int fd() const { return fd_; }
+
+ private:
+  std::unique_ptr<T> msg_;
+  bool has_more_ = false;
+
+  // Optional. Only for messages that convey a file descriptor, for sharing
+  // memory across processes.
+  int fd_ = -1;
+};
+
+}  // namespace ipc
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_IPC_ASYNC_RESULT_H_
diff --git a/include/perfetto/ipc/basic_types.h b/include/perfetto/ipc/basic_types.h
new file mode 100644
index 0000000..2d14085
--- /dev/null
+++ b/include/perfetto/ipc/basic_types.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_IPC_BASIC_TYPES_H_
+#define INCLUDE_PERFETTO_IPC_BASIC_TYPES_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+namespace google {
+namespace protobuf {
+class MessageLite;
+}  // namespace protobuf
+}  // namespace google
+
+namespace perfetto {
+namespace ipc {
+
+using ProtoMessage = ::google::protobuf::MessageLite;
+using ServiceID = uint32_t;
+using MethodID = uint32_t;
+using ClientID = uint64_t;
+using RequestID = uint64_t;
+
+// This determines the maximum size allowed for an IPC message. Trying to send
+// or receive a larger message will hit DCHECK(s) and auto-disconnect.
+constexpr size_t kIPCBufferSize = 128 * 1024;
+
+constexpr uid_t kInvalidUid = static_cast<uid_t>(-1);
+constexpr pid_t kInvalidPid = static_cast<pid_t>(-1);
+
+}  // namespace ipc
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_IPC_BASIC_TYPES_H_
diff --git a/include/perfetto/ipc/client.h b/include/perfetto/ipc/client.h
new file mode 100644
index 0000000..cd802d1
--- /dev/null
+++ b/include/perfetto/ipc/client.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_IPC_CLIENT_H_
+#define INCLUDE_PERFETTO_IPC_CLIENT_H_
+
+#include <functional>
+#include <memory>
+
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/weak_ptr.h"
+#include "perfetto/ipc/basic_types.h"
+
+namespace perfetto {
+
+namespace base {
+class TaskRunner;
+}  // namespace base
+
+namespace ipc {
+class ServiceProxy;
+
+// The client-side class that talks to the host over the socket and multiplexes
+// requests coming from the various autogenerated ServiceProxy stubs.
+// This is meant to be used by the user code as follows:
+// auto client = Client::CreateInstance("socket_name", task_runner);
+// std::unique_ptr<GreeterService> svc(new GreeterService());
+// client.BindService(svc);
+// svc.OnConnect([] () {
+//    svc.SayHello(..., ...);
+// });
+class Client {
+ public:
+  static std::unique_ptr<Client> CreateInstance(const char* socket_name,
+                                                base::TaskRunner*);
+  virtual ~Client();
+
+  virtual void BindService(base::WeakPtr<ServiceProxy>) = 0;
+
+  // There is no need to call this method explicitly. Destroying the
+  // ServiceProxy instance is sufficient and will automatically unbind it. This
+  // method is exposed only for the ServiceProxy destructor.
+  virtual void UnbindService(ServiceID) = 0;
+
+  // Returns (with move semantics) the last file descriptor received on the IPC
+  // channel. No buffering is performed: if a service sends two file descriptors
+  // and the caller doesn't read them immediately, the first one will be
+  // automatically closed when the second is received (and will hit a DCHECK in
+  // debug builds).
+  virtual base::ScopedFile TakeReceivedFD() = 0;
+};
+
+}  // namespace ipc
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_IPC_CLIENT_H_
diff --git a/include/perfetto/ipc/client_info.h b/include/perfetto/ipc/client_info.h
new file mode 100644
index 0000000..5c4fe5b
--- /dev/null
+++ b/include/perfetto/ipc/client_info.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_IPC_CLIENT_INFO_H_
+#define INCLUDE_PERFETTO_IPC_CLIENT_INFO_H_
+
+#include <unistd.h>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/ipc/basic_types.h"
+
+namespace perfetto {
+namespace ipc {
+
+// Passed to Service(s) to identify remote clients.
+class ClientInfo {
+ public:
+  ClientInfo() = default;
+  ClientInfo(ClientID client_id, uid_t uid)
+      : client_id_(client_id), uid_(uid) {}
+
+  bool operator==(const ClientInfo& other) const {
+    return (client_id_ == other.client_id_ && uid_ == other.uid_);
+  }
+  bool operator!=(const ClientInfo& other) const { return !(*this == other); }
+
+  // For map<> and other sorted containers.
+  bool operator<(const ClientInfo& other) const {
+    PERFETTO_DCHECK(client_id_ != other.client_id_ || *this == other);
+    return client_id_ < other.client_id_;
+  }
+
+  bool is_valid() const { return client_id_ != 0; }
+
+  // A monotonic counter.
+  ClientID client_id() const { return client_id_; }
+
+  // Posix User ID. Comes from the kernel, can be trusted.
+  uid_t uid() const { return uid_; }
+
+ private:
+  ClientID client_id_ = 0;
+  uid_t uid_ = kInvalidUid;
+};
+
+}  // namespace ipc
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_IPC_CLIENT_INFO_H_
diff --git a/include/perfetto/ipc/codegen_helpers.h b/include/perfetto/ipc/codegen_helpers.h
new file mode 100644
index 0000000..e4cec82
--- /dev/null
+++ b/include/perfetto/ipc/codegen_helpers.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 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 file is only meant to be included in autogenerated .cc files.
+
+#ifndef INCLUDE_PERFETTO_IPC_CODEGEN_HELPERS_H_
+#define INCLUDE_PERFETTO_IPC_CODEGEN_HELPERS_H_
+
+// A templated protobuf message decoder. Returns nullptr in case of failure.
+template <typename T>
+::std::unique_ptr<::perfetto::ipc::ProtoMessage> _IPC_Decoder(
+    const std::string& proto_data) {
+  ::std::unique_ptr<::perfetto::ipc::ProtoMessage> msg(new T());
+  if (msg->ParseFromString(proto_data))
+    return msg;
+  return nullptr;
+}
+
+// Templated method dispatcher. Used to obtain a function pointer to a given
+// IPC method (Method) of a given service (TSvc) that can be invoked by the
+// host-side machinery starting from a generic Service pointer and a generic
+// ProtoMessage request argument.
+template <typename TSvc,    // Type of the actual Service subclass.
+          typename TReq,    // Type of the request argument.
+          typename TReply,  // Type of the reply argument.
+          void (TSvc::*Method)(const TReq&, ::perfetto::ipc::Deferred<TReply>)>
+void _IPC_Invoker(::perfetto::ipc::Service* s,
+                  const ::perfetto::ipc::ProtoMessage& req,
+                  ::perfetto::ipc::DeferredBase reply) {
+  (*static_cast<TSvc*>(s).*Method)(
+      static_cast<const TReq&>(req),
+      ::perfetto::ipc::Deferred<TReply>(::std::move(reply)));
+}
+
+#endif  // INCLUDE_PERFETTO_IPC_CODEGEN_HELPERS_H_
diff --git a/include/perfetto/ipc/deferred.h b/include/perfetto/ipc/deferred.h
new file mode 100644
index 0000000..b1740b0
--- /dev/null
+++ b/include/perfetto/ipc/deferred.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_IPC_DEFERRED_H_
+#define INCLUDE_PERFETTO_IPC_DEFERRED_H_
+
+#include <functional>
+#include <memory>
+#include <utility>
+
+#include "perfetto/ipc/async_result.h"
+#include "perfetto/ipc/basic_types.h"
+
+namespace perfetto {
+namespace ipc {
+
+// This class is a wrapper for a callback handling async results.
+// The problem this is solving is the following: For each result argument of the
+// methods generated from the .proto file:
+// - The client wants to see something on which it can Bind() a callback, which
+//   is invoked asynchronously once reply is received from the host.
+// - The host wants to expose something to user code that implements the IPC
+//   methods to allow them to provide an asynchronous reply back to the client.
+//   Eventually even more than once, for the case streaming replies.
+//
+// In both cases we want to make sure that callbacks don't get lost along the
+// way. To address this, this class will automatically reject the callbacks
+// if they are not resolved at destructor time (or the object is std::move()'d).
+//
+// The client is supposed to use this class as follows:
+//   class GreeterProxy {
+//      void SayHello(const HelloRequest&, Deferred<HelloReply> reply)
+//   }
+//  ...
+//  Deferred<HelloReply> reply;
+//  reply.Bind([] (AsyncResult<HelloReply> reply) {
+//    std::cout << reply.success() ? reply->message : "failure";
+//  });
+//  host_proxy_instance.SayHello(req, std::move(reply));
+//
+// The host instead is supposed to use this as follows:
+//   class GreeterImpl : public Greeter {
+//     void SayHello(const HelloRequest& req, Deferred<HelloReply> reply) {
+//        AsyncResult<HelloReply> reply = AsyncResult<HelloReply>::Create();
+//        reply->set_greeting("Hello " + req.name)
+//        reply.Resolve(std::move(reply));
+//     }
+//   }
+// Or for more complex cases, the deferred object can be std::move()'d outside
+// and the reply can continue asynchronously later.
+
+template <typename T>
+class Deferred;
+
+class DeferredBase {
+ public:
+  explicit DeferredBase(
+      std::function<void(AsyncResult<ProtoMessage>)> callback = nullptr);
+
+  template <typename T>
+  explicit DeferredBase(Deferred<T> other)
+      : callback_(std::move(other.callback_)) {}
+
+  ~DeferredBase();
+  DeferredBase(DeferredBase&&) noexcept;
+  DeferredBase& operator=(DeferredBase&&);
+  void Bind(std::function<void(AsyncResult<ProtoMessage>)> callback);
+  bool IsBound() const;
+  void Resolve(AsyncResult<ProtoMessage>);
+  void Reject();
+
+ protected:
+  template <typename T>
+  friend class Deferred;
+  void Move(DeferredBase&);
+
+  std::function<void(AsyncResult<ProtoMessage>)> callback_;
+};
+
+template <typename T = ProtoMessage>
+class Deferred : public DeferredBase {
+ public:
+  explicit Deferred(std::function<void(AsyncResult<T>)> callback = nullptr) {
+    Bind(std::move(callback));
+  }
+
+  // This move constructor (and the similar one in DeferredBase) is meant to be
+  // called only by the autogenerated code. The caller has to guarantee that the
+  // moved-from and moved-to types match. The behavior is otherwise undefined.
+  explicit Deferred(DeferredBase&& other) {
+    callback_ = std::move(other.callback_);
+    other.callback_ = nullptr;
+  }
+
+  void Bind(std::function<void(AsyncResult<T>)> callback) {
+    if (!callback)
+      return;
+
+    // Here we need a callback adapter to downcast the callback to a generic
+    // callback that takes an AsyncResult<ProtoMessage>, so that it can be
+    // stored in the base class |callback_|.
+    auto callback_adapter = [callback](
+                                AsyncResult<ProtoMessage> async_result_base) {
+      // Upcast the async_result from <ProtoMessage> -> <T : ProtoMessage>.
+      static_assert(std::is_base_of<ProtoMessage, T>::value, "T:ProtoMessage");
+      AsyncResult<T> async_result(
+          std::unique_ptr<T>(static_cast<T*>(async_result_base.release_msg())),
+          async_result_base.has_more(), async_result_base.fd());
+      callback(std::move(async_result));
+    };
+    DeferredBase::Bind(callback_adapter);
+  }
+
+  // If no more messages are expected, |callback_| is released.
+  void Resolve(AsyncResult<T> async_result) {
+    // Convert the |async_result| to the generic base one (T -> ProtoMessage).
+    AsyncResult<ProtoMessage> async_result_base(
+        std::unique_ptr<ProtoMessage>(async_result.release_msg()),
+        async_result.has_more(), async_result.fd());
+    DeferredBase::Resolve(std::move(async_result_base));
+  }
+};
+
+}  // namespace ipc
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_IPC_DEFERRED_H_
diff --git a/include/perfetto/ipc/host.h b/include/perfetto/ipc/host.h
new file mode 100644
index 0000000..a3abb99
--- /dev/null
+++ b/include/perfetto/ipc/host.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_IPC_HOST_H_
+#define INCLUDE_PERFETTO_IPC_HOST_H_
+
+#include <memory>
+
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/ipc/basic_types.h"
+
+namespace perfetto {
+
+namespace base {
+class TaskRunner;
+}  // namespace base
+
+namespace ipc {
+
+class Service;
+
+// The host-side of the IPC layer. This class acts as a registry and request
+// dispatcher. It listen on the UnixSocket |socket_name| for incoming requests
+// (coming Client instances) and dispatches their requests to the various
+// Services exposed.
+class Host {
+ public:
+  // Creates an instance and starts listening on the given |socket_name|.
+  // Returns nullptr if listening on the socket fails.
+  static std::unique_ptr<Host> CreateInstance(const char* socket_name,
+                                              base::TaskRunner*);
+
+  // Like the above but takes a file descriptor to a pre-bound unix socket.
+  // Returns nullptr if listening on the socket fails.
+  static std::unique_ptr<Host> CreateInstance(base::ScopedFile socket_fd,
+                                              base::TaskRunner*);
+
+  virtual ~Host();
+
+  // Registers a new service and makes it available to remote IPC peers.
+  // All the exposed Service instances will be destroyed when destroying the
+  // Host instance if ExposeService suceeds and returns true, or immediately
+  // after the call in case of failure.
+  // Returns true if the register has been succesfully registered, false in case
+  // of errors (e.g., another service with the same name is already registered).
+  virtual bool ExposeService(std::unique_ptr<Service>) = 0;
+};
+
+}  // namespace ipc
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_IPC_HOST_H_
diff --git a/include/perfetto/ipc/service.h b/include/perfetto/ipc/service.h
new file mode 100644
index 0000000..18dc1be
--- /dev/null
+++ b/include/perfetto/ipc/service.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_IPC_SERVICE_H_
+#define INCLUDE_PERFETTO_IPC_SERVICE_H_
+
+#include "perfetto/base/logging.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/ipc/client_info.h"
+
+namespace perfetto {
+namespace ipc {
+
+class ServiceDescriptor;
+
+// The base class for all the autogenerated host-side service interfaces.
+class Service {
+ public:
+  virtual ~Service();
+
+  // Overridden by the auto-generated class. Provides the list of methods and
+  // the protobuf (de)serialization functions for their arguments.
+  virtual const ServiceDescriptor& GetDescriptor() = 0;
+
+  // Invoked when a remote client disconnects. Use client_info() to obtain
+  // details about the client that disconnected.
+  virtual void OnClientDisconnected() {}
+
+  // Returns the ClientInfo for the current IPC request. Returns an invalid
+  // ClientInfo if called outside the scope of an IPC method.
+  const ClientInfo& client_info() {
+    PERFETTO_DCHECK(client_info_.is_valid());
+    return client_info_;
+  }
+
+  base::ScopedFile TakeReceivedFD() {
+    if (received_fd_)
+      return std::move(*received_fd_);
+    return base::ScopedFile();
+  }
+
+ private:
+  friend class HostImpl;
+  ClientInfo client_info_;
+  // This is a pointer because the received fd needs to remain owned by the
+  // ClientConnection, as we will provide it to all method invocations
+  // for that client until one of them calls Service::TakeReceivedFD.
+  //
+  // Different clients might have sent different FDs so this cannot be owned
+  // here.
+  //
+  // Note that this means that there can always only be one outstanding
+  // invocation per client that supplies an FD and the client needs to
+  // wait for this one to return before calling another one.
+  base::ScopedFile* received_fd_;
+};
+
+}  // namespace ipc
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_IPC_SERVICE_H_
diff --git a/include/perfetto/ipc/service_descriptor.h b/include/perfetto/ipc/service_descriptor.h
new file mode 100644
index 0000000..c4aca7e
--- /dev/null
+++ b/include/perfetto/ipc/service_descriptor.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_IPC_SERVICE_DESCRIPTOR_H_
+#define INCLUDE_PERFETTO_IPC_SERVICE_DESCRIPTOR_H_
+
+#include <functional>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "perfetto/ipc/basic_types.h"
+#include "perfetto/ipc/deferred.h"
+
+namespace perfetto {
+namespace ipc {
+
+class Service;
+
+// This is a pure data structure which holds factory methods and strings for the
+// services and their methods that get generated in the .h/.cc files.
+// Each autogenerated class has a GetDescriptor() method that returns one
+// instance of these and allows both client and hosts to map service and method
+// names to IDs and provide function pointers to the protobuf decoder fuctions.
+class ServiceDescriptor {
+ public:
+  struct Method {
+    const char* name;
+
+    // DecoderFunc is pointer to a function that takes a string in input
+    // containing protobuf encoded data and returns a decoded protobuf message.
+    using DecoderFunc = std::unique_ptr<ProtoMessage> (*)(const std::string&);
+
+    // Function pointer to decode the request argument of the method.
+    DecoderFunc request_proto_decoder;
+
+    // Function pointer to decoded the reply argument of the method.
+    DecoderFunc reply_proto_decoder;
+
+    // Function pointer that dispatches the generic request to the corresponding
+    // method implementation.
+    using InvokerFunc = void (*)(Service*,
+                                 const ProtoMessage& /* request_args */,
+                                 DeferredBase /* deferred_reply */);
+    InvokerFunc invoker;
+  };
+
+  const char* service_name = nullptr;
+
+  // Note that methods order is not stable. Client and Host might have different
+  // method indexes, depending on their versions. The Client can't just rely
+  // on the indexes and has to keep a [string -> remote index] translation map.
+  std::vector<Method> methods;
+};
+
+}  // namespace ipc
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_IPC_SERVICE_DESCRIPTOR_H_
diff --git a/include/perfetto/ipc/service_proxy.h b/include/perfetto/ipc/service_proxy.h
new file mode 100644
index 0000000..a0107da
--- /dev/null
+++ b/include/perfetto/ipc/service_proxy.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_IPC_SERVICE_PROXY_H_
+#define INCLUDE_PERFETTO_IPC_SERVICE_PROXY_H_
+
+#include "perfetto/ipc/basic_types.h"
+
+#include <assert.h>
+
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+
+#include "perfetto/base/weak_ptr.h"
+#include "perfetto/ipc/deferred.h"
+
+namespace perfetto {
+namespace ipc {
+
+class Client;
+class ServiceDescriptor;
+
+// The base class for the client-side autogenerated stubs that forward method
+// invocations to the host. All the methods of this class are meant to be called
+// only by the autogenerated code.
+class ServiceProxy {
+ public:
+  class EventListener {
+   public:
+    virtual ~EventListener();
+
+    // Called once after Client::BindService() if the ServiceProxy has been
+    // successfully bound to the host. It is possible to start sending IPC
+    // requests soon after this.
+    virtual void OnConnect() {}
+
+    // Called if the connection fails to be established or drops after having
+    // been established.
+    virtual void OnDisconnect() {}
+  };
+
+  // Guarantees that no callback will happen after this object has been
+  // destroyed. The caller has to guarantee that the |event_listener| stays
+  // alive at least as long as the ServiceProxy instance.
+  explicit ServiceProxy(EventListener*);
+  virtual ~ServiceProxy();
+
+  void InitializeBinding(base::WeakPtr<Client>,
+                         ServiceID,
+                         std::map<std::string, MethodID>);
+
+  // Called by the IPC methods in the autogenerated classes.
+  void BeginInvoke(const std::string& method_name,
+                   const ProtoMessage& request,
+                   DeferredBase reply,
+                   int fd = -1);
+
+  // Called by ClientImpl.
+  // |reply_args| == nullptr means request failure.
+  void EndInvoke(RequestID,
+                 std::unique_ptr<ProtoMessage> reply_arg,
+                 bool has_more);
+
+  // Called by ClientImpl.
+  void OnConnect(bool success);
+  void OnDisconnect();
+  bool connected() const { return service_id_ != 0; }
+
+  base::WeakPtr<ServiceProxy> GetWeakPtr() const;
+
+  // Implemented by the autogenerated class.
+  virtual const ServiceDescriptor& GetDescriptor() = 0;
+
+ private:
+  base::WeakPtr<Client> client_;
+  ServiceID service_id_ = 0;
+  std::map<std::string, MethodID> remote_method_ids_;
+  std::map<RequestID, DeferredBase> pending_callbacks_;
+  EventListener* const event_listener_;
+  base::WeakPtrFactory<ServiceProxy> weak_ptr_factory_;  // Keep last.
+};
+
+}  // namespace ipc
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_IPC_SERVICE_PROXY_H_
diff --git a/include/perfetto/profiling/BUILD.gn b/include/perfetto/profiling/BUILD.gn
deleted file mode 100644
index 23e19c9..0000000
--- a/include/perfetto/profiling/BUILD.gn
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright (C) 2017 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.
-
-# TODO(135923303): as part of fixing b/135923303, symbolizer.h will be removed
-# and namespacing of pprof_builder.h will be changed so do not depend on this
-# target.
-source_set("symbolizer") {
-  sources = [
-    "pprof_builder.h",
-    "symbolizer.h",
-  ]
-}
-
-source_set("normalize") {
-  sources = [
-    "normalize.h",
-  ]
-}
diff --git a/include/perfetto/profiling/normalize.h b/include/perfetto/profiling/normalize.h
deleted file mode 100644
index 7b7da1d..0000000
--- a/include/perfetto/profiling/normalize.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_PROFILING_NORMALIZE_H_
-#define INCLUDE_PERFETTO_PROFILING_NORMALIZE_H_
-
-// Header only code that gets used in other projects.
-// This is currently used in
-// * ART
-// * Bionic
-// * Heapprofd
-//
-// DO NOT USE THE STL HERE. This gets used in parts of Bionic that do not
-// use the STL.
-
-#include <string.h>
-
-namespace perfetto {
-namespace profiling {
-
-// Normalize cmdline in place. Stores new beginning of string in *cmdline_ptr.
-// Returns new size of string (from new beginning).
-// Modifies string in *cmdline_ptr.
-static ssize_t NormalizeCmdLine(char** cmdline_ptr, size_t size) {
-  char* cmdline = *cmdline_ptr;
-  char* first_arg = static_cast<char*>(memchr(cmdline, '\0', size));
-  if (first_arg == nullptr) {
-    errno = EOVERFLOW;
-    return -1;
-  }
-  // For consistency with what we do with Java app cmdlines, trim everything
-  // after the @ sign of the first arg.
-  char* first_at = static_cast<char*>(memchr(cmdline, '@', size));
-  if (first_at != nullptr && first_at < first_arg) {
-    *first_at = '\0';
-    first_arg = first_at;
-  }
-  char* start = static_cast<char*>(
-      memrchr(cmdline, '/', static_cast<size_t>(first_arg - cmdline)));
-  if (start == nullptr) {
-    start = cmdline;
-  } else {
-    // Skip the /.
-    start++;
-  }
-  *cmdline_ptr = start;
-  return first_arg - start;
-}
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_PROFILING_NORMALIZE_H_
diff --git a/include/perfetto/profiling/pprof_builder.h b/include/perfetto/profiling/pprof_builder.h
deleted file mode 100644
index cc61b68..0000000
--- a/include/perfetto/profiling/pprof_builder.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_PROFILING_PPROF_BUILDER_H_
-#define INCLUDE_PERFETTO_PROFILING_PPROF_BUILDER_H_
-
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "perfetto/trace_processor/trace_processor.h"
-
-namespace perfetto {
-namespace trace_to_text {
-
-class Symbolizer;
-
-struct SerializedProfile {
-  uint64_t pid;
-  std::string serialized;
-};
-
-bool TraceToPprof(trace_processor::TraceProcessor*,
-                  std::vector<SerializedProfile>* output,
-                  Symbolizer* symbolizer,
-                  uint64_t pid = 0,
-                  const std::vector<uint64_t>& timestamps = {});
-
-bool TraceToPprof(std::istream* input,
-                  std::vector<SerializedProfile>* output,
-                  Symbolizer* symbolizer,
-                  uint64_t pid = 0,
-                  const std::vector<uint64_t>& timestamps = {});
-
-bool TraceToPprof(std::istream* input,
-                  std::vector<SerializedProfile>* output,
-                  uint64_t pid = 0,
-                  const std::vector<uint64_t>& timestamps = {});
-
-}  // namespace trace_to_text
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_PROFILING_PPROF_BUILDER_H_
diff --git a/include/perfetto/profiling/symbolizer.h b/include/perfetto/profiling/symbolizer.h
deleted file mode 100644
index 2a5a79e..0000000
--- a/include/perfetto/profiling/symbolizer.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_PROFILING_SYMBOLIZER_H_
-#define INCLUDE_PERFETTO_PROFILING_SYMBOLIZER_H_
-
-#include <map>
-#include <string>
-#include <vector>
-
-// TODO(135923303): do not depend on anything in this file as it will be
-// removed as part of fixing b/135923303.
-namespace perfetto {
-namespace trace_to_text {
-
-struct SymbolizedFrame {
-  std::string function_name;
-  std::string file_name;
-  uint32_t line;
-};
-
-class Symbolizer {
- public:
-  // For each address in the input vector, output a vector of SymbolizedFrame
-  // representing the functions corresponding to that address. When inlining
-  // occurs, this can be more than one function for a single address.
-  //
-  // On failure, return an empty vector.
-  virtual std::vector<std::vector<SymbolizedFrame>> Symbolize(
-      const std::string& mapping_name,
-      const std::string& build_id,
-      const std::vector<uint64_t>& address) = 0;
-  virtual ~Symbolizer();
-};
-
-}  // namespace trace_to_text
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_PROFILING_SYMBOLIZER_H_
diff --git a/include/perfetto/protozero/BUILD.gn b/include/perfetto/protozero/BUILD.gn
index 994ff60..170e325 100644
--- a/include/perfetto/protozero/BUILD.gn
+++ b/include/perfetto/protozero/BUILD.gn
@@ -18,11 +18,10 @@
   ]
   sources = [
     "contiguous_memory_range.h",
-    "copyable_ptr.h",
     "field.h",
     "message.h",
     "message_handle.h",
-    "packed_repeated_fields.h",
+    "proto_decoder.h",
     "proto_decoder.h",
     "proto_utils.h",
     "scattered_heap_buffer.h",
diff --git a/include/perfetto/protozero/copyable_ptr.h b/include/perfetto/protozero/copyable_ptr.h
deleted file mode 100644
index 2fe5ff6..0000000
--- a/include/perfetto/protozero/copyable_ptr.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_PROTOZERO_COPYABLE_PTR_H_
-#define INCLUDE_PERFETTO_PROTOZERO_COPYABLE_PTR_H_
-
-#include <memory>
-
-namespace protozero {
-
-// This class is essentially a std::vector<T> of fixed size = 1.
-// It's a pointer wrapper with deep copying and deep equality comparison.
-// At all effects this wrapper behaves like the underlying T, with the exception
-// of the heap indirection.
-// Conversely to a std::unique_ptr, the pointer will be always valid, never
-// null. The problem it solves is the following: when generating C++ classes
-// from proto files, we want to keep each header hermetic (i.e. not #include
-// headers of dependent types). As such we can't directly instantiate T
-// field members but we can instead rely on pointers, so only the .cc file needs
-// to see the actual definition of T. If the generated classes were move-only we
-// could just use a unique_ptr there. But they aren't, hence this wrapper.
-// Converesely to unique_ptr, this wrapper:
-// - Default constructs the T instance in its constructor.
-// - Implements deep comparison in operator== instead of pointer comparison.
-template <typename T>
-class CopyablePtr {
- public:
-  CopyablePtr() : ptr_(new T()) {}
-  ~CopyablePtr() = default;
-
-  // Copy operators.
-  CopyablePtr(const CopyablePtr& other) : ptr_(new T(*other.ptr_)) {}
-  CopyablePtr& operator=(const CopyablePtr& other) {
-    *ptr_ = *other.ptr_;
-    return *this;
-  }
-
-  // Move operators.
-  CopyablePtr(CopyablePtr&& other) noexcept : ptr_(std::move(other.ptr_)) {
-    other.ptr_.reset(new T());
-  }
-
-  CopyablePtr& operator=(CopyablePtr&& other) {
-    ptr_ = std::move(other.ptr_);
-    other.ptr_.reset(new T());
-    return *this;
-  }
-
-  T* get() { return ptr_.get(); }
-  const T* get() const { return ptr_.get(); }
-
-  T* operator->() { return ptr_.get(); }
-  const T* operator->() const { return ptr_.get(); }
-
-  T& operator*() { return *ptr_; }
-  const T& operator*() const { return *ptr_; }
-
-  friend bool operator==(const CopyablePtr& lhs, const CopyablePtr& rhs) {
-    return *lhs == *rhs;
-  }
-
-  friend bool operator!=(const CopyablePtr& lhs, const CopyablePtr& rhs) {
-    // In theory the underlying type might have a special operator!=
-    // implementation which is not just !(x == y). Respect that.
-    return *lhs != *rhs;
-  }
-
- private:
-  std::unique_ptr<T> ptr_;
-};
-
-}  // namespace protozero
-
-#endif  // INCLUDE_PERFETTO_PROTOZERO_COPYABLE_PTR_H_
diff --git a/include/perfetto/protozero/field.h b/include/perfetto/protozero/field.h
index 5bd3021..9c6da8d 100644
--- a/include/perfetto/protozero/field.h
+++ b/include/perfetto/protozero/field.h
@@ -28,10 +28,6 @@
 namespace protozero {
 
 struct ConstBytes {
-  std::string ToStdString() const {
-    return std::string(reinterpret_cast<const char*>(data), size);
-  }
-
   const uint8_t* data;
   size_t size;
 };
@@ -54,11 +50,11 @@
 // null strings.
 class Field {
  public:
-  bool valid() const { return id_ != 0; }
-  uint16_t id() const { return id_; }
-  explicit operator bool() const { return valid(); }
+  inline bool valid() const { return id_ != 0; }
+  inline uint16_t id() const { return id_; }
+  explicit inline operator bool() const { return valid(); }
 
-  proto_utils::ProtoWireType type() const {
+  inline proto_utils::ProtoWireType type() const {
     auto res = static_cast<proto_utils::ProtoWireType>(type_);
     PERFETTO_DCHECK(res == proto_utils::ProtoWireType::kVarInt ||
                     res == proto_utils::ProtoWireType::kLengthDelimited ||
@@ -67,38 +63,38 @@
     return res;
   }
 
-  bool as_bool() const {
+  inline bool as_bool() const {
     PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt);
     return static_cast<bool>(int_value_);
   }
 
-  uint32_t as_uint32() const {
+  inline uint32_t as_uint32() const {
     PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt ||
                     type() == proto_utils::ProtoWireType::kFixed32);
     return static_cast<uint32_t>(int_value_);
   }
 
-  int32_t as_int32() const {
+  inline int32_t as_int32() const {
     PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt ||
                     type() == proto_utils::ProtoWireType::kFixed32);
     return static_cast<int32_t>(int_value_);
   }
 
-  uint64_t as_uint64() const {
+  inline uint64_t as_uint64() const {
     PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt ||
                     type() == proto_utils::ProtoWireType::kFixed32 ||
                     type() == proto_utils::ProtoWireType::kFixed64);
     return int_value_;
   }
 
-  int64_t as_int64() const {
+  inline int64_t as_int64() const {
     PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kVarInt ||
                     type() == proto_utils::ProtoWireType::kFixed32 ||
                     type() == proto_utils::ProtoWireType::kFixed64);
     return static_cast<int64_t>(int_value_);
   }
 
-  float as_float() const {
+  inline float as_float() const {
     PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kFixed32);
     float res;
     uint32_t value32 = static_cast<uint32_t>(int_value_);
@@ -106,62 +102,51 @@
     return res;
   }
 
-  double as_double() const {
+  inline double as_double() const {
     PERFETTO_DCHECK(!valid() || type() == proto_utils::ProtoWireType::kFixed64);
     double res;
     memcpy(&res, &int_value_, sizeof(res));
     return res;
   }
 
-  ConstChars as_string() const {
+  inline ConstChars as_string() const {
     PERFETTO_DCHECK(!valid() ||
                     type() == proto_utils::ProtoWireType::kLengthDelimited);
     return ConstChars{reinterpret_cast<const char*>(data()), size_};
   }
 
-  std::string as_std_string() const { return as_string().ToStdString(); }
+  inline std::string as_std_string() const { return as_string().ToStdString(); }
 
-  ConstBytes as_bytes() const {
+  inline ConstBytes as_bytes() const {
     PERFETTO_DCHECK(!valid() ||
                     type() == proto_utils::ProtoWireType::kLengthDelimited);
     return ConstBytes{data(), size_};
   }
 
-  const uint8_t* data() const {
+  inline const uint8_t* data() const {
     PERFETTO_DCHECK(!valid() ||
                     type() == proto_utils::ProtoWireType::kLengthDelimited);
     return reinterpret_cast<const uint8_t*>(int_value_);
   }
 
-  size_t size() const {
+  inline size_t size() const {
     PERFETTO_DCHECK(!valid() ||
                     type() == proto_utils::ProtoWireType::kLengthDelimited);
     return size_;
   }
 
-  uint64_t raw_int_value() const { return int_value_; }
+  inline uint64_t raw_int_value() const { return int_value_; }
 
-  void initialize(uint16_t id,
-                  uint8_t type,
-                  uint64_t int_value,
-                  uint32_t size) {
+  inline void initialize(uint16_t id,
+                         uint8_t type,
+                         uint64_t int_value,
+                         uint32_t size) {
     id_ = id;
     type_ = type;
     int_value_ = int_value;
     size_ = size;
   }
 
-  // For use with templates. This is used by RepeatedFieldIterator::operator*().
-  void get(bool* val) const { *val = as_bool(); }
-  void get(uint32_t* val) const { *val = as_uint32(); }
-  void get(int32_t* val) const { *val = as_int32(); }
-  void get(uint64_t* val) const { *val = as_uint64(); }
-  void get(int64_t* val) const { *val = as_int64(); }
-  void get(float* val) const { *val = as_float(); }
-  void get(double* val) const { *val = as_double(); }
-  void get(ConstChars* val) const { *val = as_string(); }
-  void get(ConstBytes* val) const { *val = as_bytes(); }
-
  private:
   // Fields are deliberately not initialized to keep the class trivially
   // constructible. It makes a large perf difference for ProtoDecoder.
diff --git a/include/perfetto/protozero/message.h b/include/perfetto/protozero/message.h
index 213a436..7328663 100644
--- a/include/perfetto/protozero/message.h
+++ b/include/perfetto/protozero/message.h
@@ -46,7 +46,9 @@
 class PERFETTO_EXPORT Message {
  public:
   friend class MessageHandleBase;
-
+  // Grant end_to_end_shared_memory_fuzzer access in order to write raw
+  // bytes into the buffer.
+  friend class ::perfetto::shm_fuzz::FakeProducer;
   // Adjust the |nested_messages_arena_| size when changing this, or the
   // static_assert in the .cc file will bark.
   static constexpr uint32_t kMaxNestingDepth = 10;
@@ -169,8 +171,6 @@
     return message;
   }
 
-  ScatteredStreamWriter* stream_writer_for_testing() { return stream_writer_; }
-
  private:
   Message(const Message&) = delete;
   Message& operator=(const Message&) = delete;
@@ -189,7 +189,7 @@
   }
 
   // Only POD fields are allowed. This class's dtor is never called.
-  // See the comment on the static_assert in the corresponding .cc file.
+  // See the comment on the static_assert in the the corresponding .cc file.
 
   // The stream writer interface used for the serialization.
   ScatteredStreamWriter* stream_writer_;
diff --git a/include/perfetto/protozero/packed_repeated_fields.h b/include/perfetto/protozero/packed_repeated_fields.h
deleted file mode 100644
index dff45e7..0000000
--- a/include/perfetto/protozero/packed_repeated_fields.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_PROTOZERO_PACKED_REPEATED_FIELDS_H_
-#define INCLUDE_PERFETTO_PROTOZERO_PACKED_REPEATED_FIELDS_H_
-
-#include <stdint.h>
-
-#include <array>
-#include <memory>
-#include <type_traits>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/protozero/proto_utils.h"
-
-namespace protozero {
-
-// This file contains classes used when encoding packed repeated fields.
-// To encode such a field, the caller is first expected to accumulate all of the
-// values in one of the following types (depending on the wire type of the
-// individual elements), defined below:
-// * protozero::PackedVarInt
-// * protozero::PackedFixedSizeInt</*element_type=*/ uint32_t>
-// Then that buffer is passed to the protozero-generated setters as an argument.
-// After calling the setter, the buffer can be destroyed.
-//
-// An example of encoding a packed field:
-//   protozero::HeapBuffered<protozero::Message> msg;
-//   protozero::PackedVarInt buf;
-//   buf.Append(42);
-//   buf.Append(-1);
-//   msg->set_fieldname(buf);
-//   msg.SerializeAsString();
-
-class PackedBufferBase {
- public:
-  PackedBufferBase() { Reset(); }
-
-  // Copy or move is disabled due to pointers to stack addresses.
-  PackedBufferBase(const PackedBufferBase&) = delete;
-  PackedBufferBase(PackedBufferBase&&) = delete;
-  PackedBufferBase& operator=(const PackedBufferBase&) = delete;
-  PackedBufferBase& operator=(PackedBufferBase&&) = delete;
-
-  void Reset();
-
-  const uint8_t* data() const { return storage_begin_; }
-
-  size_t size() const {
-    return static_cast<size_t>(write_ptr_ - storage_begin_);
-  }
-
- protected:
-  void GrowIfNeeded() {
-    PERFETTO_DCHECK(write_ptr_ >= storage_begin_ && write_ptr_ <= storage_end_);
-    if (PERFETTO_UNLIKELY(write_ptr_ + kMaxElementSize > storage_end_)) {
-      GrowSlowpath();
-    }
-  }
-
-  void GrowSlowpath();
-
-  // max(uint64_t varint encoding, biggest fixed type (uint64)).
-  static constexpr size_t kMaxElementSize = 10;
-
-  // So sizeof(this) == 8k.
-  static constexpr size_t kOnStackStorageSize = 8192 - 32;
-
-  uint8_t* storage_begin_;
-  uint8_t* storage_end_;
-  uint8_t* write_ptr_;
-  std::unique_ptr<uint8_t[]> heap_buf_;
-  alignas(uint64_t) uint8_t stack_buf_[kOnStackStorageSize];
-};
-
-class PackedVarInt : public PackedBufferBase {
- public:
-  template <typename T>
-  void Append(T value) {
-    GrowIfNeeded();
-    write_ptr_ = proto_utils::WriteVarInt(value, write_ptr_);
-  }
-};
-
-template <typename T /* e.g. uint32_t for Fixed32 */>
-class PackedFixedSizeInt : public PackedBufferBase {
- public:
-  void Append(T value) {
-    static_assert(sizeof(T) == 4 || sizeof(T) == 8,
-                  "PackedFixedSizeInt should be used only with 32/64-bit ints");
-    static_assert(sizeof(T) <= kMaxElementSize,
-                  "kMaxElementSize needs to be updated");
-    GrowIfNeeded();
-    PERFETTO_DCHECK(reinterpret_cast<size_t>(write_ptr_) % alignof(T) == 0);
-    memcpy(reinterpret_cast<T*>(write_ptr_), &value, sizeof(T));
-    write_ptr_ += sizeof(T);
-  }
-};
-
-}  // namespace protozero
-
-#endif  // INCLUDE_PERFETTO_PROTOZERO_PACKED_REPEATED_FIELDS_H_
diff --git a/include/perfetto/protozero/proto_decoder.h b/include/perfetto/protozero/proto_decoder.h
index 584f7be..8089acf 100644
--- a/include/perfetto/protozero/proto_decoder.h
+++ b/include/perfetto/protozero/proto_decoder.h
@@ -22,8 +22,9 @@
 #include <memory>
 #include <vector>
 
-#include "perfetto/base/compiler.h"
 #include "perfetto/base/logging.h"
+#include "perfetto/base/string_view.h"
+#include "perfetto/base/utils.h"
 #include "perfetto/protozero/field.h"
 #include "perfetto/protozero/proto_utils.h"
 
@@ -43,9 +44,8 @@
 class ProtoDecoder {
  public:
   // Creates a ProtoDecoder using the given |buffer| with size |length| bytes.
-  ProtoDecoder(const uint8_t* buffer, size_t length)
+  inline ProtoDecoder(const uint8_t* buffer, size_t length)
       : begin_(buffer), end_(buffer + length), read_ptr_(buffer) {}
-  ProtoDecoder(const ConstBytes& cb) : ProtoDecoder(cb.data, cb.size) {}
 
   // Reads the next field from the buffer and advances the read cursor. If a
   // full field cannot be read, the returned Field will be invalid (i.e.
@@ -56,18 +56,20 @@
   Field FindField(uint32_t field_id);
 
   // Resets the read cursor to the start of the buffer.
-  void Reset() { read_ptr_ = begin_; }
+  inline void Reset() { read_ptr_ = begin_; }
 
   // Resets the read cursor to the given position (must be within the buffer).
-  void Reset(const uint8_t* pos) {
+  inline void Reset(const uint8_t* pos) {
     PERFETTO_DCHECK(pos >= begin_ && pos < end_);
     read_ptr_ = pos;
   }
 
   // Returns the position of read cursor, relative to the start of the buffer.
-  size_t read_offset() const { return static_cast<size_t>(read_ptr_ - begin_); }
+  inline size_t read_offset() const {
+    return static_cast<size_t>(read_ptr_ - begin_);
+  }
 
-  size_t bytes_left() const {
+  inline size_t bytes_left() const {
     PERFETTO_DCHECK(read_ptr_ <= end_);
     return static_cast<size_t>(end_ - read_ptr_);
   }
@@ -87,14 +89,13 @@
 // first, but the remaining storage holds repeated fields in FIFO order.
 // Assume that we push the 10,11,12 into a repeated field with ID=1.
 //
-// Decoder memory layout:  [  fields storage  ] [ repeated fields storage ]
+// Decoder memory layout:  [  fields storage  ] [ repeated fields storage]
 // 1st iteration:           10
 // 2nd iteration:           11                   10
 // 3rd iteration:           12                   10 11
 //
 // We start the iteration @ fields_[num_fields], which is the start of the
 // repeated fields storage, proceed until the end and lastly jump @ fields_[id].
-template <typename T>
 class RepeatedFieldIterator {
  public:
   RepeatedFieldIterator(uint32_t field_id,
@@ -105,14 +106,9 @@
     FindNextMatchingId();
   }
 
-  explicit operator bool() const { return iter_ != end_; }
-  const Field& field() const { return *iter_; }
-
-  T operator*() const {
-    T val{};
-    iter_->get(&val);
-    return val;
-  }
+  inline const Field* operator->() const { return &*iter_; }
+  inline const Field& operator*() const { return *iter_; }
+  inline explicit operator bool() const { return iter_ != end_; }
 
   RepeatedFieldIterator& operator++() {
     PERFETTO_DCHECK(iter_ != end_);
@@ -125,15 +121,8 @@
     return *this;
   }
 
-  RepeatedFieldIterator operator++(int) {
-    PERFETTO_DCHECK(iter_ != end_);
-    RepeatedFieldIterator it(*this);
-    ++(*this);
-    return it;
-  }
-
  private:
-  void FindNextMatchingId() {
+  inline void FindNextMatchingId() {
     PERFETTO_DCHECK(iter_ != last_);
     for (; iter_ != end_; ++iter_) {
       if (iter_->id() == field_id_)
@@ -155,110 +144,6 @@
   const Field* last_;
 };
 
-// As RepeatedFieldIterator, but allows iterating over a packed repeated field
-// (which will be initially stored as a single length-delimited field).
-// See |GetPackedRepeatedField| for details.
-//
-// Assumes little endianness, and that the input buffers are well formed -
-// containing an exact multiple of encoded elements.
-template <proto_utils::ProtoWireType wire_type, typename CppType>
-class PackedRepeatedFieldIterator {
- public:
-  PackedRepeatedFieldIterator(const uint8_t* data_begin,
-                              size_t size,
-                              bool* parse_error_ptr)
-      : data_end_(data_begin ? data_begin + size : nullptr),
-        read_ptr_(data_begin),
-        parse_error_(parse_error_ptr) {
-    using proto_utils::ProtoWireType;
-    static_assert(wire_type == ProtoWireType::kVarInt ||
-                      wire_type == ProtoWireType::kFixed32 ||
-                      wire_type == ProtoWireType::kFixed64,
-                  "invalid type");
-
-    PERFETTO_DCHECK(parse_error_ptr);
-
-    // Either the field is unset (and there are no data pointer), or the field
-    // is set with a zero length payload. Mark the iterator as invalid in both
-    // cases.
-    if (size == 0) {
-      curr_value_valid_ = false;
-      return;
-    }
-
-    if ((wire_type == ProtoWireType::kFixed32 && (size % 4) != 0) ||
-        (wire_type == ProtoWireType::kFixed64 && (size % 8) != 0)) {
-      *parse_error_ = true;
-      curr_value_valid_ = false;
-      return;
-    }
-
-    ++(*this);
-  }
-
-  const CppType operator*() const { return curr_value_; }
-  explicit operator bool() const { return curr_value_valid_; }
-
-  PackedRepeatedFieldIterator& operator++() {
-    using proto_utils::ProtoWireType;
-
-    if (PERFETTO_UNLIKELY(!curr_value_valid_))
-      return *this;
-
-    if (PERFETTO_UNLIKELY(read_ptr_ == data_end_)) {
-      curr_value_valid_ = false;
-      return *this;
-    }
-
-    if (wire_type == ProtoWireType::kVarInt) {
-      uint64_t new_value = 0;
-      const uint8_t* new_pos =
-          proto_utils::ParseVarInt(read_ptr_, data_end_, &new_value);
-
-      if (PERFETTO_UNLIKELY(new_pos == read_ptr_)) {
-        // Failed to decode the varint (probably incomplete buffer).
-        *parse_error_ = true;
-        curr_value_valid_ = false;
-      } else {
-        read_ptr_ = new_pos;
-        curr_value_ = static_cast<CppType>(new_value);
-      }
-    } else {  // kFixed32 or kFixed64
-      constexpr size_t kStep = wire_type == ProtoWireType::kFixed32 ? 4 : 8;
-
-      // NB: the raw buffer is not guaranteed to be aligned, so neither are
-      // these copies.
-      memcpy(&curr_value_, read_ptr_, sizeof(CppType));
-      read_ptr_ += kStep;
-    }
-
-    return *this;
-  }
-
-  PackedRepeatedFieldIterator operator++(int) {
-    PackedRepeatedFieldIterator it(*this);
-    ++(*this);
-    return it;
-  }
-
- private:
-  // Might be null if the backing proto field isn't set.
-  const uint8_t* const data_end_;
-
-  // The iterator looks ahead by an element, so |curr_value| holds the value
-  // to be returned when the caller dereferences the iterator, and |read_ptr_|
-  // points at the start of the next element to be decoded.
-  // |read_ptr_| might be null if the backing proto field isn't set.
-  const uint8_t* read_ptr_;
-  CppType curr_value_ = 0;
-
-  // Set to false once we've exhausted the iterator, or encountered an error.
-  bool curr_value_valid_ = true;
-
-  // Where to set parsing errors, supplied by the caller.
-  bool* const parse_error_;
-};
-
 // This decoder loads all fields upfront, without recursing in nested messages.
 // It is used as a base class for typed decoders generated by the pbzero plugin.
 // The split between TypedProtoDecoderBase and TypedProtoDecoder<> is to have
@@ -273,44 +158,16 @@
  public:
   // If the field |id| is known at compile time, prefer the templated
   // specialization at<kFieldNumber>().
-  const Field& Get(uint32_t id) const {
+  inline const Field& Get(uint32_t id) {
     return PERFETTO_LIKELY(id < num_fields_) ? fields_[id] : fields_[0];
   }
 
   // Returns an object that allows to iterate over all instances of a repeated
   // field given its id. Example usage:
-  //   for (auto it = decoder.GetRepeated<int32_t>(N); it; ++it) { ... }
-  template <typename T>
-  RepeatedFieldIterator<T> GetRepeated(uint32_t field_id) const {
-    return RepeatedFieldIterator<T>(field_id, &fields_[num_fields_],
-                                    &fields_[size_], &fields_[field_id]);
-  }
-
-  // Returns an objects that allows to iterate over all entries of a packed
-  // repeated field given its id and type. The |wire_type| is necessary for
-  // decoding the packed field, the |cpp_type| is for convenience & stronger
-  // typing.
-  //
-  // The caller must also supply a pointer to a bool that is set to true if the
-  // packed buffer is found to be malformed while iterating (so you need to
-  // exhaust the iterator if you want to check the full extent of the buffer).
-  //
-  // Note that unlike standard protobuf parsers, protozero does not allow
-  // treating of packed repeated fields as non-packed and vice-versa (therefore
-  // not making the packed option forwards and backwards compatible). So
-  // the caller needs to use the right accessor for correct results.
-  template <proto_utils::ProtoWireType wire_type, typename cpp_type>
-  PackedRepeatedFieldIterator<wire_type, cpp_type> GetPackedRepeated(
-      uint32_t field_id,
-      bool* parse_error_location) const {
-    const Field& field = Get(field_id);
-    if (field.valid()) {
-      return PackedRepeatedFieldIterator<wire_type, cpp_type>(
-          field.data(), field.size(), parse_error_location);
-    } else {
-      return PackedRepeatedFieldIterator<wire_type, cpp_type>(
-          nullptr, 0, parse_error_location);
-    }
+  // for (auto it = decoder.GetRepeated(N); it; ++it) { ... }
+  inline RepeatedFieldIterator GetRepeated(uint32_t field_id) const {
+    return RepeatedFieldIterator(field_id, &fields_[num_fields_],
+                                 &fields_[size_], &fields_[field_id]);
   }
 
  protected:
@@ -369,7 +226,7 @@
 
 // Template class instantiated by the auto-generated decoder classes declared in
 // xxx.pbzero.h files.
-template <int MAX_FIELD_ID, bool HAS_NONPACKED_REPEATED_FIELDS>
+template <int MAX_FIELD_ID, bool HAS_REPEATED_FIELDS>
 class TypedProtoDecoder : public TypedProtoDecoderBase {
  public:
   TypedProtoDecoder(const uint8_t* buffer, size_t length)
@@ -383,22 +240,11 @@
   }
 
   template <uint32_t FIELD_ID>
-  const Field& at() const {
+  inline const Field& at() const {
     static_assert(FIELD_ID <= MAX_FIELD_ID, "FIELD_ID > MAX_FIELD_ID");
     return fields_[FIELD_ID];
   }
 
-  TypedProtoDecoder(TypedProtoDecoder&& other) noexcept
-      : TypedProtoDecoderBase(std::move(other)) {
-    // If the moved-from decoder was using on-stack storage, we need to update
-    // our pointer to point to this decoder's on-stack storage.
-    if (fields_ == other.on_stack_storage_) {
-      fields_ = on_stack_storage_;
-      memcpy(on_stack_storage_, other.on_stack_storage_,
-             sizeof(on_stack_storage_));
-    }
-  }
-
  private:
   // In the case of non-repeated fields, this constant defines the highest field
   // id we are able to decode. This is to limit the on-stack storage.
@@ -411,7 +257,7 @@
   // in the on-stack storage, where N is the highest field id.
   // Otherwise we need some room to store repeated fields.
   static constexpr size_t kCapacity =
-      1 + (HAS_NONPACKED_REPEATED_FIELDS ? kMaxDecoderFieldId : MAX_FIELD_ID);
+      1 + (HAS_REPEATED_FIELDS ? kMaxDecoderFieldId : MAX_FIELD_ID);
 
   Field on_stack_storage_[kCapacity];
 };
diff --git a/include/perfetto/protozero/proto_utils.h b/include/perfetto/protozero/proto_utils.h
index 3bfe470..9dd5278 100644
--- a/include/perfetto/protozero/proto_utils.h
+++ b/include/perfetto/protozero/proto_utils.h
@@ -23,6 +23,7 @@
 #include <type_traits>
 
 #include "perfetto/base/logging.h"
+#include "perfetto/base/utils.h"
 
 namespace protozero {
 namespace proto_utils {
@@ -140,22 +141,8 @@
 // Proto types: sint64, sint32.
 template <typename T>
 inline typename std::make_unsigned<T>::type ZigZagEncode(T value) {
-  using UnsignedType = typename std::make_unsigned<T>::type;
-
-  // Right-shift of negative values is implementation specific.
-  // Assert the implementation does what we expect, which is that shifting any
-  // positive value by sizeof(T) * 8 - 1 gives an all 0 bitmap, and a negative
-  // value gives and all 1 bitmap.
-  constexpr uint64_t kUnsignedZero = 0u;
-  constexpr int64_t kNegativeOne = -1;
-  constexpr int64_t kPositiveOne = 1;
-  static_assert(static_cast<uint64_t>(kNegativeOne >> 63) == ~kUnsignedZero,
-                "implementation does not support assumed rightshift");
-  static_assert(static_cast<uint64_t>(kPositiveOne >> 63) == kUnsignedZero,
-                "implementation does not support assumed rightshift");
-
-  return (static_cast<UnsignedType>(value) << 1) ^
-         static_cast<UnsignedType>(value >> (sizeof(T) * 8 - 1));
+  return static_cast<typename std::make_unsigned<T>::type>(
+      (value << 1) ^ (value >> (sizeof(T) * 8 - 1)));
 }
 
 template <typename T>
diff --git a/include/perfetto/protozero/scattered_heap_buffer.h b/include/perfetto/protozero/scattered_heap_buffer.h
index bc6a0d2..7f3906e 100644
--- a/include/perfetto/protozero/scattered_heap_buffer.h
+++ b/include/perfetto/protozero/scattered_heap_buffer.h
@@ -34,11 +34,9 @@
  public:
   class PERFETTO_EXPORT Slice {
    public:
-    Slice();
     explicit Slice(size_t size);
     Slice(Slice&& slice) noexcept;
     ~Slice();
-    Slice& operator=(Slice&&);
 
     inline protozero::ContiguousMemoryRange GetTotalRange() const {
       return {buffer_.get(), buffer_.get() + size_};
@@ -56,11 +54,9 @@
       unused_bytes_ = unused_bytes;
     }
 
-    void Clear();
-
    private:
     std::unique_ptr<uint8_t[]> buffer_;
-    size_t size_;
+    const size_t size_;
     size_t unused_bytes_;
   };
 
@@ -74,10 +70,6 @@
   // Stitch all the slices into a single contiguous buffer.
   std::vector<uint8_t> StitchSlices();
 
-  // Note that the returned ranges point back to this buffer and thus cannot
-  // outlive it.
-  std::vector<protozero::ContiguousMemoryRange> GetRanges();
-
   const std::vector<Slice>& slices() const { return slices_; }
 
   void set_writer(protozero::ScatteredStreamWriter* writer) {
@@ -90,40 +82,28 @@
   // Returns the total size the slices occupy in heap memory (including unused).
   size_t GetTotalSize();
 
-  // Reset the contents of this buffer but retain one slice allocation (if it
-  // exists) to be reused for future writes.
-  void Reset();
-
  private:
   size_t next_slice_size_;
   const size_t maximum_slice_size_;
   protozero::ScatteredStreamWriter* writer_ = nullptr;
   std::vector<Slice> slices_;
-
-  // Used to keep an allocated slice around after this buffer is reset.
-  Slice cached_slice_;
 };
 
 // Helper function to create heap-based protozero messages in one line.
-// Useful when manually serializing a protozero message (primarily in
-// tests/utilities). So instead of the following:
-//   protozero::MyMessage msg;
-//   protozero::ScatteredHeapBuffer shb;
-//   protozero::ScatteredStreamWriter writer(&shb);
+// This is a convenience wrapper, mostly for tests, to avoid having to do:
+//   MyMessage msg;
+//   ScatteredHeapBuffer shb;
+//   ScatteredStreamWriter writer(&shb);
 //   shb.set_writer(&writer);
-//   msg.Reset(&writer);
-//   ...
-// You can write:
-//   protozero::HeapBuffered<protozero::MyMessage> msg;
+//   msg.Reset(&shb);
+// Just to get an easily serializable message. Instead this allows simply:
+//   HeapBuffered<MyMessage> msg;
 //   msg->set_stuff(...);
-//   msg.SerializeAsString();
+//   msg->SerializeAsString();
 template <typename T = ::protozero::Message>
 class HeapBuffered {
  public:
-  HeapBuffered() : HeapBuffered(4096, 4096) {}
-  HeapBuffered(size_t initial_slice_size_bytes, size_t maximum_slice_size_bytes)
-      : shb_(initial_slice_size_bytes, maximum_slice_size_bytes),
-        writer_(&shb_) {
+  HeapBuffered() : shb_(4096, 4096), writer_(&shb_) {
     shb_.set_writer(&writer_);
     msg_.Reset(&writer_);
   }
@@ -138,30 +118,13 @@
   T* get() { return &msg_; }
   T* operator->() { return &msg_; }
 
-  bool empty() const { return shb_.slices().empty(); }
-
-  std::vector<uint8_t> SerializeAsArray() {
-    msg_.Finalize();
-    return shb_.StitchSlices();
-  }
+  std::vector<uint8_t> SerializeAsArray() { return shb_.StitchSlices(); }
 
   std::string SerializeAsString() {
     auto vec = SerializeAsArray();
     return std::string(reinterpret_cast<const char*>(vec.data()), vec.size());
   }
 
-  std::vector<protozero::ContiguousMemoryRange> GetRanges() {
-    msg_.Finalize();
-    return shb_.GetRanges();
-  }
-
-  void Reset() {
-    shb_.Reset();
-    writer_.Reset(protozero::ContiguousMemoryRange{});
-    msg_.Reset(&writer_);
-    PERFETTO_DCHECK(empty());
-  }
-
  private:
   ScatteredHeapBuffer shb_;
   ScatteredStreamWriter writer_;
diff --git a/include/perfetto/protozero/scattered_stream_writer.h b/include/perfetto/protozero/scattered_stream_writer.h
index c508ad9..175a0aa 100644
--- a/include/perfetto/protozero/scattered_stream_writer.h
+++ b/include/perfetto/protozero/scattered_stream_writer.h
@@ -22,8 +22,8 @@
 #include <stdint.h>
 #include <string.h>
 
-#include "perfetto/base/compiler.h"
 #include "perfetto/base/export.h"
+#include "perfetto/base/utils.h"
 #include "perfetto/protozero/contiguous_memory_range.h"
 
 namespace protozero {
diff --git a/include/perfetto/public/BUILD.gn b/include/perfetto/public/BUILD.gn
deleted file mode 100644
index 0ec88f1..0000000
--- a/include/perfetto/public/BUILD.gn
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (C) 2019 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.
-
-source_set("public") {
-  sources = [
-    "consumer_api.h",
-  ]
-}
diff --git a/include/perfetto/public/README.md b/include/perfetto/public/README.md
deleted file mode 100644
index e26e9c3..0000000
--- a/include/perfetto/public/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-This folder contains the deprecated consumer API. The only client of this
-is iorap in the Android tree. For any new use-case use the new Perfetto Client
-API under include/perfetto/tracing. 
\ No newline at end of file
diff --git a/include/perfetto/trace_processor/BUILD.gn b/include/perfetto/trace_processor/BUILD.gn
index 1c419f9..e887327 100644
--- a/include/perfetto/trace_processor/BUILD.gn
+++ b/include/perfetto/trace_processor/BUILD.gn
@@ -14,27 +14,7 @@
 
 source_set("trace_processor") {
   sources = [
-    "read_trace.h",
-    "trace_processor.h",
-  ]
-  public_deps = [
-    ":basic_types",
-    ":storage",
-  ]
-}
-
-source_set("storage") {
-  sources = [
-    "trace_processor_storage.h",
-  ]
-  public_deps = [
-    ":basic_types",
-  ]
-}
-
-source_set("basic_types") {
-  sources = [
     "basic_types.h",
-    "status.h",
+    "trace_processor.h",
   ]
 }
diff --git a/include/perfetto/trace_processor/basic_types.h b/include/perfetto/trace_processor/basic_types.h
index efac31c..535969c 100644
--- a/include/perfetto/trace_processor/basic_types.h
+++ b/include/perfetto/trace_processor/basic_types.h
@@ -17,95 +17,26 @@
 #ifndef INCLUDE_PERFETTO_TRACE_PROCESSOR_BASIC_TYPES_H_
 #define INCLUDE_PERFETTO_TRACE_PROCESSOR_BASIC_TYPES_H_
 
-#include <assert.h>
-#include <math.h>
-#include <stdarg.h>
 #include <stdint.h>
-#include <functional>
-#include <string>
-
-#include "perfetto/base/export.h"
-#include "perfetto/base/logging.h"
 
 namespace perfetto {
 namespace trace_processor {
 
-// Struct for configuring a TraceProcessor instance (see trace_processor.h).
-struct PERFETTO_EXPORT Config {
-  // When set to true, this option forces trace processor to perform a full
-  // sort ignoring any internal heureustics to skip sorting parts of the data.
-  bool force_full_sort = false;
+
+struct Config {
+  uint64_t window_size_ns = 180 * 1000 * 1000 * 1000ULL;  // 3 minutes.
 };
 
 // Represents a dynamically typed value returned by SQL.
-struct PERFETTO_EXPORT SqlValue {
+struct SqlValue {
   // Represents the type of the value.
   enum Type {
     kNull = 0,
+    kString,
     kLong,
     kDouble,
-    kString,
-    kBytes,
   };
 
-  SqlValue() = default;
-
-  static SqlValue Long(int64_t v) {
-    SqlValue value;
-    value.long_value = v;
-    value.type = Type::kLong;
-    return value;
-  }
-
-  static SqlValue String(const char* v) {
-    SqlValue value;
-    value.string_value = v;
-    value.type = Type::kString;
-    return value;
-  }
-
-  double AsDouble() {
-    assert(type == kDouble);
-    return double_value;
-  }
-
-  int Compare(const SqlValue& value) const {
-    // TODO(lalitm): this is almost the same as what SQLite does with the
-    // exception of comparisions between long and double - we choose (for
-    // performance reasons) to omit comparisions between them.
-    if (type != value.type)
-      return type - value.type;
-
-    switch (type) {
-      case Type::kNull:
-        return 0;
-      case Type::kLong:
-        return static_cast<int>(long_value - value.long_value);
-      case Type::kDouble: {
-        double diff = double_value - value.double_value;
-        return diff < 0 ? -1 : (diff > 0 ? 1 : 0);
-      }
-      case Type::kString:
-        return strcmp(string_value, value.string_value);
-      case Type::kBytes: {
-        size_t bytes = std::min(bytes_count, value.bytes_count);
-        int ret = memcmp(bytes_value, value.bytes_value, bytes);
-        if (ret != 0)
-          return ret;
-        return static_cast<int>(bytes_count - value.bytes_count);
-      }
-    }
-    PERFETTO_FATAL("For GCC");
-  }
-  bool operator==(const SqlValue& value) const { return Compare(value) == 0; }
-  bool operator<(const SqlValue& value) const { return Compare(value) < 0; }
-  bool operator!=(const SqlValue& value) const { return !(*this == value); }
-  bool operator>=(const SqlValue& value) const { return !(*this < value); }
-  bool operator<=(const SqlValue& value) const { return !(value < *this); }
-  bool operator>(const SqlValue& value) const { return value < *this; }
-
-  bool is_null() const { return type == Type::kNull; }
-
   // Up to 1 of these fields can be accessed depending on |type|.
   union {
     // This string will be owned by the iterator that returned it and is valid
@@ -113,10 +44,7 @@
     const char* string_value;
     int64_t long_value;
     double double_value;
-    const void* bytes_value;
   };
-  // The size of bytes_value. Only valid when |type == kBytes|.
-  size_t bytes_count = 0;
   Type type = kNull;
 };
 
diff --git a/include/perfetto/trace_processor/read_trace.h b/include/perfetto/trace_processor/read_trace.h
deleted file mode 100644
index ac2053d..0000000
--- a/include/perfetto/trace_processor/read_trace.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACE_PROCESSOR_READ_TRACE_H_
-#define INCLUDE_PERFETTO_TRACE_PROCESSOR_READ_TRACE_H_
-
-#include <functional>
-
-#include "perfetto/base/export.h"
-#include "perfetto/trace_processor/status.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessor;
-
-util::Status PERFETTO_EXPORT ReadTrace(
-    TraceProcessor* tp,
-    const char* filename,
-    const std::function<void(uint64_t parsed_size)>& progress_callback = {});
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACE_PROCESSOR_READ_TRACE_H_
diff --git a/include/perfetto/trace_processor/status.h b/include/perfetto/trace_processor/status.h
deleted file mode 100644
index ee7271a..0000000
--- a/include/perfetto/trace_processor/status.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACE_PROCESSOR_STATUS_H_
-#define INCLUDE_PERFETTO_TRACE_PROCESSOR_STATUS_H_
-
-#include <stdarg.h>
-#include <string>
-
-#include "perfetto/base/export.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Status and related methods are inside util for consistency with embedders of
-// trace processor.
-namespace util {
-
-// Represents either the success or the failure message of a function.
-// This can used as the return type of functions which would usually return an
-// bool for success or int for errno but also wants to add some string context
-// (ususally for logging).
-class PERFETTO_EXPORT Status {
- public:
-  Status() : ok_(true) {}
-  explicit Status(std::string error) : ok_(false), message_(std::move(error)) {}
-
-  // Copy operations.
-  Status(const Status&) = default;
-  Status& operator=(const Status&) = default;
-
-  // Move operations. The moved-from state is valid but unspecified.
-  Status(Status&&) noexcept = default;
-  Status& operator=(Status&&) = default;
-
-  bool ok() const { return ok_; }
-
-  // Only valid to call when this message has an Err status (i.e. ok() returned
-  // false or operator bool() returned true).
-  const std::string& message() const { return message_; }
-
-  // Only valid to call when this message has an Err status (i.e. ok() returned
-  // false or operator bool() returned true).
-  const char* c_message() const { return message_.c_str(); }
-
- private:
-  bool ok_ = false;
-  std::string message_;
-};
-
-// Returns a status object which represents the Ok status.
-inline Status OkStatus() {
-  return Status();
-}
-
-// Returns a status object which represents an error with the given message
-// formatted using printf.
-__attribute__((__format__(__printf__, 1, 2))) inline Status ErrStatus(
-    const char* format,
-    ...) {
-  va_list ap;
-  va_start(ap, format);
-
-  char buffer[1024];
-  vsnprintf(buffer, sizeof(buffer), format, ap);
-  return Status(std::string(buffer));
-}
-
-}  // namespace util
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACE_PROCESSOR_STATUS_H_
diff --git a/include/perfetto/trace_processor/trace_processor.h b/include/perfetto/trace_processor/trace_processor.h
index d469937..13be4dd 100644
--- a/include/perfetto/trace_processor/trace_processor.h
+++ b/include/perfetto/trace_processor/trace_processor.h
@@ -17,21 +17,20 @@
 #ifndef INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_PROCESSOR_H_
 #define INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_PROCESSOR_H_
 
+#include <functional>
 #include <memory>
 #include <vector>
 
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/export.h"
+#include "perfetto/base/optional.h"
 #include "perfetto/trace_processor/basic_types.h"
-#include "perfetto/trace_processor/status.h"
-#include "perfetto/trace_processor/trace_processor_storage.h"
 
 namespace perfetto {
+
 namespace trace_processor {
 
-// Extends TraceProcessorStorage to support execution of SQL queries on loaded
-// traces. See TraceProcessorStorage for parsing of trace files.
-class PERFETTO_EXPORT TraceProcessor : public TraceProcessorStorage {
+// Coordinates the loading of traces from an arbitrary source and allows
+// execution of SQL queries on the events in these traces.
+class TraceProcessor {
  public:
   class IteratorImpl;
 
@@ -49,12 +48,12 @@
 
     // Forwards the iterator to the next result row and returns a boolean of
     // whether there is a next row. If this method returns false,
-    // |Status()| should be called to check if there was an error. If
+    // |GetLastError()| should be called to check if there was an error. If
     // there was no error, this means the EOF was reached.
     bool Next();
 
     // Returns the value associated with the column |col|. Any call to
-    // |Get()| must be preceded by a call to |Next()| returning
+    // |Get()| must be preceeded by a call to |Next()| returning
     // kHasNext. |col| must be less than the number returned by |ColumnCount()|.
     SqlValue Get(uint32_t col);
 
@@ -66,8 +65,10 @@
     // even before calling |Next()|.
     uint32_t ColumnCount();
 
-    // Returns the status of the iterator.
-    util::Status Status();
+    // Returns the error (if any) from the last call to next. If no error
+    // occurred, the returned value will be base::nullopt and implies that
+    // EOF was reached.
+    base::Optional<std::string> GetLastError();
 
    private:
     std::unique_ptr<IteratorImpl> iterator_;
@@ -76,51 +77,41 @@
   // Creates a new instance of TraceProcessor.
   static std::unique_ptr<TraceProcessor> CreateInstance(const Config&);
 
-  ~TraceProcessor() override;
+  virtual ~TraceProcessor();
+
+  // The entry point to push trace data into the processor. The trace format
+  // will be automatically discovered on the first push call. It is possible
+  // to make queries between two pushes.
+  // Returns true if parsing has been succeeding so far, false if some
+  // unrecoverable error happened. If this happens, the TraceProcessor will
+  // ignore the following Parse() requests and drop data on the floor.
+  virtual bool Parse(std::unique_ptr<uint8_t[]>, size_t) = 0;
+
+  // When parsing a bounded file (as opposite to streaming from a device) this
+  // function should be called when the last chunk of the file has been passed
+  // into Parse(). This allows to flush the events queued in the ordering stage,
+  // without having to wait for their time window to expire.
+  virtual void NotifyEndOfFile() = 0;
 
   // Executes a SQLite query on the loaded portion of the trace. The returned
   // iterator can be used to load rows from the result.
   virtual Iterator ExecuteQuery(const std::string& sql,
                                 int64_t time_queued = 0) = 0;
 
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
-  // Registers a metric at the given path which will run the specified SQL.
-  virtual util::Status RegisterMetric(const std::string& path,
-                                      const std::string& sql) = 0;
-
-  // Reads the FileDescriptorSet proto message given by |data| and |size| and
-  // adds any extensions to the metrics proto to allow them to be available as
-  // proto builder functions when computing metrics.
-  virtual util::Status ExtendMetricsProto(const uint8_t* data, size_t size) = 0;
-
   // Computes the given metrics on the loded portion of the trace. If
   // successful, the output argument |metrics_proto| will be filled with the
   // proto-encoded bytes for the message TraceMetrics in
-  // perfetto/metrics/metrics.proto.
-  virtual util::Status ComputeMetric(
-      const std::vector<std::string>& metric_names,
-      std::vector<uint8_t>* metrics_proto) = 0;
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
+  // perfetto/metrics/metrics.proto. The return value will be 0 if no error
+  // occured or non-zero otherwise.
+  virtual int ComputeMetric(const std::vector<std::string>& metric_names,
+                            std::vector<uint8_t>* metrics_proto) = 0;
 
   // Interrupts the current query. Typically used by Ctrl-C handler.
   virtual void InterruptQuery() = 0;
-
-  // Deletes all tables and views that have been created (by the UI or user)
-  // after the trace was loaded. It preserves the built-in tables/view created
-  // by the ingestion process. Returns the number of table/views deleted.
-  virtual size_t RestoreInitialTables() = 0;
-
-  // Sets/returns the name of the currently loaded trace or an empty string if
-  // no trace is fully loaded yet. This has no effect on the Trace Processor
-  // functionality and is used for UI purposes only.
-  // The returned name is NOT a path and will contain extra text w.r.t. the
-  // argument originally passed to SetCurrentTraceName(), e.g., "file (42 MB)".
-  virtual std::string GetCurrentTraceName() = 0;
-  virtual void SetCurrentTraceName(const std::string&) = 0;
 };
 
 // When set, logs SQLite actions on the console.
-void PERFETTO_EXPORT EnableSQLiteVtableDebugging();
+void EnableSQLiteVtableDebugging();
 
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/include/perfetto/trace_processor/trace_processor_storage.h b/include/perfetto/trace_processor/trace_processor_storage.h
deleted file mode 100644
index 9d27edb..0000000
--- a/include/perfetto/trace_processor/trace_processor_storage.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_PROCESSOR_STORAGE_H_
-#define INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_PROCESSOR_STORAGE_H_
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "perfetto/base/export.h"
-#include "perfetto/trace_processor/basic_types.h"
-#include "perfetto/trace_processor/status.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Coordinates the loading of traces from an arbitrary source.
-class PERFETTO_EXPORT TraceProcessorStorage {
- public:
-  // Creates a new instance of TraceProcessorStorage.
-  static std::unique_ptr<TraceProcessorStorage> CreateInstance(const Config&);
-
-  virtual ~TraceProcessorStorage();
-
-  // The entry point to push trace data into the processor. The trace format
-  // will be automatically discovered on the first push call. It is possible
-  // to make queries between two pushes.
-  // Returns the Ok status if parsing has been succeeding so far, and Error
-  // status if some unrecoverable error happened. If this happens, the
-  // TraceProcessor will ignore the following Parse() requests, drop data on the
-  // floor and return errors forever.
-  virtual util::Status Parse(std::unique_ptr<uint8_t[]>, size_t) = 0;
-
-  // When parsing a bounded file (as opposite to streaming from a device) this
-  // function should be called when the last chunk of the file has been passed
-  // into Parse(). This allows to flush the events queued in the ordering stage,
-  // without having to wait for their time window to expire.
-  virtual void NotifyEndOfFile() = 0;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_PROCESSOR_STORAGE_H_
diff --git a/include/perfetto/traced/BUILD.gn b/include/perfetto/traced/BUILD.gn
new file mode 100644
index 0000000..c0c9316
--- /dev/null
+++ b/include/perfetto/traced/BUILD.gn
@@ -0,0 +1,31 @@
+# Copyright (C) 2017 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.
+
+source_set("traced") {
+  sources = [
+    "data_source_types.h",
+    "traced.h",
+  ]
+}
+
+source_set("sys_stats_counters") {
+  deps = [
+    "../../../gn:default_deps",
+    "../../../protos/perfetto/common:zero",
+    "../base",
+  ]
+  sources = [
+    "sys_stats_counters.h",
+  ]
+}
diff --git a/include/perfetto/traced/data_source_types.h b/include/perfetto/traced/data_source_types.h
new file mode 100644
index 0000000..6a76e50
--- /dev/null
+++ b/include/perfetto/traced/data_source_types.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACED_DATA_SOURCE_TYPES_H_
+#define INCLUDE_PERFETTO_TRACED_DATA_SOURCE_TYPES_H_
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <set>
+#include <string>
+
+#include "perfetto/trace/filesystem/inode_file_map.pbzero.h"
+
+namespace perfetto {
+
+// On ARM, st_ino is not ino_t but unsigned long long.
+using Inode = decltype(stat::st_ino);
+
+// On ARM, st_dev is not dev_t but unsigned long long.
+using BlockDeviceID = decltype(stat::st_dev);
+
+class InodeMapValue {
+ public:
+  InodeMapValue(protos::pbzero::InodeFileMap_Entry_Type entry_type,
+                std::set<std::string> paths)
+      : entry_type_(entry_type), paths_(std::move(paths)) {}
+
+  InodeMapValue() {}
+
+  protos::pbzero::InodeFileMap_Entry_Type type() const { return entry_type_; }
+  const std::set<std::string>& paths() const { return paths_; }
+  void SetType(protos::pbzero::InodeFileMap_Entry_Type entry_type) {
+    entry_type_ = entry_type;
+  }
+  void SetPaths(std::set<std::string> paths) { paths_ = std::move(paths); }
+  void AddPath(std::string path) { paths_.emplace(std::move(path)); }
+
+  bool operator==(const perfetto::InodeMapValue& rhs) const {
+    return type() == rhs.type() && paths() == rhs.paths();
+  }
+
+ private:
+  protos::pbzero::InodeFileMap_Entry_Type entry_type_;
+  std::set<std::string> paths_;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACED_DATA_SOURCE_TYPES_H_
diff --git a/include/perfetto/traced/sys_stats_counters.h b/include/perfetto/traced/sys_stats_counters.h
new file mode 100644
index 0000000..98d25af
--- /dev/null
+++ b/include/perfetto/traced/sys_stats_counters.h
@@ -0,0 +1,235 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACED_SYS_STATS_COUNTERS_H_
+#define INCLUDE_PERFETTO_TRACED_SYS_STATS_COUNTERS_H_
+
+#include "perfetto/base/utils.h"
+#include "perfetto/common/sys_stats_counters.pbzero.h"
+
+#include <vector>
+
+namespace perfetto {
+
+struct KeyAndId {
+  const char* str;
+  int id;
+};
+
+constexpr KeyAndId kMeminfoKeys[] = {
+    {"MemUnspecified", protos::pbzero::MeminfoCounters::MEMINFO_UNSPECIFIED},
+    {"MemTotal", protos::pbzero::MeminfoCounters::MEMINFO_MEM_TOTAL},
+    {"MemFree", protos::pbzero::MeminfoCounters::MEMINFO_MEM_FREE},
+    {"MemAvailable", protos::pbzero::MeminfoCounters::MEMINFO_MEM_AVAILABLE},
+    {"Buffers", protos::pbzero::MeminfoCounters::MEMINFO_BUFFERS},
+    {"Cached", protos::pbzero::MeminfoCounters::MEMINFO_CACHED},
+    {"SwapCached", protos::pbzero::MeminfoCounters::MEMINFO_SWAP_CACHED},
+    {"Active", protos::pbzero::MeminfoCounters::MEMINFO_ACTIVE},
+    {"Inactive", protos::pbzero::MeminfoCounters::MEMINFO_INACTIVE},
+    {"Active(anon)", protos::pbzero::MeminfoCounters::MEMINFO_ACTIVE_ANON},
+    {"Inactive(anon)", protos::pbzero::MeminfoCounters::MEMINFO_INACTIVE_ANON},
+    {"Active(file)", protos::pbzero::MeminfoCounters::MEMINFO_ACTIVE_FILE},
+    {"Inactive(file)", protos::pbzero::MeminfoCounters::MEMINFO_INACTIVE_FILE},
+    {"Unevictable", protos::pbzero::MeminfoCounters::MEMINFO_UNEVICTABLE},
+    {"Mlocked", protos::pbzero::MeminfoCounters::MEMINFO_MLOCKED},
+    {"SwapTotal", protos::pbzero::MeminfoCounters::MEMINFO_SWAP_TOTAL},
+    {"SwapFree", protos::pbzero::MeminfoCounters::MEMINFO_SWAP_FREE},
+    {"Dirty", protos::pbzero::MeminfoCounters::MEMINFO_DIRTY},
+    {"Writeback", protos::pbzero::MeminfoCounters::MEMINFO_WRITEBACK},
+    {"AnonPages", protos::pbzero::MeminfoCounters::MEMINFO_ANON_PAGES},
+    {"Mapped", protos::pbzero::MeminfoCounters::MEMINFO_MAPPED},
+    {"Shmem", protos::pbzero::MeminfoCounters::MEMINFO_SHMEM},
+    {"Slab", protos::pbzero::MeminfoCounters::MEMINFO_SLAB},
+    {"SReclaimable", protos::pbzero::MeminfoCounters::MEMINFO_SLAB_RECLAIMABLE},
+    {"SUnreclaim", protos::pbzero::MeminfoCounters::MEMINFO_SLAB_UNRECLAIMABLE},
+    {"KernelStack", protos::pbzero::MeminfoCounters::MEMINFO_KERNEL_STACK},
+    {"PageTables", protos::pbzero::MeminfoCounters::MEMINFO_PAGE_TABLES},
+    {"CommitLimit", protos::pbzero::MeminfoCounters::MEMINFO_COMMIT_LIMIT},
+    {"Committed_AS", protos::pbzero::MeminfoCounters::MEMINFO_COMMITED_AS},
+    {"VmallocTotal", protos::pbzero::MeminfoCounters::MEMINFO_VMALLOC_TOTAL},
+    {"VmallocUsed", protos::pbzero::MeminfoCounters::MEMINFO_VMALLOC_USED},
+    {"VmallocChunk", protos::pbzero::MeminfoCounters::MEMINFO_VMALLOC_CHUNK},
+    {"CmaTotal", protos::pbzero::MeminfoCounters::MEMINFO_CMA_TOTAL},
+    {"CmaFree", protos::pbzero::MeminfoCounters::MEMINFO_CMA_FREE},
+};
+
+const KeyAndId kVmstatKeys[] = {
+    {"VmstatUnspecified", protos::pbzero::VmstatCounters::VMSTAT_UNSPECIFIED},
+    {"nr_free_pages", protos::pbzero::VmstatCounters::VMSTAT_NR_FREE_PAGES},
+    {"nr_alloc_batch", protos::pbzero::VmstatCounters::VMSTAT_NR_ALLOC_BATCH},
+    {"nr_inactive_anon",
+     protos::pbzero::VmstatCounters::VMSTAT_NR_INACTIVE_ANON},
+    {"nr_active_anon", protos::pbzero::VmstatCounters::VMSTAT_NR_ACTIVE_ANON},
+    {"nr_inactive_file",
+     protos::pbzero::VmstatCounters::VMSTAT_NR_INACTIVE_FILE},
+    {"nr_active_file", protos::pbzero::VmstatCounters::VMSTAT_NR_ACTIVE_FILE},
+    {"nr_unevictable", protos::pbzero::VmstatCounters::VMSTAT_NR_UNEVICTABLE},
+    {"nr_mlock", protos::pbzero::VmstatCounters::VMSTAT_NR_MLOCK},
+    {"nr_anon_pages", protos::pbzero::VmstatCounters::VMSTAT_NR_ANON_PAGES},
+    {"nr_mapped", protos::pbzero::VmstatCounters::VMSTAT_NR_MAPPED},
+    {"nr_file_pages", protos::pbzero::VmstatCounters::VMSTAT_NR_FILE_PAGES},
+    {"nr_dirty", protos::pbzero::VmstatCounters::VMSTAT_NR_DIRTY},
+    {"nr_writeback", protos::pbzero::VmstatCounters::VMSTAT_NR_WRITEBACK},
+    {"nr_slab_reclaimable",
+     protos::pbzero::VmstatCounters::VMSTAT_NR_SLAB_RECLAIMABLE},
+    {"nr_slab_unreclaimable",
+     protos::pbzero::VmstatCounters::VMSTAT_NR_SLAB_UNRECLAIMABLE},
+    {"nr_page_table_pages",
+     protos::pbzero::VmstatCounters::VMSTAT_NR_PAGE_TABLE_PAGES},
+    {"nr_kernel_stack", protos::pbzero::VmstatCounters::VMSTAT_NR_KERNEL_STACK},
+    {"nr_overhead", protos::pbzero::VmstatCounters::VMSTAT_NR_OVERHEAD},
+    {"nr_unstable", protos::pbzero::VmstatCounters::VMSTAT_NR_UNSTABLE},
+    {"nr_bounce", protos::pbzero::VmstatCounters::VMSTAT_NR_BOUNCE},
+    {"nr_vmscan_write", protos::pbzero::VmstatCounters::VMSTAT_NR_VMSCAN_WRITE},
+    {"nr_vmscan_immediate_reclaim",
+     protos::pbzero::VmstatCounters::VMSTAT_NR_VMSCAN_IMMEDIATE_RECLAIM},
+    {"nr_writeback_temp",
+     protos::pbzero::VmstatCounters::VMSTAT_NR_WRITEBACK_TEMP},
+    {"nr_isolated_anon",
+     protos::pbzero::VmstatCounters::VMSTAT_NR_ISOLATED_ANON},
+    {"nr_isolated_file",
+     protos::pbzero::VmstatCounters::VMSTAT_NR_ISOLATED_FILE},
+    {"nr_shmem", protos::pbzero::VmstatCounters::VMSTAT_NR_SHMEM},
+    {"nr_dirtied", protos::pbzero::VmstatCounters::VMSTAT_NR_DIRTIED},
+    {"nr_written", protos::pbzero::VmstatCounters::VMSTAT_NR_WRITTEN},
+    {"nr_pages_scanned",
+     protos::pbzero::VmstatCounters::VMSTAT_NR_PAGES_SCANNED},
+    {"workingset_refault",
+     protos::pbzero::VmstatCounters::VMSTAT_WORKINGSET_REFAULT},
+    {"workingset_activate",
+     protos::pbzero::VmstatCounters::VMSTAT_WORKINGSET_ACTIVATE},
+    {"workingset_nodereclaim",
+     protos::pbzero::VmstatCounters::VMSTAT_WORKINGSET_NODERECLAIM},
+    {"nr_anon_transparent_hugepages",
+     protos::pbzero::VmstatCounters::VMSTAT_NR_ANON_TRANSPARENT_HUGEPAGES},
+    {"nr_free_cma", protos::pbzero::VmstatCounters::VMSTAT_NR_FREE_CMA},
+    {"nr_swapcache", protos::pbzero::VmstatCounters::VMSTAT_NR_SWAPCACHE},
+    {"nr_dirty_threshold",
+     protos::pbzero::VmstatCounters::VMSTAT_NR_DIRTY_THRESHOLD},
+    {"nr_dirty_background_threshold",
+     protos::pbzero::VmstatCounters::VMSTAT_NR_DIRTY_BACKGROUND_THRESHOLD},
+    {"pgpgin", protos::pbzero::VmstatCounters::VMSTAT_PGPGIN},
+    {"pgpgout", protos::pbzero::VmstatCounters::VMSTAT_PGPGOUT},
+    {"pgpgoutclean", protos::pbzero::VmstatCounters::VMSTAT_PGPGOUTCLEAN},
+    {"pswpin", protos::pbzero::VmstatCounters::VMSTAT_PSWPIN},
+    {"pswpout", protos::pbzero::VmstatCounters::VMSTAT_PSWPOUT},
+    {"pgalloc_dma", protos::pbzero::VmstatCounters::VMSTAT_PGALLOC_DMA},
+    {"pgalloc_normal", protos::pbzero::VmstatCounters::VMSTAT_PGALLOC_NORMAL},
+    {"pgalloc_movable", protos::pbzero::VmstatCounters::VMSTAT_PGALLOC_MOVABLE},
+    {"pgfree", protos::pbzero::VmstatCounters::VMSTAT_PGFREE},
+    {"pgactivate", protos::pbzero::VmstatCounters::VMSTAT_PGACTIVATE},
+    {"pgdeactivate", protos::pbzero::VmstatCounters::VMSTAT_PGDEACTIVATE},
+    {"pgfault", protos::pbzero::VmstatCounters::VMSTAT_PGFAULT},
+    {"pgmajfault", protos::pbzero::VmstatCounters::VMSTAT_PGMAJFAULT},
+    {"pgrefill_dma", protos::pbzero::VmstatCounters::VMSTAT_PGREFILL_DMA},
+    {"pgrefill_normal", protos::pbzero::VmstatCounters::VMSTAT_PGREFILL_NORMAL},
+    {"pgrefill_movable",
+     protos::pbzero::VmstatCounters::VMSTAT_PGREFILL_MOVABLE},
+    {"pgsteal_kswapd_dma",
+     protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_KSWAPD_DMA},
+    {"pgsteal_kswapd_normal",
+     protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_KSWAPD_NORMAL},
+    {"pgsteal_kswapd_movable",
+     protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_KSWAPD_MOVABLE},
+    {"pgsteal_direct_dma",
+     protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_DIRECT_DMA},
+    {"pgsteal_direct_normal",
+     protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_DIRECT_NORMAL},
+    {"pgsteal_direct_movable",
+     protos::pbzero::VmstatCounters::VMSTAT_PGSTEAL_DIRECT_MOVABLE},
+    {"pgscan_kswapd_dma",
+     protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_KSWAPD_DMA},
+    {"pgscan_kswapd_normal",
+     protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_KSWAPD_NORMAL},
+    {"pgscan_kswapd_movable",
+     protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_KSWAPD_MOVABLE},
+    {"pgscan_direct_dma",
+     protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_DIRECT_DMA},
+    {"pgscan_direct_normal",
+     protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_DIRECT_NORMAL},
+    {"pgscan_direct_movable",
+     protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_DIRECT_MOVABLE},
+    {"pgscan_direct_throttle",
+     protos::pbzero::VmstatCounters::VMSTAT_PGSCAN_DIRECT_THROTTLE},
+    {"pginodesteal", protos::pbzero::VmstatCounters::VMSTAT_PGINODESTEAL},
+    {"slabs_scanned", protos::pbzero::VmstatCounters::VMSTAT_SLABS_SCANNED},
+    {"kswapd_inodesteal",
+     protos::pbzero::VmstatCounters::VMSTAT_KSWAPD_INODESTEAL},
+    {"kswapd_low_wmark_hit_quickly",
+     protos::pbzero::VmstatCounters::VMSTAT_KSWAPD_LOW_WMARK_HIT_QUICKLY},
+    {"kswapd_high_wmark_hit_quickly",
+     protos::pbzero::VmstatCounters::VMSTAT_KSWAPD_HIGH_WMARK_HIT_QUICKLY},
+    {"pageoutrun", protos::pbzero::VmstatCounters::VMSTAT_PAGEOUTRUN},
+    {"allocstall", protos::pbzero::VmstatCounters::VMSTAT_ALLOCSTALL},
+    {"pgrotated", protos::pbzero::VmstatCounters::VMSTAT_PGROTATED},
+    {"drop_pagecache", protos::pbzero::VmstatCounters::VMSTAT_DROP_PAGECACHE},
+    {"drop_slab", protos::pbzero::VmstatCounters::VMSTAT_DROP_SLAB},
+    {"pgmigrate_success",
+     protos::pbzero::VmstatCounters::VMSTAT_PGMIGRATE_SUCCESS},
+    {"pgmigrate_fail", protos::pbzero::VmstatCounters::VMSTAT_PGMIGRATE_FAIL},
+    {"compact_migrate_scanned",
+     protos::pbzero::VmstatCounters::VMSTAT_COMPACT_MIGRATE_SCANNED},
+    {"compact_free_scanned",
+     protos::pbzero::VmstatCounters::VMSTAT_COMPACT_FREE_SCANNED},
+    {"compact_isolated",
+     protos::pbzero::VmstatCounters::VMSTAT_COMPACT_ISOLATED},
+    {"compact_stall", protos::pbzero::VmstatCounters::VMSTAT_COMPACT_STALL},
+    {"compact_fail", protos::pbzero::VmstatCounters::VMSTAT_COMPACT_FAIL},
+    {"compact_success", protos::pbzero::VmstatCounters::VMSTAT_COMPACT_SUCCESS},
+    {"compact_daemon_wake",
+     protos::pbzero::VmstatCounters::VMSTAT_COMPACT_DAEMON_WAKE},
+    {"unevictable_pgs_culled",
+     protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_CULLED},
+    {"unevictable_pgs_scanned",
+     protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_SCANNED},
+    {"unevictable_pgs_rescued",
+     protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_RESCUED},
+    {"unevictable_pgs_mlocked",
+     protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_MLOCKED},
+    {"unevictable_pgs_munlocked",
+     protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_MUNLOCKED},
+    {"unevictable_pgs_cleared",
+     protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_CLEARED},
+    {"unevictable_pgs_stranded",
+     protos::pbzero::VmstatCounters::VMSTAT_UNEVICTABLE_PGS_STRANDED},
+};
+
+// Returns a lookup table of meminfo counter names addressable by counter id.
+inline std::vector<const char*> BuildMeminfoCounterNames() {
+  int max_id = 0;
+  for (size_t i = 0; i < base::ArraySize(kMeminfoKeys); i++)
+    max_id = std::max(max_id, kMeminfoKeys[i].id);
+  std::vector<const char*> v;
+  v.resize(static_cast<size_t>(max_id) + 1);
+  for (size_t i = 0; i < base::ArraySize(kMeminfoKeys); i++)
+    v[static_cast<size_t>(kMeminfoKeys[i].id)] = kMeminfoKeys[i].str;
+  return v;
+}
+
+inline std::vector<const char*> BuildVmstatCounterNames() {
+  int max_id = 0;
+  for (size_t i = 0; i < base::ArraySize(kVmstatKeys); i++)
+    max_id = std::max(max_id, kVmstatKeys[i].id);
+  std::vector<const char*> v;
+  v.resize(static_cast<size_t>(max_id) + 1);
+  for (size_t i = 0; i < base::ArraySize(kVmstatKeys); i++)
+    v[static_cast<size_t>(kVmstatKeys[i].id)] = kVmstatKeys[i].str;
+  return v;
+}
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACED_SYS_STATS_COUNTERS_H_
diff --git a/include/perfetto/traced/traced.h b/include/perfetto/traced/traced.h
new file mode 100644
index 0000000..dd58d63
--- /dev/null
+++ b/include/perfetto/traced/traced.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_TRACED_TRACED_H_
+#define INCLUDE_PERFETTO_TRACED_TRACED_H_
+
+#include "perfetto/base/build_config.h"
+
+namespace perfetto {
+
+int ServiceMain(int argc, char** argv);
+int ProbesMain(int argc, char** argv);
+int PerfettoCmdMain(int argc, char** argv);
+int TriggerPerfettoMain(int argc, char** argv);
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACED_TRACED_H_
diff --git a/include/perfetto/tracing.h b/include/perfetto/tracing.h
deleted file mode 100644
index be9ef6d..0000000
--- a/include/perfetto/tracing.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_H_
-#define INCLUDE_PERFETTO_TRACING_H_
-
-// This headers wraps all the headers necessary to use the public Perfetto
-// Tracing API. Embedders should preferably use this one header to avoid having
-// to figure out the various set of header required for each class.
-// The only exception to this should be large projects where build time is a
-// concern (e.g. chromium), which migh prefer sticking to strict IWYU.
-
-#include "perfetto/tracing/buffer_exhausted_policy.h"
-#include "perfetto/tracing/core/data_source_config.h"
-#include "perfetto/tracing/core/data_source_descriptor.h"
-#include "perfetto/tracing/core/trace_config.h"
-#include "perfetto/tracing/data_source.h"
-#include "perfetto/tracing/platform.h"
-#include "perfetto/tracing/tracing.h"
-#include "perfetto/tracing/tracing_backend.h"
-#include "perfetto/tracing/track_event.h"
-#include "perfetto/tracing/track_event_interned_data_index.h"
-
-#endif  // INCLUDE_PERFETTO_TRACING_H_
diff --git a/include/perfetto/tracing/BUILD.gn b/include/perfetto/tracing/BUILD.gn
deleted file mode 100644
index e40d43f..0000000
--- a/include/perfetto/tracing/BUILD.gn
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright (C) 2019 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.
-
-source_set("tracing") {
-  public_deps = [
-    "../../../gn:default_deps",
-    "../../../protos/perfetto/common:cpp",
-    "../../../protos/perfetto/trace:zero",
-    "../../../protos/perfetto/trace/interned_data:zero",
-    "../../../protos/perfetto/trace/track_event:zero",
-    "../base",
-    "../protozero",
-  ]
-
-  sources = [
-    "buffer_exhausted_policy.h",
-    "data_source.h",
-    "internal/basic_types.h",
-    "internal/data_source_internal.h",
-    "internal/tracing_muxer.h",
-    "internal/tracing_tls.h",
-    "internal/track_event_data_source.h",
-    "internal/track_event_internal.h",
-    "internal/track_event_macros.h",
-    "locked_handle.h",
-    "platform.h",
-    "trace_writer_base.h",
-    "tracing.h",
-    "tracing_backend.h",
-    "track_event.h",
-    "track_event_category_registry.h",
-    "track_event_context.h",
-    "track_event_interned_data_index.h",
-  ]
-}
diff --git a/include/perfetto/tracing/buffer_exhausted_policy.h b/include/perfetto/tracing/buffer_exhausted_policy.h
deleted file mode 100644
index 62da9fb..0000000
--- a/include/perfetto/tracing/buffer_exhausted_policy.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_BUFFER_EXHAUSTED_POLICY_H_
-#define INCLUDE_PERFETTO_TRACING_BUFFER_EXHAUSTED_POLICY_H_
-
-namespace perfetto {
-
-// Determines how SharedMemoryArbiterImpl::GetNewChunk() behaves when no free
-// chunks are available.
-enum class BufferExhaustedPolicy {
-  // SharedMemoryArbiterImpl::GetNewChunk() will stall if no free SMB chunk is
-  // available and wait for the tracing service to free one. Note that this
-  // requires that messages the arbiter sends to the tracing service (from any
-  // TraceWriter thread) will be received by it, even if all TraceWriter threads
-  // are stalled.
-  kStall,
-
-  // SharedMemoryArbiterImpl::GetNewChunk() will return an invalid chunk if no
-  // free SMB chunk is available. In this case, the TraceWriter will fall back
-  // to a garbage chunk and drop written data until acquiring a future chunk
-  // succeeds again.
-  kDrop,
-
-  // TODO(eseckler): Switch to kDrop by default and change the Android code to
-  // explicitly request kStall instead.
-  kDefault = kStall
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_BUFFER_EXHAUSTED_POLICY_H_
diff --git a/include/perfetto/tracing/core/BUILD.gn b/include/perfetto/tracing/core/BUILD.gn
index 8cc4829..78bc8e3 100644
--- a/include/perfetto/tracing/core/BUILD.gn
+++ b/include/perfetto/tracing/core/BUILD.gn
@@ -1,4 +1,4 @@
-# Copyright (C) 2019 The Android Open Source Project
+# Copyright (C) 2017 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.
@@ -14,14 +14,27 @@
 
 source_set("core") {
   public_deps = [
-    "../../../../protos/perfetto/common:cpp",
-    "../../../../protos/perfetto/config:cpp",
+    "../../base",
   ]
   sources = [
-    "chrome_config.h",
+    "basic_types.h",
+    "commit_data_request.h",
+    "consumer.h",
     "data_source_config.h",
     "data_source_descriptor.h",
+    "observable_events.h",
+    "producer.h",
+    "shared_memory.h",
+    "shared_memory_abi.h",
+    "shared_memory_arbiter.h",
+    "slice.h",
+    "startup_trace_writer.h",
+    "startup_trace_writer_registry.h",
     "trace_config.h",
+    "trace_packet.h",
+    "trace_stats.h",
+    "trace_writer.h",
+    "tracing_service.h",
     "tracing_service_state.h",
   ]
 }
diff --git a/include/perfetto/tracing/core/android_log_config.h b/include/perfetto/tracing/core/android_log_config.h
new file mode 100644
index 0000000..5eaa4ff
--- /dev/null
+++ b/include/perfetto/tracing/core/android_log_config.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/android/android_log_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_ANDROID_LOG_CONFIG_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_ANDROID_LOG_CONFIG_H_
+
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+#include "perfetto/tracing/core/android_log_constants.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {
+class AndroidLogConfig;
+}
+}  // namespace perfetto
+
+namespace perfetto {
+
+class PERFETTO_EXPORT AndroidLogConfig {
+ public:
+  enum AndroidLogId {
+    LID_DEFAULT = 0,
+    LID_RADIO = 1,
+    LID_EVENTS = 2,
+    LID_SYSTEM = 3,
+    LID_CRASH = 4,
+    LID_STATS = 5,
+    LID_SECURITY = 6,
+    LID_KERNEL = 7,
+  };
+  enum AndroidLogPriority {
+    PRIO_UNSPECIFIED = 0,
+    PRIO_UNUSED = 1,
+    PRIO_VERBOSE = 2,
+    PRIO_DEBUG = 3,
+    PRIO_INFO = 4,
+    PRIO_WARN = 5,
+    PRIO_ERROR = 6,
+    PRIO_FATAL = 7,
+  };
+  AndroidLogConfig();
+  ~AndroidLogConfig();
+  AndroidLogConfig(AndroidLogConfig&&) noexcept;
+  AndroidLogConfig& operator=(AndroidLogConfig&&);
+  AndroidLogConfig(const AndroidLogConfig&);
+  AndroidLogConfig& operator=(const AndroidLogConfig&);
+  bool operator==(const AndroidLogConfig&) const;
+  bool operator!=(const AndroidLogConfig& other) const {
+    return !(*this == other);
+  }
+
+  // Conversion methods from/to the corresponding protobuf types.
+  void FromProto(const perfetto::protos::AndroidLogConfig&);
+  void ToProto(perfetto::protos::AndroidLogConfig*) const;
+
+  int log_ids_size() const { return static_cast<int>(log_ids_.size()); }
+  const std::vector<AndroidLogId>& log_ids() const { return log_ids_; }
+  std::vector<AndroidLogId>* mutable_log_ids() { return &log_ids_; }
+  void clear_log_ids() { log_ids_.clear(); }
+  AndroidLogId* add_log_ids() {
+    log_ids_.emplace_back();
+    return &log_ids_.back();
+  }
+
+  AndroidLogPriority min_prio() const { return min_prio_; }
+  void set_min_prio(AndroidLogPriority value) { min_prio_ = value; }
+
+  int filter_tags_size() const { return static_cast<int>(filter_tags_.size()); }
+  const std::vector<std::string>& filter_tags() const { return filter_tags_; }
+  std::vector<std::string>* mutable_filter_tags() { return &filter_tags_; }
+  void clear_filter_tags() { filter_tags_.clear(); }
+  std::string* add_filter_tags() {
+    filter_tags_.emplace_back();
+    return &filter_tags_.back();
+  }
+
+ private:
+  std::vector<AndroidLogId> log_ids_;
+  AndroidLogPriority min_prio_ = {};
+  std::vector<std::string> filter_tags_;
+
+  // Allows to preserve unknown protobuf fields for compatibility
+  // with future versions of .proto files.
+  std::string unknown_fields_;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_ANDROID_LOG_CONFIG_H_
diff --git a/include/perfetto/tracing/core/android_log_constants.h b/include/perfetto/tracing/core/android_log_constants.h
new file mode 100644
index 0000000..9fefd1b
--- /dev/null
+++ b/include/perfetto/tracing/core/android_log_constants.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/common/android_log_constants.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_ANDROID_LOG_CONSTANTS_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_ANDROID_LOG_CONSTANTS_H_
+
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {}
+}  // namespace perfetto
+
+namespace perfetto {}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_ANDROID_LOG_CONSTANTS_H_
diff --git a/include/perfetto/tracing/core/android_power_config.h b/include/perfetto/tracing/core/android_power_config.h
new file mode 100644
index 0000000..6776d1c
--- /dev/null
+++ b/include/perfetto/tracing/core/android_power_config.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/power/android_power_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_ANDROID_POWER_CONFIG_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_ANDROID_POWER_CONFIG_H_
+
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {
+class AndroidPowerConfig;
+}
+}  // namespace perfetto
+
+namespace perfetto {
+
+class PERFETTO_EXPORT AndroidPowerConfig {
+ public:
+  enum BatteryCounters {
+    BATTERY_COUNTER_UNSPECIFIED = 0,
+    BATTERY_COUNTER_CHARGE = 1,
+    BATTERY_COUNTER_CAPACITY_PERCENT = 2,
+    BATTERY_COUNTER_CURRENT = 3,
+    BATTERY_COUNTER_CURRENT_AVG = 4,
+  };
+  AndroidPowerConfig();
+  ~AndroidPowerConfig();
+  AndroidPowerConfig(AndroidPowerConfig&&) noexcept;
+  AndroidPowerConfig& operator=(AndroidPowerConfig&&);
+  AndroidPowerConfig(const AndroidPowerConfig&);
+  AndroidPowerConfig& operator=(const AndroidPowerConfig&);
+  bool operator==(const AndroidPowerConfig&) const;
+  bool operator!=(const AndroidPowerConfig& other) const {
+    return !(*this == other);
+  }
+
+  // Conversion methods from/to the corresponding protobuf types.
+  void FromProto(const perfetto::protos::AndroidPowerConfig&);
+  void ToProto(perfetto::protos::AndroidPowerConfig*) const;
+
+  uint32_t battery_poll_ms() const { return battery_poll_ms_; }
+  void set_battery_poll_ms(uint32_t value) { battery_poll_ms_ = value; }
+
+  int battery_counters_size() const {
+    return static_cast<int>(battery_counters_.size());
+  }
+  const std::vector<BatteryCounters>& battery_counters() const {
+    return battery_counters_;
+  }
+  std::vector<BatteryCounters>* mutable_battery_counters() {
+    return &battery_counters_;
+  }
+  void clear_battery_counters() { battery_counters_.clear(); }
+  BatteryCounters* add_battery_counters() {
+    battery_counters_.emplace_back();
+    return &battery_counters_.back();
+  }
+
+  bool collect_power_rails() const { return collect_power_rails_; }
+  void set_collect_power_rails(bool value) { collect_power_rails_ = value; }
+
+ private:
+  uint32_t battery_poll_ms_ = {};
+  std::vector<BatteryCounters> battery_counters_;
+  bool collect_power_rails_ = {};
+
+  // Allows to preserve unknown protobuf fields for compatibility
+  // with future versions of .proto files.
+  std::string unknown_fields_;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_ANDROID_POWER_CONFIG_H_
diff --git a/include/perfetto/tracing/core/basic_types.h b/include/perfetto/tracing/core/basic_types.h
new file mode 100644
index 0000000..a7bbdf2
--- /dev/null
+++ b/include/perfetto/tracing/core/basic_types.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_TRACING_CORE_BASIC_TYPES_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_BASIC_TYPES_H_
+
+#include "perfetto/base/build_config.h"
+
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+using uid_t = unsigned int;
+#endif
+
+namespace perfetto {
+
+// Unique within the scope of the tracing service.
+using TracingSessionID = uint64_t;
+
+// Unique within the scope of the tracing service.
+using ProducerID = uint16_t;
+
+// Unique within the scope of the tracing service.
+using DataSourceInstanceID = uint64_t;
+
+// Unique within the scope of a Producer.
+using WriterID = uint16_t;
+
+// Unique within the scope of the tracing service.
+using FlushRequestID = uint64_t;
+
+// We need one FD per producer and we are not going to be able to keep > 64k FDs
+// open in the service.
+static constexpr ProducerID kMaxProducerID = static_cast<ProducerID>(-1);
+
+// 1024 Writers per producer seems a resonable bound. This reduces the ability
+// to memory-DoS the service by having to keep track of too many writer IDs.
+static constexpr WriterID kMaxWriterID = static_cast<WriterID>((1 << 10) - 1);
+
+// Unique within the scope of a {ProducerID, WriterID} tuple.
+using ChunkID = uint32_t;
+static constexpr ChunkID kMaxChunkID = static_cast<ChunkID>(-1);
+
+// Unique within the scope of the tracing service.
+using BufferID = uint16_t;
+
+// Keep this in sync with SharedMemoryABI::PageHeader::target_buffer.
+static constexpr BufferID kMaxTraceBufferID = static_cast<BufferID>(-1);
+
+// Unique within the scope of a tracing session.
+using PacketSequenceID = uint32_t;
+// Used for extra packets emitted by the service, such as statistics.
+static constexpr PacketSequenceID kInvalidPacketSequenceID = 0;
+static constexpr PacketSequenceID kServicePacketSequenceID = 1;
+static constexpr PacketSequenceID kMaxPacketSequenceID =
+    static_cast<PacketSequenceID>(-1);
+
+// TODO(primiano): temporary. The buffer page size should be configurable by
+// consumers.
+static constexpr size_t kBufferPageSize = 8192;
+
+constexpr uid_t kInvalidUid = static_cast<uid_t>(-1);
+
+constexpr uint32_t kDefaultFlushTimeoutMs = 5000;
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_BASIC_TYPES_H_
diff --git a/include/perfetto/tracing/core/chrome_config.h b/include/perfetto/tracing/core/chrome_config.h
index dff4d87..228ca0a 100644
--- a/include/perfetto/tracing/core/chrome_config.h
+++ b/include/perfetto/tracing/core/chrome_config.h
@@ -14,14 +14,68 @@
  * limitations under the License.
  */
 
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/chrome/chrome_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
 #ifndef INCLUDE_PERFETTO_TRACING_CORE_CHROME_CONFIG_H_
 #define INCLUDE_PERFETTO_TRACING_CORE_CHROME_CONFIG_H_
 
-// This header exists only for legacy code that used to refer to the
-// checked-in auto-generated code, before it was moved to be a build-time gen
-// rule. DO NOT add any new includes to this header, instead directly include
-// the one below.
-// TODO(primiano): cleanup call-sites and remove this header.
-#include "protos/perfetto/config/chrome/chrome_config.gen.h"
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {
+class ChromeConfig;
+}
+}  // namespace perfetto
+
+namespace perfetto {
+
+class PERFETTO_EXPORT ChromeConfig {
+ public:
+  ChromeConfig();
+  ~ChromeConfig();
+  ChromeConfig(ChromeConfig&&) noexcept;
+  ChromeConfig& operator=(ChromeConfig&&);
+  ChromeConfig(const ChromeConfig&);
+  ChromeConfig& operator=(const ChromeConfig&);
+  bool operator==(const ChromeConfig&) const;
+  bool operator!=(const ChromeConfig& other) const { return !(*this == other); }
+
+  // Conversion methods from/to the corresponding protobuf types.
+  void FromProto(const perfetto::protos::ChromeConfig&);
+  void ToProto(perfetto::protos::ChromeConfig*) const;
+
+  const std::string& trace_config() const { return trace_config_; }
+  void set_trace_config(const std::string& value) { trace_config_ = value; }
+
+  bool privacy_filtering_enabled() const { return privacy_filtering_enabled_; }
+  void set_privacy_filtering_enabled(bool value) {
+    privacy_filtering_enabled_ = value;
+  }
+
+ private:
+  std::string trace_config_ = {};
+  bool privacy_filtering_enabled_ = {};
+
+  // Allows to preserve unknown protobuf fields for compatibility
+  // with future versions of .proto files.
+  std::string unknown_fields_;
+};
+
+}  // namespace perfetto
 
 #endif  // INCLUDE_PERFETTO_TRACING_CORE_CHROME_CONFIG_H_
diff --git a/include/perfetto/tracing/core/commit_data_request.h b/include/perfetto/tracing/core/commit_data_request.h
new file mode 100644
index 0000000..7b6278e
--- /dev/null
+++ b/include/perfetto/tracing/core/commit_data_request.h
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/common/commit_data_request.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_COMMIT_DATA_REQUEST_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_COMMIT_DATA_REQUEST_H_
+
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {
+class CommitDataRequest;
+class CommitDataRequest_ChunksToMove;
+class CommitDataRequest_ChunkToPatch;
+class CommitDataRequest_ChunkToPatch_Patch;
+}  // namespace protos
+}  // namespace perfetto
+
+namespace perfetto {
+
+class PERFETTO_EXPORT CommitDataRequest {
+ public:
+  class PERFETTO_EXPORT ChunksToMove {
+   public:
+    ChunksToMove();
+    ~ChunksToMove();
+    ChunksToMove(ChunksToMove&&) noexcept;
+    ChunksToMove& operator=(ChunksToMove&&);
+    ChunksToMove(const ChunksToMove&);
+    ChunksToMove& operator=(const ChunksToMove&);
+    bool operator==(const ChunksToMove&) const;
+    bool operator!=(const ChunksToMove& other) const {
+      return !(*this == other);
+    }
+
+    // Conversion methods from/to the corresponding protobuf types.
+    void FromProto(const perfetto::protos::CommitDataRequest_ChunksToMove&);
+    void ToProto(perfetto::protos::CommitDataRequest_ChunksToMove*) const;
+
+    uint32_t page() const { return page_; }
+    void set_page(uint32_t value) { page_ = value; }
+
+    uint32_t chunk() const { return chunk_; }
+    void set_chunk(uint32_t value) { chunk_ = value; }
+
+    uint32_t target_buffer() const { return target_buffer_; }
+    void set_target_buffer(uint32_t value) { target_buffer_ = value; }
+
+   private:
+    uint32_t page_ = {};
+    uint32_t chunk_ = {};
+    uint32_t target_buffer_ = {};
+
+    // Allows to preserve unknown protobuf fields for compatibility
+    // with future versions of .proto files.
+    std::string unknown_fields_;
+  };
+
+  class PERFETTO_EXPORT ChunkToPatch {
+   public:
+    class PERFETTO_EXPORT Patch {
+     public:
+      Patch();
+      ~Patch();
+      Patch(Patch&&) noexcept;
+      Patch& operator=(Patch&&);
+      Patch(const Patch&);
+      Patch& operator=(const Patch&);
+      bool operator==(const Patch&) const;
+      bool operator!=(const Patch& other) const { return !(*this == other); }
+
+      // Conversion methods from/to the corresponding protobuf types.
+      void FromProto(
+          const perfetto::protos::CommitDataRequest_ChunkToPatch_Patch&);
+      void ToProto(
+          perfetto::protos::CommitDataRequest_ChunkToPatch_Patch*) const;
+
+      uint32_t offset() const { return offset_; }
+      void set_offset(uint32_t value) { offset_ = value; }
+
+      const std::string& data() const { return data_; }
+      void set_data(const std::string& value) { data_ = value; }
+      void set_data(const void* p, size_t s) {
+        data_.assign(reinterpret_cast<const char*>(p), s);
+      }
+
+     private:
+      uint32_t offset_ = {};
+      std::string data_ = {};
+
+      // Allows to preserve unknown protobuf fields for compatibility
+      // with future versions of .proto files.
+      std::string unknown_fields_;
+    };
+
+    ChunkToPatch();
+    ~ChunkToPatch();
+    ChunkToPatch(ChunkToPatch&&) noexcept;
+    ChunkToPatch& operator=(ChunkToPatch&&);
+    ChunkToPatch(const ChunkToPatch&);
+    ChunkToPatch& operator=(const ChunkToPatch&);
+    bool operator==(const ChunkToPatch&) const;
+    bool operator!=(const ChunkToPatch& other) const {
+      return !(*this == other);
+    }
+
+    // Conversion methods from/to the corresponding protobuf types.
+    void FromProto(const perfetto::protos::CommitDataRequest_ChunkToPatch&);
+    void ToProto(perfetto::protos::CommitDataRequest_ChunkToPatch*) const;
+
+    uint32_t target_buffer() const { return target_buffer_; }
+    void set_target_buffer(uint32_t value) { target_buffer_ = value; }
+
+    uint32_t writer_id() const { return writer_id_; }
+    void set_writer_id(uint32_t value) { writer_id_ = value; }
+
+    uint32_t chunk_id() const { return chunk_id_; }
+    void set_chunk_id(uint32_t value) { chunk_id_ = value; }
+
+    int patches_size() const { return static_cast<int>(patches_.size()); }
+    const std::vector<Patch>& patches() const { return patches_; }
+    std::vector<Patch>* mutable_patches() { return &patches_; }
+    void clear_patches() { patches_.clear(); }
+    Patch* add_patches() {
+      patches_.emplace_back();
+      return &patches_.back();
+    }
+
+    bool has_more_patches() const { return has_more_patches_; }
+    void set_has_more_patches(bool value) { has_more_patches_ = value; }
+
+   private:
+    uint32_t target_buffer_ = {};
+    uint32_t writer_id_ = {};
+    uint32_t chunk_id_ = {};
+    std::vector<Patch> patches_;
+    bool has_more_patches_ = {};
+
+    // Allows to preserve unknown protobuf fields for compatibility
+    // with future versions of .proto files.
+    std::string unknown_fields_;
+  };
+
+  CommitDataRequest();
+  ~CommitDataRequest();
+  CommitDataRequest(CommitDataRequest&&) noexcept;
+  CommitDataRequest& operator=(CommitDataRequest&&);
+  CommitDataRequest(const CommitDataRequest&);
+  CommitDataRequest& operator=(const CommitDataRequest&);
+  bool operator==(const CommitDataRequest&) const;
+  bool operator!=(const CommitDataRequest& other) const {
+    return !(*this == other);
+  }
+
+  // Conversion methods from/to the corresponding protobuf types.
+  void FromProto(const perfetto::protos::CommitDataRequest&);
+  void ToProto(perfetto::protos::CommitDataRequest*) const;
+
+  int chunks_to_move_size() const {
+    return static_cast<int>(chunks_to_move_.size());
+  }
+  const std::vector<ChunksToMove>& chunks_to_move() const {
+    return chunks_to_move_;
+  }
+  std::vector<ChunksToMove>* mutable_chunks_to_move() {
+    return &chunks_to_move_;
+  }
+  void clear_chunks_to_move() { chunks_to_move_.clear(); }
+  ChunksToMove* add_chunks_to_move() {
+    chunks_to_move_.emplace_back();
+    return &chunks_to_move_.back();
+  }
+
+  int chunks_to_patch_size() const {
+    return static_cast<int>(chunks_to_patch_.size());
+  }
+  const std::vector<ChunkToPatch>& chunks_to_patch() const {
+    return chunks_to_patch_;
+  }
+  std::vector<ChunkToPatch>* mutable_chunks_to_patch() {
+    return &chunks_to_patch_;
+  }
+  void clear_chunks_to_patch() { chunks_to_patch_.clear(); }
+  ChunkToPatch* add_chunks_to_patch() {
+    chunks_to_patch_.emplace_back();
+    return &chunks_to_patch_.back();
+  }
+
+  uint64_t flush_request_id() const { return flush_request_id_; }
+  void set_flush_request_id(uint64_t value) { flush_request_id_ = value; }
+
+ private:
+  std::vector<ChunksToMove> chunks_to_move_;
+  std::vector<ChunkToPatch> chunks_to_patch_;
+  uint64_t flush_request_id_ = {};
+
+  // Allows to preserve unknown protobuf fields for compatibility
+  // with future versions of .proto files.
+  std::string unknown_fields_;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_COMMIT_DATA_REQUEST_H_
diff --git a/include/perfetto/tracing/core/consumer.h b/include/perfetto/tracing/core/consumer.h
new file mode 100644
index 0000000..d8d3f13
--- /dev/null
+++ b/include/perfetto/tracing/core/consumer.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_TRACING_CORE_CONSUMER_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_CONSUMER_H_
+
+#include <vector>
+
+#include "perfetto/base/export.h"
+#include "perfetto/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/observable_events.h"
+
+namespace perfetto {
+
+class TraceConfig;
+class TracePacket;
+class TraceStats;
+class TracingServiceState;
+
+class PERFETTO_EXPORT Consumer {
+ public:
+  virtual ~Consumer();
+
+  // Called by Service (or more typically by the transport layer, on behalf of
+  // the remote Service), once the Consumer <> Service connection has been
+  // established.
+  virtual void OnConnect() = 0;
+
+  // Called by the Service or by the transport layer if the connection with the
+  // service drops, either voluntarily (e.g., by destroying the ConsumerEndpoint
+  // obtained through Service::ConnectConsumer()) or involuntarily (e.g., if the
+  // Service process crashes).
+  virtual void OnDisconnect() = 0;
+
+  // Called by the Service after the tracing session has ended. This can happen
+  // for a variety of reasons:
+  // - The consumer explicitly called DisableTracing()
+  // - The TraceConfig's |duration_ms| has been reached.
+  // - The TraceConfig's |max_file_size_bytes| has been reached.
+  // - An error occurred while trying to enable tracing.
+  virtual void OnTracingDisabled() = 0;
+
+  // Called back by the Service (or transport layer) after invoking
+  // TracingService::ConsumerEndpoint::ReadBuffers(). This function can be
+  // called more than once. Each invocation can carry one or more
+  // TracePacket(s). Upon the last call, |has_more| is set to true (i.e.
+  // |has_more| is a !EOF).
+  virtual void OnTraceData(std::vector<TracePacket>, bool has_more) = 0;
+
+  // Called back by the Service (or transport layer) after invoking
+  // TracingService::ConsumerEndpoint::Detach().
+  // The consumer can disconnect at this point and the trace session will keep
+  // on going. A new consumer can later re-attach passing back the same |key|
+  // passed to Detach(), but only if the two requests come from the same uid.
+  virtual void OnDetach(bool success) = 0;
+
+  // Called back by the Service (or transport layer) after invoking
+  // TracingService::ConsumerEndpoint::Attach().
+  virtual void OnAttach(bool success, const TraceConfig&) = 0;
+
+  // Called back by the Service (or transport layer) after invoking
+  // TracingService::ConsumerEndpoint::GetTraceStats().
+  virtual void OnTraceStats(bool success, const TraceStats&) = 0;
+
+  // Called back by the Service (or transport layer) after invoking
+  // TracingService::ConsumerEndpoint::ObserveEvents() whenever one or more
+  // ObservableEvents of enabled event types occur.
+  virtual void OnObservableEvents(const ObservableEvents&) = 0;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_CONSUMER_H_
diff --git a/include/perfetto/tracing/core/data_source_config.h b/include/perfetto/tracing/core/data_source_config.h
index 9b7966c..5cb0cf1 100644
--- a/include/perfetto/tracing/core/data_source_config.h
+++ b/include/perfetto/tracing/core/data_source_config.h
@@ -14,14 +14,168 @@
  * limitations under the License.
  */
 
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/data_source_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
 #ifndef INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_CONFIG_H_
 #define INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_CONFIG_H_
 
-// This header exists only for legacy code that used to refer to the
-// checked-in auto-generated code, before it was moved to be a build-time gen
-// rule. DO NOT add any new includes to this header, instead directly include
-// the one below.
-// TODO(primiano): cleanup call-sites and remove this header.
-#include "protos/perfetto/config/data_source_config.gen.h"
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+#include "perfetto/tracing/core/android_log_config.h"
+#include "perfetto/tracing/core/android_power_config.h"
+#include "perfetto/tracing/core/chrome_config.h"
+#include "perfetto/tracing/core/ftrace_config.h"
+#include "perfetto/tracing/core/heapprofd_config.h"
+#include "perfetto/tracing/core/inode_file_config.h"
+#include "perfetto/tracing/core/packages_list_config.h"
+#include "perfetto/tracing/core/process_stats_config.h"
+#include "perfetto/tracing/core/sys_stats_config.h"
+#include "perfetto/tracing/core/test_config.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {
+class DataSourceConfig;
+class FtraceConfig;
+class ChromeConfig;
+class InodeFileConfig;
+class InodeFileConfig_MountPointMappingEntry;
+class ProcessStatsConfig;
+class SysStatsConfig;
+class HeapprofdConfig;
+class HeapprofdConfig_ContinuousDumpConfig;
+class AndroidPowerConfig;
+class AndroidLogConfig;
+class PackagesListConfig;
+class TestConfig;
+class TestConfig_DummyFields;
+}  // namespace protos
+}  // namespace perfetto
+
+namespace perfetto {
+
+class PERFETTO_EXPORT DataSourceConfig {
+ public:
+  DataSourceConfig();
+  ~DataSourceConfig();
+  DataSourceConfig(DataSourceConfig&&) noexcept;
+  DataSourceConfig& operator=(DataSourceConfig&&);
+  DataSourceConfig(const DataSourceConfig&);
+  DataSourceConfig& operator=(const DataSourceConfig&);
+  bool operator==(const DataSourceConfig&) const;
+  bool operator!=(const DataSourceConfig& other) const {
+    return !(*this == other);
+  }
+
+  // Conversion methods from/to the corresponding protobuf types.
+  void FromProto(const perfetto::protos::DataSourceConfig&);
+  void ToProto(perfetto::protos::DataSourceConfig*) const;
+
+  const std::string& name() const { return name_; }
+  void set_name(const std::string& value) { name_ = value; }
+
+  uint32_t target_buffer() const { return target_buffer_; }
+  void set_target_buffer(uint32_t value) { target_buffer_ = value; }
+
+  uint32_t trace_duration_ms() const { return trace_duration_ms_; }
+  void set_trace_duration_ms(uint32_t value) { trace_duration_ms_ = value; }
+
+  bool enable_extra_guardrails() const { return enable_extra_guardrails_; }
+  void set_enable_extra_guardrails(bool value) {
+    enable_extra_guardrails_ = value;
+  }
+
+  uint64_t tracing_session_id() const { return tracing_session_id_; }
+  void set_tracing_session_id(uint64_t value) { tracing_session_id_ = value; }
+
+  const FtraceConfig& ftrace_config() const { return ftrace_config_; }
+  FtraceConfig* mutable_ftrace_config() { return &ftrace_config_; }
+
+  const ChromeConfig& chrome_config() const { return chrome_config_; }
+  ChromeConfig* mutable_chrome_config() { return &chrome_config_; }
+
+  const InodeFileConfig& inode_file_config() const {
+    return inode_file_config_;
+  }
+  InodeFileConfig* mutable_inode_file_config() { return &inode_file_config_; }
+
+  const ProcessStatsConfig& process_stats_config() const {
+    return process_stats_config_;
+  }
+  ProcessStatsConfig* mutable_process_stats_config() {
+    return &process_stats_config_;
+  }
+
+  const SysStatsConfig& sys_stats_config() const { return sys_stats_config_; }
+  SysStatsConfig* mutable_sys_stats_config() { return &sys_stats_config_; }
+
+  const HeapprofdConfig& heapprofd_config() const { return heapprofd_config_; }
+  HeapprofdConfig* mutable_heapprofd_config() { return &heapprofd_config_; }
+
+  const AndroidPowerConfig& android_power_config() const {
+    return android_power_config_;
+  }
+  AndroidPowerConfig* mutable_android_power_config() {
+    return &android_power_config_;
+  }
+
+  const AndroidLogConfig& android_log_config() const {
+    return android_log_config_;
+  }
+  AndroidLogConfig* mutable_android_log_config() {
+    return &android_log_config_;
+  }
+
+  const PackagesListConfig& packages_list_config() const {
+    return packages_list_config_;
+  }
+  PackagesListConfig* mutable_packages_list_config() {
+    return &packages_list_config_;
+  }
+
+  const std::string& legacy_config() const { return legacy_config_; }
+  void set_legacy_config(const std::string& value) { legacy_config_ = value; }
+
+  const TestConfig& for_testing() const { return for_testing_; }
+  TestConfig* mutable_for_testing() { return &for_testing_; }
+
+ private:
+  std::string name_ = {};
+  uint32_t target_buffer_ = {};
+  uint32_t trace_duration_ms_ = {};
+  bool enable_extra_guardrails_ = {};
+  uint64_t tracing_session_id_ = {};
+  FtraceConfig ftrace_config_ = {};
+  ChromeConfig chrome_config_ = {};
+  InodeFileConfig inode_file_config_ = {};
+  ProcessStatsConfig process_stats_config_ = {};
+  SysStatsConfig sys_stats_config_ = {};
+  HeapprofdConfig heapprofd_config_ = {};
+  AndroidPowerConfig android_power_config_ = {};
+  AndroidLogConfig android_log_config_ = {};
+  PackagesListConfig packages_list_config_ = {};
+  std::string legacy_config_ = {};
+  TestConfig for_testing_ = {};
+
+  // Allows to preserve unknown protobuf fields for compatibility
+  // with future versions of .proto files.
+  std::string unknown_fields_;
+};
+
+}  // namespace perfetto
 
 #endif  // INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_CONFIG_H_
diff --git a/include/perfetto/tracing/core/data_source_descriptor.h b/include/perfetto/tracing/core/data_source_descriptor.h
index 75818bf..79346cc 100644
--- a/include/perfetto/tracing/core/data_source_descriptor.h
+++ b/include/perfetto/tracing/core/data_source_descriptor.h
@@ -14,14 +14,80 @@
  * limitations under the License.
  */
 
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/common/data_source_descriptor.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
 #ifndef INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_DESCRIPTOR_H_
 #define INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_DESCRIPTOR_H_
 
-// This header exists only for legacy code that used to refer to the
-// checked-in auto-generated code, before it was moved to be a build-time gen
-// rule. DO NOT add any new includes to this header, instead directly include
-// the one below.
-// TODO(primiano): cleanup call-sites and remove this header.
-#include "protos/perfetto/common/data_source_descriptor.gen.h"
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {
+class DataSourceDescriptor;
+}
+}  // namespace perfetto
+
+namespace perfetto {
+
+class PERFETTO_EXPORT DataSourceDescriptor {
+ public:
+  DataSourceDescriptor();
+  ~DataSourceDescriptor();
+  DataSourceDescriptor(DataSourceDescriptor&&) noexcept;
+  DataSourceDescriptor& operator=(DataSourceDescriptor&&);
+  DataSourceDescriptor(const DataSourceDescriptor&);
+  DataSourceDescriptor& operator=(const DataSourceDescriptor&);
+  bool operator==(const DataSourceDescriptor&) const;
+  bool operator!=(const DataSourceDescriptor& other) const {
+    return !(*this == other);
+  }
+
+  // Conversion methods from/to the corresponding protobuf types.
+  void FromProto(const perfetto::protos::DataSourceDescriptor&);
+  void ToProto(perfetto::protos::DataSourceDescriptor*) const;
+
+  const std::string& name() const { return name_; }
+  void set_name(const std::string& value) { name_ = value; }
+
+  bool will_notify_on_stop() const { return will_notify_on_stop_; }
+  void set_will_notify_on_stop(bool value) { will_notify_on_stop_ = value; }
+
+  bool will_notify_on_start() const { return will_notify_on_start_; }
+  void set_will_notify_on_start(bool value) { will_notify_on_start_ = value; }
+
+  bool handles_incremental_state_clear() const {
+    return handles_incremental_state_clear_;
+  }
+  void set_handles_incremental_state_clear(bool value) {
+    handles_incremental_state_clear_ = value;
+  }
+
+ private:
+  std::string name_ = {};
+  bool will_notify_on_stop_ = {};
+  bool will_notify_on_start_ = {};
+  bool handles_incremental_state_clear_ = {};
+
+  // Allows to preserve unknown protobuf fields for compatibility
+  // with future versions of .proto files.
+  std::string unknown_fields_;
+};
+
+}  // namespace perfetto
 
 #endif  // INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_DESCRIPTOR_H_
diff --git a/include/perfetto/tracing/core/ftrace_config.h b/include/perfetto/tracing/core/ftrace_config.h
new file mode 100644
index 0000000..1b6abb4
--- /dev/null
+++ b/include/perfetto/tracing/core/ftrace_config.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/ftrace/ftrace_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_FTRACE_CONFIG_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_FTRACE_CONFIG_H_
+
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {
+class FtraceConfig;
+}
+}  // namespace perfetto
+
+namespace perfetto {
+
+class PERFETTO_EXPORT FtraceConfig {
+ public:
+  FtraceConfig();
+  ~FtraceConfig();
+  FtraceConfig(FtraceConfig&&) noexcept;
+  FtraceConfig& operator=(FtraceConfig&&);
+  FtraceConfig(const FtraceConfig&);
+  FtraceConfig& operator=(const FtraceConfig&);
+  bool operator==(const FtraceConfig&) const;
+  bool operator!=(const FtraceConfig& other) const { return !(*this == other); }
+
+  // Conversion methods from/to the corresponding protobuf types.
+  void FromProto(const perfetto::protos::FtraceConfig&);
+  void ToProto(perfetto::protos::FtraceConfig*) const;
+
+  int ftrace_events_size() const {
+    return static_cast<int>(ftrace_events_.size());
+  }
+  const std::vector<std::string>& ftrace_events() const {
+    return ftrace_events_;
+  }
+  std::vector<std::string>* mutable_ftrace_events() { return &ftrace_events_; }
+  void clear_ftrace_events() { ftrace_events_.clear(); }
+  std::string* add_ftrace_events() {
+    ftrace_events_.emplace_back();
+    return &ftrace_events_.back();
+  }
+
+  int atrace_categories_size() const {
+    return static_cast<int>(atrace_categories_.size());
+  }
+  const std::vector<std::string>& atrace_categories() const {
+    return atrace_categories_;
+  }
+  std::vector<std::string>* mutable_atrace_categories() {
+    return &atrace_categories_;
+  }
+  void clear_atrace_categories() { atrace_categories_.clear(); }
+  std::string* add_atrace_categories() {
+    atrace_categories_.emplace_back();
+    return &atrace_categories_.back();
+  }
+
+  int atrace_apps_size() const { return static_cast<int>(atrace_apps_.size()); }
+  const std::vector<std::string>& atrace_apps() const { return atrace_apps_; }
+  std::vector<std::string>* mutable_atrace_apps() { return &atrace_apps_; }
+  void clear_atrace_apps() { atrace_apps_.clear(); }
+  std::string* add_atrace_apps() {
+    atrace_apps_.emplace_back();
+    return &atrace_apps_.back();
+  }
+
+  uint32_t buffer_size_kb() const { return buffer_size_kb_; }
+  void set_buffer_size_kb(uint32_t value) { buffer_size_kb_ = value; }
+
+  uint32_t drain_period_ms() const { return drain_period_ms_; }
+  void set_drain_period_ms(uint32_t value) { drain_period_ms_ = value; }
+
+ private:
+  std::vector<std::string> ftrace_events_;
+  std::vector<std::string> atrace_categories_;
+  std::vector<std::string> atrace_apps_;
+  uint32_t buffer_size_kb_ = {};
+  uint32_t drain_period_ms_ = {};
+
+  // Allows to preserve unknown protobuf fields for compatibility
+  // with future versions of .proto files.
+  std::string unknown_fields_;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_FTRACE_CONFIG_H_
diff --git a/include/perfetto/tracing/core/heapprofd_config.h b/include/perfetto/tracing/core/heapprofd_config.h
new file mode 100644
index 0000000..cd3244c
--- /dev/null
+++ b/include/perfetto/tracing/core/heapprofd_config.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/profiling/heapprofd_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_HEAPPROFD_CONFIG_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_HEAPPROFD_CONFIG_H_
+
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {
+class HeapprofdConfig;
+class HeapprofdConfig_ContinuousDumpConfig;
+}  // namespace protos
+}  // namespace perfetto
+
+namespace perfetto {
+
+class PERFETTO_EXPORT HeapprofdConfig {
+ public:
+  class PERFETTO_EXPORT ContinuousDumpConfig {
+   public:
+    ContinuousDumpConfig();
+    ~ContinuousDumpConfig();
+    ContinuousDumpConfig(ContinuousDumpConfig&&) noexcept;
+    ContinuousDumpConfig& operator=(ContinuousDumpConfig&&);
+    ContinuousDumpConfig(const ContinuousDumpConfig&);
+    ContinuousDumpConfig& operator=(const ContinuousDumpConfig&);
+    bool operator==(const ContinuousDumpConfig&) const;
+    bool operator!=(const ContinuousDumpConfig& other) const {
+      return !(*this == other);
+    }
+
+    // Conversion methods from/to the corresponding protobuf types.
+    void FromProto(
+        const perfetto::protos::HeapprofdConfig_ContinuousDumpConfig&);
+    void ToProto(perfetto::protos::HeapprofdConfig_ContinuousDumpConfig*) const;
+
+    uint32_t dump_phase_ms() const { return dump_phase_ms_; }
+    void set_dump_phase_ms(uint32_t value) { dump_phase_ms_ = value; }
+
+    uint32_t dump_interval_ms() const { return dump_interval_ms_; }
+    void set_dump_interval_ms(uint32_t value) { dump_interval_ms_ = value; }
+
+   private:
+    uint32_t dump_phase_ms_ = {};
+    uint32_t dump_interval_ms_ = {};
+
+    // Allows to preserve unknown protobuf fields for compatibility
+    // with future versions of .proto files.
+    std::string unknown_fields_;
+  };
+
+  HeapprofdConfig();
+  ~HeapprofdConfig();
+  HeapprofdConfig(HeapprofdConfig&&) noexcept;
+  HeapprofdConfig& operator=(HeapprofdConfig&&);
+  HeapprofdConfig(const HeapprofdConfig&);
+  HeapprofdConfig& operator=(const HeapprofdConfig&);
+  bool operator==(const HeapprofdConfig&) const;
+  bool operator!=(const HeapprofdConfig& other) const {
+    return !(*this == other);
+  }
+
+  // Conversion methods from/to the corresponding protobuf types.
+  void FromProto(const perfetto::protos::HeapprofdConfig&);
+  void ToProto(perfetto::protos::HeapprofdConfig*) const;
+
+  uint64_t sampling_interval_bytes() const { return sampling_interval_bytes_; }
+  void set_sampling_interval_bytes(uint64_t value) {
+    sampling_interval_bytes_ = value;
+  }
+
+  int process_cmdline_size() const {
+    return static_cast<int>(process_cmdline_.size());
+  }
+  const std::vector<std::string>& process_cmdline() const {
+    return process_cmdline_;
+  }
+  std::vector<std::string>* mutable_process_cmdline() {
+    return &process_cmdline_;
+  }
+  void clear_process_cmdline() { process_cmdline_.clear(); }
+  std::string* add_process_cmdline() {
+    process_cmdline_.emplace_back();
+    return &process_cmdline_.back();
+  }
+
+  int pid_size() const { return static_cast<int>(pid_.size()); }
+  const std::vector<uint64_t>& pid() const { return pid_; }
+  std::vector<uint64_t>* mutable_pid() { return &pid_; }
+  void clear_pid() { pid_.clear(); }
+  uint64_t* add_pid() {
+    pid_.emplace_back();
+    return &pid_.back();
+  }
+
+  bool all() const { return all_; }
+  void set_all(bool value) { all_ = value; }
+
+  int skip_symbol_prefix_size() const {
+    return static_cast<int>(skip_symbol_prefix_.size());
+  }
+  const std::vector<std::string>& skip_symbol_prefix() const {
+    return skip_symbol_prefix_;
+  }
+  std::vector<std::string>* mutable_skip_symbol_prefix() {
+    return &skip_symbol_prefix_;
+  }
+  void clear_skip_symbol_prefix() { skip_symbol_prefix_.clear(); }
+  std::string* add_skip_symbol_prefix() {
+    skip_symbol_prefix_.emplace_back();
+    return &skip_symbol_prefix_.back();
+  }
+
+  const ContinuousDumpConfig& continuous_dump_config() const {
+    return continuous_dump_config_;
+  }
+  ContinuousDumpConfig* mutable_continuous_dump_config() {
+    return &continuous_dump_config_;
+  }
+
+  uint64_t shmem_size_bytes() const { return shmem_size_bytes_; }
+  void set_shmem_size_bytes(uint64_t value) { shmem_size_bytes_ = value; }
+
+  bool block_client() const { return block_client_; }
+  void set_block_client(bool value) { block_client_ = value; }
+
+ private:
+  uint64_t sampling_interval_bytes_ = {};
+  std::vector<std::string> process_cmdline_;
+  std::vector<uint64_t> pid_;
+  bool all_ = {};
+  std::vector<std::string> skip_symbol_prefix_;
+  ContinuousDumpConfig continuous_dump_config_ = {};
+  uint64_t shmem_size_bytes_ = {};
+  bool block_client_ = {};
+
+  // Allows to preserve unknown protobuf fields for compatibility
+  // with future versions of .proto files.
+  std::string unknown_fields_;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_HEAPPROFD_CONFIG_H_
diff --git a/include/perfetto/tracing/core/inode_file_config.h b/include/perfetto/tracing/core/inode_file_config.h
new file mode 100644
index 0000000..ea93568
--- /dev/null
+++ b/include/perfetto/tracing/core/inode_file_config.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/inode_file/inode_file_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_INODE_FILE_CONFIG_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_INODE_FILE_CONFIG_H_
+
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {
+class InodeFileConfig;
+class InodeFileConfig_MountPointMappingEntry;
+}  // namespace protos
+}  // namespace perfetto
+
+namespace perfetto {
+
+class PERFETTO_EXPORT InodeFileConfig {
+ public:
+  class PERFETTO_EXPORT MountPointMappingEntry {
+   public:
+    MountPointMappingEntry();
+    ~MountPointMappingEntry();
+    MountPointMappingEntry(MountPointMappingEntry&&) noexcept;
+    MountPointMappingEntry& operator=(MountPointMappingEntry&&);
+    MountPointMappingEntry(const MountPointMappingEntry&);
+    MountPointMappingEntry& operator=(const MountPointMappingEntry&);
+    bool operator==(const MountPointMappingEntry&) const;
+    bool operator!=(const MountPointMappingEntry& other) const {
+      return !(*this == other);
+    }
+
+    // Conversion methods from/to the corresponding protobuf types.
+    void FromProto(
+        const perfetto::protos::InodeFileConfig_MountPointMappingEntry&);
+    void ToProto(
+        perfetto::protos::InodeFileConfig_MountPointMappingEntry*) const;
+
+    const std::string& mountpoint() const { return mountpoint_; }
+    void set_mountpoint(const std::string& value) { mountpoint_ = value; }
+
+    int scan_roots_size() const { return static_cast<int>(scan_roots_.size()); }
+    const std::vector<std::string>& scan_roots() const { return scan_roots_; }
+    std::vector<std::string>* mutable_scan_roots() { return &scan_roots_; }
+    void clear_scan_roots() { scan_roots_.clear(); }
+    std::string* add_scan_roots() {
+      scan_roots_.emplace_back();
+      return &scan_roots_.back();
+    }
+
+   private:
+    std::string mountpoint_ = {};
+    std::vector<std::string> scan_roots_;
+
+    // Allows to preserve unknown protobuf fields for compatibility
+    // with future versions of .proto files.
+    std::string unknown_fields_;
+  };
+
+  InodeFileConfig();
+  ~InodeFileConfig();
+  InodeFileConfig(InodeFileConfig&&) noexcept;
+  InodeFileConfig& operator=(InodeFileConfig&&);
+  InodeFileConfig(const InodeFileConfig&);
+  InodeFileConfig& operator=(const InodeFileConfig&);
+  bool operator==(const InodeFileConfig&) const;
+  bool operator!=(const InodeFileConfig& other) const {
+    return !(*this == other);
+  }
+
+  // Conversion methods from/to the corresponding protobuf types.
+  void FromProto(const perfetto::protos::InodeFileConfig&);
+  void ToProto(perfetto::protos::InodeFileConfig*) const;
+
+  uint32_t scan_interval_ms() const { return scan_interval_ms_; }
+  void set_scan_interval_ms(uint32_t value) { scan_interval_ms_ = value; }
+
+  uint32_t scan_delay_ms() const { return scan_delay_ms_; }
+  void set_scan_delay_ms(uint32_t value) { scan_delay_ms_ = value; }
+
+  uint32_t scan_batch_size() const { return scan_batch_size_; }
+  void set_scan_batch_size(uint32_t value) { scan_batch_size_ = value; }
+
+  bool do_not_scan() const { return do_not_scan_; }
+  void set_do_not_scan(bool value) { do_not_scan_ = value; }
+
+  int scan_mount_points_size() const {
+    return static_cast<int>(scan_mount_points_.size());
+  }
+  const std::vector<std::string>& scan_mount_points() const {
+    return scan_mount_points_;
+  }
+  std::vector<std::string>* mutable_scan_mount_points() {
+    return &scan_mount_points_;
+  }
+  void clear_scan_mount_points() { scan_mount_points_.clear(); }
+  std::string* add_scan_mount_points() {
+    scan_mount_points_.emplace_back();
+    return &scan_mount_points_.back();
+  }
+
+  int mount_point_mapping_size() const {
+    return static_cast<int>(mount_point_mapping_.size());
+  }
+  const std::vector<MountPointMappingEntry>& mount_point_mapping() const {
+    return mount_point_mapping_;
+  }
+  std::vector<MountPointMappingEntry>* mutable_mount_point_mapping() {
+    return &mount_point_mapping_;
+  }
+  void clear_mount_point_mapping() { mount_point_mapping_.clear(); }
+  MountPointMappingEntry* add_mount_point_mapping() {
+    mount_point_mapping_.emplace_back();
+    return &mount_point_mapping_.back();
+  }
+
+ private:
+  uint32_t scan_interval_ms_ = {};
+  uint32_t scan_delay_ms_ = {};
+  uint32_t scan_batch_size_ = {};
+  bool do_not_scan_ = {};
+  std::vector<std::string> scan_mount_points_;
+  std::vector<MountPointMappingEntry> mount_point_mapping_;
+
+  // Allows to preserve unknown protobuf fields for compatibility
+  // with future versions of .proto files.
+  std::string unknown_fields_;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_INODE_FILE_CONFIG_H_
diff --git a/include/perfetto/tracing/core/observable_events.h b/include/perfetto/tracing/core/observable_events.h
new file mode 100644
index 0000000..0429411
--- /dev/null
+++ b/include/perfetto/tracing/core/observable_events.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/common/observable_events.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_OBSERVABLE_EVENTS_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_OBSERVABLE_EVENTS_H_
+
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {
+class ObservableEvents;
+class ObservableEvents_DataSourceInstanceStateChange;
+}  // namespace protos
+}  // namespace perfetto
+
+namespace perfetto {
+
+class PERFETTO_EXPORT ObservableEvents {
+ public:
+  class PERFETTO_EXPORT DataSourceInstanceStateChange {
+   public:
+    enum DataSourceInstanceState {
+      DATA_SOURCE_INSTANCE_STATE_STOPPED = 1,
+      DATA_SOURCE_INSTANCE_STATE_STARTED = 2,
+    };
+    DataSourceInstanceStateChange();
+    ~DataSourceInstanceStateChange();
+    DataSourceInstanceStateChange(DataSourceInstanceStateChange&&) noexcept;
+    DataSourceInstanceStateChange& operator=(DataSourceInstanceStateChange&&);
+    DataSourceInstanceStateChange(const DataSourceInstanceStateChange&);
+    DataSourceInstanceStateChange& operator=(
+        const DataSourceInstanceStateChange&);
+    bool operator==(const DataSourceInstanceStateChange&) const;
+    bool operator!=(const DataSourceInstanceStateChange& other) const {
+      return !(*this == other);
+    }
+
+    // Conversion methods from/to the corresponding protobuf types.
+    void FromProto(const perfetto::protos::
+                       ObservableEvents_DataSourceInstanceStateChange&);
+    void ToProto(
+        perfetto::protos::ObservableEvents_DataSourceInstanceStateChange*)
+        const;
+
+    const std::string& producer_name() const { return producer_name_; }
+    void set_producer_name(const std::string& value) { producer_name_ = value; }
+
+    const std::string& data_source_name() const { return data_source_name_; }
+    void set_data_source_name(const std::string& value) {
+      data_source_name_ = value;
+    }
+
+    DataSourceInstanceState state() const { return state_; }
+    void set_state(DataSourceInstanceState value) { state_ = value; }
+
+   private:
+    std::string producer_name_ = {};
+    std::string data_source_name_ = {};
+    DataSourceInstanceState state_ = {};
+
+    // Allows to preserve unknown protobuf fields for compatibility
+    // with future versions of .proto files.
+    std::string unknown_fields_;
+  };
+
+  ObservableEvents();
+  ~ObservableEvents();
+  ObservableEvents(ObservableEvents&&) noexcept;
+  ObservableEvents& operator=(ObservableEvents&&);
+  ObservableEvents(const ObservableEvents&);
+  ObservableEvents& operator=(const ObservableEvents&);
+  bool operator==(const ObservableEvents&) const;
+  bool operator!=(const ObservableEvents& other) const {
+    return !(*this == other);
+  }
+
+  // Conversion methods from/to the corresponding protobuf types.
+  void FromProto(const perfetto::protos::ObservableEvents&);
+  void ToProto(perfetto::protos::ObservableEvents*) const;
+
+  int instance_state_changes_size() const {
+    return static_cast<int>(instance_state_changes_.size());
+  }
+  const std::vector<DataSourceInstanceStateChange>& instance_state_changes()
+      const {
+    return instance_state_changes_;
+  }
+  std::vector<DataSourceInstanceStateChange>* mutable_instance_state_changes() {
+    return &instance_state_changes_;
+  }
+  void clear_instance_state_changes() { instance_state_changes_.clear(); }
+  DataSourceInstanceStateChange* add_instance_state_changes() {
+    instance_state_changes_.emplace_back();
+    return &instance_state_changes_.back();
+  }
+
+ private:
+  std::vector<DataSourceInstanceStateChange> instance_state_changes_;
+
+  // Allows to preserve unknown protobuf fields for compatibility
+  // with future versions of .proto files.
+  std::string unknown_fields_;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_OBSERVABLE_EVENTS_H_
diff --git a/include/perfetto/tracing/core/packages_list_config.h b/include/perfetto/tracing/core/packages_list_config.h
new file mode 100644
index 0000000..5df87d4
--- /dev/null
+++ b/include/perfetto/tracing/core/packages_list_config.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/android/packages_list_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_PACKAGES_LIST_CONFIG_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_PACKAGES_LIST_CONFIG_H_
+
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {
+class PackagesListConfig;
+}
+}  // namespace perfetto
+
+namespace perfetto {
+
+class PERFETTO_EXPORT PackagesListConfig {
+ public:
+  PackagesListConfig();
+  ~PackagesListConfig();
+  PackagesListConfig(PackagesListConfig&&) noexcept;
+  PackagesListConfig& operator=(PackagesListConfig&&);
+  PackagesListConfig(const PackagesListConfig&);
+  PackagesListConfig& operator=(const PackagesListConfig&);
+  bool operator==(const PackagesListConfig&) const;
+  bool operator!=(const PackagesListConfig& other) const {
+    return !(*this == other);
+  }
+
+  // Conversion methods from/to the corresponding protobuf types.
+  void FromProto(const perfetto::protos::PackagesListConfig&);
+  void ToProto(perfetto::protos::PackagesListConfig*) const;
+
+  int package_name_filter_size() const {
+    return static_cast<int>(package_name_filter_.size());
+  }
+  const std::vector<std::string>& package_name_filter() const {
+    return package_name_filter_;
+  }
+  std::vector<std::string>* mutable_package_name_filter() {
+    return &package_name_filter_;
+  }
+  void clear_package_name_filter() { package_name_filter_.clear(); }
+  std::string* add_package_name_filter() {
+    package_name_filter_.emplace_back();
+    return &package_name_filter_.back();
+  }
+
+ private:
+  std::vector<std::string> package_name_filter_;
+
+  // Allows to preserve unknown protobuf fields for compatibility
+  // with future versions of .proto files.
+  std::string unknown_fields_;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_PACKAGES_LIST_CONFIG_H_
diff --git a/include/perfetto/tracing/core/process_stats_config.h b/include/perfetto/tracing/core/process_stats_config.h
new file mode 100644
index 0000000..d31540a
--- /dev/null
+++ b/include/perfetto/tracing/core/process_stats_config.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/process_stats/process_stats_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_PROCESS_STATS_CONFIG_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_PROCESS_STATS_CONFIG_H_
+
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {
+class ProcessStatsConfig;
+}
+}  // namespace perfetto
+
+namespace perfetto {
+
+class PERFETTO_EXPORT ProcessStatsConfig {
+ public:
+  enum Quirks {
+    QUIRKS_UNSPECIFIED = 0,
+    DISABLE_INITIAL_DUMP = 1,
+    DISABLE_ON_DEMAND = 2,
+  };
+  ProcessStatsConfig();
+  ~ProcessStatsConfig();
+  ProcessStatsConfig(ProcessStatsConfig&&) noexcept;
+  ProcessStatsConfig& operator=(ProcessStatsConfig&&);
+  ProcessStatsConfig(const ProcessStatsConfig&);
+  ProcessStatsConfig& operator=(const ProcessStatsConfig&);
+  bool operator==(const ProcessStatsConfig&) const;
+  bool operator!=(const ProcessStatsConfig& other) const {
+    return !(*this == other);
+  }
+
+  // Conversion methods from/to the corresponding protobuf types.
+  void FromProto(const perfetto::protos::ProcessStatsConfig&);
+  void ToProto(perfetto::protos::ProcessStatsConfig*) const;
+
+  int quirks_size() const { return static_cast<int>(quirks_.size()); }
+  const std::vector<Quirks>& quirks() const { return quirks_; }
+  std::vector<Quirks>* mutable_quirks() { return &quirks_; }
+  void clear_quirks() { quirks_.clear(); }
+  Quirks* add_quirks() {
+    quirks_.emplace_back();
+    return &quirks_.back();
+  }
+
+  bool scan_all_processes_on_start() const {
+    return scan_all_processes_on_start_;
+  }
+  void set_scan_all_processes_on_start(bool value) {
+    scan_all_processes_on_start_ = value;
+  }
+
+  bool record_thread_names() const { return record_thread_names_; }
+  void set_record_thread_names(bool value) { record_thread_names_ = value; }
+
+  uint32_t proc_stats_poll_ms() const { return proc_stats_poll_ms_; }
+  void set_proc_stats_poll_ms(uint32_t value) { proc_stats_poll_ms_ = value; }
+
+  uint32_t proc_stats_cache_ttl_ms() const { return proc_stats_cache_ttl_ms_; }
+  void set_proc_stats_cache_ttl_ms(uint32_t value) {
+    proc_stats_cache_ttl_ms_ = value;
+  }
+
+ private:
+  std::vector<Quirks> quirks_;
+  bool scan_all_processes_on_start_ = {};
+  bool record_thread_names_ = {};
+  uint32_t proc_stats_poll_ms_ = {};
+  uint32_t proc_stats_cache_ttl_ms_ = {};
+
+  // Allows to preserve unknown protobuf fields for compatibility
+  // with future versions of .proto files.
+  std::string unknown_fields_;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_PROCESS_STATS_CONFIG_H_
diff --git a/include/perfetto/tracing/core/producer.h b/include/perfetto/tracing/core/producer.h
new file mode 100644
index 0000000..f383b7e
--- /dev/null
+++ b/include/perfetto/tracing/core/producer.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_TRACING_CORE_PRODUCER_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_PRODUCER_H_
+
+#include "perfetto/base/export.h"
+#include "perfetto/tracing/core/basic_types.h"
+
+namespace perfetto {
+
+class DataSourceConfig;
+class SharedMemory;
+
+// A Producer is an entity that connects to the write-only port of the Service
+// and exposes the ability to produce performance data on-demand. The lifecycle
+// of a Producer is as follows:
+// 1. The producer connects to the service and advertises its data sources
+//    (e.g., the ability to get kernel ftraces, to list process stats).
+// 2. The service acknowledges the connection and sends over the SharedMemory
+//    region that will be used to exchange data (together with the signalling
+//    API TracingService::ProducerEndpoint::OnPageAcquired()/OnPageReleased()).
+// 3. At some point later on, the Service asks the Producer to turn on some of
+//    the previously registered data sources, together with some configuration
+//    parameters. This happens via the StartDataSource() callback.
+// 4. In response to that the Producer will spawn an instance of the given data
+//    source and inject its data into the shared memory buffer (obtained during
+//    OnConnect).
+// This interface is subclassed by:
+//  1. The actual producer code in the clients e.g., the ftrace reader process.
+//  2. The transport layer when interposing RPC between service and producers.
+class PERFETTO_EXPORT Producer {
+ public:
+  virtual ~Producer();
+
+  // Called by Service (or more typically by the transport layer, on behalf of
+  // the remote Service), once the Producer <> Service connection has been
+  // established.
+  virtual void OnConnect() = 0;
+
+  // Called by the Service or by the transport layer if the connection with the
+  // service drops, either voluntarily (e.g., by destroying the ProducerEndpoint
+  // obtained through Service::ConnectProducer()) or involuntarily (e.g., if the
+  // Service process crashes).
+  // The Producer is expected to tear down all its data sources if this happens.
+  // Once this call returns it is possible to safely destroy the Producer
+  // instance.
+  virtual void OnDisconnect() = 0;
+
+  // Called by the Service after OnConnect but before the first DataSource is
+  // created. Can be used for any setup required before tracing begins.
+  virtual void OnTracingSetup() = 0;
+
+  // The lifecycle methods below are always called in the following sequence:
+  // SetupDataSource  -> StartDataSource -> StopDataSource.
+  // Or, in the edge case where a trace is aborted immediately:
+  // SetupDataSource  -> StopDataSource.
+  // The Setup+Start call sequence is always guaranateed, regardless of the
+  // TraceConfig.deferred_start flags.
+  // Called by the Service to configure one of the data sources previously
+  // registered through TracingService::ProducerEndpoint::RegisterDataSource().
+  // This method is always called before StartDataSource. There is always a
+  // SetupDataSource() call before each StartDataSource() call.
+  // Args:
+  // - DataSourceInstanceID is an identifier chosen by the Service that should
+  //   be assigned to the newly created data source instance. It is used to
+  //   match the StopDataSource() request below.
+  // - DataSourceConfig is the configuration for the new data source (e.g.,
+  //   tells which trace categories to enable).
+  virtual void SetupDataSource(DataSourceInstanceID,
+                               const DataSourceConfig&) = 0;
+
+  // Called by the Service to turn on one of the data sources previously
+  // registered through TracingService::ProducerEndpoint::RegisterDataSource()
+  // and initialized through SetupDataSource().
+  // Both arguments are guaranteed to be identical to the ones passed to the
+  // prior SetupDataSource() call.
+  virtual void StartDataSource(DataSourceInstanceID,
+                               const DataSourceConfig&) = 0;
+
+  // Called by the Service to shut down an existing data source instance.
+  virtual void StopDataSource(DataSourceInstanceID) = 0;
+
+  // Called by the service to request the Producer to commit the data of the
+  // given data sources and return their chunks into the shared memory buffer.
+  // The Producer is expected to invoke NotifyFlushComplete(FlushRequestID) on
+  // the Service after the data has been committed. The producer has to either
+  // reply to the flush requests in order, or can just reply to the latest one
+  // Upon seeing a NotifyFlushComplete(N), the service will assume that all
+  // flushes < N have also been committed.
+  virtual void Flush(FlushRequestID,
+                     const DataSourceInstanceID* data_source_ids,
+                     size_t num_data_sources) = 0;
+
+  // Called by the service to instruct the given data sources to stop referring
+  // to any trace contents emitted so far. The intent is that after processing
+  // this call, the rest of the trace should be parsable even if all of the
+  // packets emitted so far have been lost (for example due to ring buffer
+  // overwrites).
+  //
+  // Called only for Producers with active data sources that have opted in by
+  // setting |handles_incremental_state_clear| in their DataSourceDescriptor.
+  //
+  // The way this call is handled is up to the individual Producer
+  // implementation. Some might wish to emit invalidation markers in the trace
+  // (see TracePacket.incremental_state_cleared for an existing field), and
+  // handle them when parsing the trace.
+  virtual void ClearIncrementalState(
+      const DataSourceInstanceID* data_source_ids,
+      size_t num_data_sources) = 0;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_PRODUCER_H_
diff --git a/include/perfetto/tracing/core/shared_memory.h b/include/perfetto/tracing/core/shared_memory.h
new file mode 100644
index 0000000..b2ca791
--- /dev/null
+++ b/include/perfetto/tracing/core/shared_memory.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_TRACING_CORE_SHARED_MEMORY_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_SHARED_MEMORY_H_
+
+#include <stddef.h>
+
+#include <memory>
+
+#include "perfetto/base/export.h"
+
+namespace perfetto {
+
+// An abstract interface that models the shared memory region shared between
+// Service and Producer. The concrete implementation of this is up to the
+// transport layer. This can be as simple as a malloc()-ed buffer, if both
+// Producer and Service are hosted in the same process, or some posix shared
+// memory for the out-of-process case (see src/unix_rpc).
+// Both this class and the Factory are subclassed by the transport layer, which
+// will attach platform specific fields to it (e.g., a unix file descriptor).
+class PERFETTO_EXPORT SharedMemory {
+ public:
+  class PERFETTO_EXPORT Factory {
+   public:
+    virtual ~Factory();
+    virtual std::unique_ptr<SharedMemory> CreateSharedMemory(size_t) = 0;
+  };
+
+  // The transport layer is expected to tear down the resource associated to
+  // this object region when destroyed.
+  virtual ~SharedMemory();
+
+  virtual void* start() const = 0;
+  virtual size_t size() const = 0;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_SHARED_MEMORY_H_
diff --git a/include/perfetto/tracing/core/shared_memory_abi.h b/include/perfetto/tracing/core/shared_memory_abi.h
new file mode 100644
index 0000000..7a5a14c
--- /dev/null
+++ b/include/perfetto/tracing/core/shared_memory_abi.h
@@ -0,0 +1,581 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_TRACING_CORE_SHARED_MEMORY_ABI_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_SHARED_MEMORY_ABI_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <array>
+#include <atomic>
+#include <bitset>
+#include <thread>
+#include <type_traits>
+#include <utility>
+
+#include "perfetto/base/logging.h"
+
+namespace perfetto {
+
+// This file defines the binary interface of the memory buffers shared between
+// Producer and Service. This is a long-term stable ABI and has to be backwards
+// compatible to deal with mismatching Producer and Service versions.
+//
+// Overview
+// --------
+// SMB := "Shared Memory Buffer".
+// In the most typical case of a multi-process architecture (i.e. Producer and
+// Service are hosted by different processes), a Producer means almost always
+// a "client process producing data" (almost: in some cases a process might host
+// > 1 Producer, if it links two libraries, independent of each other, that both
+// use Perfetto tracing).
+// The Service has one SMB for each Producer.
+// A producer has one or (typically) more data sources. They all share the same
+// SMB.
+// The SMB is a staging area to decouple data sources living in the Producer
+// and allow them to do non-blocking async writes.
+// The SMB is *not* the ultimate logging buffer seen by the Consumer. That one
+// is larger (~MBs) and not shared with Producers.
+// Each SMB is small, typically few KB. Its size is configurable by the producer
+// within a max limit of ~MB (see kMaxShmSize in tracing_service_impl.cc).
+// The SMB is partitioned into fixed-size Page(s). The size of the Pages are
+// determined by each Producer at connection time and cannot be changed.
+// Hence, different producers can have SMB(s) that have a different Page size
+// from each other, but the page size will be constant throughout all the
+// lifetime of the SMB.
+// Page(s) are partitioned by the Producer into variable size Chunk(s):
+//
+// +------------+      +--------------------------+
+// | Producer 1 |  <-> |      SMB 1 [~32K - 1MB]  |
+// +------------+      +--------+--------+--------+
+//                     |  Page  |  Page  |  Page  |
+//                     +--------+--------+--------+
+//                     | Chunk  |        | Chunk  |
+//                     +--------+  Chunk +--------+ <----+
+//                     | Chunk  |        | Chunk  |      |
+//                     +--------+--------+--------+      +---------------------+
+//                                                       |       Service       |
+// +------------+      +--------------------------+      +---------------------+
+// | Producer 2 |  <-> |      SMB 2 [~32K - 1MB]  |     /| large ring buffers  |
+// +------------+      +--------+--------+--------+ <--+ | (100K - several MB) |
+//                     |  Page  |  Page  |  Page  |      +---------------------+
+//                     +--------+--------+--------+
+//                     | Chunk  |        | Chunk  |
+//                     +--------+  Chunk +--------+
+//                     | Chunk  |        | Chunk  |
+//                     +--------+--------+--------+
+//
+// * Sizes of both SMB and ring buffers are purely indicative and decided at
+// configuration time by the Producer (for SMB sizes) and the Consumer (for the
+// final ring buffer size).
+
+// Page
+// ----
+// A page is a portion of the shared memory buffer and defines the granularity
+// of the interaction between the Producer and tracing Service. When scanning
+// the shared memory buffer to determine if something should be moved to the
+// central logging buffers, the Service most of the times looks at and moves
+// whole pages. Similarly, the Producer sends an IPC to invite the Service to
+// drain the shared memory buffer only when a whole page is filled.
+// Having fixed the total SMB size (hence the total memory overhead), the page
+// size is a triangular tradeoff between:
+// 1) IPC traffic: smaller pages -> more IPCs.
+// 2) Producer lock freedom: larger pages -> larger chunks -> data sources can
+//    write more data without needing to swap chunks and synchronize.
+// 3) Risk of write-starving the SMB: larger pages -> higher chance that the
+//    Service won't manage to drain them and the SMB remains full.
+// The page size, on the other side, has no implications on wasted memory due to
+// fragmentations (see Chunk below).
+// The size of the page is chosen by the Service at connection time and stays
+// fixed throughout all the lifetime of the Producer. Different producers (i.e.
+// ~ different client processes) can use different page sizes.
+// The page size must be an integer multiple of 4k (this is to allow VM page
+// stealing optimizations) and obviously has to be an integer divisor of the
+// total SMB size.
+
+// Chunk
+// -----
+// A chunk is a portion of a Page which is written and handled by a Producer.
+// A chunk contains a linear sequence of TracePacket(s) (the root proto).
+// A chunk cannot be written concurrently by two data sources. Protobufs must be
+// encoded as contiguous byte streams and cannot be interleaved. Therefore, on
+// the Producer side, a chunk is almost always owned exclusively by one thread
+// (% extremely peculiar slow-path cases).
+// Chunks are essentially single-writer single-thread lock-free arenas. Locking
+// happens only when a Chunk is full and a new one needs to be acquired.
+// Locking happens only within the scope of a Producer process. There is no
+// inter-process locking. The Producer cannot lock the Service and viceversa.
+// In the worst case, any of the two can starve the SMB, by marking all chunks
+// as either being read or written. But that has the only side effect of
+// losing the trace data.
+// The Producer can decide to partition each page into a number of limited
+// configurations (e.g., 1 page == 1 chunk, 1 page == 2 chunks and so on).
+
+// TracePacket
+// -----------
+// Is the atom of tracing. Putting aside pages and chunks a trace is merely a
+// sequence of TracePacket(s). TracePacket is the root protobuf message.
+// A TracePacket can span across several chunks (hence even across several
+// pages). A TracePacket can therefore be >> chunk size, >> page size and even
+// >> SMB size. The Chunk header carries metadata to deal with the TracePacket
+// splitting case.
+
+// Use only explicitly-sized types below. DO NOT use size_t or any architecture
+// dependent size (e.g. size_t) in the struct fields. This buffer will be read
+// and written by processes that have a different bitness in the same OS.
+// Instead it's fine to assume little-endianess. Big-endian is a dream we are
+// not currently pursuing.
+
+class SharedMemoryABI {
+ public:
+  // This is due to Chunk::size being 16 bits.
+  static constexpr size_t kMaxPageSize = 64 * 1024;
+
+  // "14" is the max number that can be encoded in a 32 bit atomic word using
+  // 2 state bits per Chunk and leaving 4 bits for the page layout.
+  // See PageLayout below.
+  static constexpr size_t kMaxChunksPerPage = 14;
+
+  // Each TracePacket in the Chunk is prefixed by a 4 bytes redundant VarInt
+  // (see proto_utils.h) stating its size.
+  static constexpr size_t kPacketHeaderSize = 4;
+
+  // Chunk states and transitions:
+  //    kChunkFree  <----------------+
+  //         |  (Producer)           |
+  //         V                       |
+  //  kChunkBeingWritten             |
+  //         |  (Producer)           |
+  //         V                       |
+  //  kChunkComplete                 |
+  //         |  (Service)            |
+  //         V                       |
+  //  kChunkBeingRead                |
+  //        |   (Service)            |
+  //        +------------------------+
+  enum ChunkState : uint32_t {
+    // The Chunk is free. The Service shall never touch it, the Producer can
+    // acquire it and transition it into kChunkBeingWritten.
+    kChunkFree = 0,
+
+    // The Chunk is being used by the Producer and is not complete yet.
+    // The Service shall never touch kChunkBeingWritten pages.
+    kChunkBeingWritten = 1,
+
+    // The Service is moving the page into its non-shared ring buffer. The
+    // Producer shall never touch kChunkBeingRead pages.
+    kChunkBeingRead = 2,
+
+    // The Producer is done writing the page and won't touch it again. The
+    // Service can now move it to its non-shared ring buffer.
+    // kAllChunksComplete relies on this being == 3.
+    kChunkComplete = 3,
+  };
+  static constexpr const char* kChunkStateStr[] = {"Free", "BeingWritten",
+                                                   "BeingRead", "Complete"};
+
+  enum PageLayout : uint32_t {
+    // The page is fully free and has not been partitioned yet.
+    kPageNotPartitioned = 0,
+
+    // TODO(primiano): Aligning a chunk @ 16 bytes could allow to use faster
+    // intrinsics based on quad-word moves. Do the math and check what is the
+    // fragmentation loss.
+
+    // align4(X) := the largest integer N s.t. (N % 4) == 0 && N <= X.
+    // 8 == sizeof(PageHeader).
+    kPageDiv1 = 1,   // Only one chunk of size: PAGE_SIZE - 8.
+    kPageDiv2 = 2,   // Two chunks of size: align4((PAGE_SIZE - 8) / 2).
+    kPageDiv4 = 3,   // Four chunks of size: align4((PAGE_SIZE - 8) / 4).
+    kPageDiv7 = 4,   // Seven chunks of size: align4((PAGE_SIZE - 8) / 7).
+    kPageDiv14 = 5,  // Fourteen chunks of size: align4((PAGE_SIZE - 8) / 14).
+
+    // The rationale for 7 and 14 above is to maximize the page usage for the
+    // likely case of |page_size| == 4096:
+    // (((4096 - 8) / 14) % 4) == 0, while (((4096 - 8) / 16 % 4)) == 3. So
+    // Div16 would waste 3 * 16 = 48 bytes per page for chunk alignment gaps.
+
+    kPageDivReserved1 = 6,
+    kPageDivReserved2 = 7,
+    kNumPageLayouts = 8,
+  };
+
+  // Keep this consistent with the PageLayout enum above.
+  static constexpr uint32_t kNumChunksForLayout[] = {0, 1, 2, 4, 7, 14, 0, 0};
+
+  // Layout of a Page.
+  // +===================================================+
+  // | Page header [8 bytes]                             |
+  // | Tells how many chunks there are, how big they are |
+  // | and their state (free, read, write, complete).    |
+  // +===================================================+
+  // +***************************************************+
+  // | Chunk #0 header [8 bytes]                         |
+  // | Tells how many packets there are and whether the  |
+  // | whether the 1st and last ones are fragmented.     |
+  // | Also has a chunk id to reassemble fragments.    |
+  // +***************************************************+
+  // +---------------------------------------------------+
+  // | Packet #0 size [varint, up to 4 bytes]            |
+  // + - - - - - - - - - - - - - - - - - - - - - - - - - +
+  // | Packet #0 payload                                 |
+  // | A TracePacket protobuf message                    |
+  // +---------------------------------------------------+
+  //                         ...
+  // + . . . . . . . . . . . . . . . . . . . . . . . . . +
+  // |      Optional padding to maintain aligment        |
+  // + . . . . . . . . . . . . . . . . . . . . . . . . . +
+  // +---------------------------------------------------+
+  // | Packet #N size [varint, up to 4 bytes]            |
+  // + - - - - - - - - - - - - - - - - - - - - - - - - - +
+  // | Packet #N payload                                 |
+  // | A TracePacket protobuf message                    |
+  // +---------------------------------------------------+
+  //                         ...
+  // +***************************************************+
+  // | Chunk #M header [8 bytes]                         |
+  //                         ...
+
+  // Alignment applies to start offset only. The Chunk size is *not* aligned.
+  static constexpr uint32_t kChunkAlignment = 4;
+  static constexpr uint32_t kChunkShift = 2;
+  static constexpr uint32_t kChunkMask = 0x3;
+  static constexpr uint32_t kLayoutMask = 0x70000000;
+  static constexpr uint32_t kLayoutShift = 28;
+  static constexpr uint32_t kAllChunksMask = 0x0FFFFFFF;
+
+  // This assumes that kChunkComplete == 3.
+  static constexpr uint32_t kAllChunksComplete = 0x0FFFFFFF;
+  static constexpr uint32_t kAllChunksFree = 0;
+  static constexpr size_t kInvalidPageIdx = static_cast<size_t>(-1);
+
+  // There is one page header per page, at the beginning of the page.
+  struct PageHeader {
+    // |layout| bits:
+    // [31] [30:28] [27:26] ... [1:0]
+    //  |      |       |     |    |
+    //  |      |       |     |    +---------- ChunkState[0]
+    //  |      |       |     +--------------- ChunkState[12..1]
+    //  |      |       +--------------------- ChunkState[13]
+    //  |      +----------------------------- PageLayout (0 == page fully free)
+    //  +------------------------------------ Reserved for future use
+    std::atomic<uint32_t> layout;
+
+    // If we'll ever going to use this in the future it might come handy
+    // reviving the kPageBeingPartitioned logic (look in git log, it was there
+    // at some point in the past).
+    uint32_t reserved;
+  };
+
+  // There is one Chunk header per chunk (hence PageLayout per page) at the
+  // beginning of each chunk.
+  struct ChunkHeader {
+    enum Flags : uint8_t {
+      // If set, the first TracePacket in the chunk is partial and continues
+      // from |chunk_id| - 1 (within the same |writer_id|).
+      kFirstPacketContinuesFromPrevChunk = 1 << 0,
+
+      // If set, the last TracePacket in the chunk is partial and continues on
+      // |chunk_id| + 1 (within the same |writer_id|).
+      kLastPacketContinuesOnNextChunk = 1 << 1,
+
+      // If set, the last (fragmented) TracePacket in the chunk has holes (even
+      // if the chunk is marked as kChunkComplete) that need to be patched
+      // out-of-band before the chunk can be read.
+      kChunkNeedsPatching = 1 << 2,
+    };
+
+    struct Packets {
+      // Number of valid TracePacket protobuf messages contained in the chunk.
+      // Each TracePacket is prefixed by its own size. This field is
+      // monotonically updated by the Producer with release store semantic when
+      // the packet at position |count| is started. This last packet may not be
+      // considered complete until |count| is incremented for the subsequent
+      // packet or the chunk is completed.
+      uint16_t count : 10;
+      static constexpr size_t kMaxCount = (1 << 10) - 1;
+
+      // See Flags above.
+      uint16_t flags : 6;
+    };
+
+    // A monotonic counter of the chunk within the scoped of a |writer_id|.
+    // The tuple (ProducerID, WriterID, ChunkID) allows to figure out if two
+    // chunks are contiguous (and hence a trace packets spanning across them can
+    // be glued) or we had some holes due to the ring buffer wrapping.
+    // This is set only when transitioning from kChunkFree to kChunkBeingWritten
+    // and remains unchanged throughout the remaining lifetime of the chunk.
+    std::atomic<uint32_t> chunk_id;
+
+    // ID of the writer, unique within the producer.
+    // Like |chunk_id|, this is set only when transitioning from kChunkFree to
+    // kChunkBeingWritten.
+    std::atomic<uint16_t> writer_id;
+
+    // There is no ProducerID here. The service figures that out from the IPC
+    // channel, which is unspoofable.
+
+    // Updated with release-store semantics.
+    std::atomic<Packets> packets;
+  };
+
+  class Chunk {
+   public:
+    Chunk();  // Constructs an invalid chunk.
+
+    // Chunk is move-only, to document the scope of the Acquire/Release
+    // TryLock operations below.
+    Chunk(const Chunk&) = delete;
+    Chunk operator=(const Chunk&) = delete;
+    Chunk(Chunk&&) noexcept;
+    Chunk& operator=(Chunk&&);
+
+    uint8_t* begin() const { return begin_; }
+    uint8_t* end() const { return begin_ + size_; }
+
+    // Size, including Chunk header.
+    size_t size() const { return size_; }
+
+    // Begin of the first packet (or packet fragment).
+    uint8_t* payload_begin() const { return begin_ + sizeof(ChunkHeader); }
+    size_t payload_size() const {
+      PERFETTO_DCHECK(size_ >= sizeof(ChunkHeader));
+      return size_ - sizeof(ChunkHeader);
+    }
+
+    bool is_valid() const { return begin_ && size_; }
+
+    // Index of the chunk within the page [0..13] (13 comes from kPageDiv14).
+    uint8_t chunk_idx() const { return chunk_idx_; }
+
+    ChunkHeader* header() { return reinterpret_cast<ChunkHeader*>(begin_); }
+
+    uint16_t writer_id() {
+      return header()->writer_id.load(std::memory_order_relaxed);
+    }
+
+    // Returns the count of packets and the flags with acquire-load semantics.
+    std::pair<uint16_t, uint8_t> GetPacketCountAndFlags() {
+      auto packets = header()->packets.load(std::memory_order_acquire);
+      const uint16_t packets_count = packets.count;
+      const uint8_t packets_flags = packets.flags;
+      return std::make_pair(packets_count, packets_flags);
+    }
+
+    // Increases |packets.count| with release semantics (note, however, that the
+    // packet count is incremented *before* starting writing a packet). Returns
+    // the new packet count. The increment is atomic but NOT race-free (i.e. no
+    // CAS). Only the Producer is supposed to perform this increment, and it's
+    // supposed to do that in a thread-safe way (holding a lock). A Chunk cannot
+    // be shared by multiple Producer threads without locking. The packet count
+    // is cleared by TryAcquireChunk(), when passing the new header for the
+    // chunk.
+    uint16_t IncrementPacketCount() {
+      ChunkHeader* chunk_header = header();
+      auto packets = chunk_header->packets.load(std::memory_order_relaxed);
+      packets.count++;
+      chunk_header->packets.store(packets, std::memory_order_release);
+      return packets.count;
+    }
+
+    // Increases |packets.count| to the given |packet_count|, but only if
+    // |packet_count| is larger than the current value of |packets.count|.
+    // Returns the new packet count. Same atomicity guarantees as
+    // IncrementPacketCount().
+    uint16_t IncreasePacketCountTo(uint16_t packet_count) {
+      ChunkHeader* chunk_header = header();
+      auto packets = chunk_header->packets.load(std::memory_order_relaxed);
+      if (packets.count < packet_count)
+        packets.count = packet_count;
+      chunk_header->packets.store(packets, std::memory_order_release);
+      return packets.count;
+    }
+
+    // Flags are cleared by TryAcquireChunk(), by passing the new header for
+    // the chunk.
+    void SetFlag(ChunkHeader::Flags flag) {
+      ChunkHeader* chunk_header = header();
+      auto packets = chunk_header->packets.load(std::memory_order_relaxed);
+      packets.flags |= flag;
+      chunk_header->packets.store(packets, std::memory_order_release);
+    }
+
+   private:
+    friend class SharedMemoryABI;
+    Chunk(uint8_t* begin, uint16_t size, uint8_t chunk_idx);
+
+    // Don't add extra fields, keep the move operator fast.
+    uint8_t* begin_ = nullptr;
+    uint16_t size_ = 0;
+    uint8_t chunk_idx_ = 0;
+  };
+
+  // Construct an instance from an existing shared memory buffer.
+  SharedMemoryABI(uint8_t* start, size_t size, size_t page_size);
+  SharedMemoryABI();
+
+  void Initialize(uint8_t* start, size_t size, size_t page_size);
+
+  uint8_t* start() const { return start_; }
+  uint8_t* end() const { return start_ + size_; }
+  size_t size() const { return size_; }
+  size_t page_size() const { return page_size_; }
+  size_t num_pages() const { return num_pages_; }
+  bool is_valid() { return num_pages() > 0; }
+
+  uint8_t* page_start(size_t page_idx) {
+    PERFETTO_DCHECK(page_idx < num_pages_);
+    return start_ + page_size_ * page_idx;
+  }
+
+  PageHeader* page_header(size_t page_idx) {
+    return reinterpret_cast<PageHeader*>(page_start(page_idx));
+  }
+
+  // Returns true if the page is fully clear and has not been partitioned yet.
+  // The state of the page can change at any point after this returns (or even
+  // before). The Producer should use this only as a hint to decide out whether
+  // it should TryPartitionPage() or acquire an individual chunk.
+  bool is_page_free(size_t page_idx) {
+    return page_header(page_idx)->layout.load(std::memory_order_relaxed) == 0;
+  }
+
+  // Returns true if all chunks in the page are kChunkComplete. As above, this
+  // is advisory only. The Service is supposed to use this only to decide
+  // whether to TryAcquireAllChunksForReading() or not.
+  bool is_page_complete(size_t page_idx) {
+    auto layout = page_header(page_idx)->layout.load(std::memory_order_relaxed);
+    const uint32_t num_chunks = GetNumChunksForLayout(layout);
+    if (num_chunks == 0)
+      return false;  // Non partitioned pages cannot be complete.
+    return (layout & kAllChunksMask) ==
+           (kAllChunksComplete & ((1 << (num_chunks * kChunkShift)) - 1));
+  }
+
+  // For testing / debugging only.
+  std::string page_header_dbg(size_t page_idx) {
+    uint32_t x = page_header(page_idx)->layout.load(std::memory_order_relaxed);
+    return std::bitset<32>(x).to_string();
+  }
+
+  // Returns the page layout, which is a bitmap that specifies the chunking
+  // layout of the page and each chunk's current state. Reads with an
+  // acquire-load semantic to ensure a producer's writes corresponding to an
+  // update of the layout (e.g. clearing a chunk's header) are observed
+  // consistently.
+  uint32_t GetPageLayout(size_t page_idx) {
+    return page_header(page_idx)->layout.load(std::memory_order_acquire);
+  }
+
+  // Returns a bitmap in which each bit is set if the corresponding Chunk exists
+  // in the page (according to the page layout) and is free. If the page is not
+  // partitioned it returns 0 (as if the page had no free chunks).
+  uint32_t GetFreeChunks(size_t page_idx);
+
+  // Tries to atomically partition a page with the given |layout|. Returns true
+  // if the page was free and has been partitioned with the given |layout|,
+  // false if the page wasn't free anymore by the time we got there.
+  // If succeeds all the chunks are atomically set in the kChunkFree state.
+  bool TryPartitionPage(size_t page_idx, PageLayout layout);
+
+  // Tries to atomically mark a single chunk within the page as
+  // kChunkBeingWritten. Returns an invalid chunk if the page is not partitioned
+  // or the chunk is not in the kChunkFree state. If succeeds sets the chunk
+  // header to |header|.
+  Chunk TryAcquireChunkForWriting(size_t page_idx,
+                                  size_t chunk_idx,
+                                  const ChunkHeader* header) {
+    return TryAcquireChunk(page_idx, chunk_idx, kChunkBeingWritten, header);
+  }
+
+  // Similar to TryAcquireChunkForWriting. Fails if the chunk isn't in the
+  // kChunkComplete state.
+  Chunk TryAcquireChunkForReading(size_t page_idx, size_t chunk_idx) {
+    return TryAcquireChunk(page_idx, chunk_idx, kChunkBeingRead, nullptr);
+  }
+
+  // The caller must have successfully TryAcquireAllChunksForReading().
+  Chunk GetChunkUnchecked(size_t page_idx,
+                          uint32_t page_layout,
+                          size_t chunk_idx);
+
+  // Puts a chunk into the kChunkComplete state. Returns the page index.
+  size_t ReleaseChunkAsComplete(Chunk chunk) {
+    return ReleaseChunk(std::move(chunk), kChunkComplete);
+  }
+
+  // Puts a chunk into the kChunkFree state. Returns the page index.
+  size_t ReleaseChunkAsFree(Chunk chunk) {
+    return ReleaseChunk(std::move(chunk), kChunkFree);
+  }
+
+  ChunkState GetChunkState(size_t page_idx, size_t chunk_idx) {
+    PageHeader* phdr = page_header(page_idx);
+    uint32_t layout = phdr->layout.load(std::memory_order_relaxed);
+    return GetChunkStateFromLayout(layout, chunk_idx);
+  }
+
+  std::pair<size_t, size_t> GetPageAndChunkIndex(const Chunk& chunk);
+
+  uint16_t GetChunkSizeForLayout(uint32_t page_layout) const {
+    return chunk_sizes_[(page_layout & kLayoutMask) >> kLayoutShift];
+  }
+
+  static ChunkState GetChunkStateFromLayout(uint32_t page_layout,
+                                            size_t chunk_idx) {
+    return static_cast<ChunkState>((page_layout >> (chunk_idx * kChunkShift)) &
+                                   kChunkMask);
+  }
+
+  static constexpr uint32_t GetNumChunksForLayout(uint32_t page_layout) {
+    return kNumChunksForLayout[(page_layout & kLayoutMask) >> kLayoutShift];
+  }
+
+  // Returns a bitmap in which each bit is set if the corresponding Chunk exists
+  // in the page (according to the page layout) and is not free. If the page is
+  // not partitioned it returns 0 (as if the page had no used chunks). Bit N
+  // corresponds to Chunk N.
+  static uint32_t GetUsedChunks(uint32_t page_layout) {
+    const uint32_t num_chunks = GetNumChunksForLayout(page_layout);
+    uint32_t res = 0;
+    for (uint32_t i = 0; i < num_chunks; i++) {
+      res |= ((page_layout & kChunkMask) != kChunkFree) ? (1 << i) : 0;
+      page_layout >>= kChunkShift;
+    }
+    return res;
+  }
+
+ private:
+  SharedMemoryABI(const SharedMemoryABI&) = delete;
+  SharedMemoryABI& operator=(const SharedMemoryABI&) = delete;
+
+  Chunk TryAcquireChunk(size_t page_idx,
+                        size_t chunk_idx,
+                        ChunkState,
+                        const ChunkHeader*);
+  size_t ReleaseChunk(Chunk chunk, ChunkState);
+
+  uint8_t* start_ = nullptr;
+  size_t size_ = 0;
+  size_t page_size_ = 0;
+  size_t num_pages_ = 0;
+  std::array<uint16_t, kNumPageLayouts> chunk_sizes_;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_SHARED_MEMORY_ABI_H_
diff --git a/include/perfetto/tracing/core/shared_memory_arbiter.h b/include/perfetto/tracing/core/shared_memory_arbiter.h
new file mode 100644
index 0000000..660014c
--- /dev/null
+++ b/include/perfetto/tracing/core/shared_memory_arbiter.h
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_SHARED_MEMORY_ARBITER_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_SHARED_MEMORY_ARBITER_H_
+
+#include <stddef.h>
+
+#include <functional>
+#include <memory>
+#include <vector>
+
+#include "perfetto/base/export.h"
+#include "perfetto/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/tracing_service.h"
+
+namespace perfetto {
+
+namespace base {
+class TaskRunner;
+}
+
+class CommitDataRequest;
+class StartupTraceWriter;
+class StartupTraceWriterRegistry;
+class SharedMemory;
+class TraceWriter;
+
+// Used by the Producer-side of the transport layer to vend TraceWriters
+// from the SharedMemory it receives from the Service-side.
+class PERFETTO_EXPORT SharedMemoryArbiter {
+ public:
+  virtual ~SharedMemoryArbiter();
+
+  // Creates a new TraceWriter and assigns it a new WriterID. The WriterID is
+  // written in each chunk header owned by a given TraceWriter and is used by
+  // the Service to reconstruct TracePackets written by the same TraceWriter.
+  // Returns null impl of TraceWriter if all WriterID slots are exhausted.
+  virtual std::unique_ptr<TraceWriter> CreateTraceWriter(
+      BufferID target_buffer) = 0;
+
+  // Binds the provided unbound StartupTraceWriterRegistry to the arbiter's SMB.
+  // Normally this happens when the perfetto service has been initialized and we
+  // want to rebind all the writers created in the early startup phase.
+  //
+  // All StartupTraceWriters created by the registry are bound to the arbiter
+  // and the given target buffer. The writers may not be bound immediately if
+  // they are concurrently being written to or if this method isn't called on
+  // the arbiter's TaskRunner. The registry will retry on the arbiter's
+  // TaskRunner until all writers were bound successfully.
+  //
+  // By calling this method, the registry's ownership is transferred to the
+  // arbiter. The arbiter will delete the registry once all writers were bound.
+  //
+  // TODO(eseckler): Make target buffer assignment more flexible (i.e. per
+  // writer). For now, embedders can use multiple registries instead.
+  virtual void BindStartupTraceWriterRegistry(
+      std::unique_ptr<StartupTraceWriterRegistry>,
+      BufferID target_buffer) = 0;
+
+  // Notifies the service that all data for the given FlushRequestID has been
+  // committed in the shared memory buffer.
+  virtual void NotifyFlushComplete(FlushRequestID) = 0;
+
+  // Implemented in src/core/shared_memory_arbiter_impl.cc .
+  static std::unique_ptr<SharedMemoryArbiter> CreateInstance(
+      SharedMemory*,
+      size_t page_size,
+      TracingService::ProducerEndpoint*,
+      base::TaskRunner*);
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_SHARED_MEMORY_ARBITER_H_
diff --git a/include/perfetto/tracing/core/slice.h b/include/perfetto/tracing/core/slice.h
new file mode 100644
index 0000000..954e58d
--- /dev/null
+++ b/include/perfetto/tracing/core/slice.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_TRACING_CORE_SLICE_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_SLICE_H_
+
+#include <stddef.h>
+#include <string.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "perfetto/base/logging.h"
+
+namespace perfetto {
+
+// A simple wrapper around a virtually contiguous memory range that contains a
+// TracePacket, or just a portion of it.
+struct Slice {
+  Slice() : start(nullptr), size(0) {}
+  Slice(const void* st, size_t sz) : start(st), size(sz) {}
+
+  // Used to inherit ownership of a buffer from a protobuf via release_str().
+  explicit Slice(std::unique_ptr<std::string> str)
+      : start(&(*str)[0]), size(str->size()), moved_str_data_(std::move(str)) {}
+
+  Slice(Slice&& other) noexcept = default;
+
+  // Create a Slice which owns |size| bytes of memory.
+  static Slice Allocate(size_t size) {
+    Slice slice;
+    slice.own_data_.reset(new uint8_t[size]);
+    slice.start = &slice.own_data_[0];
+    slice.size = size;
+    return slice;
+  }
+
+  uint8_t* own_data() {
+    PERFETTO_DCHECK(own_data_);
+    return own_data_.get();
+  }
+
+  const void* start;
+  size_t size;
+
+ private:
+  Slice(const Slice&) = delete;
+  void operator=(const Slice&) = delete;
+
+  std::unique_ptr<uint8_t[]> own_data_;
+  std::unique_ptr<std::string> moved_str_data_;
+};
+
+// TODO(primiano): most TracePacket(s) fit in a slice or two. We need something
+// a bit more clever here that has inline capacity for 2 slices and then uses a
+// std::forward_list or a std::vector for the less likely cases.
+using Slices = std::vector<Slice>;
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_SLICE_H_
diff --git a/include/perfetto/tracing/core/startup_trace_writer.h b/include/perfetto/tracing/core/startup_trace_writer.h
new file mode 100644
index 0000000..d1ad82c
--- /dev/null
+++ b/include/perfetto/tracing/core/startup_trace_writer.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_CORE_STARTUP_TRACE_WRITER_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_STARTUP_TRACE_WRITER_H_
+
+#include <memory>
+#include <mutex>
+#include <set>
+#include <vector>
+
+#include "perfetto/base/export.h"
+#include "perfetto/base/optional.h"
+#include "perfetto/base/thread_checker.h"
+#include "perfetto/protozero/message_handle.h"
+#include "perfetto/protozero/scattered_heap_buffer.h"
+#include "perfetto/protozero/scattered_stream_writer.h"
+#include "perfetto/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/trace_writer.h"
+
+namespace perfetto {
+
+class SharedMemoryArbiterImpl;
+class StartupTraceWriterRegistryHandle;
+
+namespace protos {
+namespace pbzero {
+class TracePacket;
+}  // namespace pbzero
+}  // namespace protos
+
+// Facilitates writing trace events in early phases of an application's startup
+// when the perfetto service is not available yet.
+//
+// Until the service is available, producer threads instantiate an unbound
+// StartupTraceWriter instance (via a StartupTraceWriterRegistry) and use it to
+// emit trace events. Each writer will record the serialized trace events into a
+// temporary local memory buffer.
+//
+// Once the service is available, the producer binds each StartupTraceWriter to
+// the SMB by calling SharedMemoryArbiter::BindStartupTraceWriter(). The data in
+// the writer's local buffer will then be copied into the SMB and the any future
+// writes will proxy directly to a new SMB-backed TraceWriter.
+//
+// Writing to the temporary local trace buffer is guarded by a lock and flag to
+// allow binding the writer from a different thread. When the writer starts
+// writing data by calling NewTracePacket(), the writer thread acquires the lock
+// to set a flag indicating that a write is in progress. Once the packet is
+// finalized, the flag is reset. To bind the writer, the lock is acquired while
+// the flag is unset and released only once binding completed, thereby blocking
+// the writer thread from starting a write concurrently.
+//
+// While unbound, the writer thread should finalize each TracePacket as soon as
+// possible to ensure that it doesn't block binding the writer.
+class PERFETTO_EXPORT StartupTraceWriter
+    : public TraceWriter,
+      public protozero::MessageHandleBase::FinalizationListener {
+ public:
+  // Create a StartupTraceWriter bound to |trace_writer|. Should only be called
+  // on the writer thread.
+  explicit StartupTraceWriter(std::unique_ptr<TraceWriter> trace_writer);
+
+  ~StartupTraceWriter() override;
+
+  // TraceWriter implementation. These methods should only be called on the
+  // writer thread.
+  TracePacketHandle NewTracePacket() override;
+  void Flush(std::function<void()> callback = {}) override;
+
+  // Note that this will return 0 until the first TracePacket was started after
+  // binding.
+  WriterID writer_id() const override;
+
+  uint64_t written() const override;
+
+  // Returns |true| if the writer thread has observed that the writer was bound
+  // to an SMB. Should only be called on the writer thread.
+  //
+  // The writer thread can use the return value to determine whether it needs to
+  // finalize the current TracePacket as soon as possible. It is only safe for
+  // the writer to batch data into a single TracePacket over a longer time
+  // period when this returns |true|.
+  bool was_bound() const {
+    PERFETTO_DCHECK_THREAD(writer_thread_checker_);
+    return was_bound_;
+  }
+
+  // Should only be called on the writer thread.
+  size_t used_buffer_size();
+
+ private:
+  friend class StartupTraceWriterRegistry;
+  friend class StartupTraceWriterTest;
+
+  // Create an unbound StartupTraceWriter associated with the registry pointed
+  // to by the handle. The writer can later be bound by calling
+  // BindToTraceWriter(). The registry handle may be nullptr in tests.
+  StartupTraceWriter(std::shared_ptr<StartupTraceWriterRegistryHandle>);
+
+  StartupTraceWriter(const StartupTraceWriter&) = delete;
+  StartupTraceWriter& operator=(const StartupTraceWriter&) = delete;
+
+  // Bind this StartupTraceWriter to the provided SharedMemoryArbiterImpl.
+  // Called by StartupTraceWriterRegistry::BindToArbiter().
+  //
+  // This method can be called on any thread. If any data was written locally
+  // before the writer was bound, BindToArbiter() will copy this data into
+  // chunks in the provided target buffer via the SMB. Any future packets will
+  // be directly written into the SMB via a newly obtained TraceWriter from the
+  // arbiter.
+  //
+  // Will fail and return |false| if a concurrent write is in progress. Returns
+  // |true| if successfully bound and should then not be called again.
+  bool BindToArbiter(SharedMemoryArbiterImpl*,
+                     BufferID target_buffer) PERFETTO_WARN_UNUSED_RESULT;
+
+  // protozero::MessageHandleBase::FinalizationListener implementation.
+  void OnMessageFinalized(protozero::Message* message) override;
+
+  void OnTracePacketCompleted();
+  ChunkID CommitLocalBufferChunks(SharedMemoryArbiterImpl*, WriterID, BufferID);
+
+  PERFETTO_THREAD_CHECKER(writer_thread_checker_)
+
+  std::shared_ptr<StartupTraceWriterRegistryHandle> registry_handle_;
+
+  // Only set and accessed from the writer thread. The writer thread flips this
+  // bit when it sees that trace_writer_ is set (while holding the lock).
+  // Caching this fact in this variable avoids the need to acquire the lock to
+  // check on later calls to NewTracePacket().
+  bool was_bound_ = false;
+
+  // All variables below this point are protected by |lock_|.
+  std::mutex lock_;
+
+  // Never reset once it is changed from |nullptr|.
+  std::unique_ptr<TraceWriter> trace_writer_ = nullptr;
+
+  // Local memory buffer for trace packets written before the writer is bound.
+  std::unique_ptr<protozero::ScatteredHeapBuffer> memory_buffer_;
+  std::unique_ptr<protozero::ScatteredStreamWriter> memory_stream_writer_;
+
+  std::vector<uint32_t> packet_sizes_;
+
+  // Whether the writer thread is currently writing a TracePacket.
+  bool write_in_progress_ = false;
+
+  // The packet returned via NewTracePacket() while the writer is unbound. Reset
+  // to |nullptr| once bound. Owned by this class, TracePacketHandle has just a
+  // pointer to it.
+  std::unique_ptr<protos::pbzero::TracePacket> cur_packet_;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_STARTUP_TRACE_WRITER_H_
diff --git a/include/perfetto/tracing/core/startup_trace_writer_registry.h b/include/perfetto/tracing/core/startup_trace_writer_registry.h
new file mode 100644
index 0000000..df48c5f
--- /dev/null
+++ b/include/perfetto/tracing/core/startup_trace_writer_registry.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_CORE_STARTUP_TRACE_WRITER_REGISTRY_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_STARTUP_TRACE_WRITER_REGISTRY_H_
+
+#include <functional>
+#include <memory>
+#include <mutex>
+#include <set>
+#include <vector>
+
+#include "perfetto/base/export.h"
+#include "perfetto/base/weak_ptr.h"
+#include "perfetto/tracing/core/basic_types.h"
+
+namespace perfetto {
+
+class SharedMemoryArbiterImpl;
+class StartupTraceWriter;
+class StartupTraceWriterRegistry;
+
+namespace base {
+class TaskRunner;
+}  // namespace base
+
+// Notifies the registry about the destruction of a StartupTraceWriter, provided
+// the registry itself wasn't deleted yet. The indirection via the handle is
+// necessary to avoid potential deadlocks caused by lock order inversion. These
+// issues are avoided by locking on the handle's common lock in the destructors
+// of the registry and writer.
+class StartupTraceWriterRegistryHandle {
+ public:
+  explicit StartupTraceWriterRegistryHandle(StartupTraceWriterRegistry*);
+
+  // Called by StartupTraceWriter destructor.
+  void OnWriterDestroyed(StartupTraceWriter*);
+
+  // Called by StartupTraceWriterRegistry destructor.
+  void OnRegistryDestroyed();
+
+ private:
+  StartupTraceWriterRegistryHandle(const StartupTraceWriterRegistryHandle&) =
+      delete;
+  StartupTraceWriterRegistryHandle& operator=(
+      const StartupTraceWriterRegistryHandle&) = delete;
+
+  std::mutex lock_;
+  StartupTraceWriterRegistry* registry_;
+};
+
+// Embedders can use this registry to create unbound StartupTraceWriters during
+// startup, and later bind them all safely to an arbiter and target buffer.
+class PERFETTO_EXPORT StartupTraceWriterRegistry {
+ public:
+  StartupTraceWriterRegistry();
+  ~StartupTraceWriterRegistry();
+
+  // Returns a new unbound StartupTraceWriter. Should only be called while
+  // unbound. Usually called on a writer thread.
+  std::unique_ptr<StartupTraceWriter> CreateUnboundTraceWriter();
+
+  // Return an unbound StartupTraceWriter back to the registry before it could
+  // be bound (usually called when the writer's thread is destroyed). The
+  // registry will keep this writer alive until the registry is bound to an
+  // arbiter (or destroyed itself). This way, its buffered data is retained.
+  // Should only be called while unbound. All packets written to the passed
+  // writer should have been completed and it should no longer be used to write
+  // data after calling this method.
+  void ReturnUnboundTraceWriter(std::unique_ptr<StartupTraceWriter>);
+
+  // Binds all StartupTraceWriters created by this registry to the given arbiter
+  // and target buffer. Should only be called once and on the passed
+  // TaskRunner's sequence. See
+  // SharedMemoryArbiter::BindStartupTraceWriterRegistry() for details.
+  //
+  // Note that the writers may not be bound synchronously if they are
+  // concurrently being written to. The registry will retry on the passed
+  // TaskRunner until all writers were bound successfully.
+  //
+  // Calls |on_bound_callback| asynchronously on the passed TaskRunner once all
+  // writers were bound.
+  void BindToArbiter(
+      SharedMemoryArbiterImpl*,
+      BufferID target_buffer,
+      base::TaskRunner*,
+      std::function<void(StartupTraceWriterRegistry*)> on_bound_callback);
+
+ private:
+  friend class StartupTraceWriterRegistryHandle;
+  friend class StartupTraceWriterTest;
+
+  StartupTraceWriterRegistry(const StartupTraceWriterRegistry&) = delete;
+  StartupTraceWriterRegistry& operator=(const StartupTraceWriterRegistry&) =
+      delete;
+
+  // Called by StartupTraceWriterRegistryHandle.
+  void OnStartupTraceWriterDestroyed(StartupTraceWriter*);
+
+  // Try to bind the remaining unbound writers and post a continuation to
+  // |task_runner_| if any writers could not be bound.
+  void TryBindWriters();
+
+  // Notifies the arbiter when we have bound all writers. May delete |this|.
+  void OnUnboundWritersRemovedLocked();
+
+  std::shared_ptr<StartupTraceWriterRegistryHandle> handle_;
+
+  // Begin lock-protected members.
+  std::mutex lock_;
+
+  // Unbound writers that we handed out to writer threads. These writers may be
+  // concurrently written to by the writer threads.
+  std::set<StartupTraceWriter*> unbound_writers_;
+
+  // Unbound writers that writer threads returned to the registry by calling
+  // ReturnUnboundTraceWriter(). Writers are removed from |unbound_writers_|
+  // when they are added to |unbound_owned_writers_|. No new data can be written
+  // to these writers.
+  std::vector<std::unique_ptr<StartupTraceWriter>> unbound_owned_writers_;
+
+  SharedMemoryArbiterImpl* arbiter_ = nullptr;  // |nullptr| while unbound.
+  BufferID target_buffer_ = 0;
+  base::TaskRunner* task_runner_;
+  std::function<void(StartupTraceWriterRegistry*)> on_bound_callback_ = nullptr;
+
+  // Keep at the end. Initialized during |BindToArbiter()|, like |task_runner_|.
+  // Weak pointers are only valid on |task_runner_|'s thread/sequence.
+  std::unique_ptr<base::WeakPtrFactory<StartupTraceWriterRegistry>>
+      weak_ptr_factory_;
+  // End lock-protected members.
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_STARTUP_TRACE_WRITER_REGISTRY_H_
diff --git a/include/perfetto/tracing/core/sys_stats_config.h b/include/perfetto/tracing/core/sys_stats_config.h
new file mode 100644
index 0000000..5e1b0da
--- /dev/null
+++ b/include/perfetto/tracing/core/sys_stats_config.h
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/sys_stats/sys_stats_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_SYS_STATS_CONFIG_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_SYS_STATS_CONFIG_H_
+
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+#include "perfetto/tracing/core/sys_stats_counters.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {
+class SysStatsConfig;
+}
+}  // namespace perfetto
+
+namespace perfetto {
+
+class PERFETTO_EXPORT SysStatsConfig {
+ public:
+  enum MeminfoCounters {
+    MEMINFO_UNSPECIFIED = 0,
+    MEMINFO_MEM_TOTAL = 1,
+    MEMINFO_MEM_FREE = 2,
+    MEMINFO_MEM_AVAILABLE = 3,
+    MEMINFO_BUFFERS = 4,
+    MEMINFO_CACHED = 5,
+    MEMINFO_SWAP_CACHED = 6,
+    MEMINFO_ACTIVE = 7,
+    MEMINFO_INACTIVE = 8,
+    MEMINFO_ACTIVE_ANON = 9,
+    MEMINFO_INACTIVE_ANON = 10,
+    MEMINFO_ACTIVE_FILE = 11,
+    MEMINFO_INACTIVE_FILE = 12,
+    MEMINFO_UNEVICTABLE = 13,
+    MEMINFO_MLOCKED = 14,
+    MEMINFO_SWAP_TOTAL = 15,
+    MEMINFO_SWAP_FREE = 16,
+    MEMINFO_DIRTY = 17,
+    MEMINFO_WRITEBACK = 18,
+    MEMINFO_ANON_PAGES = 19,
+    MEMINFO_MAPPED = 20,
+    MEMINFO_SHMEM = 21,
+    MEMINFO_SLAB = 22,
+    MEMINFO_SLAB_RECLAIMABLE = 23,
+    MEMINFO_SLAB_UNRECLAIMABLE = 24,
+    MEMINFO_KERNEL_STACK = 25,
+    MEMINFO_PAGE_TABLES = 26,
+    MEMINFO_COMMIT_LIMIT = 27,
+    MEMINFO_COMMITED_AS = 28,
+    MEMINFO_VMALLOC_TOTAL = 29,
+    MEMINFO_VMALLOC_USED = 30,
+    MEMINFO_VMALLOC_CHUNK = 31,
+    MEMINFO_CMA_TOTAL = 32,
+    MEMINFO_CMA_FREE = 33,
+  };
+  enum VmstatCounters {
+    VMSTAT_UNSPECIFIED = 0,
+    VMSTAT_NR_FREE_PAGES = 1,
+    VMSTAT_NR_ALLOC_BATCH = 2,
+    VMSTAT_NR_INACTIVE_ANON = 3,
+    VMSTAT_NR_ACTIVE_ANON = 4,
+    VMSTAT_NR_INACTIVE_FILE = 5,
+    VMSTAT_NR_ACTIVE_FILE = 6,
+    VMSTAT_NR_UNEVICTABLE = 7,
+    VMSTAT_NR_MLOCK = 8,
+    VMSTAT_NR_ANON_PAGES = 9,
+    VMSTAT_NR_MAPPED = 10,
+    VMSTAT_NR_FILE_PAGES = 11,
+    VMSTAT_NR_DIRTY = 12,
+    VMSTAT_NR_WRITEBACK = 13,
+    VMSTAT_NR_SLAB_RECLAIMABLE = 14,
+    VMSTAT_NR_SLAB_UNRECLAIMABLE = 15,
+    VMSTAT_NR_PAGE_TABLE_PAGES = 16,
+    VMSTAT_NR_KERNEL_STACK = 17,
+    VMSTAT_NR_OVERHEAD = 18,
+    VMSTAT_NR_UNSTABLE = 19,
+    VMSTAT_NR_BOUNCE = 20,
+    VMSTAT_NR_VMSCAN_WRITE = 21,
+    VMSTAT_NR_VMSCAN_IMMEDIATE_RECLAIM = 22,
+    VMSTAT_NR_WRITEBACK_TEMP = 23,
+    VMSTAT_NR_ISOLATED_ANON = 24,
+    VMSTAT_NR_ISOLATED_FILE = 25,
+    VMSTAT_NR_SHMEM = 26,
+    VMSTAT_NR_DIRTIED = 27,
+    VMSTAT_NR_WRITTEN = 28,
+    VMSTAT_NR_PAGES_SCANNED = 29,
+    VMSTAT_WORKINGSET_REFAULT = 30,
+    VMSTAT_WORKINGSET_ACTIVATE = 31,
+    VMSTAT_WORKINGSET_NODERECLAIM = 32,
+    VMSTAT_NR_ANON_TRANSPARENT_HUGEPAGES = 33,
+    VMSTAT_NR_FREE_CMA = 34,
+    VMSTAT_NR_SWAPCACHE = 35,
+    VMSTAT_NR_DIRTY_THRESHOLD = 36,
+    VMSTAT_NR_DIRTY_BACKGROUND_THRESHOLD = 37,
+    VMSTAT_PGPGIN = 38,
+    VMSTAT_PGPGOUT = 39,
+    VMSTAT_PGPGOUTCLEAN = 40,
+    VMSTAT_PSWPIN = 41,
+    VMSTAT_PSWPOUT = 42,
+    VMSTAT_PGALLOC_DMA = 43,
+    VMSTAT_PGALLOC_NORMAL = 44,
+    VMSTAT_PGALLOC_MOVABLE = 45,
+    VMSTAT_PGFREE = 46,
+    VMSTAT_PGACTIVATE = 47,
+    VMSTAT_PGDEACTIVATE = 48,
+    VMSTAT_PGFAULT = 49,
+    VMSTAT_PGMAJFAULT = 50,
+    VMSTAT_PGREFILL_DMA = 51,
+    VMSTAT_PGREFILL_NORMAL = 52,
+    VMSTAT_PGREFILL_MOVABLE = 53,
+    VMSTAT_PGSTEAL_KSWAPD_DMA = 54,
+    VMSTAT_PGSTEAL_KSWAPD_NORMAL = 55,
+    VMSTAT_PGSTEAL_KSWAPD_MOVABLE = 56,
+    VMSTAT_PGSTEAL_DIRECT_DMA = 57,
+    VMSTAT_PGSTEAL_DIRECT_NORMAL = 58,
+    VMSTAT_PGSTEAL_DIRECT_MOVABLE = 59,
+    VMSTAT_PGSCAN_KSWAPD_DMA = 60,
+    VMSTAT_PGSCAN_KSWAPD_NORMAL = 61,
+    VMSTAT_PGSCAN_KSWAPD_MOVABLE = 62,
+    VMSTAT_PGSCAN_DIRECT_DMA = 63,
+    VMSTAT_PGSCAN_DIRECT_NORMAL = 64,
+    VMSTAT_PGSCAN_DIRECT_MOVABLE = 65,
+    VMSTAT_PGSCAN_DIRECT_THROTTLE = 66,
+    VMSTAT_PGINODESTEAL = 67,
+    VMSTAT_SLABS_SCANNED = 68,
+    VMSTAT_KSWAPD_INODESTEAL = 69,
+    VMSTAT_KSWAPD_LOW_WMARK_HIT_QUICKLY = 70,
+    VMSTAT_KSWAPD_HIGH_WMARK_HIT_QUICKLY = 71,
+    VMSTAT_PAGEOUTRUN = 72,
+    VMSTAT_ALLOCSTALL = 73,
+    VMSTAT_PGROTATED = 74,
+    VMSTAT_DROP_PAGECACHE = 75,
+    VMSTAT_DROP_SLAB = 76,
+    VMSTAT_PGMIGRATE_SUCCESS = 77,
+    VMSTAT_PGMIGRATE_FAIL = 78,
+    VMSTAT_COMPACT_MIGRATE_SCANNED = 79,
+    VMSTAT_COMPACT_FREE_SCANNED = 80,
+    VMSTAT_COMPACT_ISOLATED = 81,
+    VMSTAT_COMPACT_STALL = 82,
+    VMSTAT_COMPACT_FAIL = 83,
+    VMSTAT_COMPACT_SUCCESS = 84,
+    VMSTAT_COMPACT_DAEMON_WAKE = 85,
+    VMSTAT_UNEVICTABLE_PGS_CULLED = 86,
+    VMSTAT_UNEVICTABLE_PGS_SCANNED = 87,
+    VMSTAT_UNEVICTABLE_PGS_RESCUED = 88,
+    VMSTAT_UNEVICTABLE_PGS_MLOCKED = 89,
+    VMSTAT_UNEVICTABLE_PGS_MUNLOCKED = 90,
+    VMSTAT_UNEVICTABLE_PGS_CLEARED = 91,
+    VMSTAT_UNEVICTABLE_PGS_STRANDED = 92,
+  };
+  enum StatCounters {
+    STAT_UNSPECIFIED = 0,
+    STAT_CPU_TIMES = 1,
+    STAT_IRQ_COUNTS = 2,
+    STAT_SOFTIRQ_COUNTS = 3,
+    STAT_FORK_COUNT = 4,
+  };
+  SysStatsConfig();
+  ~SysStatsConfig();
+  SysStatsConfig(SysStatsConfig&&) noexcept;
+  SysStatsConfig& operator=(SysStatsConfig&&);
+  SysStatsConfig(const SysStatsConfig&);
+  SysStatsConfig& operator=(const SysStatsConfig&);
+  bool operator==(const SysStatsConfig&) const;
+  bool operator!=(const SysStatsConfig& other) const {
+    return !(*this == other);
+  }
+
+  // Conversion methods from/to the corresponding protobuf types.
+  void FromProto(const perfetto::protos::SysStatsConfig&);
+  void ToProto(perfetto::protos::SysStatsConfig*) const;
+
+  uint32_t meminfo_period_ms() const { return meminfo_period_ms_; }
+  void set_meminfo_period_ms(uint32_t value) { meminfo_period_ms_ = value; }
+
+  int meminfo_counters_size() const {
+    return static_cast<int>(meminfo_counters_.size());
+  }
+  const std::vector<MeminfoCounters>& meminfo_counters() const {
+    return meminfo_counters_;
+  }
+  std::vector<MeminfoCounters>* mutable_meminfo_counters() {
+    return &meminfo_counters_;
+  }
+  void clear_meminfo_counters() { meminfo_counters_.clear(); }
+  MeminfoCounters* add_meminfo_counters() {
+    meminfo_counters_.emplace_back();
+    return &meminfo_counters_.back();
+  }
+
+  uint32_t vmstat_period_ms() const { return vmstat_period_ms_; }
+  void set_vmstat_period_ms(uint32_t value) { vmstat_period_ms_ = value; }
+
+  int vmstat_counters_size() const {
+    return static_cast<int>(vmstat_counters_.size());
+  }
+  const std::vector<VmstatCounters>& vmstat_counters() const {
+    return vmstat_counters_;
+  }
+  std::vector<VmstatCounters>* mutable_vmstat_counters() {
+    return &vmstat_counters_;
+  }
+  void clear_vmstat_counters() { vmstat_counters_.clear(); }
+  VmstatCounters* add_vmstat_counters() {
+    vmstat_counters_.emplace_back();
+    return &vmstat_counters_.back();
+  }
+
+  uint32_t stat_period_ms() const { return stat_period_ms_; }
+  void set_stat_period_ms(uint32_t value) { stat_period_ms_ = value; }
+
+  int stat_counters_size() const {
+    return static_cast<int>(stat_counters_.size());
+  }
+  const std::vector<StatCounters>& stat_counters() const {
+    return stat_counters_;
+  }
+  std::vector<StatCounters>* mutable_stat_counters() { return &stat_counters_; }
+  void clear_stat_counters() { stat_counters_.clear(); }
+  StatCounters* add_stat_counters() {
+    stat_counters_.emplace_back();
+    return &stat_counters_.back();
+  }
+
+ private:
+  uint32_t meminfo_period_ms_ = {};
+  std::vector<MeminfoCounters> meminfo_counters_;
+  uint32_t vmstat_period_ms_ = {};
+  std::vector<VmstatCounters> vmstat_counters_;
+  uint32_t stat_period_ms_ = {};
+  std::vector<StatCounters> stat_counters_;
+
+  // Allows to preserve unknown protobuf fields for compatibility
+  // with future versions of .proto files.
+  std::string unknown_fields_;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_SYS_STATS_CONFIG_H_
diff --git a/include/perfetto/tracing/core/sys_stats_counters.h b/include/perfetto/tracing/core/sys_stats_counters.h
new file mode 100644
index 0000000..3d44148
--- /dev/null
+++ b/include/perfetto/tracing/core/sys_stats_counters.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/common/sys_stats_counters.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_SYS_STATS_COUNTERS_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_SYS_STATS_COUNTERS_H_
+
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {}
+}  // namespace perfetto
+
+namespace perfetto {}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_SYS_STATS_COUNTERS_H_
diff --git a/include/perfetto/tracing/core/test_config.h b/include/perfetto/tracing/core/test_config.h
new file mode 100644
index 0000000..51e02d1
--- /dev/null
+++ b/include/perfetto/tracing/core/test_config.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/test_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_TEST_CONFIG_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_TEST_CONFIG_H_
+
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {
+class TestConfig;
+class TestConfig_DummyFields;
+}  // namespace protos
+}  // namespace perfetto
+
+namespace perfetto {
+
+class PERFETTO_EXPORT TestConfig {
+ public:
+  class PERFETTO_EXPORT DummyFields {
+   public:
+    DummyFields();
+    ~DummyFields();
+    DummyFields(DummyFields&&) noexcept;
+    DummyFields& operator=(DummyFields&&);
+    DummyFields(const DummyFields&);
+    DummyFields& operator=(const DummyFields&);
+    bool operator==(const DummyFields&) const;
+    bool operator!=(const DummyFields& other) const {
+      return !(*this == other);
+    }
+
+    // Conversion methods from/to the corresponding protobuf types.
+    void FromProto(const perfetto::protos::TestConfig_DummyFields&);
+    void ToProto(perfetto::protos::TestConfig_DummyFields*) const;
+
+    uint32_t field_uint32() const { return field_uint32_; }
+    void set_field_uint32(uint32_t value) { field_uint32_ = value; }
+
+    int32_t field_int32() const { return field_int32_; }
+    void set_field_int32(int32_t value) { field_int32_ = value; }
+
+    uint64_t field_uint64() const { return field_uint64_; }
+    void set_field_uint64(uint64_t value) { field_uint64_ = value; }
+
+    int64_t field_int64() const { return field_int64_; }
+    void set_field_int64(int64_t value) { field_int64_ = value; }
+
+    uint64_t field_fixed64() const { return field_fixed64_; }
+    void set_field_fixed64(uint64_t value) { field_fixed64_ = value; }
+
+    int64_t field_sfixed64() const { return field_sfixed64_; }
+    void set_field_sfixed64(int64_t value) { field_sfixed64_ = value; }
+
+    uint32_t field_fixed32() const { return field_fixed32_; }
+    void set_field_fixed32(uint32_t value) { field_fixed32_ = value; }
+
+    int32_t field_sfixed32() const { return field_sfixed32_; }
+    void set_field_sfixed32(int32_t value) { field_sfixed32_ = value; }
+
+    double field_double() const { return field_double_; }
+    void set_field_double(double value) { field_double_ = value; }
+
+    float field_float() const { return field_float_; }
+    void set_field_float(float value) { field_float_ = value; }
+
+    int64_t field_sint64() const { return field_sint64_; }
+    void set_field_sint64(int64_t value) { field_sint64_ = value; }
+
+    int32_t field_sint32() const { return field_sint32_; }
+    void set_field_sint32(int32_t value) { field_sint32_ = value; }
+
+    const std::string& field_string() const { return field_string_; }
+    void set_field_string(const std::string& value) { field_string_ = value; }
+
+    const std::string& field_bytes() const { return field_bytes_; }
+    void set_field_bytes(const std::string& value) { field_bytes_ = value; }
+    void set_field_bytes(const void* p, size_t s) {
+      field_bytes_.assign(reinterpret_cast<const char*>(p), s);
+    }
+
+   private:
+    uint32_t field_uint32_ = {};
+    int32_t field_int32_ = {};
+    uint64_t field_uint64_ = {};
+    int64_t field_int64_ = {};
+    uint64_t field_fixed64_ = {};
+    int64_t field_sfixed64_ = {};
+    uint32_t field_fixed32_ = {};
+    int32_t field_sfixed32_ = {};
+    double field_double_ = {};
+    float field_float_ = {};
+    int64_t field_sint64_ = {};
+    int32_t field_sint32_ = {};
+    std::string field_string_ = {};
+    std::string field_bytes_ = {};
+
+    // Allows to preserve unknown protobuf fields for compatibility
+    // with future versions of .proto files.
+    std::string unknown_fields_;
+  };
+
+  TestConfig();
+  ~TestConfig();
+  TestConfig(TestConfig&&) noexcept;
+  TestConfig& operator=(TestConfig&&);
+  TestConfig(const TestConfig&);
+  TestConfig& operator=(const TestConfig&);
+  bool operator==(const TestConfig&) const;
+  bool operator!=(const TestConfig& other) const { return !(*this == other); }
+
+  // Conversion methods from/to the corresponding protobuf types.
+  void FromProto(const perfetto::protos::TestConfig&);
+  void ToProto(perfetto::protos::TestConfig*) const;
+
+  uint32_t message_count() const { return message_count_; }
+  void set_message_count(uint32_t value) { message_count_ = value; }
+
+  uint32_t max_messages_per_second() const { return max_messages_per_second_; }
+  void set_max_messages_per_second(uint32_t value) {
+    max_messages_per_second_ = value;
+  }
+
+  uint32_t seed() const { return seed_; }
+  void set_seed(uint32_t value) { seed_ = value; }
+
+  uint32_t message_size() const { return message_size_; }
+  void set_message_size(uint32_t value) { message_size_ = value; }
+
+  bool send_batch_on_register() const { return send_batch_on_register_; }
+  void set_send_batch_on_register(bool value) {
+    send_batch_on_register_ = value;
+  }
+
+  const DummyFields& dummy_fields() const { return dummy_fields_; }
+  DummyFields* mutable_dummy_fields() { return &dummy_fields_; }
+
+ private:
+  uint32_t message_count_ = {};
+  uint32_t max_messages_per_second_ = {};
+  uint32_t seed_ = {};
+  uint32_t message_size_ = {};
+  bool send_batch_on_register_ = {};
+  DummyFields dummy_fields_ = {};
+
+  // Allows to preserve unknown protobuf fields for compatibility
+  // with future versions of .proto files.
+  std::string unknown_fields_;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_TEST_CONFIG_H_
diff --git a/include/perfetto/tracing/core/trace_config.h b/include/perfetto/tracing/core/trace_config.h
index d2ec6e1..c6fa937 100644
--- a/include/perfetto/tracing/core/trace_config.h
+++ b/include/perfetto/tracing/core/trace_config.h
@@ -14,14 +14,647 @@
  * limitations under the License.
  */
 
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/trace_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
 #ifndef INCLUDE_PERFETTO_TRACING_CORE_TRACE_CONFIG_H_
 #define INCLUDE_PERFETTO_TRACING_CORE_TRACE_CONFIG_H_
 
-// This header exists only for legacy code that used to refer to the
-// checked-in auto-generated code, before it was moved to be a build-time gen
-// rule. DO NOT add any new includes to this header, instead directly include
-// the one below.
-// TODO(primiano): cleanup call-sites and remove this header.
-#include "protos/perfetto/config/trace_config.gen.h"
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+#include "perfetto/tracing/core/data_source_config.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {
+class TraceConfig;
+class TraceConfig_BufferConfig;
+class TraceConfig_DataSource;
+class DataSourceConfig;
+class FtraceConfig;
+class ChromeConfig;
+class InodeFileConfig;
+class InodeFileConfig_MountPointMappingEntry;
+class ProcessStatsConfig;
+class SysStatsConfig;
+class HeapprofdConfig;
+class HeapprofdConfig_ContinuousDumpConfig;
+class AndroidPowerConfig;
+class AndroidLogConfig;
+class PackagesListConfig;
+class TestConfig;
+class TestConfig_DummyFields;
+class TraceConfig_BuiltinDataSource;
+class TraceConfig_ProducerConfig;
+class TraceConfig_StatsdMetadata;
+class TraceConfig_GuardrailOverrides;
+class TraceConfig_TriggerConfig;
+class TraceConfig_TriggerConfig_Trigger;
+class TraceConfig_IncrementalStateConfig;
+class TraceConfig_IncidentReportConfig;
+}  // namespace protos
+}  // namespace perfetto
+
+namespace perfetto {
+
+class PERFETTO_EXPORT TraceConfig {
+ public:
+  class PERFETTO_EXPORT BufferConfig {
+   public:
+    enum FillPolicy {
+      UNSPECIFIED = 0,
+      RING_BUFFER = 1,
+      DISCARD = 2,
+    };
+    BufferConfig();
+    ~BufferConfig();
+    BufferConfig(BufferConfig&&) noexcept;
+    BufferConfig& operator=(BufferConfig&&);
+    BufferConfig(const BufferConfig&);
+    BufferConfig& operator=(const BufferConfig&);
+    bool operator==(const BufferConfig&) const;
+    bool operator!=(const BufferConfig& other) const {
+      return !(*this == other);
+    }
+
+    // Conversion methods from/to the corresponding protobuf types.
+    void FromProto(const perfetto::protos::TraceConfig_BufferConfig&);
+    void ToProto(perfetto::protos::TraceConfig_BufferConfig*) const;
+
+    uint32_t size_kb() const { return size_kb_; }
+    void set_size_kb(uint32_t value) { size_kb_ = value; }
+
+    FillPolicy fill_policy() const { return fill_policy_; }
+    void set_fill_policy(FillPolicy value) { fill_policy_ = value; }
+
+   private:
+    uint32_t size_kb_ = {};
+    FillPolicy fill_policy_ = {};
+
+    // Allows to preserve unknown protobuf fields for compatibility
+    // with future versions of .proto files.
+    std::string unknown_fields_;
+  };
+
+  class PERFETTO_EXPORT DataSource {
+   public:
+    DataSource();
+    ~DataSource();
+    DataSource(DataSource&&) noexcept;
+    DataSource& operator=(DataSource&&);
+    DataSource(const DataSource&);
+    DataSource& operator=(const DataSource&);
+    bool operator==(const DataSource&) const;
+    bool operator!=(const DataSource& other) const { return !(*this == other); }
+
+    // Conversion methods from/to the corresponding protobuf types.
+    void FromProto(const perfetto::protos::TraceConfig_DataSource&);
+    void ToProto(perfetto::protos::TraceConfig_DataSource*) const;
+
+    const DataSourceConfig& config() const { return config_; }
+    DataSourceConfig* mutable_config() { return &config_; }
+
+    int producer_name_filter_size() const {
+      return static_cast<int>(producer_name_filter_.size());
+    }
+    const std::vector<std::string>& producer_name_filter() const {
+      return producer_name_filter_;
+    }
+    std::vector<std::string>* mutable_producer_name_filter() {
+      return &producer_name_filter_;
+    }
+    void clear_producer_name_filter() { producer_name_filter_.clear(); }
+    std::string* add_producer_name_filter() {
+      producer_name_filter_.emplace_back();
+      return &producer_name_filter_.back();
+    }
+
+   private:
+    DataSourceConfig config_ = {};
+    std::vector<std::string> producer_name_filter_;
+
+    // Allows to preserve unknown protobuf fields for compatibility
+    // with future versions of .proto files.
+    std::string unknown_fields_;
+  };
+
+  class PERFETTO_EXPORT BuiltinDataSource {
+   public:
+    BuiltinDataSource();
+    ~BuiltinDataSource();
+    BuiltinDataSource(BuiltinDataSource&&) noexcept;
+    BuiltinDataSource& operator=(BuiltinDataSource&&);
+    BuiltinDataSource(const BuiltinDataSource&);
+    BuiltinDataSource& operator=(const BuiltinDataSource&);
+    bool operator==(const BuiltinDataSource&) const;
+    bool operator!=(const BuiltinDataSource& other) const {
+      return !(*this == other);
+    }
+
+    // Conversion methods from/to the corresponding protobuf types.
+    void FromProto(const perfetto::protos::TraceConfig_BuiltinDataSource&);
+    void ToProto(perfetto::protos::TraceConfig_BuiltinDataSource*) const;
+
+    bool disable_clock_snapshotting() const {
+      return disable_clock_snapshotting_;
+    }
+    void set_disable_clock_snapshotting(bool value) {
+      disable_clock_snapshotting_ = value;
+    }
+
+    bool disable_trace_config() const { return disable_trace_config_; }
+    void set_disable_trace_config(bool value) { disable_trace_config_ = value; }
+
+    bool disable_system_info() const { return disable_system_info_; }
+    void set_disable_system_info(bool value) { disable_system_info_ = value; }
+
+   private:
+    bool disable_clock_snapshotting_ = {};
+    bool disable_trace_config_ = {};
+    bool disable_system_info_ = {};
+
+    // Allows to preserve unknown protobuf fields for compatibility
+    // with future versions of .proto files.
+    std::string unknown_fields_;
+  };
+
+  enum LockdownModeOperation {
+    LOCKDOWN_UNCHANGED = 0,
+    LOCKDOWN_CLEAR = 1,
+    LOCKDOWN_SET = 2,
+  };
+
+  class PERFETTO_EXPORT ProducerConfig {
+   public:
+    ProducerConfig();
+    ~ProducerConfig();
+    ProducerConfig(ProducerConfig&&) noexcept;
+    ProducerConfig& operator=(ProducerConfig&&);
+    ProducerConfig(const ProducerConfig&);
+    ProducerConfig& operator=(const ProducerConfig&);
+    bool operator==(const ProducerConfig&) const;
+    bool operator!=(const ProducerConfig& other) const {
+      return !(*this == other);
+    }
+
+    // Conversion methods from/to the corresponding protobuf types.
+    void FromProto(const perfetto::protos::TraceConfig_ProducerConfig&);
+    void ToProto(perfetto::protos::TraceConfig_ProducerConfig*) const;
+
+    const std::string& producer_name() const { return producer_name_; }
+    void set_producer_name(const std::string& value) { producer_name_ = value; }
+
+    uint32_t shm_size_kb() const { return shm_size_kb_; }
+    void set_shm_size_kb(uint32_t value) { shm_size_kb_ = value; }
+
+    uint32_t page_size_kb() const { return page_size_kb_; }
+    void set_page_size_kb(uint32_t value) { page_size_kb_ = value; }
+
+   private:
+    std::string producer_name_ = {};
+    uint32_t shm_size_kb_ = {};
+    uint32_t page_size_kb_ = {};
+
+    // Allows to preserve unknown protobuf fields for compatibility
+    // with future versions of .proto files.
+    std::string unknown_fields_;
+  };
+
+  class PERFETTO_EXPORT StatsdMetadata {
+   public:
+    StatsdMetadata();
+    ~StatsdMetadata();
+    StatsdMetadata(StatsdMetadata&&) noexcept;
+    StatsdMetadata& operator=(StatsdMetadata&&);
+    StatsdMetadata(const StatsdMetadata&);
+    StatsdMetadata& operator=(const StatsdMetadata&);
+    bool operator==(const StatsdMetadata&) const;
+    bool operator!=(const StatsdMetadata& other) const {
+      return !(*this == other);
+    }
+
+    // Conversion methods from/to the corresponding protobuf types.
+    void FromProto(const perfetto::protos::TraceConfig_StatsdMetadata&);
+    void ToProto(perfetto::protos::TraceConfig_StatsdMetadata*) const;
+
+    int64_t triggering_alert_id() const { return triggering_alert_id_; }
+    void set_triggering_alert_id(int64_t value) {
+      triggering_alert_id_ = value;
+    }
+
+    int32_t triggering_config_uid() const { return triggering_config_uid_; }
+    void set_triggering_config_uid(int32_t value) {
+      triggering_config_uid_ = value;
+    }
+
+    int64_t triggering_config_id() const { return triggering_config_id_; }
+    void set_triggering_config_id(int64_t value) {
+      triggering_config_id_ = value;
+    }
+
+    int64_t triggering_subscription_id() const {
+      return triggering_subscription_id_;
+    }
+    void set_triggering_subscription_id(int64_t value) {
+      triggering_subscription_id_ = value;
+    }
+
+   private:
+    int64_t triggering_alert_id_ = {};
+    int32_t triggering_config_uid_ = {};
+    int64_t triggering_config_id_ = {};
+    int64_t triggering_subscription_id_ = {};
+
+    // Allows to preserve unknown protobuf fields for compatibility
+    // with future versions of .proto files.
+    std::string unknown_fields_;
+  };
+
+  class PERFETTO_EXPORT GuardrailOverrides {
+   public:
+    GuardrailOverrides();
+    ~GuardrailOverrides();
+    GuardrailOverrides(GuardrailOverrides&&) noexcept;
+    GuardrailOverrides& operator=(GuardrailOverrides&&);
+    GuardrailOverrides(const GuardrailOverrides&);
+    GuardrailOverrides& operator=(const GuardrailOverrides&);
+    bool operator==(const GuardrailOverrides&) const;
+    bool operator!=(const GuardrailOverrides& other) const {
+      return !(*this == other);
+    }
+
+    // Conversion methods from/to the corresponding protobuf types.
+    void FromProto(const perfetto::protos::TraceConfig_GuardrailOverrides&);
+    void ToProto(perfetto::protos::TraceConfig_GuardrailOverrides*) const;
+
+    uint64_t max_upload_per_day_bytes() const {
+      return max_upload_per_day_bytes_;
+    }
+    void set_max_upload_per_day_bytes(uint64_t value) {
+      max_upload_per_day_bytes_ = value;
+    }
+
+   private:
+    uint64_t max_upload_per_day_bytes_ = {};
+
+    // Allows to preserve unknown protobuf fields for compatibility
+    // with future versions of .proto files.
+    std::string unknown_fields_;
+  };
+
+  class PERFETTO_EXPORT TriggerConfig {
+   public:
+    enum TriggerMode {
+      UNSPECIFIED = 0,
+      START_TRACING = 1,
+      STOP_TRACING = 2,
+    };
+
+    class PERFETTO_EXPORT Trigger {
+     public:
+      Trigger();
+      ~Trigger();
+      Trigger(Trigger&&) noexcept;
+      Trigger& operator=(Trigger&&);
+      Trigger(const Trigger&);
+      Trigger& operator=(const Trigger&);
+      bool operator==(const Trigger&) const;
+      bool operator!=(const Trigger& other) const { return !(*this == other); }
+
+      // Conversion methods from/to the corresponding protobuf types.
+      void FromProto(
+          const perfetto::protos::TraceConfig_TriggerConfig_Trigger&);
+      void ToProto(perfetto::protos::TraceConfig_TriggerConfig_Trigger*) const;
+
+      const std::string& name() const { return name_; }
+      void set_name(const std::string& value) { name_ = value; }
+
+      const std::string& producer_name_regex() const {
+        return producer_name_regex_;
+      }
+      void set_producer_name_regex(const std::string& value) {
+        producer_name_regex_ = value;
+      }
+
+      uint32_t stop_delay_ms() const { return stop_delay_ms_; }
+      void set_stop_delay_ms(uint32_t value) { stop_delay_ms_ = value; }
+
+     private:
+      std::string name_ = {};
+      std::string producer_name_regex_ = {};
+      uint32_t stop_delay_ms_ = {};
+
+      // Allows to preserve unknown protobuf fields for compatibility
+      // with future versions of .proto files.
+      std::string unknown_fields_;
+    };
+
+    TriggerConfig();
+    ~TriggerConfig();
+    TriggerConfig(TriggerConfig&&) noexcept;
+    TriggerConfig& operator=(TriggerConfig&&);
+    TriggerConfig(const TriggerConfig&);
+    TriggerConfig& operator=(const TriggerConfig&);
+    bool operator==(const TriggerConfig&) const;
+    bool operator!=(const TriggerConfig& other) const {
+      return !(*this == other);
+    }
+
+    // Conversion methods from/to the corresponding protobuf types.
+    void FromProto(const perfetto::protos::TraceConfig_TriggerConfig&);
+    void ToProto(perfetto::protos::TraceConfig_TriggerConfig*) const;
+
+    TriggerMode trigger_mode() const { return trigger_mode_; }
+    void set_trigger_mode(TriggerMode value) { trigger_mode_ = value; }
+
+    int triggers_size() const { return static_cast<int>(triggers_.size()); }
+    const std::vector<Trigger>& triggers() const { return triggers_; }
+    std::vector<Trigger>* mutable_triggers() { return &triggers_; }
+    void clear_triggers() { triggers_.clear(); }
+    Trigger* add_triggers() {
+      triggers_.emplace_back();
+      return &triggers_.back();
+    }
+
+    uint32_t trigger_timeout_ms() const { return trigger_timeout_ms_; }
+    void set_trigger_timeout_ms(uint32_t value) { trigger_timeout_ms_ = value; }
+
+   private:
+    TriggerMode trigger_mode_ = {};
+    std::vector<Trigger> triggers_;
+    uint32_t trigger_timeout_ms_ = {};
+
+    // Allows to preserve unknown protobuf fields for compatibility
+    // with future versions of .proto files.
+    std::string unknown_fields_;
+  };
+
+  class PERFETTO_EXPORT IncrementalStateConfig {
+   public:
+    IncrementalStateConfig();
+    ~IncrementalStateConfig();
+    IncrementalStateConfig(IncrementalStateConfig&&) noexcept;
+    IncrementalStateConfig& operator=(IncrementalStateConfig&&);
+    IncrementalStateConfig(const IncrementalStateConfig&);
+    IncrementalStateConfig& operator=(const IncrementalStateConfig&);
+    bool operator==(const IncrementalStateConfig&) const;
+    bool operator!=(const IncrementalStateConfig& other) const {
+      return !(*this == other);
+    }
+
+    // Conversion methods from/to the corresponding protobuf types.
+    void FromProto(const perfetto::protos::TraceConfig_IncrementalStateConfig&);
+    void ToProto(perfetto::protos::TraceConfig_IncrementalStateConfig*) const;
+
+    uint32_t clear_period_ms() const { return clear_period_ms_; }
+    void set_clear_period_ms(uint32_t value) { clear_period_ms_ = value; }
+
+   private:
+    uint32_t clear_period_ms_ = {};
+
+    // Allows to preserve unknown protobuf fields for compatibility
+    // with future versions of .proto files.
+    std::string unknown_fields_;
+  };
+
+  enum CompressionType {
+    COMPRESSION_TYPE_UNSPECIFIED = 0,
+    COMPRESSION_TYPE_DEFLATE = 1,
+  };
+
+  class PERFETTO_EXPORT IncidentReportConfig {
+   public:
+    IncidentReportConfig();
+    ~IncidentReportConfig();
+    IncidentReportConfig(IncidentReportConfig&&) noexcept;
+    IncidentReportConfig& operator=(IncidentReportConfig&&);
+    IncidentReportConfig(const IncidentReportConfig&);
+    IncidentReportConfig& operator=(const IncidentReportConfig&);
+    bool operator==(const IncidentReportConfig&) const;
+    bool operator!=(const IncidentReportConfig& other) const {
+      return !(*this == other);
+    }
+
+    // Conversion methods from/to the corresponding protobuf types.
+    void FromProto(const perfetto::protos::TraceConfig_IncidentReportConfig&);
+    void ToProto(perfetto::protos::TraceConfig_IncidentReportConfig*) const;
+
+    const std::string& destination_package() const {
+      return destination_package_;
+    }
+    void set_destination_package(const std::string& value) {
+      destination_package_ = value;
+    }
+
+    const std::string& destination_class() const { return destination_class_; }
+    void set_destination_class(const std::string& value) {
+      destination_class_ = value;
+    }
+
+    int32_t privacy_level() const { return privacy_level_; }
+    void set_privacy_level(int32_t value) { privacy_level_ = value; }
+
+    bool skip_dropbox() const { return skip_dropbox_; }
+    void set_skip_dropbox(bool value) { skip_dropbox_ = value; }
+
+   private:
+    std::string destination_package_ = {};
+    std::string destination_class_ = {};
+    int32_t privacy_level_ = {};
+    bool skip_dropbox_ = {};
+
+    // Allows to preserve unknown protobuf fields for compatibility
+    // with future versions of .proto files.
+    std::string unknown_fields_;
+  };
+
+  TraceConfig();
+  ~TraceConfig();
+  TraceConfig(TraceConfig&&) noexcept;
+  TraceConfig& operator=(TraceConfig&&);
+  TraceConfig(const TraceConfig&);
+  TraceConfig& operator=(const TraceConfig&);
+  bool operator==(const TraceConfig&) const;
+  bool operator!=(const TraceConfig& other) const { return !(*this == other); }
+
+  // Conversion methods from/to the corresponding protobuf types.
+  void FromProto(const perfetto::protos::TraceConfig&);
+  void ToProto(perfetto::protos::TraceConfig*) const;
+
+  int buffers_size() const { return static_cast<int>(buffers_.size()); }
+  const std::vector<BufferConfig>& buffers() const { return buffers_; }
+  std::vector<BufferConfig>* mutable_buffers() { return &buffers_; }
+  void clear_buffers() { buffers_.clear(); }
+  BufferConfig* add_buffers() {
+    buffers_.emplace_back();
+    return &buffers_.back();
+  }
+
+  int data_sources_size() const {
+    return static_cast<int>(data_sources_.size());
+  }
+  const std::vector<DataSource>& data_sources() const { return data_sources_; }
+  std::vector<DataSource>* mutable_data_sources() { return &data_sources_; }
+  void clear_data_sources() { data_sources_.clear(); }
+  DataSource* add_data_sources() {
+    data_sources_.emplace_back();
+    return &data_sources_.back();
+  }
+
+  const BuiltinDataSource& builtin_data_sources() const {
+    return builtin_data_sources_;
+  }
+  BuiltinDataSource* mutable_builtin_data_sources() {
+    return &builtin_data_sources_;
+  }
+
+  uint32_t duration_ms() const { return duration_ms_; }
+  void set_duration_ms(uint32_t value) { duration_ms_ = value; }
+
+  bool enable_extra_guardrails() const { return enable_extra_guardrails_; }
+  void set_enable_extra_guardrails(bool value) {
+    enable_extra_guardrails_ = value;
+  }
+
+  LockdownModeOperation lockdown_mode() const { return lockdown_mode_; }
+  void set_lockdown_mode(LockdownModeOperation value) {
+    lockdown_mode_ = value;
+  }
+
+  int producers_size() const { return static_cast<int>(producers_.size()); }
+  const std::vector<ProducerConfig>& producers() const { return producers_; }
+  std::vector<ProducerConfig>* mutable_producers() { return &producers_; }
+  void clear_producers() { producers_.clear(); }
+  ProducerConfig* add_producers() {
+    producers_.emplace_back();
+    return &producers_.back();
+  }
+
+  const StatsdMetadata& statsd_metadata() const { return statsd_metadata_; }
+  StatsdMetadata* mutable_statsd_metadata() { return &statsd_metadata_; }
+
+  bool write_into_file() const { return write_into_file_; }
+  void set_write_into_file(bool value) { write_into_file_ = value; }
+
+  uint32_t file_write_period_ms() const { return file_write_period_ms_; }
+  void set_file_write_period_ms(uint32_t value) {
+    file_write_period_ms_ = value;
+  }
+
+  uint64_t max_file_size_bytes() const { return max_file_size_bytes_; }
+  void set_max_file_size_bytes(uint64_t value) { max_file_size_bytes_ = value; }
+
+  const GuardrailOverrides& guardrail_overrides() const {
+    return guardrail_overrides_;
+  }
+  GuardrailOverrides* mutable_guardrail_overrides() {
+    return &guardrail_overrides_;
+  }
+
+  bool deferred_start() const { return deferred_start_; }
+  void set_deferred_start(bool value) { deferred_start_ = value; }
+
+  uint32_t flush_period_ms() const { return flush_period_ms_; }
+  void set_flush_period_ms(uint32_t value) { flush_period_ms_ = value; }
+
+  uint32_t flush_timeout_ms() const { return flush_timeout_ms_; }
+  void set_flush_timeout_ms(uint32_t value) { flush_timeout_ms_ = value; }
+
+  bool notify_traceur() const { return notify_traceur_; }
+  void set_notify_traceur(bool value) { notify_traceur_ = value; }
+
+  const TriggerConfig& trigger_config() const { return trigger_config_; }
+  TriggerConfig* mutable_trigger_config() { return &trigger_config_; }
+
+  int activate_triggers_size() const {
+    return static_cast<int>(activate_triggers_.size());
+  }
+  const std::vector<std::string>& activate_triggers() const {
+    return activate_triggers_;
+  }
+  std::vector<std::string>* mutable_activate_triggers() {
+    return &activate_triggers_;
+  }
+  void clear_activate_triggers() { activate_triggers_.clear(); }
+  std::string* add_activate_triggers() {
+    activate_triggers_.emplace_back();
+    return &activate_triggers_.back();
+  }
+
+  const IncrementalStateConfig& incremental_state_config() const {
+    return incremental_state_config_;
+  }
+  IncrementalStateConfig* mutable_incremental_state_config() {
+    return &incremental_state_config_;
+  }
+
+  bool allow_user_build_tracing() const { return allow_user_build_tracing_; }
+  void set_allow_user_build_tracing(bool value) {
+    allow_user_build_tracing_ = value;
+  }
+
+  const std::string& unique_session_name() const {
+    return unique_session_name_;
+  }
+  void set_unique_session_name(const std::string& value) {
+    unique_session_name_ = value;
+  }
+
+  CompressionType compression_type() const { return compression_type_; }
+  void set_compression_type(CompressionType value) {
+    compression_type_ = value;
+  }
+
+  const IncidentReportConfig& incident_report_config() const {
+    return incident_report_config_;
+  }
+  IncidentReportConfig* mutable_incident_report_config() {
+    return &incident_report_config_;
+  }
+
+ private:
+  std::vector<BufferConfig> buffers_;
+  std::vector<DataSource> data_sources_;
+  BuiltinDataSource builtin_data_sources_ = {};
+  uint32_t duration_ms_ = {};
+  bool enable_extra_guardrails_ = {};
+  LockdownModeOperation lockdown_mode_ = {};
+  std::vector<ProducerConfig> producers_;
+  StatsdMetadata statsd_metadata_ = {};
+  bool write_into_file_ = {};
+  uint32_t file_write_period_ms_ = {};
+  uint64_t max_file_size_bytes_ = {};
+  GuardrailOverrides guardrail_overrides_ = {};
+  bool deferred_start_ = {};
+  uint32_t flush_period_ms_ = {};
+  uint32_t flush_timeout_ms_ = {};
+  bool notify_traceur_ = {};
+  TriggerConfig trigger_config_ = {};
+  std::vector<std::string> activate_triggers_;
+  IncrementalStateConfig incremental_state_config_ = {};
+  bool allow_user_build_tracing_ = {};
+  std::string unique_session_name_ = {};
+  CompressionType compression_type_ = {};
+  IncidentReportConfig incident_report_config_ = {};
+
+  // Allows to preserve unknown protobuf fields for compatibility
+  // with future versions of .proto files.
+  std::string unknown_fields_;
+};
+
+}  // namespace perfetto
 
 #endif  // INCLUDE_PERFETTO_TRACING_CORE_TRACE_CONFIG_H_
diff --git a/include/perfetto/tracing/core/trace_packet.h b/include/perfetto/tracing/core/trace_packet.h
new file mode 100644
index 0000000..3c9d44c
--- /dev/null
+++ b/include/perfetto/tracing/core/trace_packet.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_TRACING_CORE_TRACE_PACKET_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_TRACE_PACKET_H_
+
+#include <stddef.h>
+
+#include <memory>
+#include <tuple>
+
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "perfetto/base/export.h"
+#include "perfetto/base/logging.h"
+#include "perfetto/tracing/core/slice.h"
+
+namespace perfetto {
+
+namespace protos {
+class TracePacket;  // From protos/trace_packet.pb.h.
+}  // namespace protos
+
+// A wrapper around a byte buffer that contains a protobuf-encoded TracePacket
+// (see trace_packet.proto). The TracePacket is decoded only if the Consumer
+// requests that. This is to allow Consumer(s) to just stream the packet over
+// the network or save it to a file without wasting time decoding it and without
+// needing to depend on libprotobuf or the trace_packet.pb.h header.
+// If the packets are saved / streamed and not just consumed locally, consumers
+// should ensure to preserve the unknown fields in the proto. A consumer, in
+// fact, might have an older version .proto which is newer on the producer.
+class PERFETTO_EXPORT TracePacket {
+ public:
+  using const_iterator = Slices::const_iterator;
+  using ZeroCopyInputStream = ::google::protobuf::io::ZeroCopyInputStream;
+
+  // The field id of protos::Trace::packet, static_assert()-ed in the unittest.
+  static constexpr uint32_t kPacketFieldNumber = 1;
+
+  TracePacket();
+  ~TracePacket();
+  TracePacket(TracePacket&&) noexcept;
+  TracePacket& operator=(TracePacket&&);
+
+  // Accesses all the raw slices in the packet, for saving them to file/network.
+  const Slices& slices() const { return slices_; }
+
+  // Decodes the packet. This function requires that the caller:
+  // 1) Does #include "perfetto/trace/trace_packet.pb.h"
+  // 2) Links against the //protos/trace:lite target.
+  // The core service code deliberately doesn't link against that in order to
+  // avoid binary bloat. This is the reason why this is a templated function.
+  // It doesn't need to be (i.e. the caller should not specify the template
+  // argument) but doing so prevents the compiler trying to resolve the
+  // TracePacket type until it's needed, in which case the caller needs (1).
+  template <typename TracePacketType = protos::TracePacket>
+  bool Decode(TracePacketType* packet) const {
+    std::unique_ptr<ZeroCopyInputStream> istr = CreateSlicedInputStream();
+    return packet->ParseFromZeroCopyStream(istr.get());
+  }
+
+  // Mutator, used only by the service and tests.
+  void AddSlice(Slice);
+
+  // Does not copy / take ownership of the memory of the slice. The TracePacket
+  // will be valid only as long as the original buffer is valid.
+  void AddSlice(const void* start, size_t size);
+
+  // Total size of all slices.
+  size_t size() const { return size_; }
+
+  // Generates a protobuf preamble suitable to represent this packet as a
+  // repeated field within a root trace.proto message.
+  // Returns a pointer to a buffer, owned by this class, containing the preamble
+  // and its size.
+  std::tuple<char*, size_t> GetProtoPreamble();
+
+ private:
+  TracePacket(const TracePacket&) = delete;
+  TracePacket& operator=(const TracePacket&) = delete;
+
+  std::unique_ptr<ZeroCopyInputStream> CreateSlicedInputStream() const;
+
+  Slices slices_;     // Not owned.
+  size_t size_ = 0;   // SUM(slice.size for slice in slices_).
+  char preamble_[8];  // Deliberately not initialized.
+
+  // Remember to update the move operators and their unittest if adding new
+  // fields. ConsumerIPCClientImpl::OnReadBuffersResponse() relies on
+  // std::move(TracePacket) to clear up the moved-from instance.
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_TRACE_PACKET_H_
diff --git a/include/perfetto/tracing/core/trace_stats.h b/include/perfetto/tracing/core/trace_stats.h
new file mode 100644
index 0000000..8e5949c
--- /dev/null
+++ b/include/perfetto/tracing/core/trace_stats.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/common/trace_stats.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_CORE_TRACE_STATS_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_TRACE_STATS_H_
+
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {
+class TraceStats;
+class TraceStats_BufferStats;
+}  // namespace protos
+}  // namespace perfetto
+
+namespace perfetto {
+
+class PERFETTO_EXPORT TraceStats {
+ public:
+  class PERFETTO_EXPORT BufferStats {
+   public:
+    BufferStats();
+    ~BufferStats();
+    BufferStats(BufferStats&&) noexcept;
+    BufferStats& operator=(BufferStats&&);
+    BufferStats(const BufferStats&);
+    BufferStats& operator=(const BufferStats&);
+    bool operator==(const BufferStats&) const;
+    bool operator!=(const BufferStats& other) const {
+      return !(*this == other);
+    }
+
+    // Conversion methods from/to the corresponding protobuf types.
+    void FromProto(const perfetto::protos::TraceStats_BufferStats&);
+    void ToProto(perfetto::protos::TraceStats_BufferStats*) const;
+
+    uint64_t buffer_size() const { return buffer_size_; }
+    void set_buffer_size(uint64_t value) { buffer_size_ = value; }
+
+    uint64_t bytes_written() const { return bytes_written_; }
+    void set_bytes_written(uint64_t value) { bytes_written_ = value; }
+
+    uint64_t bytes_overwritten() const { return bytes_overwritten_; }
+    void set_bytes_overwritten(uint64_t value) { bytes_overwritten_ = value; }
+
+    uint64_t bytes_read() const { return bytes_read_; }
+    void set_bytes_read(uint64_t value) { bytes_read_ = value; }
+
+    uint64_t padding_bytes_written() const { return padding_bytes_written_; }
+    void set_padding_bytes_written(uint64_t value) {
+      padding_bytes_written_ = value;
+    }
+
+    uint64_t padding_bytes_cleared() const { return padding_bytes_cleared_; }
+    void set_padding_bytes_cleared(uint64_t value) {
+      padding_bytes_cleared_ = value;
+    }
+
+    uint64_t chunks_written() const { return chunks_written_; }
+    void set_chunks_written(uint64_t value) { chunks_written_ = value; }
+
+    uint64_t chunks_rewritten() const { return chunks_rewritten_; }
+    void set_chunks_rewritten(uint64_t value) { chunks_rewritten_ = value; }
+
+    uint64_t chunks_overwritten() const { return chunks_overwritten_; }
+    void set_chunks_overwritten(uint64_t value) { chunks_overwritten_ = value; }
+
+    uint64_t chunks_discarded() const { return chunks_discarded_; }
+    void set_chunks_discarded(uint64_t value) { chunks_discarded_ = value; }
+
+    uint64_t chunks_read() const { return chunks_read_; }
+    void set_chunks_read(uint64_t value) { chunks_read_ = value; }
+
+    uint64_t chunks_committed_out_of_order() const {
+      return chunks_committed_out_of_order_;
+    }
+    void set_chunks_committed_out_of_order(uint64_t value) {
+      chunks_committed_out_of_order_ = value;
+    }
+
+    uint64_t write_wrap_count() const { return write_wrap_count_; }
+    void set_write_wrap_count(uint64_t value) { write_wrap_count_ = value; }
+
+    uint64_t patches_succeeded() const { return patches_succeeded_; }
+    void set_patches_succeeded(uint64_t value) { patches_succeeded_ = value; }
+
+    uint64_t patches_failed() const { return patches_failed_; }
+    void set_patches_failed(uint64_t value) { patches_failed_ = value; }
+
+    uint64_t readaheads_succeeded() const { return readaheads_succeeded_; }
+    void set_readaheads_succeeded(uint64_t value) {
+      readaheads_succeeded_ = value;
+    }
+
+    uint64_t readaheads_failed() const { return readaheads_failed_; }
+    void set_readaheads_failed(uint64_t value) { readaheads_failed_ = value; }
+
+    uint64_t abi_violations() const { return abi_violations_; }
+    void set_abi_violations(uint64_t value) { abi_violations_ = value; }
+
+   private:
+    uint64_t buffer_size_ = {};
+    uint64_t bytes_written_ = {};
+    uint64_t bytes_overwritten_ = {};
+    uint64_t bytes_read_ = {};
+    uint64_t padding_bytes_written_ = {};
+    uint64_t padding_bytes_cleared_ = {};
+    uint64_t chunks_written_ = {};
+    uint64_t chunks_rewritten_ = {};
+    uint64_t chunks_overwritten_ = {};
+    uint64_t chunks_discarded_ = {};
+    uint64_t chunks_read_ = {};
+    uint64_t chunks_committed_out_of_order_ = {};
+    uint64_t write_wrap_count_ = {};
+    uint64_t patches_succeeded_ = {};
+    uint64_t patches_failed_ = {};
+    uint64_t readaheads_succeeded_ = {};
+    uint64_t readaheads_failed_ = {};
+    uint64_t abi_violations_ = {};
+
+    // Allows to preserve unknown protobuf fields for compatibility
+    // with future versions of .proto files.
+    std::string unknown_fields_;
+  };
+
+  TraceStats();
+  ~TraceStats();
+  TraceStats(TraceStats&&) noexcept;
+  TraceStats& operator=(TraceStats&&);
+  TraceStats(const TraceStats&);
+  TraceStats& operator=(const TraceStats&);
+  bool operator==(const TraceStats&) const;
+  bool operator!=(const TraceStats& other) const { return !(*this == other); }
+
+  // Conversion methods from/to the corresponding protobuf types.
+  void FromProto(const perfetto::protos::TraceStats&);
+  void ToProto(perfetto::protos::TraceStats*) const;
+
+  int buffer_stats_size() const {
+    return static_cast<int>(buffer_stats_.size());
+  }
+  const std::vector<BufferStats>& buffer_stats() const { return buffer_stats_; }
+  std::vector<BufferStats>* mutable_buffer_stats() { return &buffer_stats_; }
+  void clear_buffer_stats() { buffer_stats_.clear(); }
+  BufferStats* add_buffer_stats() {
+    buffer_stats_.emplace_back();
+    return &buffer_stats_.back();
+  }
+
+  uint32_t producers_connected() const { return producers_connected_; }
+  void set_producers_connected(uint32_t value) { producers_connected_ = value; }
+
+  uint64_t producers_seen() const { return producers_seen_; }
+  void set_producers_seen(uint64_t value) { producers_seen_ = value; }
+
+  uint32_t data_sources_registered() const { return data_sources_registered_; }
+  void set_data_sources_registered(uint32_t value) {
+    data_sources_registered_ = value;
+  }
+
+  uint64_t data_sources_seen() const { return data_sources_seen_; }
+  void set_data_sources_seen(uint64_t value) { data_sources_seen_ = value; }
+
+  uint32_t tracing_sessions() const { return tracing_sessions_; }
+  void set_tracing_sessions(uint32_t value) { tracing_sessions_ = value; }
+
+  uint32_t total_buffers() const { return total_buffers_; }
+  void set_total_buffers(uint32_t value) { total_buffers_ = value; }
+
+  uint64_t chunks_discarded() const { return chunks_discarded_; }
+  void set_chunks_discarded(uint64_t value) { chunks_discarded_ = value; }
+
+  uint64_t patches_discarded() const { return patches_discarded_; }
+  void set_patches_discarded(uint64_t value) { patches_discarded_ = value; }
+
+ private:
+  std::vector<BufferStats> buffer_stats_;
+  uint32_t producers_connected_ = {};
+  uint64_t producers_seen_ = {};
+  uint32_t data_sources_registered_ = {};
+  uint64_t data_sources_seen_ = {};
+  uint32_t tracing_sessions_ = {};
+  uint32_t total_buffers_ = {};
+  uint64_t chunks_discarded_ = {};
+  uint64_t patches_discarded_ = {};
+
+  // Allows to preserve unknown protobuf fields for compatibility
+  // with future versions of .proto files.
+  std::string unknown_fields_;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_TRACE_STATS_H_
diff --git a/include/perfetto/tracing/core/trace_writer.h b/include/perfetto/tracing/core/trace_writer.h
new file mode 100644
index 0000000..6cc76a6
--- /dev/null
+++ b/include/perfetto/tracing/core/trace_writer.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_TRACING_CORE_TRACE_WRITER_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_TRACE_WRITER_H_
+
+#include <functional>
+
+#include "perfetto/base/export.h"
+#include "perfetto/protozero/message_handle.h"
+#include "perfetto/tracing/core/basic_types.h"
+
+namespace perfetto {
+
+namespace protos {
+namespace pbzero {
+class TracePacket;
+}  // namespace pbzero
+}  // namespace protos
+
+// This is a single-thread write interface that allows to write protobufs
+// directly into the tracing shared buffer without making any copies.
+// It takes care of acquiring and releasing chunks from the
+// SharedMemoryArbiter and splitting protos over chunks.
+// The idea is that each data source creates one (or more) TraceWriter for each
+// thread it wants to write from. Each TraceWriter will get its own dedicated
+// chunk and will write into the shared buffer without any locking most of the
+// time. Locking will happen only when a chunk is exhausted and a new one is
+// acquired from the arbiter.
+
+// TODO: TraceWriter needs to keep the shared memory buffer alive (refcount?).
+// Otherwise if the shared memory buffer goes away (e.g. the Service crashes)
+// the TraceWriter will keep writing into unmapped memory.
+
+class PERFETTO_EXPORT TraceWriter {
+ public:
+  using TracePacketHandle =
+      protozero::MessageHandle<protos::pbzero::TracePacket>;
+
+  TraceWriter();
+  virtual ~TraceWriter();
+
+  // Returns a handle to the root proto message for the trace. The message will
+  // be finalized either by calling directly handle.Finalize() or by letting the
+  // handle go out of scope. The returned handle can be std::move()'d but cannot
+  // be used after either: (i) the TraceWriter instance is destroyed, (ii) a
+  // subsequence NewTracePacket() call is made on the same TraceWriter instance.
+  virtual TracePacketHandle NewTracePacket() = 0;
+
+  // Commits the data pending for the current chunk into the shared memory
+  // buffer and sends a CommitDataRequest() to the service. This can be called
+  // only if handle returned by NewTracePacket() has been destroyed (i.e. we
+  // cannot Flush() while writing a TracePacket).
+  // Note: Flush() also happens implicitly when destroying the TraceWriter.
+  // |callback| is an optional callback. When non-null it will request the
+  // service to ACK the flush and will be invoked after the service has
+  // ackwnoledged it. Please note that the callback might be NEVER INVOKED, for
+  // instance if the service crashes or the IPC connection is dropped. The
+  // callback should be used only by tests and best-effort features (logging).
+  // TODO(primiano): right now the |callback| will be called on the IPC thread.
+  // This is fine in the current single-thread scenario, but long-term
+  // trace_writer_impl.cc should be smarter and post it on the right thread.
+  virtual void Flush(std::function<void()> callback = {}) = 0;
+
+  virtual WriterID writer_id() const = 0;
+
+  // Bytes written since creation. Is not reset when new chunks are acquired.
+  virtual uint64_t written() const = 0;
+
+  // Set the id of the first chunk the writer will emit. Returns |false| if not
+  // implemented or if the first chunk was already emitted by the writer.
+  //
+  // StartupTraceWriter will call this if it committed buffered data on
+  // behalf of the TraceWriter.
+  virtual bool SetFirstChunkId(ChunkID);
+
+ private:
+  TraceWriter(const TraceWriter&) = delete;
+  TraceWriter& operator=(const TraceWriter&) = delete;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_TRACE_WRITER_H_
diff --git a/include/perfetto/tracing/core/tracing_service.h b/include/perfetto/tracing/core/tracing_service.h
new file mode 100644
index 0000000..5b12e11
--- /dev/null
+++ b/include/perfetto/tracing/core/tracing_service.h
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_TRACING_CORE_TRACING_SERVICE_H_
+#define INCLUDE_PERFETTO_TRACING_CORE_TRACING_SERVICE_H_
+
+#include <stdint.h>
+
+#include <functional>
+#include <memory>
+#include <vector>
+
+#include "perfetto/base/export.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/shared_memory.h"
+
+namespace perfetto {
+
+namespace base {
+class TaskRunner;
+}  // namespace base
+
+class CommitDataRequest;
+class Consumer;
+class DataSourceDescriptor;
+class Producer;
+class SharedMemoryArbiter;
+class TracingServiceState;
+class TraceConfig;
+class TraceWriter;
+
+// TODO: for the moment this assumes that all the calls happen on the same
+// thread/sequence. Not sure this will be the case long term in Chrome.
+
+// The API for the Producer port of the Service.
+// Subclassed by:
+// 1. The tracing_service_impl.cc business logic when returning it in response
+//    to the ConnectProducer() method.
+// 2. The transport layer (e.g., src/ipc) when the producer and
+//    the service don't talk locally but via some IPC mechanism.
+class PERFETTO_EXPORT ProducerEndpoint {
+ public:
+  virtual ~ProducerEndpoint();
+
+  // Called by the Producer to (un)register data sources. Data sources are
+  // identified by their name (i.e. DataSourceDescriptor.name)
+  virtual void RegisterDataSource(const DataSourceDescriptor&) = 0;
+  virtual void UnregisterDataSource(const std::string& name) = 0;
+
+  // Associate the trace writer with the given |writer_id| with
+  // |target_buffer|. The service may use this information to retrieve and
+  // copy uncommitted chunks written by the trace writer into its associated
+  // buffer, e.g. when a producer process crashes or when a flush is
+  // necessary.
+  virtual void RegisterTraceWriter(uint32_t writer_id,
+                                   uint32_t target_buffer) = 0;
+
+  // Remove the association of the trace writer previously created via
+  // RegisterTraceWriter.
+  virtual void UnregisterTraceWriter(uint32_t writer_id) = 0;
+
+  // Called by the Producer to signal that some pages in the shared memory
+  // buffer (shared between Service and Producer) have changed.
+  // When the Producer and the Service are hosted in the same process and
+  // hence potentially live on the same task runner, This method must call
+  // TracingServiceImpl's CommitData synchronously, without any PostTask()s,
+  // if on the same thread. This is to avoid a deadlock where the Producer
+  // exhausts its SMB and stalls waiting for the service to catch up with
+  // reads, but the Service never gets to that because it lives on the same
+  // thread.
+  using CommitDataCallback = std::function<void()>;
+  virtual void CommitData(const CommitDataRequest&,
+                          CommitDataCallback callback = {}) = 0;
+
+  virtual SharedMemory* shared_memory() const = 0;
+
+  // Size of shared memory buffer pages. It's always a multiple of 4K.
+  // See shared_memory_abi.h
+  virtual size_t shared_buffer_page_size_kb() const = 0;
+
+  // Creates a trace writer, which allows to create events, handling the
+  // underying shared memory buffer and signalling to the Service. This method
+  // is thread-safe but the returned object is not. A TraceWriter should be
+  // used only from a single thread, or the caller has to handle sequencing
+  // via a mutex or equivalent. This method can only be called if
+  // TracingService::ConnectProducer was called with |in_process=true|.
+  // Args:
+  // |target_buffer| is the target buffer ID where the data produced by the
+  // writer should be stored by the tracing service. This value is passed
+  // upon creation of the data source (StartDataSource()) in the
+  // DataSourceConfig.target_buffer().
+  virtual std::unique_ptr<TraceWriter> CreateTraceWriter(
+      BufferID target_buffer) = 0;
+
+  // If TracingService::ConnectProducer is called with |in_process=true|,
+  // this returns the producer's SharedMemoryArbiter which can be used
+  // to create TraceWriters which is able to directly commit chunks
+  // without going through an IPC layer.
+  virtual SharedMemoryArbiter* GetInProcessShmemArbiter() = 0;
+
+  // Called in response to a Producer::Flush(request_id) call after all data
+  // for the flush request has been committed.
+  virtual void NotifyFlushComplete(FlushRequestID) = 0;
+
+  // Called in response to one or more Producer::StartDataSource(),
+  // if the data source registered setting the flag
+  // DataSourceDescriptor.will_notify_on_start.
+  virtual void NotifyDataSourceStarted(DataSourceInstanceID) = 0;
+
+  // Called in response to one or more Producer::StopDataSource(),
+  // if the data source registered setting the flag
+  // DataSourceDescriptor.will_notify_on_stop.
+  virtual void NotifyDataSourceStopped(DataSourceInstanceID) = 0;
+
+  // This informs the service to activate any of these triggers if any tracing
+  // session was waiting for them.
+  virtual void ActivateTriggers(const std::vector<std::string>&) = 0;
+};  // class ProducerEndpoint.
+
+// The API for the Consumer port of the Service.
+// Subclassed by:
+// 1. The tracing_service_impl.cc business logic when returning it in response
+// to
+//    the ConnectConsumer() method.
+// 2. The transport layer (e.g., src/ipc) when the consumer and
+//    the service don't talk locally but via some IPC mechanism.
+class ConsumerEndpoint {
+ public:
+  virtual ~ConsumerEndpoint();
+
+  // Enables tracing with the given TraceConfig. The ScopedFile argument is
+  // used only when TraceConfig.write_into_file == true.
+  // If TraceConfig.deferred_start == true data sources are configured via
+  // SetupDataSource() but are not started until StartTracing() is called.
+  // This is to support pre-initialization and fast triggering of traces.
+  // The ScopedFile argument is used only when TraceConfig.write_into_file
+  // == true.
+  virtual void EnableTracing(const TraceConfig&,
+                             base::ScopedFile = base::ScopedFile()) = 0;
+
+  // Update the trace config of an existing tracing session; only a subset
+  // of options can be changed mid-session. Currently the only
+  // supported functionality is expanding the list of producer_name_filters()
+  // (or removing the filter entirely) for existing data sources.
+  virtual void ChangeTraceConfig(const TraceConfig&) = 0;
+
+  // Starts all data sources configured in the trace config. This is used only
+  // after calling EnableTracing() with TraceConfig.deferred_start=true.
+  // It's a no-op if called after a regular EnableTracing(), without setting
+  // deferred_start.
+  virtual void StartTracing() = 0;
+
+  virtual void DisableTracing() = 0;
+
+  // Requests all data sources to flush their data immediately and invokes the
+  // passed callback once all of them have acked the flush (in which case
+  // the callback argument |success| will be true) or |timeout_ms| are elapsed
+  // (in which case |success| will be false).
+  // If |timeout_ms| is 0 the TraceConfig's flush_timeout_ms is used, or,
+  // if that one is not set (or is set to 0), kDefaultFlushTimeoutMs (5s) is
+  // used.
+  using FlushCallback = std::function<void(bool /*success*/)>;
+  virtual void Flush(uint32_t timeout_ms, FlushCallback) = 0;
+
+  // Tracing data will be delivered invoking Consumer::OnTraceData().
+  virtual void ReadBuffers() = 0;
+
+  virtual void FreeBuffers() = 0;
+
+  // Will call OnDetach().
+  virtual void Detach(const std::string& key) = 0;
+
+  // Will call OnAttach().
+  virtual void Attach(const std::string& key) = 0;
+
+  // Will call OnTraceStats().
+  virtual void GetTraceStats() = 0;
+
+  enum ObservableEventType : uint32_t {
+    kNone = 0,
+    kDataSourceInstances = 1 << 0
+  };
+
+  // Start or stop observing events of selected types. |enabled_event_types|
+  // specifies the types of events to observe in a bitmask (see
+  // ObservableEventType enum). To disable observing, pass
+  // ObservableEventType::kNone. Will call OnObservableEvents() repeatedly
+  // whenever an event of an enabled ObservableEventType occurs.
+  //
+  // TODO(eseckler): Extend this to support producers & data sources.
+  virtual void ObserveEvents(uint32_t enabled_event_types) = 0;
+
+  // Used to obtain the list of connected data sources and other info about
+  // the tracing service.
+  using QueryServiceStateCallback =
+      std::function<void(bool success, const TracingServiceState&)>;
+  virtual void QueryServiceState(QueryServiceStateCallback) = 0;
+};  // class ConsumerEndpoint.
+
+// The public API of the tracing Service business logic.
+//
+// Exposed to:
+// 1. The transport layer (e.g., src/unix_rpc/unix_service_host.cc),
+//    which forwards commands received from a remote producer or consumer to
+//    the actual service implementation.
+// 2. Tests.
+//
+// Subclassed by:
+//   The service business logic in src/core/tracing_service_impl.cc.
+class PERFETTO_EXPORT TracingService {
+ public:
+  using ProducerEndpoint = perfetto::ProducerEndpoint;
+  using ConsumerEndpoint = perfetto::ConsumerEndpoint;
+
+  enum class ProducerSMBScrapingMode {
+    // Use service's default setting for SMB scraping. Currently, the default
+    // mode is to disable SMB scraping, but this may change in the future.
+    kDefault,
+
+    // Enable scraping of uncommitted chunks in producers' shared memory
+    // buffers.
+    kEnabled,
+
+    // Disable scraping of uncommitted chunks in producers' shared memory
+    // buffers.
+    kDisabled
+  };
+
+  // Implemented in src/core/tracing_service_impl.cc .
+  static std::unique_ptr<TracingService> CreateInstance(
+      std::unique_ptr<SharedMemory::Factory>,
+      base::TaskRunner*);
+
+  virtual ~TracingService();
+
+  // Connects a Producer instance and obtains a ProducerEndpoint, which is
+  // essentially a 1:1 channel between one Producer and the Service.
+  // The caller has to guarantee that the passed Producer will be alive as long
+  // as the returned ProducerEndpoint is alive.
+  // Both the passed Prodcer and the returned ProducerEndpint must live on the
+  // same task runner of the service, specifically:
+  // 1) The Service will call Producer::* methods on the Service's task runner.
+  // 2) The Producer should call ProducerEndpoint::* methods only on the
+  //    service's task runner, except for ProducerEndpoint::CreateTraceWriter(),
+  //    which can be called on any thread.
+  // To disconnect just destroy the returned ProducerEndpoint object. It is safe
+  // to destroy the Producer once the Producer::OnDisconnect() has been invoked.
+  // |uid| is the trusted user id of the producer process, used by the consumers
+  // for validating the origin of trace data.
+  // |shared_memory_size_hint_bytes| is an optional hint on the size of the
+  // shared memory buffer. The service can ignore the hint (e.g., if the hint
+  // is unreasonably large).
+  // |in_process| enables the ProducerEndpoint to manage its own shared memory
+  // and enables use of |ProducerEndpoint::CreateTraceWriter|.
+  // Can return null in the unlikely event that service has too many producers
+  // connected.
+  virtual std::unique_ptr<ProducerEndpoint> ConnectProducer(
+      Producer*,
+      uid_t uid,
+      const std::string& name,
+      size_t shared_memory_size_hint_bytes = 0,
+      bool in_process = false,
+      ProducerSMBScrapingMode smb_scraping_mode =
+          ProducerSMBScrapingMode::kDefault) = 0;
+
+  // Connects a Consumer instance and obtains a ConsumerEndpoint, which is
+  // essentially a 1:1 channel between one Consumer and the Service.
+  // The caller has to guarantee that the passed Consumer will be alive as long
+  // as the returned ConsumerEndpoint is alive.
+  // To disconnect just destroy the returned ConsumerEndpoint object. It is safe
+  // to destroy the Consumer once the Consumer::OnDisconnect() has been invoked.
+  virtual std::unique_ptr<ConsumerEndpoint> ConnectConsumer(Consumer*,
+                                                            uid_t) = 0;
+
+  // Enable/disable scraping of chunks in the shared memory buffer. If enabled,
+  // the service will copy uncommitted but non-empty chunks from the SMB when
+  // flushing (e.g. to handle unresponsive producers or producers unable to
+  // flush their active chunks), on producer disconnect (e.g. to recover data
+  // from crashed producers), and after disabling a tracing session (e.g. to
+  // gather data from producers that didn't stop their data sources in time).
+  //
+  // This feature is currently used by Chrome.
+  virtual void SetSMBScrapingEnabled(bool enabled) = 0;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_CORE_TRACING_SERVICE_H_
diff --git a/include/perfetto/tracing/core/tracing_service_state.h b/include/perfetto/tracing/core/tracing_service_state.h
index c9d74cd..f8a1373 100644
--- a/include/perfetto/tracing/core/tracing_service_state.h
+++ b/include/perfetto/tracing/core/tracing_service_state.h
@@ -14,15 +14,161 @@
  * limitations under the License.
  */
 
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/common/tracing_service_state.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
 
 #ifndef INCLUDE_PERFETTO_TRACING_CORE_TRACING_SERVICE_STATE_H_
 #define INCLUDE_PERFETTO_TRACING_CORE_TRACING_SERVICE_STATE_H_
 
-// This header exists only for legacy code that used to refer to the
-// checked-in auto-generated code, before it was moved to be a build-time gen
-// rule. DO NOT add any new includes to this header, instead directly include
-// the one below.
-// TODO(primiano): cleanup call-sites and remove this header.
-#include "protos/perfetto/common/tracing_service_state.gen.h"
+#include <stdint.h>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "perfetto/base/export.h"
+
+#include "perfetto/tracing/core/data_source_descriptor.h"
+
+// Forward declarations for protobuf types.
+namespace perfetto {
+namespace protos {
+class TracingServiceState;
+class TracingServiceState_Producer;
+class TracingServiceState_DataSource;
+class DataSourceDescriptor;
+}  // namespace protos
+}  // namespace perfetto
+
+namespace perfetto {
+
+class PERFETTO_EXPORT TracingServiceState {
+ public:
+  class PERFETTO_EXPORT Producer {
+   public:
+    Producer();
+    ~Producer();
+    Producer(Producer&&) noexcept;
+    Producer& operator=(Producer&&);
+    Producer(const Producer&);
+    Producer& operator=(const Producer&);
+    bool operator==(const Producer&) const;
+    bool operator!=(const Producer& other) const { return !(*this == other); }
+
+    // Conversion methods from/to the corresponding protobuf types.
+    void FromProto(const perfetto::protos::TracingServiceState_Producer&);
+    void ToProto(perfetto::protos::TracingServiceState_Producer*) const;
+
+    int32_t id() const { return id_; }
+    void set_id(int32_t value) { id_ = value; }
+
+    const std::string& name() const { return name_; }
+    void set_name(const std::string& value) { name_ = value; }
+
+    int32_t uid() const { return uid_; }
+    void set_uid(int32_t value) { uid_ = value; }
+
+   private:
+    int32_t id_ = {};
+    std::string name_ = {};
+    int32_t uid_ = {};
+
+    // Allows to preserve unknown protobuf fields for compatibility
+    // with future versions of .proto files.
+    std::string unknown_fields_;
+  };
+
+  class PERFETTO_EXPORT DataSource {
+   public:
+    DataSource();
+    ~DataSource();
+    DataSource(DataSource&&) noexcept;
+    DataSource& operator=(DataSource&&);
+    DataSource(const DataSource&);
+    DataSource& operator=(const DataSource&);
+    bool operator==(const DataSource&) const;
+    bool operator!=(const DataSource& other) const { return !(*this == other); }
+
+    // Conversion methods from/to the corresponding protobuf types.
+    void FromProto(const perfetto::protos::TracingServiceState_DataSource&);
+    void ToProto(perfetto::protos::TracingServiceState_DataSource*) const;
+
+    const DataSourceDescriptor& descriptor() const { return descriptor_; }
+    DataSourceDescriptor* mutable_descriptor() { return &descriptor_; }
+
+    int32_t producer_id() const { return producer_id_; }
+    void set_producer_id(int32_t value) { producer_id_ = value; }
+
+   private:
+    DataSourceDescriptor descriptor_ = {};
+    int32_t producer_id_ = {};
+
+    // Allows to preserve unknown protobuf fields for compatibility
+    // with future versions of .proto files.
+    std::string unknown_fields_;
+  };
+
+  TracingServiceState();
+  ~TracingServiceState();
+  TracingServiceState(TracingServiceState&&) noexcept;
+  TracingServiceState& operator=(TracingServiceState&&);
+  TracingServiceState(const TracingServiceState&);
+  TracingServiceState& operator=(const TracingServiceState&);
+  bool operator==(const TracingServiceState&) const;
+  bool operator!=(const TracingServiceState& other) const {
+    return !(*this == other);
+  }
+
+  // Conversion methods from/to the corresponding protobuf types.
+  void FromProto(const perfetto::protos::TracingServiceState&);
+  void ToProto(perfetto::protos::TracingServiceState*) const;
+
+  int producers_size() const { return static_cast<int>(producers_.size()); }
+  const std::vector<Producer>& producers() const { return producers_; }
+  std::vector<Producer>* mutable_producers() { return &producers_; }
+  void clear_producers() { producers_.clear(); }
+  Producer* add_producers() {
+    producers_.emplace_back();
+    return &producers_.back();
+  }
+
+  int data_sources_size() const {
+    return static_cast<int>(data_sources_.size());
+  }
+  const std::vector<DataSource>& data_sources() const { return data_sources_; }
+  std::vector<DataSource>* mutable_data_sources() { return &data_sources_; }
+  void clear_data_sources() { data_sources_.clear(); }
+  DataSource* add_data_sources() {
+    data_sources_.emplace_back();
+    return &data_sources_.back();
+  }
+
+  int32_t num_sessions() const { return num_sessions_; }
+  void set_num_sessions(int32_t value) { num_sessions_ = value; }
+
+  int32_t num_sessions_started() const { return num_sessions_started_; }
+  void set_num_sessions_started(int32_t value) {
+    num_sessions_started_ = value;
+  }
+
+ private:
+  std::vector<Producer> producers_;
+  std::vector<DataSource> data_sources_;
+  int32_t num_sessions_ = {};
+  int32_t num_sessions_started_ = {};
+
+  // Allows to preserve unknown protobuf fields for compatibility
+  // with future versions of .proto files.
+  std::string unknown_fields_;
+};
+
+}  // namespace perfetto
 
 #endif  // INCLUDE_PERFETTO_TRACING_CORE_TRACING_SERVICE_STATE_H_
diff --git a/include/perfetto/tracing/data_source.h b/include/perfetto/tracing/data_source.h
deleted file mode 100644
index dfbeaed..0000000
--- a/include/perfetto/tracing/data_source.h
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_
-#define INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_
-
-// This header contains the key class (DataSource) that a producer app should
-// override in order to create a custom data source that gets tracing Start/Stop
-// notifications and emits tracing data.
-
-#include <assert.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include <array>
-#include <atomic>
-#include <functional>
-#include <memory>
-#include <mutex>
-
-#include "perfetto/base/compiler.h"
-#include "perfetto/base/export.h"
-#include "perfetto/protozero/message.h"
-#include "perfetto/protozero/message_handle.h"
-#include "perfetto/tracing/buffer_exhausted_policy.h"
-#include "perfetto/tracing/internal/basic_types.h"
-#include "perfetto/tracing/internal/data_source_internal.h"
-#include "perfetto/tracing/internal/tracing_muxer.h"
-#include "perfetto/tracing/locked_handle.h"
-#include "perfetto/tracing/trace_writer_base.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-namespace perfetto {
-namespace internal {
-class TracingMuxerImpl;
-class TrackEventCategoryRegistry;
-template <typename, const internal::TrackEventCategoryRegistry*>
-class TrackEventDataSource;
-}  // namespace internal
-
-class DataSourceConfig;
-
-// Base class with the virtual methods to get start/stop notifications.
-// Embedders are supposed to derive the templated version below, not this one.
-class PERFETTO_EXPORT DataSourceBase {
- public:
-  virtual ~DataSourceBase();
-
-  // TODO(primiano): change the const& args below to be pointers instead. It
-  // makes it more awkward to handle output arguments and require mutable(s).
-  // This requires synchronizing a breaking API change for existing embedders.
-
-  // OnSetup() is invoked when tracing is configured. In most cases this happens
-  // just before starting the trace. In the case of deferred start (see
-  // deferred_start in trace_config.proto) start might happen later.
-  class SetupArgs {
-   public:
-    // This is valid only within the scope of the OnSetup() call and must not
-    // be retained.
-    const DataSourceConfig* config = nullptr;
-
-    // The index of this data source instance (0..kMaxDataSourceInstances - 1).
-    uint32_t internal_instance_index = 0;
-  };
-  virtual void OnSetup(const SetupArgs&);
-
-  class StartArgs {
-   public:
-    // The index of this data source instance (0..kMaxDataSourceInstances - 1).
-    uint32_t internal_instance_index = 0;
-  };
-  virtual void OnStart(const StartArgs&);
-
-  class StopArgs {
-   public:
-    virtual ~StopArgs();
-
-    // HandleAsynchronously() can optionally be called to defer the tracing
-    // session stop and write tracing data just before stopping.
-    // This function returns a closure that must be invoked after the last
-    // trace events have been emitted. The returned closure can be called from
-    // any thread. The caller also needs to explicitly call TraceContext.Flush()
-    // from the last Trace() lambda invocation because no other implicit flushes
-    // will happen after the stop signal.
-    // When this function is called, the tracing service will defer the stop of
-    // the tracing session until the returned closure is invoked.
-    // However, the caller cannot hang onto this closure for too long. The
-    // tracing service will forcefully stop the tracing session without waiting
-    // for pending producers after TraceConfig.data_source_stop_timeout_ms
-    // (default: 5s, can be overridden by Consumers when starting a trace).
-    // If the closure is called after this timeout an error will be logged and
-    // the trace data emitted will not be present in the trace. No other
-    // functional side effects (e.g. crashes or corruptions) will happen. In
-    // other words, it is fine to accidentally hold onto this closure for too
-    // long but, if that happens, some tracing data will be lost.
-    virtual std::function<void()> HandleStopAsynchronously() const = 0;
-
-    // The index of this data source instance (0..kMaxDataSourceInstances - 1).
-    uint32_t internal_instance_index = 0;
-  };
-  virtual void OnStop(const StopArgs&);
-};
-
-struct DefaultDataSourceTraits {
-  // |IncrementalStateType| can optionally be used store custom per-sequence
-  // incremental data (e.g., interning tables). It should have a Clear() method
-  // for when incremental state needs to be cleared. See
-  // TraceContext::GetIncrementalState().
-  using IncrementalStateType = void;
-
-  // Allows overriding what type of thread-local state configuration the data
-  // source uses. By default every data source gets independent thread-local
-  // state, which means every instance uses separate trace writers and
-  // incremental state even on the same thread. Some data sources (most notably
-  // the track event data source) want to share trace writers and incremental
-  // state on the same thread.
-  static internal::DataSourceThreadLocalState* GetDataSourceTLS(
-      internal::DataSourceStaticState* static_state,
-      internal::TracingTLS* root_tls) {
-    auto* ds_tls = &root_tls->data_sources_tls[static_state->index];
-    // The per-type TLS is either zero-initialized or must have been initialized
-    // for this specific data source type.
-    assert(!ds_tls->static_state ||
-           ds_tls->static_state->index == static_state->index);
-    return ds_tls;
-  }
-};
-
-// Templated base class meant to be derived by embedders to create a custom data
-// source. DataSourceType must be the type of the derived class itself, e.g.:
-// class MyDataSource : public DataSourceBase<MyDataSource> {...}.
-//
-// |DataSourceTraits| allows customizing the behavior of the data source. See
-// |DefaultDataSourceTraits|.
-template <typename DataSourceType,
-          typename DataSourceTraits = DefaultDataSourceTraits>
-class DataSource : public DataSourceBase {
-  struct DefaultTracePointTraits;
-
- public:
-  // The BufferExhaustedPolicy to use for TraceWriters of this DataSource.
-  // Override this in your DataSource class to change the default, which is to
-  // drop data on shared memory overruns.
-  constexpr static BufferExhaustedPolicy kBufferExhaustedPolicy =
-      BufferExhaustedPolicy::kDrop;
-
-  // Argument passed to the lambda function passed to Trace() (below).
-  class TraceContext {
-   public:
-    using TracePacketHandle =
-        ::protozero::MessageHandle<::perfetto::protos::pbzero::TracePacket>;
-
-    TraceContext(TraceContext&&) noexcept = default;
-    ~TraceContext() = default;
-
-    TracePacketHandle NewTracePacket() {
-      return tls_inst_->trace_writer->NewTracePacket();
-    }
-
-    // Forces a commit of the thread-local tracing data written so far to the
-    // service. This is almost never required (tracing data is periodically
-    // committed as trace pages are filled up) and has a non-negligible
-    // performance hit (requires an IPC + refresh of the current thread-local
-    // chunk). The only case when this should be used is when handling OnStop()
-    // asynchronously, to ensure sure that the data is committed before the
-    // Stop timeout expires.
-    // The TracePacketHandle obtained by the last NewTracePacket() call must be
-    // finalized before calling Flush() (either implicitly by going out of scope
-    // or by explicitly calling Finalize()).
-    // |cb| is an optional callback. When non-null it will request the
-    // service to ACK the flush and will be invoked on an internal thread after
-    // the service has  acknowledged it. The callback might be NEVER INVOKED if
-    // the service crashes or the IPC connection is dropped.
-    void Flush(std::function<void()> cb = {}) {
-      tls_inst_->trace_writer->Flush(cb);
-    }
-
-    // Returns a RAII handle to access the data source instance, guaranteeing
-    // that it won't be deleted on another thread (because of trace stopping)
-    // while accessing it from within the Trace() lambda.
-    // The returned handle can be invalid (nullptr) if tracing is stopped
-    // immediately before calling this. The caller is supposed to check for its
-    // validity before using it. After checking, the handle is guaranteed to
-    // remain valid until the handle goes out of scope.
-    LockedHandle<DataSourceType> GetDataSourceLocked() {
-      auto* internal_state = static_state_.TryGet(instance_index_);
-      if (!internal_state)
-        return LockedHandle<DataSourceType>();
-      return LockedHandle<DataSourceType>(
-          &internal_state->lock,
-          static_cast<DataSourceType*>(internal_state->data_source.get()));
-    }
-
-    typename DataSourceTraits::IncrementalStateType* GetIncrementalState() {
-      return reinterpret_cast<typename DataSourceTraits::IncrementalStateType*>(
-          tls_inst_->incremental_state.get());
-    }
-
-   private:
-    friend class DataSource;
-    template <typename, const internal::TrackEventCategoryRegistry*>
-    friend class internal::TrackEventDataSource;
-    TraceContext(internal::DataSourceInstanceThreadLocalState* tls_inst,
-                 uint32_t instance_index)
-        : tls_inst_(tls_inst), instance_index_(instance_index) {}
-    TraceContext(const TraceContext&) = delete;
-    TraceContext& operator=(const TraceContext&) = delete;
-
-    internal::DataSourceInstanceThreadLocalState* const tls_inst_;
-    uint32_t const instance_index_;
-  };
-
-  // The main tracing method. Tracing code should call this passing a lambda as
-  // argument, with the following signature: void(TraceContext).
-  // The lambda will be called synchronously (i.e., always before Trace()
-  // returns) only if tracing is enabled and the data source has been enabled in
-  // the tracing config.
-  // The lambda can be called more than once per Trace() call, in the case of
-  // concurrent tracing sessions (or even if the data source is instantiated
-  // twice within the same trace config).
-  template <typename Lambda>
-  static void Trace(Lambda tracing_fn) {
-    CallIfEnabled<DefaultTracePointTraits>([&tracing_fn](uint32_t instances) {
-      TraceWithInstances<DefaultTracePointTraits>(instances,
-                                                  std::move(tracing_fn));
-    });
-  }
-
-  // An efficient trace point guard for checking if this data source is active.
-  // |callback| is a function which will only be called if there are active
-  // instances. It is given an instance state parameter, which should be passed
-  // to TraceWithInstances() to actually record trace data.
-  template <typename Traits = DefaultTracePointTraits, typename Callback>
-  static void CallIfEnabled(Callback callback) PERFETTO_ALWAYS_INLINE {
-    // |instances| is a per-class bitmap that tells:
-    // 1. If the data source is enabled at all.
-    // 2. The index of the slot within |static_state_| that holds the instance
-    //    state. In turn this allows to map the data source to the tracing
-    //    session and buffers.
-    // memory_order_relaxed is okay because:
-    // - |instances| is re-read with an acquire barrier below if this succeeds.
-    // - The code between this point and the acquire-load is based on static
-    //    storage which has indefinite lifetime.
-    uint32_t instances =
-        Traits::GetActiveInstances()->load(std::memory_order_relaxed);
-
-    // This is the tracing fast-path. Bail out immediately if tracing is not
-    // enabled (or tracing is enabled but not for this data source).
-    if (PERFETTO_LIKELY(!instances))
-      return;
-    callback(instances);
-  }
-
-  // The "lower half" of a trace point which actually performs tracing after
-  // this data source has been determined to be active.
-  // |instances| must be the instance state value retrieved through
-  // CallIfEnabled().
-  // |tracing_fn| will be called to record trace data as in Trace().
-  //
-  // TODO(primiano): all the stuff below should be outlined from the trace
-  // point. Or at least we should have some compile-time traits like
-  // kOptimizeBinarySize / kOptimizeTracingLatency.
-  template <typename Traits = DefaultTracePointTraits, typename Lambda>
-  static void TraceWithInstances(uint32_t instances, Lambda tracing_fn) {
-    PERFETTO_DCHECK(instances);
-    constexpr auto kMaxDataSourceInstances = internal::kMaxDataSourceInstances;
-
-    // See tracing_muxer.h for the structure of the TLS.
-    auto* tracing_impl = internal::TracingMuxer::Get();
-    if (PERFETTO_UNLIKELY(!tls_state_))
-      tls_state_ = GetOrCreateDataSourceTLS(&static_state_);
-
-    // TracingTLS::generation is a global monotonic counter that is incremented
-    // every time a tracing session is stopped. We use that as a signal to force
-    // a slow-path garbage collection of all the trace writers for the current
-    // thread and to destroy the ones that belong to tracing sessions that have
-    // ended. This is to avoid having too many TraceWriter instances alive, each
-    // holding onto one chunk of the shared memory buffer.
-    // Rationale why memory_order_relaxed should be fine:
-    // - The TraceWriter object that we use is always constructed and destructed
-    //   on the current thread. There is no risk of accessing a half-initialized
-    //   TraceWriter (which would be really bad).
-    // - In the worst case, in the case of a race on the generation check, we
-    //   might end up using a TraceWriter for the same data source that belongs
-    //   to a stopped session. This is not really wrong, as we don't give any
-    //   guarantee on the global atomicity of the stop. In the worst case the
-    //   service will reject the data commit if this arrives too late.
-
-    if (PERFETTO_UNLIKELY(
-            tls_state_->root_tls->generation !=
-            tracing_impl->generation(std::memory_order_relaxed))) {
-      // Will update root_tls->generation.
-      tracing_impl->DestroyStoppedTraceWritersForCurrentThread();
-    }
-
-    for (uint32_t i = 0; i < kMaxDataSourceInstances; i++) {
-      internal::DataSourceState* instance_state =
-          static_state_.TryGetCached(instances, i);
-      if (!instance_state)
-        continue;
-
-      // Even if we passed the check above, the DataSourceInstance might be
-      // still destroyed concurrently while this code runs. The code below is
-      // designed to deal with such race, as follows:
-      // - We don't access the user-defined data source instance state. The only
-      //   bits of state we use are |backend_id| and |buffer_id|.
-      // - Beyond those two integers, we access only the TraceWriter here. The
-      //   TraceWriter is always safe because it lives on the TLS.
-      // - |instance_state| is backed by static storage, so the pointer is
-      //   always valid, even after the data source instance is destroyed.
-      // - In the case of a race-on-destruction, we'll still see the latest
-      //   backend_id and buffer_id and in the worst case keep trying writing
-      //   into the tracing shared memory buffer after stopped. But this isn't
-      //   really any worse than the case of the stop IPC being delayed by the
-      //   kernel scheduler. The tracing service is robust against data commit
-      //   attemps made after tracing is stopped.
-      // There is a theoretical race that would case the wrong behavior w.r.t
-      // writing data in the wrong buffer, but it's so rare that we ignore it:
-      // if the data source is stopped and started kMaxDataSourceInstances
-      // times (so that the same id is recycled) while we are in this function,
-      // we might end up reusing the old data source's backend_id and buffer_id
-      // for the new one, because we don't see the generation change past this
-      // point. But stopping and starting tracing (even once) takes so much
-      // handshaking to make this extremely unrealistic.
-
-      auto& tls_inst = tls_state_->per_instance[i];
-      if (PERFETTO_UNLIKELY(!tls_inst.trace_writer)) {
-        // Here we need an acquire barrier, which matches the release-store made
-        // by TracingMuxerImpl::SetupDataSource(), to ensure that the backend_id
-        // and buffer_id are consistent.
-        instances =
-            Traits::GetActiveInstances()->load(std::memory_order_acquire);
-        instance_state = static_state_.TryGetCached(instances, i);
-        if (!instance_state || !instance_state->trace_lambda_enabled)
-          return;
-        tls_inst.backend_id = instance_state->backend_id;
-        tls_inst.buffer_id = instance_state->buffer_id;
-        tls_inst.trace_writer = tracing_impl->CreateTraceWriter(
-            instance_state, DataSourceType::kBufferExhaustedPolicy);
-        CreateIncrementalState(
-            &tls_inst,
-            static_cast<typename DataSourceTraits::IncrementalStateType*>(
-                nullptr));
-
-        // Even in the case of out-of-IDs, SharedMemoryArbiterImpl returns a
-        // NullTraceWriter. The returned pointer should never be null.
-        assert(tls_inst.trace_writer);
-      }
-
-      tracing_fn(TraceContext(&tls_inst, i));
-    }
-  }
-
-  // Registers the data source on all tracing backends, including ones that
-  // connect after the registration. Doing so enables the data source to receive
-  // Setup/Start/Stop notifications and makes the Trace() method work when
-  // tracing is enabled and the data source is selected.
-  // This must be called after Tracing::Initialize().
-  // The caller must also use the DEFINE_DATA_SOURCE_STATIC_MEMBERS() macro
-  // documented below.
-  // Can return false to signal failure if attemping to register more than
-  // kMaxDataSources (32) data sources types.
-  static bool Register(const DataSourceDescriptor& descriptor) {
-    // Silences -Wunused-variable warning in case the trace method is not used
-    // by the translation unit that declares the data source.
-    (void)static_state_;
-    (void)tls_state_;
-
-    auto factory = [] {
-      return std::unique_ptr<DataSourceBase>(new DataSourceType());
-    };
-    auto* tracing_impl = internal::TracingMuxer::Get();
-    return tracing_impl->RegisterDataSource(descriptor, factory,
-                                            &static_state_);
-  }
-
- private:
-  // Traits for customizing the behavior of a specific trace point.
-  struct DefaultTracePointTraits {
-    // By default, every call to DataSource::Trace() will record trace events
-    // for every active instance of that data source. A single trace point can,
-    // however, use a custom set of enable flags for more fine grained control
-    // of when that trace point is active.
-    //
-    // DANGER: when doing this, the data source must use the appropriate memory
-    // fences when changing the state of the bitmap.
-    static constexpr std::atomic<uint32_t>* GetActiveInstances() {
-      return &static_state_.valid_instances;
-    }
-  };
-
-  // Create the user provided incremental state in the given thread-local
-  // storage. Note: The second parameter here is used to specialize the case
-  // where there is no incremental state type.
-  template <typename T>
-  static void CreateIncrementalState(
-      internal::DataSourceInstanceThreadLocalState* tls_inst,
-      const T*) {
-    PERFETTO_DCHECK(!tls_inst->incremental_state);
-    tls_inst->incremental_state =
-        internal::DataSourceInstanceThreadLocalState::IncrementalStatePointer(
-            reinterpret_cast<void*>(new T()),
-            [](void* p) { delete reinterpret_cast<T*>(p); });
-  }
-  static void CreateIncrementalState(
-      internal::DataSourceInstanceThreadLocalState*,
-      const void*) {}
-
-  // Note that the returned object is one per-thread per-data-source-type, NOT
-  // per data-source *instance*.
-  static internal::DataSourceThreadLocalState* GetOrCreateDataSourceTLS(
-      internal::DataSourceStaticState* static_state) {
-    auto* tracing_impl = internal::TracingMuxer::Get();
-    internal::TracingTLS* root_tls = tracing_impl->GetOrCreateTracingTLS();
-    internal::DataSourceThreadLocalState* ds_tls =
-        DataSourceTraits::GetDataSourceTLS(static_state, root_tls);
-    // We keep re-initializing as the initialization is idempotent and not worth
-    // the code for extra checks.
-    ds_tls->static_state = static_state;
-    assert(!ds_tls->root_tls || ds_tls->root_tls == root_tls);
-    ds_tls->root_tls = root_tls;
-    return ds_tls;
-  }
-
-  // Static state. Accessed by the static Trace() method fastpaths.
-  static internal::DataSourceStaticState static_state_;
-
-  // This TLS object is a cached raw pointer and has deliberately no destructor.
-  // The Platform implementation is supposed to create and manage the lifetime
-  // of the Platform::ThreadLocalObject and take care of destroying it.
-  // This is because non-POD thread_local variables have subtleties (global
-  // destructors) that we need to defer to the embedder. In chromium's platform
-  // implementation, for instance, the tls slot is implemented using
-  // chromium's base::ThreadLocalStorage.
-  static thread_local internal::DataSourceThreadLocalState* tls_state_;
-};
-
-template <typename T, typename D>
-internal::DataSourceStaticState DataSource<T, D>::static_state_;
-template <typename T, typename D>
-thread_local internal::DataSourceThreadLocalState* DataSource<T, D>::tls_state_;
-
-}  // namespace perfetto
-
-// Not needed -- only here for backwards compatibility.
-// TODO(skyostil): Remove this macro.
-#define PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(...)
-
-// The API client must use this in a translation unit. This is because it needs
-// to instantiate the static storage for the datasource to allow the fastpath
-// enabled check.
-#define PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(...)        \
-  template <>                                                  \
-  perfetto::internal::DataSourceStaticState                    \
-      perfetto::DataSource<__VA_ARGS__>::static_state_{};      \
-  template <>                                                  \
-  thread_local perfetto::internal::DataSourceThreadLocalState* \
-      perfetto::DataSource<__VA_ARGS__>::tls_state_ = nullptr
-
-#endif  // INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_
diff --git a/include/perfetto/tracing/internal/basic_types.h b/include/perfetto/tracing/internal/basic_types.h
deleted file mode 100644
index 81f5353..0000000
--- a/include/perfetto/tracing/internal/basic_types.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_INTERNAL_BASIC_TYPES_H_
-#define INCLUDE_PERFETTO_TRACING_INTERNAL_BASIC_TYPES_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-namespace perfetto {
-namespace internal {
-
-// A static_assert in tracing_muxer_impl.cc guarantees that this stays in sync
-// with the definition in tracing/core/basic_types.h
-using BufferId = uint16_t;
-
-// This is a direct index in the TracingMuxer::backends_ vector.
-// Backends are only added and never removed.
-using TracingBackendId = size_t;
-
-// Max numbers of data sources that can be registered in a process.
-constexpr size_t kMaxDataSources = 32;
-
-// Max instances for each data source type. This typically matches the
-// "max number of concurrent tracing sessions". However remember that a data
-// source can be instantiated more than once within one tracing session by
-// creating two entries for it in the trace config.
-constexpr size_t kMaxDataSourceInstances = 8;
-
-}  // namespace internal
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_BASIC_TYPES_H_
diff --git a/include/perfetto/tracing/internal/data_source_internal.h b/include/perfetto/tracing/internal/data_source_internal.h
deleted file mode 100644
index 8e06ee4..0000000
--- a/include/perfetto/tracing/internal/data_source_internal.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_INTERNAL_DATA_SOURCE_INTERNAL_H_
-#define INCLUDE_PERFETTO_TRACING_INTERNAL_DATA_SOURCE_INTERNAL_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <array>
-#include <atomic>
-#include <functional>
-#include <memory>
-#include <mutex>
-
-// No perfetto headers (other than tracing/api and protozero) should be here.
-#include "perfetto/tracing/buffer_exhausted_policy.h"
-#include "perfetto/tracing/internal/basic_types.h"
-#include "perfetto/tracing/trace_writer_base.h"
-
-namespace perfetto {
-
-class DataSourceBase;
-class TraceWriterBase;
-
-namespace internal {
-
-class TracingTLS;
-
-// This maintains the internal state of a data source instance that is used only
-// to implement the tracing mechanics and is not exposed to the API client.
-// There is one of these object per DataSource instance (up to
-// kMaxDataSourceInstances).
-struct DataSourceState {
-  // This boolean flag determines whether the DataSource::Trace() method should
-  // do something or be a no-op. This flag doesn't give the full guarantee
-  // that tracing data will be visible in the trace, it just makes it so that
-  // the client attemps writing trace data and interacting with the service.
-  // For instance, when a tracing session ends the service will reject data
-  // commits that arrive too late even if the producer hasn't received the stop
-  // IPC message.
-  // This flag is set right before calling OnStart() and cleared right before
-  // calling OnStop(), unless using HandleStopAsynchronously() (see comments
-  // in data_source.h).
-  // Keep this flag as the first field. This allows the compiler to directly
-  // dereference the DataSourceState* pointer in the trace fast-path without
-  // doing extra pointr arithmetic.
-  bool trace_lambda_enabled = false;
-
-  // The central buffer id that all TraceWriter(s) created by this data source
-  // must target.
-  BufferId buffer_id = 0;
-
-  // The index within TracingMuxerImpl.backends_. Practically it allows to
-  // lookup the Producer object, and hence the IPC channel, for this data
-  // source.
-  TracingBackendId backend_id = 0;
-
-  // The instance id as assigned by the tracing service. Note that because a
-  // process can be connected to >1 services, this ID is not globally unique but
-  // is only unique within the scope of its backend.
-  // Only the tuple (backend_id, data_source_instance_id) is globally unique.
-  uint64_t data_source_instance_id = 0;
-
-  // A hash of the trace config used by this instance. This is used to
-  // de-duplicate instances for data sources with identical names (e.g., track
-  // event).
-  uint64_t config_hash = 0;
-
-  // This lock is not held to implement Trace() and it's used only if the trace
-  // code wants to access its own data source state.
-  // This is to prevent that accessing the data source on an arbitrary embedder
-  // thread races with the internal IPC thread destroying the data source
-  // because of a end-of-tracing notification from the service.
-  std::recursive_mutex lock;
-  std::unique_ptr<DataSourceBase> data_source;
-};
-
-// This is to allow lazy-initialization and avoid static initializers and
-// at-exit destructors. All the entries are initialized via placement-new when
-// DataSource::Register() is called, see TracingMuxerImpl::RegisterDataSource().
-struct DataSourceStateStorage {
-  alignas(DataSourceState) char storage[sizeof(DataSourceState)]{};
-};
-
-// Per-DataSource-type global state.
-struct DataSourceStaticState {
-  // Unique index of the data source, assigned at registration time.
-  uint32_t index = kMaxDataSources;
-
-  // A bitmap that tells about the validity of each |instances| entry. When the
-  // i-th bit of the bitmap it's set, instances[i] is valid.
-  std::atomic<uint32_t> valid_instances{};
-  std::array<DataSourceStateStorage, kMaxDataSourceInstances> instances{};
-
-  // Can be used with a cached |valid_instances| bitmap.
-  DataSourceState* TryGetCached(uint32_t cached_bitmap, size_t n) {
-    return cached_bitmap & (1 << n)
-               ? reinterpret_cast<DataSourceState*>(&instances[n])
-               : nullptr;
-  }
-
-  DataSourceState* TryGet(size_t n) {
-    return TryGetCached(valid_instances.load(std::memory_order_acquire), n);
-  }
-
-  void CompilerAsserts() {
-    static_assert(sizeof(valid_instances.load()) * 8 >= kMaxDataSourceInstances,
-                  "kMaxDataSourceInstances too high");
-  }
-};
-
-// Per-DataSource-instance thread-local state.
-struct DataSourceInstanceThreadLocalState {
-  using IncrementalStatePointer = std::unique_ptr<void, void (*)(void*)>;
-
-  void Reset() {
-    trace_writer.reset();
-    incremental_state.reset();
-    backend_id = 0;
-    buffer_id = 0;
-  }
-
-  std::unique_ptr<TraceWriterBase> trace_writer;
-  IncrementalStatePointer incremental_state = {nullptr, [](void*) {}};
-  TracingBackendId backend_id;
-  BufferId buffer_id;
-};
-
-// Per-DataSource-type thread-local state.
-struct DataSourceThreadLocalState {
-  DataSourceStaticState* static_state = nullptr;
-
-  // Pointer to the parent tls object that holds us. Used to retrieve the
-  // generation, which is per-global-TLS and not per data-source.
-  TracingTLS* root_tls = nullptr;
-
-  // One entry per each data source instance.
-  std::array<DataSourceInstanceThreadLocalState, kMaxDataSourceInstances>
-      per_instance{};
-};
-
-}  // namespace internal
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_DATA_SOURCE_INTERNAL_H_
diff --git a/include/perfetto/tracing/internal/tracing_muxer.h b/include/perfetto/tracing/internal/tracing_muxer.h
deleted file mode 100644
index 4556ed3..0000000
--- a/include/perfetto/tracing/internal/tracing_muxer.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_MUXER_H_
-#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_MUXER_H_
-
-#include <atomic>
-#include <memory>
-
-#include "perfetto/base/export.h"
-#include "perfetto/tracing/internal/basic_types.h"
-#include "perfetto/tracing/internal/tracing_tls.h"
-#include "perfetto/tracing/platform.h"
-
-namespace perfetto {
-
-class DataSourceBase;
-class DataSourceDescriptor;
-class TraceWriterBase;
-struct TracingInitArgs;
-class TracingSession;
-
-namespace internal {
-
-struct DataSourceStaticState;
-
-// This class acts as a bridge between the public API methods and the
-// TracingBackend(s). It exposes a simplified view of the world to the API
-// methods, so that they don't have to care about the multiplicity of backends.
-// It handles all the bookkeeping to map data source instances and trace writers
-// to the various backends.
-// See tracing_muxer_impl.h for the full picture. This class contains only the
-// fewer fields and methods that need to be exposed to public/ headers. Fields
-// and methods that are required to implement them should go into
-// src/tracing/internal/tracing_muxer_impl.h instead: that one can pull in
-// perfetto headers outside of public, this one cannot.
-class PERFETTO_EXPORT TracingMuxer {
- public:
-  static TracingMuxer* Get() { return instance_; }
-
-  virtual ~TracingMuxer();
-
-  TracingTLS* GetOrCreateTracingTLS() {
-    return static_cast<TracingTLS*>(platform_->GetOrCreateThreadLocalObject());
-  }
-
-  // This method can fail and return false if trying to register more than
-  // kMaxDataSources types.
-  using DataSourceFactory = std::function<std::unique_ptr<DataSourceBase>()>;
-  virtual bool RegisterDataSource(const DataSourceDescriptor&,
-                                  DataSourceFactory,
-                                  DataSourceStaticState*) = 0;
-
-  // It identifies the right backend and forwards the call to it.
-  // The returned TraceWriter must be used within the same sequence (for most
-  // projects this means "same thread"). Alternatively the client needs to take
-  // care of using synchronization primitives to prevent concurrent accesses.
-  virtual std::unique_ptr<TraceWriterBase> CreateTraceWriter(
-      DataSourceState*,
-      BufferExhaustedPolicy buffer_exhausted_policy) = 0;
-
-  virtual void DestroyStoppedTraceWritersForCurrentThread() = 0;
-
-  uint32_t generation(std::memory_order ord) { return generation_.load(ord); }
-
- protected:
-  explicit TracingMuxer(Platform* platform) : platform_(platform) {}
-
-  static TracingMuxer* instance_;
-  Platform* const platform_ = nullptr;
-
-  // Incremented every time a data source is destroyed. See tracing_tls.h.
-  std::atomic<uint32_t> generation_{};
-};
-
-}  // namespace internal
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_MUXER_H_
diff --git a/include/perfetto/tracing/internal/tracing_tls.h b/include/perfetto/tracing/internal/tracing_tls.h
deleted file mode 100644
index 67f0637..0000000
--- a/include/perfetto/tracing/internal/tracing_tls.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_TLS_H_
-#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_TLS_H_
-
-#include <array>
-#include <memory>
-
-#include "perfetto/tracing/internal/basic_types.h"
-#include "perfetto/tracing/internal/data_source_internal.h"
-#include "perfetto/tracing/platform.h"
-
-namespace perfetto {
-
-class TraceWriterBase;
-
-namespace internal {
-
-// Organization of the thread-local storage
-// ----------------------------------------
-// First of all, remember the cardinality of the problem: at any point in time
-// there are M data sources registered (i.e. number of subclasses of DataSource)
-// and up to N concurrent instances for each data source, so up to M * N total
-// data source instances around.
-// Each data source instance can be accessed by T threads (no upper bound).
-// We can safely put hard limits both to M and N (i.e. say that we support at
-// most 32 data source types per process and up to 8 concurrent instances).
-//
-// We want to make it so from the Platform viewpoint, we use only one global
-// TLS object, so T instances in total, one per thread, regardless of M and N.
-// This allows to deal with at-thread-exit destruction only in one place, rather
-// than N, M or M * N.
-//
-// Visually:
-//                     [    Thread 1   ] [    Thread 2   ] [    Thread T   ]
-//                     +---------------+ +---------------+ +---------------+
-// Data source Foo     |               | |               | |               |
-//  Instance 1         |     TLS       | |     TLS       | |     TLS       |
-//  Instance 2         |    Object     | |    Object     | |    Object     |
-//  Instance 3         |               | |               | |               |
-//                     |               | |               | |               |
-// Data source Bar     |               | |               | |               |
-//  Instance 1         |               | |               | |               |
-//  Instance 2         |               | |               | |               |
-//                     +---------------+ +---------------+ +---------------+
-//
-// Each TLS Object is organized as an array of M DataSourceThreadLocalState.
-// Each DSTLS itself is an array of up to N per-instance objects.
-// The only per-instance object for now is the TraceWriter.
-// So for each data source, for each instance, for each thread we keep one
-// TraceWriter.
-// The lookup is O(1): Given the TLS object, the TraceWriter is just tls[M][N].
-class TracingTLS : public Platform::ThreadLocalObject {
- public:
-  ~TracingTLS() override;
-
-  // This is checked against TraceMuxerImpl's global generation counter to
-  // handle destruction of TraceWriter(s) that belong to data sources that
-  // have been stopped. When the two numbers diverge, a scan of all the
-  // thread-local TraceWriter(s) is issued.
-  uint32_t generation = 0;
-
-  // By default all data source instances have independent thread-local state
-  // (see above).
-  std::array<DataSourceThreadLocalState, kMaxDataSources> data_sources_tls{};
-
-  // Track event data sources, however, share the same thread-local state in
-  // order to be able to share trace writers and interning state across all
-  // track event categories.
-  DataSourceThreadLocalState track_event_tls{};
-};
-
-}  // namespace internal
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACING_TLS_H_
diff --git a/include/perfetto/tracing/internal/track_event_data_source.h b/include/perfetto/tracing/internal/track_event_data_source.h
deleted file mode 100644
index ec5e632..0000000
--- a/include/perfetto/tracing/internal/track_event_data_source.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_DATA_SOURCE_H_
-#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_DATA_SOURCE_H_
-
-#include "perfetto/base/compiler.h"
-#include "perfetto/protozero/message_handle.h"
-#include "perfetto/tracing/data_source.h"
-#include "perfetto/tracing/internal/track_event_internal.h"
-#include "perfetto/tracing/track_event_category_registry.h"
-#include "perfetto/tracing/track_event_context.h"
-#include "protos/perfetto/trace/track_event/track_event.pbzero.h"
-
-#include <unordered_map>
-
-namespace perfetto {
-namespace internal {
-
-struct TrackEventDataSourceTraits : public perfetto::DefaultDataSourceTraits {
-  using IncrementalStateType = TrackEventIncrementalState;
-
-  // Use a one shared TLS slot so that all track event data sources write into
-  // the same sequence and share interning dictionaries.
-  static DataSourceThreadLocalState* GetDataSourceTLS(DataSourceStaticState*,
-                                                      TracingTLS* root_tls) {
-    return &root_tls->track_event_tls;
-  }
-};
-
-// A generic track event data source which is instantiated once per track event
-// category namespace.
-template <typename DataSourceType, const TrackEventCategoryRegistry* Registry>
-class TrackEventDataSource
-    : public DataSource<DataSourceType, TrackEventDataSourceTraits> {
-  using Base = DataSource<DataSourceType, TrackEventDataSourceTraits>;
-
- public:
-  // DataSource implementation.
-  void OnSetup(const DataSourceBase::SetupArgs& args) override {
-    TrackEventInternal::EnableTracing(*Registry, *args.config,
-                                      args.internal_instance_index);
-  }
-
-  void OnStart(const DataSourceBase::StartArgs&) override {}
-
-  void OnStop(const DataSourceBase::StopArgs& args) override {
-    TrackEventInternal::DisableTracing(*Registry, args.internal_instance_index);
-  }
-
-  static void Flush() {
-    Base::template Trace([](typename Base::TraceContext ctx) { ctx.Flush(); });
-  }
-
-  // This is the inlined entrypoint for all track event trace points. It tries
-  // to be as lightweight as possible in terms of instructions and aims to
-  // compile down to an unlikely conditional jump to the actual trace writing
-  // function.
-  template <size_t CategoryIndex, typename Callback>
-  static void CallIfCategoryEnabled(Callback callback) PERFETTO_ALWAYS_INLINE {
-    Base::template CallIfEnabled<CategoryTracePointTraits<CategoryIndex>>(
-        [&callback](uint32_t instances) { callback(instances); });
-  }
-
-  // Once we've determined tracing to be enabled for this category, actually
-  // write a trace event. Outlined to avoid bloating code at the actual trace
-  // point.
-  // TODO(skyostil): Investigate whether this should be fully outlined to reduce
-  // binary size.
-  template <size_t CategoryIndex,
-            typename ArgumentFunction = void (*)(TrackEventContext)>
-  static void TraceForCategory(
-      uint32_t instances,
-      const char* event_name,
-      perfetto::protos::pbzero::TrackEvent::Type type,
-      ArgumentFunction arg_function = [](TrackEventContext) {
-      }) PERFETTO_NO_INLINE {
-    Base::template TraceWithInstances<CategoryTracePointTraits<CategoryIndex>>(
-        instances, [&](typename Base::TraceContext ctx) {
-          // TODO(skyostil): Intern categories at compile time.
-          arg_function(TrackEventInternal::WriteEvent(
-              ctx.tls_inst_->trace_writer.get(), ctx.GetIncrementalState(),
-              Registry->GetCategory(CategoryIndex)->name, event_name, type));
-        });
-  }
-
-  static bool Register() {
-    // Registration is performed out-of-line so users don't need to depend on
-    // DataSourceDescriptor C++ bindings.
-    return TrackEventInternal::Initialize(
-        [](const DataSourceDescriptor& dsd) { return Base::Register(dsd); });
-  }
-
- private:
-  // Each category has its own enabled/disabled state, stored in the category
-  // registry.
-  template <size_t CategoryIndex>
-  struct CategoryTracePointTraits {
-    static constexpr std::atomic<uint8_t>* GetActiveInstances() {
-      return Registry->GetCategoryState(CategoryIndex);
-    }
-  };
-};
-
-}  // namespace internal
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_DATA_SOURCE_H_
diff --git a/include/perfetto/tracing/internal/track_event_internal.h b/include/perfetto/tracing/internal/track_event_internal.h
deleted file mode 100644
index c303938..0000000
--- a/include/perfetto/tracing/internal/track_event_internal.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_INTERNAL_H_
-#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_INTERNAL_H_
-
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "perfetto/tracing/trace_writer_base.h"
-#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
-#include "protos/perfetto/trace/track_event/track_event.pbzero.h"
-
-#include <unordered_map>
-
-namespace perfetto {
-class DataSourceConfig;
-class DataSourceDescriptor;
-class TrackEventContext;
-
-namespace internal {
-class TrackEventCategoryRegistry;
-
-class BaseTrackEventInternedDataIndex {
- public:
-  virtual ~BaseTrackEventInternedDataIndex();
-
-#if PERFETTO_DCHECK_IS_ON()
-  const char* type_id_ = nullptr;
-#endif  // PERFETTO_DCHECK_IS_ON()
-};
-
-struct TrackEventIncrementalState {
-  static constexpr size_t kMaxInternedDataFields = 32;
-
-  bool was_cleared = true;
-
-  // A heap-allocated message for storing newly seen interned data while we are
-  // in the middle of writing a track event. When a track event wants to write
-  // new interned data into the trace, it is first serialized into this message
-  // and then flushed to the real trace in TrackEventContext when the packet
-  // ends. The message is cached here as a part of incremental state so that we
-  // can reuse the underlying buffer allocation for subsequently written
-  // interned data.
-  protozero::HeapBuffered<protos::pbzero::InternedData>
-      serialized_interned_data;
-
-  // In-memory indices for looking up interned data ids.
-  // For each intern-able field (up to a max of 32) we keep a dictionary of
-  // field-value -> interning-key. Depending on the type we either keep the full
-  // value or a hash of it (See track_event_interned_data_index.h)
-  using InternedDataIndex =
-      std::pair</* interned_data.proto field number */ size_t,
-                std::unique_ptr<BaseTrackEventInternedDataIndex>>;
-  std::array<InternedDataIndex, kMaxInternedDataFields> interned_data_indices =
-      {};
-};
-
-// The backend portion of the track event trace point implemention. Outlined to
-// a separate .cc file so it can be shared by different track event category
-// namespaces.
-class TrackEventInternal {
- public:
-  static bool Initialize(
-      bool (*register_data_source)(const DataSourceDescriptor&));
-
-  static void EnableTracing(const TrackEventCategoryRegistry& registry,
-                            const DataSourceConfig& config,
-                            uint32_t instance_index);
-  static void DisableTracing(const TrackEventCategoryRegistry& registry,
-                             uint32_t instance_index);
-
-  static perfetto::TrackEventContext WriteEvent(
-      TraceWriterBase*,
-      TrackEventIncrementalState*,
-      const char* category,
-      const char* name,
-      perfetto::protos::pbzero::TrackEvent::Type);
-};
-
-}  // namespace internal
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_INTERNAL_H_
diff --git a/include/perfetto/tracing/internal/track_event_macros.h b/include/perfetto/tracing/internal/track_event_macros.h
deleted file mode 100644
index 5ebf8a4..0000000
--- a/include/perfetto/tracing/internal/track_event_macros.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_MACROS_H_
-#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_MACROS_H_
-
-// This file contains underlying macros for the trace point track event
-// implementation. Perfetto API users typically don't need to use anything here
-// directly.
-
-#include "perfetto/base/compiler.h"
-#include "perfetto/tracing/internal/track_event_data_source.h"
-#include "perfetto/tracing/track_event_category_registry.h"
-
-// Defines data structures for backing a category registry.
-//
-// Each category has one enabled/disabled bit per possible data source instance.
-// The bits are packed, i.e., each byte holds the state for instances. To
-// improve cache locality, the bits for each instance are stored separately from
-// the names of the categories:
-//
-//   byte 0                      byte 1
-//   (inst0, inst1, ..., inst7), (inst0, inst1, ..., inst7)
-//
-#define PERFETTO_INTERNAL_DECLARE_CATEGORIES(...)                             \
-  namespace internal {                                                        \
-  constexpr ::perfetto::internal::TrackEventCategory kCategories[] = {        \
-      __VA_ARGS__};                                                           \
-  constexpr size_t kCategoryCount =                                           \
-      sizeof(kCategories) / sizeof(kCategories[0]);                           \
-  /* The per-instance enable/disable state per category */                    \
-  extern std::atomic<uint8_t> g_category_state_storage[kCategoryCount];       \
-  /* The category registry which mediates access to the above structures. */  \
-  /* The registry is used for two purposes: */                                \
-  /**/                                                                        \
-  /*    1) For looking up categories at build (constexpr) time. */            \
-  /*    2) For declaring the per-namespace TrackEvent data source. */         \
-  /**/                                                                        \
-  /* Because usage #1 requires a constexpr type and usage #2 requires an */   \
-  /* extern type (to avoid declaring a type based on a translation-unit */    \
-  /* variable), we need two separate copies of the registry with different */ \
-  /* storage specifiers. */                                                   \
-  /**/                                                                        \
-  /* TODO(skyostil): Unify these using a C++17 inline constexpr variable. */  \
-  constexpr ::perfetto::internal::TrackEventCategoryRegistry                  \
-      kConstExprCategoryRegistry(kCategoryCount,                              \
-                                 &kCategories[0],                             \
-                                 &g_category_state_storage[0]);               \
-  extern const ::perfetto::internal::TrackEventCategoryRegistry               \
-      kCategoryRegistry;                                                      \
-  }  // namespace internal
-
-// In a .cc file, declares storage for each category's runtime state.
-#define PERFETTO_INTERNAL_CATEGORY_STORAGE()                     \
-  namespace internal {                                           \
-  std::atomic<uint8_t> g_category_state_storage[kCategoryCount]; \
-  constexpr ::perfetto::internal::TrackEventCategoryRegistry     \
-      kCategoryRegistry(kCategoryCount,                          \
-                        &kCategories[0],                         \
-                        &g_category_state_storage[0]);           \
-  }  // namespace internal
-
-// Defines the TrackEvent data source for the current track event namespace.
-#define PERFETTO_INTERNAL_DECLARE_TRACK_EVENT_DATA_SOURCE()              \
-  struct TrackEvent : public ::perfetto::internal::TrackEventDataSource< \
-                          TrackEvent, &internal::kCategoryRegistry> {}
-
-// At compile time, turns a category name represented by a static string into an
-// index into the current category registry. A build error will be generated if
-// the category hasn't been registered. See PERFETTO_DEFINE_CATEGORIES.
-#define PERFETTO_GET_CATEGORY_INDEX(category)                                \
-  ::perfetto::internal::TrackEventCategoryRegistry::Validate<                \
-      ::PERFETTO_TRACK_EVENT_NAMESPACE::internal::kConstExprCategoryRegistry \
-          .Find(category)>()
-
-// Efficiently determines whether tracing is enabled for the given category, and
-// if so, emits one trace event with the given arguments.
-#define PERFETTO_INTERNAL_TRACK_EVENT(category, ...)                      \
-  ::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::CallIfCategoryEnabled<    \
-      PERFETTO_GET_CATEGORY_INDEX(category)>([&](uint32_t instances) {    \
-    ::PERFETTO_TRACK_EVENT_NAMESPACE::TrackEvent::TraceForCategory<       \
-        PERFETTO_GET_CATEGORY_INDEX(category)>(instances, ##__VA_ARGS__); \
-  })
-
-#endif  // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_MACROS_H_
diff --git a/include/perfetto/tracing/ipc/BUILD.gn b/include/perfetto/tracing/ipc/BUILD.gn
new file mode 100644
index 0000000..1f42bff
--- /dev/null
+++ b/include/perfetto/tracing/ipc/BUILD.gn
@@ -0,0 +1,25 @@
+# Copyright (C) 2017 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.
+
+source_set("ipc") {
+  public_deps = [
+    "../../base",
+    "../core",
+  ]
+  sources = [
+    "consumer_ipc_client.h",
+    "producer_ipc_client.h",
+    "service_ipc_host.h",
+  ]
+}
diff --git a/include/perfetto/tracing/ipc/consumer_ipc_client.h b/include/perfetto/tracing/ipc/consumer_ipc_client.h
new file mode 100644
index 0000000..85ca354
--- /dev/null
+++ b/include/perfetto/tracing/ipc/consumer_ipc_client.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_TRACING_IPC_CONSUMER_IPC_CLIENT_H_
+#define INCLUDE_PERFETTO_TRACING_IPC_CONSUMER_IPC_CLIENT_H_
+
+#include <memory>
+#include <string>
+
+#include "perfetto/tracing/core/tracing_service.h"
+
+namespace perfetto {
+
+class Consumer;
+
+// Allows to connect to a remote Service through a UNIX domain socket.
+// Exposed to:
+//   Consumer(s) of the tracing library.
+// Implemented in:
+//   src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
+class ConsumerIPCClient {
+ public:
+  // Connects to the producer port of the Service listening on the given
+  // |service_sock_name|. If the connection is successful, the OnConnect()
+  // method will be invoked asynchronously on the passed Consumer interface.
+  // If the connection fails, OnDisconnect() will be invoked instead.
+  // The returned ConsumerEndpoint serves also to delimit the scope of the
+  // callbacks invoked on the Consumer interface: no more Consumer callbacks are
+  // invoked immediately after its destruction and any pending callback will be
+  // dropped.
+  static std::unique_ptr<TracingService::ConsumerEndpoint>
+  Connect(const char* service_sock_name, Consumer*, base::TaskRunner*);
+
+ protected:
+  ConsumerIPCClient() = delete;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_IPC_CONSUMER_IPC_CLIENT_H_
diff --git a/include/perfetto/tracing/ipc/producer_ipc_client.h b/include/perfetto/tracing/ipc/producer_ipc_client.h
new file mode 100644
index 0000000..533c97f
--- /dev/null
+++ b/include/perfetto/tracing/ipc/producer_ipc_client.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_TRACING_IPC_PRODUCER_IPC_CLIENT_H_
+#define INCLUDE_PERFETTO_TRACING_IPC_PRODUCER_IPC_CLIENT_H_
+
+#include <memory>
+#include <string>
+
+#include "perfetto/tracing/core/tracing_service.h"
+
+namespace perfetto {
+
+class Producer;
+
+// Allows to connect to a remote Service through a UNIX domain socket.
+// Exposed to:
+//   Producer(s) of the tracing library.
+// Implemented in:
+//   src/tracing/ipc/producer/producer_ipc_client_impl.cc
+class ProducerIPCClient {
+ public:
+  // Connects to the producer port of the Service listening on the given
+  // |service_sock_name|. If the connection is successful, the OnConnect()
+  // method will be invoked asynchronously on the passed Producer interface.
+  // If the connection fails, OnDisconnect() will be invoked instead.
+  // The returned ProducerEndpoint serves also to delimit the scope of the
+  // callbacks invoked on the Producer interface: no more Producer callbacks are
+  // invoked immediately after its destruction and any pending callback will be
+  // dropped.
+  static std::unique_ptr<TracingService::ProducerEndpoint> Connect(
+      const char* service_sock_name,
+      Producer*,
+      const std::string& producer_name,
+      base::TaskRunner*,
+      TracingService::ProducerSMBScrapingMode smb_scraping_mode =
+          TracingService::ProducerSMBScrapingMode::kDefault);
+
+ protected:
+  ProducerIPCClient() = delete;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_IPC_PRODUCER_IPC_CLIENT_H_
diff --git a/include/perfetto/tracing/ipc/service_ipc_host.h b/include/perfetto/tracing/ipc/service_ipc_host.h
new file mode 100644
index 0000000..eeec568
--- /dev/null
+++ b/include/perfetto/tracing/ipc/service_ipc_host.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2017 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 INCLUDE_PERFETTO_TRACING_IPC_SERVICE_IPC_HOST_H_
+#define INCLUDE_PERFETTO_TRACING_IPC_SERVICE_IPC_HOST_H_
+
+#include <memory>
+
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/tracing/core/basic_types.h"
+
+namespace perfetto {
+namespace base {
+class TaskRunner;
+}  // namespace base.
+
+class TracingService;
+
+// Creates an instance of the service (business logic + UNIX socket transport).
+// Exposed to:
+//   The code in the tracing client that will host the service e.g., traced.
+// Implemented in:
+//   src/tracing/ipc/service/service_ipc_host_impl.cc
+class ServiceIPCHost {
+ public:
+  static std::unique_ptr<ServiceIPCHost> CreateInstance(base::TaskRunner*);
+  virtual ~ServiceIPCHost();
+
+  // Start listening on the Producer & Consumer ports. Returns false in case of
+  // failure (e.g., something else is listening on |socket_name|).
+  virtual bool Start(const char* producer_socket_name,
+                     const char* consumer_socket_name) = 0;
+
+  // Like the above, but takes two file descriptors to already bound sockets.
+  // This is used when building as part of the Android tree, where init opens
+  // and binds the socket beore exec()-ing us.
+  virtual bool Start(base::ScopedFile producer_socket_fd,
+                     base::ScopedFile consumer_socket_fd) = 0;
+
+  virtual TracingService* service() const = 0;
+
+ protected:
+  ServiceIPCHost();
+
+ private:
+  ServiceIPCHost(const ServiceIPCHost&) = delete;
+  ServiceIPCHost& operator=(const ServiceIPCHost&) = delete;
+};
+
+}  // namespace perfetto
+
+#endif  // INCLUDE_PERFETTO_TRACING_IPC_SERVICE_IPC_HOST_H_
diff --git a/include/perfetto/tracing/locked_handle.h b/include/perfetto/tracing/locked_handle.h
deleted file mode 100644
index 3d4c461..0000000
--- a/include/perfetto/tracing/locked_handle.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_LOCKED_HANDLE_H_
-#define INCLUDE_PERFETTO_TRACING_LOCKED_HANDLE_H_
-
-#include <mutex>
-
-namespace perfetto {
-
-// This is used for GetDataSourceLocked(), in the (rare) case where the
-// tracing code wants to access the state of its data source from the Trace()
-// method.
-template <typename T>
-class LockedHandle {
- public:
-  LockedHandle(std::recursive_mutex* mtx, T* obj) : lock_(*mtx), obj_(obj) {}
-  LockedHandle() = default;  // For the invalid case.
-  LockedHandle(LockedHandle&&) = default;
-  LockedHandle& operator=(LockedHandle&&) = default;
-
-  bool valid() const { return obj_; }
-  explicit operator bool() const { return valid(); }
-
-  T* operator->() {
-    assert(valid());
-    return obj_;
-  }
-
-  T& operator*() { return *(this->operator->()); }
-
- private:
-  std::unique_lock<std::recursive_mutex> lock_;
-  T* obj_ = nullptr;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_LOCKED_HANDLE_H_
diff --git a/include/perfetto/tracing/platform.h b/include/perfetto/tracing/platform.h
deleted file mode 100644
index 8ba4dd5..0000000
--- a/include/perfetto/tracing/platform.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_PLATFORM_H_
-#define INCLUDE_PERFETTO_TRACING_PLATFORM_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <functional>
-#include <memory>
-
-#include "perfetto/base/export.h"
-
-namespace perfetto {
-
-namespace base {
-class TaskRunner;
-}  // namespace base
-
-// This abstract class is used to abstract dependencies on platform-specific
-// primitives that cannot be implemented by the perfetto codebase and must be
-// provided or overridden by the embedder.
-// This is, for instance, for cases where we want to use some particular
-// base:: class in Chrome and provide instead POSIX fallbacks for other
-// embedders.
-
-// Base class for thread-local objects. This is to get a basic object vtable and
-// delegate destruction to the embedder. See Platform::CreateThreadLocalObject.
-class PlatformThreadLocalObject {
- public:
-  // Implemented by perfetto internal code. The embedder must call this when
-  // implementing GetOrCreateThreadLocalObject() to create an instance for the
-  // first time on each thread.
-  static std::unique_ptr<PlatformThreadLocalObject> CreateInstance();
-  virtual ~PlatformThreadLocalObject();
-};
-
-class PERFETTO_EXPORT Platform {
- public:
-  // Embedders can use this unless they have custom needs (e.g. Chrome wanting
-  // to use its own base class for TLS).
-  static Platform* GetDefaultPlatform();
-
-  virtual ~Platform();
-
-  // Creates a thread-local object. The embedder must:
-  // - Create an instance per-thread calling ThreadLocalObject::CreateInstance.
-  // - Own the lifetime of the returned object as long as the thread is alive.
-  // - Destroy it when the thread exits.
-  // Perfetto requires only one thread-local object overall (obviously, one
-  // instance per-thread) from the embedder.
-  using ThreadLocalObject = ::perfetto::PlatformThreadLocalObject;
-  virtual ThreadLocalObject* GetOrCreateThreadLocalObject() = 0;
-
-  // Creates a sequenced task runner. The easiest implementation is to create
-  // a new thread (e.g. use base::ThreadTaskRunner) but this can also be
-  // implemented in some more clever way (e.g. using chromiums's scheduler).
-  struct CreateTaskRunnerArgs {};
-  virtual std::unique_ptr<base::TaskRunner> CreateTaskRunner(
-      const CreateTaskRunnerArgs&) = 0;
-
-  // Used to derive the producer name. Mostly relevant when using the
-  // kSystemBackend mode. It can be an arbitrary string when using the
-  // in-process mode.
-  virtual std::string GetCurrentProcessName() = 0;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_PLATFORM_H_
diff --git a/include/perfetto/tracing/trace_writer_base.h b/include/perfetto/tracing/trace_writer_base.h
deleted file mode 100644
index 2d95668..0000000
--- a/include/perfetto/tracing/trace_writer_base.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_TRACE_WRITER_BASE_H_
-#define INCLUDE_PERFETTO_TRACING_TRACE_WRITER_BASE_H_
-
-#include "perfetto/protozero/message_handle.h"
-
-namespace perfetto {
-
-namespace protos {
-namespace pbzero {
-class TracePacket;
-}  // namespace pbzero
-}  // namespace protos
-
-// The bare-minimum subset of the TraceWriter interface that is exposed as a
-// fully public API.
-// See comments in /include/perfetto/ext/tracing/core/trace_writer.h.
-class TraceWriterBase {
- public:
-  virtual ~TraceWriterBase();
-
-  virtual protozero::MessageHandle<protos::pbzero::TracePacket>
-  NewTracePacket() = 0;
-
-  virtual void Flush(std::function<void()> callback = {}) = 0;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_TRACE_WRITER_BASE_H_
diff --git a/include/perfetto/tracing/tracing.h b/include/perfetto/tracing/tracing.h
deleted file mode 100644
index 5aa0028..0000000
--- a/include/perfetto/tracing/tracing.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_TRACING_H_
-#define INCLUDE_PERFETTO_TRACING_TRACING_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <functional>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "perfetto/base/export.h"
-#include "perfetto/base/logging.h"
-
-namespace perfetto {
-
-class TracingBackend;
-class Platform;
-class TraceConfig;
-class TracingSession;  // Declared below.
-
-enum BackendType : uint32_t {
-  kUnspecifiedBackend = 0,
-
-  // Connects to a previously-initialized perfetto tracing backend for
-  // in-process. If the in-process backend has not been previously initialized
-  // it will do so and create the tracing service on a dedicated thread.
-  kInProcessBackend = 1 << 0,
-
-  // Connects to the system tracing service (e.g. on Linux/Android/Mac uses a
-  // named UNIX socket).
-  kSystemBackend = 1 << 1,
-
-  // Used to provide a custom IPC transport to connect to the service.
-  // TracingInitArgs::custom_backend must be non-null and point to an
-  // indefinitely lived instance.
-  kCustomBackend = 1 << 2,
-};
-
-struct TracingInitArgs {
-  uint32_t backends = 0;                     // One or more BackendFlags.
-  TracingBackend* custom_backend = nullptr;  // [Optional].
-
-  // [Optional] Platform implementation. It allows the embedder to take control
-  // of platform-specific bits like thread creation and TLS slot handling. If
-  // not set it will use Platform::GetDefaultPlatform().
-  Platform* platform = nullptr;
-
-  // [Optional] Tune the size of the shared memory buffer between the current
-  // process and the service backend(s). This is a trade-off between memory
-  // footprint and the ability to sustain bursts of trace writes (see comments
-  // in shared_memory_abi.h).
-  // If set, the value must be a multiple of 4KB. The value can be ignored if
-  // larger than kMaxShmSize (32MB) or not a multiple of 4KB.
-  uint32_t shmem_size_hint_kb = 0;
-
-  // [Optional] Specifies the preferred size of each page in the shmem buffer.
-  // This is a trade-off between IPC overhead and fragmentation/efficiency of
-  // the shmem buffer in presence of multiple writer threads.
-  // Must be one of [4, 8, 16, 32].
-  uint32_t shmem_page_size_hint_kb = 0;
-
- protected:
-  friend class Tracing;
-  bool dcheck_is_on_ = PERFETTO_DCHECK_IS_ON();
-};
-
-// The entry-point for using perfetto.
-class PERFETTO_EXPORT Tracing {
- public:
-  // Initializes Perfetto with the given backends in the calling process and/or
-  // with a user-provided backend. Can only be called once.
-  static void Initialize(const TracingInitArgs&);
-
-  // Start a new tracing session using the given tracing backend. Use
-  // |kUnspecifiedBackend| to select an available backend automatically.
-  // For the moment this can be used only when initializing tracing in
-  // kInProcess mode. For the system mode use the 'bin/perfetto' cmdline client.
-  static std::unique_ptr<TracingSession> NewTrace(
-      BackendType = kUnspecifiedBackend);
-
- private:
-  Tracing() = delete;
-};
-
-class PERFETTO_EXPORT TracingSession {
- public:
-  virtual ~TracingSession();
-
-  // Configure the session passing the trace config.
-  // If a writable file handle is given through |fd|, the trace will
-  // automatically written to that file. Otherwise you should call ReadTrace()
-  // to retrieve the trace data. This call does not take ownership of |fd|.
-  // TODO(primiano): add an error callback.
-  virtual void Setup(const TraceConfig&, int fd = -1) = 0;
-
-  // Enable tracing asynchronously.
-  virtual void Start() = 0;
-
-  // Enable tracing and block until tracing has started. Note that if data
-  // sources are registered after this call was initiated, the call may return
-  // before the additional data sources have started. Also, if other producers
-  // (e.g., with system-wide tracing) have registered data sources without start
-  // notification support, this call may return before those data sources have
-  // started.
-  virtual void StartBlocking() = 0;
-
-  // Disable tracing asynchronously.
-  // Use SetOnStopCallback() to get a notification when the tracing session is
-  // fully stopped and all data sources have acked.
-  virtual void Stop() = 0;
-
-  // Disable tracing and block until tracing has stopped.
-  virtual void StopBlocking() = 0;
-
-  // This callback will be invoked when tracing is disabled.
-  // This can happen either when explicitly calling TracingSession.Stop() or
-  // when the trace reaches its |duration_ms| time limit.
-  // This callback will be invoked on an internal perfetto thread.
-  virtual void SetOnStopCallback(std::function<void()>) = 0;
-
-  // Struct passed as argument to the callback passed to ReadTrace().
-  // [data, size] is guaranteed to contain 1 or more full trace packets, which
-  // can be decoded using trace.proto. No partial or truncated packets are
-  // exposed. If the trace is empty this returns a zero-sized nullptr with
-  // |has_more| == true to signal EOF.
-  // This callback will be invoked on an internal perfetto thread.
-  struct ReadTraceCallbackArgs {
-    const char* data = nullptr;
-    size_t size = 0;
-
-    // When false, this will be the last invocation of the callback for this
-    // read cycle.
-    bool has_more = false;
-  };
-
-  // Reads back the trace data (raw protobuf-encoded bytes) asynchronously.
-  // Can be called at any point during the trace, typically but not necessarily,
-  // after stopping. Reading the trace data is a destructive operation w.r.t.
-  // contents of the trace buffer and is not idempotent.
-  // A single ReadTrace() call can yield >1 callback invocations, until
-  // |has_more| is true.
-  using ReadTraceCallback = std::function<void(ReadTraceCallbackArgs)>;
-  virtual void ReadTrace(ReadTraceCallback) = 0;
-
-  // Synchronous version of ReadTrace(). It blocks the calling thread until all
-  // the trace contents are read. This is slow and inefficient (involves more
-  // copies) and is mainly intended for testing.
-  std::vector<char> ReadTraceBlocking();
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_TRACING_H_
diff --git a/include/perfetto/tracing/tracing_backend.h b/include/perfetto/tracing/tracing_backend.h
deleted file mode 100644
index 745778f..0000000
--- a/include/perfetto/tracing/tracing_backend.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_TRACING_BACKEND_H_
-#define INCLUDE_PERFETTO_TRACING_TRACING_BACKEND_H_
-
-#include <memory>
-#include <string>
-
-// The embedder can (but doesn't have to) extend the TracingBackend class and
-// pass as an argument to Tracing::Initialize(kCustomBackend) to override the
-// way to reach the service. This is for peculiar cases where the embedder has
-// a multi-process architecture and wants to override the IPC transport. The
-// real use-case for this at the time of writing is chromium (+ Mojo IPC).
-// Extending this class requires depending on the full set of perfetto headers
-// (not just /public/). Contact the team before doing so as the non-public
-// headers are not guaranteed to be API stable.
-
-namespace perfetto {
-
-namespace base {
-class TaskRunner;
-}
-
-// These classes are declared in headers outside of /public/.
-class Consumer;
-class ConsumerEndpoint;
-class Producer;
-class ProducerEndpoint;
-
-class TracingBackend {
- public:
-  virtual ~TracingBackend();
-
-  // Connects a Producer instance and obtains a ProducerEndpoint, which is
-  // essentially a 1:1 channel between one Producer and the Service.
-  // To disconnect just destroy the returned endpoint object. It is safe to
-  // destroy the Producer once Producer::OnDisconnect() has been invoked.
-  struct ConnectProducerArgs {
-    std::string producer_name;
-
-    // The Producer object that will receive calls like Start/StopDataSource().
-    // The caller has to guarantee that this object is valid as long as the
-    // returned ProducerEndpoint is alive.
-    Producer* producer = nullptr;
-
-    // The task runner where the Producer methods will be called onto.
-    // The caller has to guarantee that the passed TaskRunner is valid as long
-    // as the returned ProducerEndpoint is alive.
-    ::perfetto::base::TaskRunner* task_runner = nullptr;
-
-    // These get propagated from TracingInitArgs and are optionally provided by
-    // the client when calling Tracing::Initialize().
-    uint32_t shmem_size_hint_bytes = 0;
-    uint32_t shmem_page_size_hint_bytes = 0;
-  };
-
-  virtual std::unique_ptr<ProducerEndpoint> ConnectProducer(
-      const ConnectProducerArgs&) = 0;
-
-  // As above, for the Consumer-side.
-  struct ConnectConsumerArgs {
-    // The Consumer object that will receive calls like OnTracingDisabled(),
-    // OnTraceData().
-    Consumer* consumer{};
-
-    // The task runner where the Consumer methods will be called onto.
-    ::perfetto::base::TaskRunner* task_runner{};
-  };
-  virtual std::unique_ptr<ConsumerEndpoint> ConnectConsumer(
-      const ConnectConsumerArgs&) = 0;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_TRACING_BACKEND_H_
diff --git a/include/perfetto/tracing/track_event.h b/include/perfetto/tracing/track_event.h
deleted file mode 100644
index 83907ab7..0000000
--- a/include/perfetto/tracing/track_event.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_TRACK_EVENT_H_
-#define INCLUDE_PERFETTO_TRACING_TRACK_EVENT_H_
-
-#include "perfetto/base/time.h"
-#include "perfetto/tracing/internal/track_event_data_source.h"
-#include "perfetto/tracing/internal/track_event_internal.h"
-#include "perfetto/tracing/internal/track_event_macros.h"
-#include "perfetto/tracing/track_event_category_registry.h"
-#include "protos/perfetto/trace/track_event/track_event.pbzero.h"
-
-// This file contains a set of macros designed for instrumenting applications
-// with track event trace points. While the underlying TrackEvent API can also
-// be used directly, doing so efficiently requires some care (e.g., to avoid
-// evaluating arguments while tracing is disabled). These types of optimizations
-// are abstracted away by the macros below.
-//
-// ================
-// Quickstart guide
-// ================
-//
-//   To add track events to your application, first define your categories in,
-//   e.g., my_tracing.h:
-//
-//       PERFETTO_DEFINE_CATEGORIES(
-//           PERFETTO_CATEGORY(base),
-//           PERFETTO_CATEGORY(v8),
-//           PERFETTO_CATEGORY(cc));
-//
-//   Then in a single .cc file, e.g., my_tracing.cc:
-//
-//       #include "my_tracing.h"
-//       PERFETTO_TRACK_EVENT_STATIC_STORAGE();
-//
-//   Finally, register track events at startup, after which you can record
-//   events with the TRACE_EVENT macros:
-//
-//       #include "my_tracing.h"
-//
-//       int main() {
-//         perfetto::TrackEvent::Register();
-//         TRACK_EVENT_BEGIN("category", "MyEvent");
-//         TRACK_EVENT_END("category");
-//         ...
-//       }
-//
-// ====================
-// Implementation notes
-// ====================
-//
-// The track event library consists of the following layers and components. The
-// classes the internal namespace shouldn't be considered part of the public
-// API.
-//                    .--------------------------------.
-//               .----|  TRACE_EVENT                   |----.
-//      write   |     |   - App instrumentation point  |     |  write
-//      event   |     '--------------------------------'     |  arguments
-//              V                                            V
-//  .----------------------------------.    .-----------------------------.
-//  | TrackEvent                       |    | TrackEventContext           |
-//  |  - Registry of event categories  |    |  - One track event instance |
-//  '----------------------------------'    '-----------------------------'
-//              |                                            |
-//              |                                            | look up
-//              | is                                         | interning ids
-//              V                                            V
-//  .----------------------------------.    .-----------------------------.
-//  | internal::TrackEventDataSource   |    | TrackEventInternedDataIndex |
-//  | - Perfetto data source           |    | - Corresponds to a field in |
-//  | - Has TrackEventIncrementalState |    |   in interned_data.proto    |
-//  '----------------------------------'    '-----------------------------'
-//              |                  |                         ^
-//              |                  |       owns (1:many)     |
-//              | write event      '-------------------------'
-//              V
-//  .----------------------------------.
-//  | internal::TrackEventInternal     |
-//  | - Outlined code to serialize     |
-//  |   one track event                |
-//  '----------------------------------'
-//
-
-// Each compilation unit can be in exactly one track event namespace,
-// allowing the overall program to use multiple track event data sources and
-// category lists if necessary. Use this macro to select the namespace for the
-// current compilation unit.
-//
-// If the program uses multiple track event namespaces, category & track event
-// registration (see quickstart above) needs to happen for both namespaces
-// separately.
-#ifndef PERFETTO_TRACK_EVENT_NAMESPACE
-#define PERFETTO_TRACK_EVENT_NAMESPACE perfetto
-#endif
-
-// A name for a single category. Wrapped in a macro in case we need to introduce
-// more fields in the future.
-#define PERFETTO_CATEGORY(name) \
-  { #name }
-
-// Register the set of available categories by passing a list of categories to
-// this macro: PERFETTO_CATEGORY(cat1), PERFETTO_CATEGORY(cat2), ...
-#define PERFETTO_DEFINE_CATEGORIES(...)                        \
-  namespace PERFETTO_TRACK_EVENT_NAMESPACE {                   \
-  /* The list of category names */                             \
-  PERFETTO_INTERNAL_DECLARE_CATEGORIES(__VA_ARGS__);           \
-  /* The track event data source for this set of categories */ \
-  PERFETTO_INTERNAL_DECLARE_TRACK_EVENT_DATA_SOURCE();         \
-  }  // namespace PERFETTO_TRACK_EVENT_NAMESPACE
-
-// Allocate storage for each category by using this macro once per track event
-// namespace.
-#define PERFETTO_TRACK_EVENT_STATIC_STORAGE() \
-  namespace PERFETTO_TRACK_EVENT_NAMESPACE {  \
-  PERFETTO_INTERNAL_CATEGORY_STORAGE();       \
-  }  // namespace PERFETTO_TRACK_EVENT_NAMESPACE
-
-// Begin a thread-scoped slice under |category| with the title |name|. Both
-// strings must be static constants. The track event is only recorded if
-// |category| is enabled for a tracing session.
-#define TRACE_EVENT_BEGIN(category, name, ...) \
-  PERFETTO_INTERNAL_TRACK_EVENT(               \
-      category, name,                          \
-      ::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN, ##__VA_ARGS__)
-
-// End a thread-scoped slice under |category|.
-#define TRACE_EVENT_END(category, ...) \
-  PERFETTO_INTERNAL_TRACK_EVENT(       \
-      category, nullptr,               \
-      ::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END, ##__VA_ARGS__)
-
-// TODO(skyostil): Add arguments.
-// TODO(skyostil): Add scoped events.
-// TODO(skyostil): Add async events.
-// TODO(skyostil): Add flow events.
-// TODO(skyostil): Add instant events.
-// TODO(skyostil): Add counters.
-
-#endif  // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_H_
diff --git a/include/perfetto/tracing/track_event_category_registry.h b/include/perfetto/tracing/track_event_category_registry.h
deleted file mode 100644
index 3e15db6..0000000
--- a/include/perfetto/tracing/track_event_category_registry.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_TRACK_EVENT_CATEGORY_REGISTRY_H_
-#define INCLUDE_PERFETTO_TRACING_TRACK_EVENT_CATEGORY_REGISTRY_H_
-
-#include "perfetto/tracing/data_source.h"
-
-#include <atomic>
-
-namespace perfetto {
-namespace internal {
-
-// A compile-time representation of a track event category. See
-// PERFETTO_DEFINE_CATEGORIES for registering your own categories.
-struct TrackEventCategory {
-  const char* const name;
-};
-
-// Holds all the registered categories for one category namespace. See
-// PERFETTO_DEFINE_CATEGORIES for building the registry.
-class TrackEventCategoryRegistry {
- public:
-  constexpr TrackEventCategoryRegistry(size_t category_count,
-                                       const TrackEventCategory* categories,
-                                       std::atomic<uint8_t>* state_storage)
-      : categories_(categories),
-        category_count_(category_count),
-        state_storage_(state_storage) {
-    static_assert(
-        sizeof(state_storage[0].load()) * 8 >= kMaxDataSourceInstances,
-        "The category state must have enough bits for all possible data source "
-        "instances");
-  }
-
-  size_t category_count() const { return category_count_; }
-
-  // Returns a category based on its index.
-  const TrackEventCategory* GetCategory(size_t index) const;
-
-  // Turn tracing on or off for the given category in a track event data source
-  // instance.
-  void EnableCategoryForInstance(size_t category_index,
-                                 uint32_t instance_index) const;
-  void DisableCategoryForInstance(size_t category_index,
-                                  uint32_t instance_index) const;
-
-  constexpr std::atomic<uint8_t>* GetCategoryState(
-      size_t category_index) const {
-    return &state_storage_[category_index];
-  }
-
-  // --------------------------------------------------------------------------
-  // Trace point support
-  // --------------------------------------------------------------------------
-  //
-  // (The following methods are used by the track event trace point
-  // implementation and typically don't need to be called by other code.)
-
-  // At compile time, turn a category name into an index into the registry.
-  // Returns kInvalidCategoryIndex if the category was not found.
-  static constexpr size_t kInvalidCategoryIndex = static_cast<size_t>(-1);
-  constexpr size_t Find(const char* name, size_t index = 0) const {
-    return (index == category_count_) ? kInvalidCategoryIndex
-                                      : StringEq(categories_[index].name, name)
-                                            ? index
-                                            : Find(name, index + 1);
-  }
-
-  // A helper for validating that a category was registered at compile time.
-  template <size_t CategoryIndex>
-  static constexpr size_t Validate() {
-    static_assert(CategoryIndex != kInvalidCategoryIndex,
-                  "A track event used an unknown category. Please add it to "
-                  "PERFETTO_DEFINE_CATEGORIES().");
-    return CategoryIndex;
-  }
-
- private:
-  // TODO(skyostil): Make the compile-time routines nicer with C++14.
-  static constexpr bool StringEq(const char* a, const char* b) {
-    return *a != *b ? false
-                    : (!*a || !*b) ? (*a == *b) : StringEq(a + 1, b + 1);
-  }
-
-  const TrackEventCategory* const categories_;
-  const size_t category_count_;
-  std::atomic<uint8_t>* const state_storage_;
-};
-
-}  // namespace internal
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_CATEGORY_REGISTRY_H_
diff --git a/include/perfetto/tracing/track_event_context.h b/include/perfetto/tracing/track_event_context.h
deleted file mode 100644
index 5cf657a..0000000
--- a/include/perfetto/tracing/track_event_context.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_TRACK_EVENT_CONTEXT_H_
-#define INCLUDE_PERFETTO_TRACING_TRACK_EVENT_CONTEXT_H_
-
-#include "perfetto/protozero/message_handle.h"
-#include "perfetto/tracing/internal/track_event_internal.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-namespace perfetto {
-namespace internal {
-class TrackEventInternal;
-}
-
-// Allows adding custom arguments into track events. Example:
-//
-//   TRACE_EVENT_BEGIN("category", "Title",
-//                     [](perfetto::TrackEventContext ctx) {
-//                       auto* dbg = ctx.track_event()->add_debug_annotations();
-//                       dbg->set_name("name");
-//                       dbg->set_int_value(1234);
-//                     });
-//
-class TrackEventContext {
- public:
-  TrackEventContext(TrackEventContext&&) = default;
-  ~TrackEventContext();
-
-  protos::pbzero::TrackEvent* track_event() const { return track_event_; }
-
- private:
-  template <typename, size_t, typename, typename>
-  friend class TrackEventInternedDataIndex;
-  friend class internal::TrackEventInternal;
-
-  using TracePacketHandle =
-      ::protozero::MessageHandle<protos::pbzero::TracePacket>;
-
-  TrackEventContext(TracePacketHandle, internal::TrackEventIncrementalState*);
-  TrackEventContext(const TrackEventContext&) = delete;
-
-  TracePacketHandle trace_packet_;
-  protos::pbzero::TrackEvent* track_event_;
-  internal::TrackEventIncrementalState* incremental_state_;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_CONTEXT_H_
diff --git a/include/perfetto/tracing/track_event_interned_data_index.h b/include/perfetto/tracing/track_event_interned_data_index.h
deleted file mode 100644
index e1ef7ee..0000000
--- a/include/perfetto/tracing/track_event_interned_data_index.h
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (C) 2019 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 INCLUDE_PERFETTO_TRACING_TRACK_EVENT_INTERNED_DATA_INDEX_H_
-#define INCLUDE_PERFETTO_TRACING_TRACK_EVENT_INTERNED_DATA_INDEX_H_
-
-#include "perfetto/tracing/internal/track_event_internal.h"
-
-#include "perfetto/base/compiler.h"
-
-#include <map>
-#include <type_traits>
-#include <unordered_map>
-
-// This file has templates for defining your own interned data types to be used
-// with track event. Interned data can be useful for avoiding repeating the same
-// constant data (e.g., strings) throughout the trace.
-//
-// =============
-// Example usage
-// =============
-//
-// First define an interning index for your type. It should map to a specific
-// field of interned_data.proto and define how the interned data is written into
-// that message.
-//
-//   struct MyInternedData
-//       : public perfetto::TrackEventInternedDataIndex<
-//           MyInternedData,
-//           perfetto::protos::pbzero::InternedData::kMyInternedDataFieldNumber,
-//           const char*> {
-//     static void Add(perfetto::protos::pbzero::InternedData* interned_data,
-//                      size_t iid,
-//                      const char* value) {
-//       auto my_data = interned_data->add_my_interned_data();
-//       my_data->set_iid(iid);
-//       my_data->set_value(value);
-//     }
-//   };
-//
-// Next, use your interned data in a trace point as shown below. The interned
-// string will only be emitted the first time the trace point is hit.
-//
-//   TRACE_EVENT_BEGIN(
-//      "category", "Event", [&](perfetto::TrackEventContext ctx) {
-//        auto my_message = ctx.track_event()->set_my_message();
-//        size_t iid = MyInternedData::Get(&ctx, "Some data");
-//        my_message->set_iid(iid);
-//      });
-//
-
-namespace perfetto {
-
-// By default, the interning index stores a full copy of the interned data. This
-// ensures the same data is always mapped to the same interning id, and there is
-// no danger of collisions. This comes at the cost of memory usage, however, so
-// consider using HashedInternedDataTraits if that may be an issue.
-//
-// This type of index also performs hashing on the stored data for lookups; for
-// types where this isn't necessary (e.g., raw const char*), use
-// SmallInternedDataTraits.
-struct BigInternedDataTraits {
-  template <typename ValueType>
-  class Index {
-   public:
-    bool LookUpOrInsert(size_t* iid, const ValueType& value) {
-      size_t next_id = data_.size() + 1;
-      auto it_and_inserted = data_.insert(std::make_pair(value, next_id));
-      if (!it_and_inserted.second) {
-        *iid = it_and_inserted.first->second;
-        return true;
-      }
-      *iid = next_id;
-      return false;
-    }
-
-   private:
-    std::unordered_map<ValueType, size_t> data_;
-  };
-};
-
-// This type of interning index keeps full copies of interned data without
-// hashing the values. This is a good fit for small types that can be directly
-// used as index keys.
-struct SmallInternedDataTraits {
-  template <typename ValueType>
-  class Index {
-   public:
-    bool LookUpOrInsert(size_t* iid, const ValueType& value) {
-      size_t next_id = data_.size() + 1;
-      auto it_and_inserted = data_.insert(std::make_pair(value, next_id));
-      if (!it_and_inserted.second) {
-        *iid = it_and_inserted.first->second;
-        return true;
-      }
-      *iid = next_id;
-      return false;
-    }
-
-   private:
-    std::map<ValueType, size_t> data_;
-  };
-};
-
-// This type of interning index only stores the hash of the interned values
-// instead of the values themselves. This is more efficient in terms of memory
-// usage, but assumes that there are no hash collisions. If a hash collision
-// occurs, two or more values will be mapped to the same interning id.
-//
-// Note that the given type must have a specialization for std::hash.
-struct HashedInternedDataTraits {
-  template <typename ValueType>
-  class Index {
-   public:
-    bool LookUpOrInsert(size_t* iid, const ValueType& value) {
-      auto key = std::hash<ValueType>()(value);
-      size_t next_id = data_.size() + 1;
-      auto it_and_inserted = data_.insert(std::make_pair(key, next_id));
-      if (!it_and_inserted.second) {
-        *iid = it_and_inserted.first->second;
-        return true;
-      }
-      *iid = next_id;
-      return false;
-    }
-
-   private:
-    std::map<size_t, size_t> data_;
-  };
-};
-
-// A templated base class for an interned data type which corresponds to a field
-// in interned_data.proto.
-//
-// |InternedDataType| must be the type of the subclass.
-// |FieldNumber| is the corresponding protobuf field in InternedData.
-// |ValueType| is the type which is stored in the index. It must be copyable.
-// |Traits| can be used to customize the storage and lookup mechanism.
-//
-// The subclass should define a static method with the following signature for
-// committing interned data together with the interning id |iid| into the trace:
-//
-//   static void Add(perfetto::protos::pbzero::InternedData*,
-//                   size_t iid,
-//                   const ValueType& value);
-//
-template <typename InternedDataType,
-          size_t FieldNumber,
-          typename ValueType,
-          // Avoid unnecessary hashing for pointers by default.
-          typename Traits =
-              typename std::conditional<(std::is_pointer<ValueType>::value),
-                                        SmallInternedDataTraits,
-                                        BigInternedDataTraits>::type>
-class TrackEventInternedDataIndex
-    : public internal::BaseTrackEventInternedDataIndex {
- public:
-  // Return an interning id for |value|. The returned id can be immediately
-  // written to the trace.
-  static size_t Get(TrackEventContext* ctx, const ValueType& value) {
-    // First check if the value exists in the dictionary.
-    auto index_for_field = GetOrCreateIndexForField(ctx->incremental_state_);
-    size_t iid;
-    if (PERFETTO_LIKELY(index_for_field->index_.LookUpOrInsert(&iid, value))) {
-      PERFETTO_DCHECK(iid);
-      return iid;
-    }
-
-    // If not, we need to serialize the definition of the interned value into
-    // the heap buffered message (which is committed to the trace when the
-    // packet ends).
-    PERFETTO_DCHECK(iid);
-    InternedDataType::Add(
-        ctx->incremental_state_->serialized_interned_data.get(), iid,
-        std::move(value));
-    return iid;
-  }
-
- private:
-  static InternedDataType* GetOrCreateIndexForField(
-      internal::TrackEventIncrementalState* incremental_state) {
-    // Fast path: look for matching field number.
-    for (const auto& entry : incremental_state->interned_data_indices) {
-      if (entry.first == FieldNumber) {
-#if PERFETTO_DCHECK_IS_ON()
-        if (strcmp(PERFETTO_DEBUG_FUNCTION_IDENTIFIER(),
-                   entry.second->type_id_)) {
-          PERFETTO_FATAL(
-              "Interned data accessed under different types! Previous type: "
-              "%s. New type: %s.",
-              entry.second->type_id_, PERFETTO_DEBUG_FUNCTION_IDENTIFIER());
-        }
-#endif  // PERFETTO_DCHECK_IS_ON()
-        return reinterpret_cast<InternedDataType*>(entry.second.get());
-      }
-    }
-    // No match -- add a new entry for this field.
-    for (auto& entry : incremental_state->interned_data_indices) {
-      if (!entry.first) {
-        entry.first = FieldNumber;
-        entry.second.reset(new InternedDataType());
-#if PERFETTO_DCHECK_IS_ON()
-        entry.second->type_id_ = PERFETTO_DEBUG_FUNCTION_IDENTIFIER();
-#endif  // PERFETTO_DCHECK_IS_ON()
-        return reinterpret_cast<InternedDataType*>(entry.second.get());
-      }
-    }
-    // Out of space in the interned data index table.
-    PERFETTO_CHECK(false);
-  }
-
-  // The actual interning dictionary for this type of interned data. The actual
-  // container type is defined by |Traits|, hence the extra layer of template
-  // indirection here.
-  typename Traits::template Index<ValueType> index_;
-};
-
-}  // namespace perfetto
-
-#endif  // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_INTERNED_DATA_INDEX_H_
diff --git a/infra/ci/.gitignore b/infra/ci/.gitignore
deleted file mode 100644
index 70fcf84..0000000
--- a/infra/ci/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-test-credentials.json
-.deps/
diff --git a/infra/ci/.pylintrc b/infra/ci/.pylintrc
deleted file mode 100644
index 684fb10..0000000
--- a/infra/ci/.pylintrc
+++ /dev/null
@@ -1,23 +0,0 @@
-[MESSAGES CONTROL]
-
-disable=
-  bad-indentation,
-  missing-docstring,
-  import-error,
-  no-name-in-module,
-  unused-argument,
-  invalid-name,
-  too-few-public-methods,
-
-[REPORTS]
-reports=no
-
-[VARIABLES]
-dummy-variables-rgx=_$|unused_
-
-[FORMAT]
-indent-string='  '
-
-# We suppress long line check for lines that contain only the URL (with or
-# without quote).
-ignore-long-lines=^\s*'?https?://\S+'?$
\ No newline at end of file
diff --git a/infra/ci/Makefile b/infra/ci/Makefile
deleted file mode 100644
index b122287..0000000
--- a/infra/ci/Makefile
+++ /dev/null
@@ -1,148 +0,0 @@
-# Copyright (C) 2019 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 $(shell python config.py makefile)
-
-override COMMON_DEPS := Makefile *.py
-override GCE_LOCAL_STARTUP_SCRIPT := worker/gce-startup-script.sh
-override SCRIPT_HASH := $(shell git hash-object ${GCE_LOCAL_STARTUP_SCRIPT} | cut -c 1-8)
-override GCE_STARTUP_SCRIPT := gs://perfetto/ci/worker-startup-script/${SCRIPT_HASH}
-BUILDER := docker
-
-.PHONY: help
-help:
-	@echo "build:              Builds the worker and sandbox containers"
-	@echo "build-worker:       Builds the worker container"
-	@echo "build-sandbox:      Builds the sandbox container"
-	@echo "push:               Pushes the containers to the registry"
-	@echo "deploy-controller:  Deploys and restarts the controller"
-	@echo "deploy-frontend:    Deploys and restarts the controller"
-	@echo "stop-workers:       Stops the whole workers GCE instance group"
-	@echo "start-workers:      Starts the whole workers GCE instance group"
-	@echo "restart-workers:    Restarts the whole workers GCE instance group"
-
-.PHONY: build
-build: build-worker build-sandbox
-
-.PHONY: build-worker
-build-worker: .deps/${BUILDER}-worker
-
-.PHONY: build-sandbox
-build-sandbox: .deps/${BUILDER}-sandbox
-
-.PHONY: push
-push: build
-	${BUILDER} push ${WORKER_IMG}
-	${BUILDER} push ${SANDBOX_IMG}
-
-.PHONY: clean
-clean:
-	rm -rf .deps
-
-.deps/${BUILDER}-worker: worker/* ${COMMON_DEPS}
-	mkdir -p worker/tmp
-	cp -a config.py common_utils.py worker/tmp/
-	${BUILDER} build --rm --force-rm -t ${WORKER_IMG} worker
-	rm -rf worker/tmp/
-	touch $@
-
-.deps/${BUILDER}-sandbox: sandbox/* ${COMMON_DEPS}
-	${BUILDER} build --rm --force-rm -t ${SANDBOX_IMG} sandbox
-	touch $@
-
-.deps/upload-startup-script: ${GCE_LOCAL_STARTUP_SCRIPT} ${COMMON_DEPS}
-	gsutil -q cp -a public-read ${GCE_LOCAL_STARTUP_SCRIPT} ${GCE_STARTUP_SCRIPT}
-	touch $@
-
-.deps/gce-template: ${COMMON_DEPS} .deps/upload-startup-script
-	gcloud compute --quiet --project=${PROJECT} \
-		instance-templates delete --quiet ${GCE_TEMPLATE} || true
-	gcloud compute --quiet --project=${PROJECT} \
-		instance-templates create ${GCE_TEMPLATE} \
-		--machine-type=${GCE_VM_TYPE} \
-		--network=projects/perfetto-ci/global/networks/default \
-		--network-tier=PREMIUM \
-		--metadata='startup-script-url=${GCE_STARTUP_SCRIPT},num-workers=${NUM_WORKERS_PER_VM},google-logging-enabled=true' \
-		--maintenance-policy=MIGRATE \
-		--service-account=gce-ci-worker@perfetto-ci.iam.gserviceaccount.com \
-		--scopes=${GCE_SCOPES} \
-		--image=cos-stable-75-12105-77-0 \
-		--image-project=cos-cloud \
-		--boot-disk-size=200GB \
-		--boot-disk-type=pd-ssd \
-		--boot-disk-device-name=ci-worker-template
-	touch $@
-
-.PHONY: deploy-controller
-deploy-controller:
-	make -C controller deploy
-
-.PHONY: deploy-frontend
-deploy-frontend:
-	make -C frontend deploy
-
-.PHONY: stop-workers
-stop-workers:
-	gcloud compute --quiet --project=${PROJECT} \
-		instance-groups managed delete ${GCE_GROUP_NAME} --zone=${ZONE} || true
-
-# Fix the replicas to 2. Dynamic scaling causes too jobs to be aborted while
-# scaling down.
-.PHONY: start-workers
-start-workers: .deps/gce-template
-	gcloud beta compute --project=${PROJECT} \
-		instance-groups managed create ${GCE_GROUP_NAME} \
-		--zone=${ZONE} \
-		--base-instance-name=ci-worker-group \
-		--template=ci-worker-template \
-		--size=1
-	gcloud beta compute --quiet --project=${PROJECT} \
-		instance-groups managed set-autoscaling ${GCE_GROUP_NAME} \
-		--zone ${ZONE} \
-		--min-num-replicas "2" \
-		--max-num-replicas "2" \
-		--cool-down-period "1800" \
-		--stackdriver-metric-filter "resource.type = \"global\"" \
-		--update-stackdriver-metric "custom.googleapis.com/perfetto-ci/ci_job_queue_len" \
-		--stackdriver-metric-single-instance-assignment "10"
-
-.PHONY: restart-workers
-restart-workers: stop-workers start-workers
-
-# These are for testing only, start an individual VM. Use start-group for
-# production.
-
-.PHONY: stop-worker-for-testing
-stop-worker-for-testing:
-	gcloud compute --quiet \
-		--project ${PROJECT} \
-		instances delete ${GCE_VM_NAME} \
-		--zone ${ZONE}
-
-.PHONY: start-worker-for-testing
-start-worker-for-testing: .deps/gce-template
-	gcloud compute --quiet \
-		--project ${PROJECT} \
-		instances create ${GCE_VM_NAME} \
-		--zone ${ZONE} \
-		--source-instance-template=${GCE_TEMPLATE}
-
-# Debugging client to make OAuth2 authenticated requests manually.
-.PHONY: cli
-cli:
-	GOOGLE_APPLICATION_CREDENTIALS=test-credentials.json \
-	python -i -c 'from common_utils import *; from config import *; \
-		SCOPES += ["https://www.googleapis.com/auth/firebase.database", \
-								"https://www.googleapis.com/auth/userinfo.email", \
-								"https://www.googleapis.com/auth/datastore"]'
diff --git a/infra/ci/common_utils.py b/infra/ci/common_utils.py
deleted file mode 100644
index 61d600c..0000000
--- a/infra/ci/common_utils.py
+++ /dev/null
@@ -1,110 +0,0 @@
-# Copyright (C) 2019 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.
-
-import json
-import httplib2
-import os
-import logging
-import threading
-
-from datetime import datetime
-from oauth2client.client import GoogleCredentials
-from config import PROJECT
-
-tls = threading.local()
-
-# Caller has to initialize this
-SCOPES = []
-
-
-class ConcurrentModificationError(Exception):
-  pass
-
-
-def get_gerrit_credentials():
-  '''Retrieve the credentials used to authenticate Gerrit requests
-
-  Returns a tuple (user, gitcookie). These fields are obtained from the Gerrit
-  'New HTTP password' page which generates a .gitcookie file and stored in the
-  project datastore.
-  user: typically looks like git-user.gmail.com.
-  gitcookie: is the password after the = token.
-  '''
-  body = {'query': {'kind': [{'name': 'GerritAuth'}]}}
-  res = req(
-      'POST',
-      'https://datastore.googleapis.com/v1/projects/%s:runQuery' % PROJECT,
-      body=body)
-  auth = res['batch']['entityResults'][0]['entity']['properties']
-  user = auth['user']['stringValue']
-  gitcookie = auth['gitcookie']['stringValue']
-  return user, gitcookie
-
-
-def req(method, uri, body=None, req_etag=False, etag=None, gerrit=False):
-  '''Helper function to handle authenticated HTTP requests.
-
-  Cloud API and Gerrit require two different types of authentication and as
-  such need to be handled differently. The HTTP connection is cached in the
-  TLS slot to avoid refreshing oauth tokens too often for back-to-back requests.
-  Appengine takes care of clearing the TLS slot upon each frontend request so
-  these connections won't be recycled for too long.
-  '''
-  hdr = {'Content-Type': 'application/json; charset=UTF-8'}
-  tls_key = 'gerrit_http' if gerrit else 'oauth2_http'
-  if hasattr(tls, tls_key):
-    http = getattr(tls, tls_key)
-  else:
-    http = httplib2.Http()
-    setattr(tls, tls_key, http)
-    if gerrit:
-      http.add_credentials(*get_gerrit_credentials())
-    elif SCOPES:
-      creds = GoogleCredentials.get_application_default().create_scoped(SCOPES)
-      creds.authorize(http)
-
-  if req_etag:
-    hdr['X-Firebase-ETag'] = 'true'
-  if etag:
-    hdr['if-match'] = etag
-  body = None if body is None else json.dumps(body)
-  logging.debug('%s %s', method, uri)
-  resp, res = http.request(uri, method=method, headers=hdr, body=body)
-  if resp.status == 200:
-    res = res[4:] if gerrit else res  # Strip Gerrit XSSI projection chars.
-    return (json.loads(res), resp['etag']) if req_etag else json.loads(res)
-  elif resp.status == 412:
-    raise ConcurrentModificationError()
-  else:
-    delattr(tls, tls_key)
-    raise Exception(resp, res)
-
-
-# Datetime functions to deal with the fact that Javascript expects a trailing
-# 'Z' (Z == 'Zulu' == UTC) for timestamps.
-
-
-def parse_iso_time(time_str):
-  return datetime.strptime(time_str, r'%Y-%m-%dT%H:%M:%SZ')
-
-
-def utc_now_iso(utcnow=None):
-  return (utcnow or datetime.utcnow()).strftime(r'%Y-%m-%dT%H:%M:%SZ')
-
-
-def init_logging():
-  logging.basicConfig(
-      format='%(asctime)s %(levelname)-8s %(message)s',
-      level=logging.DEBUG if os.getenv('VERBOSE') else logging.INFO,
-      datefmt=r'%Y-%m-%d %H:%M:%S')
diff --git a/infra/ci/config.py b/infra/ci/config.py
deleted file mode 100755
index 8426880..0000000
--- a/infra/ci/config.py
+++ /dev/null
@@ -1,153 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2019 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.
-'''Project-wide configuration
-
-This file is either imported from other python scripts or executed to generate
-makefile dumps of the variables. This is so all vars can live in one place.
-'''
-
-from __future__ import print_function
-
-# Gerrit config
-GERRIT_HOST = 'android-review.googlesource.com'
-GERRIT_PROJECT = 'platform/external/perfetto'
-GERRIT_REVIEW_URL = (
-    'https://android-review.googlesource.com/c/' + GERRIT_PROJECT)
-REPO_URL = 'https://android.googlesource.com/' + GERRIT_PROJECT
-GERRIT_POLL_SEC = 15
-GERRIT_VOTING_ENABLED = True
-LOGLEVEL = 'info'
-
-# Cloud config (GCE = Google Compute Engine, GAE = Google App Engine)
-PROJECT = 'perfetto-ci'
-ZONE = 'us-west1-b'
-GAE_VERSION = 'prod'
-DB_ROOT = 'https://%s.firebaseio.com' % PROJECT
-DB = DB_ROOT + '/ci'
-SANDBOX_IMG = 'eu.gcr.io/%s/sandbox' % PROJECT
-WORKER_IMG = 'eu.gcr.io/%s/worker' % PROJECT
-CI_SITE = 'https://ci.perfetto.dev'
-GCS_ARTIFACTS = 'perfetto-ci-artifacts'
-
-JOB_TIMEOUT_SEC = 60 * 30
-CL_TIMEOUT_SEC = 60 * 60 * 3
-LOGS_TTL_DAYS = 15
-TRUSTED_EMAILS = '^.*@google.com$'
-
-GCE_VM_NAME = 'ci-worker'
-GCE_VM_TYPE = 'n1-standard-64'
-GCE_TEMPLATE = 'ci-worker-template'
-GCE_GROUP_NAME = 'ci'
-NUM_WORKERS_PER_VM = 10
-
-GCE_SCOPES = [
-    'https://www.googleapis.com/auth/cloud-platform',
-    'https://www.googleapis.com/auth/devstorage.read_write',
-    'https://www.googleapis.com/auth/firebase.database',
-    'https://www.googleapis.com/auth/logging.write',
-    'https://www.googleapis.com/auth/monitoring.write',
-    'https://www.googleapis.com/auth/trace.append',
-    'https://www.googleapis.com/auth/userinfo.email',
-]
-
-# Only variables starting with PERFETTO_ are propagated into the sandbox.
-JOB_CONFIGS = {
-    'linux-clang-x86_64-debug': {
-        'PERFETTO_TEST_GN_ARGS': 'is_debug=true is_hermetic_clang=false',
-        'PERFETTO_TEST_SCRIPT': 'test/ci/linux_tests.sh',
-    },
-    'linux-clang-x86_64-tsan': {
-        'PERFETTO_TEST_GN_ARGS': 'is_debug=false is_tsan=true',
-        'PERFETTO_TEST_SCRIPT': 'test/ci/linux_tests.sh',
-    },
-    'linux-clang-x86_64-msan': {
-        'PERFETTO_TEST_GN_ARGS': 'is_debug=false is_msan=true',
-        'PERFETTO_TEST_SCRIPT': 'test/ci/linux_tests.sh',
-    },
-    'linux-clang-x86_64-asan_lsan': {
-        'PERFETTO_TEST_GN_ARGS': 'is_debug=false is_asan=true is_lsan=true',
-        'PERFETTO_TEST_SCRIPT': 'test/ci/linux_tests.sh',
-    },
-    'linux-clang-x86-asan_lsan': {
-        'PERFETTO_TEST_GN_ARGS': 'is_debug=false is_asan=true is_lsan=true '
-                                 'target_cpu="x86"',
-        'PERFETTO_TEST_SCRIPT': 'test/ci/linux_tests.sh',
-    },
-    'linux-gcc7-x86_64-release': {
-        'PERFETTO_TEST_GN_ARGS': 'is_debug=false is_clang=false '
-                                 'cc="gcc-7" cxx="g++-7"',
-        'PERFETTO_TEST_SCRIPT': 'test/ci/linux_tests.sh',
-    },
-    'android-clang-arm-release': {
-        'PERFETTO_TEST_GN_ARGS':
-            'is_debug=false target_os="android" target_cpu="arm"',
-        'PERFETTO_TEST_SCRIPT':
-            'test/ci/android_tests.sh',
-    },
-    'android-clang-arm-asan': {
-        'PERFETTO_TEST_GN_ARGS': 'is_debug=false target_os="android" '
-                                 'target_cpu="arm" is_asan=true',
-        'PERFETTO_TEST_SCRIPT': 'test/ci/android_tests.sh',
-    },
-    'linux-clang-x86_64-libfuzzer': {
-        'PERFETTO_TEST_GN_ARGS': 'is_debug=false is_fuzzer=true is_asan=true',
-        'PERFETTO_TEST_SCRIPT': 'test/ci/fuzzer_tests.sh',
-    },
-    'linux-clang-x86_64-bazel': {
-        'PERFETTO_TEST_GN_ARGS': '',
-        'PERFETTO_TEST_SCRIPT': 'test/ci/bazel_tests.sh',
-    },
-    'ui-clang-x86_64-debug': {
-        'PERFETTO_TEST_GN_ARGS': 'is_debug=true',
-        'PERFETTO_TEST_SCRIPT': 'test/ci/ui_tests.sh',
-    },
-    'ui-clang-x86_64-release': {
-        'PERFETTO_TEST_GN_ARGS': 'is_debug=false',
-        'PERFETTO_TEST_SCRIPT': 'test/ci/ui_tests.sh',
-    },
-}
-
-if __name__ == '__main__':
-  import os
-  import json
-  import re
-  import sys
-  vars = dict(kv for kv in locals().items() if re.match('^[A-Z0-9_]+$', kv[0]))
-
-  if len(sys.argv) > 1 and sys.argv[1] == 'makefile':
-    deps_path = os.path.join(os.path.dirname(__file__), '.deps')
-    if not os.path.exists(deps_path):
-      os.mkdir(deps_path)
-    gen_file = os.path.join(deps_path, 'config.mk')
-
-    try:
-      literals = (int, long, basestring)
-    except NameError:
-      literals = (int, str)
-
-    with open(gen_file, 'w') as f:
-      for k, v in vars.items():
-        if isinstance(v, literals):
-          f.write('override %s=%s\n' % (k, v))
-        elif isinstance(v, list):
-          f.write('override %s=%s\n' % (k, ','.join(v)))
-
-    print(gen_file)
-
-  if len(sys.argv) > 1 and sys.argv[1] == 'js':
-    jsn = json.dumps(vars, indent=2)
-    print('// Auto-generated by %s, do not edit.\n' % __file__)
-    print('\'use strict\';\n')
-    print('const cfg = JSON.parse(`%s`);\n' % jsn.replace(r'\"', r'\\\"'))
diff --git a/infra/ci/controller/.gitignore b/infra/ci/controller/.gitignore
deleted file mode 100644
index 18a0855..0000000
--- a/infra/ci/controller/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-config.py
-common_utils.py
-lib/
diff --git a/infra/ci/controller/Makefile b/infra/ci/controller/Makefile
deleted file mode 100644
index f72394d..0000000
--- a/infra/ci/controller/Makefile
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (C) 2019 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 $(shell python ../config.py makefile)
-
-test: lib/.stamp config.py common_utils.py
-	GOOGLE_APPLICATION_CREDENTIALS=../test-credentials.json \
-		dev_appserver.py app.yaml --dev_appserver_log_level ${LOGLEVEL}
-
-deploy: lib/.stamp config.py common_utils.py
-	gcloud app deploy -q app.yaml queue.yaml cron.yaml \
-		--project ${PROJECT} \
-		-v ${GAE_VERSION} \
-		--stop-previous-version
-
-stop:
-		gcloud app instances delete \
-		$(shell gcloud app instances list --project ${PROJECT} -v ${GAE_VERSION} -s default | tail -n1 | awk '{print $$3}') \
-		--project ${PROJECT} -v ${GAE_VERSION} -s default -q
-
-lib/.stamp:
-	pip install -t lib/ oauth2client httplib2
-	touch $@
-
-config.py: ../config.py
-	cp ../$@ $@
-
-common_utils.py: ../common_utils.py
-	cp ../$@ $@
-
-.PHONY: deploy test
diff --git a/infra/ci/controller/app.yaml b/infra/ci/controller/app.yaml
deleted file mode 100644
index ae1117b..0000000
--- a/infra/ci/controller/app.yaml
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2019 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.
-
-runtime: python27
-service: controller
-api_version: 1
-threadsafe: yes
-
-# B4 := 2.4 GHz 1024 MB
-instance_class: B4
-manual_scaling:
-  instances: 1
-
-# Login: admin is to avoid exposing the controller to the public and directly
-# poking at its internals. These endpoints are hit only by the tasks posted
-# by the controller itself. Everything happens as a continuation of either the
-# /_ah/start call or the Cron job calls (see cron.yaml).
-handlers:
-- url: (/controller/.*)|(/_ah/.*)
-  script: controller.app
-  login: admin
diff --git a/infra/ci/controller/appengine_config.py b/infra/ci/controller/appengine_config.py
deleted file mode 100644
index 91ff5bd..0000000
--- a/infra/ci/controller/appengine_config.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (C) 2019 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.
-
-from google.appengine.ext import vendor
-vendor.add('lib')
\ No newline at end of file
diff --git a/infra/ci/controller/controller.py b/infra/ci/controller/controller.py
deleted file mode 100644
index ef46916..0000000
--- a/infra/ci/controller/controller.py
+++ /dev/null
@@ -1,520 +0,0 @@
-# Copyright (C) 2019 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.
-
-import logging
-import re
-import time
-import urllib
-
-from datetime import datetime, timedelta
-from google.appengine.api import taskqueue
-
-import webapp2
-
-from common_utils import req, utc_now_iso, parse_iso_time, SCOPES
-from config import DB, GERRIT_HOST, GERRIT_PROJECT, GERRIT_POLL_SEC, PROJECT
-from config import CI_SITE, GERRIT_VOTING_ENABLED, JOB_CONFIGS, LOGS_TTL_DAYS
-from config import TRUSTED_EMAILS, GCS_ARTIFACTS, JOB_TIMEOUT_SEC
-from config import CL_TIMEOUT_SEC
-from stackdriver_metrics import STACKDRIVER_METRICS
-
-STACKDRIVER_API = 'https://monitoring.googleapis.com/v3/projects/%s' % PROJECT
-
-SCOPES.append('https://www.googleapis.com/auth/firebase.database')
-SCOPES.append('https://www.googleapis.com/auth/userinfo.email')
-SCOPES.append('https://www.googleapis.com/auth/datastore')
-SCOPES.append('https://www.googleapis.com/auth/monitoring')
-SCOPES.append('https://www.googleapis.com/auth/monitoring.write')
-
-last_tick = 0
-
-# ------------------------------------------------------------------------------
-# Misc utility functions
-# ------------------------------------------------------------------------------
-
-
-def defer(action, **kwargs):
-  '''Appends a task to the deferred queue.
-
-  Each task will become a new HTTP request made by the AppEngine service.
-  This pattern is used extensively here for several reasons:
-  - Auditability in logs: it's easier to scrape logs and debug.
-  - Stability: an exception fails only the current task not the whole function.
-  - Reliability: The AppEngine runtime will retry failed tasks with exponential
-    backoff.
-  - Performance: tasks are run concurrently, which is quite important given that
-    most of them are bound by HTTP latency to Gerrit of Firebase.
-  '''
-  taskqueue.add(
-      queue_name='deferred-jobs',
-      url='/controller/' + action,
-      params=kwargs,
-      method='GET')
-
-
-def create_stackdriver_metric_definitions():
-  logging.info('Creating Stackdriver metric definitions')
-  for name, metric in STACKDRIVER_METRICS.iteritems():
-    logging.info('Creating metric %s', name)
-    req('POST', STACKDRIVER_API + '/metricDescriptors', body=metric)
-
-
-def write_metrics(metric_dict):
-  now = utc_now_iso()
-  desc = {'timeSeries': []}
-  for key, spec in metric_dict.iteritems():
-    desc['timeSeries'] += [{
-        'metric': {
-            'type': STACKDRIVER_METRICS[key]['type'],
-            'labels': spec.get('l', {})
-        },
-        'resource': {
-            'type': 'global'
-        },
-        'points': [{
-            'interval': {
-                'endTime': now
-            },
-            'value': {
-                'int64Value': str(spec['v'])
-            }
-        }]
-    }]
-  try:
-    req('POST', STACKDRIVER_API + '/timeSeries', body=desc)
-  except Exception as e:
-    # Metric updates can easily fail due to Stackdriver API limitations.
-    msg = str(e)
-    if 'written more frequently than the maximum sampling' not in msg:
-      logging.error('Metrics update failed: %s', msg)
-
-
-def is_trusted(email):
-  return re.match(TRUSTED_EMAILS, email)
-
-
-# ------------------------------------------------------------------------------
-# Deferred job handlers
-# ------------------------------------------------------------------------------
-
-
-def start(handler):
-  create_stackdriver_metric_definitions()
-  tick(handler)
-
-
-def tick(handler):
-  global last_tick
-  now = time.time()
-  # Avoid avalanching effects due to the failsafe tick job in cron.yaml.
-  if now - last_tick < GERRIT_POLL_SEC - 1:
-    return
-  taskqueue.add(
-      url='/controller/tick', queue_name='tick', countdown=GERRIT_POLL_SEC)
-  defer('check_new_cls')
-  defer('check_pending_cls')
-  defer('update_queue_metrics')
-  last_tick = now
-
-
-def check_new_cls(handler):
-  ''' Poll for new CLs and asynchronously enqueue jobs for them.'''
-  logging.info('Polling for new Gerrit CLs')
-  date_limit = (datetime.utcnow() - timedelta(days=1)).strftime('%Y-%m-%d')
-  url = 'https://%s/a/changes/' % GERRIT_HOST
-  url += '?o=CURRENT_REVISION&o=DETAILED_ACCOUNTS&o=LABELS&n=200'
-  url += '&q=branch:master+project:%s' % GERRIT_PROJECT
-  url += '+is:open+after:%s' % date_limit
-  resp = req('GET', url, gerrit=True)
-  for change in (change for change in resp if 'revisions' in change):
-    rev_hash = change['revisions'].keys()[0]
-    rev = change['revisions'][rev_hash]
-    owner = rev['uploader']['email']
-    prs_ready = change['labels'].get('Presubmit-Ready', {}).get('approved', {})
-    prs_owner = prs_ready.get('email', '')
-    # Only submit jobs for patchsets that are either uploaded by a trusted
-    # account or are marked as Presubmit-Verified by a trustd account.
-    if not is_trusted(owner) and not is_trusted(prs_owner):
-      continue
-    defer(
-        'check_new_cl',
-        cl=str(change['_number']),
-        patchset=str(rev['_number']),
-        change_id=change['id'],
-        rev_hash=rev_hash,
-        ref=rev['ref'],
-        owner=rev['uploader']['email'],
-        wants_vote='1' if prs_ready else '0')
-
-
-def append_jobs(patch_obj, src, git_ref, now=None):
-  '''Creates the worker jobs (defined in config.py) for the given CL.
-
-  Jobs are keyed by timestamp-cl-patchset-config to get a fair schedule (workers
-  pull jobs ordered by the key above).
-  It dosn't directly write into the DB, it just appends keys to the passed
-  |patch_obj|, so the whole set of CL descriptor + jobs can be added atomically
-  to the datastore.
-  src: is cls/1234/1 (cl and patchset number).
-  '''
-  logging.info('Enqueueing jobs fos cl %s', src)
-  timestamp = (now or datetime.utcnow()).strftime('%Y%m%d%H%M%S')
-  for cfg_name, env in JOB_CONFIGS.iteritems():
-    job_id = '%s--%s--%s' % (timestamp, src.replace('/', '-'), cfg_name)
-    logging.info('Enqueueing job %s', job_id)
-    patch_obj['jobs/' + job_id] = {
-        'src': src,
-        'type': cfg_name,
-        'env': dict(env, PERFETTO_TEST_GIT_REF=git_ref),
-        'status': 'QUEUED',
-        'time_queued': utc_now_iso(),
-    }
-    patch_obj['jobs_queued/' + job_id] = 0
-    patch_obj[src]['jobs'][job_id] = 0
-
-
-def check_new_cl(handler):
-  '''Creates the CL + jobs entries in the DB for the given CL if doesn't exist
-
-  If exists check if a Presubmit-Ready label has been added and if so updates it
-  with the message + vote.
-  '''
-  change_id = handler.request.get('change_id')
-  rev_hash = handler.request.get('rev_hash')
-  cl = handler.request.get('cl')
-  patchset = handler.request.get('patchset')
-  ref = handler.request.get('ref')
-  wants_vote = handler.request.get('wants_vote') == '1'
-
-  # We want to do two things here:
-  # 1) If the CL doesn't exist (hence vote_prop is None) carry on below and
-  #    enqueue jobs for it.
-  # 2) If the CL exists, we don't need to kick new jobs. However, the user
-  #    might have addeed a Presubmit-Ready label after we created the CL. In
-  #    this case update the |wants_vote| flag and return.
-  vote_prop = req('GET', '%s/cls/%s-%s/wants_vote.json' % (DB, cl, patchset))
-  if vote_prop is not None:
-    if vote_prop != wants_vote and wants_vote:
-      logging.info('Updating wants_vote flag on %s-%s', cl, patchset)
-      req('PUT', '%s/cls/%s-%s/wants_vote.json' % (DB, cl, patchset), body=True)
-      # If the label is applied after we have finished running all the jobs just
-      # jump straight to the voting.
-      defer('check_pending_cl', cl_and_ps='%s-%s' % (cl, patchset))
-    return
-
-  # This is the first time we see this patchset, enqueue jobs for it.
-
-  # Dequeue jobs for older patchsets, if any.
-  defer('cancel_older_jobs', cl=cl, patchset=patchset)
-
-  src = 'cls/%s-%s' % (cl, patchset)
-  # Enqueue jobs for the latest patchset.
-  patch_obj = {}
-  patch_obj['cls_pending/%s-%s' % (cl, patchset)] = 0
-  patch_obj[src] = {
-      'change_id': change_id,
-      'revision_id': rev_hash,
-      'time_queued': utc_now_iso(),
-      'jobs': {},
-      'wants_vote': wants_vote,
-  }
-  append_jobs(patch_obj, src, ref)
-  req('PATCH', DB + '.json', body=patch_obj)
-
-
-def cancel_older_jobs(handler):
-  cl = handler.request.get('cl')
-  patchset = handler.request.get('patchset')
-  first_key = '%s-0' % cl
-  last_key = '%s-z' % cl
-  filt = 'orderBy="$key"&startAt="%s"&endAt="%s"' % (first_key, last_key)
-  cl_objs = req('GET', '%s/cls.json?%s' % (DB, filt)) or {}
-  for cl_and_ps, cl_obj in cl_objs.iteritems():
-    ps = int(cl_and_ps.split('-')[-1])
-    if cl_obj.get('time_ended') or ps >= int(patchset):
-      continue
-    logging.info('Cancelling jobs for previous patchset %s', cl_and_ps)
-    map(lambda x: defer('cancel_job', job_id=x), cl_obj['jobs'].keys())
-
-
-def check_pending_cls(handler):
-  # Check if any pending CL has completed (all jobs are done). If so publish
-  # the comment and vote on the CL.
-  pending_cls = req('GET', '%s/cls_pending.json' % DB) or {}
-  for cl_and_ps, _ in pending_cls.iteritems():
-    defer('check_pending_cl', cl_and_ps=cl_and_ps)
-
-
-def check_pending_cl(handler):
-  # This function can be called twice on the same CL, e.g., in the case when the
-  # Presubmit-Ready label is applied after we have finished running all the
-  # jobs (we run presubmit regardless, only the voting is conditioned by PR).
-  cl_and_ps = handler.request.get('cl_and_ps')
-  cl_obj = req('GET', '%s/cls/%s.json' % (DB, cl_and_ps))
-  all_jobs = cl_obj.get('jobs', {}).keys()
-  pending_jobs = []
-  for job_id in all_jobs:
-    job_status = req('GET', '%s/jobs/%s/status.json' % (DB, job_id))
-    pending_jobs += [job_id] if job_status in ('QUEUED', 'STARTED') else []
-
-  if pending_jobs:
-    # If the CL has been pending for too long cancel all its jobs. Upon the next
-    # scan it will be deleted and optionally voted on.
-    t_queued = parse_iso_time(cl_obj['time_queued'])
-    age_sec = (datetime.utcnow() - t_queued).total_seconds()
-    if age_sec > CL_TIMEOUT_SEC:
-      logging.warning('Canceling %s, it has been pending for too long (%s sec)',
-                      cl_and_ps, int(age_sec))
-      map(lambda x: defer('cancel_job', job_id=x), pending_jobs)
-    return
-
-  logging.info('All jobs completed for CL %s', cl_and_ps)
-
-  # Remove the CL from the pending queue and update end time.
-  patch_obj = {
-      'cls_pending/%s' % cl_and_ps: {},  # = DELETE
-      'cls/%s/time_ended' % cl_and_ps: cl_obj.get('time_ended', utc_now_iso()),
-  }
-  req('PATCH', '%s.json' % DB, body=patch_obj)
-  defer('update_cl_metrics', src='cls/' + cl_and_ps)
-  map(lambda x: defer('update_job_metrics', job_id=x), all_jobs)
-  if cl_obj.get('wants_vote'):
-    defer('comment_and_vote_cl', cl_and_ps=cl_and_ps)
-
-
-def comment_and_vote_cl(handler):
-  cl_and_ps = handler.request.get('cl_and_ps')
-  cl_obj = req('GET', '%s/cls/%s.json' % (DB, cl_and_ps))
-
-  if cl_obj.get('voted'):
-    logging.error('Already voted on CL %s', cl_and_ps)
-    return
-
-  if not cl_obj['wants_vote'] or not GERRIT_VOTING_ENABLED:
-    logging.info('Skipping voting on CL %s', cl_and_ps)
-    return
-
-  cl_vote = 1
-  passed_jobs = []
-  failed_jobs = {}
-  ui_links = []
-  cancelled = False
-  for job_id in cl_obj['jobs'].keys():
-    job_obj = req('GET', '%s/jobs/%s.json' % (DB, job_id))
-    job_config = JOB_CONFIGS.get(job_obj['type'], {})
-    if job_obj['status'] == 'CANCELLED':
-      cancelled = True
-    if '-ui-' in job_id:
-      ui_links.append('https://storage.googleapis.com/%s/%s/ui/index.html' %
-                      (GCS_ARTIFACTS, job_id))
-    if job_obj['status'] == 'COMPLETED':
-      passed_jobs.append(job_id)
-    elif not job_config.get('SKIP_VOTING', False):
-      cl_vote = -1
-      failed_jobs[job_id] = job_obj['status']
-
-  msg = ''
-  if cancelled:
-    msg += 'Some jobs in this CI run were cancelled. This likely happened '
-    msg += 'because a new patchset has been uploaded. Skipping vote.\n'
-  log_url = CI_SITE + '/#!/logs'
-  if failed_jobs:
-    msg += 'FAIL:\n'
-    msg += ''.join([
-        ' %s/%s (%s)\n' % (log_url, job_id, status)
-        for (job_id, status) in failed_jobs.iteritems()
-    ])
-  if passed_jobs:
-    msg += 'PASS:\n'
-    msg += ''.join([' %s/%s\n' % (log_url, job_id) for job_id in passed_jobs])
-  if ui_links:
-    msg += 'Artifacts:\n' + ''.join(' %s\n' % link for link in ui_links)
-  msg += 'CI page for this CL:\n'
-  msg += ' https://ci.perfetto.dev/#!/cls/%s\n' % cl_and_ps.split('-')[0]
-  body = {'labels': {}, 'message': msg}
-  if not cancelled:
-    body['labels']['Code-Review'] = cl_vote
-  logging.info('Posting results for CL %s', cl_and_ps)
-  url = 'https://%s/a/changes/%s/revisions/%s/review' % (
-      GERRIT_HOST, cl_obj['change_id'], cl_obj['revision_id'])
-  req('POST', url, body=body, gerrit=True)
-  req('PUT', '%s/cls/%s/voted.json' % (DB, cl_and_ps), body=True)
-
-
-def queue_postsubmit_jobs(handler):
-  '''Creates the jobs entries in the DB for the given branch or revision
-
-  Can be called in two modes:
-    1. ?branch=master: Will retrieve the SHA1 of master and call the one below.
-    2. ?branch=master&rev=deadbeef1234: queues jobs for the given revision.
-  '''
-  prj = urllib.quote(GERRIT_PROJECT, '')
-  branch = handler.request.get('branch')
-  revision = handler.request.get('revision')
-  assert branch
-
-  if not revision:
-    # Get the commit SHA1 of the head of the branch.
-    url = 'https://%s/a/projects/%s/branches/%s' % (GERRIT_HOST, prj, branch)
-    revision = req('GET', url, gerrit=True)['revision']
-    assert revision
-    defer('queue_postsubmit_jobs', branch=branch, revision=revision)
-    return
-
-  # Get the committer datetime for the given revision.
-  url = 'https://%s/a/projects/%s/commits/%s' % (GERRIT_HOST, prj, revision)
-  commit_info = req('GET', url, gerrit=True)
-  time_committed = commit_info['committer']['date'].split('.')[0]
-  time_committed = datetime.strptime(time_committed, '%Y-%m-%d %H:%M:%S')
-
-  # Enqueue jobs.
-  src = 'branches/%s-%s' % (branch, time_committed.strftime('%Y%m%d%H%M%S'))
-  now = datetime.utcnow()
-  patch_obj = {
-      src: {
-          'rev': revision,
-          'subject': commit_info['subject'][:100],
-          'author': commit_info['author'].get('email', 'N/A'),
-          'time_committed': utc_now_iso(time_committed),
-          'time_queued': utc_now_iso(),
-          'jobs': {},
-      }
-  }
-  ref = 'refs/heads/' + branch
-  append_jobs(patch_obj, src, ref, now)
-  req('PATCH', DB + '.json', body=patch_obj)
-
-
-def delete_stale_jobs(handler):
-  '''Deletes jobs that are left in the running queue for too long
-
-  This is usually due to a crash in the VM that handles them.
-  '''
-  running_jobs = req('GET', '%s/jobs_running.json?shallow=true' % (DB)) or {}
-  for job_id in running_jobs.iterkeys():
-    job = req('GET', '%s/jobs/%s.json' % (DB, job_id))
-    time_started = parse_iso_time(job.get('time_started', utc_now_iso()))
-    age = (datetime.now() - time_started).total_seconds()
-    if age > JOB_TIMEOUT_SEC * 2:
-      defer('cancel_job', job_id=job_id)
-
-
-def cancel_job(handler):
-  '''Cancels a job if not completed or failed.
-
-  This function is racy: workers can complete the queued jobs while we mark them
-  as cancelled. The result of such race is still acceptable.'''
-  job_id = handler.request.get('job_id')
-  status = req('GET', '%s/jobs/%s/status.json' % (DB, job_id))
-  patch_obj = {
-      'jobs_running/%s' % job_id: {},  # = DELETE,
-      'jobs_queued/%s' % job_id: {},  # = DELETE,
-  }
-  if status in ('QUEUED', 'STARTED'):
-    patch_obj['jobs/%s/status' % job_id] = 'CANCELLED'
-    patch_obj['jobs/%s/time_ended' % job_id] = utc_now_iso()
-  req('PATCH', DB + '.json', body=patch_obj)
-
-
-def delete_expired_logs(handler):
-  logs = req('GET', '%s/logs.json?shallow=true' % (DB)) or {}
-  for job_id in logs.iterkeys():
-    age_days = (datetime.now() - datetime.strptime(job_id[:8], '%Y%m%d')).days
-    if age_days > LOGS_TTL_DAYS:
-      defer('delete_job_logs', job_id=job_id)
-
-
-def delete_job_logs(handler):
-  req('DELETE', '%s/logs/%s.json' % (DB, handler.request.get('job_id')))
-
-
-def update_cl_metrics(handler):
-  cl_obj = req('GET', '%s/%s.json' % (DB, handler.request.get('src')))
-  t_queued = parse_iso_time(cl_obj['time_queued'])
-  t_ended = parse_iso_time(cl_obj['time_ended'])
-  write_metrics({
-      'ci_cl_completion_time': {
-          'l': {},
-          'v': int((t_ended - t_queued).total_seconds())
-      }
-  })
-
-
-def update_job_metrics(handler):
-  job_id = handler.request.get('job_id')
-  job = req('GET', '%s/jobs/%s.json' % (DB, job_id))
-  metrics = {}
-  if 'time_queued' in job and 'time_started' in job:
-    t_queued = parse_iso_time(job['time_queued'])
-    t_started = parse_iso_time(job['time_started'])
-    metrics['ci_job_queue_time'] = {
-        'l': {
-            'job_type': job['type']
-        },
-        'v': int((t_started - t_queued).total_seconds())
-    }
-  if 'time_ended' in job and 'time_started' in job:
-    t_started = parse_iso_time(job['time_started'])
-    t_ended = parse_iso_time(job['time_ended'])
-    metrics['ci_job_run_time'] = {
-        'l': {
-            'job_type': job['type']
-        },
-        'v': int((t_ended - t_started).total_seconds())
-    }
-  if metrics:
-    write_metrics(metrics)
-
-
-def update_queue_metrics(handler):
-  # Update the stackdriver metric that will drive the autoscaler.
-  queued = req('GET', DB + '/jobs_queued.json?shallow=true') or {}
-  running = req('GET', DB + '/jobs_running.json?shallow=true') or {}
-  write_metrics({'ci_job_queue_len': {'v': len(queued) + len(running)}})
-
-
-class ControllerHandler(webapp2.RequestHandler):
-  ACTIONS = {
-      'start': start,
-      'tick': tick,
-      'check_pending_cls': check_pending_cls,
-      'check_pending_cl': check_pending_cl,
-      'check_new_cls': check_new_cls,
-      'check_new_cl': check_new_cl,
-      'comment_and_vote_cl': comment_and_vote_cl,
-      'cancel_older_jobs': cancel_older_jobs,
-      'queue_postsubmit_jobs': queue_postsubmit_jobs,
-      'update_job_metrics': update_job_metrics,
-      'update_queue_metrics': update_queue_metrics,
-      'update_cl_metrics': update_cl_metrics,
-      'delete_expired_logs': delete_expired_logs,
-      'delete_job_logs': delete_job_logs,
-      'delete_stale_jobs': delete_stale_jobs,
-      'cancel_job': cancel_job,
-  }
-
-  def handle(self, action):
-    if action in ControllerHandler.ACTIONS:
-      return ControllerHandler.ACTIONS[action](self)
-    raise Exception('Invalid request %s' % action)
-
-  get = handle
-  post = handle
-
-
-app = webapp2.WSGIApplication([
-    ('/_ah/(start)', ControllerHandler),
-    (r'/controller/(\w+)', ControllerHandler),
-],
-                              debug=True)
diff --git a/infra/ci/controller/cron.yaml b/infra/ci/controller/cron.yaml
deleted file mode 100644
index ef9605b..0000000
--- a/infra/ci/controller/cron.yaml
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (C) 2019 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.
-cron:
-- description: "Run postsubmits"
-  url: /controller/queue_postsubmit_jobs?branch=master
-  schedule: every 1 hours
-  target: controller
-
-- description: "Logs cleanup"
-  url: /controller/delete_expired_logs
-  schedule: every 24 hours
-  target: controller
-
-- description: "Delete stale jobs from the running queue"
-  url: /controller/delete_stale_jobs
-  schedule: every 15 minutes
-  target: controller
-
-# This is unnecessary if everything works fine all the time, because each
-# /worker/tick task enqueues the next one. However if anything goes wrong the
-# chain would break. We use this cron job to re-kick it if this happens.
-- description: "Gerrit poller failsafe"
-  url: /controller/tick
-  schedule: every 5 minutes
-  target: controller
diff --git a/infra/ci/controller/index.yaml b/infra/ci/controller/index.yaml
deleted file mode 100644
index 36e4583..0000000
--- a/infra/ci/controller/index.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-indexes:
-# AUTOGENERATED
-
-# This index.yaml is automatically updated whenever the Cloud Datastore
-# emulator detects that a new type of query is run. If you want to manage the
-# index.yaml file manually, remove the "# AUTOGENERATED" marker line above.
-# If you want to manage some indexes manually, move them above the marker line.
-
diff --git a/infra/ci/controller/queue.yaml b/infra/ci/controller/queue.yaml
deleted file mode 100644
index 1c5e53e..0000000
--- a/infra/ci/controller/queue.yaml
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2019 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.
-queue:
-- name: tick
-  rate: 12/m
-  bucket_size: 1
-  max_concurrent_requests: 1
-  retry_parameters:
-    task_retry_limit: 1
-- name: deferred-jobs
-  rate: 50/s
-  bucket_size: 10
-  max_concurrent_requests: 10
-  retry_parameters:
-    task_retry_limit: 3
-    min_backoff_seconds: 5
-    max_backoff_seconds: 30
\ No newline at end of file
diff --git a/infra/ci/controller/stackdriver_metrics.py b/infra/ci/controller/stackdriver_metrics.py
deleted file mode 100644
index 2fa5fb8..0000000
--- a/infra/ci/controller/stackdriver_metrics.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# Copyright (C) 2019 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.
-
-STACKDRIVER_METRICS = {
-    'ci_job_queue_len': {
-        'name': 'ci_job_queue_len',
-        'displayName': 'ci_job_queue_len',
-        'description': 'Length of the CI jobs queue',
-        'type': 'custom.googleapis.com/perfetto-ci/ci_job_queue_len',
-        'metricKind': 'GAUGE',
-        'valueType': 'INT64',
-        'metadata': {
-            'samplePeriod': {
-                'seconds': 1
-            }
-        },
-        'labels': []
-    },
-    'ci_job_queue_time': {
-        'name': 'ci_job_queue_time',
-        'displayName': 'ci_job_queue_time',
-        'description': 'Queueing time of CI jobs, before they start running',
-        'type': 'custom.googleapis.com/perfetto-ci/ci_job_queue_time',
-        'metricKind': 'GAUGE',
-        'valueType': 'INT64',
-        'unit': 's',
-        'metadata': {
-            'samplePeriod': {
-                'seconds': 1
-            }
-        },
-        'labels': [{
-            'key': 'job_type',
-            'valueType': 'STRING'
-        }]
-    },
-    'ci_job_run_time': {
-        'name': 'ci_job_run_time',
-        'displayName': 'ci_job_run_time',
-        'description': 'Running time of CI jobs',
-        'type': 'custom.googleapis.com/perfetto-ci/ci_job_run_time',
-        'metricKind': 'GAUGE',
-        'valueType': 'INT64',
-        'unit': 's',
-        'metadata': {
-            'samplePeriod': {
-                'seconds': 1
-            }
-        },
-        'labels': [{
-            'key': 'job_type',
-            'valueType': 'STRING'
-        }]
-    },
-    'ci_cl_completion_time': {
-        'name': 'ci_cl_completion_time',
-        'displayName': 'ci_cl_completion_time',
-        'description': 'Time it takes for all jobs of a CL to complete',
-        'type': 'custom.googleapis.com/perfetto-ci/ci_cl_completion_time',
-        'metricKind': 'GAUGE',
-        'valueType': 'INT64',
-        'unit': 's',
-        'metadata': {
-            'samplePeriod': {
-                'seconds': 1
-            }
-        },
-        'labels': []
-    },
-}
diff --git a/infra/ci/frontend/.gitignore b/infra/ci/frontend/.gitignore
deleted file mode 100644
index 18a0855..0000000
--- a/infra/ci/frontend/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-config.py
-common_utils.py
-lib/
diff --git a/infra/ci/frontend/Makefile b/infra/ci/frontend/Makefile
deleted file mode 100644
index 14431aa..0000000
--- a/infra/ci/frontend/Makefile
+++ /dev/null
@@ -1,61 +0,0 @@
-# Copyright (C) 2019 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 $(shell python ../config.py makefile)
-
-SHASUM=shasum
-
-test: LOGLEVEL=info
-test: static_3p config.py common_utils.py static/config.js
-	dev_appserver.py app.yaml --dev_appserver_log_level ${LOGLEVEL}
-
-deploy: static_3p config.py common_utils.py static/config.js
-	gcloud app deploy -q app.yaml \
-		--project ${PROJECT} \
-		-v ${GAE_VERSION} \
-		--stop-previous-version
-
-config.py: ../config.py
-	cp ../$@ $@
-
-common_utils.py: ../common_utils.py
-	cp ../$@ $@
-
-static/config.js: ../config.py
-	../config.py js > $@
-
-static/third_party/xterm-3.14.4.min.css:
-	curl -Sso $@ https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.4/xterm.min.css
-	echo "ad80f73df001c943cfcd98d706dba050704f715d  $@" | ${SHASUM} -c || rm $@
-
-static/third_party/xterm-3.14.4.min.js:
-	curl -Sso $@ https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.4/xterm.min.js
-	echo "9a92b3fbb118fd2a672f7eb4e69598384ca91756  $@" | ${SHASUM} -c || rm $@
-
-static/third_party/xterm-3.14.4-addon-search.min.js:
-	curl -Sso $@ https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.4/addons/search/search.min.js
-	echo "73f55082d00c98b372cac1264ba9da70cdf603d0  $@" | ${SHASUM} -c || rm $@
-
-static/third_party/xterm-3.14.4-addon-fit.min.js:
-	curl -Sso $@ https://cdnjs.cloudflare.com/ajax/libs/xterm/3.14.4/addons/fit/fit.min.js
-	echo "64835b1b71e8ca2d5bbb1a8e3c7f8a8f1edb2e5c  $@" | ${SHASUM} -c || rm $@
-
-static/third_party/mithril-1.1.6.min.js:
-	curl -Sso $@ https://cdnjs.cloudflare.com/ajax/libs/mithril/1.1.6/mithril.min.js
-	echo "a204c02ee15c347cf368c3481bdea967b443c8d0  $@" | ${SHASUM} -c || rm $@
-
-static_3p: static/third_party/xterm-3.14.4.min.css static/third_party/xterm-3.14.4.min.js static/third_party/xterm-3.14.4-addon-search.min.js static/third_party/xterm-3.14.4-addon-fit.min.js static/third_party/mithril-1.1.6.min.js
-
-.PHONY: test deploy static_3p
diff --git a/infra/ci/frontend/app.yaml b/infra/ci/frontend/app.yaml
deleted file mode 100644
index fffd024..0000000
--- a/infra/ci/frontend/app.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (C) 2019 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.
-
-runtime: python27
-api_version: 1
-threadsafe: yes
-service: default
-handlers:
-- url: /
-  static_files: static/index.html
-  upload: static/index.html
-  secure: always
-  redirect_http_response_code: 301
-- url: /static/
-  static_dir: static/
-  secure: always
-- url: /gerrit/.*
-  script: frontend.app
-  secure: always
diff --git a/infra/ci/frontend/frontend.py b/infra/ci/frontend/frontend.py
deleted file mode 100644
index ff16ad7..0000000
--- a/infra/ci/frontend/frontend.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright (C) 2019 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.
-
-import logging
-import webapp2
-import urllib
-
-from google.appengine.api import urlfetch
-from google.appengine.api import memcache
-from config import GERRIT_HOST, GERRIT_PROJECT
-''' Makes anonymous GET-only requests to Gerrit.
-
-Solves the lack of CORS headers from AOSP gerrit.'''
-
-
-def req_cached(url):
-  '''Used for requests that return immutable data, avoid hitting Gerrit 500'''
-  resp = memcache.get(url)
-  if resp is not None:
-    return 200, resp
-  result = urlfetch.fetch(url)
-  if result.status_code == 200:
-    memcache.add(url, result.content, 3600 * 24)
-  return result.status_code, result.content
-
-
-class GerritCommitsHandler(webapp2.RequestHandler):
-
-  def get(self, sha1):
-    project = urllib.quote(GERRIT_PROJECT, '')
-    url = 'https://%s/projects/%s/commits/%s' % (GERRIT_HOST, project, sha1)
-    status, content = req_cached(url)
-    self.response.status_int = status
-    self.response.write(content[4:])  # 4: -> Strip Gerrit XSSI chars.
-
-
-class GerritLogHandler(webapp2.RequestHandler):
-
-  def get(self, first, second):
-    url = 'https://%s/%s/+log/%s..%s?format=json' % (GERRIT_HOST.replace(
-        '-review', ''), GERRIT_PROJECT, first, second)
-    status, content = req_cached(url)
-    self.response.status_int = status
-    self.response.write(content[4:])  # 4: -> Strip Gerrit XSSI chars.
-
-
-class GerritChangesHandler(webapp2.RequestHandler):
-
-  def get(self):
-    url = 'https://%s/changes/?q=project:%s+' % (GERRIT_HOST, GERRIT_PROJECT)
-    url += self.request.query_string
-    result = urlfetch.fetch(url)
-    self.response.status_int = result.status_code
-    self.response.write(result.content[4:])  # 4: -> Strip Gerrit XSSI chars.
-
-
-app = webapp2.WSGIApplication([
-    ('/gerrit/commits/([a-f0-9]+)', GerritCommitsHandler),
-    ('/gerrit/log/([a-f0-9]+)..([a-f0-9]+)', GerritLogHandler),
-    ('/gerrit/changes/', GerritChangesHandler),
-],
-                              debug=True)
diff --git a/infra/ci/frontend/index.yaml b/infra/ci/frontend/index.yaml
deleted file mode 100644
index 6536212..0000000
--- a/infra/ci/frontend/index.yaml
+++ /dev/null
@@ -1,2 +0,0 @@
-indexes:
-# AUTOGENERATED
diff --git a/infra/ci/frontend/static/.gitignore b/infra/ci/frontend/static/.gitignore
deleted file mode 100644
index e5df90e..0000000
--- a/infra/ci/frontend/static/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-config.js
-third_party/
diff --git a/infra/ci/frontend/static/icon.png b/infra/ci/frontend/static/icon.png
deleted file mode 100644
index 611bad8..0000000
--- a/infra/ci/frontend/static/icon.png
+++ /dev/null
Binary files differ
diff --git a/infra/ci/frontend/static/index.html b/infra/ci/frontend/static/index.html
deleted file mode 100644
index 7c67790..0000000
--- a/infra/ci/frontend/static/index.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<!doctype html>
-<html>
-<!--
-    Copyright 2019 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.
-  -->
-
-<head>
-    <meta charset="utf-8">
-    <title>Perfetto CI</title>
-    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
-    <link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:100,300,400" rel="stylesheet">
-    <link rel="stylesheet" type="text/css" href="/static/third_party/xterm-3.14.4.min.css">
-    <link rel="stylesheet" type="text/css" href="/static/style.css">
-    <link href="static/icon.png" rel="shortcut icon">
-</head>
-
-<body>
-</body>
-
-<script src="https://www.gstatic.com/firebasejs/6.2.4/firebase-app.js"></script>
-<script src="https://www.gstatic.com/firebasejs/6.2.4/firebase-database.js"></script>
-<script src="/static/third_party/xterm-3.14.4.min.js"></script>
-<script src="/static/third_party/xterm-3.14.4-addon-fit.min.js"></script>
-<script src="/static/third_party/xterm-3.14.4-addon-search.min.js"></script>
-<script src="/static/third_party/mithril-1.1.6.min.js"></script>
-<script src="/static/config.js"></script>
-<script src="/static/script.js"></script>
-
-</html>
diff --git a/infra/ci/frontend/static/script.js b/infra/ci/frontend/static/script.js
deleted file mode 100644
index d6fe73e..0000000
--- a/infra/ci/frontend/static/script.js
+++ /dev/null
@@ -1,820 +0,0 @@
-/**
- * Copyright (c) 2019 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.
- */
-
-'use strict';
-
-// If you add or remove job types, do not forget to fix the colspans below.
-const JOB_TYPES = [
-  { id: 'linux-gcc7-x86_64-release', label: 'rel' },
-  { id: 'linux-clang-x86_64-debug', label: 'dbg' },
-  { id: 'linux-clang-x86_64-tsan', label: 'tsan' },
-  { id: 'linux-clang-x86_64-msan', label: 'msan' },
-  { id: 'linux-clang-x86_64-asan_lsan', label: '{a,l}san' },
-  { id: 'linux-clang-x86-asan_lsan', label: 'x86 {a,l}san' },
-  { id: 'linux-clang-x86_64-libfuzzer', label: 'fuzzer' },
-  { id: 'linux-clang-x86_64-bazel', label: 'bazel' },
-  { id: 'ui-clang-x86_64-debug', label: 'dbg' },
-  { id: 'ui-clang-x86_64-release', label: 'rel' },
-  { id: 'android-clang-arm-release', label: 'rel' },
-  { id: 'android-clang-arm-asan', label: 'asan' },
-];
-
-// Chart IDs from the Stackdriver daashboard
-// https://app.google.stackdriver.com/dashboards/5008687313278081798?project=perfetto-ci.
-const STATS_CHART_IDS = [
-  '2617092544855936024',   // Job queue len.
-  '15349606823829051218',  // Workers CPU usage
-  '2339121267466167448',   // E2E CL test time (median).
-  '6055813426334723906',   // Job run time (median).
-  '13112965165933080534',  // Job queue time (P95).
-  '2617092544855936456',   // Job run time (P95).
-];
-
-const state = {
-  // An array of recent CL objects retrieved from Gerrit.
-  gerritCls: [],
-
-  // A map of sha1 -> Gerrit commit object.
-  // See https://gerrit-review.googlesource.com/Documentation/rest-api-projects.html#get-commit
-  gerritCommits: {},
-
-  // A map of git-log ranges to commit objects:
-  // 'dead..beef' -> [commit1, 2]
-  gerritLogs: {},
-
-  // Maps 'cls/1234-1' or 'branches/xxxx' -> array of job ids.
-  dbJobSets: {},
-
-  // Maps 'jobId' -> DB job object, as perf /ci/jobs/jobID.
-  // A jobId looks like 20190702143507-1008614-9-android-clang-arm.
-  dbJobs: {},
-
-  // Maps 'worker id' -> DB wokrker object, as per /ci/workers.
-  dbWorker: {},
-
-  // Maps 'master-YYMMDD' -> DB branch object, as perf /ci/branches/xxx.
-  dbBranches: {},
-  getBranchKeys: () => Object.keys(state.dbBranches).sort().reverse(),
-
-  // Maps 'CL number' -> true|false. Retains the collapsed/expanded information
-  // for each row in the CLs table.
-  expandCl: {},
-
-  postsubmitShown: 3,
-
-  // Lines that will be appended to the terminal on the next redraw() cycle.
-  termLines: [
-    'Hover a CL icon to see the log tail.',
-    'Click on it to load the full log.'
-  ],
-  termJobId: undefined, // The job id currently being shown by the terminal.
-  termClear: false,     // If true the next redraw will clear the terminal.
-  redrawPending: false,
-
-  // State for the Jobs page. These are arrays of job ids.
-  jobsQueued: [],
-  jobsRunning: [],
-  jobsRecent: [],
-
-  // Firebase DB listeners (the objects returned by the .ref() operator).
-  realTimeLogRef: undefined, // Ref for the real-time log streaming.
-  workersRef: undefined,
-  jobsRunningRef: undefined,
-  jobsQueuedRef: undefined,
-  jobsRecentRef: undefined,
-  clRefs: {},    // '1234-1' -> Ref subscribed to updates on the given cl.
-  jobRefs: {},   // '....-arm-asan' -> Ref subscribed updates on the given job.
-  branchRefs: {} // 'master' -> Ref subscribed updates on the given branch.
-};
-
-let term = undefined;
-
-function main() {
-  firebase.initializeApp({ databaseURL: cfg.DB_ROOT });
-  Terminal.applyAddon(fit);
-  Terminal.applyAddon(search);
-
-  m.route(document.body, '/cls', {
-    '/cls': CLsPageRenderer,
-    '/cls/:cl': CLsPageRenderer,
-    '/logs/:jobId': LogsPageRenderer,
-    '/jobs': JobsPageRenderer,
-    '/jobs/:jobId': JobsPageRenderer,
-    '/stats/:period': StatsPageRenderer,
-  });
-
-  setInterval(fetchGerritCLs, 15000);
-  fetchGerritCLs();
-  fetchCIStatusForBranch('master');
-}
-
-// -----------------------------------------------------------------------------
-// Rendering functions
-// -----------------------------------------------------------------------------
-
-function renderHeader() {
-  const active = id => m.route.get().startsWith(`/${id}`) ? '.active' : '';
-  const logUrl = 'https://goto.google.com/perfetto-ci-logs-';
-  const docsUrl = 'https://docs.perfetto.dev/#/continuous-integration';
-  return m('header',
-    m('h1', 'Perfetto ', m('span', 'CI')),
-    m('nav',
-      m(`div${active('cls')}`, m('a[href=/#!/cls]', 'CLs')),
-      m(`div${active('jobs')}`, m('a[href=/#!/jobs]', 'Jobs')),
-      m(`div${active('stats')}`, m('a[href=/#!/stats/1d]', 'Stats')),
-      m(`div`, m(`a[href=${docsUrl}][target=_blank]`, 'Docs')),
-      m(`div.logs`, 'Logs',
-        m('div', m(`a[href=${logUrl}controller][target=_blank]`, 'Controller')),
-        m('div', m(`a[href=${logUrl}workers][target=_blank]`, 'Workers')),
-        m('div', m(`a[href=${logUrl}frontend][target=_blank]`, 'Frontend')),
-      ),
-    )
-  );
-}
-
-var CLsPageRenderer = {
-  view: function (vnode) {
-    const allCols = 4 + JOB_TYPES.length;
-    const postsubmitHeader = m('tr',
-      m(`td.header[colspan=${allCols}]`, 'Post-submit')
-    );
-
-    const postsubmitLoadMore = m('tr',
-      m(`td[colspan=${allCols}]`,
-        m('a[href=#]',
-          { onclick: () => state.postsubmitShown += 10 },
-          'Load more'
-        )
-      )
-    );
-
-    const presubmitHeader = m('tr',
-      m(`td.header[colspan=${allCols}]`, 'Pre-submit')
-    );
-
-    let branchRows = [];
-    const branchKeys = state.getBranchKeys();
-    for (let i = 0; i < branchKeys.length && i < state.postsubmitShown; i++) {
-      const rowsForBranch = renderPostsubmitRow(branchKeys[i]);
-      branchRows = branchRows.concat(rowsForBranch);
-    }
-
-    let clRows = [];
-    for (const gerritCl of state.gerritCls) {
-      if (vnode.attrs.cl && gerritCl.num != vnode.attrs.cl) continue;
-      clRows = clRows.concat(renderCLRow(gerritCl));
-    }
-
-    let footer = [];
-    if (vnode.attrs.cl) {
-      footer = m('footer',
-        `Showing only CL ${vnode.attrs.cl} - `,
-        m(`a[href=#!/cls]`, 'Click here to see all CLs')
-      );
-    }
-
-    return [
-      renderHeader(),
-      m('main#cls',
-        m('div.table-scrolling-container',
-          m('table.main-table',
-            m('thead',
-              m('tr',
-                m('td[rowspan=4]', 'Subject'),
-                m('td[rowspan=4]', 'Status'),
-                m('td[rowspan=4]', 'Owner'),
-                m('td[rowspan=4]', 'Updated'),
-                m('td[colspan=12]', 'Bots'),
-              ),
-              m('tr',
-                m('td[colspan=10]', 'linux'),
-                m('td[colspan=2]', 'android'),
-              ),
-              m('tr',
-                m('td', 'gcc7'),
-                m('td[colspan=7]', 'clang'),
-                m('td[colspan=2]', 'ui'),
-                m('td[colspan=2]', 'clang-arm'),
-              ),
-              m('tr#cls_header',
-                JOB_TYPES.map(job => m(`td#${job.id}`, job.label))
-              ),
-            ),
-            m('tbody',
-              postsubmitHeader,
-              branchRows,
-              postsubmitLoadMore,
-              presubmitHeader,
-              clRows,
-            )
-          ),
-          footer,
-        ),
-        m(TermRenderer),
-      ),
-    ];
-  }
-};
-
-
-function getLastUpdate(lastUpdate) {
-  const lastUpdateMins = Math.ceil((Date.now() - lastUpdate) / 60000);
-  if (lastUpdateMins < 60)
-    return lastUpdateMins + ' mins ago';
-  if (lastUpdateMins < 60 * 24)
-    return Math.ceil(lastUpdateMins / 60) + ' hours ago';
-  return lastUpdate.toLocaleDateString();
-}
-
-function renderCLRow(cl) {
-  const expanded = !!state.expandCl[cl.num];
-  const toggleExpand = () => {
-    state.expandCl[cl.num] ^= 1;
-    fetchCIJobsForAllPatchsetOfCL(cl.num);
-  }
-  const rows = [];
-
-  // Create the row for the latest patchset (as fetched by Gerrit).
-  rows.push(m(`tr.${cl.status}`,
-    m('td',
-      m(`i.material-icons.expand${expanded ? '.expanded' : ''}`,
-        { onclick: toggleExpand },
-        'arrow_right'
-      ),
-      m(`a[href=${cfg.GERRIT_REVIEW_URL}/+/${cl.num}/${cl.psNum}]`,
-        `${cl.subject}`, m('span.ps', `#${cl.psNum}`))
-    ),
-    m('td', cl.status),
-    m('td', stripEmail(cl.owner)),
-    m('td', getLastUpdate(cl.lastUpdate)),
-    JOB_TYPES.map(x => renderClJobCell(`cls/${cl.num}-${cl.psNum}`, x.id))
-  ));
-
-  // If the usere clicked on the expand button, show also the other patchsets
-  // present in the CI DB.
-  for (let psNum = cl.psNum; expanded && psNum > 0; psNum--) {
-    const src = `cls/${cl.num}-${psNum}`;
-    const jobs = state.dbJobSets[src];
-    if (!jobs) continue;
-    rows.push(m(`tr.nested`,
-      m('td',
-        m(`a[href=${cfg.GERRIT_REVIEW_URL}/+/${cl.num}/${psNum}]`,
-          '  Patchset', m('span.ps', `#${psNum}`))
-      ),
-      m('td', ''),
-      m('td', ''),
-      m('td', ''),
-      JOB_TYPES.map(x => renderClJobCell(src, x.id))
-    ));
-  }
-
-  return rows;
-}
-
-function renderPostsubmitRow(key) {
-  const branch = state.dbBranches[key];
-  console.assert(branch !== undefined);
-  const subject = branch.subject;
-  let rows = [];
-  rows.push(m(`tr`,
-    m('td',
-      m(`a[href=${cfg.REPO_URL}/+/${branch.rev}]`,
-        subject, m('span.ps', `#${branch.rev.substr(0, 8)}`)
-      )
-    ),
-    m('td', ''),
-    m('td', stripEmail(branch.author)),
-    m('td', getLastUpdate(new Date(branch.time_committed))),
-    JOB_TYPES.map(x => renderClJobCell(`branches/${key}`, x.id))
-  ));
-
-
-  const allKeys = state.getBranchKeys();
-  const curIdx = allKeys.indexOf(key);
-  if (curIdx >= 0 && curIdx < allKeys.length - 1) {
-    const nextKey = allKeys[curIdx + 1];
-    const range = `${state.dbBranches[nextKey].rev}..${branch.rev}`;
-    const logs = (state.gerritLogs[range] || []).slice(1);
-    for (const log of logs) {
-      if (log.parents.length < 2)
-        continue;  // Show only merge commits.
-      rows.push(
-        m('tr.nested',
-          m('td',
-            m(`a[href=${cfg.REPO_URL}/+/${log.commit}]`,
-              log.message.split('\n')[0],
-              m('span.ps', `#${log.commit.substr(0, 8)}`)
-            )
-          ),
-          m('td', ''),
-          m('td', stripEmail(log.author.email)),
-          m('td', getLastUpdate(parseGerritTime(log.committer.time))),
-          m(`td[colspan=${JOB_TYPES.length}]`,
-            'No post-submit was run for this revision'
-          ),
-        )
-      );
-    }
-  }
-
-  return rows;
-}
-
-function renderJobLink(jobId, jobStatus) {
-  const ICON_MAP = {
-    'COMPLETED': 'check_circle',
-    'STARTED': 'hourglass_full',
-    'QUEUED': 'schedule',
-    'FAILED': 'bug_report',
-    'CANCELLED': 'cancel',
-    'INTERRUPTED': 'cancel',
-    'TIMED_OUT': 'notification_important',
-  };
-  const icon = ICON_MAP[jobStatus] || 'clear';
-  const eventHandlers = jobId ? { onmouseover: () => showLogTail(jobId) } : {};
-  const logUrl = jobId ? `#!/logs/${jobId}` : '#';
-  return m(`a.${jobStatus}[href=${logUrl}][title=${jobStatus}]`,
-    eventHandlers,
-    m(`i.material-icons`, icon)
-  );
-}
-
-function renderClJobCell(src, jobType) {
-  let jobStatus = 'UNKNOWN';
-  let jobId = undefined;
-
-  // To begin with check that the given CL/PS is present in the DB (the
-  // AppEngine cron job might have not seen that at all yet).
-  // If it is, find the global job id for the given jobType for the passed CL.
-  for (const id of (state.dbJobSets[src] || [])) {
-    const job = state.dbJobs[id];
-    if (job !== undefined && job.type == jobType) {
-      // We found the job object that corresponds to jobType for the given CL.
-      jobStatus = job.status;
-      jobId = id;
-    }
-  }
-  return m('td.job', renderJobLink(jobId, jobStatus));
-}
-
-const TermRenderer = {
-  oncreate: function (vnode) {
-    console.log('Creating terminal object');
-    term = new Terminal({ rows: 6, fontSize: 12, scrollback: 100000 });
-    term.open(vnode.dom);
-    term.fit();
-    if (vnode.attrs.focused) term.focus();
-  },
-  onremove: function (vnode) {
-    term.destroy();
-  },
-  onupdate: function (vnode) {
-    if (state.termClear) {
-      term.clear()
-      state.termClear = false;
-    }
-    for (const line of state.termLines) {
-      term.write(line + '\r\n');
-    }
-    state.termLines = [];
-  },
-  view: function () {
-    return m('.term-container',
-      {
-        onkeydown: (e) => {
-          if (e.key === 'f' && (e.ctrlKey || e.metaKey)) {
-            document.querySelector('.term-search').select();
-            e.preventDefault();
-          }
-        }
-      },
-      m('input[type=text][placeholder=search and press Enter].term-search', {
-        onkeydown: (e) => {
-          if (e.key !== 'Enter') return;
-          if (e.shiftKey) {
-            term.findNext(e.target.value);
-          } else {
-            term.findPrevious(e.target.value);
-          }
-          e.stopPropagation();
-          e.preventDefault();
-        }
-      })
-    );
-  }
-};
-
-const LogsPageRenderer = {
-  oncreate: function (vnode) {
-    showFullLog(vnode.attrs.jobId);
-  },
-  view: function () {
-    return [
-      renderHeader(),
-      m(TermRenderer, { focused: true })
-    ];
-  }
-}
-
-const JobsPageRenderer = {
-  oncreate: function (vnode) {
-    fetchRecentJobsStatus();
-    fetchWorkers();
-  },
-
-  createWorkerTable: function () {
-    const makeWokerRow = workerId => {
-      const worker = state.dbWorker[workerId];
-      if (worker.status === 'TERMINATED') return [];
-      return m('tr',
-        m('td', worker.host),
-        m('td', workerId),
-        m('td', worker.status),
-        m('td', getLastUpdate(new Date(worker.last_update))),
-        m('td', m(`a[href=#!/jobs/${worker.job_id}]`, worker.job_id)),
-      );
-    };
-    return m('table.main-table',
-      m('thead',
-        m('tr', m('td[colspan=5]', 'Workers')),
-        m('tr',
-          m('td', 'Host'),
-          m('td', 'Worker'),
-          m('td', 'Status'),
-          m('td', 'Last ping'),
-          m('td', 'Job'),
-        )
-      ),
-      m('tbody', Object.keys(state.dbWorker).map(makeWokerRow))
-    );
-  },
-
-  createJobsTable: function (vnode, title, jobIds) {
-    const tStr = function (tStart, tEnd) {
-      return new Date(tEnd - tStart).toUTCString().substr(17, 9);
-    };
-
-    const makeJobRow = function (jobId) {
-      const job = state.dbJobs[jobId] || {};
-      let cols = [
-        m('td.job.align-left',
-          renderJobLink(jobId, job ? job.status : undefined),
-          m(`span.status.${job.status}`, job.status)
-        )
-      ];
-      if (job) {
-        const tQ = Date.parse(job.time_queued);
-        const tS = Date.parse(job.time_started);
-        const tE = Date.parse(job.time_ended) || Date.now();
-        let cell = m('');
-        if (job.src === undefined) {
-          cell = '?';
-        } else if (job.src.startsWith('cls/')) {
-          const cl_and_ps = job.src.substr(4).replace('-', '/');
-          const href = `${cfg.GERRIT_REVIEW_URL}/+/${cl_and_ps}`;
-          cell = m(`a[href=${href}][target=_blank]`, cl_and_ps);
-        } else if (job.src.startsWith('branches/')) {
-          cell = job.src.substr(9).split('-')[0]
-        }
-        cols.push(m('td', cell));
-        cols.push(m('td', `${job.type}`));
-        cols.push(m('td', `${job.worker || ''}`));
-        cols.push(m('td', `${job.time_queued}`));
-        cols.push(m(`td[title=Start ${job.time_started}]`, `${tStr(tQ, tS)}`));
-        cols.push(m(`td[title=End ${job.time_ended}]`, `${tStr(tS, tE)}`));
-      } else {
-        cols.push(m('td[colspan=6]', jobId));
-      }
-      return m(`tr${vnode.attrs.jobId === jobId ? '.selected' : ''}`, cols)
-    };
-
-    return m('table.main-table',
-      m('thead',
-        m('tr', m('td[colspan=7]', title)),
-
-        m('tr',
-          m('td', 'Status'),
-          m('td', 'CL'),
-          m('td', 'Type'),
-          m('td', 'Worker'),
-          m('td', 'T queued'),
-          m('td', 'Queue time'),
-          m('td', 'Run time'),
-        )
-      ),
-      m('tbody', jobIds.map(makeJobRow))
-    );
-  },
-
-  view: function (vnode) {
-    return [
-      renderHeader(),
-      m('main',
-        m('.jobs-list',
-          this.createWorkerTable(),
-          this.createJobsTable(vnode, 'Queued + Running jobs',
-            state.jobsRunning.concat(state.jobsQueued)),
-          this.createJobsTable(vnode, 'Last 100 jobs', state.jobsRecent),
-        ),
-      )
-    ];
-  }
-};
-
-const StatsPageRenderer = {
-  view: function (vnode) {
-    const makeIframe = id => {
-      let url = 'https://public.google.stackdriver.com/public/chart';
-      url += `/${id}?timeframe=${vnode.attrs.period}`;
-      url += '&drawMode=color&showLegend=false&theme=light';
-      return m('iframe', {
-        src: url,
-        scrolling: 'no',
-        seamless: 'seamless',
-      });
-    };
-
-    return [
-      renderHeader(),
-      m('main#stats',
-        m('.stats-grid', STATS_CHART_IDS.map(makeIframe))
-      )
-    ];
-  }
-}
-
-// -----------------------------------------------------------------------------
-// Business logic (handles fetching from Gerrit and Firebase DB).
-// -----------------------------------------------------------------------------
-
-function parseGerritTime(str) {
-  // Gerrit timestamps are UTC (as per public docs) but obviously they are not
-  // encoded in ISO format.
-  return new Date(`${str} UTC`);
-}
-
-function stripEmail(email) {
-  return email.replace('@google.com', '@');
-}
-
-// Fetches the list of CLs from gerrit and updates the state.
-async function fetchGerritCLs() {
-  console.log('Fetching CL list from Gerrit');
-  let uri = '/gerrit/changes/?-age:7days';
-  uri += '+-is:abandoned&o=DETAILED_ACCOUNTS&o=CURRENT_REVISION';
-  const response = await fetch(uri);
-  state.gerritCls = [];
-  let json = '';
-  if (response.status !== 200) {
-    setTimeout(fetchGerritCLs, 3000);  // Retry.
-    return;
-  }
-
-  json = (await response.text());
-  const cls = [];
-  for (const e of JSON.parse(json)) {
-    const revHash = Object.keys(e.revisions)[0];
-    const cl = {
-      subject: e.subject,
-      status: e.status,
-      num: e._number,
-      revHash: revHash,
-      psNum: e.revisions[revHash]._number,
-      lastUpdate: parseGerritTime(e.updated),
-      owner: e.owner.email,
-    };
-    cls.push(cl);
-    fetchCIJobsForCLOrBranch(`cls/${cl.num}-${cl.psNum}`);
-  }
-  state.gerritCls = cls;
-  scheduleRedraw();
-}
-
-async function fetchGerritCommit(sha1) {
-  const response = await fetch(`/gerrit/commits/${sha1}`);
-  console.assert(response.status === 200);
-  const json = (await response.text());
-  state.gerritCommits[sha1] = JSON.parse(json);
-  scheduleRedraw();
-}
-
-async function fetchGerritLog(first, second) {
-  const range = `${first}..${second}`;
-  const response = await fetch(`/gerrit/log/${range}`);
-  if (response.status !== 200) return;
-  const json = await response.text();
-  state.gerritLogs[range] = JSON.parse(json).log;
-  scheduleRedraw();
-}
-
-// Retrieves the status of a given (CL, PS) in the DB.
-function fetchCIJobsForCLOrBranch(src) {
-  if (src in state.clRefs) return;  // Aslready have a listener for this key.
-  const ref = firebase.database().ref(`/ci/${src}`);
-  state.clRefs[src] = ref;
-  ref.on('value', (e) => {
-    const obj = e.val();
-    if (!obj) return;
-    state.dbJobSets[src] = Object.keys(obj.jobs);
-    for (var jobId of state.dbJobSets[src]) {
-      fetchCIStatusForJob(jobId);
-    }
-    scheduleRedraw();
-  });
-}
-
-function fetchCIJobsForAllPatchsetOfCL(cl) {
-  let ref = firebase.database().ref('/ci/cls').orderByKey();
-  ref = ref.startAt(`${cl}-0`).endAt(`${cl}-~`);
-  ref.once('value', (e) => {
-    const patchsets = e.val() || {};
-    for (const clAndPs in patchsets) {
-      const jobs = Object.keys(patchsets[clAndPs].jobs);
-      state.dbJobSets[`cls/${clAndPs}`] = jobs;
-      for (var jobId of jobs) {
-        fetchCIStatusForJob(jobId);
-      }
-    }
-    scheduleRedraw();
-  });
-}
-
-function fetchCIStatusForJob(jobId) {
-  if (jobId in state.jobRefs) return;  // Already have a listener for this key.
-  const ref = firebase.database().ref(`/ci/jobs/${jobId}`);
-  state.jobRefs[jobId] = ref;
-  ref.on('value', (e) => {
-    if (e.val()) state.dbJobs[jobId] = e.val();
-    scheduleRedraw();
-  });
-}
-
-function fetchCIStatusForBranch(branch) {
-  if (branch in state.branchRefs) return;  // Already have a listener.
-  const db = firebase.database();
-  const ref = db.ref('/ci/branches').orderByKey().limitToLast(20);
-  state.branchRefs[branch] = ref;
-  ref.on('value', (e) => {
-    const resp = e.val();
-    if (!resp) return;
-    // key looks like 'master-YYYYMMDDHHMMSS', where YMD is the commit datetime.
-    // Iterate in most-recent-first order.
-    const keys = Object.keys(resp).sort().reverse();
-    for (let i = 0; i < keys.length; i++) {
-      const key = keys[i];
-      const branchInfo = resp[key];
-      state.dbBranches[key] = branchInfo;
-      fetchCIJobsForCLOrBranch(`branches/${key}`);
-      if (i < keys.length - 1) {
-        fetchGerritLog(resp[keys[i + 1]].rev, branchInfo.rev);
-      }
-    }
-    scheduleRedraw();
-  });
-}
-
-function fetchWorkers() {
-  if (state.workersRef !== undefined) return;  // Aslready have a listener.
-  const ref = firebase.database().ref('/ci/workers');
-  state.workersRef = ref;
-  ref.on('value', (e) => {
-    state.dbWorker = e.val() || {};
-    scheduleRedraw();
-  });
-}
-
-async function showLogTail(jobId) {
-  if (state.termJobId === jobId) return;  // Already on it.
-  const TAIL = 20;
-  state.termClear = true;
-  state.termLines = [
-    `Fetching last ${TAIL} lines for ${jobId}.`,
-    `Click on the CI icon to see the full log.`
-  ];
-  state.termJobId = jobId;
-  scheduleRedraw();
-  const ref = firebase.database().ref(`/ci/logs/${jobId}`);
-  const lines = (await ref.orderByKey().limitToLast(TAIL).once('value')).val();
-  if (state.termJobId !== jobId || !lines) return;
-  const lastKey = appendLogLinesAndRedraw(lines);
-  startRealTimeLogs(jobId, lastKey);
-}
-
-async function showFullLog(jobId) {
-  state.termClear = true;
-  state.termLines = [`Fetching full for ${jobId} ...`];
-  state.termJobId = jobId;
-  scheduleRedraw();
-
-  // Suspend any other real-time logging in progress.
-  stopRealTimeLogs();
-
-  // Starts a chain of async tasks that fetch the current log lines in batches.
-  state.termJobId = jobId;
-  const ref = firebase.database().ref(`/ci/logs/${jobId}`).orderByKey();
-  let lastKey = '';
-  const BATCH = 1000;
-  for (; ;) {
-    const batchRef = ref.startAt(`${lastKey}!`).limitToFirst(BATCH);
-    const logs = (await batchRef.once('value')).val();
-    if (!logs)
-      break;
-    lastKey = appendLogLinesAndRedraw(logs);
-  }
-
-  startRealTimeLogs(jobId, lastKey)
-}
-
-function startRealTimeLogs(jobId, lastLineKey) {
-  stopRealTimeLogs();
-  console.log('Starting real-time logs for ', jobId);
-  state.termJobId = jobId;
-  let ref = firebase.database().ref(`/ci/logs/${jobId}`);
-  ref = ref.orderByKey().startAt(`${lastLineKey}!`);
-  state.realTimeLogRef = ref;
-  state.realTimeLogRef.on('child_added', res => {
-    const line = res.val();
-    if (state.termJobId !== jobId || !line) return;
-    const lines = {};
-    lines[res.key] = line;
-    appendLogLinesAndRedraw(lines);
-  });
-}
-
-function stopRealTimeLogs() {
-  if (state.realTimeLogRef !== undefined) {
-    state.realTimeLogRef.off();
-    state.realTimeLogRef = undefined;
-  }
-}
-
-function appendLogLinesAndRedraw(lines) {
-  const keys = Object.keys(lines).sort();
-  for (var key of keys) {
-    const date = new Date(null);
-    date.setSeconds(parseInt(key.substr(0, 6), 16) / 1000);
-    const timeString = date.toISOString().substr(11, 8);
-    const isErr = lines[key].indexOf('FAILED:') >= 0;
-    let line = `[${timeString}] ${lines[key]}`;
-    if (isErr) line = `\u001b[33m${line}\u001b[0m`;
-    state.termLines.push(line);
-  }
-  scheduleRedraw();
-  return keys[keys.length - 1];
-}
-
-async function fetchRecentJobsStatus() {
-  const db = firebase.database();
-  if (state.jobsQueuedRef === undefined) {
-    state.jobsQueuedRef = db.ref(`/ci/jobs_queued`).on('value', e => {
-      state.jobsQueued = Object.keys(e.val() || {}).sort().reverse();
-      for (const jobId of state.jobsQueued)
-        fetchCIStatusForJob(jobId);
-      scheduleRedraw();
-    });
-  }
-
-  if (state.jobsRunningRef === undefined) {
-    state.jobsRunningRef = db.ref(`/ci/jobs_running`).on('value', e => {
-      state.jobsRunning = Object.keys(e.val() || {}).sort().reverse();
-      for (const jobId of state.jobsRunning)
-        fetchCIStatusForJob(jobId);
-      scheduleRedraw();
-    });
-  }
-
-  if (state.jobsRecentRef === undefined) {
-    state.jobsRecentRef = db.ref(`/ci/jobs`).orderByKey().limitToLast(100);
-    state.jobsRecentRef.on('value', e => {
-      state.jobsRecent = Object.keys(e.val() || {}).sort().reverse();
-      for (const jobId of state.jobsRecent)
-        fetchCIStatusForJob(jobId);
-      scheduleRedraw();
-    });
-  }
-}
-
-
-function scheduleRedraw() {
-  if (state.redrawPending) return;
-  state.redrawPending = true;
-  window.requestAnimationFrame(() => {
-    state.redrawPending = false;
-    m.redraw();
-  });
-}
-
-main();
diff --git a/infra/ci/frontend/static/style.css b/infra/ci/frontend/static/style.css
deleted file mode 100644
index 5ce48b2..0000000
--- a/infra/ci/frontend/static/style.css
+++ /dev/null
@@ -1,359 +0,0 @@
-* {
-    box-sizing: border-box;
-}
-
-html {
-    font-size: 13px;
-    font-weight: 300;
-    padding: 0;
-    margin: 0;
-    height: 100%;
-}
-
-body {
-    padding: 0;
-    margin: 0;
-    height: 100%;
-    display: grid;
-    grid-template-columns: 1fr;
-    grid-template-rows: 50px 1fr;
-    overflow: hidden;
-    background: #eff1f5;
-    font-family: 'Source Sans Pro', sans-serif;
-}
-
-header {
-    background: #2b3643;
-    color: #eee;
-    height: 50px;
-    line-height: 50px;
-    width: 100%;
-    display: grid;
-    grid-template-rows: 1fr;
-    grid-template-columns: fit-content(250px) 1fr;
-}
-
-h1 {
-    font-size: 20px;
-    font-weight: 100;
-    padding-left: 20px;
-    height: 50px;
-    margin: 0;
-    text-transform: uppercase;
-    background-image: url('/static/icon.png');
-    background-repeat: no-repeat;
-    background-size: 30px;
-    background-position: 10px;
-    padding-left: 50px;
-}
-
-h1 span {
-    color: #db3f41;
-    font-weight: 500;
-}
-
-header>nav {
-    margin: auto 10px auto auto;
-}
-
-header>nav>div {
-    width: 80px;
-    box-sizing: border-box;
-    height: 50px;
-    line-height: 50px;
-    font-weight: 300;
-    float: left;
-    text-align: center;
-    font-size: 16px;
-    color: #ccc;
-    vertical-align: middle;
-    padding: 0;
-    letter-spacing: 0.5px;
-    border-left: 0.5px solid rgba(255, 255, 255, 0.2);
-    border-right: 0.5px solid rgba(255, 255, 255, 0.2);
-    text-transform: uppercase;
-}
-
-header>nav>div.logs {
-    position: relative;
-    z-index: 20;
-    background: #2b3643;
-    overflow: hidden;
-    transition: max-height 0.2s ease;
-    height: auto;
-    max-height: 50px;
-}
-
-header>nav>div.logs:hover {
-    max-height: 500px;
-}
-
-header>nav>div.logs div {
-    font-size: 10px;
-    text-align: left;
-    height: 20px;
-    line-height: 20px;
-    margin: 10px;
-}
-
-header>nav>div.active {
-    border-bottom: 4px solid #39aa56;
-}
-
-header>nav>div:hover {
-    color: #fff;
-}
-
-header a, header a:hover  {
-    color: inherit;
-    text-decoration: none;
-}
-
-header>nav>div:first-child {
-    border-left: 0;
-}
-
-header>nav>div:last-child {
-    border-right: 0;
-}
-
-.term-container {
-    position: relative;
-    background: #000;
-    border-top: 3px solid #39aa56;
-    box-sizing: content-box;
-    padding: 5px 0px 5px 20px;
-}
-
-main { overflow: scroll; }
-
-.term-container.maximized {
-    position: absolute;
-    height: calc(100% - 50px);
-    top: 50px;
-    max-height: initial;
-}
-
-input[type=text].term-search {
-    position: absolute;
-    background: rgba(255, 255, 255, 0.1);
-    font-weight: 100;
-    font-size: 12px;
-    border-radius: 2px;
-    width: 150px;
-    height: 20px;
-    line-height: 20px;
-    right: 5px;
-    top: 5px;
-    z-index: 10;
-    outline: none;
-    color: #000;
-    border: 0px solid #aaa;
-    padding: 5px 10px;
-    transition: color ease 0.2s, background-color ease 0.2s
-}
-
-input[type=text].term-search:focus {
-    background: rgba(255, 255, 255, 0.9);
-    color: #333;
-}
-
-.term-info > div {
-    margin: 5px;
-}
-
-#cls {
-    display: grid;
-    grid-template-columns: 1fr;
-    grid-template-rows: 4fr 1fr;
-    overflow: hidden;
-}
-
-.table-scrolling-container {
-    overflow: scroll;
-}
-
-.table-scrolling-container footer {
-    font-size: 14px;
-    text-align: center;
-    color: #666;
-}
-
-.main-table {
-    width: calc(100% - 40px);
-    background: #fff;
-    margin: 20px;
-    box-shadow: 0 0 20px #aaa;
-}
-
-
-.main-table td.warning {
-    background: #333;
-    color: #fff;
-    text-align: center;
-}
-
-.main-table tbody td:first-child {
-    padding-left: 20px;
-}
-
-.main-table thead {
-    color: #111;
-    font-size: 14px;
-    font-weight: 300;
-}
-
-.main-table thead tr:nth-child(n+3) td {
-    font-size: 10px;
-}
-
-.main-table thead tr:nth-child(4) td {
-    width: 20px;
-}
-
-.main-table thead td {
-    font-family: 'Source Sans Pro', sans-serif;
-    text-transform: uppercase;
-    color: #888;
-    padding: 2px 5px;
-    text-align: center;
-    background: #73b672;
-    color: #fff;
-}
-
-a {
-    color: black;
-    text-decoration: none;
-}
-
-a:hover {
-    text-decoration: underline;
-}
-
-.main-table tbody td {
-    border-bottom: 1px solid #eee;
-    overflow: hidden;
-    text-overflow: ellipsis;
-    white-space: nowrap;
-    position: relative;
-}
-
-.main-table tbody td.job {
-    text-align: center;
-}
-
-.main-table tbody td.job i {
-    font-size: 16px;
-}
-
-.main-table tbody td.job .status {
-    margin-left: 5px;
-}
-
-.main-table tbody td.job .COMPLETED {
-    color: #39aa56;
-}
-
-.main-table tbody td.job .STARTED {
-    color: #607d8b;
-}
-
-.main-table tbody td.job .FAILED {
-    color: #db4545;
-}
-
-.main-table tbody td.job .CANCELLED {
-    color: #ffa000;
-}
-
-.main-table tbody td.job .INTERRUPTED {
-    color: #ffa000;
-}
-
-.main-table tbody td.job .TIMED_OUT {
-    color: #db4545;
-}
-
-.main-table tbody td.job .UNKNOWN {
-    color: #607d8b;
-}
-
-.main-table tbody td.align-left {
-    text-align: left
-}
-
-.main-table tbody td.header {
-    background: #dcedc8;
-    text-align: center;
-    font-size: 13px;
-    font-weight: 500;
-    text-transform: uppercase;
-    position: relative;
-}
-
-
-.main-table tbody tr {
-    height: 25px;
-    line-height: 25px;
-    font-size: 13px;
-    font-weight: 300;
-}
-
-.main-table tbody tr.nested td:first-child, .main-table tbody tr.nested a {
-    color: #999;
-}
-
-.main-table .expand {
-    position: absolute;
-    left: -5px;
-    font-size: 30px;
-    line-height: 25px;
-    color: #454e5a;
-    transition: transform ease 0.2s;
-    cursor: pointer;
-    user-select: none;
-}
-
-
-.main-table .expand.expanded {
-    transform: rotate(90deg);
-}
-
-.main-table tbody tr.MERGED td:not(.job),
-.main-table tbody tr.MERGED td:not(.job) a {
-    color: #BBB;
-}
-
-
-.main-table tbody tr:nth-child(2n+1) {
-    background: #fafafa;
-}
-
-
-.main-table tbody tr:hover {
-    background: #e1ebf1 !important;
-}
-
-.main-table tbody tr.selected  {
-    background: #dcedc8;
-}
-
-.main-table tbody .ps {
-    margin-left: 5px;
-    color: #43a047;
-}
-
-.stats-grid {
-    display: grid;
-    grid-template-columns: 1fr 1fr;
-    grid-auto-rows: 400px;
-    grid-gap: 20px;
-    margin: 20px;
-}
-
-.stats-grid  > * {
-    width: 100%;
-    height: 100%;
-    border: 0;
-    background: #fff;
-}
diff --git a/infra/ci/frontend/static/third_party/README.md b/infra/ci/frontend/static/third_party/README.md
deleted file mode 100644
index cecb7e7..0000000
--- a/infra/ci/frontend/static/third_party/README.md
+++ /dev/null
@@ -1 +0,0 @@
-This file is needed to keep this directory in git.
diff --git a/infra/ci/sandbox/Dockerfile b/infra/ci/sandbox/Dockerfile
deleted file mode 100644
index 04e22a3..0000000
--- a/infra/ci/sandbox/Dockerfile
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (C) 2019 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.
-
-# Creates an image that can check out / build / test the perfetto source. The
-# image is used by the Kokoro continuous integration jobs, but is also suitable
-# for local development.
-
-FROM debian:latest
-
-RUN set -ex; \
-    export DEBIAN_FRONTEND=noninteractive; \
-    echo deb http://deb.debian.org/debian testing main > \
-             /etc/apt/sources.list.d/testing.list; \
-    apt-get update; \
-    apt-get -y install python git curl sudo lz4 tar ccache tini libpulse0 \
-                       libgl1 libxml2 libc6-dev-i386 libtinfo5 gnupg2 \
-                       pkg-config zip g++ zlib1g-dev unzip python3; \
-    apt-get -y -t testing install gcc-7 g++-7 clang; \
-    curl https://bootstrap.pypa.io/get-pip.py | python -; \
-    pip install --quiet protobuf; \
-    curl -LO https://github.com/bazelbuild/bazel/releases/download/0.29.1/bazel-0.29.1-installer-linux-x86_64.sh; \
-    chmod +x bazel-*-installer-linux-x86_64.sh; \
-    ./bazel-*-installer-linux-x86_64.sh; \
-    rm bazel-*-installer-linux-x86_64.sh; \
-    bazel version; \
-    useradd -d /ci/ramdisk perfetto; \
-    apt-get -y autoremove; \
-    rm -rf /var/lib/apt/lists/* /usr/share/man/* /usr/share/doc/*;
-
-COPY testrunner.sh /ci/testrunner.sh
-COPY init.sh /ci/init.sh
-
-VOLUME [ "/ci/cache", "/ci/ramdisk", "/ci/artifacts" ]
-ENTRYPOINT [ "tini", "-g", "--" ]
-CMD [ "bash", "/ci/init.sh" ]
-
diff --git a/infra/ci/sandbox/init.sh b/infra/ci/sandbox/init.sh
deleted file mode 100644
index 68e4118..0000000
--- a/infra/ci/sandbox/init.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2019 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.
-
-# Performs initialization that requires root, then runs the test as non-root.
-
-set -eux
-chmod 777 /ci/cache /ci/artifacts
-chown perfetto.perfetto /ci/ramdisk
-cd /ci/ramdisk
-exec sudo -u perfetto -g perfetto -EH bash /ci/testrunner.sh
diff --git a/infra/ci/sandbox/testrunner.sh b/infra/ci/sandbox/testrunner.sh
deleted file mode 100755
index d16554e..0000000
--- a/infra/ci/sandbox/testrunner.sh
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2019 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.
-
-# Should code live in this script or in the PERFETTO_TEST_SCRIPT script?
-# You might argue: after all they are both part of the same repo? The difference
-# is in temporal pinning.
-# Code in this script is part of the Docker image that is manually pushed
-# on the VMs. Everything in here is orthogonal to the evolution of the repo.
-# Everything from /ramdisk instead will reflect the state of the repo at the
-# point in time of the checkout.
-# Things like script that upload performance data to dashboarads should probably
-# be in the docker image. Things that depend on build artifacts should probably
-# come from the repo.
-
-set -eux
-
-# CWD is /ci/ramdisk. In the CI this is based on a tmpfs ramdisk.
-
-# Print env vars for debugging. They contain GN args and entrypoint.
-date
-env
-
-mkdir src && cd src
-
-if [[ $PERFETTO_TEST_GIT_REF == "file://"* ]]; then
-# This is used only by tools/run_test_like_ci.
-git clone -q --no-tags --single-branch --depth=1 "$PERFETTO_TEST_GIT_REF" .
-else
-git clone -q --no-tags --single-branch \
-  https://android.googlesource.com/platform/external/perfetto.git .
-git config user.email "ci-bot@perfetto.dev"
-git config user.name "Perfetto CI"
-git fetch -q origin "$PERFETTO_TEST_GIT_REF"
-
-# We really want to test the result of the merge of the CL in ToT master. Don't
-# really care about whether the CL passes the test at the time it was written.
-git merge -q FETCH_HEAD -m merge
-fi
-
-# The android buildtools are huge due to the emulator, keep that as a separate
-# cache and pack/unpack separately. It's worth  ~30s on each non-android test.
-if [[ "$PERFETTO_TEST_GN_ARGS" =~ "android" ]]; then
-PREBUILTS_ARCHIVE=/ci/cache/buildtools-$(date +%Y-%m-%d)-android.tar.lz4
-else
-PREBUILTS_ARCHIVE=/ci/cache/buildtools-$(date +%Y-%m-%d).tar.lz4
-fi
-
-# Clear stale buildtools caches after 24h.
-(echo /ci/cache/buildtools-* | grep -v $PREBUILTS_ARCHIVE | xargs rm -f) || true
-
-if [ -f $PREBUILTS_ARCHIVE ]; then
-  lz4 -d $PREBUILTS_ARCHIVE | tar xf - || rm -f $PREBUILTS_ARCHIVE
-  git reset --hard  # Just in case some versioned file gets overwritten.
-fi
-
-
-# By default ccache uses the mtime of the compiler. This doesn't work because
-# our compilers are hermetic and their mtime is the time when we run
-# install-build-deps. Given that the toolchain is rolled via install-build-deps
-# we use that file as an identity function for the compiler check.
-export CCACHE_COMPILERCHECK=string:$(shasum tools/install-build-deps)
-export CCACHE_UMASK=000
-export CCACHE_DEPEND=1
-export CCACHE_MAXSIZE=8G
-export CCACHE_DIR=/ci/cache/ccache
-export CCACHE_SLOPPINESS=include_file_ctime,include_file_mtime
-export CCACHE_COMPRESS=1
-export CCACHE_COMPRESSLEVEL=4
-mkdir -m 777 -p $CCACHE_DIR
-
-export PERFETTO_TEST_GN_ARGS="${PERFETTO_TEST_GN_ARGS} cc_wrapper=\"ccache\""
-
-export PERFETTO_TEST_NINJA_ARGS="-l 100"
-$PERFETTO_TEST_SCRIPT
-
-# The code after this point will NOT run if the test fails (because of set -e).
-
-ccache --show-stats
-
-# Populate the cache on the first run. Do that atomically so in case of races
-# one random worker wins.
-if [ ! -f $PREBUILTS_ARCHIVE ]; then
-  TMPFILE=$(mktemp -p /ci/cache).tar.lz4
-  # Add only git-ignored dirs to the cache.
-  git check-ignore buildtools/* | xargs tar c | lz4 -z - $TMPFILE
-  mv -f $TMPFILE $PREBUILTS_ARCHIVE
-fi
diff --git a/infra/ci/worker/.gitignore b/infra/ci/worker/.gitignore
deleted file mode 100644
index 3fec32c..0000000
--- a/infra/ci/worker/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-tmp/
diff --git a/infra/ci/worker/Dockerfile b/infra/ci/worker/Dockerfile
deleted file mode 100644
index 8b1788a..0000000
--- a/infra/ci/worker/Dockerfile
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright (C) 2019 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.
-
-# docker:stable is an Alpine-based distro.
-FROM docker:stable
-
-RUN apk update && apk add python py-pip sudo tini
-RUN pip install oauth2client httplib2
-
-# Unfortunately Docker doesn't allow to copy a file from ../. So we copy instead
-# the config files into tmp/ from the Makefile that runs docker build.
-COPY tmp/config.py /home/perfetto/config.py
-COPY tmp/common_utils.py /home/perfetto/common_utils.py
-COPY artifacts_uploader.py /home/perfetto/
-COPY perf_metrics_uploader.py /home/perfetto/
-COPY run_job.py /home/perfetto/
-COPY worker.py /home/perfetto/
-
-# Allow the worker to spawn new docker containers (for the jobs' sandboxes).
-# This makes the worker container highly priviledged (effectiveely can run  any
-# commands on the GCE vm). The worker container is trusted and must never run
-# code from a tryjob (which instead is run into the sandbox containers).
-RUN set -e; \
-    echo 'root ALL=(ALL) ALL' /etc/sudoers; \
-    echo 'perfetto ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers; \
-    addgroup -S perfetto; \
-    adduser -S -h /home/perfetto perfetto perfetto; \
-    chown perfetto.perfetto -R /home/perfetto; \
-    chmod -R 755 /home/perfetto;
-
-USER perfetto:perfetto
-WORKDIR /home/perfetto
-
-ENTRYPOINT [ "tini", "--" ]
-CMD [ "python2", "/home/perfetto/worker.py" ]
diff --git a/infra/ci/worker/artifacts_uploader.py b/infra/ci/worker/artifacts_uploader.py
deleted file mode 100644
index 2a44633..0000000
--- a/infra/ci/worker/artifacts_uploader.py
+++ /dev/null
@@ -1,141 +0,0 @@
-#!/usr/bin/env python2
-# Copyright (C) 2019 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.
-
-import argparse
-import httplib2
-import logging
-import mimetypes
-import mmap
-import os
-import subprocess
-import signal
-import sys
-import threading
-import time
-
-from common_utils import init_logging
-from config import GCS_ARTIFACTS
-from multiprocessing.pool import ThreadPool
-from oauth2client.client import GoogleCredentials
-
-CUR_DIR = os.path.dirname(__file__)
-RESCAN_PERIOD_SEC = 5  # Scan for new artifact directories every X seconds.
-WATCHDOG_SEC = 60 * 6  # Self kill after 5 minutes
-
-tls = threading.local()
-'''Polls for new directories under ARTIFACTS_DIR and uploads them to GCS'''
-
-
-def get_http_obj():
-  http = getattr(tls, 'http', None)
-  if http is not None:
-    return http
-  tls.http = httplib2.Http()
-  scopes = ['https://www.googleapis.com/auth/cloud-platform']
-  creds = GoogleCredentials.get_application_default().create_scoped(scopes)
-  creds.authorize(tls.http)
-  return tls.http
-
-
-def upload_one_file(fpath):
-  http = get_http_obj()
-  relpath = os.path.relpath(fpath, os.getenv('ARTIFACTS_DIR'))
-  logging.debug('Uploading %s', relpath)
-  assert (os.path.exists(fpath))
-  fsize = os.path.getsize(fpath)
-  mime_type = mimetypes.guess_type(fpath)[0] or 'application/octet-stream'
-  mm = ''
-  hdr = {'Content-Length': fsize, 'Content-type': mime_type}
-  if fsize > 0:
-    with open(fpath, 'rb') as f:
-      mm = mmap.mmap(f.fileno(), fsize, access=mmap.ACCESS_READ)
-  uri = 'https://%s.storage.googleapis.com/%s' % (GCS_ARTIFACTS, relpath)
-  resp, res = http.request(uri, method='PUT', headers=hdr, body=mm)
-  if fsize > 0:
-    mm.close()
-  if resp.status != 200:
-    logging.error('HTTP request failed with code %d : %s', resp.status, res)
-    return -1
-  return fsize
-
-
-def upload_one_file_with_retries(fpath):
-  for retry in [0.5, 1.5, 3]:
-    res = upload_one_file(fpath)
-    if res >= 0:
-      return res
-    logging.warn('Upload of %s failed, retrying in %s seconds', fpath, retry)
-    time.sleep(retry)
-
-
-def list_files(path):
-  for root, _, files in os.walk(path):
-    for fname in files:
-      fpath = os.path.join(root, fname)
-      if os.path.isfile(fpath):
-        yield fpath
-
-
-def scan_and_upload_perf_folder(job_id, dirpath):
-  perf_folder = os.path.join(dirpath, 'perf')
-  if not os.path.isdir(perf_folder):
-    return
-  uploader = os.path.join(CUR_DIR, 'perf_metrics_uploader.py')
-  for path in list_files(perf_folder):
-    subprocess.call([uploader, '--job-id', job_id, path])
-
-
-def main():
-  init_logging()
-  signal.alarm(WATCHDOG_SEC)
-  mimetypes.add_type('application/wasm', '.wasm')
-
-  parser = argparse.ArgumentParser()
-  parser.add_argument('--rm', action='store_true', help='Removes the directory')
-  parser.add_argument(
-      '--job-id',
-      type=str,
-      required=True,
-      help='The Perfetto CI job ID to tie this upload to')
-  args = parser.parse_args()
-  job_id = args.job_id
-  dirpath = os.path.join(os.getenv('ARTIFACTS_DIR', default=os.curdir), job_id)
-  if not os.path.isdir(dirpath):
-    logging.error('Directory not found: %s', dirpath)
-    return 1
-
-  total_size = 0
-  uploads = 0
-  failures = 0
-  files = list_files(dirpath)
-  pool = ThreadPool(processes=10)
-  for upl_size in pool.imap_unordered(upload_one_file_with_retries, files):
-    uploads += 1 if upl_size >= 0 else 0
-    failures += 1 if upl_size < 0 else 0
-    total_size += max(upl_size, 0)
-
-  logging.info('Uploaded artifacts for %s: %d files, %s failures, %d KB',
-               job_id, uploads, failures, total_size / 1e3)
-
-  scan_and_upload_perf_folder(job_id, dirpath)
-
-  if args.rm:
-    subprocess.call(['sudo', 'rm', '-rf', dirpath])
-
-  return 0
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/infra/ci/worker/gce-startup-script.sh b/infra/ci/worker/gce-startup-script.sh
deleted file mode 100644
index 7a3081d..0000000
--- a/infra/ci/worker/gce-startup-script.sh
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/bin/bash
-set -eux -o pipefail
-
-# num-workers is set at VM creation time in the Makefile.
-URL='http://metadata.google.internal/computeMetadata/v1/instance/attributes/num-workers'
-NUM_WORKERS=$(curl --silent --fail -H'Metadata-Flavor:Google' $URL || echo 1)
-
-# This is used by the sandbox containers, NOT needed by the workers.
-export SHARED_WORKER_CACHE=/mnt/disks/shared_worker_cache
-rm -rf $SHARED_WORKER_CACHE
-mkdir -p $SHARED_WORKER_CACHE
-mount -t tmpfs tmpfs $SHARED_WORKER_CACHE -o mode=777
-
-# This is used to queue build artifacts that are uploaded to GCS.
-export ARTIFACTS_DIR=/mnt/stateful_partition/artifacts
-rm -rf $ARTIFACTS_DIR
-mkdir -m 777 -p $ARTIFACTS_DIR
-
-# Pull the latest images from the registry.
-docker pull eu.gcr.io/perfetto-ci/worker
-docker pull eu.gcr.io/perfetto-ci/sandbox
-
-# Create the restricted bridge for the sandbox container.
-# Prevent access to the metadata server and impersonation of service accounts.
-docker network rm sandbox 2>/dev/null || true  # Handles the reboot case.
-docker network create sandbox -o com.docker.network.bridge.name=sandbox
-sudo iptables -I DOCKER-USER -i sandbox -d 169.254.0.0/16 -j REJECT
-
-# These args will be appended to the docker run invocation for the sandbox.
-export SANDBOX_NETWORK_ARGS="--network sandbox --dns 8.8.8.8"
-
-# The worker_main_loop.py script creates one docker sandbox container for
-# each job invocation. It needs to talk back to the host docker to do so.
-# This implies that the worker container is trusted and should never run code
-# from the repo, as opposite to the sandbox container that is isolated.
-for i in $(seq $NUM_WORKERS); do
-docker rm -f worker-$i 2>/dev/null || true
-docker run -d \
-  -v /var/run/docker.sock:/var/run/docker.sock \
-  -v $ARTIFACTS_DIR:$ARTIFACTS_DIR \
-  --env SHARED_WORKER_CACHE="$SHARED_WORKER_CACHE" \
-  --env SANDBOX_NETWORK_ARGS="$SANDBOX_NETWORK_ARGS" \
-  --env ARTIFACTS_DIR="$ARTIFACTS_DIR" \
-  --env WORKER_HOST="$(hostname)" \
-  --name worker-$i \
-  --hostname worker-$i \
-  --log-driver gcplogs \
-  eu.gcr.io/perfetto-ci/worker
-done
-
-
-# Register a systemd service to stop worker containers gracefully on shutdown.
-cat > /etc/systemd/system/graceful_shutdown.sh <<EOF
-#!/bin/sh
-logger 'Shutting down worker containers'
-docker ps -q  -f 'name=worker-\d+$' | xargs docker stop -t 30
-exit 0
-EOF
-
-chmod 755 /etc/systemd/system/graceful_shutdown.sh
-
-# This service will cause the graceful_shutdown.sh to be invoked before stopping
-# docker, hence before tearing down any other container.
-cat > /etc/systemd/system/graceful_shutdown.service <<EOF
-[Unit]
-Description=Worker container lifecycle
-Wants=gcr-online.target docker.service
-After=gcr-online.target docker.service
-Requires=docker.service
-
-[Service]
-Type=oneshot
-RemainAfterExit=yes
-ExecStop=/etc/systemd/system/graceful_shutdown.sh
-EOF
-
-systemctl daemon-reload
-systemctl start graceful_shutdown.service
\ No newline at end of file
diff --git a/infra/ci/worker/perf_metrics_uploader.py b/infra/ci/worker/perf_metrics_uploader.py
deleted file mode 100755
index 05e4095..0000000
--- a/infra/ci/worker/perf_metrics_uploader.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2019 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.
-
-import argparse
-import json
-import hashlib
-import sys
-
-from config import DB, PROJECT
-from common_utils import req, SCOPES
-'''
-Uploads the performance metrics of the Perfetto tests to StackDriver and
-Firebase.
-
-The expected format of the JSON is as follows:
-{
-  metrics: [
-    {
-      'metric': *metric name*,
-      'value': *metric value*,
-      'unit': *either s (seconds) or b (bytes)*,
-      'tags': {
-        *tag name*: *tag value*,
-        ...
-      },
-      'labels': {
-        *label name*: *label value*,
-        ...
-      }
-    },
-    ...
-  ]
-}
-'''
-
-STACKDRIVER_API = 'https://monitoring.googleapis.com/v3/projects/%s' % PROJECT
-SCOPES.append('https://www.googleapis.com/auth/firebase.database')
-SCOPES.append('https://www.googleapis.com/auth/userinfo.email')
-SCOPES.append('https://www.googleapis.com/auth/monitoring.write')
-
-
-def sha1(obj):
-  hasher = hashlib.sha1()
-  hasher.update(json.dumps(obj, sort_keys=True, separators=(',', ':')))
-  return hasher.hexdigest()
-
-
-def metric_list_to_hash_dict(raw_metrics):
-  metrics = {}
-  for metric in raw_metrics:
-    key = '%s-%s' % (metric['metric'], sha1(metric['tags']))
-    metrics[key] = metric
-  return metrics
-
-
-def create_stackdriver_metrics(ts, metrics):
-  desc = {'timeSeries': []}
-  for _, metric in metrics.iteritems():
-    metric_name = metric['metric']
-    desc['timeSeries'] += [{
-        'metric': {
-            'type':
-                'custom.googleapis.com/perfetto-ci/perf/%s' % metric_name,
-            'labels':
-                dict(
-                    list(metric.get('tags', {}).items()) +
-                    list(metric.get('labels', {}).items())),
-        },
-        'resource': {
-            'type': 'global'
-        },
-        'points': [{
-            'interval': {
-                'endTime': ts
-            },
-            'value': {
-                'doubleValue': str(metric['value'])
-            }
-        }]
-    }]
-  return desc
-
-
-def main():
-  parser = argparse.ArgumentParser()
-  parser.add_argument(
-      '--job-id',
-      type=str,
-      required=True,
-      help='The Perfetto CI job ID to tie this upload to')
-  parser.add_argument(
-      'metrics_file', type=str, help='File containing the metrics to upload')
-  args = parser.parse_args()
-
-  with open(args.metrics_file, 'r') as metrics_file:
-    raw_metrics = json.loads(metrics_file.read())
-
-  job = req('GET', '%s/jobs/%s.json' % (DB, args.job_id))
-  ts = job['time_started']
-
-  metrics = metric_list_to_hash_dict(raw_metrics['metrics'])
-  req('PUT', '%s/perf/%s.json' % (DB, args.job_id), body=metrics)
-
-  # Only upload Stackdriver metrics for post-submit runs.
-  git_ref = job['env'].get('PERFETTO_TEST_GIT_REF')
-  if git_ref == 'refs/heads/master':
-    sd_metrics = create_stackdriver_metrics(ts, metrics)
-    req('POST', STACKDRIVER_API + '/timeSeries', body=sd_metrics)
-
-  return 0
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/infra/ci/worker/run_job.py b/infra/ci/worker/run_job.py
deleted file mode 100755
index ad3f833..0000000
--- a/infra/ci/worker/run_job.py
+++ /dev/null
@@ -1,185 +0,0 @@
-#!/usr/bin/env python2
-# Copyright (C) 2019 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.
-''' Runs the given job in an isolated docker container.
-
-Also streams stdout/err onto the firebase realtime DB.
-'''
-
-import fcntl
-import logging
-import json
-import os
-import Queue
-import signal
-import socket
-import shutil
-import subprocess
-import sys
-import threading
-import time
-
-from datetime import datetime, timedelta
-from oauth2client.client import GoogleCredentials
-from config import DB, SANDBOX_IMG
-from common_utils import init_logging, req, ConcurrentModificationError, SCOPES
-
-CUR_DIR = os.path.dirname(__file__)
-SCOPES.append('https://www.googleapis.com/auth/firebase.database')
-SCOPES.append('https://www.googleapis.com/auth/userinfo.email')
-
-
-def read_nonblock(fd):
-  fcntl.fcntl(fd, fcntl.F_SETFL, fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK)
-  res = ''
-  while True:
-    try:
-      buf = os.read(fd.fileno(), 1024)
-      if not buf:
-        break
-      res += buf
-    except OSError:
-      break
-  return res
-
-
-def log_thread(job_id, queue):
-  ''' Uploads stdout/stderr from the queue to the firebase DB.
-
-  Each line is logged as an invidivual entry in the DB, as follows:
-  MMMMMM-NNNN log line, where M: hex-encodeed timestamp, N:  monotonic counter.
-  '''
-  uri = '%s/logs/%s.json' % (DB, job_id)
-  req('DELETE', uri)
-  while True:
-    batch = queue.get()
-    if batch is None:
-      break  # EOF
-    req('PATCH', uri, body=batch)
-  logging.debug('Uploader thread terminated')
-
-
-def main(argv):
-  init_logging()
-  if len(argv) != 2:
-    print 'Usage: %s job_id' % argv[0]
-    return 1
-
-  job_id = argv[1]
-  res = 42
-
-  # The container name will be worker-N-sandbox.
-  container = socket.gethostname() + '-sandbox'
-
-  # Remove stale jobs, if any.
-  subprocess.call(['sudo', 'docker', 'rm', '-f', container])
-
-  q = Queue.Queue()
-
-  # Conversely to real programs, signal handlers in python aren't really async
-  # but are queued on the main thread. Hence We need to keep the main thread
-  # responsive to react to signals. This is to handle timeouts and graceful
-  # termination of the worker container, which dispatches a SIGTERM on stop.
-  def sig_handler(sig, _):
-    logging.warn('Job runner got signal %s, terminating job %s', sig, job_id)
-    subprocess.call(['sudo', 'docker', 'kill', container])
-    os._exit(1)  # sys.exit throws a SystemExit exception, _exit really exits.
-
-  signal.signal(signal.SIGTERM, sig_handler)
-
-  log_thd = threading.Thread(target=log_thread, args=(job_id, q))
-  log_thd.start()
-
-  # SYS_PTRACE is required for gtest death tests and LSan.
-  cmd = [
-      'sudo', 'docker', 'run', '--name', container, '--hostname', container,
-      '--cap-add', 'SYS_PTRACE', '--rm', '--tmpfs', '/ci/ramdisk:exec',
-      '--tmpfs', '/tmp:exec', '--env',
-      'PERFETTO_TEST_JOB=%s' % job_id
-  ]
-
-  # Propagate environment variables coming from the job config.
-  for kv in [kv for kv in os.environ.items() if kv[0].startswith('PERFETTO_')]:
-    cmd += ['--env', '%s=%s' % kv]
-
-  # Rationale for the conditional branches below: when running in the real GCE
-  # environment, the gce-startup-script.sh mounts these directories in the right
-  # locations, so that they are shared between all workers.
-  # When running the worker container outside of GCE (i.e.for local testing) we
-  # leave these empty. The VOLUME directive in the dockerfile will cause docker
-  # to automatically mount a scratch volume for those.
-  # This is so that the CI containers can be tested without having to do the
-  # work that gce-startup-script.sh does.
-  if os.getenv('SHARED_WORKER_CACHE'):
-    cmd += ['--volume=%s:/ci/cache' % os.getenv('SHARED_WORKER_CACHE')]
-
-  artifacts_dir = None
-  if os.getenv('ARTIFACTS_DIR'):
-    artifacts_dir = os.path.join(os.getenv('ARTIFACTS_DIR'), job_id)
-    subprocess.call(['sudo', 'rm', '-rf', artifacts_dir])
-    os.mkdir(artifacts_dir)
-    cmd += ['--volume=%s:/ci/artifacts' % artifacts_dir]
-
-  cmd += os.getenv('SANDBOX_NETWORK_ARGS', '').split()
-  cmd += [SANDBOX_IMG]
-
-  logging.info('Starting %s', ' '.join(cmd))
-  proc = subprocess.Popen(
-      cmd,
-      stdin=open(os.devnull),
-      stdout=subprocess.PIPE,
-      stderr=subprocess.STDOUT,
-      bufsize=65536)
-  stdout = ''
-  tstart = time.time()
-  while True:
-    ms_elapsed = int((time.time() - tstart) * 1000)
-    stdout += read_nonblock(proc.stdout)
-
-    # stdout/err pipes are not atomic w.r.t. '\n'. Extract whole lines out into
-    # |olines| and keep the last partial line (-1) in the |stdout| buffer.
-    lines = stdout.split('\n')
-    stdout = lines[-1]
-    lines = lines[:-1]
-
-    # Each line has a key of the form <time-from-start><out|err><counter>
-    # |counter| is relative to the batch and is only used to disambiguate lines
-    # fetched at the same time, preserving the ordering.
-    batch = {}
-    for counter, line in enumerate(lines):
-      batch['%06x-%04x' % (ms_elapsed, counter)] = line
-    if batch:
-      q.put(batch)
-    if proc.poll() is not None:
-      res = proc.returncode
-      logging.info('Job subprocess terminated with code %s', res)
-      break
-
-    # Large sleeps favour batching in the log uploader.
-    # Small sleeps favour responsiveness of the signal handler.
-    time.sleep(1)
-
-  q.put(None)  # EOF maker
-  log_thd.join()
-
-  if artifacts_dir:
-    artifacts_uploader = os.path.join(CUR_DIR, 'artifacts_uploader.py')
-    cmd = ['setsid', artifacts_uploader, '--job-id=%s' % job_id, '--rm']
-    subprocess.call(cmd)
-
-  return res
-
-
-if __name__ == '__main__':
-  sys.exit(main(sys.argv))
diff --git a/infra/ci/worker/worker.py b/infra/ci/worker/worker.py
deleted file mode 100755
index 764b0e5..0000000
--- a/infra/ci/worker/worker.py
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/usr/bin/env python2
-# Copyright (C) 2019 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.
-''' Worker main loop. Pulls jobs from the DB and runs them in the sandbox
-
-It also handles timeouts and graceful container termination.
-'''
-
-import logging
-import os
-import random
-import signal
-import socket
-import subprocess
-import threading
-import time
-import traceback
-
-from config import DB, JOB_TIMEOUT_SEC
-from common_utils import req, utc_now_iso, init_logging
-from common_utils import ConcurrentModificationError, SCOPES
-
-CUR_DIR = os.path.dirname(__file__)
-SCOPES.append('https://www.googleapis.com/auth/firebase.database')
-SCOPES.append('https://www.googleapis.com/auth/userinfo.email')
-WORKER_NAME = '%s-%s' % (os.getenv('WORKER_HOST', 'local').split('-')[-1],
-                         socket.gethostname())
-sigterm = threading.Event()
-
-
-def try_acquire_job(job_id):
-  ''' Transactionally acquire the given job.
-
-  Returns the job JSON object if it managed to acquire and put it into the
-  STARTED state, None if another worker got there first.
-  '''
-  logging.debug('Trying to acquire job %s', job_id)
-
-  uri = '%s/jobs/%s.json' % (DB, job_id)
-  job, etag = req('GET', uri, req_etag=True)
-  if job['status'] != 'QUEUED':
-    return None  # Somebody else took it
-  try:
-    job['status'] = 'STARTED'
-    job['time_started'] = utc_now_iso()
-    job['worker'] = WORKER_NAME
-    req('PUT', uri, body=job, etag=etag)
-    return job
-  except ConcurrentModificationError:
-    return None
-
-
-def make_worker_obj(status, job_id=None):
-  return {
-      'job_id': job_id,
-      'status': status,
-      'last_update': utc_now_iso(),
-      'host': os.getenv('WORKER_HOST', '')
-  }
-
-
-def worker_loop():
-  ''' Pulls a job from the queue and runs it invoking run_job.py  '''
-  uri = '%s/jobs_queued.json?orderBy="$key"&limitToLast=10' % DB
-  jobs = req('GET', uri)
-  if not jobs:
-    return
-
-  # Transactionally acquire a job. Deal with races (two workers trying to
-  # acquire the same job).
-  job = None
-  job_id = None
-  for job_id in sorted(jobs.keys(), reverse=True):
-    job = try_acquire_job(job_id)
-    if job is not None:
-      break
-    logging.info('Raced while trying to acquire job %s, retrying', job_id)
-    time.sleep(int(random.random() * 3))
-  if job is None:
-    logging.error('Failed to acquire a job')
-    return
-
-  logging.info('Starting job %s', job_id)
-
-  # Update the db, move the job to the running queue.
-  patch_obj = {
-      'jobs_queued/' + job_id: {},  # = DELETE
-      'jobs_running/' + job_id: {
-          'worker': WORKER_NAME
-      },
-      'workers/' + WORKER_NAME: make_worker_obj('RUNNING', job_id=job_id)
-  }
-  req('PATCH', '%s.json' % DB, body=patch_obj)
-
-  cmd = [os.path.join(CUR_DIR, 'run_job.py'), job_id]
-
-  # Propagate the worker's PERFETTO_  vars and merge with the job-specific vars.
-  env = dict(os.environ, **{k: str(v) for (k, v) in job['env'].iteritems()})
-  job_runner = subprocess.Popen(cmd, env=env)
-
-  # Run the job in a python subprocess, to isolate the main loop from logs
-  # uploader failures.
-  res = None
-  cancelled = False
-  timed_out = False
-  time_started = time.time()
-  time_last_db_poll = time_started
-  polled_status = 'STARTED'
-  while res is None:
-    time.sleep(0.25)
-    res = job_runner.poll()
-    now = time.time()
-    if now - time_last_db_poll > 10:  # Throttle DB polling.
-      polled_status = req('GET', '%s/jobs/%s/status.json' % (DB, job_id))
-      time_last_db_poll = now
-    if now - time_started > JOB_TIMEOUT_SEC:
-      logging.info('Job %s timed out, terminating', job_id)
-      timed_out = True
-      job_runner.terminate()
-    if (sigterm.is_set() or polled_status != 'STARTED') and not cancelled:
-      logging.info('Job %s cancelled, terminating', job_id)
-      cancelled = True
-      job_runner.terminate()
-
-  status = ('INTERRUPTED' if sigterm.is_set() else 'CANCELLED' if cancelled else
-            'TIMED_OUT' if timed_out else 'COMPLETED' if res == 0 else 'FAILED')
-  logging.info('Job %s %s with code %s', job_id, status, res)
-
-  # Update the DB, unless the job has been cancelled. The "is not None"
-  # condition deals with a very niche case, that is, avoid creating a partial
-  # job entry after doing a full clear of the DB (which is super rare, happens
-  # only when re-deploying the CI).
-  if polled_status is not None:
-    patch = {
-        'jobs/%s/status' % job_id: status,
-        'jobs/%s/exit_code' % job_id: {} if res is None else res,
-        'jobs/%s/time_ended' % job_id: utc_now_iso(),
-        'jobs_running/%s' % job_id: {},  # = DELETE
-    }
-    req('PATCH', '%s.json' % (DB), body=patch)
-
-
-def sig_handler(_, __):
-  logging.warn('Interrupted by signal, exiting worker')
-  sigterm.set()
-
-
-def main():
-  init_logging()
-  logging.info('Worker started')
-  signal.signal(signal.SIGTERM, sig_handler)
-  signal.signal(signal.SIGINT, sig_handler)
-
-  while not sigterm.is_set():
-    logging.debug('Starting poll cycle')
-    try:
-      worker_loop()
-      req('PUT',
-          '%s/workers/%s.json' % (DB, WORKER_NAME),
-          body=make_worker_obj('IDLE'))
-    except:
-      logging.error('Exception in worker loop:\n%s', traceback.format_exc())
-    if sigterm.is_set():
-      break
-    time.sleep(5)
-
-  # The use case here is the VM being terminated by the GCE infrastructure.
-  # We mark the worker as terminated and the job as cancelled so we don't wait
-  # forever for it.
-  logging.warn('Exiting the worker loop, got signal: %s', sigterm.is_set())
-  req('PUT',
-      '%s/workers/%s.json' % (DB, WORKER_NAME),
-      body=make_worker_obj('TERMINATED'))
-
-
-if __name__ == '__main__':
-  main()
diff --git a/infra/discord-irc-bridge/Dockerfile b/infra/discord-irc-bridge/Dockerfile
deleted file mode 100644
index 5591da2..0000000
--- a/infra/discord-irc-bridge/Dockerfile
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (C) 2019 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.
-
-FROM node:latest
-
-RUN useradd -m discord_irc
-RUN npm install -g discord-irc
-RUN apt-get -y update && apt-get -y install supervisor
-COPY supervisord.conf /etc/
-COPY discord-irc.json /etc/
-COPY start.py /
-USER discord_irc
-
-CMD ["python", "start.py"]
\ No newline at end of file
diff --git a/infra/discord-irc-bridge/README.md b/infra/discord-irc-bridge/README.md
deleted file mode 100644
index 9c79d2d..0000000
--- a/infra/discord-irc-bridge/README.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# IRC <> Discord bridge
-
-This directory contains the docker image for the discord<>IRC bot.
-The docker container is built and pushed running:
-
-```bash
-docker build -t gcr.io/perfetto-irc/discord-irc-bridge .
-docker push gcr.io/perfetto-irc/discord-irc-bridge
-```
-
-The docker container requires two environment variables to be set (see below).
-These are set at the GCE project level (project: perfetto-irc).
-There is a VM template in the GCE project which has the right env vars set.
-If a VM restart is required use the template, don't create the VM from scratch.
-
-NICKNAME: This must be set to perfetto_discord:password. The password can be
-  obtained on the usual internal website for passwords. Look for the account
-  "perfetto_discord@freenode".
-
-DISCORD_TOKEN: This must be set to the Discord token for the bot. Look for
-  the account "perfetto-discord-bot-token" in the internal password website.
diff --git a/infra/discord-irc-bridge/discord-irc.json b/infra/discord-irc-bridge/discord-irc.json
deleted file mode 100644
index bf71f2a..0000000
--- a/infra/discord-irc-bridge/discord-irc.json
+++ /dev/null
@@ -1,23 +0,0 @@
-[
-  {
-    "server": "irc.freenode.org",
-    "autoSendCommands": [
-    ],
-    "channelMapping": {
-      "629013441096450058": "#perfetto-dev"
-    },
-    "ircOptions": {
-      "port": "6697",
-      "secure": true
-    },
-    "ircNickColor": false,
-    "ircPreventMention": true,
-    "commandCharacters": [],
-    "ignoreUsers": {
-      "irc": [],
-      "discord": []
-    },
-    "webhooks": {
-    }
-  }
-]
diff --git a/infra/discord-irc-bridge/start.py b/infra/discord-irc-bridge/start.py
deleted file mode 100644
index 35bbb93..0000000
--- a/infra/discord-irc-bridge/start.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2019 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.
-
-import json
-import os
-import sys
-
-with open("/etc/discord-irc.json") as f:
-  cfg = json.load(f)
-
-cfg[0]["nickname"] = os.getenv("NICKNAME")
-cfg[0]["discordToken"] = os.getenv("DISCORD_TOKEN")
-
-if cfg[0]["nickname"] is None:
-  sys.stderr.write("NICKNAME env var not set\n")
-  sys.exit(1)
-
-if cfg[0]["discordToken"] is None:
-  sys.stderr.write("DISCORD_TOKEN env var not set\n")
-  sys.exit(1)
-
-with open("/tmp/discord-irc-merged.json", "w") as f:
-  json.dump(cfg, f)
-
-os.execl("/usr/bin/supervisord", "supervisord")
diff --git a/infra/discord-irc-bridge/supervisord.conf b/infra/discord-irc-bridge/supervisord.conf
deleted file mode 100644
index 713b332..0000000
--- a/infra/discord-irc-bridge/supervisord.conf
+++ /dev/null
@@ -1,13 +0,0 @@
-[supervisord]
-nodaemon=true
-logfile=/dev/stdout
-logfile_maxbytes=0
-
-[program:discord_irc]
-command=discord-irc --config /tmp/discord-irc-merged.json
-stdout_logfile=/dev/stdout
-stdout_logfile_maxbytes=0
-stdout_logfile_backups=0
-stderr_logfile=/dev/stderr
-stderr_logfile_maxbytes=0
-stderr_logfile_backups=0
diff --git a/infra/git_mirror_bot/Makefile b/infra/git_mirror_bot/Makefile
index dedaad9..270ea06 100644
--- a/infra/git_mirror_bot/Makefile
+++ b/infra/git_mirror_bot/Makefile
@@ -35,7 +35,7 @@
 		--project $(PROJECT) \
 		instances create $(VM_NAME) \
 		--zone $(ZONE) \
-		--machine-type "n1-highcpu-16" \
+		--machine-type "f1-micro" \
 		--subnet "default" \
 		--maintenance-policy "MIGRATE" \
 		--image "debian-9-stretch-v20170918" \
diff --git a/infra/git_mirror_bot/mirror_aosp_to_ghub_repo.py b/infra/git_mirror_bot/mirror_aosp_to_ghub_repo.py
index fa17382..53e27ce 100644
--- a/infra/git_mirror_bot/mirror_aosp_to_ghub_repo.py
+++ b/infra/git_mirror_bot/mirror_aosp_to_ghub_repo.py
@@ -12,18 +12,45 @@
 # 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.
-""" Mirrors a Gerrit repo into GitHub.
 
-Mirrors all the branches (refs/heads/foo) from Gerrit to Github as-is, taking
-care of propagating also deletions.
+""" Mirrors a Gerrit repo into GitHub, turning CLs into individual branches.
 
-This script used to be more complex, turning all the Gerrit CLs
-(refs/changes/NN/cl_number/patchset_number) into Github branches
-(refs/heads/cl_number). This use case was dropped as we moved away from Travis.
-See the git history of this file for more.
+This script does a bit of git black magic. It does mainly two things:
+1) Mirrors all the branches (refs/heads/foo) from Gerrit to Github as-is, taking
+   care of propagating also deletions.
+2) Rewrites Gerrit CLs (refs/changes/NN/cl_number/patchset_number) as
+   Github branches (refs/heads/cl_number) recreating a linear chain of commits
+   for each patchset in any given CL.
+
+2. Is the trickier part. The problem is that Gerrit stores each patchset of
+each CL as an independent ref, e.g.:
+  $ git ls-remote origin
+  94df12f950462b55a2257b89d1fad6fac24353f9	refs/changes/10/496410/1
+  4472fadddf8def74fd76a66ff373ca1245c71bcc	refs/changes/10/496410/2
+  90b8535da0653d8f072e86cef9891a664f4e9ed7	refs/changes/10/496410/3
+  2149c215fa9969bb454f23ce355459f28604c545	refs/changes/10/496410/meta
+
+  53db7261268802648d7f6125ae6242db17e7a60d	refs/changes/20/494620/1
+  d25e56930486363e0637b0a9debe3ae3ec805207	refs/changes/20/494620/2
+
+Where each ref is base on top of the master branch (or whatever the dev choose).
+On GitHub, instead, we want to recreate something similar to the pull-request
+model, ending up with one branch per CL, and one commit per patchset.
+Also we want to make them non-hidden branch heads (i.e. in the refs/heads/)
+name space, because Travis CI does not hooks hidden branches.
+In conclusion we want to transform the above into:
+
+refs/changes/496410
+  * commit: [CL 496410, Patchset 3] (parent: [CL 496410, Patchset 2])
+  * commit: [CL 496410, Patchset 2] (parent: [CL 496410, Patchset 1])
+  * commit: [CL 496410, Patchset 1] (parent: [master])
+refs/changes/496420
+  * commit: [CL 496420, Patchset 2] (parent: [CL 496420, Patchset 1])
+  * commit: [CL 496420, Patchset 1] (parent: [master])
+
 """
 
-import argparse
+import collections
 import logging
 import os
 import re
@@ -31,12 +58,27 @@
 import subprocess
 import sys
 import time
+import traceback
+
+from multiprocessing.pool import ThreadPool
 
 CUR_DIR = os.path.dirname(os.path.abspath(__file__))
 GIT_UPSTREAM = 'https://android.googlesource.com/platform/external/perfetto/'
 GIT_MIRROR = 'git@github.com:catapult-project/perfetto.git'
 WORKDIR = os.path.join(CUR_DIR, 'repo')
 
+# Ignores CLs that have a cumulative tree size greater than this. GitHub rightly
+# refuses to accept commits that have files that are too big, suggesting to use
+# LFS instead.
+MAX_TREE_SIZE_MB = 50
+
+# Ignores all CL numbers < this. 913796 roughly maps to end of Feb 2019.
+MIN_CL_NUM = 913796
+
+# Max number of concurrent git subprocesses that can be run while generating
+# per-CL branches.
+GIT_SUBPROCESS_CONCURRENCY = 10
+
 # Min delay (in seconds) between two consecutive git poll cycles. This is to
 # avoid hitting gerrit API quota limits.
 POLL_PERIOD_SEC = 60
@@ -48,22 +90,16 @@
 def GitCmd(*args, **kwargs):
   cmd = ['git'] + list(args)
   p = subprocess.Popen(
-      cmd,
-      stdin=subprocess.PIPE,
-      stdout=subprocess.PIPE,
-      stderr=sys.stderr,
-      cwd=WORKDIR,
-      env=ENV)
+      cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=sys.stderr,
+      cwd=WORKDIR, env=ENV)
   out = p.communicate(kwargs.get('stdin'))[0]
   assert p.returncode == 0, 'FAIL: ' + ' '.join(cmd)
   return out
 
 
 # Create a git repo that mirrors both the upstream and the mirror repos.
-def Setup(args):
+def Setup():
   if os.path.exists(WORKDIR):
-    if args.no_clean:
-      return
     shutil.rmtree(WORKDIR)
   os.makedirs(WORKDIR)
   GitCmd('init', '--bare', '--quiet')
@@ -72,12 +108,64 @@
   GitCmd('remote', 'add', 'mirror', GIT_MIRROR, '--mirror=fetch')
 
 
-def Sync(args):
+# Returns the SUM(file.size) for file in the given git tree.
+def GetTreeSize(tree_sha1):
+  raw = GitCmd('ls-tree', '-r', '--long', tree_sha1)
+  return sum(int(line.split()[3]) for line in raw.splitlines())
+
+
+def GetCommit(commit_sha1):
+  raw = GitCmd('cat-file', 'commit', commit_sha1)
+  return {
+    'tree': re.search(r'^tree\s(\w+)$', raw, re.M).group(1),
+    'parent': re.search(r'^parent\s(\w+)$', raw, re.M).group(1),
+    'author': re.search(r'^author\s(.+)$', raw, re.M).group(1),
+    'committer': re.search(r'^committer\s(.+)$', raw, re.M).group(1),
+    'message': re.search(r'\n\n(.+)', raw, re.M | re.DOTALL).group(1),
+  }
+
+
+def ForgeCommit(tree, parent, author, committer, message):
+  raw = 'tree %s\nparent %s\nauthor %s\ncommitter %s\n\n%s' % (
+      tree, parent, author, committer, message)
+  out = GitCmd('hash-object', '-w', '-t', 'commit', '--stdin', stdin=raw)
+  return out.strip()
+
+
+# Translates a CL, identified by a (Gerrit) CL number and a list of patchsets
+# into a git branch, where all patchsets look like subsequent commits.
+# This function must be stateless and idempotent, it's invoked by ThreadPool.
+def TranslateClIntoBranch(packed_args):
+  cl_num, patchsets = packed_args
+  if cl_num < MIN_CL_NUM:
+    return
+  parent_sha1 = None
+  for patchset_num, commit_sha1 in sorted(patchsets.items(), key=lambda x:x[0]):
+    patchset_data = GetCommit(commit_sha1)
+    # Skip Cls that are too big as they would be rejected by GitHub.
+    tree_size_bytes = GetTreeSize(patchset_data['tree'])
+    if tree_size_bytes > MAX_TREE_SIZE_MB * (1 << 20):
+      logging.warning('Skipping CL %s because its too big (%d bytes)',
+                      cl_num, tree_size_bytes)
+      return
+    parent_sha1 = parent_sha1 or patchset_data['parent']
+    forged_sha1 = ForgeCommit(
+        tree=patchset_data['tree'],
+        parent=parent_sha1,
+        author=patchset_data['author'],
+        committer=patchset_data['committer'],
+        message='[Patchset %d] %s' % (patchset_num, patchset_data['message']))
+    parent_sha1 = forged_sha1
+    return 'refs/heads/changes/%d' % cl_num, forged_sha1
+
+
+def Sync():
   logging.info('Fetching git remotes')
   GitCmd('fetch', '--all', '--quiet')
   all_refs = GitCmd('show-ref')
   future_heads = {}
   current_heads = {}
+  changes = collections.defaultdict(dict)
 
   # List all refs from both repos and:
   # 1. Keep track of all branch heads refnames and sha1s from the (github)
@@ -102,6 +190,27 @@
       future_heads['refs/heads/' + branch] = ref_sha1
       continue
 
+    PREFIX = 'refs/remotes/upstream/changes/'
+    if ref.startswith(PREFIX):
+      (_, cl_num, patchset) = ref[len(PREFIX):].split('/')
+      if not cl_num.isdigit() or not patchset.isdigit():
+        continue
+      cl_num, patchset = int(cl_num), int(patchset)
+      changes[cl_num][patchset] = ref_sha1
+
+  # Now iterate over the upstream (AOSP) CLS and forge a chain of commits,
+  # creating one branch refs/heads/changes/cl_number for each set of patchsets.
+  # Forging commits is mostly fork() + exec() and I/O bound, parallelism helps
+  # significantly to hide those latencies.
+  logging.info('Forging per-CL branches')
+  pool = ThreadPool(processes=GIT_SUBPROCESS_CONCURRENCY)
+  for res in pool.imap_unordered(TranslateClIntoBranch, changes.iteritems()):
+    if res is None:
+      continue
+    branch_ref, forged_sha1 = res
+    future_heads[branch_ref] = forged_sha1
+  pool.close()
+
   deleted_heads = set(current_heads) - set(future_heads)
   logging.info('current_heads: %d, future_heads: %d, deleted_heads: %d',
                len(current_heads), len(future_heads), len(deleted_heads))
@@ -116,37 +225,28 @@
   for ref_to_update, ref_sha1 in future_heads.iteritems():
     if current_heads.get(ref_to_update) != ref_sha1:
       update_ref_cmd += 'update %s %s\n' % (ref_to_update, ref_sha1)
+  print update_ref_cmd
 
+  logging.info('Pushing updates')
+  # Update objects and push.
   GitCmd('update-ref', '--stdin', stdin=update_ref_cmd)
-
-  if args.push:
-    logging.info('Pushing updates')
-    GitCmd('push', 'mirror', '--all', '--prune', '--force')
-    GitCmd('gc', '--prune=all', '--aggressive', '--quiet')
-  else:
-    logging.info('Dry-run mode, skipping git push. Pass --push for prod mode.')
+  GitCmd('push', 'mirror', '--all', '--prune', '--force')
+  GitCmd('gc', '--prune=all', '--aggressive', '--quiet')
 
 
 def Main():
-  parser = argparse.ArgumentParser()
-  parser.add_argument('--push', default=False, action='store_true')
-  parser.add_argument('--no-clean', default=False, action='store_true')
-  parser.add_argument('-v', dest='verbose', default=False, action='store_true')
-  args = parser.parse_args()
-
-  logging.basicConfig(
-      format='%(asctime)s %(levelname)-8s %(message)s',
-      level=logging.DEBUG if args.verbose else logging.INFO,
-      datefmt='%Y-%m-%d %H:%M:%S')
-
   logging.info('Setting up git repo one-off')
-  Setup(args)
+  Setup()
   while True:
     logging.info('------- BEGINNING OF SYNC CYCLE -------')
-    Sync(args)
+    Sync()
     logging.info('------- END OF SYNC CYCLE -------')
     time.sleep(POLL_PERIOD_SEC)
 
 
 if __name__ == '__main__':
+  logging.basicConfig(
+    format='%(asctime)s %(levelname)-8s %(message)s',
+    level=logging.INFO,
+    datefmt='%Y-%m-%d %H:%M:%S')
   sys.exit(Main())
diff --git a/infra/git_mirror_bot/startup-script.sh b/infra/git_mirror_bot/startup-script.sh
index cba2d93..19e5c38 100644
--- a/infra/git_mirror_bot/startup-script.sh
+++ b/infra/git_mirror_bot/startup-script.sh
@@ -30,7 +30,7 @@
 
 [program:gitbot]
 directory=/home/gitbot
-command=python mirror_aosp_to_ghub_repo.py --push
+command=python mirror_aosp_to_ghub_repo.py
 user=gitbot
 autorestart=true
 startretries=10
diff --git a/infra/kokoro_ci/dockerfiles/Dockerfile b/infra/kokoro_ci/dockerfiles/Dockerfile
new file mode 100644
index 0000000..552c190
--- /dev/null
+++ b/infra/kokoro_ci/dockerfiles/Dockerfile
@@ -0,0 +1,38 @@
+# 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.
+
+
+# Creates an image that can check out / build / test the perfetto source. The
+# image is used by the Kokoro continuous integration jobs, but is also suitable
+# for local development. There is no pre-defined entrypoint on purpose (to keep
+# it flexible).
+#
+# The built image is available as asia.gcr.io/perfetto-ci/perfetto-ci:latest
+
+FROM debian:latest
+
+ENV DEBIAN_FRONTEND noninteractive
+
+RUN echo deb http://deb.debian.org/debian testing main > /etc/apt/sources.list.d/testing.list
+RUN apt-get update
+RUN apt-get -y install python git curl
+# gcc-7 for sysroot
+RUN apt-get -y -t testing install gcc-7
+
+# pip for installing certiain test script dependencies
+RUN curl https://bootstrap.pypa.io/get-pip.py | python -
+
+RUN useradd -m perfetto
+USER perfetto:perfetto
+WORKDIR /home/perfetto
diff --git a/infra/kokoro_ci/kokoro_entry.sh b/infra/kokoro_ci/kokoro_entry.sh
new file mode 100755
index 0000000..6c3997f
--- /dev/null
+++ b/infra/kokoro_ci/kokoro_entry.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# 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.
+
+
+# Initial script invoked by Kokoro continuous integration / presubmit jobs.
+# Sets up Kokoro-specific environment, invoking the test script afterwards.
+# What & how to run is carried by environment variables.
+#
+# You shouldn't need to invoke this when running tests locally.
+
+set -eux
+
+SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
+ROOT_DIR="$(realpath ${SCRIPT_DIR}/../..)"
+
+cd ${ROOT_DIR}
+
+# Check that the expected environment variables are present (due to set -u).
+echo PERFETTO_TEST_GN_ARGS: ${PERFETTO_TEST_GN_ARGS}
+echo PERFETTO_TEST_ENTRYPT: ${PERFETTO_TEST_ENTRYPT}
+
+# Make space for docker image by symlinking the hardcoded /var/lib/docker path
+# to a tmpfs mount. Cargo culted from other projects' scripts.
+sudo -n /etc/init.d/docker stop
+sudo -n mv /var/lib/docker /tmpfs/
+sudo -n ln -s /tmpfs/docker /var/lib/docker
+sudo -n /etc/init.d/docker start
+
+# Invoke the tests within a container.
+${SCRIPT_DIR}/run_test_in_container.sh
diff --git a/infra/kokoro_ci/linux/ci-clang-x86_64-asan_lsan_ubsan.cfg b/infra/kokoro_ci/linux/ci-clang-x86_64-asan_lsan_ubsan.cfg
new file mode 100644
index 0000000..8aa1dba
--- /dev/null
+++ b/infra/kokoro_ci/linux/ci-clang-x86_64-asan_lsan_ubsan.cfg
@@ -0,0 +1,30 @@
+# 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.
+
+
+# Location of the shell script that is the entry point for continuous
+# integration jobs. The first directory in the path is where Kokoro will check
+# out the repository. The rest is the path relative to the repository's root.
+build_file: "perfetto/infra/kokoro_ci/kokoro_entry.sh"
+
+env_vars {
+  key: "PERFETTO_TEST_GN_ARGS"
+  value: "is_debug=false is_ubsan=true is_asan=true is_lsan=true"
+}
+
+env_vars {
+  key: "PERFETTO_TEST_ENTRYPT"
+  value: "infra/kokoro_ci/run_standalone_tests.sh"
+}
+
diff --git a/infra/kokoro_ci/linux/ci-clang-x86_64-msan.cfg b/infra/kokoro_ci/linux/ci-clang-x86_64-msan.cfg
new file mode 100644
index 0000000..1e85fa4
--- /dev/null
+++ b/infra/kokoro_ci/linux/ci-clang-x86_64-msan.cfg
@@ -0,0 +1,30 @@
+# 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.
+
+
+# Location of the shell script that is the entry point for continuous
+# integration jobs. The first directory in the path is where Kokoro will check
+# out the repository. The rest is the path relative to the repository's root.
+build_file: "perfetto/infra/kokoro_ci/kokoro_entry.sh"
+
+env_vars {
+  key: "PERFETTO_TEST_GN_ARGS"
+  value: "is_debug=false is_msan=true"
+}
+
+env_vars {
+  key: "PERFETTO_TEST_ENTRYPT"
+  value: "infra/kokoro_ci/run_standalone_tests.sh"
+}
+
diff --git a/infra/kokoro_ci/linux/ci-clang-x86_64-tsan.cfg b/infra/kokoro_ci/linux/ci-clang-x86_64-tsan.cfg
new file mode 100644
index 0000000..22fd946
--- /dev/null
+++ b/infra/kokoro_ci/linux/ci-clang-x86_64-tsan.cfg
@@ -0,0 +1,30 @@
+# 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.
+
+
+# Location of the shell script that is the entry point for continuous
+# integration jobs. The first directory in the path is where Kokoro will check
+# out the repository. The rest is the path relative to the repository's root.
+build_file: "perfetto/infra/kokoro_ci/kokoro_entry.sh"
+
+env_vars {
+  key: "PERFETTO_TEST_GN_ARGS"
+  value: "is_debug=false is_tsan=true"
+}
+
+env_vars {
+  key: "PERFETTO_TEST_ENTRYPT"
+  value: "infra/kokoro_ci/run_standalone_tests.sh"
+}
+
diff --git a/infra/kokoro_ci/linux/ci-ui-clang-x86_64-debug.cfg b/infra/kokoro_ci/linux/ci-ui-clang-x86_64-debug.cfg
new file mode 100644
index 0000000..c67a806
--- /dev/null
+++ b/infra/kokoro_ci/linux/ci-ui-clang-x86_64-debug.cfg
@@ -0,0 +1,30 @@
+# 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.
+
+
+# Location of the shell script that is the entry point for continuous
+# integration jobs. The first directory in the path is where Kokoro will check
+# out the repository. The rest is the path relative to the repository's root.
+build_file: "perfetto/infra/kokoro_ci/kokoro_entry.sh"
+
+env_vars {
+  key: "PERFETTO_TEST_GN_ARGS"
+  value: "is_debug=true"
+}
+
+env_vars {
+  key: "PERFETTO_TEST_ENTRYPT"
+  value: "infra/kokoro_ci/run_ui_tests.sh"
+}
+
diff --git a/infra/kokoro_ci/run_standalone_tests.sh b/infra/kokoro_ci/run_standalone_tests.sh
new file mode 100755
index 0000000..f9a08bf
--- /dev/null
+++ b/infra/kokoro_ci/run_standalone_tests.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# 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.
+
+set -eux
+
+SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
+ROOT_DIR="$(realpath ${SCRIPT_DIR}/../..)"
+
+cd ${ROOT_DIR}
+
+# Check that the expected environment variables are present (due to set -u).
+echo PERFETTO_TEST_GN_ARGS: ${PERFETTO_TEST_GN_ARGS}
+
+OUT_PATH="out/dist"
+
+tools/install-build-deps --no-android
+
+pip install --quiet --user protobuf
+
+if [[ -e buildtools/clang/bin/llvm-symbolizer ]]; then
+  export ASAN_SYMBOLIZER_PATH="buildtools/clang/bin/llvm-symbolizer"
+  export MSAN_SYMBOLIZER_PATH="buildtools/clang/bin/llvm-symbolizer"
+fi
+
+tools/gn gen ${OUT_PATH} --args="${PERFETTO_TEST_GN_ARGS}" --check
+tools/ninja -C ${OUT_PATH}
+
+# Run the tests
+${OUT_PATH}/perfetto_unittests
+${OUT_PATH}/perfetto_integrationtests
+
+BENCHMARK_FUNCTIONAL_TEST_ONLY=true ${OUT_PATH}/perfetto_benchmarks
+tools/diff_test_trace_processor.py ${OUT_PATH}/trace_processor_shell
diff --git a/infra/kokoro_ci/run_test_in_container.sh b/infra/kokoro_ci/run_test_in_container.sh
new file mode 100755
index 0000000..ec743ea
--- /dev/null
+++ b/infra/kokoro_ci/run_test_in_container.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# 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.
+
+set -eux
+
+SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
+ROOT_DIR="$(realpath ${SCRIPT_DIR}/../..)"
+
+cd ${ROOT_DIR}
+
+# Check that the expected environment variables are present (due to set -u).
+echo PERFETTO_TEST_GN_ARGS: ${PERFETTO_TEST_GN_ARGS}
+echo PERFETTO_TEST_ENTRYPT: ${PERFETTO_TEST_ENTRYPT}
+
+# Run PERFETTO_TEST_ENTRYPOINT inside the container with the following setup:
+# Mount (readonly) the current source directory inside the container. Enter the
+# container as root, make a mutable copy the source tree, and then invoke
+# the test script as that user.
+#
+# SYS_PTRACE capability is added for [at least] the leak sanitizer.
+# TODO(rsavitski): figure out why "su perfetto -c" was messing with the test
+# scripts (at least the output truncation).
+sudo docker run --rm -t \
+  --user=root:root \
+  --cap-add=SYS_PTRACE \
+  -e PERFETTO_TEST_GN_ARGS="${PERFETTO_TEST_GN_ARGS}" \
+  -v ${ROOT_DIR}:/perfetto:ro \
+  asia.gcr.io/perfetto-ci/perfetto-ci:latest \
+  /bin/bash \
+  "-c" \
+  "cp -r /perfetto /home/perfetto/src && \
+  cd /home/perfetto/src && \
+  ${PERFETTO_TEST_ENTRYPT}"
diff --git a/infra/kokoro_ci/run_ui_tests.sh b/infra/kokoro_ci/run_ui_tests.sh
new file mode 100755
index 0000000..906d9ea
--- /dev/null
+++ b/infra/kokoro_ci/run_ui_tests.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# 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.
+
+set -eux
+
+SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
+ROOT_DIR="$(realpath ${SCRIPT_DIR}/../..)"
+
+cd ${ROOT_DIR}
+
+# Check that the expected environment variables are present (due to set -u).
+echo PERFETTO_TEST_GN_ARGS: ${PERFETTO_TEST_GN_ARGS}
+
+OUT_PATH="out/dist"
+
+tools/install-build-deps --no-android --ui
+
+tools/gn gen ${OUT_PATH} --args="${PERFETTO_TEST_GN_ARGS}" --check
+tools/ninja -C ${OUT_PATH} ui 2>&1 | grep -v "no version information available"
+
+# Run the tests
+${OUT_PATH}/ui_unittests --ci
diff --git a/infra/oss-fuzz/build_fuzzers b/infra/oss-fuzz/build_fuzzers
index 19a36a2..7275a69 100755
--- a/infra/oss-fuzz/build_fuzzers
+++ b/infra/oss-fuzz/build_fuzzers
@@ -8,10 +8,8 @@
 
 GN_ARGS="is_clang=true is_debug=false is_fuzzer=true use_libfuzzer=false \
 link_fuzzer=\"-lFuzzingEngine\" is_asan=true is_hermetic_clang=false \
-use_custom_libcxx=false \
-extra_cflags=\"$CFLAGS -Wno-implicit-int-float-conversion\" \
-extra_cxxflags=\"$CXXFLAGS\" extra_ldflags=\"$CXXFLAGS\" \
-is_system_compiler=true"
+use_custom_libcxx=false extra_cflags=\"$CFLAGS\" extra_cxxflags=\"$CXXFLAGS\" \
+extra_ldflags=\"$CXXFLAGS\" is_system_compiler=true"
 
 OUTDIR=$WORK/build
 $SRC/perfetto/tools/gn gen "$OUTDIR" --args="${GN_ARGS}" --check
diff --git a/infra/perfetto-ci.appspot.com/Makefile b/infra/perfetto-ci.appspot.com/Makefile
new file mode 100644
index 0000000..044f307
--- /dev/null
+++ b/infra/perfetto-ci.appspot.com/Makefile
@@ -0,0 +1,21 @@
+# Copyright (C) 2017 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.
+
+deploy:
+	gcloud app deploy app.yaml --project perfetto-ci
+
+test:
+	dev_appserver.py .
+
+.PHONY: deploy test
diff --git a/infra/perfetto-ci.appspot.com/app.yaml b/infra/perfetto-ci.appspot.com/app.yaml
new file mode 100644
index 0000000..ada3b40
--- /dev/null
+++ b/infra/perfetto-ci.appspot.com/app.yaml
@@ -0,0 +1,37 @@
+# Copyright (C) 2017 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.
+
+runtime: python27
+api_version: 1
+threadsafe: yes
+instance_class: B1
+manual_scaling:
+  instances: 1
+handlers:
+- url: /
+  static_files: static/index.html
+  upload: static/index.html
+  secure: always
+  redirect_http_response_code: 301
+- url: /service_worker.js
+  static_files: static/service_worker.js
+  upload: static/service_worker.js
+  secure: always
+  redirect_http_response_code: 301
+- url: /static/
+  static_dir: static/
+  secure: always
+  redirect_http_response_code: 301
+- url: /changes/.*
+  script: main.app
diff --git a/infra/perfetto-ci.appspot.com/main.py b/infra/perfetto-ci.appspot.com/main.py
new file mode 100644
index 0000000..bc27afe
--- /dev/null
+++ b/infra/perfetto-ci.appspot.com/main.py
@@ -0,0 +1,31 @@
+# Copyright (C) 2017 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.
+
+import webapp2
+
+from google.appengine.api import urlfetch
+
+
+class ChangesHandler(webapp2.RequestHandler):
+  def get(self):
+    url = ('https://android-review.googlesource.com/changes/?' +
+        self.request.query_string)
+    result = urlfetch.fetch(url)
+    self.response.status_int = result.status_code
+    self.response.write(result.content)
+
+
+app = webapp2.WSGIApplication([
+    ('/changes/', ChangesHandler),
+], debug=True)
diff --git a/infra/perfetto-ci.appspot.com/static/icon.png b/infra/perfetto-ci.appspot.com/static/icon.png
new file mode 100644
index 0000000..e003c1d
--- /dev/null
+++ b/infra/perfetto-ci.appspot.com/static/icon.png
Binary files differ
diff --git a/infra/perfetto-ci.appspot.com/static/index.html b/infra/perfetto-ci.appspot.com/static/index.html
new file mode 100644
index 0000000..f9e9eee
--- /dev/null
+++ b/infra/perfetto-ci.appspot.com/static/index.html
@@ -0,0 +1,97 @@
+<!doctype html>
+<html>
+  <!--
+    Copyright 2017 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.
+  -->
+  <head>
+    <meta charset="utf-8">
+    <title>Perfetto CI</title>
+    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
+    <link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400" rel="stylesheet">
+    <link href="static/icon.png" rel="shortcut icon">
+    <style type="text/css">
+      html { font-family: 'Source Sans Pro', sans-serif; font-size: 13px; font-weight: 300; padding: 0; margin: 0; }
+      body { padding: 0; margin: 0; }
+      header { background: rgb(212, 233, 169); width: 100%; padding: 0 20px; box-sizing: border-box; overflow: hidden; }
+      #travis-badge { float: right; line-height: 80px; }
+      h1 { font-size: 32px; font-weight: 300; padding-left: 60px; line-height: 50px; background-image: url('static/icon.png'); background-repeat: no-repeat; background-size: contain; }
+      h2 { margin: 20px; font-size: 20px; font-weight: 400; color: #333; }
+      table { width: 100%; }
+      table tbody td:first-child { padding-left: 20px !important; }
+      thead { background: #fafafa; color: #111; font-size: 14px; font-weight: 400; }
+      thead tr:nth-child(n+3) td { font-size: 10px; }
+      thead tr:nth-child(4) td { width: 20px; }
+      thead td { padding: 2px 5px; text-align: center; border: 1px solid #ddd; }
+      a { color: black; text-decoration: none; }
+      a:hover { text-decoration: underline; }
+      #cls td { border-bottom: 1px solid #eee; font-size: 13px; font-weight: 300; line-height: 2; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
+      #cls tr:hover { background: #eef; }
+      #cls td:nth-child(n+5) { text-align: center; }
+      #cls td.job i { font-size: 16px; }
+      #cls td.job { color: #edde3f; }
+      #cls td.job .finished { color: #39aa56; }
+      #cls td.job .errored { color: #db4545; }
+      #cls tr.MERGED td:not(.job), #cls tr.MERGED td:not(.job) a { color: #BBB ; }
+    </style>
+  </head>
+  <body>
+    <header>
+      <div id="travis-badge">
+        <a href="https://travis-ci.org/catapult-project/perfetto/builds">
+          <img src="https://travis-ci.org/catapult-project/perfetto.svg?branch=master">
+        </a>
+      </div>
+      <h1>Perfetto Continuous Integration</h1>
+    </header>
+
+    <h2>Recent CLs</h2>
+    <table>
+      <thead>
+        <tr>
+          <td rowspan="4">Subject</td>
+          <td rowspan="4">Status</td>
+          <td rowspan="4">Owner</td>
+          <td rowspan="4">Updated</td>
+          <td colspan="10">Bots</td>
+        </tr>
+        <tr>
+          <td colspan="8">linux</td>
+          <td colspan="2">android</td>
+        </tr>
+        <tr>
+          <td>gcc7</td>
+          <td colspan="5">clang</td>
+          <td colspan="2">ui</td>
+          <td colspan="2">clang-arm</td>
+        </tr>
+        <tr id="cls_header">
+          <td id="linux_trusty-gcc7-x86_64-release">rel</td>
+          <td id="linux_trusty-clang-x86_64-debug">dbg</td>
+          <td id="linux_trusty-clang-x86_64-tsan">tsan</td>
+          <td id="linux_trusty-clang-x86_64-msan">msan</td>
+          <td id="linux_trusty-clang-x86_64-asan_lsan">{a,l}san</td>
+          <td id="linux_trusty-clang-x86_64-libfuzzer">fuzzer</td>
+          <td id="ui-clang-x86_64-debug">dbg</td>
+          <td id="ui-clang-x86_64-release">rel</td>
+          <td id="android-clang-arm-release">rel</td>
+          <td id="android-clang-arm-asan">asan</td>
+        </tr>
+      </thead>
+      <tbody id="cls">
+      </tbody>
+    </table>
+  </body>
+</html>
+<script type="text/javascript" src="static/script.js"></script>
diff --git a/infra/perfetto-ci.appspot.com/static/script.js b/infra/perfetto-ci.appspot.com/static/script.js
new file mode 100644
index 0000000..d1d0f95
--- /dev/null
+++ b/infra/perfetto-ci.appspot.com/static/script.js
@@ -0,0 +1,157 @@
+/**
+ * Copyright (c) 2017 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.
+ */
+
+'use strict';
+
+const REPO_URL = 'https://android.googlesource.com/platform/external/perfetto/';
+const GERRIT_REVIEW_URL = 'https://android-review.googlesource.com/c/platform/external/perfetto';
+const CHANGES_URL = '/changes/?q=project:platform/external/perfetto+-age:7days+-is:abandoned&o=DETAILED_ACCOUNTS';
+const REPO = 'catapult-project/perfetto';
+
+let botIndex = {};
+
+// Builds a map of bot name -> column index, e.g.:
+// {'linux-clang-x86_64-relese' -> 1, 'android-clang-arm-debug' -> 2}.
+function GetColumnIndexes() {
+  const cols = document.getElementById('cls_header').children;
+  for (let i = 0; i < cols.length; i++) {
+    const id = cols[i].id;
+    if (id)
+      botIndex[id] = i + 4 /* 4 = subject...updated columns */;
+  }
+}
+
+function GetTravisStatusForJob(jobId, div) {
+  fetch('https://api.travis-ci.org/jobs/' + jobId)
+    .then(response => {
+      if (response.status != 200)
+        throw 'Unable to make request to Travis';
+      return response.json();
+    })
+    .then(resp => {
+      let jobName = resp.config.env.split(' ')[0];
+      if (jobName.startsWith('CFG='))
+        jobName = jobName.substring(4);
+      if (!(jobName in botIndex))
+        return;
+      let link = document.createElement('a');
+      link.href = 'https://travis-ci.org/' + REPO + '/jobs/' + jobId;
+      link.title = resp.state + ' [' + jobName + ']';
+      let jobState = resp.state;
+      if (resp.state == 'finished' && resp.result !== 0)
+        jobState = 'errored';
+      link.classList.add(jobState);
+      if (jobState == 'finished')
+        link.innerHTML = '<i class="material-icons">check_circle</i>';
+      else if (jobState == 'created')
+        link.innerHTML = '<i class="material-icons">autorenew</i>';
+      else if (jobState == 'errored' || jobState == 'cancelled')
+        link.innerHTML = '<i class="material-icons">bug_report</i>';
+      else
+        link.innerHTML = '<i class="material-icons">hourglass_full</i>';
+      let td = div.children[botIndex[jobName]];
+      td.innerHTML = '';
+      td.appendChild(link);
+    });
+}
+
+function GetTravisStatusForBranch(branch, div) {
+  fetch('https://api.travis-ci.org/repos/' + REPO + '/branches/' + branch)
+    .then(response => {
+      if (response.status != 200)
+        throw 'Unable to make request to Travis';
+      return response.json()
+    })
+    .then(resp => {
+      for (const jobId of resp.branch.job_ids)
+        GetTravisStatusForJob(jobId, div);
+    });
+}
+
+function CreateRowForBranch(branch, href, subject, status, author, updated) {
+  let table = document.getElementById('cls');
+  let tr = document.createElement('tr');
+  tr.classList.add(status);
+
+  let link = document.createElement('a');
+  link.href = href;
+  link.innerText = subject;
+  let td = document.createElement('td');
+  td.appendChild(link);
+  tr.appendChild(td);
+
+  td = document.createElement('td');
+  td.innerText = status;
+  tr.appendChild(td);
+
+  td = document.createElement('td');
+  td.innerText = author;
+  tr.appendChild(td);
+
+  td = document.createElement('td');
+  td.innerText = updated;
+  tr.appendChild(td);
+
+  for (let _ in botIndex) {
+    td = document.createElement('td');
+    td.classList.add('job');
+    tr.appendChild(td);
+  }
+  table.appendChild(tr);
+  GetTravisStatusForBranch(branch, tr);
+}
+
+function LoadGerritCLs() {
+  fetch(CHANGES_URL)
+    .then(response => {
+      if (response.status != 200)
+        throw 'Unable to make request to Travis';
+      return response.text();
+    })
+    .then(text => {
+      let json;
+      if (text.startsWith(')]}\''))
+        json = text.substring(4);
+      else
+        json = text;
+      let resp = JSON.parse(json);
+      for (const cl of resp) {
+        const branch = 'changes/' + cl._number;
+        const href = GERRIT_REVIEW_URL + '/+/' + cl._number;;
+        const lastUpdate = new Date(cl.updated + ' UTC');
+        const lastUpdateMins = Math.ceil((Date.now() - lastUpdate) / 60000);
+        let lastUpdateText = '';
+        if (lastUpdateMins < 60)
+          lastUpdateText = lastUpdateMins + ' mins ago';
+        else if (lastUpdateMins < 60 * 24)
+          lastUpdateText = Math.ceil(lastUpdateMins / 60) + ' hours ago';
+        else
+          lastUpdateText = lastUpdate.toLocaleDateString();
+        CreateRowForBranch(branch, href, cl.subject, cl.status,
+            cl.owner.email.replace('@google.com', '@'), lastUpdateText);
+      }
+    });
+}
+
+// Register the service worker to cache job requests.
+if ('serviceWorker' in navigator) {
+  navigator.serviceWorker.register('/service_worker.js', { scope: '/' });
+}
+
+// Fetch the CLs and the corresponding status for the Travis jobs.
+GetColumnIndexes();
+CreateRowForBranch('master', REPO_URL, '*** master branch ***', 'MASTER', '', '');
+LoadGerritCLs();
diff --git a/infra/perfetto-ci.appspot.com/static/service_worker.js b/infra/perfetto-ci.appspot.com/static/service_worker.js
new file mode 100644
index 0000000..75403d8
--- /dev/null
+++ b/infra/perfetto-ci.appspot.com/static/service_worker.js
@@ -0,0 +1,56 @@
+/**
+ * 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.
+ */
+
+'use strict';
+
+const CACHE_NAME = 'travis-cache';
+const JOBS_URL = 'https://api.travis-ci.org/jobs/';
+
+async function FetchAndCacheIfJob(event) {
+  if (!event.request.url.startsWith(JOBS_URL)) {
+    return fetch(event.request);
+  }
+
+  // Try and retrieve from the cache.
+  const cachedResponse = await caches.match(event.request);
+  if (cachedResponse) {
+    return cachedResponse;
+  }
+
+  // If network request failed just return the response.
+  const response = await fetch(event.request);
+  if (!response || response.status !== 200) {
+    return response;
+  }
+
+  // Extract the JSON from the response.
+  const json = await response.clone().json();
+  if (json.state !== 'cancelled' && json.state !== 'finished') {
+    return response;
+  }
+
+  var responseToCache = response.clone();
+  caches.open(CACHE_NAME)
+    .then(cache => {
+      cache.put(event.request, responseToCache);
+    });
+
+  return response;
+}
+
+self.addEventListener('fetch', event => {
+  event.respondWith(FetchAndCacheIfJob(event));
+});
diff --git a/infra/perfetto-get.appspot.com/main.py b/infra/perfetto-get.appspot.com/main.py
index dc06974..132464d 100644
--- a/infra/perfetto-get.appspot.com/main.py
+++ b/infra/perfetto-get.appspot.com/main.py
@@ -28,14 +28,12 @@
 
 
 class RedirectHandler(webapp2.RequestHandler):
-
   def get(self):
     self.error(301)
     self.response.headers['Location'] = 'https://www.perfetto.dev/'
 
 
 class GitilesMirrorHandler(webapp2.RequestHandler):
-
   def get(self, resource):
     resource = resource.lower()
     if resource not in RESOURCES:
@@ -51,7 +49,8 @@
         memcache.delete(url)
         self.response.set_status(result.status_code)
         self.response.write(
-            'http error %d while fetching %s' % (result.status_code, url))
+            'http error %d while fetching %s' % (
+                result.status_code, url))
         return
       contents = base64.b64decode(result.content)
       memcache.set(url, contents, time=3600)  # 1h
@@ -64,5 +63,4 @@
 app = webapp2.WSGIApplication([
     ('/', RedirectHandler),
     ('/(.*)', GitilesMirrorHandler),
-],
-                              debug=True)
+], debug=True)
diff --git a/infra/perfetto-site.appspot.com/Makefile b/infra/perfetto-site.appspot.com/Makefile
index 0811e7f..a1586e4 100644
--- a/infra/perfetto-site.appspot.com/Makefile
+++ b/infra/perfetto-site.appspot.com/Makefile
@@ -23,8 +23,6 @@
 	cp node_modules/docsify-themeable/dist/css/theme-simple.css static/
 	cp node_modules/docsify-copy-code/dist/docsify-copy-code.min.js static/
 	cp node_modules/prismjs/components/prism-bash.min.js static/
-	cp node_modules/prismjs/components/prism-protobuf.min.js static/
-	cp node_modules/prismjs/components/prism-sql.min.js static/
 
 deploy: static
 	gcloud app deploy app.yaml --project perfetto-site
diff --git a/infra/perfetto-site.appspot.com/main.py b/infra/perfetto-site.appspot.com/main.py
index b42dd96..b05de0b 100644
--- a/infra/perfetto-site.appspot.com/main.py
+++ b/infra/perfetto-site.appspot.com/main.py
@@ -18,55 +18,50 @@
 import re
 import webapp2
 
-MEMCACHE_TTL_SEC = 60 * 60 * 24
+MEMCACHE_TTL_SEC= 60 * 60 * 24
 BASE = 'https://catapult-project.github.io/perfetto/%s'
-HEADERS = {
-    'last-modified', 'content-type', 'content-length', 'content-encoding',
-    'etag'
-}
+HEADERS = {'last-modified', 'content-type',
+           'content-length', 'content-encoding', 'etag'}
 
 
 class MainHandler(webapp2.RequestHandler):
-
-  def get(self):
-    handler = GithubMirrorHandler()
-    handler.initialize(self.request, self.response)
-    return handler.get("index.html")
+    def get(self):
+        handler = GithubMirrorHandler()
+        handler.initialize(self.request, self.response)
+        return handler.get("index.html")
 
 
 class GithubMirrorHandler(webapp2.RequestHandler):
+    def get(self, resource):
+        if not re.match('^[a-zA-Z0-9-_./]*$', resource):
+            self.response.set_status(403)
+            return
 
-  def get(self, resource):
-    if not re.match('^[a-zA-Z0-9-_./]*$', resource):
-      self.response.set_status(403)
-      return
+        url = BASE % resource
+        cache = memcache.get(url)
+        if not cache or self.request.get('reload'):
+            result = urlfetch.fetch(url)
+            if result.status_code != 200:
+                memcache.delete(url)
+                self.response.set_status(result.status_code)
+                self.response.write(result.content)
+                return
+            cache = {'content-type': 'text/html'}
+            for k, v in result.headers.iteritems():
+                k = k.lower()
+                if k in HEADERS:
+                    cache[k] = v
+            cache['content'] = result.content
+            memcache.set(url, cache, time=MEMCACHE_TTL_SEC)
 
-    url = BASE % resource
-    cache = memcache.get(url)
-    if not cache or self.request.get('reload'):
-      result = urlfetch.fetch(url)
-      if result.status_code != 200:
-        memcache.delete(url)
-        self.response.set_status(result.status_code)
-        self.response.write(result.content)
-        return
-      cache = {'content-type': 'text/html'}
-      for k, v in result.headers.iteritems():
-        k = k.lower()
-        if k in HEADERS:
-          cache[k] = v
-      cache['content'] = result.content
-      memcache.set(url, cache, time=MEMCACHE_TTL_SEC)
-
-    for k, v in cache.iteritems():
-      if k != 'content':
-        self.response.headers[k] = v
-    self.response.headers['cache-control'] = 'public,max-age=600'
-    self.response.write(cache['content'])
+        for k, v in cache.iteritems():
+            if k != 'content':
+                self.response.headers[k] = v
+        self.response.headers['cache-control'] = 'public,max-age=600'
+        self.response.write(cache['content'])
 
 
 app = webapp2.WSGIApplication([
     ('/', MainHandler),
     ('/(.+)', GithubMirrorHandler),
-],
-                              debug=True)
+], debug=True)
diff --git a/perfetto.rc b/perfetto.rc
index 8d07713..a33bd03 100644
--- a/perfetto.rc
+++ b/perfetto.rc
@@ -62,3 +62,7 @@
 on property:persist.traced.enable=0
     stop traced
     stop traced_probes
+
+# Reset the Perfetto guard rail state on boot:
+on post-fs-data
+    rm /data/misc/perfetto-traces/.guardraildata
diff --git a/protos/BUILD b/protos/BUILD
new file mode 100644
index 0000000..4a8d55f
--- /dev/null
+++ b/protos/BUILD
@@ -0,0 +1,906 @@
+# Copyright (C) 2019 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 file is automatically generated by tools/gen_build. Do not edit.
+
+load("//tools/build_defs/proto/cpp:cc_proto_library.bzl", "cc_proto_library")
+load("//third_party/perfetto/google:build_defs.bzl", "pbzero_cc_proto_library")
+
+package(default_visibility = ["//third_party/perfetto:__subpackages__"])
+
+licenses(["notice"])  # Apache 2.0
+
+exports_files(["LICENSE"])
+
+# GN target: //protos/perfetto/common:lite_gen
+proto_library(
+    name = "common",
+    srcs = [
+        "perfetto/common/android_log_constants.proto",
+        "perfetto/common/commit_data_request.proto",
+        "perfetto/common/data_source_descriptor.proto",
+        "perfetto/common/descriptor.proto",
+        "perfetto/common/observable_events.proto",
+        "perfetto/common/sys_stats_counters.proto",
+        "perfetto/common/trace_stats.proto",
+        "perfetto/common/tracing_service_state.proto",
+    ],
+    has_services = 1,
+    cc_api_version = 2,
+    cc_generic_services = 1,
+    visibility = [
+        "//visibility:public",
+    ],
+)
+
+# GN target: //protos/perfetto/common:lite_gen
+cc_proto_library(
+    name = "common_cc_proto",
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:common",
+    ],
+)
+
+# GN target: //protos/perfetto/common:zero_gen
+proto_library(
+    name = "common_zero",
+    srcs = [
+        "perfetto/common/android_log_constants.proto",
+        "perfetto/common/commit_data_request.proto",
+        "perfetto/common/data_source_descriptor.proto",
+        "perfetto/common/descriptor.proto",
+        "perfetto/common/observable_events.proto",
+        "perfetto/common/sys_stats_counters.proto",
+        "perfetto/common/trace_stats.proto",
+        "perfetto/common/tracing_service_state.proto",
+    ],
+)
+
+# GN target: //protos/perfetto/common:zero_gen
+pbzero_cc_proto_library(
+    name = "common_zero_cc_proto",
+    src_proto_library = "//third_party/perfetto/protos:common_zero",
+    deps = [
+        "//third_party/perfetto:libprotozero",
+        "//third_party/perfetto/google:gtest_prod",
+    ],
+)
+
+# GN target: //protos/perfetto/config:lite_gen
+proto_library(
+    name = "config",
+    srcs = [
+        "perfetto/config/android/android_log_config.proto",
+        "perfetto/config/android/packages_list_config.proto",
+        "perfetto/config/chrome/chrome_config.proto",
+        "perfetto/config/data_source_config.proto",
+        "perfetto/config/ftrace/ftrace_config.proto",
+        "perfetto/config/inode_file/inode_file_config.proto",
+        "perfetto/config/power/android_power_config.proto",
+        "perfetto/config/process_stats/process_stats_config.proto",
+        "perfetto/config/profiling/heapprofd_config.proto",
+        "perfetto/config/sys_stats/sys_stats_config.proto",
+        "perfetto/config/test_config.proto",
+        "perfetto/config/trace_config.proto",
+    ],
+    has_services = 1,
+    cc_api_version = 2,
+    cc_generic_services = 1,
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:common",
+    ],
+)
+
+# GN target: //protos/perfetto/config:lite_gen
+cc_proto_library(
+    name = "config_cc_proto",
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:config",
+    ],
+)
+
+# GN target: //protos/perfetto/config:merged_config_gen
+proto_library(
+    name = "config_merged_config_gen",
+    srcs = [
+        "perfetto/config/perfetto_config.proto",
+    ],
+    has_services = 1,
+    cc_api_version = 2,
+    cc_generic_services = 1,
+    visibility = [
+        "//visibility:public",
+    ],
+)
+
+# GN target: //protos/perfetto/config:merged_config_gen
+cc_proto_library(
+    name = "config_merged_config_gen_cc_proto",
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:config_merged_config_gen",
+    ],
+)
+
+# GN target: //protos/perfetto/config:zero_gen
+proto_library(
+    name = "config_zero",
+    srcs = [
+        "perfetto/config/android/android_log_config.proto",
+        "perfetto/config/android/packages_list_config.proto",
+        "perfetto/config/chrome/chrome_config.proto",
+        "perfetto/config/data_source_config.proto",
+        "perfetto/config/ftrace/ftrace_config.proto",
+        "perfetto/config/inode_file/inode_file_config.proto",
+        "perfetto/config/power/android_power_config.proto",
+        "perfetto/config/process_stats/process_stats_config.proto",
+        "perfetto/config/profiling/heapprofd_config.proto",
+        "perfetto/config/sys_stats/sys_stats_config.proto",
+        "perfetto/config/test_config.proto",
+        "perfetto/config/trace_config.proto",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:common_zero",
+    ],
+)
+
+# GN target: //protos/perfetto/config:zero_gen
+pbzero_cc_proto_library(
+    name = "config_zero_cc_proto",
+    src_proto_library = "//third_party/perfetto/protos:config_zero",
+    deps = [
+        "//third_party/perfetto:libprotozero",
+        "//third_party/perfetto/google:gtest_prod",
+    ],
+)
+
+# GN target: //protos/perfetto/metrics/android:zero_gen
+proto_library(
+    name = "metrics_android_zero",
+    srcs = [
+        "perfetto/metrics/android/mem_metric.proto",
+    ],
+)
+
+# GN target: //protos/perfetto/metrics/android:zero_gen
+pbzero_cc_proto_library(
+    name = "metrics_android_zero_cc_proto",
+    src_proto_library = "//third_party/perfetto/protos:metrics_android_zero",
+    deps = [
+        "//third_party/perfetto:libprotozero",
+        "//third_party/perfetto/google:gtest_prod",
+    ],
+)
+
+# GN target: //protos/perfetto/metrics:zero_gen
+proto_library(
+    name = "metrics_zero",
+    srcs = [
+        "perfetto/metrics/metrics.proto",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:metrics_android_zero",
+    ],
+)
+
+# GN target: //protos/perfetto/metrics:zero_gen
+pbzero_cc_proto_library(
+    name = "metrics_zero_cc_proto",
+    src_proto_library = "//third_party/perfetto/protos:metrics_zero",
+    deps = [
+        "//third_party/perfetto:libprotozero",
+        "//third_party/perfetto/google:gtest_prod",
+    ],
+)
+
+# GN target: //protos/third_party/pprof:lite_gen
+proto_library(
+    name = "protos_third_party_pprof",
+    srcs = [
+        "third_party/pprof/profile.proto",
+    ],
+    has_services = 1,
+    cc_api_version = 2,
+    cc_generic_services = 1,
+    visibility = [
+        "//visibility:public",
+    ],
+)
+
+# GN target: //protos/third_party/pprof:lite_gen
+cc_proto_library(
+    name = "protos_third_party_pprof_cc_proto",
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:protos_third_party_pprof",
+    ],
+)
+
+# GN target: //protos/perfetto/trace:lite_gen
+proto_library(
+    name = "trace",
+    srcs = [
+        "perfetto/trace/test_event.proto",
+        "perfetto/trace/trace.proto",
+        "perfetto/trace/trace_packet.proto",
+    ],
+    has_services = 1,
+    cc_api_version = 2,
+    cc_generic_services = 1,
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:common",
+        "//third_party/perfetto/protos:config",
+        "//third_party/perfetto/protos:trace_android",
+        "//third_party/perfetto/protos:trace_chrome",
+        "//third_party/perfetto/protos:trace_filesystem",
+        "//third_party/perfetto/protos:trace_ftrace",
+        "//third_party/perfetto/protos:trace_interned_data",
+        "//third_party/perfetto/protos:trace_minimal",
+        "//third_party/perfetto/protos:trace_power",
+        "//third_party/perfetto/protos:trace_profiling",
+        "//third_party/perfetto/protos:trace_ps",
+        "//third_party/perfetto/protos:trace_sys_stats",
+        "//third_party/perfetto/protos:trace_track_event",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/android:lite_gen
+proto_library(
+    name = "trace_android",
+    srcs = [
+        "perfetto/trace/android/android_log.proto",
+        "perfetto/trace/android/packages_list.proto",
+    ],
+    has_services = 1,
+    cc_api_version = 2,
+    cc_generic_services = 1,
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:common",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/android:lite_gen
+cc_proto_library(
+    name = "trace_android_cc_proto",
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:trace_android",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/android:zero_gen
+proto_library(
+    name = "trace_android_zero",
+    srcs = [
+        "perfetto/trace/android/android_log.proto",
+        "perfetto/trace/android/packages_list.proto",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:common_zero",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/android:zero_gen
+pbzero_cc_proto_library(
+    name = "trace_android_zero_cc_proto",
+    src_proto_library = "//third_party/perfetto/protos:trace_android_zero",
+    deps = [
+        "//third_party/perfetto:libprotozero",
+        "//third_party/perfetto/google:gtest_prod",
+    ],
+)
+
+# GN target: //protos/perfetto/trace:lite_gen
+cc_proto_library(
+    name = "trace_cc_proto",
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:trace",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/chrome:lite_gen
+proto_library(
+    name = "trace_chrome",
+    srcs = [
+        "perfetto/trace/chrome/chrome_trace_event.proto",
+    ],
+    has_services = 1,
+    cc_api_version = 2,
+    cc_generic_services = 1,
+    visibility = [
+        "//visibility:public",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/chrome:lite_gen
+cc_proto_library(
+    name = "trace_chrome_cc_proto",
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:trace_chrome",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/chrome:zero_gen
+proto_library(
+    name = "trace_chrome_zero",
+    srcs = [
+        "perfetto/trace/chrome/chrome_trace_event.proto",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:trace_interned_data_zero",
+        "//third_party/perfetto/protos:trace_track_event_zero",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/chrome:zero_gen
+pbzero_cc_proto_library(
+    name = "trace_chrome_zero_cc_proto",
+    src_proto_library = "//third_party/perfetto/protos:trace_chrome_zero",
+    deps = [
+        "//third_party/perfetto:libprotozero",
+        "//third_party/perfetto/google:gtest_prod",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/filesystem:lite_gen
+proto_library(
+    name = "trace_filesystem",
+    srcs = [
+        "perfetto/trace/filesystem/inode_file_map.proto",
+    ],
+    has_services = 1,
+    cc_api_version = 2,
+    cc_generic_services = 1,
+    visibility = [
+        "//visibility:public",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/filesystem:lite_gen
+cc_proto_library(
+    name = "trace_filesystem_cc_proto",
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:trace_filesystem",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/filesystem:zero_gen
+proto_library(
+    name = "trace_filesystem_zero",
+    srcs = [
+        "perfetto/trace/filesystem/inode_file_map.proto",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/filesystem:zero_gen
+pbzero_cc_proto_library(
+    name = "trace_filesystem_zero_cc_proto",
+    src_proto_library = "//third_party/perfetto/protos:trace_filesystem_zero",
+    deps = [
+        "//third_party/perfetto:libprotozero",
+        "//third_party/perfetto/google:gtest_prod",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/ftrace:lite_gen
+proto_library(
+    name = "trace_ftrace",
+    srcs = [
+        "perfetto/trace/ftrace/binder.proto",
+        "perfetto/trace/ftrace/block.proto",
+        "perfetto/trace/ftrace/cgroup.proto",
+        "perfetto/trace/ftrace/clk.proto",
+        "perfetto/trace/ftrace/compaction.proto",
+        "perfetto/trace/ftrace/ext4.proto",
+        "perfetto/trace/ftrace/f2fs.proto",
+        "perfetto/trace/ftrace/fence.proto",
+        "perfetto/trace/ftrace/filemap.proto",
+        "perfetto/trace/ftrace/ftrace.proto",
+        "perfetto/trace/ftrace/ftrace_event.proto",
+        "perfetto/trace/ftrace/ftrace_event_bundle.proto",
+        "perfetto/trace/ftrace/ftrace_stats.proto",
+        "perfetto/trace/ftrace/generic.proto",
+        "perfetto/trace/ftrace/i2c.proto",
+        "perfetto/trace/ftrace/ipi.proto",
+        "perfetto/trace/ftrace/irq.proto",
+        "perfetto/trace/ftrace/kmem.proto",
+        "perfetto/trace/ftrace/lowmemorykiller.proto",
+        "perfetto/trace/ftrace/mdss.proto",
+        "perfetto/trace/ftrace/mm_event.proto",
+        "perfetto/trace/ftrace/oom.proto",
+        "perfetto/trace/ftrace/power.proto",
+        "perfetto/trace/ftrace/raw_syscalls.proto",
+        "perfetto/trace/ftrace/regulator.proto",
+        "perfetto/trace/ftrace/sched.proto",
+        "perfetto/trace/ftrace/signal.proto",
+        "perfetto/trace/ftrace/sync.proto",
+        "perfetto/trace/ftrace/systrace.proto",
+        "perfetto/trace/ftrace/task.proto",
+        "perfetto/trace/ftrace/test_bundle_wrapper.proto",
+        "perfetto/trace/ftrace/vmscan.proto",
+        "perfetto/trace/ftrace/workqueue.proto",
+    ],
+    has_services = 1,
+    cc_api_version = 2,
+    cc_generic_services = 1,
+    visibility = [
+        "//visibility:public",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/ftrace:lite_gen
+cc_proto_library(
+    name = "trace_ftrace_cc_proto",
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:trace_ftrace",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/ftrace:zero_gen
+proto_library(
+    name = "trace_ftrace_zero",
+    srcs = [
+        "perfetto/trace/ftrace/binder.proto",
+        "perfetto/trace/ftrace/block.proto",
+        "perfetto/trace/ftrace/cgroup.proto",
+        "perfetto/trace/ftrace/clk.proto",
+        "perfetto/trace/ftrace/compaction.proto",
+        "perfetto/trace/ftrace/ext4.proto",
+        "perfetto/trace/ftrace/f2fs.proto",
+        "perfetto/trace/ftrace/fence.proto",
+        "perfetto/trace/ftrace/filemap.proto",
+        "perfetto/trace/ftrace/ftrace.proto",
+        "perfetto/trace/ftrace/ftrace_event.proto",
+        "perfetto/trace/ftrace/ftrace_event_bundle.proto",
+        "perfetto/trace/ftrace/ftrace_stats.proto",
+        "perfetto/trace/ftrace/generic.proto",
+        "perfetto/trace/ftrace/i2c.proto",
+        "perfetto/trace/ftrace/ipi.proto",
+        "perfetto/trace/ftrace/irq.proto",
+        "perfetto/trace/ftrace/kmem.proto",
+        "perfetto/trace/ftrace/lowmemorykiller.proto",
+        "perfetto/trace/ftrace/mdss.proto",
+        "perfetto/trace/ftrace/mm_event.proto",
+        "perfetto/trace/ftrace/oom.proto",
+        "perfetto/trace/ftrace/power.proto",
+        "perfetto/trace/ftrace/raw_syscalls.proto",
+        "perfetto/trace/ftrace/regulator.proto",
+        "perfetto/trace/ftrace/sched.proto",
+        "perfetto/trace/ftrace/signal.proto",
+        "perfetto/trace/ftrace/sync.proto",
+        "perfetto/trace/ftrace/systrace.proto",
+        "perfetto/trace/ftrace/task.proto",
+        "perfetto/trace/ftrace/test_bundle_wrapper.proto",
+        "perfetto/trace/ftrace/vmscan.proto",
+        "perfetto/trace/ftrace/workqueue.proto",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/ftrace:zero_gen
+pbzero_cc_proto_library(
+    name = "trace_ftrace_zero_cc_proto",
+    src_proto_library = "//third_party/perfetto/protos:trace_ftrace_zero",
+    deps = [
+        "//third_party/perfetto:libprotozero",
+        "//third_party/perfetto/google:gtest_prod",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/interned_data:lite_gen
+proto_library(
+    name = "trace_interned_data",
+    srcs = [
+        "perfetto/trace/interned_data/interned_data.proto",
+    ],
+    has_services = 1,
+    cc_api_version = 2,
+    cc_generic_services = 1,
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:trace_track_event",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/interned_data:lite_gen
+cc_proto_library(
+    name = "trace_interned_data_cc_proto",
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:trace_interned_data",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/interned_data:zero_gen
+proto_library(
+    name = "trace_interned_data_zero",
+    srcs = [
+        "perfetto/trace/interned_data/interned_data.proto",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:trace_track_event_zero",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/interned_data:zero_gen
+pbzero_cc_proto_library(
+    name = "trace_interned_data_zero_cc_proto",
+    src_proto_library = "//third_party/perfetto/protos:trace_interned_data_zero",
+    deps = [
+        "//third_party/perfetto:libprotozero",
+        "//third_party/perfetto/google:gtest_prod",
+    ],
+)
+
+# GN target: //protos/perfetto/trace:merged_trace_gen
+proto_library(
+    name = "trace_merged_trace_gen",
+    srcs = [
+        "perfetto/trace/perfetto_trace.proto",
+    ],
+    has_services = 1,
+    cc_api_version = 2,
+    cc_generic_services = 1,
+    visibility = [
+        "//visibility:public",
+    ],
+)
+
+# GN target: //protos/perfetto/trace:merged_trace_gen
+cc_proto_library(
+    name = "trace_merged_trace_gen_cc_proto",
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:trace_merged_trace_gen",
+    ],
+)
+
+# GN target: //protos/perfetto/trace:minimal_lite_gen
+proto_library(
+    name = "trace_minimal",
+    srcs = [
+        "perfetto/trace/clock_snapshot.proto",
+        "perfetto/trace/system_info.proto",
+        "perfetto/trace/trigger.proto",
+    ],
+    has_services = 1,
+    cc_api_version = 2,
+    cc_generic_services = 1,
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:common",
+        "//third_party/perfetto/protos:config",
+    ],
+)
+
+# GN target: //protos/perfetto/trace:minimal_lite_gen
+cc_proto_library(
+    name = "trace_minimal_cc_proto",
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:trace_minimal",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/power:lite_gen
+proto_library(
+    name = "trace_power",
+    srcs = [
+        "perfetto/trace/power/battery_counters.proto",
+        "perfetto/trace/power/power_rails.proto",
+    ],
+    has_services = 1,
+    cc_api_version = 2,
+    cc_generic_services = 1,
+    visibility = [
+        "//visibility:public",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/power:lite_gen
+cc_proto_library(
+    name = "trace_power_cc_proto",
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:trace_power",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/power:zero_gen
+proto_library(
+    name = "trace_power_zero",
+    srcs = [
+        "perfetto/trace/power/battery_counters.proto",
+        "perfetto/trace/power/power_rails.proto",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/power:zero_gen
+pbzero_cc_proto_library(
+    name = "trace_power_zero_cc_proto",
+    src_proto_library = "//third_party/perfetto/protos:trace_power_zero",
+    deps = [
+        "//third_party/perfetto:libprotozero",
+        "//third_party/perfetto/google:gtest_prod",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/profiling:lite_gen
+proto_library(
+    name = "trace_profiling",
+    srcs = [
+        "perfetto/trace/profiling/profile_packet.proto",
+    ],
+    has_services = 1,
+    cc_api_version = 2,
+    cc_generic_services = 1,
+    visibility = [
+        "//visibility:public",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/profiling:lite_gen
+cc_proto_library(
+    name = "trace_profiling_cc_proto",
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:trace_profiling",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/profiling:zero_gen
+proto_library(
+    name = "trace_profiling_zero",
+    srcs = [
+        "perfetto/trace/profiling/profile_packet.proto",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/profiling:zero_gen
+pbzero_cc_proto_library(
+    name = "trace_profiling_zero_cc_proto",
+    src_proto_library = "//third_party/perfetto/protos:trace_profiling_zero",
+    deps = [
+        "//third_party/perfetto:libprotozero",
+        "//third_party/perfetto/google:gtest_prod",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/ps:lite_gen
+proto_library(
+    name = "trace_ps",
+    srcs = [
+        "perfetto/trace/ps/process_stats.proto",
+        "perfetto/trace/ps/process_tree.proto",
+    ],
+    has_services = 1,
+    cc_api_version = 2,
+    cc_generic_services = 1,
+    visibility = [
+        "//visibility:public",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/ps:lite_gen
+cc_proto_library(
+    name = "trace_ps_cc_proto",
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:trace_ps",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/ps:zero_gen
+proto_library(
+    name = "trace_ps_zero",
+    srcs = [
+        "perfetto/trace/ps/process_stats.proto",
+        "perfetto/trace/ps/process_tree.proto",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/ps:zero_gen
+pbzero_cc_proto_library(
+    name = "trace_ps_zero_cc_proto",
+    src_proto_library = "//third_party/perfetto/protos:trace_ps_zero",
+    deps = [
+        "//third_party/perfetto:libprotozero",
+        "//third_party/perfetto/google:gtest_prod",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/sys_stats:lite_gen
+proto_library(
+    name = "trace_sys_stats",
+    srcs = [
+        "perfetto/trace/sys_stats/sys_stats.proto",
+    ],
+    has_services = 1,
+    cc_api_version = 2,
+    cc_generic_services = 1,
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:common",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/sys_stats:lite_gen
+cc_proto_library(
+    name = "trace_sys_stats_cc_proto",
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:trace_sys_stats",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/sys_stats:zero_gen
+proto_library(
+    name = "trace_sys_stats_zero",
+    srcs = [
+        "perfetto/trace/sys_stats/sys_stats.proto",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:common_zero",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/sys_stats:zero_gen
+pbzero_cc_proto_library(
+    name = "trace_sys_stats_zero_cc_proto",
+    src_proto_library = "//third_party/perfetto/protos:trace_sys_stats_zero",
+    deps = [
+        "//third_party/perfetto:libprotozero",
+        "//third_party/perfetto/google:gtest_prod",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/track_event:lite_gen
+proto_library(
+    name = "trace_track_event",
+    srcs = [
+        "perfetto/trace/track_event/debug_annotation.proto",
+        "perfetto/trace/track_event/process_descriptor.proto",
+        "perfetto/trace/track_event/task_execution.proto",
+        "perfetto/trace/track_event/thread_descriptor.proto",
+        "perfetto/trace/track_event/track_event.proto",
+    ],
+    has_services = 1,
+    cc_api_version = 2,
+    cc_generic_services = 1,
+    visibility = [
+        "//visibility:public",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/track_event:lite_gen
+cc_proto_library(
+    name = "trace_track_event_cc_proto",
+    visibility = [
+        "//visibility:public",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:trace_track_event",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/track_event:zero_gen
+proto_library(
+    name = "trace_track_event_zero",
+    srcs = [
+        "perfetto/trace/track_event/debug_annotation.proto",
+        "perfetto/trace/track_event/process_descriptor.proto",
+        "perfetto/trace/track_event/task_execution.proto",
+        "perfetto/trace/track_event/thread_descriptor.proto",
+        "perfetto/trace/track_event/track_event.proto",
+    ],
+)
+
+# GN target: //protos/perfetto/trace/track_event:zero_gen
+pbzero_cc_proto_library(
+    name = "trace_track_event_zero_cc_proto",
+    src_proto_library = "//third_party/perfetto/protos:trace_track_event_zero",
+    deps = [
+        "//third_party/perfetto:libprotozero",
+        "//third_party/perfetto/google:gtest_prod",
+    ],
+)
+
+# GN target: //protos/perfetto/trace:zero_gen
+proto_library(
+    name = "trace_zero",
+    srcs = [
+        "perfetto/trace/clock_snapshot.proto",
+        "perfetto/trace/system_info.proto",
+        "perfetto/trace/test_event.proto",
+        "perfetto/trace/trace.proto",
+        "perfetto/trace/trace_packet.proto",
+        "perfetto/trace/trigger.proto",
+    ],
+    deps = [
+        "//third_party/perfetto/protos:common_zero",
+        "//third_party/perfetto/protos:config_zero",
+        "//third_party/perfetto/protos:trace_android_zero",
+        "//third_party/perfetto/protos:trace_chrome_zero",
+        "//third_party/perfetto/protos:trace_filesystem_zero",
+        "//third_party/perfetto/protos:trace_ftrace_zero",
+        "//third_party/perfetto/protos:trace_interned_data_zero",
+        "//third_party/perfetto/protos:trace_power_zero",
+        "//third_party/perfetto/protos:trace_profiling_zero",
+        "//third_party/perfetto/protos:trace_ps_zero",
+        "//third_party/perfetto/protos:trace_sys_stats_zero",
+        "//third_party/perfetto/protos:trace_track_event_zero",
+    ],
+)
+
+# GN target: //protos/perfetto/trace:zero_gen
+pbzero_cc_proto_library(
+    name = "trace_zero_cc_proto",
+    src_proto_library = "//third_party/perfetto/protos:trace_zero",
+    deps = [
+        "//third_party/perfetto:libprotozero",
+        "//third_party/perfetto/google:gtest_prod",
+    ],
+)
diff --git a/protos/perfetto/common/BUILD.gn b/protos/perfetto/common/BUILD.gn
index 6721740..e70b03c 100644
--- a/protos/perfetto/common/BUILD.gn
+++ b/protos/perfetto/common/BUILD.gn
@@ -14,20 +14,31 @@
 
 import("../../../gn/perfetto.gni")
 import("../../../gn/proto_library.gni")
+import("../../../gn/protozero_library.gni")
+
+common_sources = [
+  "android_log_constants.proto",
+  "commit_data_request.proto",
+  "data_source_descriptor.proto",
+  "descriptor.proto",
+  "observable_events.proto",
+  "sys_stats_counters.proto",
+  "tracing_service_state.proto",
+  "trace_stats.proto",
+]
 
 # Proto messages that are required by the IPC service definitions but have also
 # a C++ counterpart in tracing/core (i.e. are used also for the non-IPC cases).
-perfetto_proto_library("@TYPE@") {
-  sources = [
-    "android_log_constants.proto",
-    "commit_data_request.proto",
-    "data_source_descriptor.proto",
-    "descriptor.proto",
-    "gpu_counter_descriptor.proto",
-    "observable_events.proto",
-    "sys_stats_counters.proto",
-    "trace_stats.proto",
-    "tracing_service_state.proto",
-    "track_event_descriptor.proto",
-  ]
+proto_library("lite") {
+  generate_python = false
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  sources = common_sources
+}
+
+protozero_library("zero") {
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  sources = common_sources
+  generator_plugin_options = "wrapper_namespace=pbzero"
 }
diff --git a/protos/perfetto/common/data_source_descriptor.proto b/protos/perfetto/common/data_source_descriptor.proto
index 63a5114..08ed058 100644
--- a/protos/perfetto/common/data_source_descriptor.proto
+++ b/protos/perfetto/common/data_source_descriptor.proto
@@ -19,8 +19,8 @@
 
 package perfetto.protos;
 
-import "protos/perfetto/common/gpu_counter_descriptor.proto";
-import "protos/perfetto/common/track_event_descriptor.proto";
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
 
 // This message is sent from Producer(s) to the tracing Service when registering
 // to advertise their capabilities. It describes the structure of tracing
@@ -42,9 +42,4 @@
   // set if the data source writes packets that refer to previous trace
   // contents, and knows how to stop referring to the already-emitted data.
   optional bool handles_incremental_state_clear = 4;
-
-  // Optional specification about available GPU counters.
-  optional GpuCounterDescriptor gpu_counter_descriptor = 5 [lazy = true];
-
-  optional TrackEventDescriptor track_event_descriptor = 6 [lazy = true];
 }
diff --git a/protos/perfetto/common/descriptor.proto b/protos/perfetto/common/descriptor.proto
index d0d86ab..be0fff5 100644
--- a/protos/perfetto/common/descriptor.proto
+++ b/protos/perfetto/common/descriptor.proto
@@ -43,9 +43,9 @@
   // All top-level definitions in this file.
   repeated DescriptorProto message_type = 4;
   repeated EnumDescriptorProto enum_type = 5;
-  repeated FieldDescriptorProto extension = 7;
 
   reserved 6;
+  reserved 7;
   reserved 8;
   reserved 9;
   reserved 12;
@@ -137,9 +137,7 @@
   // namespace).
   optional string type_name = 6;
 
-  // For extensions, this is the name of the type being extended.  It is
-  // resolved in the same manner as type_name.
-  optional string extendee = 2;
+  reserved 2;
 
   // For numeric types, contains the original text representation of the value.
   // For booleans, "true" or "false".
diff --git a/protos/perfetto/common/gpu_counter_descriptor.proto b/protos/perfetto/common/gpu_counter_descriptor.proto
deleted file mode 100644
index c3c8eae..0000000
--- a/protos/perfetto/common/gpu_counter_descriptor.proto
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-// Description of GPU counters.
-// This message is sent by a GPU counter producer to specify the counters
-// available in the hardware.
-message GpuCounterDescriptor {
-  message GpuCounterSpec {
-    optional uint32 counter_id = 1;
-    optional string name = 2;
-    optional string description = 3;
-    reserved 4;  // MeasureUnit unit (deprecated)
-    oneof peak_value {
-      int64 int_peak_value = 5;
-      double double_peak_value = 6;
-    }
-    repeated MeasureUnit numerator_units = 7;
-    repeated MeasureUnit denominator_units = 8;
-    optional bool select_by_default = 9;
-  }
-  repeated GpuCounterSpec specs = 1;
-
-  // Allow producer to group counters into block to represent counter islands.
-  // A capacity may be specified to indicate the number of counters that can be
-  // enable simultaneously in that block.
-  message GpuCounterBlock {
-    // required. Unique ID for the counter group.
-    optional uint32 block_id = 1;
-    // optional. Number of counters supported by the block. No limit if unset.
-    optional uint32 block_capacity = 2;
-    // optional. Name of block.
-    optional string name = 3;
-    // optional. Description for the block.
-    optional string description = 4;
-    // list of counters that are part of the block.
-    repeated uint32 counter_ids = 5;
-  }
-  repeated GpuCounterBlock blocks = 2;
-
-  // optional.  Minimum sampling period supported by the producer in
-  // nanoseconds.
-  optional uint64 min_sampling_period_ns = 3;
-
-  // optional.  Maximum sampling period supported by the producer in
-  // nanoseconds.
-  optional uint64 max_sampling_period_ns = 4;
-
-  // optional.  The producer supports counter sampling by instrumenting the
-  // command buffer.
-  optional bool supports_instrumented_sampling = 5;
-
-  // next id: 41
-  enum MeasureUnit {
-    NONE = 0;
-
-    BIT = 1;
-    KILOBIT = 2;
-    MEGABIT = 3;
-    GIGABIT = 4;
-    TERABIT = 5;
-    PETABIT = 6;
-
-    BYTE = 7;
-    KILOBYTE = 8;
-    MEGABYTE = 9;
-    GIGABYTE = 10;
-    TERABYTE = 11;
-    PETABYTE = 12;
-
-    HERTZ = 13;
-    KILOHERTZ = 14;
-    MEGAHERTZ = 15;
-    GIGAHERTZ = 16;
-    TERAHERTZ = 17;
-    PETAHERTZ = 18;
-
-    NANOSECOND = 19;
-    MICROSECOND = 20;
-    MILLISECOND = 21;
-    SECOND = 22;
-    MINUTE = 23;
-    HOUR = 24;
-
-    VERTEX = 25;
-    PIXEL = 26;
-    TRIANGLE = 27;
-    PRIMITIVE = 38;
-    FRAGMENT = 39;
-
-    MILLIWATT = 28;
-    WATT = 29;
-    KILOWATT = 30;
-
-    JOULE = 31;
-    VOLT = 32;
-    AMPERE = 33;
-
-    CELSIUS = 34;
-    FAHRENHEIT = 35;
-    KELVIN = 36;
-
-    PERCENT = 37;
-
-    INSTRUCTION = 40;
-  }
-}
diff --git a/protos/perfetto/common/sys_stats_counters.proto b/protos/perfetto/common/sys_stats_counters.proto
index 91c4e80..2e482e7 100644
--- a/protos/perfetto/common/sys_stats_counters.proto
+++ b/protos/perfetto/common/sys_stats_counters.proto
@@ -155,7 +155,4 @@
   VMSTAT_UNEVICTABLE_PGS_MUNLOCKED = 90;
   VMSTAT_UNEVICTABLE_PGS_CLEARED = 91;
   VMSTAT_UNEVICTABLE_PGS_STRANDED = 92;
-  VMSTAT_NR_ZSPAGES = 93;
-  VMSTAT_NR_ION_HEAP = 94;
-  VMSTAT_NR_GPU_HEAP = 95;
 }
\ No newline at end of file
diff --git a/protos/perfetto/common/trace_stats.proto b/protos/perfetto/common/trace_stats.proto
index 9a661e1..9706087 100644
--- a/protos/perfetto/common/trace_stats.proto
+++ b/protos/perfetto/common/trace_stats.proto
@@ -21,11 +21,11 @@
 
 // Statistics for the internals of the tracing service.
 //
-// Next id: 11.
+// Next id: 10.
 message TraceStats {
   // From TraceBuffer::Stats.
   //
-  // Next id: 20.
+  // Next id: 19.
   message BufferStats {
     // Size of the circular buffer in bytes.
     optional uint64 buffer_size = 12;
@@ -110,15 +110,6 @@
     // the buffer. This is an indication of either a bug in the producer(s) or
     // malicious producer(s).
     optional uint64 abi_violations = 9;
-
-    // The fields below have been introduced in Android R.
-
-    // Num. of times the service detected packet loss on a trace writer
-    // sequence. This is usually caused by exhaustion of available chunks in the
-    // writer process's SMB. Note that this relies on the client's TraceWriter
-    // indicating this loss to the service -- packets lost for other reasons are
-    // not reflected in this stat.
-    optional uint64 trace_writer_packet_loss = 19;
   }
 
   // Stats for the TraceBuffer(s) of the current trace session.
@@ -155,8 +146,4 @@
   // Num. patches that were discarded by the service before attempting to apply
   // them to a buffer, e.g. because the producer specified an invalid buffer ID.
   optional uint64 patches_discarded = 9;
-
-  // Packets that failed validation of the TrustedPacket. If this is > 0, there
-  // is a bug in the producer.
-  optional uint64 invalid_packets = 10;
 }
diff --git a/protos/perfetto/common/tracing_service_state.proto b/protos/perfetto/common/tracing_service_state.proto
index 86723b3..dd8572c 100644
--- a/protos/perfetto/common/tracing_service_state.proto
+++ b/protos/perfetto/common/tracing_service_state.proto
@@ -19,7 +19,10 @@
 
 package perfetto.protos;
 
-import "protos/perfetto/common/data_source_descriptor.proto";
+import "perfetto/common/data_source_descriptor.proto";
+
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
 
 // Reports the state of the tracing service. Used to gather details about the
 // data sources connected.
@@ -36,7 +39,7 @@
   // regardless of the fact that they are being used or not.
   message DataSource {
     // Descriptor passed by the data source when calling RegisterDataSource().
-    optional DataSourceDescriptor ds_descriptor = 1;
+    optional DataSourceDescriptor descriptor = 1;
 
     // ID of the producer, as per Producer.id.
     optional int32 producer_id = 2;
diff --git a/protos/perfetto/common/track_event_descriptor.proto b/protos/perfetto/common/track_event_descriptor.proto
deleted file mode 100644
index 5536cc8..0000000
--- a/protos/perfetto/common/track_event_descriptor.proto
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-message TrackEventDescriptor {
-  repeated string available_categories = 1;
-}
diff --git a/protos/perfetto/config/BUILD.gn b/protos/perfetto/config/BUILD.gn
index 1ccbba4..5aec57c 100644
--- a/protos/perfetto/config/BUILD.gn
+++ b/protos/perfetto/config/BUILD.gn
@@ -14,37 +14,70 @@
 
 import("../../../gn/perfetto.gni")
 import("../../../gn/proto_library.gni")
+import("../../../gn/protozero_library.gni")
 
-# The core config protos, without the [lazy = true] imports pulled by
-# data_source_config.proto.
-
-perfetto_proto_library("@TYPE@") {
+proto_library("lite") {
   # Chromium shouldn't ignore the "android/" folder.
   set_sources_assignment_filter([])
-  deps = [
-    "../common:@TYPE@",
-    "android:@TYPE@",
-    "ftrace:@TYPE@",
-    "gpu:@TYPE@",
-    "inode_file:@TYPE@",
-    "power:@TYPE@",
-    "process_stats:@TYPE@",
-    "profiling:@TYPE@",
-    "sys_stats:@TYPE@",
-  ]
 
+  generate_python = false
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  if (!build_with_chromium) {
+    generate_descriptor =
+        "$perfetto_root_path/protos/perfetto/trace/config.descriptor"
+  }
+  deps = [
+    "../common:lite",
+  ]
   sources = [
+    "android/android_log_config.proto",
+    "android/packages_list_config.proto",
     "chrome/chrome_config.proto",
     "data_source_config.proto",
+    "ftrace/ftrace_config.proto",
+    "inode_file/inode_file_config.proto",
+    "power/android_power_config.proto",
+    "process_stats/process_stats_config.proto",
+    "profiling/heapprofd_config.proto",
+    "sys_stats/sys_stats_config.proto",
     "test_config.proto",
     "trace_config.proto",
   ]
 }
 
+protozero_library("zero") {
+  # Chromium shouldn't ignore the "android/" folder.
+  set_sources_assignment_filter([])
+
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  deps = [
+    "../common:zero",
+  ]
+  sources = [
+    "android/android_log_config.proto",
+    "android/packages_list_config.proto",
+    "chrome/chrome_config.proto",
+    "data_source_config.proto",
+    "ftrace/ftrace_config.proto",
+    "inode_file/inode_file_config.proto",
+    "power/android_power_config.proto",
+    "process_stats/process_stats_config.proto",
+    "profiling/heapprofd_config.proto",
+    "sys_stats/sys_stats_config.proto",
+    "test_config.proto",
+    "trace_config.proto",
+  ]
+  generator_plugin_options = "wrapper_namespace=pbzero"
+}
+
 # This target is not used in the tree and is built only to guarantee that the
 # autogenerated merged proto has a valid syntax.
-perfetto_proto_library("merged_config") {
-  proto_generators = [ "lite" ]
+proto_library("merged_config") {
+  generate_python = false
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
   sources = [
     "perfetto_config.proto",
   ]
diff --git a/protos/perfetto/config/android/BUILD.gn b/protos/perfetto/config/android/BUILD.gn
deleted file mode 100644
index 6e98fbb..0000000
--- a/protos/perfetto/config/android/BUILD.gn
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../../../gn/perfetto.gni")
-import("../../../../gn/proto_library.gni")
-
-perfetto_proto_library("@TYPE@") {
-  deps = [
-    "../../common:@TYPE@",
-  ]
-  sources = [
-    "android_log_config.proto",
-    "packages_list_config.proto",
-  ]
-}
diff --git a/protos/perfetto/config/android/android_log_config.proto b/protos/perfetto/config/android/android_log_config.proto
index 5a43f2d..f4496eb 100644
--- a/protos/perfetto/config/android/android_log_config.proto
+++ b/protos/perfetto/config/android/android_log_config.proto
@@ -18,7 +18,7 @@
 option optimize_for = LITE_RUNTIME;
 package perfetto.protos;
 
-import "protos/perfetto/common/android_log_constants.proto";
+import "perfetto/common/android_log_constants.proto";
 
 message AndroidLogConfig {
   repeated AndroidLogId log_ids = 1;
diff --git a/protos/perfetto/config/chrome/BUILD.gn b/protos/perfetto/config/chrome/BUILD.gn
deleted file mode 100644
index b893d06..0000000
--- a/protos/perfetto/config/chrome/BUILD.gn
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../../../gn/perfetto.gni")
-import("../../../../gn/proto_library.gni")
-
-perfetto_proto_library("@TYPE@") {
-  sources = [
-    "chrome_config.proto",
-  ]
-}
diff --git a/protos/perfetto/config/chrome/chrome_config.proto b/protos/perfetto/config/chrome/chrome_config.proto
index 3906f03..e5c92d6 100644
--- a/protos/perfetto/config/chrome/chrome_config.proto
+++ b/protos/perfetto/config/chrome/chrome_config.proto
@@ -19,6 +19,9 @@
 
 package perfetto.protos;
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 message ChromeConfig {
   optional string trace_config = 1;
 
diff --git a/protos/perfetto/config/data_source_config.proto b/protos/perfetto/config/data_source_config.proto
index 3a63cbf..526e8fb 100644
--- a/protos/perfetto/config/data_source_config.proto
+++ b/protos/perfetto/config/data_source_config.proto
@@ -19,18 +19,19 @@
 
 package perfetto.protos;
 
-import "protos/perfetto/config/android/android_log_config.proto";
-import "protos/perfetto/config/android/packages_list_config.proto";
-import "protos/perfetto/config/chrome/chrome_config.proto";
-import "protos/perfetto/config/ftrace/ftrace_config.proto";
-import "protos/perfetto/config/gpu/gpu_counter_config.proto";
-import "protos/perfetto/config/inode_file/inode_file_config.proto";
-import "protos/perfetto/config/power/android_power_config.proto";
-import "protos/perfetto/config/process_stats/process_stats_config.proto";
-import "protos/perfetto/config/profiling/heapprofd_config.proto";
-import "protos/perfetto/config/profiling/java_hprof_config.proto";
-import "protos/perfetto/config/sys_stats/sys_stats_config.proto";
-import "protos/perfetto/config/test_config.proto";
+import "perfetto/config/android/android_log_config.proto";
+import "perfetto/config/android/packages_list_config.proto";
+import "perfetto/config/chrome/chrome_config.proto";
+import "perfetto/config/ftrace/ftrace_config.proto";
+import "perfetto/config/inode_file/inode_file_config.proto";
+import "perfetto/config/power/android_power_config.proto";
+import "perfetto/config/process_stats/process_stats_config.proto";
+import "perfetto/config/profiling/heapprofd_config.proto";
+import "perfetto/config/sys_stats/sys_stats_config.proto";
+import "perfetto/config/test_config.proto";
+
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
 
 // The configuration that is passed to each data source when starting tracing.
 message DataSourceConfig {
@@ -51,10 +52,6 @@
   // DO NOT SET in consumer as this will be overridden by the service.
   optional uint32 trace_duration_ms = 3;
 
-  // Set by the service to indicate how long it waits after StopDataSource.
-  // DO NOT SET in consumer as this will be overridden by the service.
-  optional uint32 stop_timeout_ms = 7;
-
   // Set by the service to indicate whether this tracing session has extra
   // guardrails.
   // DO NOT SET in consumer as this will be overridden by the service.
@@ -70,27 +67,15 @@
   // Keeep the lower IDs (up to 99) for fields that are *not* specific to
   // data-sources and needs to be processed by the traced daemon.
 
-  // All data source config fields must be marked as [lazy=true]. This prevents
-  // the proto-to-cpp generator from recursing into those when generating the
-  // cpp classes and polluting tracing/core with data-source-specific classes.
-  // Instead they are treated as opaque strings containing raw proto bytes.
-
-  optional FtraceConfig ftrace_config = 100 [lazy = true];
-  optional InodeFileConfig inode_file_config = 102 [lazy = true];
-  optional ProcessStatsConfig process_stats_config = 103 [lazy = true];
-  optional SysStatsConfig sys_stats_config = 104 [lazy = true];
-  optional HeapprofdConfig heapprofd_config = 105 [lazy = true];
-  optional JavaHprofConfig java_hprof_config = 110 [lazy = true];
-  optional AndroidPowerConfig android_power_config = 106 [lazy = true];
-  optional AndroidLogConfig android_log_config = 107 [lazy = true];
-  optional GpuCounterConfig gpu_counter_config = 108 [lazy = true];
-  optional PackagesListConfig packages_list_config = 109 [lazy = true];
-
-  // Chrome is special as it doesn't use the perfetto IPC layer. We want to
-  // avoid proto serialization and de-serialization there because that would
-  // just add extra hops on top of the Mojo ser/des. Instead we auto-generate a
-  // C++ class for it so it can pass around plain C++ objets.
+  optional FtraceConfig ftrace_config = 100;
   optional ChromeConfig chrome_config = 101;
+  optional InodeFileConfig inode_file_config = 102;
+  optional ProcessStatsConfig process_stats_config = 103;
+  optional SysStatsConfig sys_stats_config = 104;
+  optional HeapprofdConfig heapprofd_config = 105;
+  optional AndroidPowerConfig android_power_config = 106;
+  optional AndroidLogConfig android_log_config = 107;
+  optional PackagesListConfig packages_list_config = 109;
 
   // This is a fallback mechanism to send a free-form text config to the
   // producer. In theory this should never be needed. All the code that
@@ -102,7 +87,6 @@
   optional string legacy_config = 1000;
 
   // This field is only used for testing.
-  optional TestConfig for_testing = 1001;
-
-  reserved 268435455;  // Was |for_testing|. Caused more problems then found.
+  optional TestConfig for_testing =
+      268435455;  // 2^28 - 1, max field id for protos supported by Java.
 }
diff --git a/protos/perfetto/config/ftrace/BUILD.gn b/protos/perfetto/config/ftrace/BUILD.gn
deleted file mode 100644
index 37ff9ca..0000000
--- a/protos/perfetto/config/ftrace/BUILD.gn
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../../../gn/perfetto.gni")
-import("../../../../gn/proto_library.gni")
-
-perfetto_proto_library("@TYPE@") {
-  sources = [
-    "ftrace_config.proto",
-  ]
-}
diff --git a/protos/perfetto/config/ftrace/ftrace_config.proto b/protos/perfetto/config/ftrace/ftrace_config.proto
index a612d89..5eed9ae 100644
--- a/protos/perfetto/config/ftrace/ftrace_config.proto
+++ b/protos/perfetto/config/ftrace/ftrace_config.proto
@@ -19,6 +19,9 @@
 
 package perfetto.protos;
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 message FtraceConfig {
   repeated string ftrace_events = 1;
   repeated string atrace_categories = 2;
@@ -26,14 +29,4 @@
   // *Per-CPU* buffer size.
   optional uint32 buffer_size_kb = 10;
   optional uint32 drain_period_ms = 11;
-
-  // Configuration for compact encoding of scheduler events. When enabled (and
-  // recording the relevant ftrace events), specific high-volume events are
-  // encoded in a denser format than normal.
-  message CompactSchedConfig {
-    // If true, and sched_switch or sched_waking ftrace events are enabled,
-    // record those events in the compact format.
-    optional bool enabled = 1;
-  }
-  optional CompactSchedConfig compact_sched = 12;
 }
diff --git a/protos/perfetto/config/gpu/BUILD.gn b/protos/perfetto/config/gpu/BUILD.gn
deleted file mode 100644
index 66f73c6..0000000
--- a/protos/perfetto/config/gpu/BUILD.gn
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../../../gn/proto_library.gni")
-
-perfetto_proto_library("@TYPE@") {
-  sources = [
-    "gpu_counter_config.proto",
-  ]
-}
diff --git a/protos/perfetto/config/gpu/gpu_counter_config.proto b/protos/perfetto/config/gpu/gpu_counter_config.proto
deleted file mode 100644
index 017195b..0000000
--- a/protos/perfetto/config/gpu/gpu_counter_config.proto
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-message GpuCounterConfig {
-  // Desired sampling interval for counters.
-  optional uint64 counter_period_ns = 1;
-
-  // List of counters to be sampled. Counter IDs correspond to the ones
-  // described in GpuCounterSpec in the data source descriptor.
-  repeated uint32 counter_ids = 2;
-
-  // Sample counters by instrumenting command buffers.
-  optional bool instrumented_sampling = 3;
-
-  // Fix gpu clock rate during trace session.
-  optional bool fix_gpu_clock = 4;
-}
diff --git a/protos/perfetto/config/inode_file/BUILD.gn b/protos/perfetto/config/inode_file/BUILD.gn
deleted file mode 100644
index d2cbdfd..0000000
--- a/protos/perfetto/config/inode_file/BUILD.gn
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../../../gn/proto_library.gni")
-
-perfetto_proto_library("@TYPE@") {
-  sources = [
-    "inode_file_config.proto",
-  ]
-}
diff --git a/protos/perfetto/config/inode_file/inode_file_config.proto b/protos/perfetto/config/inode_file/inode_file_config.proto
index d291cd1..47669bf 100644
--- a/protos/perfetto/config/inode_file/inode_file_config.proto
+++ b/protos/perfetto/config/inode_file/inode_file_config.proto
@@ -19,6 +19,9 @@
 
 package perfetto.protos;
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 message InodeFileConfig {
   message MountPointMappingEntry {
     optional string mountpoint = 1;
diff --git a/protos/perfetto/config/perfetto_config.proto b/protos/perfetto/config/perfetto_config.proto
index 1ba3c08..767c8cb 100644
--- a/protos/perfetto/config/perfetto_config.proto
+++ b/protos/perfetto/config/perfetto_config.proto
@@ -38,145 +38,6 @@
 
 // End of protos/perfetto/common/android_log_constants.proto
 
-// Begin of protos/perfetto/common/data_source_descriptor.proto
-
-// This message is sent from Producer(s) to the tracing Service when registering
-// to advertise their capabilities. It describes the structure of tracing
-// protos that will be produced by the data source and the supported filters.
-message DataSourceDescriptor {
-  optional string name = 1;  // e.g., "linux.ftrace", "chromium.tracing"
-
-  // When true the data source is expected to ack the stop request through the
-  // NotifyDataSourceStopped() IPC. This field has been introduced after
-  // Android P in Jul 2018 and is not supported on older versions.
-  optional bool will_notify_on_stop = 2;
-
-  // When true the data source is expected to ack the start request through the
-  // NotifyDataSourceStarted() IPC. This field has been introduced after
-  // Android P in March 2019 and is not supported on older versions.
-  optional bool will_notify_on_start = 3;
-
-  // If true, opt into receiving the ClearIncrementalState() IPC. This should be
-  // set if the data source writes packets that refer to previous trace
-  // contents, and knows how to stop referring to the already-emitted data.
-  optional bool handles_incremental_state_clear = 4;
-
-  // Optional specification about available GPU counters.
-  optional GpuCounterDescriptor gpu_counter_descriptor = 5 [lazy = true];
-
-  optional TrackEventDescriptor track_event_descriptor = 6 [lazy = true];
-}
-
-// End of protos/perfetto/common/data_source_descriptor.proto
-
-// Begin of protos/perfetto/common/gpu_counter_descriptor.proto
-
-// Description of GPU counters.
-// This message is sent by a GPU counter producer to specify the counters
-// available in the hardware.
-message GpuCounterDescriptor {
-  message GpuCounterSpec {
-    optional uint32 counter_id = 1;
-    optional string name = 2;
-    optional string description = 3;
-    reserved 4;  // MeasureUnit unit (deprecated)
-    oneof peak_value {
-      int64 int_peak_value = 5;
-      double double_peak_value = 6;
-    }
-    repeated MeasureUnit numerator_units = 7;
-    repeated MeasureUnit denominator_units = 8;
-    optional bool select_by_default = 9;
-  }
-  repeated GpuCounterSpec specs = 1;
-
-  // Allow producer to group counters into block to represent counter islands.
-  // A capacity may be specified to indicate the number of counters that can be
-  // enable simultaneously in that block.
-  message GpuCounterBlock {
-    // required. Unique ID for the counter group.
-    optional uint32 block_id = 1;
-    // optional. Number of counters supported by the block. No limit if unset.
-    optional uint32 block_capacity = 2;
-    // optional. Name of block.
-    optional string name = 3;
-    // optional. Description for the block.
-    optional string description = 4;
-    // list of counters that are part of the block.
-    repeated uint32 counter_ids = 5;
-  }
-  repeated GpuCounterBlock blocks = 2;
-
-  // optional.  Minimum sampling period supported by the producer in
-  // nanoseconds.
-  optional uint64 min_sampling_period_ns = 3;
-
-  // optional.  Maximum sampling period supported by the producer in
-  // nanoseconds.
-  optional uint64 max_sampling_period_ns = 4;
-
-  // optional.  The producer supports counter sampling by instrumenting the
-  // command buffer.
-  optional bool supports_instrumented_sampling = 5;
-
-  // next id: 41
-  enum MeasureUnit {
-    NONE = 0;
-
-    BIT = 1;
-    KILOBIT = 2;
-    MEGABIT = 3;
-    GIGABIT = 4;
-    TERABIT = 5;
-    PETABIT = 6;
-
-    BYTE = 7;
-    KILOBYTE = 8;
-    MEGABYTE = 9;
-    GIGABYTE = 10;
-    TERABYTE = 11;
-    PETABYTE = 12;
-
-    HERTZ = 13;
-    KILOHERTZ = 14;
-    MEGAHERTZ = 15;
-    GIGAHERTZ = 16;
-    TERAHERTZ = 17;
-    PETAHERTZ = 18;
-
-    NANOSECOND = 19;
-    MICROSECOND = 20;
-    MILLISECOND = 21;
-    SECOND = 22;
-    MINUTE = 23;
-    HOUR = 24;
-
-    VERTEX = 25;
-    PIXEL = 26;
-    TRIANGLE = 27;
-    PRIMITIVE = 38;
-    FRAGMENT = 39;
-
-    MILLIWATT = 28;
-    WATT = 29;
-    KILOWATT = 30;
-
-    JOULE = 31;
-    VOLT = 32;
-    AMPERE = 33;
-
-    CELSIUS = 34;
-    FAHRENHEIT = 35;
-    KELVIN = 36;
-
-    PERCENT = 37;
-
-    INSTRUCTION = 40;
-  }
-}
-
-// End of protos/perfetto/common/gpu_counter_descriptor.proto
-
 // Begin of protos/perfetto/common/sys_stats_counters.proto
 
 // When editing entries here remember also to update "sys_stats_counters.h" with
@@ -315,204 +176,9 @@
   VMSTAT_UNEVICTABLE_PGS_MUNLOCKED = 90;
   VMSTAT_UNEVICTABLE_PGS_CLEARED = 91;
   VMSTAT_UNEVICTABLE_PGS_STRANDED = 92;
-  VMSTAT_NR_ZSPAGES = 93;
-  VMSTAT_NR_ION_HEAP = 94;
-  VMSTAT_NR_GPU_HEAP = 95;
 }
 // End of protos/perfetto/common/sys_stats_counters.proto
 
-// Begin of protos/perfetto/common/trace_stats.proto
-
-// Statistics for the internals of the tracing service.
-//
-// Next id: 11.
-message TraceStats {
-  // From TraceBuffer::Stats.
-  //
-  // Next id: 20.
-  message BufferStats {
-    // Size of the circular buffer in bytes.
-    optional uint64 buffer_size = 12;
-
-    // Num. bytes written into the circular buffer, including chunk headers.
-    optional uint64 bytes_written = 1;
-
-    // Num. bytes overwritten before they have been read (i.e. loss of data).
-    optional uint64 bytes_overwritten = 13;
-
-    // Total size of chunks that were fully read from the circular buffer by the
-    // consumer. This may not be equal to |bytes_written| either in the middle
-    // of tracing, or if |chunks_overwritten| is non-zero. Note that this is the
-    // size of the chunks read from the buffer, including chunk headers, which
-    // will be different from the total size of packets returned to the
-    // consumer.
-    //
-    // The current utilization of the trace buffer (mid-tracing) can be obtained
-    // by subtracting |bytes_read| and |bytes_overwritten| from |bytes_written|,
-    // adding the difference of |padding_bytes_written| and
-    // |padding_bytes_cleared|, and comparing this sum to the |buffer_size|.
-    // Note that this represents the total size of buffered data in the buffer,
-    // yet this data may be spread non-contiguously through the buffer and may
-    // be overridden before the utilization reaches 100%.
-    optional uint64 bytes_read = 14;
-
-    // Num. bytes that were allocated as padding between chunks in the circular
-    // buffer.
-    optional uint64 padding_bytes_written = 15;
-
-    // Num. of padding bytes that were removed from the circular buffer when
-    // they were overwritten.
-    //
-    // The difference between |padding_bytes_written| and
-    // |padding_bytes_cleared| denotes the total size of padding currently
-    // present in the buffer.
-    optional uint64 padding_bytes_cleared = 16;
-
-    // Num. chunks (!= packets) written into the buffer.
-    optional uint64 chunks_written = 2;
-
-    // Num. chunks (!= packets) rewritten into the buffer. This means we rewrote
-    // the same chunk with additional packets appended to the end.
-    optional uint64 chunks_rewritten = 10;
-
-    // Num. chunks overwritten before they have been read (i.e. loss of data).
-    optional uint64 chunks_overwritten = 3;
-
-    // Num. chunks discarded (i.e. loss of data). Can be > 0 only when a buffer
-    // is configured with FillPolicy == DISCARD.
-    optional uint64 chunks_discarded = 18;
-
-    // Num. chunks (!= packets) that were fully read from the circular buffer by
-    // the consumer. This may not be equal to |chunks_written| either in the
-    // middle of tracing, or if |chunks_overwritten| is non-zero.
-    optional uint64 chunks_read = 17;
-
-    // Num. chunks that were committed out of order.
-    optional uint64 chunks_committed_out_of_order = 11;
-
-    // Num. times the ring buffer wrapped around.
-    optional uint64 write_wrap_count = 4;
-
-    // Num. out-of-band (OOB) patches that succeeded.
-    optional uint64 patches_succeeded = 5;
-
-    // Num. OOB patches that failed (e.g., the chunk to patch was gone).
-    optional uint64 patches_failed = 6;
-
-    // Num. readaheads (for large multi-chunk packet reads) that ended up in a
-    // successful packet read.
-    optional uint64 readaheads_succeeded = 7;
-
-    // Num. readaheads aborted because of missing chunks in the sequence stream.
-    // Note that a small number > 0 is totally expected: occasionally, when
-    // issuing a read, the very last packet in a sequence might be incomplete
-    // (because the producer is still writing it while we read). The read will
-    // stop at that point, for that sequence, increasing this counter.
-    optional uint64 readaheads_failed = 8;
-
-    // Num. of violations of the SharedMemoryABI found while writing or reading
-    // the buffer. This is an indication of either a bug in the producer(s) or
-    // malicious producer(s).
-    optional uint64 abi_violations = 9;
-
-    // The fields below have been introduced in Android R.
-
-    // Num. of times the service detected packet loss on a trace writer
-    // sequence. This is usually caused by exhaustion of available chunks in the
-    // writer process's SMB. Note that this relies on the client's TraceWriter
-    // indicating this loss to the service -- packets lost for other reasons are
-    // not reflected in this stat.
-    optional uint64 trace_writer_packet_loss = 19;
-  }
-
-  // Stats for the TraceBuffer(s) of the current trace session.
-  repeated BufferStats buffer_stats = 1;
-
-  // Num. producers connected (whether they are involved in the current tracing
-  // session or not).
-  optional uint32 producers_connected = 2;
-
-  // Num. producers ever seen for all trace sessions since startup (it's a good
-  // proxy for inferring num. producers crashed / killed).
-  optional uint64 producers_seen = 3;
-
-  // Num. data sources registered for all trace sessions.
-  optional uint32 data_sources_registered = 4;
-
-  // Num. data sources ever seen for all trace sessions since startup.
-  optional uint64 data_sources_seen = 5;
-
-  // Num. concurrently active tracing sessions.
-  optional uint32 tracing_sessions = 6;
-
-  // Num. buffers for all tracing session (not just the current one). This will
-  // be >= buffer_stats.size(), because the latter is only about the current
-  // session.
-  optional uint32 total_buffers = 7;
-
-  // The fields below have been introduced in Android Q.
-
-  // Num. chunks that were discarded by the service before attempting to commit
-  // them to a buffer, e.g. because the producer specified an invalid buffer ID.
-  optional uint64 chunks_discarded = 8;
-
-  // Num. patches that were discarded by the service before attempting to apply
-  // them to a buffer, e.g. because the producer specified an invalid buffer ID.
-  optional uint64 patches_discarded = 9;
-
-  // Packets that failed validation of the TrustedPacket. If this is > 0, there
-  // is a bug in the producer.
-  optional uint64 invalid_packets = 10;
-}
-
-// End of protos/perfetto/common/trace_stats.proto
-
-// Begin of protos/perfetto/common/tracing_service_state.proto
-
-// Reports the state of the tracing service. Used to gather details about the
-// data sources connected.
-// See ConsumerPort::QueryServiceState().
-message TracingServiceState {
-  // Describes a producer process.
-  message Producer {
-    optional int32 id = 1;     // Unique ID of the producer (monotonic counter).
-    optional string name = 2;  // Typically matches the process name.
-    optional int32 uid = 3;    // Unix uid of the remote process.
-  }
-
-  // Describes a data source registered by a producer. Data sources are listed
-  // regardless of the fact that they are being used or not.
-  message DataSource {
-    // Descriptor passed by the data source when calling RegisterDataSource().
-    optional DataSourceDescriptor ds_descriptor = 1;
-
-    // ID of the producer, as per Producer.id.
-    optional int32 producer_id = 2;
-  }
-
-  // Lists all the producers connected.
-  repeated Producer producers = 1;
-
-  // Lists the data sources available.
-  repeated DataSource data_sources = 2;
-
-  // Total number of tracing sessions.
-  optional int32 num_sessions = 3;
-
-  // Number of tracing sessions in the started state. Always <= num_sessions.
-  optional int32 num_sessions_started = 4;
-}
-
-// End of protos/perfetto/common/tracing_service_state.proto
-
-// Begin of protos/perfetto/common/track_event_descriptor.proto
-
-message TrackEventDescriptor {
-  repeated string available_categories = 1;
-}
-
-// End of protos/perfetto/common/track_event_descriptor.proto
-
 // Begin of protos/perfetto/config/android/android_log_config.proto
 
 message AndroidLogConfig {
@@ -532,6 +198,9 @@
 
 // Begin of protos/perfetto/config/chrome/chrome_config.proto
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 message ChromeConfig {
   optional string trace_config = 1;
 
@@ -544,6 +213,9 @@
 
 // Begin of protos/perfetto/config/data_source_config.proto
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 // The configuration that is passed to each data source when starting tracing.
 message DataSourceConfig {
   // Data source unique name, e.g., "linux.ftrace". This must match
@@ -563,10 +235,6 @@
   // DO NOT SET in consumer as this will be overridden by the service.
   optional uint32 trace_duration_ms = 3;
 
-  // Set by the service to indicate how long it waits after StopDataSource.
-  // DO NOT SET in consumer as this will be overridden by the service.
-  optional uint32 stop_timeout_ms = 7;
-
   // Set by the service to indicate whether this tracing session has extra
   // guardrails.
   // DO NOT SET in consumer as this will be overridden by the service.
@@ -582,27 +250,15 @@
   // Keeep the lower IDs (up to 99) for fields that are *not* specific to
   // data-sources and needs to be processed by the traced daemon.
 
-  // All data source config fields must be marked as [lazy=true]. This prevents
-  // the proto-to-cpp generator from recursing into those when generating the
-  // cpp classes and polluting tracing/core with data-source-specific classes.
-  // Instead they are treated as opaque strings containing raw proto bytes.
-
-  optional FtraceConfig ftrace_config = 100 [lazy = true];
-  optional InodeFileConfig inode_file_config = 102 [lazy = true];
-  optional ProcessStatsConfig process_stats_config = 103 [lazy = true];
-  optional SysStatsConfig sys_stats_config = 104 [lazy = true];
-  optional HeapprofdConfig heapprofd_config = 105 [lazy = true];
-  optional JavaHprofConfig java_hprof_config = 110 [lazy = true];
-  optional AndroidPowerConfig android_power_config = 106 [lazy = true];
-  optional AndroidLogConfig android_log_config = 107 [lazy = true];
-  optional GpuCounterConfig gpu_counter_config = 108 [lazy = true];
-  optional PackagesListConfig packages_list_config = 109 [lazy = true];
-
-  // Chrome is special as it doesn't use the perfetto IPC layer. We want to
-  // avoid proto serialization and de-serialization there because that would
-  // just add extra hops on top of the Mojo ser/des. Instead we auto-generate a
-  // C++ class for it so it can pass around plain C++ objets.
+  optional FtraceConfig ftrace_config = 100;
   optional ChromeConfig chrome_config = 101;
+  optional InodeFileConfig inode_file_config = 102;
+  optional ProcessStatsConfig process_stats_config = 103;
+  optional SysStatsConfig sys_stats_config = 104;
+  optional HeapprofdConfig heapprofd_config = 105;
+  optional AndroidPowerConfig android_power_config = 106;
+  optional AndroidLogConfig android_log_config = 107;
+  optional PackagesListConfig packages_list_config = 109;
 
   // This is a fallback mechanism to send a free-form text config to the
   // producer. In theory this should never be needed. All the code that
@@ -614,15 +270,17 @@
   optional string legacy_config = 1000;
 
   // This field is only used for testing.
-  optional TestConfig for_testing = 1001;
-
-  reserved 268435455;  // Was |for_testing|. Caused more problems then found.
+  optional TestConfig for_testing =
+      268435455;  // 2^28 - 1, max field id for protos supported by Java.
 }
 
 // End of protos/perfetto/config/data_source_config.proto
 
 // Begin of protos/perfetto/config/ftrace/ftrace_config.proto
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 message FtraceConfig {
   repeated string ftrace_events = 1;
   repeated string atrace_categories = 2;
@@ -630,22 +288,15 @@
   // *Per-CPU* buffer size.
   optional uint32 buffer_size_kb = 10;
   optional uint32 drain_period_ms = 11;
-
-  // Configuration for compact encoding of scheduler events. When enabled (and
-  // recording the relevant ftrace events), specific high-volume events are
-  // encoded in a denser format than normal.
-  message CompactSchedConfig {
-    // If true, and sched_switch or sched_waking ftrace events are enabled,
-    // record those events in the compact format.
-    optional bool enabled = 1;
-  }
-  optional CompactSchedConfig compact_sched = 12;
 }
 
 // End of protos/perfetto/config/ftrace/ftrace_config.proto
 
 // Begin of protos/perfetto/config/inode_file/inode_file_config.proto
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 message InodeFileConfig {
   message MountPointMappingEntry {
     optional string mountpoint = 1;
@@ -696,6 +347,9 @@
 
 // Begin of protos/perfetto/config/process_stats/process_stats_config.proto
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 message ProcessStatsConfig {
   enum Quirks {
     QUIRKS_UNSPECIFIED = 0;
@@ -740,6 +394,9 @@
 
 // Begin of protos/perfetto/config/sys_stats/sys_stats_config.proto
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 // This file defines the configuration for the Linux /proc poller data source,
 // which injects counters in the trace.
 // Counters that are needed in the trace must be explicitly listed in the
@@ -755,8 +412,7 @@
   // Cost: 0.3 ms [read] + 0.07 ms [parse + trace injection]
   optional uint32 meminfo_period_ms = 1;
 
-  // If empty all known counters are reported. Otherwise, only the counters
-  // specified below are reported.
+  // Only the counters specified below are reported.
   repeated MeminfoCounters meminfo_counters = 2;
 
   // Polls /proc/vmstat every X ms, if non-zero.
@@ -783,6 +439,9 @@
 
 // Begin of protos/perfetto/config/test_config.proto
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 // The configuration for a fake producer used in tests.
 message TestConfig {
   message DummyFields {
@@ -831,12 +490,15 @@
 
 // Begin of protos/perfetto/config/trace_config.proto
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos
+// to reflect changes in the corresponding C++ headers.
+
 // The overall config that is used when starting a new tracing session through
 // ProducerPort::StartTracing().
 // It contains the general config for the logging buffer(s) and the configs for
 // all the data source being enabled.
 //
-// Next id: 27.
+// Next id: 26.
 message TraceConfig {
   message BufferConfig {
     optional uint32 size_kb = 1;
@@ -986,10 +648,6 @@
   // Default 5s.
   optional uint32 flush_timeout_ms = 14;
 
-  // Wait for this long for producers to acknowledge stop requests.
-  // Default 5s.
-  optional uint32 data_source_stop_timeout_ms = 23;
-
   reserved 15;  // |disable_clock_snapshotting| moved.
 
   // Android-only. If set, sends an intent to the Traceur system app when the
@@ -1094,7 +752,7 @@
   enum CompressionType {
     COMPRESSION_TYPE_UNSPECIFIED = 0;
     COMPRESSION_TYPE_DEFLATE = 1;
-  }
+  };
   optional CompressionType compression_type = 24;
 
   // Android-only. Debug builds only. Not for general use. If set, saves a
@@ -1111,9 +769,6 @@
     optional bool skip_dropbox = 4;
   }
   optional IncidentReportConfig incident_report_config = 25;
-
-  // An identifier clients can use to tie this trace to other logging.
-  optional bytes trace_uuid = 26;
 }
 
 // End of protos/perfetto/config/trace_config.proto
@@ -1127,7 +782,7 @@
     optional uint32 dump_phase_ms = 5;
     // ms to wait between following dumps.
     optional uint32 dump_interval_ms = 6;
-  }
+  };
 
   // Set to 1 for perfect accuracy.
   // Otherwise, sample every sample_interval_bytes on average.
@@ -1164,6 +819,10 @@
   // E.g. /system to not emit symbols for any system libraries.
   repeated string skip_symbol_prefix = 7;
 
+  // Dump once at the end of the trace, emitting the heap dump at maximum
+  // memory usage.
+  // optional bool retain_max = 5;  // TODO(fmayer): Implement
+
   // Dump at a predefined interval.
   optional ContinuousDumpConfig continuous_dump_config = 6;
 
@@ -1181,88 +840,10 @@
   // trace. Use with caution as this will significantly slow down the target
   // process.
   optional bool block_client = 9;
-
-  // Do not profile processes from startup, only match already running
-  // processes.
-  //
-  // Can not be set at the same time as no_running.
-  optional bool no_startup = 10;
-
-  // Do not profile running processes. Only match processes on startup.
-  //
-  // Can not be set at the same time as no_startup.
-  optional bool no_running = 11;
-
-  // Gather information on how many bytes of allocations are on non-referenced
-  // pages. The way to use this generally is:
-  // 1. Start profile of app.
-  // 2. Start app.
-  // 3. Trigger a dump by sending SIGUSR1 to heapprofd.
-  // 4. Do operations.
-  // 5. End profile.
-  //
-  // You can then find the allocations that were not used for the operations you
-  // did in step 4.
-  optional bool idle_allocations = 12;
-
-  // Cause heapprofd to emit a single dump at the end, showing the memory usage
-  // at the point in time when the sampled heap usage of the process was at its
-  // maximum. This causes ProfilePacket.HeapSample.self_max to be set, and
-  // self_allocated and self_freed to not be set.
-  optional bool dump_at_max = 13;
 }
 
 // End of protos/perfetto/config/profiling/heapprofd_config.proto
 
-// Begin of protos/perfetto/config/profiling/java_hprof_config.proto
-
-// Configuration for go/heapprofd.
-message JavaHprofConfig {
-  // If dump_interval_ms != 0, the following configuration is used.
-  message ContinuousDumpConfig {
-    // ms to wait before first continuous dump.
-    // A dump is always created at the beginning of the trace.
-    optional uint32 dump_phase_ms = 1;
-    // ms to wait between following dumps.
-    optional uint32 dump_interval_ms = 2;
-  }
-
-  // This input is normalized in the following way: if it contains slashes,
-  // everything up to the last slash is discarded. If it contains "@",
-  // everything after the first @ is discared.
-  // E.g. /system/bin/surfaceflinger@1.0 normalizes to surfaceflinger.
-  // This transformation is also applied to the processes' command lines when
-  // matching.
-  repeated string process_cmdline = 1;
-
-  // For watermark based triggering or local debugging.
-  repeated uint64 pid = 2;
-
-  // Dump at a predefined interval.
-  optional ContinuousDumpConfig continuous_dump_config = 3;
-}
-
-// End of protos/perfetto/config/profiling/java_hprof_config.proto
-
-// Begin of protos/perfetto/config/gpu/gpu_counter_config.proto
-
-message GpuCounterConfig {
-  // Desired sampling interval for counters.
-  optional uint64 counter_period_ns = 1;
-
-  // List of counters to be sampled. Counter IDs correspond to the ones
-  // described in GpuCounterSpec in the data source descriptor.
-  repeated uint32 counter_ids = 2;
-
-  // Sample counters by instrumenting command buffers.
-  optional bool instrumented_sampling = 3;
-
-  // Fix gpu clock rate during trace session.
-  optional bool fix_gpu_clock = 4;
-}
-
-// End of protos/perfetto/config/gpu/gpu_counter_config.proto
-
 // Begin of protos/perfetto/config/android/packages_list_config.proto
 
 // Data source that lists details (such as version code) about packages on an
diff --git a/protos/perfetto/config/power/BUILD.gn b/protos/perfetto/config/power/BUILD.gn
deleted file mode 100644
index 0f74515..0000000
--- a/protos/perfetto/config/power/BUILD.gn
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../../../gn/proto_library.gni")
-
-perfetto_proto_library("@TYPE@") {
-  sources = [
-    "android_power_config.proto",
-  ]
-}
diff --git a/protos/perfetto/config/process_stats/BUILD.gn b/protos/perfetto/config/process_stats/BUILD.gn
deleted file mode 100644
index 7acfffe..0000000
--- a/protos/perfetto/config/process_stats/BUILD.gn
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../../../gn/proto_library.gni")
-
-perfetto_proto_library("@TYPE@") {
-  sources = [
-    "process_stats_config.proto",
-  ]
-}
diff --git a/protos/perfetto/config/process_stats/process_stats_config.proto b/protos/perfetto/config/process_stats/process_stats_config.proto
index 14cb4e9..14b964d 100644
--- a/protos/perfetto/config/process_stats/process_stats_config.proto
+++ b/protos/perfetto/config/process_stats/process_stats_config.proto
@@ -19,6 +19,9 @@
 
 package perfetto.protos;
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 message ProcessStatsConfig {
   enum Quirks {
     QUIRKS_UNSPECIFIED = 0;
diff --git a/protos/perfetto/config/profiling/BUILD.gn b/protos/perfetto/config/profiling/BUILD.gn
deleted file mode 100644
index 8482441..0000000
--- a/protos/perfetto/config/profiling/BUILD.gn
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../../../gn/proto_library.gni")
-
-perfetto_proto_library("@TYPE@") {
-  sources = [
-    "heapprofd_config.proto",
-    "java_hprof_config.proto",
-  ]
-}
diff --git a/protos/perfetto/config/profiling/heapprofd_config.proto b/protos/perfetto/config/profiling/heapprofd_config.proto
index 2d208d3..cc9085f 100644
--- a/protos/perfetto/config/profiling/heapprofd_config.proto
+++ b/protos/perfetto/config/profiling/heapprofd_config.proto
@@ -26,7 +26,7 @@
     optional uint32 dump_phase_ms = 5;
     // ms to wait between following dumps.
     optional uint32 dump_interval_ms = 6;
-  }
+  };
 
   // Set to 1 for perfect accuracy.
   // Otherwise, sample every sample_interval_bytes on average.
@@ -63,6 +63,10 @@
   // E.g. /system to not emit symbols for any system libraries.
   repeated string skip_symbol_prefix = 7;
 
+  // Dump once at the end of the trace, emitting the heap dump at maximum
+  // memory usage.
+  // optional bool retain_max = 5;  // TODO(fmayer): Implement
+
   // Dump at a predefined interval.
   optional ContinuousDumpConfig continuous_dump_config = 6;
 
@@ -80,33 +84,4 @@
   // trace. Use with caution as this will significantly slow down the target
   // process.
   optional bool block_client = 9;
-
-  // Do not profile processes from startup, only match already running
-  // processes.
-  //
-  // Can not be set at the same time as no_running.
-  optional bool no_startup = 10;
-
-  // Do not profile running processes. Only match processes on startup.
-  //
-  // Can not be set at the same time as no_startup.
-  optional bool no_running = 11;
-
-  // Gather information on how many bytes of allocations are on non-referenced
-  // pages. The way to use this generally is:
-  // 1. Start profile of app.
-  // 2. Start app.
-  // 3. Trigger a dump by sending SIGUSR1 to heapprofd.
-  // 4. Do operations.
-  // 5. End profile.
-  //
-  // You can then find the allocations that were not used for the operations you
-  // did in step 4.
-  optional bool idle_allocations = 12;
-
-  // Cause heapprofd to emit a single dump at the end, showing the memory usage
-  // at the point in time when the sampled heap usage of the process was at its
-  // maximum. This causes ProfilePacket.HeapSample.self_max to be set, and
-  // self_allocated and self_freed to not be set.
-  optional bool dump_at_max = 13;
 }
diff --git a/protos/perfetto/config/profiling/java_hprof_config.proto b/protos/perfetto/config/profiling/java_hprof_config.proto
deleted file mode 100644
index 07d0993..0000000
--- a/protos/perfetto/config/profiling/java_hprof_config.proto
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-// Configuration for go/heapprofd.
-message JavaHprofConfig {
-  // If dump_interval_ms != 0, the following configuration is used.
-  message ContinuousDumpConfig {
-    // ms to wait before first continuous dump.
-    // A dump is always created at the beginning of the trace.
-    optional uint32 dump_phase_ms = 1;
-    // ms to wait between following dumps.
-    optional uint32 dump_interval_ms = 2;
-  }
-
-  // This input is normalized in the following way: if it contains slashes,
-  // everything up to the last slash is discarded. If it contains "@",
-  // everything after the first @ is discared.
-  // E.g. /system/bin/surfaceflinger@1.0 normalizes to surfaceflinger.
-  // This transformation is also applied to the processes' command lines when
-  // matching.
-  repeated string process_cmdline = 1;
-
-  // For watermark based triggering or local debugging.
-  repeated uint64 pid = 2;
-
-  // Dump at a predefined interval.
-  optional ContinuousDumpConfig continuous_dump_config = 3;
-}
diff --git a/protos/perfetto/config/sys_stats/BUILD.gn b/protos/perfetto/config/sys_stats/BUILD.gn
deleted file mode 100644
index 634dd7e..0000000
--- a/protos/perfetto/config/sys_stats/BUILD.gn
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../../../gn/proto_library.gni")
-
-perfetto_proto_library("@TYPE@") {
-  deps = [
-    "../../common:@TYPE@",
-  ]
-  sources = [
-    "sys_stats_config.proto",
-  ]
-}
diff --git a/protos/perfetto/config/sys_stats/sys_stats_config.proto b/protos/perfetto/config/sys_stats/sys_stats_config.proto
index 7eafa3e..a773c3e 100644
--- a/protos/perfetto/config/sys_stats/sys_stats_config.proto
+++ b/protos/perfetto/config/sys_stats/sys_stats_config.proto
@@ -19,7 +19,10 @@
 
 package perfetto.protos;
 
-import "protos/perfetto/common/sys_stats_counters.proto";
+import "perfetto/common/sys_stats_counters.proto";
+
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
 
 // This file defines the configuration for the Linux /proc poller data source,
 // which injects counters in the trace.
@@ -36,8 +39,7 @@
   // Cost: 0.3 ms [read] + 0.07 ms [parse + trace injection]
   optional uint32 meminfo_period_ms = 1;
 
-  // If empty all known counters are reported. Otherwise, only the counters
-  // specified below are reported.
+  // Only the counters specified below are reported.
   repeated MeminfoCounters meminfo_counters = 2;
 
   // Polls /proc/vmstat every X ms, if non-zero.
diff --git a/protos/perfetto/config/test_config.proto b/protos/perfetto/config/test_config.proto
index c22a7e9..b50012e 100644
--- a/protos/perfetto/config/test_config.proto
+++ b/protos/perfetto/config/test_config.proto
@@ -19,6 +19,9 @@
 
 package perfetto.protos;
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 // The configuration for a fake producer used in tests.
 message TestConfig {
   message DummyFields {
diff --git a/protos/perfetto/config/trace_config.proto b/protos/perfetto/config/trace_config.proto
index 364fea7..88b1b44 100644
--- a/protos/perfetto/config/trace_config.proto
+++ b/protos/perfetto/config/trace_config.proto
@@ -17,16 +17,19 @@
 syntax = "proto2";
 option optimize_for = LITE_RUNTIME;
 
-import "protos/perfetto/config/data_source_config.proto";
+import "perfetto/config/data_source_config.proto";
 
 package perfetto.protos;
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos
+// to reflect changes in the corresponding C++ headers.
+
 // The overall config that is used when starting a new tracing session through
 // ProducerPort::StartTracing().
 // It contains the general config for the logging buffer(s) and the configs for
 // all the data source being enabled.
 //
-// Next id: 27.
+// Next id: 26.
 message TraceConfig {
   message BufferConfig {
     optional uint32 size_kb = 1;
@@ -176,10 +179,6 @@
   // Default 5s.
   optional uint32 flush_timeout_ms = 14;
 
-  // Wait for this long for producers to acknowledge stop requests.
-  // Default 5s.
-  optional uint32 data_source_stop_timeout_ms = 23;
-
   reserved 15;  // |disable_clock_snapshotting| moved.
 
   // Android-only. If set, sends an intent to the Traceur system app when the
@@ -284,7 +283,7 @@
   enum CompressionType {
     COMPRESSION_TYPE_UNSPECIFIED = 0;
     COMPRESSION_TYPE_DEFLATE = 1;
-  }
+  };
   optional CompressionType compression_type = 24;
 
   // Android-only. Debug builds only. Not for general use. If set, saves a
@@ -301,7 +300,4 @@
     optional bool skip_dropbox = 4;
   }
   optional IncidentReportConfig incident_report_config = 25;
-
-  // An identifier clients can use to tie this trace to other logging.
-  optional bytes trace_uuid = 26;
 }
diff --git a/protos/perfetto/ipc/BUILD.gn b/protos/perfetto/ipc/BUILD.gn
index 48f54a1..cd78bc1 100644
--- a/protos/perfetto/ipc/BUILD.gn
+++ b/protos/perfetto/ipc/BUILD.gn
@@ -12,9 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../gn/ipc_library.gni")
 import("../../../gn/perfetto.gni")
-import("../../../gn/proto_library.gni")
+import("../../../gn/ipc_library.gni")
 
 # IPC service definitions.
 ipc_library("ipc") {
@@ -22,17 +21,10 @@
     "../common:lite",
     "../config:lite",
   ]
-  proto_in_dir = perfetto_root_path
-  proto_out_dir = perfetto_root_path
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
   sources = [
     "consumer_port.proto",
     "producer_port.proto",
   ]
 }
-
-perfetto_proto_library("wire_protocol") {
-  proto_generators = [ "lite" ]
-  sources = [
-    "wire_protocol.proto",
-  ]
-}
diff --git a/protos/perfetto/ipc/consumer_port.proto b/protos/perfetto/ipc/consumer_port.proto
index 26854e8..595c53b 100644
--- a/protos/perfetto/ipc/consumer_port.proto
+++ b/protos/perfetto/ipc/consumer_port.proto
@@ -17,10 +17,10 @@
 syntax = "proto2";
 option optimize_for = LITE_RUNTIME;
 
-import "protos/perfetto/common/observable_events.proto";
-import "protos/perfetto/common/tracing_service_state.proto";
-import "protos/perfetto/common/trace_stats.proto";
-import "protos/perfetto/config/trace_config.proto";
+import "perfetto/common/observable_events.proto";
+import "perfetto/common/tracing_service_state.proto";
+import "perfetto/common/trace_stats.proto";
+import "perfetto/config/trace_config.proto";
 
 package perfetto.protos;
 
diff --git a/protos/perfetto/ipc/producer_port.proto b/protos/perfetto/ipc/producer_port.proto
index ebd8b98..465022b 100644
--- a/protos/perfetto/ipc/producer_port.proto
+++ b/protos/perfetto/ipc/producer_port.proto
@@ -17,9 +17,9 @@
 syntax = "proto2";
 option optimize_for = LITE_RUNTIME;
 
-import "protos/perfetto/common/commit_data_request.proto";
-import "protos/perfetto/config/data_source_config.proto";
-import "protos/perfetto/common/data_source_descriptor.proto";
+import "perfetto/common/commit_data_request.proto";
+import "perfetto/config/data_source_config.proto";
+import "perfetto/common/data_source_descriptor.proto";
 
 package perfetto.protos;
 
@@ -69,7 +69,7 @@
       returns (NotifyDataSourceStartedResponse) {}
 
   // Sent by the client in response to a StopDataSource message, when a data
-  // source is successfully stopped. This is expected only for data sources that
+  // source is succesfully stopped. This is expected only for data sources that
   // set the DataSourceDescriptor.will_notify_on_stop flag when registering.
   rpc NotifyDataSourceStopped(NotifyDataSourceStoppedRequest)
       returns (NotifyDataSourceStoppedResponse) {}
@@ -83,12 +83,9 @@
 
 // Arguments for rpc InitializeConnection().
 message InitializeConnectionRequest {
-  // Optional. Provides a hint to the tracing service about the suggested size
-  // of the shared memory buffer pages. The service is not required to respect
-  // this if it has already another value in the configuration or if the hint
-  // is unreasonably large. Must be an integer multiple of 4096. See tradeoff
-  // considerations in shared_memory_abi.h.
-  optional uint32 shared_memory_page_size_hint_bytes = 1;
+  // Defines the granularity of the tracing pages. Must be an integer multiple
+  // of 4096. See tradeoff considerations in shared_memory_abi.h.
+  optional uint32 shared_buffer_page_size_bytes = 1;
 
   // Optional. Provides a hint to the tracing service about the suggested size
   // of the shared memory buffer. The service is not required to respect this
@@ -114,17 +111,6 @@
 
   // If provided, overrides the service's SMB scraping setting for the producer.
   optional ProducerSMBScrapingMode smb_scraping_mode = 4;
-
-  enum ProducerBuildFlags {
-    BUILD_FLAGS_UNSPECIFIED = 0;
-    BUILD_FLAGS_DCHECKS_ON = 1;
-    BUILD_FLAGS_DCHECKS_OFF = 2;
-  }
-
-  // If provided, reports the build flags of the producer. It's used merely for
-  // error reporting, to print a log message when a producer connects to a
-  // service that has mismatching build flags.
-  optional ProducerBuildFlags build_flags = 5;
 }
 
 message InitializeConnectionResponse {
@@ -175,7 +161,8 @@
 
 // Arguments for rpc CommitData().
 // See commit_data_request.proto for CommitDataRequest. That has its own file
-// because it is used also as input to generate C++ classes (xxx.gen.h).
+// because it is used also as input to generate the C++ classes in tracing/core
+// via tools/gen_tracing_cpp_headers_from_protos.py.
 
 message CommitDataResponse {}
 
diff --git a/protos/perfetto/metrics/BUILD.gn b/protos/perfetto/metrics/BUILD.gn
index 1bb4387..7b8e505 100644
--- a/protos/perfetto/metrics/BUILD.gn
+++ b/protos/perfetto/metrics/BUILD.gn
@@ -14,22 +14,26 @@
 
 import("../../../gn/perfetto.gni")
 import("../../../gn/proto_library.gni")
+import("../../../gn/protozero_library.gni")
 
-perfetto_proto_library("@TYPE@") {
+common_sources = [ "metrics.proto" ]
+
+proto_library("lite") {
   deps = [
-    "android:@TYPE@",
+    "android:lite",
   ]
-  sources = [
-    "metrics.proto",
-  ]
+  generate_python = false
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  sources = common_sources
 }
 
-if (perfetto_build_standalone) {
-  perfetto_proto_library("descriptor") {
-    proto_generators = [ "descriptor" ]
-    generate_descriptor = "metrics.descriptor"
-    sources = [
-      "metrics.proto",
-    ]
-  }
+protozero_library("zero") {
+  deps = [
+    "android:zero",
+  ]
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  sources = common_sources
+  generator_plugin_options = "wrapper_namespace=pbzero"
 }
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index 41353b0..e47c896 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -12,22 +12,22 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import("../../../../gn/perfetto.gni")
 import("../../../../gn/proto_library.gni")
+import("../../../../gn/protozero_library.gni")
 
-perfetto_proto_library("@TYPE@") {
-  sources = [
-    "batt_metric.proto",
-    "cpu_metric.proto",
-    "heap_profile_callsites.proto",
-    "ion_metric.proto",
-    "java_heap_stats.proto",
-    "lmk_metric.proto",
-    "mem_metric.proto",
-    "mem_unagg_metric.proto",
-    "package_list.proto",
-    "powrails_metric.proto",
-    "process_growth.proto",
-    "startup_metric.proto",
-    "unsymbolized_frames.proto",
-  ]
+common_sources = [ "mem_metric.proto" ]
+
+proto_library("lite") {
+  generate_python = false
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  sources = common_sources
+}
+
+protozero_library("zero") {
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  sources = common_sources
+  generator_plugin_options = "wrapper_namespace=pbzero"
 }
diff --git a/protos/perfetto/metrics/android/OWNERS b/protos/perfetto/metrics/android/OWNERS
deleted file mode 100644
index 0bcdb4d..0000000
--- a/protos/perfetto/metrics/android/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-ilkos@google.com
diff --git a/protos/perfetto/metrics/android/batt_metric.proto b/protos/perfetto/metrics/android/batt_metric.proto
deleted file mode 100644
index 54e6a8b..0000000
--- a/protos/perfetto/metrics/android/batt_metric.proto
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-message AndroidBatteryMetric {
-  message BatteryCounters {
-    // Timestamp measured from boot time [ns].
-    optional int64 timestamp_ns = 1;
-    // Fields 2-5 are the same as in BatteryCounters proto in TracePacket.
-    optional double charge_counter_uah = 2;
-    optional float capacity_percent = 3;
-    optional double current_ua = 4;
-    optional double current_avg_ua = 5;
-  }
-
-   // Battery counters info for each ts of the trace. This should only be
-   // extracted for short traces.
-  repeated BatteryCounters battery_counters = 1;
-}
diff --git a/protos/perfetto/metrics/android/cpu_metric.proto b/protos/perfetto/metrics/android/cpu_metric.proto
deleted file mode 100644
index 172a6d8..0000000
--- a/protos/perfetto/metrics/android/cpu_metric.proto
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-message AndroidCpuMetric {
-  // CPU frequency information for one CPU and per thread.
-  message CpuFrequencyData {
-    optional uint32 id = 1;
-    optional int64 min_freq_khz = 2;
-    optional int64 max_freq_khz = 3;
-    // Average CPU frequency weighted by the time the CPU was running at
-    // each frequency.
-    optional int64 avg_freq_khz = 4;
-    // Total time the thread was running on this CPU, in nanoseconds.
-    optional int64 duration_ns = 5;
-  }
-
-  // CPU frequency information agggregated per CPU and thread.
-  message Thread {
-    optional string name = 1;
-    repeated CpuFrequencyData cpu = 2;
-    // CPU cycles normalized at 1Ghz frequency.
-    optional int64 normalized_cpu_cycles = 3;
-  }
-
-  // Threads (name and CPU frequency) per process.
-  message Process {
-    optional string name = 1;
-    repeated Thread threads = 2;
-    optional int64 normalized_cpu_cycles = 3;
-  }
-
-  // Process name and CPU frequency data aggregated by thread and cpu.
-  repeated Process process_info = 1;
-}
diff --git a/protos/perfetto/metrics/android/heap_profile_callsites.proto b/protos/perfetto/metrics/android/heap_profile_callsites.proto
deleted file mode 100644
index d19bba3..0000000
--- a/protos/perfetto/metrics/android/heap_profile_callsites.proto
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-message HeapProfileCallsites {
-  message Frame {
-    optional string name = 1;
-    optional string mapping_name = 2;
-  }
-
-  message Counters {
-    // Count of objects allocated
-    optional int64 total_count = 1;
-    // Count of bytes allocated
-    optional int64 total_bytes = 2;
-
-    // Count of allocated objects that were not freed
-    optional int64 delta_count = 3;
-    // Count of allocated bytes that were not freed
-    optional int64 delta_bytes = 4;
-  }
-
-  message Callsite {
-    // The hash unambiguously identifies a callsite in a heap profile (as a
-    // traversal from the root node). It is based on the symbol names (instead
-    // of the addresses).
-    optional int64 hash = 1;
-    optional int64 parent_hash = 2;
-
-    // Leaf frame of the callsite. Use parent_hash to traverse to parent nodes.
-    optional Frame frame = 3;
-
-    optional Counters self_allocs = 4;
-    optional Counters child_allocs = 5;
-  }
-
-  // Callsites per process instance.
-  // Next id: 6
-  message InstanceStats {
-    optional uint32 pid = 1;
-    optional string process_name = 2;
-    repeated Callsite callsites = 3;
-
-    // Bytes allocated via malloc but not freed.
-    optional int64 profile_delta_bytes = 4;
-    // Bytes allocated via malloc irrespective of whether they were freed.
-    optional int64 profile_total_bytes = 5;
-  }
-
-  repeated InstanceStats instance_stats = 1;
-}
diff --git a/protos/perfetto/metrics/android/ion_metric.proto b/protos/perfetto/metrics/android/ion_metric.proto
deleted file mode 100644
index b50041e..0000000
--- a/protos/perfetto/metrics/android/ion_metric.proto
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-// ion memory stats on Android.
-message AndroidIonMetric {
-  message Buffer {
-    optional string name = 1;
-    optional double avg_size_bytes = 2;
-    optional double min_size_bytes = 3;
-    optional double max_size_bytes = 4;
-  }
-
-  repeated Buffer buffer = 1;
-}
diff --git a/protos/perfetto/metrics/android/java_heap_stats.proto b/protos/perfetto/metrics/android/java_heap_stats.proto
deleted file mode 100644
index a5e1513..0000000
--- a/protos/perfetto/metrics/android/java_heap_stats.proto
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-message JavaHeapStats {
-  message Sample {
-    optional int64 ts = 1;
-    optional int64 heap_size = 2;
-    optional int64 reachable_heap_size = 3;
-  }
-
-  // Heap stats per process. One sample per dump (can be > 1 if continuous
-  // dump is enabled).
-  message InstanceStats {
-    optional uint32 upid = 1;
-    optional string process_name = 2;
-    repeated Sample samples = 3;
-  }
-
-  repeated InstanceStats instance_stats = 1;
-}
diff --git a/protos/perfetto/metrics/android/lmk_metric.proto b/protos/perfetto/metrics/android/lmk_metric.proto
deleted file mode 100644
index 5bb1881..0000000
--- a/protos/perfetto/metrics/android/lmk_metric.proto
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-// LMK stats on Android.
-message AndroidLmkMetric {
-  message ByOomScore {
-    optional int32 oom_score_adj = 1;
-    optional int32 count = 2;
-  }
-
-  // Total count of LMK events observed in the trace.
-  optional int32 total_count = 1;
-  repeated ByOomScore by_oom_score = 2;
-}
diff --git a/protos/perfetto/metrics/android/mem_metric.proto b/protos/perfetto/metrics/android/mem_metric.proto
index 0443c0d..c6c0466 100644
--- a/protos/perfetto/metrics/android/mem_metric.proto
+++ b/protos/perfetto/metrics/android/mem_metric.proto
@@ -21,15 +21,47 @@
 
 // Memory metrics on Android.
 message AndroidMemoryMetric {
-  message ProcessMetrics {
-    optional string process_name = 1;
-    optional ProcessMemoryCounters total_counters = 2;
-    repeated PriorityBreakdown priority_breakdown = 3;
+  // Next id: 6
+  message SystemMetrics {
+    reserved 3;
+
+    optional Counter anon_pages = 1;
+    optional Counter mmaped_pages = 2;
+    repeated NamedCounter ion_buffers = 4;
+    optional LowMemoryKills lmks = 5;
   }
 
-  message PriorityBreakdown {
-    optional string priority = 1;
-    optional ProcessMemoryCounters counters = 2;
+  message LowMemoryKills {
+    message LowMemoryKillBreakdown {
+      optional int32 oom_score_adj = 1;
+      optional int32 count = 2;
+    }
+
+    optional int32 total_count = 1;
+    repeated LowMemoryKillBreakdown breakdown = 2;
+  }
+
+  // Next id: 14
+  message ProcessMetrics {
+    reserved 2 to 9;
+
+    optional string process_name = 1;
+    optional ProcessMemoryCounters overall_counters = 10;
+
+    message ProcessMetricsBreakdown {
+      reserved 1;
+      optional string process_priority = 3;
+      optional ProcessMemoryCounters counters = 2;
+    }
+    repeated ProcessMetricsBreakdown breakdown = 11;
+
+    // Reserved for internal use.
+    extensions 12;
+
+    // A single process might have started one or more times in the duration of
+    // a trace. For each of these instances, measure the starting and ending
+    // anon+swap memory values.
+    repeated SpanGrowth anon_growth = 13;
   }
 
   message ProcessMemoryCounters {
@@ -37,9 +69,11 @@
     optional Counter file_rss = 2;
     optional Counter swap = 3;
     optional Counter anon_and_swap = 4;
+  }
 
-    // Available when ART trace events are available.
-    optional Counter java_heap = 5;
+  message NamedCounter {
+    optional string name = 1;
+    optional Counter counter = 2;
   }
 
   message Counter {
@@ -48,6 +82,22 @@
     optional double avg = 3;
   }
 
-  // Process metrics, grouped by process name
-  repeated ProcessMetrics process_metrics = 1;
+  message SpanGrowth {
+    // Initial value (at the beginning of the trace or process start)
+    optional double start_val = 1;
+
+    // End value (last sample for the pid).
+    optional double end_val = 2;
+
+    // Process duration (might or might not match the trace duration).
+    optional int64 duration = 3;
+
+    // (end_val - start_val) / start_val
+    optional double growth = 4;
+  }
+
+  optional SystemMetrics system_metrics = 4;
+
+  // Process-level metrics
+  repeated ProcessMetrics process_metrics = 3;
 }
diff --git a/protos/perfetto/metrics/android/mem_unagg_metric.proto b/protos/perfetto/metrics/android/mem_unagg_metric.proto
deleted file mode 100644
index e86893c..0000000
--- a/protos/perfetto/metrics/android/mem_unagg_metric.proto
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-// Unaggregated memory metrics on Android.
-message AndroidMemoryUnaggregatedMetric {
-  message ProcessValues {
-    optional string process_name = 1;
-    optional ProcessMemoryValues mem_values = 2;
-  }
-
-  message ProcessMemoryValues {
-    repeated Value anon_rss = 1;
-    repeated Value file_rss = 2;
-    repeated Value swap = 3;
-    repeated Value anon_and_swap = 4;
-  }
-
-  message Value {
-    optional int64 ts = 1;
-    optional int32 oom_score = 2;
-    optional double value = 3;
-  }
-
-  // Process metrics for every process instance in trace.
-  repeated ProcessValues process_values = 1;
-}
diff --git a/protos/perfetto/metrics/android/package_list.proto b/protos/perfetto/metrics/android/package_list.proto
deleted file mode 100644
index 3525294..0000000
--- a/protos/perfetto/metrics/android/package_list.proto
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-message AndroidPackageList {
-  message Package {
-    optional string package_name = 1;
-    optional int64 uid = 2;
-    optional int64 version_code = 3;
-  }
-
-  repeated Package packages = 1;
-}
diff --git a/protos/perfetto/metrics/android/powrails_metric.proto b/protos/perfetto/metrics/android/powrails_metric.proto
deleted file mode 100644
index df0823f..0000000
--- a/protos/perfetto/metrics/android/powrails_metric.proto
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-message AndroidPowerRails {
-  // Energy data per Power Rail at given ts.
-  message EnergyData {
-    // Time since device boot(CLOCK_BOTTOMTIME) in milli-seconds.
-    optional int64 timestamp_ms = 1;
-    // Accumulated energy since device boot in microwatt-seconds(uws).
-    optional double energy_uws = 2;
-  }
-
-  message PowerRails {
-    // Name of the rail.
-    optional string name = 1;
-    // Energy data for given rail and for all samples in the trace.
-    repeated EnergyData energy_data = 2;
-  }
-
-  // Energy data per Power Rail.
-  repeated PowerRails power_rails = 1;
-}
\ No newline at end of file
diff --git a/protos/perfetto/metrics/android/process_growth.proto b/protos/perfetto/metrics/android/process_growth.proto
deleted file mode 100644
index 50fcec5..0000000
--- a/protos/perfetto/metrics/android/process_growth.proto
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-message AndroidProcessGrowth {
-  // Next id: 7
-  message InstanceMetrics {
-    optional uint32 pid = 1;
-    optional string process_name = 2;
-
-    optional int64 anon_and_swap_start_value = 5;
-    optional int64 anon_and_swap_change_bytes = 3;
-
-    // Bytes allocated via malloc but not freed.
-    // Only applicable with a heap profile.
-    optional int64 malloc_memory_change_bytes = 4;
-    // Total bytes allocated via malloc. Only applicable with a heap profile.
-    optional int64 malloc_memory_total_allocated_bytes = 6;
-  }
-
-  // Process memory per process instance.
-  repeated InstanceMetrics instance_metrics = 1;
-}
diff --git a/protos/perfetto/metrics/android/startup_metric.proto b/protos/perfetto/metrics/android/startup_metric.proto
deleted file mode 100644
index 1310a38..0000000
--- a/protos/perfetto/metrics/android/startup_metric.proto
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-// Android app startup metrics.
-message AndroidStartupMetric {
-  // A simplified view of the task state durations for a thread
-  // and a span of time.
-  message TaskStateBreakdown {
-    optional int64 running_dur_ns = 1;
-    optional int64 runnable_dur_ns = 2;
-    optional int64 uninterruptible_sleep_dur_ns = 3;
-    optional int64 interruptible_sleep_dur_ns = 4;
-  }
-
-  message Slice { optional int64 dur_ns = 1; }
-
-  // Timing information spanning the intent received by the
-  // activity manager to the first frame drawn.
-  // All times and durations in nanoseconds (ns).
-  message ToFirstFrame {
-    optional int64 dur_ns = 1;
-    optional TaskStateBreakdown main_thread_by_task_state = 2;
-
-    // In this timespan, how many processes (apart from the main activity) were
-    // spawned.
-    optional uint32 other_processes_spawned_count = 3;
-
-    // Total time spent in activity manager between the initial intent
-    // and the end of the activity starter.
-    optional Slice time_activity_manager = 4;
-
-    // The following slices follow the typical steps post-fork.
-    optional Slice time_activity_thread_main = 5;
-    optional Slice time_bind_application = 6;
-    optional Slice time_activity_start = 7;
-    optional Slice time_activity_resume = 8;
-    optional Slice time_choreographer = 9;
-
-    // If we are starting a new process, record the duration from the
-    // intent being received to the time we call the zygote.
-    optional Slice time_before_start_process = 10;
-
-    // The actual duration of the process start (based on the zygote slice).
-    optional Slice time_during_start_process = 11;
-
-    // The ratio between the cpu time of the activity process
-    // to all other processes in the system.
-    optional double other_process_to_activity_cpu_ratio = 12;
-  }
-
-  // Next id: 7
-  message Startup {
-    // Random id uniquely identifying an app startup in this trace.
-    optional uint32 startup_id = 1;
-
-    // Name of the package launched
-    optional string package_name = 2;
-
-    // Name of the process launched
-    optional string process_name = 3;
-
-    // Did we ask the zygote for a new process
-    optional bool zygote_new_process = 4;
-
-    // Number of processes hosting the activity involved in the launch.
-    // This will usually be 1. If it is 0, it is indicative of a data / process
-    // error. If > 1, the process died during startup and the system respawned
-    // it.
-    optional uint32 activity_hosting_process_count = 6;
-
-    optional ToFirstFrame to_first_frame = 5;
-  }
-
-  repeated Startup startup = 1;
-}
diff --git a/protos/perfetto/metrics/android/unsymbolized_frames.proto b/protos/perfetto/metrics/android/unsymbolized_frames.proto
deleted file mode 100644
index 98d9d44..0000000
--- a/protos/perfetto/metrics/android/unsymbolized_frames.proto
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-message UnsymbolizedFrames {
-  message Frame {
-    optional string module = 1;
-    optional string build_id = 2;
-    optional int64 address = 3;
-  }
-
-  repeated Frame frames = 1;
-}
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index 508e830..234c899 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -19,88 +19,10 @@
 
 package perfetto.protos;
 
-import "protos/perfetto/metrics/android/batt_metric.proto";
-import "protos/perfetto/metrics/android/cpu_metric.proto";
-import "protos/perfetto/metrics/android/mem_metric.proto";
-import "protos/perfetto/metrics/android/mem_unagg_metric.proto";
-import "protos/perfetto/metrics/android/process_growth.proto";
-import "protos/perfetto/metrics/android/ion_metric.proto";
-import "protos/perfetto/metrics/android/lmk_metric.proto";
-import "protos/perfetto/metrics/android/powrails_metric.proto";
-import "protos/perfetto/metrics/android/startup_metric.proto";
-import "protos/perfetto/metrics/android/heap_profile_callsites.proto";
-import "protos/perfetto/metrics/android/package_list.proto";
-import "protos/perfetto/metrics/android/unsymbolized_frames.proto";
-import "protos/perfetto/metrics/android/java_heap_stats.proto";
-
-// Trace processor metadata (taken from the stats table schema and contents).
-// TODO: perhaps add the other columns once we have enum support
-message TraceMetadata {
-  message Entry {
-    optional string name = 1;
-    optional uint32 idx = 2;
-    optional int64 value = 3;
-  }
-
-  repeated Entry error_stats_entry = 1;
-  optional int64 trace_duration_ns = 2;
-  optional string trace_uuid = 3;
-}
+import "perfetto/metrics/android/mem_metric.proto";
 
 // Root message for all Perfetto-based metrics.
-//
-// Next id: 18
 message TraceMetrics {
-  reserved 4, 13, 14;
-
-  // Battery counters metric on Android.
-  optional AndroidBatteryMetric android_batt = 5;
-
-  // CPU usage per trace, process and thread.
-  optional AndroidCpuMetric android_cpu = 6;
-
   // Memory metrics on Android (owned by the Android Telemetry team).
   optional AndroidMemoryMetric android_mem = 1;
-
-  // Memory metrics on Android in unaggregated form. (owned by the Android
-  // Telemetry team).
-  // Note: this generates a lot of data so should not be requested unless it
-  // is clear that this data is necessary.
-  optional AndroidMemoryUnaggregatedMetric android_mem_unagg = 11;
-
-  // Package list.
-  optional AndroidPackageList android_package_list = 12;
-
-  // Per-process memory growth metrics.
-  optional AndroidProcessGrowth android_process_growth = 10;
-
-  // ion buffer memory metrics.
-  optional AndroidIonMetric android_ion = 9;
-
-  // Statistics about low memory kills.
-  optional AndroidLmkMetric android_lmk = 8;
-
-  // Power Rails metrics on Android.
-  optional AndroidPowerRails android_powrails = 7;
-
-  // Startup metrics on Android (owned by the Android Telemetry team).
-  optional AndroidStartupMetric android_startup = 2;
-
-  // Heap profiler callsite statistics.
-  optional HeapProfileCallsites heap_profile_callsites = 16;
-
-  // Trace metadata (applicable to all traces).
-  optional TraceMetadata trace_metadata = 3;
-
-  // Returns stack frames missing symbols.
-  optional UnsymbolizedFrames unsymbolized_frames = 15;
-
-  // If the trace contains a heap graph, output allocation statistics.
-  optional JavaHeapStats java_heap_stats = 17;
-
-  // Demo extensions.
-  extensions 450 to 499;
-
-  // Vendor extensions.
-  extensions 500 to 1000;
 }
diff --git a/protos/perfetto/trace/BUILD.gn b/protos/perfetto/trace/BUILD.gn
index ca76396..11186ae 100644
--- a/protos/perfetto/trace/BUILD.gn
+++ b/protos/perfetto/trace/BUILD.gn
@@ -14,122 +14,101 @@
 
 import("../../../gn/perfetto.gni")
 import("../../../gn/proto_library.gni")
+import("../../../gn/protozero_library.gni")
 
-# Trace protos are split logically into two groups:
-# 1. Full set of protos: :zero (for writers) and :lite (for readers).
-# 2. Minimal set: :minimal_zero, :minimal_lite. These are mainly for chrome, to
-#    avoid bloating binary size by pulling unnecessary protos.
-#
-# In practice, however, we need to split them in disjoint targets (minmal and
-# non-minimal) and then use a group() target for the full protos. This is
-# because build systems don't like two targets having genrules for the same
-# .proto files.
-
-# By default add new protos here.
-proto_sources_non_minimal = [
-  "trace_packet_defaults.proto",
-  "test_event.proto",
-  "trace_packet.proto",
-  "trace.proto",
-]
-
+# Common protos used by both the ":minimal_lite" target (for the service) and
+# the generic ":lite" target
 proto_sources_minimal = [
   "clock_snapshot.proto",
   "trigger.proto",
   "system_info.proto",
 ]
 
-# Used only for packet_stream_validator.cc (in the service).
 proto_sources_trusted = [ "trusted_packet.proto" ]
 
-# Most targets should either depend on :zero (writers) / :lite (readers)
-# or ":minimal_zero" / :minimal_lite (mostly for chrome).
+proto_sources = [
+  "test_event.proto",
+  "trace_packet.proto",
+  "trace.proto",
+]
 
-# The full set of protozero-generated sources.
-group("zero") {
-  public_deps = [
-    ":minimal_zero",
-    ":non_minimal_zero",
+# Protozero generated stubs, for writers.
+protozero_library("zero") {
+  deps = [
+    "../config:zero",
+    "android:zero",
+    "chrome:zero",
+    "filesystem:zero",
+    "ftrace:zero",
+    "interned_data:zero",
+    "power:zero",
+    "profiling:zero",
+    "ps:zero",
+    "sys_stats:zero",
+    "track_event:zero",
   ]
+  sources = proto_sources_minimal + proto_sources
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  generator_plugin_options = "wrapper_namespace=pbzero"
 }
 
-# The full set of libprotobuf-generated sources.
-group("lite") {
-  public_deps = [
+# Protobuf Lite stubs, for readers.
+proto_library("lite") {
+  generate_python = false
+  deps = [
     ":minimal_lite",
-    ":non_minimal_lite",
+    "../config:lite",
+    "android:lite",
+    "chrome:lite",
+    "filesystem:lite",
+    "ftrace:lite",
+    "interned_data:lite",
+    "power:lite",
+    "profiling:lite",
+    "ps:lite",
+    "sys_stats:lite",
+    "track_event:lite",
   ]
+  if (perfetto_build_standalone) {
+    generate_descriptor = "$perfetto_root_path/protos/trace/trace.descriptor"
+  }
+  sources = proto_sources
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
 }
 
-group("cpp") {
-  public_deps = [
-    ":minimal_cpp",
-    ":non_minimal_cpp",
-  ]
-}
-
-perfetto_proto_library("non_minimal_@TYPE@") {
+# Contains the subprotos of TracePacket that all targets need.
+proto_library("minimal_lite") {
+  generate_python = false
   deps = [
-    ":minimal_@TYPE@",
-    "../config:@TYPE@",
-    "android:@TYPE@",
-    "chrome:@TYPE@",
-    "filesystem:@TYPE@",
-    "ftrace:@TYPE@",
-    "gpu:@TYPE@",
-    "interned_data:@TYPE@",
-    "perfetto:@TYPE@",
-    "power:@TYPE@",
-    "profiling:@TYPE@",
-    "ps:@TYPE@",
-    "sys_stats:@TYPE@",
-    "track_event:@TYPE@",
-  ]
-  sources = proto_sources_non_minimal
-}
-
-perfetto_proto_library("minimal_@TYPE@") {
-  deps = [
-    "../config:@TYPE@",
+    "../config:lite",
   ]
   sources = proto_sources_minimal
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
 }
 
 # Used by the traced service for packet sanitization.
-perfetto_proto_library("trusted_@TYPE@") {
-  proto_generators = [ "lite" ]
+proto_library("trusted_lite") {
+  generate_python = false
   deps = [
-    ":minimal_@TYPE@",
-    "../common:@TYPE@",
-    "../config:@TYPE@",
+    ":minimal_lite",
+    "../common:lite",
+    "../config:lite",
   ]
   sources = proto_sources_trusted
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
 }
 
 # This target is not used in the tree and is built only to guarantee that the
 # autogenerated merged proto has a valid syntax.
-perfetto_proto_library("merged_trace") {
-  proto_generators = [ "lite" ]
+proto_library("merged_trace") {
+  generate_python = false
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
   sources = [
     "perfetto_trace.proto",
   ]
 }
-
-if (perfetto_build_standalone) {
-  perfetto_proto_library("descriptor") {
-    proto_generators = [ "descriptor" ]
-    generate_descriptor = "trace.descriptor"
-    sources = [
-      "trace.proto",
-    ]
-  }
-}
-
-# This target exports perfetto trace protos allowing both host and device
-# targets to implement custom parsers based on our protos.
-static_library("perfetto_trace_protos") {
-  complete_static_lib = true
-  deps = [
-    ":lite",
-  ]
-}
diff --git a/protos/perfetto/trace/android/BUILD.gn b/protos/perfetto/trace/android/BUILD.gn
index 3a8334b..72a3e3c 100644
--- a/protos/perfetto/trace/android/BUILD.gn
+++ b/protos/perfetto/trace/android/BUILD.gn
@@ -12,16 +12,31 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import("../../../../gn/perfetto.gni")
 import("../../../../gn/proto_library.gni")
+import("../../../../gn/protozero_library.gni")
 
-perfetto_proto_library("@TYPE@") {
+android_proto_names = [
+  "android_log.proto",
+  "packages_list.proto",
+]
+
+proto_library("lite") {
   deps = [
-    "../../common:@TYPE@",
+    "../../common:lite",
   ]
+  generate_python = false
+  sources = android_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+}
 
-  sources = [
-    "android_log.proto",
-    "graphics_frame_event.proto",
-    "packages_list.proto",
+protozero_library("zero") {
+  deps = [
+    "../../common:zero",
   ]
+  sources = android_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  generator_plugin_options = "wrapper_namespace=pbzero"
 }
diff --git a/protos/perfetto/trace/android/android_log.proto b/protos/perfetto/trace/android/android_log.proto
index 41edacc..aca98d5 100644
--- a/protos/perfetto/trace/android/android_log.proto
+++ b/protos/perfetto/trace/android/android_log.proto
@@ -18,7 +18,7 @@
 option optimize_for = LITE_RUNTIME;
 package perfetto.protos;
 
-import "protos/perfetto/common/android_log_constants.proto";
+import "perfetto/common/android_log_constants.proto";
 
 message AndroidLogPacket {
   message LogEvent {
diff --git a/protos/perfetto/trace/android/graphics_frame_event.proto b/protos/perfetto/trace/android/graphics_frame_event.proto
deleted file mode 100644
index 36cfa39..0000000
--- a/protos/perfetto/trace/android/graphics_frame_event.proto
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-package perfetto.protos;
-
-// Generated by Android's SurfaceFlinger.
-message GraphicsFrameEvent {
-  enum BufferEventType {
-    UNSPECIFIED = 0;
-    DEQUEUE = 1;
-    QUEUE = 2;
-    POST = 3;
-    ACQUIRE_FENCE = 4;
-    LATCH = 5;
-    HWC_COMPOSITION_QUEUED = 6;  // HWC will compose this buffer
-    FALLBACK_COMPOSITION = 7;    // renderEngine composition
-    PRESENT_FENCE = 8;
-    RELEASE_FENCE = 9;
-    MODIFY = 10;
-    DETACH = 11;
-    ATTACH = 12;
-    CANCEL = 13;
-  }
-
-  message BufferEvent {
-    optional uint32 frame_number = 1;
-    optional BufferEventType type = 2;
-    optional string layer_name = 3;
-    // If no duration is set, the event is an instant event.
-    optional uint64 duration_ns = 4;
-    // Unique buffer identifier.
-    optional uint32 buffer_id = 5;
-  }
-
-  optional BufferEvent buffer_event = 1;
-}
diff --git a/protos/perfetto/trace/chrome/BUILD.gn b/protos/perfetto/trace/chrome/BUILD.gn
index e49afe9..33297f0 100644
--- a/protos/perfetto/trace/chrome/BUILD.gn
+++ b/protos/perfetto/trace/chrome/BUILD.gn
@@ -12,28 +12,43 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../../gn/proto_library.gni")
+import("../../../../gn/perfetto.gni")
+import("../../../../gn/protozero_library.gni")
 
-perfetto_proto_library("@TYPE@") {
-  sources = [
-    "chrome_benchmark_metadata.proto",
-    "chrome_metadata.proto",
-    "chrome_trace_event.proto",
-  ]
+chrome_proto_names = [
+  "chrome_trace_event.proto",
+]
+minimal_chrome_proto_names = [ "chrome_trace_packet.proto" ]
+
+proto_library("lite") {
+  generate_python = false
+  sources = chrome_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
 }
 
-perfetto_proto_library("minimal_complete_lite") {
-  proto_generators = [ "lite" ]
+protozero_library("zero") {
   deps = [
-    ":@TYPE@",
-    "../:minimal_@TYPE@",
-    "../../common:@TYPE@",
-    "../../config:@TYPE@",
-    "../interned_data:@TYPE@",
-    "../profiling:@TYPE@",
-    "../track_event:@TYPE@",
+    "../interned_data:zero",
+    "../track_event:zero",
   ]
-  sources = [
-    "chrome_trace_packet.proto",
+  sources = chrome_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  generator_plugin_options = "wrapper_namespace=pbzero"
+}
+
+proto_library("minimal_complete_lite") {
+  generate_python = false
+  deps = [
+    ":lite",
+    "../:minimal_lite",
+    "../../common:lite",
+    "../../config:lite",
+    "../interned_data:lite",
+    "../track_event:lite",
   ]
+  sources = minimal_chrome_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
 }
diff --git a/protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto b/protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto
deleted file mode 100644
index 1500660..0000000
--- a/protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-package perfetto.protos;
-
-// This message is not intended to be written by the chrome on the device.
-// It's emitted on the host by the telemetry benchmark infrastructure (it's a
-// part of the trace that's written by the telemetry tracing agent).
-message ChromeBenchmarkMetadata {
-  // Time when the benchmark execution started (host unixtime in microseconds).
-  optional int64 benchmark_start_time_us = 1;
-
-  // Time when this particular story was run (host unixtime in microseconds).
-  optional int64 story_run_time_us = 2;
-
-  // Name of benchmark.
-  optional string benchmark_name = 3;
-
-  // Description of benchmark.
-  optional string benchmark_description = 4;
-
-  // Optional label.
-  optional string label = 5;
-
-  // Name of story.
-  optional string story_name = 6;
-
-  // List of story tags.
-  repeated string story_tags = 7;
-
-  // Index of the story run (>0 if the same story was run several times).
-  optional int32 story_run_index = 8;
-
-  // Whether this run failed.
-  optional bool had_failures = 9;
-}
diff --git a/protos/perfetto/trace/chrome/chrome_metadata.proto b/protos/perfetto/trace/chrome/chrome_metadata.proto
deleted file mode 100644
index 9e91c8f..0000000
--- a/protos/perfetto/trace/chrome/chrome_metadata.proto
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-// Metadata for chrome traces.
-message ChromeMetadataPacket {
-  optional BackgroundTracingMetadata background_tracing_metadata = 1;
-
-  // Version code of Chrome used by Android's Play Store. This field is only set
-  // on Android.
-  optional int32 chrome_version_code = 2;
-}
-
-// Metadata related to background tracing scenarios, states and triggers.
-message BackgroundTracingMetadata {
-  // Information about a trigger rule defined in the experiment config.
-  message TriggerRule {
-    enum TriggerType {
-      TRIGGER_UNSPECIFIED = 0;
-
-      // Traces are triggered by specific range of values of an UMA histogram.
-      MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE = 1;
-
-      // Traces are triggered by specific named events in chromium codebase,
-      // like "second-update-failure".
-      MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED = 2;
-    }
-    optional TriggerType trigger_type = 1;
-
-    // Configuration of histogram trigger.
-    message HistogramRule {
-      // UMA histogram name hash, same as HistogramEventProto.name_hash.
-      optional fixed64 histogram_name_hash = 1;
-
-      // Range of values of the histogram that activates trigger.
-      optional int64 histogram_min_trigger = 2;
-      optional int64 histogram_max_trigger = 3;
-    }
-    optional HistogramRule histogram_rule = 2;
-
-    // Configuration of named trigger.
-    message NamedRule {
-      enum EventType {
-        UNSPECIFIED = 0;
-        SESSION_RESTORE = 1;
-        NAVIGATION = 2;
-        STARTUP = 3;
-
-        TEST_RULE = 1000;
-      }
-      optional EventType event_type = 1;
-    }
-    optional NamedRule named_rule = 3;
-  }
-
-  // Specifies the rule that caused the trace to be uploaded.
-  optional TriggerRule triggered_rule = 1;
-
-  // List of all active triggers in current session, when trace was triggered.
-  repeated TriggerRule active_rules = 2;
-}
diff --git a/protos/perfetto/trace/chrome/chrome_trace_event.proto b/protos/perfetto/trace/chrome/chrome_trace_event.proto
index 62c0ad3..6f735f3 100644
--- a/protos/perfetto/trace/chrome/chrome_trace_event.proto
+++ b/protos/perfetto/trace/chrome/chrome_trace_event.proto
@@ -102,7 +102,7 @@
 message ChromeLegacyJsonTrace {
   enum TraceType {
     USER_TRACE = 0;
-    SYSTEM_TRACE = 1;  // Deprecated.
+    SYSTEM_TRACE = 1;
   }
   optional TraceType type = 1;
   optional string data = 2;
diff --git a/protos/perfetto/trace/chrome/chrome_trace_packet.proto b/protos/perfetto/trace/chrome/chrome_trace_packet.proto
index 956f07d..43b16e5 100644
--- a/protos/perfetto/trace/chrome/chrome_trace_packet.proto
+++ b/protos/perfetto/trace/chrome/chrome_trace_packet.proto
@@ -26,16 +26,14 @@
 syntax = "proto3";
 option optimize_for = LITE_RUNTIME;
 
-import "protos/perfetto/common/trace_stats.proto";
-import "protos/perfetto/config/trace_config.proto";
-import "protos/perfetto/trace/chrome/chrome_trace_event.proto";
-import "protos/perfetto/trace/clock_snapshot.proto";
-import "protos/perfetto/trace/interned_data/interned_data.proto";
-import "protos/perfetto/trace/profiling/profile_packet.proto";
-import "protos/perfetto/trace/profiling/profile_common.proto";
-import "protos/perfetto/trace/track_event/process_descriptor.proto";
-import "protos/perfetto/trace/track_event/thread_descriptor.proto";
-import "protos/perfetto/trace/track_event/track_event.proto";
+import "perfetto/common/trace_stats.proto";
+import "perfetto/config/trace_config.proto";
+import "perfetto/trace/chrome/chrome_trace_event.proto";
+import "perfetto/trace/clock_snapshot.proto";
+import "perfetto/trace/interned_data/interned_data.proto";
+import "perfetto/trace/track_event/process_descriptor.proto";
+import "perfetto/trace/track_event/thread_descriptor.proto";
+import "perfetto/trace/track_event/track_event.proto";
 
 package perfetto.protos;
 
@@ -51,8 +49,6 @@
   TrackEvent track_event = 11;
   ProcessDescriptor process_descriptor = 43;
   ThreadDescriptor thread_descriptor = 44;
-  StreamingProfilePacket streaming_profile_packet = 54;
-  ProfiledFrameSymbols profiled_frame_symbols = 55;
 
   // The original trace config.
   TraceConfig trace_config = 33;
diff --git a/protos/perfetto/trace/clock_snapshot.proto b/protos/perfetto/trace/clock_snapshot.proto
index 12ce1b6..7cf74ba 100644
--- a/protos/perfetto/trace/clock_snapshot.proto
+++ b/protos/perfetto/trace/clock_snapshot.proto
@@ -22,7 +22,7 @@
 // A snapshot of clock readings to allow for trace alignment.
 message ClockSnapshot {
   message Clock {
-    enum BuiltinClocks {
+    enum Type {
       UNKNOWN = 0;
       REALTIME = 1;
       REALTIME_COARSE = 2;
@@ -32,35 +32,9 @@
       BOOTTIME = 6;
       PROCESS_CPUTIME = 7;
       THREAD_CPUTIME = 8;
-      BUILTIN_CLOCK_MAX_ID = 63;
     }
-
-    // Clock IDs have the following semantic:
-    // [1, 63]:    Builtin types, see BuiltinClocks above.
-    // [64, 127]:  User-defined clocks. These clocks are sequence-scoped. They
-    //             are only valid within the same |trusted_packet_sequence_id|
-    //             (i.e. only for TracePacket(s) emitted by the same TraceWriter
-    //             that emitted the clock snapshot).
-    // [128, MAX]: Reserved for future use. The idea is to allow global clock
-    //             IDs and setting this ID to hash(full_clock_name) & ~127.
-    optional uint32 clock_id = 1;
-
-    // Unit is ns unless specified otherwise by the resolution_* fields below.
+    optional Type type = 1;
     optional uint64 timestamp = 2;
-
-    // TODO(eseckler): the fields below and sequence-scoped clock IDs are not
-    // supported yet by the trace processor.
-
-    // When true the timestamp should be interpreted as a delta from the last
-    // TracePacket's timestamp emitted by the same packet_sequence_id.
-    // The first packet timestamp after a ClockSnapshot is relative to the last
-    // ClockSnapshot seen on the packet sequence.
-    // optional bool is_incremental = 3;
-
-    // Allows to specify a custom unit different than the default (ns)
-    // for this clock domain. A multiplier of 1000 means that a timestamp = 3
-    // should be interpreted as 3000 ns = 3 us.
-    // optional uint64 unit_multiplier_ns = 4;
   }
   repeated Clock clocks = 1;
 }
diff --git a/protos/perfetto/trace/filesystem/BUILD.gn b/protos/perfetto/trace/filesystem/BUILD.gn
index 7d415e1..0937581 100644
--- a/protos/perfetto/trace/filesystem/BUILD.gn
+++ b/protos/perfetto/trace/filesystem/BUILD.gn
@@ -12,10 +12,21 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../../gn/proto_library.gni")
+import("../../../../gn/perfetto.gni")
+import("../../../../gn/protozero_library.gni")
 
-perfetto_proto_library("@TYPE@") {
-  sources = [
-    "inode_file_map.proto",
-  ]
+inode_proto_names = [ "inode_file_map.proto" ]
+
+proto_library("lite") {
+  generate_python = false
+  sources = inode_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+}
+
+protozero_library("zero") {
+  sources = inode_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  generator_plugin_options = "wrapper_namespace=pbzero"
 }
diff --git a/protos/perfetto/trace/ftrace/BUILD.gn b/protos/perfetto/trace/ftrace/BUILD.gn
index 535a119..8e24e04 100644
--- a/protos/perfetto/trace/ftrace/BUILD.gn
+++ b/protos/perfetto/trace/ftrace/BUILD.gn
@@ -13,19 +13,23 @@
 # limitations under the License.
 
 import("../../../../gn/perfetto.gni")
-import("../../../../gn/proto_library.gni")
+import("../../../../gn/protozero_library.gni")
 import("all_protos.gni")
 
-perfetto_proto_library("@TYPE@") {
+proto_library("lite") {
+  generate_python = false
+  if (perfetto_build_standalone) {
+    generate_descriptor =
+        "$perfetto_root_path/protos/perfetto/trace/ftrace.descriptor"
+  }
   sources = ftrace_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
 }
 
-if (perfetto_build_standalone) {
-  perfetto_proto_library("descriptor") {
-    proto_generators = [ "descriptor" ]
-    generate_descriptor = "ftrace.descriptor"
-    sources = [
-      "ftrace_event_bundle.proto",
-    ]
-  }
+protozero_library("zero") {
+  sources = ftrace_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  generator_plugin_options = "wrapper_namespace=pbzero"
 }
diff --git a/protos/perfetto/trace/ftrace/ftrace_event.proto b/protos/perfetto/trace/ftrace/ftrace_event.proto
index c953f36..6996d0a 100644
--- a/protos/perfetto/trace/ftrace/ftrace_event.proto
+++ b/protos/perfetto/trace/ftrace/ftrace_event.proto
@@ -5,35 +5,35 @@
 syntax = "proto2";
 option optimize_for = LITE_RUNTIME;
 
-import "protos/perfetto/trace/ftrace/binder.proto";
-import "protos/perfetto/trace/ftrace/block.proto";
-import "protos/perfetto/trace/ftrace/cgroup.proto";
-import "protos/perfetto/trace/ftrace/clk.proto";
-import "protos/perfetto/trace/ftrace/compaction.proto";
-import "protos/perfetto/trace/ftrace/ext4.proto";
-import "protos/perfetto/trace/ftrace/f2fs.proto";
-import "protos/perfetto/trace/ftrace/fence.proto";
-import "protos/perfetto/trace/ftrace/filemap.proto";
-import "protos/perfetto/trace/ftrace/ftrace.proto";
-import "protos/perfetto/trace/ftrace/i2c.proto";
-import "protos/perfetto/trace/ftrace/ipi.proto";
-import "protos/perfetto/trace/ftrace/irq.proto";
-import "protos/perfetto/trace/ftrace/kmem.proto";
-import "protos/perfetto/trace/ftrace/lowmemorykiller.proto";
-import "protos/perfetto/trace/ftrace/mdss.proto";
-import "protos/perfetto/trace/ftrace/mm_event.proto";
-import "protos/perfetto/trace/ftrace/oom.proto";
-import "protos/perfetto/trace/ftrace/power.proto";
-import "protos/perfetto/trace/ftrace/raw_syscalls.proto";
-import "protos/perfetto/trace/ftrace/regulator.proto";
-import "protos/perfetto/trace/ftrace/sched.proto";
-import "protos/perfetto/trace/ftrace/signal.proto";
-import "protos/perfetto/trace/ftrace/sync.proto";
-import "protos/perfetto/trace/ftrace/systrace.proto";
-import "protos/perfetto/trace/ftrace/task.proto";
-import "protos/perfetto/trace/ftrace/vmscan.proto";
-import "protos/perfetto/trace/ftrace/workqueue.proto";
-import "protos/perfetto/trace/ftrace/generic.proto";
+import "perfetto/trace/ftrace/binder.proto";
+import "perfetto/trace/ftrace/block.proto";
+import "perfetto/trace/ftrace/cgroup.proto";
+import "perfetto/trace/ftrace/clk.proto";
+import "perfetto/trace/ftrace/compaction.proto";
+import "perfetto/trace/ftrace/ext4.proto";
+import "perfetto/trace/ftrace/f2fs.proto";
+import "perfetto/trace/ftrace/fence.proto";
+import "perfetto/trace/ftrace/filemap.proto";
+import "perfetto/trace/ftrace/ftrace.proto";
+import "perfetto/trace/ftrace/i2c.proto";
+import "perfetto/trace/ftrace/ipi.proto";
+import "perfetto/trace/ftrace/irq.proto";
+import "perfetto/trace/ftrace/kmem.proto";
+import "perfetto/trace/ftrace/lowmemorykiller.proto";
+import "perfetto/trace/ftrace/mdss.proto";
+import "perfetto/trace/ftrace/mm_event.proto";
+import "perfetto/trace/ftrace/oom.proto";
+import "perfetto/trace/ftrace/power.proto";
+import "perfetto/trace/ftrace/raw_syscalls.proto";
+import "perfetto/trace/ftrace/regulator.proto";
+import "perfetto/trace/ftrace/sched.proto";
+import "perfetto/trace/ftrace/signal.proto";
+import "perfetto/trace/ftrace/sync.proto";
+import "perfetto/trace/ftrace/systrace.proto";
+import "perfetto/trace/ftrace/task.proto";
+import "perfetto/trace/ftrace/vmscan.proto";
+import "perfetto/trace/ftrace/workqueue.proto";
+import "perfetto/trace/ftrace/generic.proto";
 
 package perfetto.protos;
 
diff --git a/protos/perfetto/trace/ftrace/ftrace_event_bundle.proto b/protos/perfetto/trace/ftrace/ftrace_event_bundle.proto
index 1d69b1f..61020eb 100644
--- a/protos/perfetto/trace/ftrace/ftrace_event_bundle.proto
+++ b/protos/perfetto/trace/ftrace/ftrace_event_bundle.proto
@@ -17,50 +17,16 @@
 syntax = "proto2";
 option optimize_for = LITE_RUNTIME;
 
-import "protos/perfetto/trace/ftrace/ftrace_event.proto";
+import "perfetto/trace/ftrace/ftrace_event.proto";
 
 package perfetto.protos;
 
-// The result of tracing one or more ftrace data pages from a single per-cpu
-// kernel ring buffer. If collating multiple pages' worth of events, all of
-// them come from contiguous pages, with no kernel data loss in between.
 message FtraceEventBundle {
   optional uint32 cpu = 1;
   repeated FtraceEvent event = 2;
-  // Set to true if there was data loss between the last time we've read from
-  // the corresponding per-cpu kernel buffer, and the earliest event recorded
-  // in this bundle.
-  optional bool lost_events = 3;
-
-  // Optionally-enabled compact encoding of a batch of scheduling events. Only
-  // a subset of events & their fields is recorded.
-  // All fields (except comms) are stored in a structure-of-arrays form, one
-  // entry in each repeated field per event.
-  message CompactSched {
-    // Interned table of unique strings for this bundle.
-    repeated string intern_table = 5;
-
-    // Delta-encoded timestamps across all sched_switch events within this
-    // bundle. The first is absolute, each next one is relative to its
-    // predecessor.
-    repeated uint64 switch_timestamp = 1 [packed = true];
-    repeated int64 switch_prev_state = 2 [packed = true];
-    repeated int32 switch_next_pid = 3 [packed = true];
-    repeated int32 switch_next_prio = 4 [packed = true];
-    // One per event, index into |intern_table| corresponding to the
-    // next_comm field of the event.
-    repeated uint32 switch_next_comm_index = 6 [packed = true];
-
-    // Delta-encoded timestamps across all sched_waking events within this
-    // bundle. The first is absolute, each next one is relative to its
-    // predecessor.
-    repeated uint64 waking_timestamp = 7 [packed = true];
-    repeated int32 waking_pid = 8 [packed = true];
-    repeated int32 waking_target_cpu = 9 [packed = true];
-    repeated int32 waking_prio = 10 [packed = true];
-    // One per event, index into |intern_table| corresponding to the
-    // comm field of the event.
-    repeated uint32 waking_comm_index = 11 [packed = true];
-  }
-  optional CompactSched compact_sched = 4;
+  // Total of all overwrite fields from the headers of all kernel
+  // ftrace pages we parsed into this FtraceEventBundle. Zero if
+  // no overwriting occurred, a number larger than zero if some overwriting
+  // occurred.
+  optional uint32 overwrite_count = 3;
 }
diff --git a/protos/perfetto/trace/ftrace/test_bundle_wrapper.proto b/protos/perfetto/trace/ftrace/test_bundle_wrapper.proto
index c15c3f6..3e23312 100644
--- a/protos/perfetto/trace/ftrace/test_bundle_wrapper.proto
+++ b/protos/perfetto/trace/ftrace/test_bundle_wrapper.proto
@@ -17,7 +17,7 @@
 syntax = "proto2";
 option optimize_for = LITE_RUNTIME;
 package perfetto.protos;
-import "protos/perfetto/trace/ftrace/ftrace_event_bundle.proto";
+import "perfetto/trace/ftrace/ftrace_event_bundle.proto";
 
 // TODO(hjd): Move this to ftrace_reader/test/protos.
 message TestBundleWrapper {
diff --git a/protos/perfetto/trace/gpu/BUILD.gn b/protos/perfetto/trace/gpu/BUILD.gn
deleted file mode 100644
index 64b913a..0000000
--- a/protos/perfetto/trace/gpu/BUILD.gn
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../../../gn/proto_library.gni")
-
-perfetto_proto_library("@TYPE@") {
-  deps = [
-    "../../common:@TYPE@",
-  ]
-  sources = [
-    "gpu_counter_event.proto",
-    "gpu_log.proto",
-    "gpu_render_stage_event.proto",
-    "vulkan_memory_event.proto",
-  ]
-}
diff --git a/protos/perfetto/trace/gpu/gpu_counter_event.proto b/protos/perfetto/trace/gpu/gpu_counter_event.proto
deleted file mode 100644
index fe3a8f0..0000000
--- a/protos/perfetto/trace/gpu/gpu_counter_event.proto
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-import "protos/perfetto/common/gpu_counter_descriptor.proto";
-
-message GpuCounterEvent {
-  // The first trace packet of each session should include counter_spec.
-  optional GpuCounterDescriptor counter_descriptor = 1;
-
-  message GpuCounter {
-    // required. Identifier for counter.
-    optional uint32 counter_id = 1;
-    // required. Value of the counter.
-    oneof value {
-      int64 int_value = 2;
-      double double_value = 3;
-    }
-  }
-  repeated GpuCounter counters = 2;
-
-  // optional. Identifier for GPU in a multi-gpu device.
-  optional int32 gpu_id = 3;
-}
diff --git a/protos/perfetto/trace/gpu/gpu_log.proto b/protos/perfetto/trace/gpu/gpu_log.proto
deleted file mode 100644
index 1c39bc0..0000000
--- a/protos/perfetto/trace/gpu/gpu_log.proto
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-// Message for logging events GPU data producer.
-message GpuLog {
-  enum Severity {
-    LOG_SEVERITY_UNSPECIFIED = 0;
-    LOG_SEVERITY_VERBOSE = 1;
-    LOG_SEVERITY_DEBUG = 2;
-    LOG_SEVERITY_INFO = 3;
-    LOG_SEVERITY_WARNING = 4;
-    LOG_SEVERITY_ERROR = 5;
-  };
-  optional Severity severity = 1;
-
-  optional string tag = 2;
-
-  optional string log_message = 3;
-}
diff --git a/protos/perfetto/trace/gpu/gpu_render_stage_event.proto b/protos/perfetto/trace/gpu/gpu_render_stage_event.proto
deleted file mode 100644
index e719b2b..0000000
--- a/protos/perfetto/trace/gpu/gpu_render_stage_event.proto
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-// next id: 13
-message GpuRenderStageEvent {
-  // required. Unique ID for the event.
-  optional uint64 event_id = 1;
-
-  // optional. Duration of the event.  This should be in the same clock domain as the timestamp of
-  // the packet.  If unset, this is a single time point event.
-  optional uint64 duration = 2;
-
-  // required. ID to a hardware queue description in the specifications.
-  optional int32 hw_queue_id = 3;
-
-  // required. ID to a render stage description in the specifications.
-  optional int32 stage_id = 4;
-
-  // required. GL context/VK device.
-  optional uint64 context = 5;
-
-  // optional. The render target for this event.
-  optional uint64 render_target_handle = 8;
-
-  // optional. The Vulkan render pass handle.
-  optional uint64 render_pass_handle = 9;
-
-  // optional. The Vulkan command buffer handle.
-  optional uint64 command_buffer_handle = 12;
-
-  // optional. Submission ID generated by the UMD.
-  optional uint32 submission_id = 10;
-
-  // optional.  Additional data for the user. This may include attribs for
-  // the event like resource ids, shaders etc
-  message ExtraData {
-    optional string name = 1;
-    optional string value = 2;
-  }
-  repeated ExtraData extra_data = 6;
-
-  // The first trace packet of each session should include a Specifications
-  // to enumerate all IDs that will be used.
-  message Specifications {
-    message ContextSpec {
-      optional uint64 context = 1;
-      optional int32 pid = 2;
-    }
-    optional ContextSpec context_spec = 1;
-
-    message Description {
-      optional string name = 1;
-      optional string description = 2;
-    }
-
-    // Labels to categorize the hw Queue this event goes on.
-    repeated Description hw_queue = 2;
-
-    // Labels to categorize render stage(binning, render, compute etc).
-    repeated Description stage = 3;
-  }
-  optional Specifications specifications = 7;
-
-  // optional. Identifier for GPU in a multi-gpu device.
-  optional int32 gpu_id = 11;
-
-  // Extension for vendor's custom proto.
-  extensions 100;
-}
diff --git a/protos/perfetto/trace/gpu/vulkan_memory_event.proto b/protos/perfetto/trace/gpu/vulkan_memory_event.proto
deleted file mode 100644
index b524f5e..0000000
--- a/protos/perfetto/trace/gpu/vulkan_memory_event.proto
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-// All the information that cannot be sent within a VulkanMemoryEvent message,
-// are sent as annotations to the main memory event. One example is the
-// properties of the object that consumes the allocated memory, for example, a
-// buffer or an image.
-// key_iid and string_iid are both interned strings. Original string value is
-// stored in vulkan_memory_keys from
-// protos/perfetto/trace/interned_data/interned_data.proto.
-message VulkanMemoryEventAnnotation {
-  optional uint64 key_iid = 1;
-  oneof value {
-    int64 int_value = 2;
-    double double_value = 3;
-    uint64 string_iid = 4;
-  }
-}
-
-// Each VulkanMemoryEvent encompasses information regarding one signle function
-// call that results in reserving, binding or freeing host or GPU memory. There
-// is a special message type, ANNOTATIONS, which is used to communicate
-// information that are not directly related to a memory event, nonetheless are
-// essential to understand the memory usage. An example is the size and memory
-// types of the memory heaps.
-message VulkanMemoryEvent {
-  enum Source {
-    UNKNOWN_SOURCE = 0;
-    DEVICE = 1;
-    HOST = 2;
-    GPU_DEVICE_MEMORY = 3;
-    GPU_BUFFER = 4;
-    GPU_IMAGE = 5;
-  }
-
-  enum Type {
-    UNKNOWN_TYPE = 0;
-    CREATE = 1;         // alloc, create
-    DESTROY = 2;        // free, destroy (non-bound)
-    BIND = 3;           // bind buffer and image
-    DESTROY_BOUND = 4;  // destroy (bound)
-    ANNOTATIONS = 5;    // only annotations
-  }
-
-  optional Source source = 1;
-  optional Type type = 2;
-  optional int64 timestamp = 3;
-  optional uint32 pid = 4;
-  optional fixed64 device = 5;
-  optional fixed64 device_memory = 6;
-  optional uint32 heap = 7;
-  // Interned string. Original string value is stored in function_names from
-  // protos/perfetto/trace/interned_data/interned_data.proto.
-  optional uint64 caller_iid = 8;  // caller api, interned string
-  optional fixed64 object_handle = 9;
-  optional fixed64 memory_address = 10;
-  optional uint64 memory_size = 11;
-  // Extra related information, e.g., create configs, etc.
-  repeated VulkanMemoryEventAnnotation annotations = 12;
-}
diff --git a/protos/perfetto/trace/interned_data/BUILD.gn b/protos/perfetto/trace/interned_data/BUILD.gn
index dbda3ab..6b68d81 100644
--- a/protos/perfetto/trace/interned_data/BUILD.gn
+++ b/protos/perfetto/trace/interned_data/BUILD.gn
@@ -12,14 +12,28 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import("../../../../gn/perfetto.gni")
 import("../../../../gn/proto_library.gni")
+import("../../../../gn/protozero_library.gni")
 
-perfetto_proto_library("@TYPE@") {
-  sources = [
-    "interned_data.proto",
-  ]
+event_proto_names = [ "interned_data.proto" ]
+
+proto_library("lite") {
   deps = [
-    "../profiling:@TYPE@",
-    "../track_event:@TYPE@",
+    "../track_event:lite",
   ]
+  generate_python = false
+  sources = event_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+}
+
+protozero_library("zero") {
+  deps = [
+    "../track_event:zero",
+  ]
+  sources = event_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  generator_plugin_options = "wrapper_namespace=pbzero"
 }
diff --git a/protos/perfetto/trace/interned_data/interned_data.proto b/protos/perfetto/trace/interned_data/interned_data.proto
index 3cacef9..4120e81 100644
--- a/protos/perfetto/trace/interned_data/interned_data.proto
+++ b/protos/perfetto/trace/interned_data/interned_data.proto
@@ -17,11 +17,9 @@
 syntax = "proto2";
 option optimize_for = LITE_RUNTIME;
 
-import "protos/perfetto/trace/track_event/debug_annotation.proto";
-import "protos/perfetto/trace/track_event/log_message.proto";
-import "protos/perfetto/trace/track_event/track_event.proto";
-import "protos/perfetto/trace/track_event/source_location.proto";
-import "protos/perfetto/trace/profiling/profile_common.proto";
+import "perfetto/trace/track_event/debug_annotation.proto";
+import "perfetto/trace/track_event/task_execution.proto";
+import "perfetto/trace/track_event/track_event.proto";
 
 package perfetto.protos;
 
@@ -39,7 +37,7 @@
 // Because of the incremental build-up, the interning index will miss data when
 // TracePackets are lost, e.g. because a chunk was overridden in the central
 // ring buffer. To avoid invalidation of the whole trace in such a case, the
-// index is periodically reset (see SEQ_INCREMENTAL_STATE_CLEARED).
+// index is periodically reset (see |incremental_state_cleared| in TracePacket).
 // When packet loss occurs, the reader will only lose interning data up to the
 // next reset.
 // -----------------------------------------------------------------------------
@@ -51,12 +49,8 @@
 // refers to them (since the last reset of interning state). They may also be
 // emitted proactively in advance of referring to them in later packets.
 //
-// Next reserved id: 8 (up to 15).
-// Next id: 23.
+// Next id: 5.
 message InternedData {
-  // TODO(eseckler): Replace iid fields inside interned messages with
-  // map<iid, message> type fields in InternedData.
-
   // Each field's message type needs to specify an |iid| field, which is the ID
   // of the entry in the field's interning index. Each field constructs its own
   // index, thus interning IDs are scoped to the tracing session and field
@@ -65,31 +59,8 @@
   // within the same tracing session, even after a reset of the emitted
   // interning state.
   repeated EventCategory event_categories = 1;
-  repeated EventName event_names = 2;
+  repeated LegacyEventName legacy_event_names = 2;
   repeated DebugAnnotationName debug_annotation_names = 3;
   repeated SourceLocation source_locations = 4;
-  repeated LogMessageBody log_message_body = 20;
-
   // Note: field IDs up to 15 should be used for frequent data only.
-
-  // Build IDs of exectuable files.
-  repeated InternedString build_ids = 16;
-  // Paths to executable files.
-  repeated InternedString mapping_paths = 17;
-  // Paths to source files.
-  repeated InternedString source_paths = 18;
-  // Names of functions used in frames below.
-  repeated InternedString function_names = 5;
-  // Symbols that were added to this trace after the fact.
-  repeated ProfiledFrameSymbols profiled_frame_symbols = 21;
-
-  // Executable files mapped into processes.
-  repeated Mapping mappings = 19;
-  // Frames of callstacks of a program.
-  repeated Frame frames = 6;
-  // A callstack of a program.
-  repeated Callstack callstacks = 7;
-
-  // Additional Vulkan information sent in a VulkanMemoryEvent message
-  repeated InternedString vulkan_memory_keys = 22;
 }
diff --git a/protos/perfetto/trace/perfetto/BUILD.gn b/protos/perfetto/trace/perfetto/BUILD.gn
deleted file mode 100644
index 5fc30a4..0000000
--- a/protos/perfetto/trace/perfetto/BUILD.gn
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../../../gn/proto_library.gni")
-
-perfetto_proto_library("@TYPE@") {
-  sources = [
-    "perfetto_metatrace.proto",
-  ]
-}
diff --git a/protos/perfetto/trace/perfetto/perfetto_metatrace.proto b/protos/perfetto/trace/perfetto/perfetto_metatrace.proto
deleted file mode 100644
index 63ceacb..0000000
--- a/protos/perfetto/trace/perfetto/perfetto_metatrace.proto
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-// Used to trace the execution of perfetto itself.
-message PerfettoMetatrace {
-  // See base/metatrace_events.h for definitions.
-  oneof record_type {
-    uint32 event_id = 1;
-    uint32 counter_id = 2;
-  }
-
-  // Only when using |event_id|.
-  optional uint32 event_duration_ns = 3;
-
-  // Only when using |counter_id|.
-  optional int32 counter_value = 4;
-
-  // ID of the thread that emitted the event.
-  optional uint32 thread_id = 5;
-
-  // If true the meta-tracing ring buffer had overruns and hence some data is
-  // missing from this point.
-  optional bool has_overruns = 6;
-}
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index abd3af1..f563be5 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -38,145 +38,6 @@
 
 // End of protos/perfetto/common/android_log_constants.proto
 
-// Begin of protos/perfetto/common/data_source_descriptor.proto
-
-// This message is sent from Producer(s) to the tracing Service when registering
-// to advertise their capabilities. It describes the structure of tracing
-// protos that will be produced by the data source and the supported filters.
-message DataSourceDescriptor {
-  optional string name = 1;  // e.g., "linux.ftrace", "chromium.tracing"
-
-  // When true the data source is expected to ack the stop request through the
-  // NotifyDataSourceStopped() IPC. This field has been introduced after
-  // Android P in Jul 2018 and is not supported on older versions.
-  optional bool will_notify_on_stop = 2;
-
-  // When true the data source is expected to ack the start request through the
-  // NotifyDataSourceStarted() IPC. This field has been introduced after
-  // Android P in March 2019 and is not supported on older versions.
-  optional bool will_notify_on_start = 3;
-
-  // If true, opt into receiving the ClearIncrementalState() IPC. This should be
-  // set if the data source writes packets that refer to previous trace
-  // contents, and knows how to stop referring to the already-emitted data.
-  optional bool handles_incremental_state_clear = 4;
-
-  // Optional specification about available GPU counters.
-  optional GpuCounterDescriptor gpu_counter_descriptor = 5 [lazy = true];
-
-  optional TrackEventDescriptor track_event_descriptor = 6 [lazy = true];
-}
-
-// End of protos/perfetto/common/data_source_descriptor.proto
-
-// Begin of protos/perfetto/common/gpu_counter_descriptor.proto
-
-// Description of GPU counters.
-// This message is sent by a GPU counter producer to specify the counters
-// available in the hardware.
-message GpuCounterDescriptor {
-  message GpuCounterSpec {
-    optional uint32 counter_id = 1;
-    optional string name = 2;
-    optional string description = 3;
-    reserved 4;  // MeasureUnit unit (deprecated)
-    oneof peak_value {
-      int64 int_peak_value = 5;
-      double double_peak_value = 6;
-    }
-    repeated MeasureUnit numerator_units = 7;
-    repeated MeasureUnit denominator_units = 8;
-    optional bool select_by_default = 9;
-  }
-  repeated GpuCounterSpec specs = 1;
-
-  // Allow producer to group counters into block to represent counter islands.
-  // A capacity may be specified to indicate the number of counters that can be
-  // enable simultaneously in that block.
-  message GpuCounterBlock {
-    // required. Unique ID for the counter group.
-    optional uint32 block_id = 1;
-    // optional. Number of counters supported by the block. No limit if unset.
-    optional uint32 block_capacity = 2;
-    // optional. Name of block.
-    optional string name = 3;
-    // optional. Description for the block.
-    optional string description = 4;
-    // list of counters that are part of the block.
-    repeated uint32 counter_ids = 5;
-  }
-  repeated GpuCounterBlock blocks = 2;
-
-  // optional.  Minimum sampling period supported by the producer in
-  // nanoseconds.
-  optional uint64 min_sampling_period_ns = 3;
-
-  // optional.  Maximum sampling period supported by the producer in
-  // nanoseconds.
-  optional uint64 max_sampling_period_ns = 4;
-
-  // optional.  The producer supports counter sampling by instrumenting the
-  // command buffer.
-  optional bool supports_instrumented_sampling = 5;
-
-  // next id: 41
-  enum MeasureUnit {
-    NONE = 0;
-
-    BIT = 1;
-    KILOBIT = 2;
-    MEGABIT = 3;
-    GIGABIT = 4;
-    TERABIT = 5;
-    PETABIT = 6;
-
-    BYTE = 7;
-    KILOBYTE = 8;
-    MEGABYTE = 9;
-    GIGABYTE = 10;
-    TERABYTE = 11;
-    PETABYTE = 12;
-
-    HERTZ = 13;
-    KILOHERTZ = 14;
-    MEGAHERTZ = 15;
-    GIGAHERTZ = 16;
-    TERAHERTZ = 17;
-    PETAHERTZ = 18;
-
-    NANOSECOND = 19;
-    MICROSECOND = 20;
-    MILLISECOND = 21;
-    SECOND = 22;
-    MINUTE = 23;
-    HOUR = 24;
-
-    VERTEX = 25;
-    PIXEL = 26;
-    TRIANGLE = 27;
-    PRIMITIVE = 38;
-    FRAGMENT = 39;
-
-    MILLIWATT = 28;
-    WATT = 29;
-    KILOWATT = 30;
-
-    JOULE = 31;
-    VOLT = 32;
-    AMPERE = 33;
-
-    CELSIUS = 34;
-    FAHRENHEIT = 35;
-    KELVIN = 36;
-
-    PERCENT = 37;
-
-    INSTRUCTION = 40;
-  }
-}
-
-// End of protos/perfetto/common/gpu_counter_descriptor.proto
-
 // Begin of protos/perfetto/common/sys_stats_counters.proto
 
 // When editing entries here remember also to update "sys_stats_counters.h" with
@@ -315,9 +176,6 @@
   VMSTAT_UNEVICTABLE_PGS_MUNLOCKED = 90;
   VMSTAT_UNEVICTABLE_PGS_CLEARED = 91;
   VMSTAT_UNEVICTABLE_PGS_STRANDED = 92;
-  VMSTAT_NR_ZSPAGES = 93;
-  VMSTAT_NR_ION_HEAP = 94;
-  VMSTAT_NR_GPU_HEAP = 95;
 }
 // End of protos/perfetto/common/sys_stats_counters.proto
 
@@ -325,11 +183,11 @@
 
 // Statistics for the internals of the tracing service.
 //
-// Next id: 11.
+// Next id: 10.
 message TraceStats {
   // From TraceBuffer::Stats.
   //
-  // Next id: 20.
+  // Next id: 19.
   message BufferStats {
     // Size of the circular buffer in bytes.
     optional uint64 buffer_size = 12;
@@ -414,15 +272,6 @@
     // the buffer. This is an indication of either a bug in the producer(s) or
     // malicious producer(s).
     optional uint64 abi_violations = 9;
-
-    // The fields below have been introduced in Android R.
-
-    // Num. of times the service detected packet loss on a trace writer
-    // sequence. This is usually caused by exhaustion of available chunks in the
-    // writer process's SMB. Note that this relies on the client's TraceWriter
-    // indicating this loss to the service -- packets lost for other reasons are
-    // not reflected in this stat.
-    optional uint64 trace_writer_packet_loss = 19;
   }
 
   // Stats for the TraceBuffer(s) of the current trace session.
@@ -459,60 +308,10 @@
   // Num. patches that were discarded by the service before attempting to apply
   // them to a buffer, e.g. because the producer specified an invalid buffer ID.
   optional uint64 patches_discarded = 9;
-
-  // Packets that failed validation of the TrustedPacket. If this is > 0, there
-  // is a bug in the producer.
-  optional uint64 invalid_packets = 10;
 }
 
 // End of protos/perfetto/common/trace_stats.proto
 
-// Begin of protos/perfetto/common/tracing_service_state.proto
-
-// Reports the state of the tracing service. Used to gather details about the
-// data sources connected.
-// See ConsumerPort::QueryServiceState().
-message TracingServiceState {
-  // Describes a producer process.
-  message Producer {
-    optional int32 id = 1;     // Unique ID of the producer (monotonic counter).
-    optional string name = 2;  // Typically matches the process name.
-    optional int32 uid = 3;    // Unix uid of the remote process.
-  }
-
-  // Describes a data source registered by a producer. Data sources are listed
-  // regardless of the fact that they are being used or not.
-  message DataSource {
-    // Descriptor passed by the data source when calling RegisterDataSource().
-    optional DataSourceDescriptor ds_descriptor = 1;
-
-    // ID of the producer, as per Producer.id.
-    optional int32 producer_id = 2;
-  }
-
-  // Lists all the producers connected.
-  repeated Producer producers = 1;
-
-  // Lists the data sources available.
-  repeated DataSource data_sources = 2;
-
-  // Total number of tracing sessions.
-  optional int32 num_sessions = 3;
-
-  // Number of tracing sessions in the started state. Always <= num_sessions.
-  optional int32 num_sessions_started = 4;
-}
-
-// End of protos/perfetto/common/tracing_service_state.proto
-
-// Begin of protos/perfetto/common/track_event_descriptor.proto
-
-message TrackEventDescriptor {
-  repeated string available_categories = 1;
-}
-
-// End of protos/perfetto/common/track_event_descriptor.proto
-
 // Begin of protos/perfetto/trace/android/android_log.proto
 
 message AndroidLogPacket {
@@ -574,42 +373,6 @@
 
 // End of protos/perfetto/trace/android/android_log.proto
 
-// Begin of protos/perfetto/trace/android/graphics_frame_event.proto
-
-// Generated by Android's SurfaceFlinger.
-message GraphicsFrameEvent {
-  enum BufferEventType {
-    UNSPECIFIED = 0;
-    DEQUEUE = 1;
-    QUEUE = 2;
-    POST = 3;
-    ACQUIRE_FENCE = 4;
-    LATCH = 5;
-    HWC_COMPOSITION_QUEUED = 6;  // HWC will compose this buffer
-    FALLBACK_COMPOSITION = 7;    // renderEngine composition
-    PRESENT_FENCE = 8;
-    RELEASE_FENCE = 9;
-    MODIFY = 10;
-    DETACH = 11;
-    ATTACH = 12;
-    CANCEL = 13;
-  }
-
-  message BufferEvent {
-    optional uint32 frame_number = 1;
-    optional BufferEventType type = 2;
-    optional string layer_name = 3;
-    // If no duration is set, the event is an instant event.
-    optional uint64 duration_ns = 4;
-    // Unique buffer identifier.
-    optional uint32 buffer_id = 5;
-  }
-
-  optional BufferEvent buffer_event = 1;
-}
-
-// End of protos/perfetto/trace/android/graphics_frame_event.proto
-
 // Begin of protos/perfetto/trace/android/packages_list.proto
 
 message PackagesList {
@@ -632,110 +395,12 @@
 
 // End of protos/perfetto/trace/android/packages_list.proto
 
-// Begin of protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto
-
-// This message is not intended to be written by the chrome on the device.
-// It's emitted on the host by the telemetry benchmark infrastructure (it's a
-// part of the trace that's written by the telemetry tracing agent).
-message ChromeBenchmarkMetadata {
-  // Time when the benchmark execution started (host unixtime in microseconds).
-  optional int64 benchmark_start_time_us = 1;
-
-  // Time when this particular story was run (host unixtime in microseconds).
-  optional int64 story_run_time_us = 2;
-
-  // Name of benchmark.
-  optional string benchmark_name = 3;
-
-  // Description of benchmark.
-  optional string benchmark_description = 4;
-
-  // Optional label.
-  optional string label = 5;
-
-  // Name of story.
-  optional string story_name = 6;
-
-  // List of story tags.
-  repeated string story_tags = 7;
-
-  // Index of the story run (>0 if the same story was run several times).
-  optional int32 story_run_index = 8;
-
-  // Whether this run failed.
-  optional bool had_failures = 9;
-}
-
-// End of protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto
-
-// Begin of protos/perfetto/trace/chrome/chrome_metadata.proto
-
-// Metadata for chrome traces.
-message ChromeMetadataPacket {
-  optional BackgroundTracingMetadata background_tracing_metadata = 1;
-
-  // Version code of Chrome used by Android's Play Store. This field is only set
-  // on Android.
-  optional int32 chrome_version_code = 2;
-}
-
-// Metadata related to background tracing scenarios, states and triggers.
-message BackgroundTracingMetadata {
-  // Information about a trigger rule defined in the experiment config.
-  message TriggerRule {
-    enum TriggerType {
-      TRIGGER_UNSPECIFIED = 0;
-
-      // Traces are triggered by specific range of values of an UMA histogram.
-      MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE = 1;
-
-      // Traces are triggered by specific named events in chromium codebase,
-      // like "second-update-failure".
-      MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED = 2;
-    }
-    optional TriggerType trigger_type = 1;
-
-    // Configuration of histogram trigger.
-    message HistogramRule {
-      // UMA histogram name hash, same as HistogramEventProto.name_hash.
-      optional fixed64 histogram_name_hash = 1;
-
-      // Range of values of the histogram that activates trigger.
-      optional int64 histogram_min_trigger = 2;
-      optional int64 histogram_max_trigger = 3;
-    }
-    optional HistogramRule histogram_rule = 2;
-
-    // Configuration of named trigger.
-    message NamedRule {
-      enum EventType {
-        UNSPECIFIED = 0;
-        SESSION_RESTORE = 1;
-        NAVIGATION = 2;
-        STARTUP = 3;
-
-        TEST_RULE = 1000;
-      }
-      optional EventType event_type = 1;
-    }
-    optional NamedRule named_rule = 3;
-  }
-
-  // Specifies the rule that caused the trace to be uploaded.
-  optional TriggerRule triggered_rule = 1;
-
-  // List of all active triggers in current session, when trace was triggered.
-  repeated TriggerRule active_rules = 2;
-}
-
-// End of protos/perfetto/trace/chrome/chrome_metadata.proto
-
 // Begin of protos/perfetto/trace/clock_snapshot.proto
 
 // A snapshot of clock readings to allow for trace alignment.
 message ClockSnapshot {
   message Clock {
-    enum BuiltinClocks {
+    enum Type {
       UNKNOWN = 0;
       REALTIME = 1;
       REALTIME_COARSE = 2;
@@ -745,35 +410,9 @@
       BOOTTIME = 6;
       PROCESS_CPUTIME = 7;
       THREAD_CPUTIME = 8;
-      BUILTIN_CLOCK_MAX_ID = 63;
     }
-
-    // Clock IDs have the following semantic:
-    // [1, 63]:    Builtin types, see BuiltinClocks above.
-    // [64, 127]:  User-defined clocks. These clocks are sequence-scoped. They
-    //             are only valid within the same |trusted_packet_sequence_id|
-    //             (i.e. only for TracePacket(s) emitted by the same TraceWriter
-    //             that emitted the clock snapshot).
-    // [128, MAX]: Reserved for future use. The idea is to allow global clock
-    //             IDs and setting this ID to hash(full_clock_name) & ~127.
-    optional uint32 clock_id = 1;
-
-    // Unit is ns unless specified otherwise by the resolution_* fields below.
+    optional Type type = 1;
     optional uint64 timestamp = 2;
-
-    // TODO(eseckler): the fields below and sequence-scoped clock IDs are not
-    // supported yet by the trace processor.
-
-    // When true the timestamp should be interpreted as a delta from the last
-    // TracePacket's timestamp emitted by the same packet_sequence_id.
-    // The first packet timestamp after a ClockSnapshot is relative to the last
-    // ClockSnapshot seen on the packet sequence.
-    // optional bool is_incremental = 3;
-
-    // Allows to specify a custom unit different than the default (ns)
-    // for this clock domain. A multiplier of 1000 means that a timestamp = 3
-    // should be interpreted as 3000 ns = 3 us.
-    // optional uint64 unit_multiplier_ns = 4;
   }
   repeated Clock clocks = 1;
 }
@@ -2301,48 +1940,14 @@
 
 // Begin of protos/perfetto/trace/ftrace/ftrace_event_bundle.proto
 
-// The result of tracing one or more ftrace data pages from a single per-cpu
-// kernel ring buffer. If collating multiple pages' worth of events, all of
-// them come from contiguous pages, with no kernel data loss in between.
 message FtraceEventBundle {
   optional uint32 cpu = 1;
   repeated FtraceEvent event = 2;
-  // Set to true if there was data loss between the last time we've read from
-  // the corresponding per-cpu kernel buffer, and the earliest event recorded
-  // in this bundle.
-  optional bool lost_events = 3;
-
-  // Optionally-enabled compact encoding of a batch of scheduling events. Only
-  // a subset of events & their fields is recorded.
-  // All fields (except comms) are stored in a structure-of-arrays form, one
-  // entry in each repeated field per event.
-  message CompactSched {
-    // Interned table of unique strings for this bundle.
-    repeated string intern_table = 5;
-
-    // Delta-encoded timestamps across all sched_switch events within this
-    // bundle. The first is absolute, each next one is relative to its
-    // predecessor.
-    repeated uint64 switch_timestamp = 1 [packed = true];
-    repeated int64 switch_prev_state = 2 [packed = true];
-    repeated int32 switch_next_pid = 3 [packed = true];
-    repeated int32 switch_next_prio = 4 [packed = true];
-    // One per event, index into |intern_table| corresponding to the
-    // next_comm field of the event.
-    repeated uint32 switch_next_comm_index = 6 [packed = true];
-
-    // Delta-encoded timestamps across all sched_waking events within this
-    // bundle. The first is absolute, each next one is relative to its
-    // predecessor.
-    repeated uint64 waking_timestamp = 7 [packed = true];
-    repeated int32 waking_pid = 8 [packed = true];
-    repeated int32 waking_target_cpu = 9 [packed = true];
-    repeated int32 waking_prio = 10 [packed = true];
-    // One per event, index into |intern_table| corresponding to the
-    // comm field of the event.
-    repeated uint32 waking_comm_index = 11 [packed = true];
-  }
-  optional CompactSched compact_sched = 4;
+  // Total of all overwrite fields from the headers of all kernel
+  // ftrace pages we parsed into this FtraceEventBundle. Zero if
+  // no overwriting occurred, a number larger than zero if some overwriting
+  // occurred.
+  optional uint32 overwrite_count = 3;
 }
 
 // End of protos/perfetto/trace/ftrace/ftrace_event_bundle.proto
@@ -2888,7 +2493,7 @@
 // Because of the incremental build-up, the interning index will miss data when
 // TracePackets are lost, e.g. because a chunk was overridden in the central
 // ring buffer. To avoid invalidation of the whole trace in such a case, the
-// index is periodically reset (see SEQ_INCREMENTAL_STATE_CLEARED).
+// index is periodically reset (see |incremental_state_cleared| in TracePacket).
 // When packet loss occurs, the reader will only lose interning data up to the
 // next reset.
 // -----------------------------------------------------------------------------
@@ -2900,12 +2505,8 @@
 // refers to them (since the last reset of interning state). They may also be
 // emitted proactively in advance of referring to them in later packets.
 //
-// Next reserved id: 8 (up to 15).
-// Next id: 23.
+// Next id: 5.
 message InternedData {
-  // TODO(eseckler): Replace iid fields inside interned messages with
-  // map<iid, message> type fields in InternedData.
-
   // Each field's message type needs to specify an |iid| field, which is the ID
   // of the entry in the field's interning index. Each field constructs its own
   // index, thus interning IDs are scoped to the tracing session and field
@@ -2914,63 +2515,14 @@
   // within the same tracing session, even after a reset of the emitted
   // interning state.
   repeated EventCategory event_categories = 1;
-  repeated EventName event_names = 2;
+  repeated LegacyEventName legacy_event_names = 2;
   repeated DebugAnnotationName debug_annotation_names = 3;
   repeated SourceLocation source_locations = 4;
-  repeated LogMessageBody log_message_body = 20;
-
   // Note: field IDs up to 15 should be used for frequent data only.
-
-  // Build IDs of exectuable files.
-  repeated InternedString build_ids = 16;
-  // Paths to executable files.
-  repeated InternedString mapping_paths = 17;
-  // Paths to source files.
-  repeated InternedString source_paths = 18;
-  // Names of functions used in frames below.
-  repeated InternedString function_names = 5;
-  // Symbols that were added to this trace after the fact.
-  repeated ProfiledFrameSymbols profiled_frame_symbols = 21;
-
-  // Executable files mapped into processes.
-  repeated Mapping mappings = 19;
-  // Frames of callstacks of a program.
-  repeated Frame frames = 6;
-  // A callstack of a program.
-  repeated Callstack callstacks = 7;
-
-  // Additional Vulkan information sent in a VulkanMemoryEvent message
-  repeated InternedString vulkan_memory_keys = 22;
 }
 
 // End of protos/perfetto/trace/interned_data/interned_data.proto
 
-// Begin of protos/perfetto/trace/perfetto/perfetto_metatrace.proto
-
-// Used to trace the execution of perfetto itself.
-message PerfettoMetatrace {
-  // See base/metatrace_events.h for definitions.
-  oneof record_type {
-    uint32 event_id = 1;
-    uint32 counter_id = 2;
-  }
-
-  // Only when using |event_id|.
-  optional uint32 event_duration_ns = 3;
-
-  // Only when using |counter_id|.
-  optional int32 counter_value = 4;
-
-  // ID of the thread that emitted the event.
-  optional uint32 thread_id = 5;
-
-  // If true the meta-tracing ring buffer had overruns and hence some data is
-  // missing from this point.
-  optional bool has_overruns = 6;
-}
-
-// End of protos/perfetto/trace/perfetto/perfetto_metatrace.proto
-
 // Begin of protos/perfetto/trace/power/battery_counters.proto
 
 message BatteryCounters {
@@ -2998,14 +2550,11 @@
   message RailDescriptor {
     // Index corresponding to the rail
     optional uint32 index = 1;
-
     // Name of the rail
     optional string rail_name = 2;
-
     // Name of the subsystem to which this rail belongs
     optional string subsys_name = 3;
-
-    // Hardware sampling rate (Hz).
+    // Hardware sampling rate
     optional uint32 sampling_rate = 4;
   }
 
@@ -3015,11 +2564,9 @@
   message EnergyData {
     // Index corresponding to RailDescriptor.index
     optional uint32 index = 1;
-
-    // Time since device boot(CLOCK_BOOTTIME) in milli-seconds.
+    // Time since device boot(CLOCK_BOOTTIME) in milli-seconds
     optional uint64 timestamp_ms = 2;
-
-    // Accumulated energy since device boot in microwatt-seconds (uWs).
+    // Accumulated energy since device boot in microwatt-seconds (uWs)
     optional uint64 energy = 3;
   }
 
@@ -3028,234 +2575,52 @@
 
 // End of protos/perfetto/trace/power/power_rails.proto
 
-// Begin of protos/perfetto/trace/profiling/heap_graph.proto
-
-message HeapGraphRoot {
-  enum Type {
-    ROOT_UNKNOWN = 0;
-    ROOT_JNI_GLOBAL = 1;
-    ROOT_JNI_LOCAL = 2;
-    ROOT_JAVA_FRAME = 3;
-    ROOT_NATIVE_STACK = 4;
-    ROOT_STICKY_CLASS = 5;
-    ROOT_THREAD_BLOCK = 6;
-    ROOT_MONITOR_USED = 7;
-    ROOT_THREAD_OBJECT = 8;
-    ROOT_INTERNED_STRING = 9;
-    ROOT_FINALIZING = 10;
-    ROOT_DEBUGGER = 11;
-    ROOT_REFERENCE_CLEANUP = 12;
-    ROOT_VM_INTERNAL = 13;
-    ROOT_JNI_MONITOR = 14;
-  };
-  // Objects retained by this root.
-  repeated uint64 object_ids = 1;
-
-  optional Type root_type = 2;
-}
-
-message HeapGraphObject {
-  optional uint64 id = 1;
-
-  // Index for InternedData.type_names for the name of the type of this object.
-  optional uint64 type_id = 2;
-
-  // Bytes occupied by this objects.
-  optional uint64 self_size = 3;
-
-  // Indices for InternedData.field_names for the name of the field referring
-  // to the object.
-  repeated uint64 reference_field_id = 4;
-
-  // Ids of the Object that is referred to.
-  repeated uint64 reference_object_id = 5;
-}
-
-message HeapGraph {
-  optional int32 pid = 1;
-
-  // This contains all objects at the time this dump was taken. Some of these
-  // will be live, some of those unreachable (garbage). To find the live
-  // objects, the client needs to build the transitive closure of objects
-  // reachable from |roots|.
-  // All objects not contained within that transitive closure are garbage that
-  // has not yet been collected.
-  repeated HeapGraphObject objects = 2;
-
-  // Roots at the time this dump was taken.
-  // All live objects are reachable from the roots. All other objects are
-  // garbage.
-  repeated HeapGraphRoot roots = 7;
-
-  // Type names used in managed heap graph.
-  repeated InternedString type_names = 3;
-
-  // Field names for references in managed heap graph.
-  repeated InternedString field_names = 4;
-
-  optional bool continued = 5;
-  optional uint64 index = 6;
-}
-
-// End of protos/perfetto/trace/profiling/heap_graph.proto
-
-// Begin of protos/perfetto/trace/profiling/profile_common.proto
-
-// TODO(fmayer): Figure out naming thoroughout this file to get a
-// nomenclature that works between Windows and Linux.
-
-// The interning fields in this file can refer to 2 different intern tables,
-// depending on the message they are used in. If the interned fields are present
-// in ProfilePacket proto, then the intern tables included in the ProfilePacket
-// should be used. If the intered fields are present in the
-// StreamingProfilePacket proto, then the intern tables included in all of the
-// previous InternedData message with same sequence ID should be used.
-// TODO(fmayer): Move to the intern tables to a common location.
-message InternedString {
-  optional uint64 iid = 1;
-  optional bytes str = 2;
-}
-
-// A symbol field that is emitted after the trace is written. These tables would
-// be appended as the last packets in the trace that the profiler will use, so
-// that the actual trace need not be rewritten to symbolize the profiles.
-message ProfiledFrameSymbols {
-  // Use the frame id as the interning key for the symbols.
-  optional uint64 frame_iid = 1;
-
-  // These are repeated because when inlining happens, multiple functions'
-  // frames can be at a single address. Imagine function Foo calling the
-  // std::vector<int> constructor, which gets inlined at 0xf00. We then get
-  // both Foo and the std::vector<int> constructor when we symbolize the
-  // address.
-  repeated uint64 function_name_id = 2;  // key to InternedString
-  repeated uint64 file_name_id = 3;      // key to InternedString
-  repeated uint32 line_number = 4;
-}
-
-message Line {
-  optional string function_name = 1;
-  optional string source_file_name = 2;
-  optional uint32 line_number = 3;
-}
-
-// Symbols for a given address in a module.
-message AddressSymbols {
-  optional uint64 address = 1;
-
-  // Source lines that correspond to this address.
-  //
-  // These are repeated because when inlining happens, multiple functions'
-  // frames can be at a single address. Imagine function Foo calling the
-  // std::vector<int> constructor, which gets inlined at 0xf00. We then get
-  // both Foo and the std::vector<int> constructor when we symbolize the
-  // address.
-  repeated Line lines = 2;
-}
-
-// Symbols for addresses seen in a module.
-message ModuleSymbols {
-  // Fully qualified path to the mapping.
-  // E.g. /system/lib64/libc.so.
-  optional string path = 1;
-
-  // .note.gnu.build-id on Linux (not hex encoded).
-  // uuid on MacOS.
-  // Module GUID on Windows.
-  optional string build_id = 2;
-  repeated AddressSymbols address_symbols = 3;
-}
-
-message Mapping {
-  optional uint64 iid = 1;       // Interning key.
-  optional uint64 build_id = 2;  // Interning key.
-
-  // The linker may create multiple memory mappings for the same shared
-  // library.
-  // This is so that the ELF header is mapped as read only, while the
-  // executable memory is mapped as executable only.
-  // The details of this depend on the linker, a possible mapping of an ELF
-  // file is this:
-  //         +----------------------+
-  // ELF     |xxxxxxxxxyyyyyyyyyyyyy|
-  //         +---------+------------+
-  //         |         |
-  //         | read    | executable
-  //         v mapping v mapping
-  //         +----------------------+
-  // Memory  |xxxxxxxxx|yyyyyyyyyyyy|
-  //         +------------------+---+
-  //         ^         ^        ^
-  //         +         +        +
-  //       start     exact    relpc
-  //       offset   offset    0x1800
-  //       0x0000   0x1000
-  //
-  // exact_offset is the offset into the library file of this mapping.
-  // start_offset is the offset into the library file of the first mapping
-  // for that library. For native libraries (.so files) this should be 0.
-  optional uint64 exact_offset = 8;  // This is not set on Android 10.
-  optional uint64 start_offset = 3;
-  optional uint64 start = 4;
-  optional uint64 end = 5;
-  optional uint64 load_bias = 6;
-  // E.g. ["system", "lib64", "libc.so"]
-  repeated uint64 path_string_ids = 7;  // id of string.
-}
-
-message Frame {
-  optional uint64 iid = 1;  // Interning key
-  // E.g. "fopen"
-  optional uint64 function_name_id = 2;  // id of string.
-  optional uint64 mapping_id = 3;
-  optional uint64 rel_pc = 4;
-}
-
-message Callstack {
-  optional uint64 iid = 1;
-  // Frames of this callstack. Bottom frame first.
-  repeated uint64 frame_ids = 2;
-}
-
-// End of protos/perfetto/trace/profiling/profile_common.proto
-
 // Begin of protos/perfetto/trace/profiling/profile_packet.proto
 
 message ProfilePacket {
-  // The following interning tables are only used in Android version Q.
-  // In newer versions, these tables are in InternedData
-  // (see protos/perfetto/trace/interned_data) and are shared across
-  // multiple ProfilePackets.
-  // For backwards compatibility, consumers need to first look up interned
-  // data in the tables within the ProfilePacket, and then, if they are empty,
-  // look up in the InternedData instead.
+  // either a function or library name.
   repeated InternedString strings = 1;
-  repeated Mapping mappings = 4;
-  repeated Frame frames = 2;
-  repeated Callstack callstacks = 3;
+  message InternedString {
+    optional uint64 id = 1;
+    optional bytes str = 2;
+  }
 
-  // Next ID: 9
+  repeated Mapping mappings = 4;
+  message Mapping {
+    optional uint64 id = 1;        // Interning key.
+    optional uint64 build_id = 2;  // Interning key.
+    optional uint64 offset = 3;
+    optional uint64 start = 4;
+    optional uint64 end = 5;
+    optional uint64 load_bias = 6;
+    // E.g. ["system", "lib64", "libc.so"]
+    repeated uint64 path_string_ids = 7;  // id of string.
+  }
+
+  repeated Frame frames = 2;
+  message Frame {
+    optional uint64 id = 1;  // Interning key
+    // E.g. "fopen"
+    optional uint64 function_name_id = 2;  // id of string.
+    optional uint64 mapping_id = 3;
+    optional uint64 rel_pc = 4;
+  }
+
+  repeated Callstack callstacks = 3;
+  message Callstack {
+    optional uint64 id = 1;
+    // Frames of this callstack. Bottom frame first.
+    repeated uint64 frame_ids = 2;
+  }
+
   message HeapSample {
     optional uint64 callstack_id = 1;
-    // bytes allocated at this callstack.
+    // bytes allocated at this frame.
     optional uint64 self_allocated = 2;
-    // bytes allocated at this callstack that have been freed.
+    // bytes allocated at this frame that have been freed.
     optional uint64 self_freed = 3;
-    // bytes allocated at this callstack but not used since the last
-    // dump.
-    // See documentation of idle_allocations in HeapprofdConfig for more
-    // details.
-    optional uint64 self_idle = 7;
-    // Bytes allocated by this callstack but not freed at the time the malloc
-    // heap usage of this process was maximal. This is only set if dump_at_max
-    // is true in HeapprofdConfig. In that case, self_allocated, self_freed and
-    // self_idle will not be set.
-    optional uint64 self_max = 8;
     optional uint64 timestamp = 4;  // timestamp [opt]
-    // Number of allocations that were sampled at this callstack.
     optional uint64 alloc_count = 5;
-    // Number of allocations that were sampled at this callstack that have been
-    // freed.
     optional uint64 free_count = 6;
   }
 
@@ -3320,31 +2685,15 @@
     //               to have a type enum that we can reuse here.
     optional uint64 timestamp = 9;
 
-    // Metadata about heapprofd.
     optional ProcessStats stats = 5;
 
     repeated HeapSample samples = 2;
   }
 
-  // If this is true, the next ProfilePacket in this package_sequence_id is a
-  // continuation of this one.
-  // To get all samples for a process, accummulate its
-  // ProcessHeapSamples.samples until you see continued=false.
   optional bool continued = 6;
-
-  // Index of this ProfilePacket on its package_sequence_id. Can be used
-  // to detect dropped data.
-  // Verify these are consecutive.
   optional uint64 index = 7;
 }
 
-// Message used to represent individual stack samples sampled at discrete
-// points in time, rather than aggregated over an interval.
-message StreamingProfilePacket {
-  repeated uint64 callstack_iid = 1;  // Index into InternedData.callstacks
-  repeated int64 timestamp_delta_us = 2;
-}
-
 // End of protos/perfetto/trace/profiling/profile_packet.proto
 
 // Begin of protos/perfetto/trace/ps/process_stats.proto
@@ -3418,9 +2767,6 @@
     // No longer used as of Apr 2018, when the dedicated |threads| field was
     // introduced in ProcessTree.
     repeated Thread threads_deprecated = 4 [deprecated = true];
-
-    // The uid for the process, as per /proc/pid/status.
-    optional int32 uid = 5;
   }
 
   // List of processes and threads in the client. These lists are incremental
@@ -3536,22 +2882,11 @@
 // TracePacket(s).
 //
 // Next reserved id: 13 (up to 15).
-// Next id: 64.
+// Next id: 51.
 message TracePacket {
-  // The timestamp of the TracePacket.
-  // By default this timestamps refers to the trace clock (CLOCK_BOOTTIME on
-  // Android). It can be overridden using a different timestamp_clock_id.
-  // The clock domain definition in ClockSnapshot can also override:
-  // - The unit (default: 1ns).
-  // - The absolute vs delta encoding (default: absolute timestamp).
-  optional uint64 timestamp = 8;
-
-  // Specifies the ID of the clock used for the TracePacket |timestamp|. Can be
-  // one of the built-in types from ClockSnapshot::BuiltinClocks, or a
-  // producer-defined clock id.
-  // If unspecified and if no default per-sequence value has been provided via
-  // TracePacketDefaults, it defaults to BuiltinClocks::BOOTTIME.
-  optional uint32 timestamp_clock_id = 58;
+  // TODO(primiano): in future we should add a timestamp_clock_domain field to
+  // allow mixing timestamps from different clock domains.
+  optional uint64 timestamp = 8;  // Timestamp [ns].
 
   oneof data {
     FtraceEventBundle ftrace_events = 1;
@@ -3576,28 +2911,9 @@
     SystemInfo system_info = 45;
     Trigger trigger = 46;
     PackagesList packages_list = 47;
-    ChromeBenchmarkMetadata chrome_benchmark_metadata = 48;
-    PerfettoMetatrace perfetto_metatrace = 49;
-    ChromeMetadataPacket chrome_metadata = 51;
-    GpuCounterEvent gpu_counter_event = 52;
-    GpuRenderStageEvent gpu_render_stage_event = 53;
-    StreamingProfilePacket streaming_profile_packet = 54;
-    HeapGraph heap_graph = 56;
-    GraphicsFrameEvent graphics_frame_event = 57;
-    // removed field with id 62
-    GpuLog gpu_log = 63;
-
-    // Only used in profile packets.
-    ProfiledFrameSymbols profiled_frame_symbols = 55;
-    ModuleSymbols module_symbols = 61;
 
     // Only used by TrackEvent.
-    TrackDescriptor track_descriptor = 60;
-
-    // Deprecated, use TrackDescriptor instead.
     ProcessDescriptor process_descriptor = 43;
-
-    // Deprecated, use TrackDescriptor instead.
     ThreadDescriptor thread_descriptor = 44;
 
     // This field is emitted at periodic intervals (~10s) and
@@ -3642,48 +2958,22 @@
   // proactively in advance of referring to them in later packets.
   optional InternedData interned_data = 12;
 
-
-  enum SequenceFlags {
-    SEQ_UNSPECIFIED = 0;
-
-    // Set by the writer to indicate that it will re-emit any incremental data
-    // for the packet's sequence before referring to it again. This includes
-    // interned data as well as periodically emitted data like
-    // Process/ThreadDescriptors. This flag only affects the current packet
-    // sequence (see |trusted_packet_sequence_id|).
-    //
-    // When set, this TracePacket and subsequent TracePackets on the same
-    // sequence will not refer to any incremental data emitted before this
-    // TracePacket. For example, previously emitted interned data will be
-    // re-emitted if it is referred to again.
-    //
-    // When the reader detects packet loss (|previous_packet_dropped|), it needs
-    // to skip packets in the sequence until the next one with this flag set, to
-    // ensure intact incremental data.
-    SEQ_INCREMENTAL_STATE_CLEARED = 1;
-
-    // This packet requires incremental state, such as TracePacketDefaults or
-    // InternedData, to be parsed correctly. The trace reader should skip this
-    // packet if incremental state is not valid on this sequence, i.e. if no
-    // packet with the SEQ_INCREMENTAL_STATE_CLEARED flag has been seen on the
-    // current |trusted_packet_sequence_id|.
-    SEQ_NEEDS_INCREMENTAL_STATE = 2;
-  };
-  optional uint32 sequence_flags = 13;
-
-  // DEPRECATED. Moved to SequenceFlags::SEQ_INCREMENTAL_STATE_CLEARED.
+  // Set to true by the writer to indicate that it will re-emit any incremental
+  // data for the packet's sequence before referring to it again. This includes
+  // interned data as well as periodically emitted data like
+  // Process/ThreadDescriptors. This flag only affects the current packet
+  // sequence (see |trusted_packet_sequence_id|).
+  //
+  // When set to true, this TracePacket and subsequent TracePackets on the same
+  // sequence will not refer to any incremental data emitted before this
+  // TracePacket. For example, previously emitted interned data will be
+  // re-emitted if it is referred to again.
+  //
+  // When the reader detects packet loss (|previous_packet_dropped|), it needs
+  // to skip packets in the sequence until the next one with this flag set, to
+  // ensure intact incremental data.
   optional bool incremental_state_cleared = 41;
 
-  // Default values for fields of later TracePackets emitted on this packet's
-  // sequence (TracePackets with the same |trusted_packet_sequence_id|).
-  // It must be reemitted when incremental state is cleared (see
-  // |incremental_state_cleared|).
-  // Requires that any future packet emitted on the same sequence specifies
-  // the SEQ_NEEDS_INCREMENTAL_STATE flag.
-  // TracePacketDefaults always override the global defaults for any future
-  // packet on this sequence (regardless of SEQ_NEEDS_INCREMENTAL_STATE).
-  optional TracePacketDefaults trace_packet_defaults = 59;
-
   // Flag set by the service if, for the current packet sequence (see
   // |trusted_packet_sequence_id|), either:
   // * this is the first packet, or
@@ -3694,36 +2984,17 @@
   //
   // When packet loss occurs, incrementally emitted data (including interned
   // data) on the sequence should be considered invalid up until the next packet
-  // with SEQ_INCREMENTAL_STATE_CLEARED set.
+  // with |incremental_state_cleared| set.
   optional bool previous_packet_dropped = 42;
 }
 
 // End of protos/perfetto/trace/trace_packet.proto
 
-// Begin of protos/perfetto/trace/trace_packet_defaults.proto
-
-// Default values for TracePacket fields that hold for a particular TraceWriter
-// packet sequence. This message contains a subset of the TracePacket fields
-// with matching IDs. When provided, these fields define the default values
-// that should be applied, at import time, to all TracePacket(s) with the same
-// |trusted_packet_sequence_id|, unless otherwise specified in each packet.
-//
-// Should be reemitted whenever incremental state is cleared on the sequence.
-message TracePacketDefaults {
-  optional uint32 timestamp_clock_id = 58;
-
-  // Default values for TrackEvents (e.g. default track).
-  optional TrackEventDefaults track_event_defaults = 11;
-}
-// End of protos/perfetto/trace/trace_packet_defaults.proto
-
 // Begin of protos/perfetto/trace/track_event/debug_annotation.proto
 
 // Key/value annotations provided in untyped TRACE_EVENT macros. These
 // annotations are intended for debug use and are not considered a stable API
 // surface. As such, they should not be relied upon to implement (new) metrics.
-//
-// Next ID: 10.
 message DebugAnnotation {
   message NestedValue {
     enum NestedType {
@@ -3742,10 +3013,7 @@
     optional string string_value = 8;
   }
 
-  oneof name_field {
-    uint64 name_iid = 1;  // interned DebugAnnotationName.
-    string name = 10;     // non-interned variant.
-  }
+  optional uint32 name_iid = 1;  // interned DebugAnnotationName.
 
   oneof value {
     bool bool_value = 2;
@@ -3769,39 +3037,25 @@
 // --------------------
 
 message DebugAnnotationName {
-  optional uint64 iid = 1;
+  optional uint32 iid = 1;
   optional string name = 2;
 }
 
 // End of protos/perfetto/trace/track_event/debug_annotation.proto
 
-// Begin of protos/perfetto/trace/track_event/log_message.proto
-
-message LogMessage {
-  optional uint64 source_location_iid = 1;  // interned SourceLocation.
-  optional uint64 body_iid = 2;             // interned LogMessageBody.
-}
-
-// --------------------
-// Interned data types:
-// --------------------
-
-message LogMessageBody {
-  optional uint64 iid = 1;
-  optional string body = 2;
-}
-// End of protos/perfetto/trace/track_event/log_message.proto
-
 // Begin of protos/perfetto/trace/track_event/process_descriptor.proto
 
-// Describes a process's attributes. Emitted as part of a TrackDescriptor,
-// usually by the process's main thread.
+// Process-wide data that is periodically emitted by one thread per process.
+// Valid for all events in packet sequences emitted by the same process.
 //
 // Next id: 5.
 message ProcessDescriptor {
   optional int32 pid = 1;
   repeated string cmdline = 2;
 
+  // To support old UI. New UI should determine default sorting by process_type.
+  optional int32 legacy_sort_index = 3;
+
   // See chromium's content::ProcessType.
   enum ChromeProcessType {
     PROCESS_UNSPECIFIED = 0;
@@ -3815,304 +3069,86 @@
     PROCESS_PPAPI_BROKER = 8;
   }
   optional ChromeProcessType chrome_process_type = 4;
-  optional int32 process_priority = 5;
-
-  // To support old UI. New UI should determine default sorting by process_type.
-  optional int32 legacy_sort_index = 3;
 }
 
 // End of protos/perfetto/trace/track_event/process_descriptor.proto
 
-// Begin of protos/perfetto/trace/track_event/source_location.proto
-
-// --------------------
-// Interned data types:
-// --------------------
-
-message SourceLocation {
-  optional uint64 iid = 1;
-
-  // We intend to add a binary symbol version of this in the future.
-  optional string file_name = 2;
-  optional string function_name = 3;
-  optional uint32 line_number = 4;
-}
-
-// End of protos/perfetto/trace/track_event/source_location.proto
-
 // Begin of protos/perfetto/trace/track_event/task_execution.proto
 
 // TrackEvent arguments describing the execution of a task.
 message TaskExecution {
   // Source location that the task was posted from.
-  optional uint64 posted_from_iid = 1;  // interned SourceLocation.
+  optional uint32 posted_from_iid = 1;  // interned SourceLocation.
 }
+
+// --------------------
+// Interned data types:
+// --------------------
+
+message SourceLocation {
+  optional uint32 iid = 1;
+
+  // We intend to add a binary symbol version of this in the future.
+  optional string file_name = 2;
+  optional string function_name = 3;
+}
+
 // End of protos/perfetto/trace/track_event/task_execution.proto
 
 // Begin of protos/perfetto/trace/track_event/thread_descriptor.proto
 
-// Describes a thread's attributes. Emitted as part of a TrackDescriptor,
-// usually by the thread's trace writer.
+// Periodically emitted data that's common to all events emitted by the same
+// thread, i.e. all events in the same packet sequence. Valid for all subsequent
+// events in the same sequence.
 //
-// Next id: 9.
+// Next id: 8.
 message ThreadDescriptor {
   optional int32 pid = 1;
   optional int32 tid = 2;
 
-  optional string thread_name = 5;
+  // To support old UI. New UI should determine default sorting by thread_type.
+  optional int32 legacy_sort_index = 3;
 
   enum ChromeThreadType {
-    CHROME_THREAD_UNSPECIFIED = 0;
-
-    CHROME_THREAD_MAIN = 1;
-    CHROME_THREAD_IO = 2;
-
-    // Scheduler:
-    CHROME_THREAD_POOL_BG_WORKER = 3;
-    CHROME_THREAD_POOL_FG_WORKER = 4;
-    CHROME_THREAD_POOL_FB_BLOCKING = 5;
-    CHROME_THREAD_POOL_BG_BLOCKING = 6;
-    CHROME_THREAD_POOL_SERVICE = 7;
-
-    // Compositor:
-    CHROME_THREAD_COMPOSITOR = 8;
-    CHROME_THREAD_VIZ_COMPOSITOR = 9;
-    CHROME_THREAD_COMPOSITOR_WORKER = 10;
-
-    // Renderer:
-    CHROME_THREAD_SERVICE_WORKER = 11;
-
-    // Tracing related threads:
-    CHROME_THREAD_MEMORY_INFRA = 50;
-    CHROME_THREAD_SAMPLING_PROFILER = 51;
+    THREAD_UNSPECIFIED = 0;
+    // TODO(eseckler): Add thread types.
   };
   optional ChromeThreadType chrome_thread_type = 4;
 
-  // ---------------------------------------------------------------------------
-  // Deprecated / legacy fields, which will be removed in the future:
-  // ---------------------------------------------------------------------------
-
-  // Deprecated. Use ClockSnapshot in combination with TracePacket's timestamp
-  // and timestamp_clock_id fields instead.
-  optional int64 reference_timestamp_us = 6;
+  // TODO(eseckler): Replace this with ChromeThreadType where possible.
+  optional string thread_name = 5;
 
   // Absolute reference values. Clock values in subsequent TrackEvents can be
   // encoded accumulatively and relative to these. This reduces their var-int
   // encoding size.
-  // TODO(eseckler): Deprecated. Replace these with ClockSnapshot encoding.
+  optional int64 reference_timestamp_us = 6;
   optional int64 reference_thread_time_us = 7;
-  optional int64 reference_thread_instruction_count = 8;
-
-  // To support old UI. New UI should determine default sorting by thread_type.
-  optional int32 legacy_sort_index = 3;
 }
 
 // End of protos/perfetto/trace/track_event/thread_descriptor.proto
 
-// Begin of protos/perfetto/trace/track_event/track_descriptor.proto
-
-// Defines a track for TrackEvents. Slices and instant events on the same track
-// will be nested based on their timestamps, see TrackEvent::Type.
-//
-// A TrackDescriptor only needs to be emitted by one trace writer / producer and
-// is valid for the entirety of the trace. To ensure the descriptor isn't lost
-// when the ring buffer wraps, it should be reemitted whenever incremental state
-// is cleared.
-//
-// As a fallback, TrackEvents emitted without an explicit track association will
-// be associated with an implicit trace-global track (uuid = 0), see also
-// |TrackEvent::track_uuid|. It is possible but not necessary to emit a
-// TrackDescriptor for this implicit track.
-//
-// Next id: 1.
-message TrackDescriptor {
-  // Unique ID that identifies this track. This ID is global to the whole trace.
-  // Producers should ensure that it is unlikely to clash with IDs emitted by
-  // other producers. A value of 0 denotes the implicit trace-global track.
-  //
-  // For example, legacy TRACE_EVENT macros may use a hash involving the async
-  // event id + id_scope, pid, and/or tid to compute this ID.
-  optional uint64 uuid = 1;
-
-  // TODO(eseckler): Support track hierarchies.
-  // uint64 parent_uuid = X;
-
-  // Name of the track.
-  optional string name = 2;
-
-  // Associate the track with a process or thread - the UI will draw this track
-  // in the context of the process/thread.
-  optional ProcessDescriptor process = 3;
-  optional ThreadDescriptor thread = 4;
-}
-
-// End of protos/perfetto/trace/track_event/track_descriptor.proto
-
 // Begin of protos/perfetto/trace/track_event/track_event.proto
 
-// NOTE: Full TrackEvent support in the client lib and chrome is WIP, thus these
-// protos are still subject to change. Don't depend on them staying as they are.
-
 // Trace events emitted by client instrumentation library (TRACE_EVENT macros),
-// which describe activity on a track, such as a thread or asynchronous event
-// track. The track is specified using separate TrackDescriptor messages and
-// referred to via the track's UUID.
+// which describe activity on a track, such as a thread, task sequence, or
+// asynchronous track.
 //
-// A simple TrackEvent packet specifies a timestamp, category, name and type:
-//   trace_packet {
-//     timestamp: 1000
-//     track_event {
-//       categories: ["my_cat"]
-//       name: "my_event"
-//       type: TYPE_INSTANT
-//      }
-//    }
+// This message is optimized for writing and makes heavy use of data interning
+// and delta encoding (e.g. of timestamps) to reduce data repetition and encoded
+// data size.
 //
-// To associate an event with a custom track (e.g. a thread), the track is
-// defined in a separate packet and referred to from the TrackEvent by its UUID:
-//   trace_packet {
-//     track_descriptor {
-//       track_uuid: 1234
-//       name: "my_track"
+// A TrackEvent exists in the context of its packet sequence (TracePackets
+// emitted by the same producer + writer) and refers to data in preceding
+// TracePackets emitted on the same sequence, both directly and indirectly. For
+// example, interned data entries are emitted as part of a TracePacket and
+// directly referred to from TrackEvents by their interning IDs. Attributes
+// shared by all events on the same sequence (e.g. their thread and process
+// association) are emitted as part of ProcessDescriptor and ThreadDescriptor
+// messages in separate TracePackets instead.
 //
-//       // Optionally, associate the track with a thread.
-//       thread_descriptor {
-//         pid: 10
-//         tid: 10
-//         ..
-//       }
-//     }
-//   }
-//
-// A pair of TYPE_SLICE_BEGIN and _END events form a slice on the track:
-//   trace_packet {
-//     timestamp: 1200
-//     track_event {
-//       track_uuid: 1234
-//       categories: ["my_cat"]
-//       name: "my_slice"
-//       type: TYPE_SLICE_BEGIN
-//     }
-//   }
-//   trace_packet {
-//     timestamp: 1400
-//     track_event {
-//       track_uuid: 1234
-//       type: TYPE_SLICE_END
-//     }
-//   }
-//
-// TrackEvents also support optimizations to reduce data repetition and encoded
-// data size, e.g. through data interning (names, categories, ...) and delta
-// encoding of timestamps/counters. For details, see the InternedData message.
-// Further, default values for attributes of events on the same sequence (e.g.
-// their default track association) can be emitted as part of a
-// TrackEventDefaults message.
-//
-// Next reserved id: 12 (up to 15). Next id: 24.
+// Next reserved id: 7 (up to 15).
+// Next id: 20.
 message TrackEvent {
-  // Names of categories of the event. In the client library, categories are a
-  // way to turn groups of individual events on or off.
-  repeated uint64 category_iids = 3;  // interned EventCategoryName.
-  repeated string categories = 22;    // non-interned variant.
-
-  // Optional name of the event for its display in trace viewer. May be left
-  // unspecified for events with typed arguments.
-  //
-  // Note that metrics should not rely on event names, as they are prone to
-  // changing. Instead, they should use typed arguments to identify the events
-  // they are interested in.
-  oneof name_field {
-    uint64 name_iid = 10;  // interned EventName.
-    string name = 23;      // non-interned variant.
-  }
-
-  // TODO(eseckler): Support using binary symbols for category/event names.
-
-  // Type of the TrackEvent (required if |phase| in LegacyEvent is not set).
-  enum Type {
-    TYPE_UNSPECIFIED = 0;
-
-    // Slice events are events that have a begin and end timestamp, i.e. a
-    // duration. They can be nested similar to a callstack: If, on the same
-    // track, event B begins after event A, but before A ends, B is a child
-    // event of A and will be drawn as a nested event underneath A in the UI.
-    // Note that child events should always end before their parents (e.g. B
-    // before A).
-    //
-    // Each slice event is formed by a pair of BEGIN + END events. The END event
-    // does not need to repeat any TrackEvent fields it has in common with its
-    // corresponding BEGIN event. Arguments and debug annotations of the BEGIN +
-    // END pair will be merged during trace import.
-    //
-    // Note that we deliberately chose not to support COMPLETE events (which
-    // would specify a duration directly) since clients would need to delay
-    // writing them until the slice is completed, which can result in reordered
-    // events in the trace and loss of unfinished events at the end of a trace.
-    TYPE_SLICE_BEGIN = 1;
-    TYPE_SLICE_END = 2;
-
-    // Instant events are nestable events without duration. They can be children
-    // of slice events on the same track.
-    TYPE_INSTANT = 3;
-
-    // TODO(eseckler): Add support for counters.
-  }
-  optional Type type = 9;
-
-  // Identifies the track of the event. The default value may be overridden
-  // using TrackEventDefaults, e.g., to specify the track of the TraceWriter's
-  // sequence (in most cases sequence = one thread). If no value is specified
-  // here or in TrackEventDefaults, the TrackEvent will be associated with an
-  // implicit trace-global track (uuid 0). See TrackDescriptor::uuid.
-  optional uint64 track_uuid = 11;
-
-  // TODO(eseckler): Add flow event support.
-
-  // TODO(eseckler): Encode thread_time and thread_instruction_count using a
-  // ClockSnapshot + clock id instead of ThreadDescriptor's reference values.
-
-  // CPU time for the current thread (e.g., CLOCK_THREAD_CPUTIME_ID) in
-  // microseconds.
-  oneof thread_time {
-    // Delta timestamp value since the last TrackEvent or ThreadDescriptor. To
-    // calculate the absolute timestamp value, sum up all delta values of the
-    // preceding TrackEvents since the last ThreadDescriptor and add the sum to
-    // the |reference_timestamp| in ThreadDescriptor. This value should always
-    // be positive.
-    int64 thread_time_delta_us = 2;
-    // This is a one-off absolute value that does not affect delta timestamp
-    // computation in subsequent TrackEvents.
-    int64 thread_time_absolute_us = 17;
-  }
-
-  // Value of the instruction counter for the current thread.
-  oneof thread_instruction_count {
-    // Same encoding as |thread_time| field above.
-    int64 thread_instruction_count_delta = 8;
-    int64 thread_instruction_count_absolute = 20;
-  }
-
-  // ---------------------------------------------------------------------------
-  // TrackEvent arguments:
-  // ---------------------------------------------------------------------------
-
-  // Unstable key/value annotations shown in the trace viewer but not intended
-  // for metrics use.
-  repeated DebugAnnotation debug_annotations = 4;
-
-  // Typed event arguments:
-  optional TaskExecution task_execution = 5;
-  optional LogMessage log_message = 21;
-  // New argument types go here :)
-
-  // ---------------------------------------------------------------------------
-  // Deprecated / legacy event fields, which will be removed in the future:
-  // ---------------------------------------------------------------------------
-
-  // Deprecated. Use the |timestamp| and |timestamp_clock_id| fields in
-  // TracePacket instead.
-  //
   // Timestamp in microseconds (usually CLOCK_MONOTONIC).
   oneof timestamp {
     // Delta timestamp value since the last TrackEvent or ThreadDescriptor. To
@@ -4127,24 +3163,44 @@
     int64 timestamp_absolute_us = 16;
   }
 
+  // CPU time for the current thread (e.g., CLOCK_THREAD_CPUTIME_ID) in
+  // microseconds.
+  oneof thread_time {
+    // Same encoding as |timestamp| fields above.
+    int64 thread_time_delta_us = 2;
+    // TODO(eseckler): Consider removing absolute thread time support. It's
+    // currently required to support writing PHASE_COMPLETE events out-of-order,
+    // but shouldn't be required anymore when we split them into begin/end.
+    int64 thread_time_absolute_us = 17;
+  }
+
+  // We intend to add a binary symbol version of this in the future.
+  repeated uint32 category_iids = 3;  // interned EventCategoryName.
+
+  // TODO(eseckler): May also want a debug_name for untyped debug-only events.
+
+  // Unstable key/value annotations shown in the trace viewer but not intended
+  // for metrics use.
+  repeated DebugAnnotation debug_annotations = 4;
+
+  // Typed event arguments:
+  optional TaskExecution task_execution = 5;
+  // TODO(eseckler): New argument types go here :)
+
   // Apart from {category, time, thread time, tid, pid}, other legacy trace
   // event attributes are initially simply proxied for conversion to a JSON
   // trace. We intend to gradually transition these attributes to similar native
   // features in TrackEvent (e.g. async + flow events), or deprecate them
   // without replacement where transition is unsuitable.
   //
-  // Next reserved id: 16 (up to 16).
+  // Next reserved id: 15 (up to 16).
   // Next id: 20.
   message LegacyEvent {
-    // Deprecated, use TrackEvent::name(_iid) instead.
-    optional uint64 name_iid = 1;  // interned EventName.
+    optional uint32 name_iid = 1;  // interned LegacyEventName.
     optional int32 phase = 2;
     optional int64 duration_us = 3;
     optional int64 thread_duration_us = 4;
 
-    // Elapsed retired instruction count during the event.
-    optional int64 thread_instruction_delta = 15;
-
     reserved 5;  // used to be |flags|.
 
     oneof id {
@@ -4191,27 +3247,17 @@
   optional LegacyEvent legacy_event = 6;
 }
 
-// Default values for fields of all TrackEvents on the same packet sequence.
-// Should be emitted as part of TracePacketDefaults whenever incremental state
-// is cleared. It's defined here because field IDs should match those of the
-// corresponding fields in TrackEvent.
-message TrackEventDefaults {
-  optional uint64 track_uuid = 10;
-
-  // TODO(eseckler): Support default values for more TrackEvent fields.
-}
-
 // --------------------
 // Interned data types:
 // --------------------
 
 message EventCategory {
-  optional uint64 iid = 1;
+  optional uint32 iid = 1;
   optional string name = 2;
 }
 
-message EventName {
-  optional uint64 iid = 1;
+message LegacyEventName {
+  optional uint32 iid = 1;
   optional string name = 2;
 }
 
@@ -4234,121 +3280,6 @@
 
 // End of protos/perfetto/trace/trigger.proto
 
-// Begin of protos/perfetto/trace/gpu/gpu_counter_event.proto
-
-message GpuCounterEvent {
-  // The first trace packet of each session should include counter_spec.
-  optional GpuCounterDescriptor counter_descriptor = 1;
-
-  message GpuCounter {
-    // required. Identifier for counter.
-    optional uint32 counter_id = 1;
-    // required. Value of the counter.
-    oneof value {
-      int64 int_value = 2;
-      double double_value = 3;
-    }
-  }
-  repeated GpuCounter counters = 2;
-
-  // optional. Identifier for GPU in a multi-gpu device.
-  optional int32 gpu_id = 3;
-}
-
-// End of protos/perfetto/trace/gpu/gpu_counter_event.proto
-
-// Begin of protos/perfetto/trace/gpu/gpu_log.proto
-
-// Message for logging events GPU data producer.
-message GpuLog {
-  enum Severity {
-    LOG_SEVERITY_UNSPECIFIED = 0;
-    LOG_SEVERITY_VERBOSE = 1;
-    LOG_SEVERITY_DEBUG = 2;
-    LOG_SEVERITY_INFO = 3;
-    LOG_SEVERITY_WARNING = 4;
-    LOG_SEVERITY_ERROR = 5;
-  };
-  optional Severity severity = 1;
-
-  optional string tag = 2;
-
-  optional string log_message = 3;
-}
-
-// End of protos/perfetto/trace/gpu/gpu_log.proto
-
-// Begin of protos/perfetto/trace/gpu/gpu_render_stage_event.proto
-
-// next id: 13
-message GpuRenderStageEvent {
-  // required. Unique ID for the event.
-  optional uint64 event_id = 1;
-
-  // optional. Duration of the event.  This should be in the same clock domain as the timestamp of
-  // the packet.  If unset, this is a single time point event.
-  optional uint64 duration = 2;
-
-  // required. ID to a hardware queue description in the specifications.
-  optional int32 hw_queue_id = 3;
-
-  // required. ID to a render stage description in the specifications.
-  optional int32 stage_id = 4;
-
-  // required. GL context/VK device.
-  optional uint64 context = 5;
-
-  // optional. The render target for this event.
-  optional uint64 render_target_handle = 8;
-
-  // optional. The Vulkan render pass handle.
-  optional uint64 render_pass_handle = 9;
-
-  // optional. The Vulkan command buffer handle.
-  optional uint64 command_buffer_handle = 12;
-
-  // optional. Submission ID generated by the UMD.
-  optional uint32 submission_id = 10;
-
-  // optional.  Additional data for the user. This may include attribs for
-  // the event like resource ids, shaders etc
-  message ExtraData {
-    optional string name = 1;
-    optional string value = 2;
-  }
-  repeated ExtraData extra_data = 6;
-
-  // The first trace packet of each session should include a Specifications
-  // to enumerate all IDs that will be used.
-  message Specifications {
-    message ContextSpec {
-      optional uint64 context = 1;
-      optional int32 pid = 2;
-    }
-    optional ContextSpec context_spec = 1;
-
-    message Description {
-      optional string name = 1;
-      optional string description = 2;
-    }
-
-    // Labels to categorize the hw Queue this event goes on.
-    repeated Description hw_queue = 2;
-
-    // Labels to categorize render stage(binning, render, compute etc).
-    repeated Description stage = 3;
-  }
-  optional Specifications specifications = 7;
-
-  // optional. Identifier for GPU in a multi-gpu device.
-  optional int32 gpu_id = 11;
-
-  // Extension for vendor's custom proto.
-  extensions 100;
-}
-
-// End of protos/perfetto/trace/gpu/gpu_render_stage_event.proto
-
 // Begin of protos/perfetto/config/android/android_log_config.proto
 
 message AndroidLogConfig {
@@ -4368,6 +3299,9 @@
 
 // Begin of protos/perfetto/config/chrome/chrome_config.proto
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 message ChromeConfig {
   optional string trace_config = 1;
 
@@ -4380,6 +3314,9 @@
 
 // Begin of protos/perfetto/config/data_source_config.proto
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 // The configuration that is passed to each data source when starting tracing.
 message DataSourceConfig {
   // Data source unique name, e.g., "linux.ftrace". This must match
@@ -4399,10 +3336,6 @@
   // DO NOT SET in consumer as this will be overridden by the service.
   optional uint32 trace_duration_ms = 3;
 
-  // Set by the service to indicate how long it waits after StopDataSource.
-  // DO NOT SET in consumer as this will be overridden by the service.
-  optional uint32 stop_timeout_ms = 7;
-
   // Set by the service to indicate whether this tracing session has extra
   // guardrails.
   // DO NOT SET in consumer as this will be overridden by the service.
@@ -4418,27 +3351,15 @@
   // Keeep the lower IDs (up to 99) for fields that are *not* specific to
   // data-sources and needs to be processed by the traced daemon.
 
-  // All data source config fields must be marked as [lazy=true]. This prevents
-  // the proto-to-cpp generator from recursing into those when generating the
-  // cpp classes and polluting tracing/core with data-source-specific classes.
-  // Instead they are treated as opaque strings containing raw proto bytes.
-
-  optional FtraceConfig ftrace_config = 100 [lazy = true];
-  optional InodeFileConfig inode_file_config = 102 [lazy = true];
-  optional ProcessStatsConfig process_stats_config = 103 [lazy = true];
-  optional SysStatsConfig sys_stats_config = 104 [lazy = true];
-  optional HeapprofdConfig heapprofd_config = 105 [lazy = true];
-  optional JavaHprofConfig java_hprof_config = 110 [lazy = true];
-  optional AndroidPowerConfig android_power_config = 106 [lazy = true];
-  optional AndroidLogConfig android_log_config = 107 [lazy = true];
-  optional GpuCounterConfig gpu_counter_config = 108 [lazy = true];
-  optional PackagesListConfig packages_list_config = 109 [lazy = true];
-
-  // Chrome is special as it doesn't use the perfetto IPC layer. We want to
-  // avoid proto serialization and de-serialization there because that would
-  // just add extra hops on top of the Mojo ser/des. Instead we auto-generate a
-  // C++ class for it so it can pass around plain C++ objets.
+  optional FtraceConfig ftrace_config = 100;
   optional ChromeConfig chrome_config = 101;
+  optional InodeFileConfig inode_file_config = 102;
+  optional ProcessStatsConfig process_stats_config = 103;
+  optional SysStatsConfig sys_stats_config = 104;
+  optional HeapprofdConfig heapprofd_config = 105;
+  optional AndroidPowerConfig android_power_config = 106;
+  optional AndroidLogConfig android_log_config = 107;
+  optional PackagesListConfig packages_list_config = 109;
 
   // This is a fallback mechanism to send a free-form text config to the
   // producer. In theory this should never be needed. All the code that
@@ -4450,15 +3371,17 @@
   optional string legacy_config = 1000;
 
   // This field is only used for testing.
-  optional TestConfig for_testing = 1001;
-
-  reserved 268435455;  // Was |for_testing|. Caused more problems then found.
+  optional TestConfig for_testing =
+      268435455;  // 2^28 - 1, max field id for protos supported by Java.
 }
 
 // End of protos/perfetto/config/data_source_config.proto
 
 // Begin of protos/perfetto/config/ftrace/ftrace_config.proto
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 message FtraceConfig {
   repeated string ftrace_events = 1;
   repeated string atrace_categories = 2;
@@ -4466,22 +3389,15 @@
   // *Per-CPU* buffer size.
   optional uint32 buffer_size_kb = 10;
   optional uint32 drain_period_ms = 11;
-
-  // Configuration for compact encoding of scheduler events. When enabled (and
-  // recording the relevant ftrace events), specific high-volume events are
-  // encoded in a denser format than normal.
-  message CompactSchedConfig {
-    // If true, and sched_switch or sched_waking ftrace events are enabled,
-    // record those events in the compact format.
-    optional bool enabled = 1;
-  }
-  optional CompactSchedConfig compact_sched = 12;
 }
 
 // End of protos/perfetto/config/ftrace/ftrace_config.proto
 
 // Begin of protos/perfetto/config/inode_file/inode_file_config.proto
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 message InodeFileConfig {
   message MountPointMappingEntry {
     optional string mountpoint = 1;
@@ -4532,6 +3448,9 @@
 
 // Begin of protos/perfetto/config/process_stats/process_stats_config.proto
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 message ProcessStatsConfig {
   enum Quirks {
     QUIRKS_UNSPECIFIED = 0;
@@ -4576,6 +3495,9 @@
 
 // Begin of protos/perfetto/config/sys_stats/sys_stats_config.proto
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 // This file defines the configuration for the Linux /proc poller data source,
 // which injects counters in the trace.
 // Counters that are needed in the trace must be explicitly listed in the
@@ -4591,8 +3513,7 @@
   // Cost: 0.3 ms [read] + 0.07 ms [parse + trace injection]
   optional uint32 meminfo_period_ms = 1;
 
-  // If empty all known counters are reported. Otherwise, only the counters
-  // specified below are reported.
+  // Only the counters specified below are reported.
   repeated MeminfoCounters meminfo_counters = 2;
 
   // Polls /proc/vmstat every X ms, if non-zero.
@@ -4619,6 +3540,9 @@
 
 // Begin of protos/perfetto/config/test_config.proto
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos.py
+// to reflect changes in the corresponding C++ headers.
+
 // The configuration for a fake producer used in tests.
 message TestConfig {
   message DummyFields {
@@ -4667,12 +3591,15 @@
 
 // Begin of protos/perfetto/config/trace_config.proto
 
+// When editing this file run ./tools/gen_tracing_cpp_headers_from_protos
+// to reflect changes in the corresponding C++ headers.
+
 // The overall config that is used when starting a new tracing session through
 // ProducerPort::StartTracing().
 // It contains the general config for the logging buffer(s) and the configs for
 // all the data source being enabled.
 //
-// Next id: 27.
+// Next id: 26.
 message TraceConfig {
   message BufferConfig {
     optional uint32 size_kb = 1;
@@ -4822,10 +3749,6 @@
   // Default 5s.
   optional uint32 flush_timeout_ms = 14;
 
-  // Wait for this long for producers to acknowledge stop requests.
-  // Default 5s.
-  optional uint32 data_source_stop_timeout_ms = 23;
-
   reserved 15;  // |disable_clock_snapshotting| moved.
 
   // Android-only. If set, sends an intent to the Traceur system app when the
@@ -4930,7 +3853,7 @@
   enum CompressionType {
     COMPRESSION_TYPE_UNSPECIFIED = 0;
     COMPRESSION_TYPE_DEFLATE = 1;
-  }
+  };
   optional CompressionType compression_type = 24;
 
   // Android-only. Debug builds only. Not for general use. If set, saves a
@@ -4947,9 +3870,6 @@
     optional bool skip_dropbox = 4;
   }
   optional IncidentReportConfig incident_report_config = 25;
-
-  // An identifier clients can use to tie this trace to other logging.
-  optional bytes trace_uuid = 26;
 }
 
 // End of protos/perfetto/config/trace_config.proto
@@ -4963,7 +3883,7 @@
     optional uint32 dump_phase_ms = 5;
     // ms to wait between following dumps.
     optional uint32 dump_interval_ms = 6;
-  }
+  };
 
   // Set to 1 for perfect accuracy.
   // Otherwise, sample every sample_interval_bytes on average.
@@ -5000,6 +3920,10 @@
   // E.g. /system to not emit symbols for any system libraries.
   repeated string skip_symbol_prefix = 7;
 
+  // Dump once at the end of the trace, emitting the heap dump at maximum
+  // memory usage.
+  // optional bool retain_max = 5;  // TODO(fmayer): Implement
+
   // Dump at a predefined interval.
   optional ContinuousDumpConfig continuous_dump_config = 6;
 
@@ -5017,88 +3941,10 @@
   // trace. Use with caution as this will significantly slow down the target
   // process.
   optional bool block_client = 9;
-
-  // Do not profile processes from startup, only match already running
-  // processes.
-  //
-  // Can not be set at the same time as no_running.
-  optional bool no_startup = 10;
-
-  // Do not profile running processes. Only match processes on startup.
-  //
-  // Can not be set at the same time as no_startup.
-  optional bool no_running = 11;
-
-  // Gather information on how many bytes of allocations are on non-referenced
-  // pages. The way to use this generally is:
-  // 1. Start profile of app.
-  // 2. Start app.
-  // 3. Trigger a dump by sending SIGUSR1 to heapprofd.
-  // 4. Do operations.
-  // 5. End profile.
-  //
-  // You can then find the allocations that were not used for the operations you
-  // did in step 4.
-  optional bool idle_allocations = 12;
-
-  // Cause heapprofd to emit a single dump at the end, showing the memory usage
-  // at the point in time when the sampled heap usage of the process was at its
-  // maximum. This causes ProfilePacket.HeapSample.self_max to be set, and
-  // self_allocated and self_freed to not be set.
-  optional bool dump_at_max = 13;
 }
 
 // End of protos/perfetto/config/profiling/heapprofd_config.proto
 
-// Begin of protos/perfetto/config/profiling/java_hprof_config.proto
-
-// Configuration for go/heapprofd.
-message JavaHprofConfig {
-  // If dump_interval_ms != 0, the following configuration is used.
-  message ContinuousDumpConfig {
-    // ms to wait before first continuous dump.
-    // A dump is always created at the beginning of the trace.
-    optional uint32 dump_phase_ms = 1;
-    // ms to wait between following dumps.
-    optional uint32 dump_interval_ms = 2;
-  }
-
-  // This input is normalized in the following way: if it contains slashes,
-  // everything up to the last slash is discarded. If it contains "@",
-  // everything after the first @ is discared.
-  // E.g. /system/bin/surfaceflinger@1.0 normalizes to surfaceflinger.
-  // This transformation is also applied to the processes' command lines when
-  // matching.
-  repeated string process_cmdline = 1;
-
-  // For watermark based triggering or local debugging.
-  repeated uint64 pid = 2;
-
-  // Dump at a predefined interval.
-  optional ContinuousDumpConfig continuous_dump_config = 3;
-}
-
-// End of protos/perfetto/config/profiling/java_hprof_config.proto
-
-// Begin of protos/perfetto/config/gpu/gpu_counter_config.proto
-
-message GpuCounterConfig {
-  // Desired sampling interval for counters.
-  optional uint64 counter_period_ns = 1;
-
-  // List of counters to be sampled. Counter IDs correspond to the ones
-  // described in GpuCounterSpec in the data source descriptor.
-  repeated uint32 counter_ids = 2;
-
-  // Sample counters by instrumenting command buffers.
-  optional bool instrumented_sampling = 3;
-
-  // Fix gpu clock rate during trace session.
-  optional bool fix_gpu_clock = 4;
-}
-
-// End of protos/perfetto/config/gpu/gpu_counter_config.proto
-
 // Begin of protos/perfetto/config/android/packages_list_config.proto
 
 // Data source that lists details (such as version code) about packages on an
diff --git a/protos/perfetto/trace/power/BUILD.gn b/protos/perfetto/trace/power/BUILD.gn
index 5664f2d..6c6e88a6 100644
--- a/protos/perfetto/trace/power/BUILD.gn
+++ b/protos/perfetto/trace/power/BUILD.gn
@@ -12,11 +12,22 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import("../../../../gn/perfetto.gni")
 import("../../../../gn/proto_library.gni")
+import("../../../../gn/protozero_library.gni")
 
-perfetto_proto_library("@TYPE@") {
-  sources = [
-    "battery_counters.proto",
-    "power_rails.proto",
-  ]
+profiling_proto_names = [ "battery_counters.proto", "power_rails.proto" ]
+
+proto_library("lite") {
+  generate_python = false
+  sources = profiling_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+}
+
+protozero_library("zero") {
+  sources = profiling_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  generator_plugin_options = "wrapper_namespace=pbzero"
 }
diff --git a/protos/perfetto/trace/power/power_rails.proto b/protos/perfetto/trace/power/power_rails.proto
index d4a718c..39486fc 100644
--- a/protos/perfetto/trace/power/power_rails.proto
+++ b/protos/perfetto/trace/power/power_rails.proto
@@ -23,14 +23,11 @@
   message RailDescriptor {
     // Index corresponding to the rail
     optional uint32 index = 1;
-
     // Name of the rail
     optional string rail_name = 2;
-
     // Name of the subsystem to which this rail belongs
     optional string subsys_name = 3;
-
-    // Hardware sampling rate (Hz).
+    // Hardware sampling rate
     optional uint32 sampling_rate = 4;
   }
 
@@ -40,11 +37,9 @@
   message EnergyData {
     // Index corresponding to RailDescriptor.index
     optional uint32 index = 1;
-
-    // Time since device boot(CLOCK_BOOTTIME) in milli-seconds.
+    // Time since device boot(CLOCK_BOOTTIME) in milli-seconds
     optional uint64 timestamp_ms = 2;
-
-    // Accumulated energy since device boot in microwatt-seconds (uWs).
+    // Accumulated energy since device boot in microwatt-seconds (uWs)
     optional uint64 energy = 3;
   }
 
diff --git a/protos/perfetto/trace/profiling/BUILD.gn b/protos/perfetto/trace/profiling/BUILD.gn
index 3b607a2..a16d5eb 100644
--- a/protos/perfetto/trace/profiling/BUILD.gn
+++ b/protos/perfetto/trace/profiling/BUILD.gn
@@ -12,12 +12,22 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import("../../../../gn/perfetto.gni")
 import("../../../../gn/proto_library.gni")
+import("../../../../gn/protozero_library.gni")
 
-perfetto_proto_library("@TYPE@") {
-  sources = [
-    "heap_graph.proto",
-    "profile_common.proto",
-    "profile_packet.proto",
-  ]
+profiling_proto_names = [ "profile_packet.proto" ]
+
+proto_library("lite") {
+  generate_python = false
+  sources = profiling_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+}
+
+protozero_library("zero") {
+  sources = profiling_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  generator_plugin_options = "wrapper_namespace=pbzero"
 }
diff --git a/protos/perfetto/trace/profiling/heap_graph.proto b/protos/perfetto/trace/profiling/heap_graph.proto
deleted file mode 100644
index d29c292..0000000
--- a/protos/perfetto/trace/profiling/heap_graph.proto
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-import "protos/perfetto/trace/profiling/profile_common.proto";
-
-// These messages encode a graph of objects that retain one another. Currently
-// this is used for Android Runtime (i.e. Java and Kotlin) heap graphs.
-
-package perfetto.protos;
-
-message HeapGraphRoot {
-  enum Type {
-    ROOT_UNKNOWN = 0;
-    ROOT_JNI_GLOBAL = 1;
-    ROOT_JNI_LOCAL = 2;
-    ROOT_JAVA_FRAME = 3;
-    ROOT_NATIVE_STACK = 4;
-    ROOT_STICKY_CLASS = 5;
-    ROOT_THREAD_BLOCK = 6;
-    ROOT_MONITOR_USED = 7;
-    ROOT_THREAD_OBJECT = 8;
-    ROOT_INTERNED_STRING = 9;
-    ROOT_FINALIZING = 10;
-    ROOT_DEBUGGER = 11;
-    ROOT_REFERENCE_CLEANUP = 12;
-    ROOT_VM_INTERNAL = 13;
-    ROOT_JNI_MONITOR = 14;
-  };
-  // Objects retained by this root.
-  repeated uint64 object_ids = 1;
-
-  optional Type root_type = 2;
-}
-
-message HeapGraphObject {
-  optional uint64 id = 1;
-
-  // Index for InternedData.type_names for the name of the type of this object.
-  optional uint64 type_id = 2;
-
-  // Bytes occupied by this objects.
-  optional uint64 self_size = 3;
-
-  // Indices for InternedData.field_names for the name of the field referring
-  // to the object.
-  repeated uint64 reference_field_id = 4;
-
-  // Ids of the Object that is referred to.
-  repeated uint64 reference_object_id = 5;
-}
-
-message HeapGraph {
-  optional int32 pid = 1;
-
-  // This contains all objects at the time this dump was taken. Some of these
-  // will be live, some of those unreachable (garbage). To find the live
-  // objects, the client needs to build the transitive closure of objects
-  // reachable from |roots|.
-  // All objects not contained within that transitive closure are garbage that
-  // has not yet been collected.
-  repeated HeapGraphObject objects = 2;
-
-  // Roots at the time this dump was taken.
-  // All live objects are reachable from the roots. All other objects are
-  // garbage.
-  repeated HeapGraphRoot roots = 7;
-
-  // Type names used in managed heap graph.
-  repeated InternedString type_names = 3;
-
-  // Field names for references in managed heap graph.
-  repeated InternedString field_names = 4;
-
-  optional bool continued = 5;
-  optional uint64 index = 6;
-}
diff --git a/protos/perfetto/trace/profiling/profile_common.proto b/protos/perfetto/trace/profiling/profile_common.proto
deleted file mode 100644
index 9b88de2..0000000
--- a/protos/perfetto/trace/profiling/profile_common.proto
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-// TODO(fmayer): Figure out naming thoroughout this file to get a
-// nomenclature that works between Windows and Linux.
-
-// The interning fields in this file can refer to 2 different intern tables,
-// depending on the message they are used in. If the interned fields are present
-// in ProfilePacket proto, then the intern tables included in the ProfilePacket
-// should be used. If the intered fields are present in the
-// StreamingProfilePacket proto, then the intern tables included in all of the
-// previous InternedData message with same sequence ID should be used.
-// TODO(fmayer): Move to the intern tables to a common location.
-message InternedString {
-  optional uint64 iid = 1;
-  optional bytes str = 2;
-}
-
-// A symbol field that is emitted after the trace is written. These tables would
-// be appended as the last packets in the trace that the profiler will use, so
-// that the actual trace need not be rewritten to symbolize the profiles.
-message ProfiledFrameSymbols {
-  // Use the frame id as the interning key for the symbols.
-  optional uint64 frame_iid = 1;
-
-  // These are repeated because when inlining happens, multiple functions'
-  // frames can be at a single address. Imagine function Foo calling the
-  // std::vector<int> constructor, which gets inlined at 0xf00. We then get
-  // both Foo and the std::vector<int> constructor when we symbolize the
-  // address.
-  repeated uint64 function_name_id = 2;  // key to InternedString
-  repeated uint64 file_name_id = 3;      // key to InternedString
-  repeated uint32 line_number = 4;
-}
-
-message Line {
-  optional string function_name = 1;
-  optional string source_file_name = 2;
-  optional uint32 line_number = 3;
-}
-
-// Symbols for a given address in a module.
-message AddressSymbols {
-  optional uint64 address = 1;
-
-  // Source lines that correspond to this address.
-  //
-  // These are repeated because when inlining happens, multiple functions'
-  // frames can be at a single address. Imagine function Foo calling the
-  // std::vector<int> constructor, which gets inlined at 0xf00. We then get
-  // both Foo and the std::vector<int> constructor when we symbolize the
-  // address.
-  repeated Line lines = 2;
-}
-
-// Symbols for addresses seen in a module.
-message ModuleSymbols {
-  // Fully qualified path to the mapping.
-  // E.g. /system/lib64/libc.so.
-  optional string path = 1;
-
-  // .note.gnu.build-id on Linux (not hex encoded).
-  // uuid on MacOS.
-  // Module GUID on Windows.
-  optional string build_id = 2;
-  repeated AddressSymbols address_symbols = 3;
-}
-
-message Mapping {
-  optional uint64 iid = 1;       // Interning key.
-  optional uint64 build_id = 2;  // Interning key.
-
-  // The linker may create multiple memory mappings for the same shared
-  // library.
-  // This is so that the ELF header is mapped as read only, while the
-  // executable memory is mapped as executable only.
-  // The details of this depend on the linker, a possible mapping of an ELF
-  // file is this:
-  //         +----------------------+
-  // ELF     |xxxxxxxxxyyyyyyyyyyyyy|
-  //         +---------+------------+
-  //         |         |
-  //         | read    | executable
-  //         v mapping v mapping
-  //         +----------------------+
-  // Memory  |xxxxxxxxx|yyyyyyyyyyyy|
-  //         +------------------+---+
-  //         ^         ^        ^
-  //         +         +        +
-  //       start     exact    relpc
-  //       offset   offset    0x1800
-  //       0x0000   0x1000
-  //
-  // exact_offset is the offset into the library file of this mapping.
-  // start_offset is the offset into the library file of the first mapping
-  // for that library. For native libraries (.so files) this should be 0.
-  optional uint64 exact_offset = 8;  // This is not set on Android 10.
-  optional uint64 start_offset = 3;
-  optional uint64 start = 4;
-  optional uint64 end = 5;
-  optional uint64 load_bias = 6;
-  // E.g. ["system", "lib64", "libc.so"]
-  repeated uint64 path_string_ids = 7;  // id of string.
-}
-
-message Frame {
-  optional uint64 iid = 1;  // Interning key
-  // E.g. "fopen"
-  optional uint64 function_name_id = 2;  // id of string.
-  optional uint64 mapping_id = 3;
-  optional uint64 rel_pc = 4;
-}
-
-message Callstack {
-  optional uint64 iid = 1;
-  // Frames of this callstack. Bottom frame first.
-  repeated uint64 frame_ids = 2;
-}
diff --git a/protos/perfetto/trace/profiling/profile_packet.proto b/protos/perfetto/trace/profiling/profile_packet.proto
index 300e2b7..91046bf 100644
--- a/protos/perfetto/trace/profiling/profile_packet.proto
+++ b/protos/perfetto/trace/profiling/profile_packet.proto
@@ -17,45 +17,52 @@
 syntax = "proto2";
 option optimize_for = LITE_RUNTIME;
 
-import "protos/perfetto/trace/profiling/profile_common.proto";
-
 package perfetto.protos;
 
 message ProfilePacket {
-  // The following interning tables are only used in Android version Q.
-  // In newer versions, these tables are in InternedData
-  // (see protos/perfetto/trace/interned_data) and are shared across
-  // multiple ProfilePackets.
-  // For backwards compatibility, consumers need to first look up interned
-  // data in the tables within the ProfilePacket, and then, if they are empty,
-  // look up in the InternedData instead.
+  // either a function or library name.
   repeated InternedString strings = 1;
-  repeated Mapping mappings = 4;
-  repeated Frame frames = 2;
-  repeated Callstack callstacks = 3;
+  message InternedString {
+    optional uint64 id = 1;
+    optional bytes str = 2;
+  }
 
-  // Next ID: 9
+  repeated Mapping mappings = 4;
+  message Mapping {
+    optional uint64 id = 1;        // Interning key.
+    optional uint64 build_id = 2;  // Interning key.
+    optional uint64 offset = 3;
+    optional uint64 start = 4;
+    optional uint64 end = 5;
+    optional uint64 load_bias = 6;
+    // E.g. ["system", "lib64", "libc.so"]
+    repeated uint64 path_string_ids = 7;  // id of string.
+  }
+
+  repeated Frame frames = 2;
+  message Frame {
+    optional uint64 id = 1;  // Interning key
+    // E.g. "fopen"
+    optional uint64 function_name_id = 2;  // id of string.
+    optional uint64 mapping_id = 3;
+    optional uint64 rel_pc = 4;
+  }
+
+  repeated Callstack callstacks = 3;
+  message Callstack {
+    optional uint64 id = 1;
+    // Frames of this callstack. Bottom frame first.
+    repeated uint64 frame_ids = 2;
+  }
+
   message HeapSample {
     optional uint64 callstack_id = 1;
-    // bytes allocated at this callstack.
+    // bytes allocated at this frame.
     optional uint64 self_allocated = 2;
-    // bytes allocated at this callstack that have been freed.
+    // bytes allocated at this frame that have been freed.
     optional uint64 self_freed = 3;
-    // bytes allocated at this callstack but not used since the last
-    // dump.
-    // See documentation of idle_allocations in HeapprofdConfig for more
-    // details.
-    optional uint64 self_idle = 7;
-    // Bytes allocated by this callstack but not freed at the time the malloc
-    // heap usage of this process was maximal. This is only set if dump_at_max
-    // is true in HeapprofdConfig. In that case, self_allocated, self_freed and
-    // self_idle will not be set.
-    optional uint64 self_max = 8;
     optional uint64 timestamp = 4;  // timestamp [opt]
-    // Number of allocations that were sampled at this callstack.
     optional uint64 alloc_count = 5;
-    // Number of allocations that were sampled at this callstack that have been
-    // freed.
     optional uint64 free_count = 6;
   }
 
@@ -120,27 +127,11 @@
     //               to have a type enum that we can reuse here.
     optional uint64 timestamp = 9;
 
-    // Metadata about heapprofd.
     optional ProcessStats stats = 5;
 
     repeated HeapSample samples = 2;
   }
 
-  // If this is true, the next ProfilePacket in this package_sequence_id is a
-  // continuation of this one.
-  // To get all samples for a process, accummulate its
-  // ProcessHeapSamples.samples until you see continued=false.
   optional bool continued = 6;
-
-  // Index of this ProfilePacket on its package_sequence_id. Can be used
-  // to detect dropped data.
-  // Verify these are consecutive.
   optional uint64 index = 7;
 }
-
-// Message used to represent individual stack samples sampled at discrete
-// points in time, rather than aggregated over an interval.
-message StreamingProfilePacket {
-  repeated uint64 callstack_iid = 1;  // Index into InternedData.callstacks
-  repeated int64 timestamp_delta_us = 2;
-}
diff --git a/protos/perfetto/trace/ps/BUILD.gn b/protos/perfetto/trace/ps/BUILD.gn
index 3f1bfe1..8d7cb40 100644
--- a/protos/perfetto/trace/ps/BUILD.gn
+++ b/protos/perfetto/trace/ps/BUILD.gn
@@ -12,11 +12,24 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../../gn/proto_library.gni")
+import("../../../../gn/perfetto.gni")
+import("../../../../gn/protozero_library.gni")
 
-perfetto_proto_library("@TYPE@") {
-  sources = [
-    "process_stats.proto",
-    "process_tree.proto",
-  ]
+ps_proto_names = [
+  "process_stats.proto",
+  "process_tree.proto",
+]
+
+proto_library("lite") {
+  generate_python = false
+  sources = ps_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+}
+
+protozero_library("zero") {
+  sources = ps_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  generator_plugin_options = "wrapper_namespace=pbzero"
 }
diff --git a/protos/perfetto/trace/ps/process_tree.proto b/protos/perfetto/trace/ps/process_tree.proto
index 14d3b6d..cf83d12 100644
--- a/protos/perfetto/trace/ps/process_tree.proto
+++ b/protos/perfetto/trace/ps/process_tree.proto
@@ -47,9 +47,6 @@
     // No longer used as of Apr 2018, when the dedicated |threads| field was
     // introduced in ProcessTree.
     repeated Thread threads_deprecated = 4 [deprecated = true];
-
-    // The uid for the process, as per /proc/pid/status.
-    optional int32 uid = 5;
   }
 
   // List of processes and threads in the client. These lists are incremental
diff --git a/protos/perfetto/trace/sys_stats/BUILD.gn b/protos/perfetto/trace/sys_stats/BUILD.gn
index aa79c47..27461fb 100644
--- a/protos/perfetto/trace/sys_stats/BUILD.gn
+++ b/protos/perfetto/trace/sys_stats/BUILD.gn
@@ -12,13 +12,27 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../../gn/proto_library.gni")
+import("../../../../gn/perfetto.gni")
+import("../../../../gn/protozero_library.gni")
 
-perfetto_proto_library("@TYPE@") {
+sys_stats_proto_names = [ "sys_stats.proto" ]
+
+proto_library("lite") {
+  generate_python = false
   deps = [
-    "../../common:@TYPE@",
+    "../../common:lite",
   ]
-  sources = [
-    "sys_stats.proto",
+  sources = sys_stats_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+}
+
+protozero_library("zero") {
+  deps = [
+    "../../common:zero",
   ]
+  sources = sys_stats_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  generator_plugin_options = "wrapper_namespace=pbzero"
 }
diff --git a/protos/perfetto/trace/sys_stats/sys_stats.proto b/protos/perfetto/trace/sys_stats/sys_stats.proto
index ad7db64..4b10ecf 100644
--- a/protos/perfetto/trace/sys_stats/sys_stats.proto
+++ b/protos/perfetto/trace/sys_stats/sys_stats.proto
@@ -18,7 +18,7 @@
 option optimize_for = LITE_RUNTIME;
 package perfetto.protos;
 
-import "protos/perfetto/common/sys_stats_counters.proto";
+import "perfetto/common/sys_stats_counters.proto";
 
 // Various Linux system stat counters from /proc.
 // The fields in this message can be reported at different rates and with
diff --git a/protos/perfetto/trace/trace.proto b/protos/perfetto/trace/trace.proto
index fa8677e..835acc5 100644
--- a/protos/perfetto/trace/trace.proto
+++ b/protos/perfetto/trace/trace.proto
@@ -17,7 +17,7 @@
 syntax = "proto2";
 option optimize_for = LITE_RUNTIME;
 
-import "protos/perfetto/trace/trace_packet.proto";
+import "perfetto/trace/trace_packet.proto";
 
 package perfetto.protos;
 
diff --git a/protos/perfetto/trace/trace_packet.proto b/protos/perfetto/trace/trace_packet.proto
index b23c98b..6482d26 100644
--- a/protos/perfetto/trace/trace_packet.proto
+++ b/protos/perfetto/trace/trace_packet.proto
@@ -17,40 +17,28 @@
 syntax = "proto2";
 option optimize_for = LITE_RUNTIME;
 
-import "protos/perfetto/common/trace_stats.proto";
-import "protos/perfetto/config/trace_config.proto";
-import "protos/perfetto/trace/android/android_log.proto";
-import "protos/perfetto/trace/android/graphics_frame_event.proto";
-import "protos/perfetto/trace/android/packages_list.proto";
-import "protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto";
-import "protos/perfetto/trace/chrome/chrome_metadata.proto";
-import "protos/perfetto/trace/chrome/chrome_trace_event.proto";
-import "protos/perfetto/trace/clock_snapshot.proto";
-import "protos/perfetto/trace/filesystem/inode_file_map.proto";
-import "protos/perfetto/trace/ftrace/ftrace_event_bundle.proto";
-import "protos/perfetto/trace/ftrace/ftrace_stats.proto";
-import "protos/perfetto/trace/gpu/gpu_counter_event.proto";
-import "protos/perfetto/trace/gpu/gpu_log.proto";
-import "protos/perfetto/trace/gpu/gpu_render_stage_event.proto";
-import "protos/perfetto/trace/gpu/vulkan_memory_event.proto";
-import "protos/perfetto/trace/interned_data/interned_data.proto";
-import "protos/perfetto/trace/perfetto/perfetto_metatrace.proto";
-import "protos/perfetto/trace/power/battery_counters.proto";
-import "protos/perfetto/trace/power/power_rails.proto";
-import "protos/perfetto/trace/profiling/heap_graph.proto";
-import "protos/perfetto/trace/profiling/profile_common.proto";
-import "protos/perfetto/trace/profiling/profile_packet.proto";
-import "protos/perfetto/trace/ps/process_stats.proto";
-import "protos/perfetto/trace/ps/process_tree.proto";
-import "protos/perfetto/trace/sys_stats/sys_stats.proto";
-import "protos/perfetto/trace/system_info.proto";
-import "protos/perfetto/trace/trace_packet_defaults.proto";
-import "protos/perfetto/trace/track_event/process_descriptor.proto";
-import "protos/perfetto/trace/track_event/thread_descriptor.proto";
-import "protos/perfetto/trace/track_event/track_descriptor.proto";
-import "protos/perfetto/trace/track_event/track_event.proto";
-import "protos/perfetto/trace/trigger.proto";
-import "protos/perfetto/trace/test_event.proto";
+import "perfetto/common/trace_stats.proto";
+import "perfetto/config/trace_config.proto";
+import "perfetto/trace/android/android_log.proto";
+import "perfetto/trace/android/packages_list.proto";
+import "perfetto/trace/chrome/chrome_trace_event.proto";
+import "perfetto/trace/clock_snapshot.proto";
+import "perfetto/trace/filesystem/inode_file_map.proto";
+import "perfetto/trace/ftrace/ftrace_event_bundle.proto";
+import "perfetto/trace/ftrace/ftrace_stats.proto";
+import "perfetto/trace/interned_data/interned_data.proto";
+import "perfetto/trace/power/battery_counters.proto";
+import "perfetto/trace/power/power_rails.proto";
+import "perfetto/trace/profiling/profile_packet.proto";
+import "perfetto/trace/ps/process_stats.proto";
+import "perfetto/trace/ps/process_tree.proto";
+import "perfetto/trace/sys_stats/sys_stats.proto";
+import "perfetto/trace/system_info.proto";
+import "perfetto/trace/track_event/process_descriptor.proto";
+import "perfetto/trace/track_event/thread_descriptor.proto";
+import "perfetto/trace/track_event/track_event.proto";
+import "perfetto/trace/trigger.proto";
+import "perfetto/trace/test_event.proto";
 
 package perfetto.protos;
 
@@ -58,22 +46,11 @@
 // TracePacket(s).
 //
 // Next reserved id: 13 (up to 15).
-// Next id: 64.
+// Next id: 51.
 message TracePacket {
-  // The timestamp of the TracePacket.
-  // By default this timestamps refers to the trace clock (CLOCK_BOOTTIME on
-  // Android). It can be overridden using a different timestamp_clock_id.
-  // The clock domain definition in ClockSnapshot can also override:
-  // - The unit (default: 1ns).
-  // - The absolute vs delta encoding (default: absolute timestamp).
-  optional uint64 timestamp = 8;
-
-  // Specifies the ID of the clock used for the TracePacket |timestamp|. Can be
-  // one of the built-in types from ClockSnapshot::BuiltinClocks, or a
-  // producer-defined clock id.
-  // If unspecified and if no default per-sequence value has been provided via
-  // TracePacketDefaults, it defaults to BuiltinClocks::BOOTTIME.
-  optional uint32 timestamp_clock_id = 58;
+  // TODO(primiano): in future we should add a timestamp_clock_domain field to
+  // allow mixing timestamps from different clock domains.
+  optional uint64 timestamp = 8;  // Timestamp [ns].
 
   oneof data {
     FtraceEventBundle ftrace_events = 1;
@@ -98,28 +75,9 @@
     SystemInfo system_info = 45;
     Trigger trigger = 46;
     PackagesList packages_list = 47;
-    ChromeBenchmarkMetadata chrome_benchmark_metadata = 48;
-    PerfettoMetatrace perfetto_metatrace = 49;
-    ChromeMetadataPacket chrome_metadata = 51;
-    GpuCounterEvent gpu_counter_event = 52;
-    GpuRenderStageEvent gpu_render_stage_event = 53;
-    StreamingProfilePacket streaming_profile_packet = 54;
-    HeapGraph heap_graph = 56;
-    GraphicsFrameEvent graphics_frame_event = 57;
-    VulkanMemoryEvent vulkan_memory_event = 62;
-    GpuLog gpu_log = 63;
-
-    // Only used in profile packets.
-    ProfiledFrameSymbols profiled_frame_symbols = 55;
-    ModuleSymbols module_symbols = 61;
 
     // Only used by TrackEvent.
-    TrackDescriptor track_descriptor = 60;
-
-    // Deprecated, use TrackDescriptor instead.
     ProcessDescriptor process_descriptor = 43;
-
-    // Deprecated, use TrackDescriptor instead.
     ThreadDescriptor thread_descriptor = 44;
 
     // This field is emitted at periodic intervals (~10s) and
@@ -164,48 +122,22 @@
   // proactively in advance of referring to them in later packets.
   optional InternedData interned_data = 12;
 
-
-  enum SequenceFlags {
-    SEQ_UNSPECIFIED = 0;
-
-    // Set by the writer to indicate that it will re-emit any incremental data
-    // for the packet's sequence before referring to it again. This includes
-    // interned data as well as periodically emitted data like
-    // Process/ThreadDescriptors. This flag only affects the current packet
-    // sequence (see |trusted_packet_sequence_id|).
-    //
-    // When set, this TracePacket and subsequent TracePackets on the same
-    // sequence will not refer to any incremental data emitted before this
-    // TracePacket. For example, previously emitted interned data will be
-    // re-emitted if it is referred to again.
-    //
-    // When the reader detects packet loss (|previous_packet_dropped|), it needs
-    // to skip packets in the sequence until the next one with this flag set, to
-    // ensure intact incremental data.
-    SEQ_INCREMENTAL_STATE_CLEARED = 1;
-
-    // This packet requires incremental state, such as TracePacketDefaults or
-    // InternedData, to be parsed correctly. The trace reader should skip this
-    // packet if incremental state is not valid on this sequence, i.e. if no
-    // packet with the SEQ_INCREMENTAL_STATE_CLEARED flag has been seen on the
-    // current |trusted_packet_sequence_id|.
-    SEQ_NEEDS_INCREMENTAL_STATE = 2;
-  };
-  optional uint32 sequence_flags = 13;
-
-  // DEPRECATED. Moved to SequenceFlags::SEQ_INCREMENTAL_STATE_CLEARED.
+  // Set to true by the writer to indicate that it will re-emit any incremental
+  // data for the packet's sequence before referring to it again. This includes
+  // interned data as well as periodically emitted data like
+  // Process/ThreadDescriptors. This flag only affects the current packet
+  // sequence (see |trusted_packet_sequence_id|).
+  //
+  // When set to true, this TracePacket and subsequent TracePackets on the same
+  // sequence will not refer to any incremental data emitted before this
+  // TracePacket. For example, previously emitted interned data will be
+  // re-emitted if it is referred to again.
+  //
+  // When the reader detects packet loss (|previous_packet_dropped|), it needs
+  // to skip packets in the sequence until the next one with this flag set, to
+  // ensure intact incremental data.
   optional bool incremental_state_cleared = 41;
 
-  // Default values for fields of later TracePackets emitted on this packet's
-  // sequence (TracePackets with the same |trusted_packet_sequence_id|).
-  // It must be reemitted when incremental state is cleared (see
-  // |incremental_state_cleared|).
-  // Requires that any future packet emitted on the same sequence specifies
-  // the SEQ_NEEDS_INCREMENTAL_STATE flag.
-  // TracePacketDefaults always override the global defaults for any future
-  // packet on this sequence (regardless of SEQ_NEEDS_INCREMENTAL_STATE).
-  optional TracePacketDefaults trace_packet_defaults = 59;
-
   // Flag set by the service if, for the current packet sequence (see
   // |trusted_packet_sequence_id|), either:
   // * this is the first packet, or
@@ -216,6 +148,6 @@
   //
   // When packet loss occurs, incrementally emitted data (including interned
   // data) on the sequence should be considered invalid up until the next packet
-  // with SEQ_INCREMENTAL_STATE_CLEARED set.
+  // with |incremental_state_cleared| set.
   optional bool previous_packet_dropped = 42;
 }
diff --git a/protos/perfetto/trace/trace_packet_defaults.proto b/protos/perfetto/trace/trace_packet_defaults.proto
deleted file mode 100644
index b6f3e83..0000000
--- a/protos/perfetto/trace/trace_packet_defaults.proto
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-import "protos/perfetto/trace/track_event/track_event.proto";
-
-package perfetto.protos;
-
-// Default values for TracePacket fields that hold for a particular TraceWriter
-// packet sequence. This message contains a subset of the TracePacket fields
-// with matching IDs. When provided, these fields define the default values
-// that should be applied, at import time, to all TracePacket(s) with the same
-// |trusted_packet_sequence_id|, unless otherwise specified in each packet.
-//
-// Should be reemitted whenever incremental state is cleared on the sequence.
-message TracePacketDefaults {
-  optional uint32 timestamp_clock_id = 58;
-
-  // Default values for TrackEvents (e.g. default track).
-  optional TrackEventDefaults track_event_defaults = 11;
-}
\ No newline at end of file
diff --git a/protos/perfetto/trace/track_event/BUILD.gn b/protos/perfetto/trace/track_event/BUILD.gn
index 929d51c..2646a09 100644
--- a/protos/perfetto/trace/track_event/BUILD.gn
+++ b/protos/perfetto/trace/track_event/BUILD.gn
@@ -12,17 +12,28 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import("../../../../gn/perfetto.gni")
 import("../../../../gn/proto_library.gni")
+import("../../../../gn/protozero_library.gni")
 
-perfetto_proto_library("@TYPE@") {
-  sources = [
-    "debug_annotation.proto",
-    "log_message.proto",
-    "process_descriptor.proto",
-    "source_location.proto",
-    "task_execution.proto",
-    "thread_descriptor.proto",
-    "track_descriptor.proto",
-    "track_event.proto",
-  ]
+event_proto_names = [
+  "debug_annotation.proto",
+  "process_descriptor.proto",
+  "task_execution.proto",
+  "thread_descriptor.proto",
+  "track_event.proto",
+]
+
+proto_library("lite") {
+  generate_python = false
+  sources = event_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+}
+
+protozero_library("zero") {
+  sources = event_proto_names
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
+  generator_plugin_options = "wrapper_namespace=pbzero"
 }
diff --git a/protos/perfetto/trace/track_event/debug_annotation.proto b/protos/perfetto/trace/track_event/debug_annotation.proto
index 1bbfaa9..8e06a7c 100644
--- a/protos/perfetto/trace/track_event/debug_annotation.proto
+++ b/protos/perfetto/trace/track_event/debug_annotation.proto
@@ -22,8 +22,6 @@
 // Key/value annotations provided in untyped TRACE_EVENT macros. These
 // annotations are intended for debug use and are not considered a stable API
 // surface. As such, they should not be relied upon to implement (new) metrics.
-//
-// Next ID: 10.
 message DebugAnnotation {
   message NestedValue {
     enum NestedType {
@@ -42,10 +40,7 @@
     optional string string_value = 8;
   }
 
-  oneof name_field {
-    uint64 name_iid = 1;  // interned DebugAnnotationName.
-    string name = 10;     // non-interned variant.
-  }
+  optional uint32 name_iid = 1;  // interned DebugAnnotationName.
 
   oneof value {
     bool bool_value = 2;
@@ -69,6 +64,6 @@
 // --------------------
 
 message DebugAnnotationName {
-  optional uint64 iid = 1;
+  optional uint32 iid = 1;
   optional string name = 2;
 }
diff --git a/protos/perfetto/trace/track_event/log_message.proto b/protos/perfetto/trace/track_event/log_message.proto
deleted file mode 100644
index a2fde6d..0000000
--- a/protos/perfetto/trace/track_event/log_message.proto
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-message LogMessage {
-  optional uint64 source_location_iid = 1;  // interned SourceLocation.
-  optional uint64 body_iid = 2;             // interned LogMessageBody.
-}
-
-// --------------------
-// Interned data types:
-// --------------------
-
-message LogMessageBody {
-  optional uint64 iid = 1;
-  optional string body = 2;
-}
\ No newline at end of file
diff --git a/protos/perfetto/trace/track_event/process_descriptor.proto b/protos/perfetto/trace/track_event/process_descriptor.proto
index cc60936..b16bca9 100644
--- a/protos/perfetto/trace/track_event/process_descriptor.proto
+++ b/protos/perfetto/trace/track_event/process_descriptor.proto
@@ -19,14 +19,17 @@
 
 package perfetto.protos;
 
-// Describes a process's attributes. Emitted as part of a TrackDescriptor,
-// usually by the process's main thread.
+// Process-wide data that is periodically emitted by one thread per process.
+// Valid for all events in packet sequences emitted by the same process.
 //
 // Next id: 5.
 message ProcessDescriptor {
   optional int32 pid = 1;
   repeated string cmdline = 2;
 
+  // To support old UI. New UI should determine default sorting by process_type.
+  optional int32 legacy_sort_index = 3;
+
   // See chromium's content::ProcessType.
   enum ChromeProcessType {
     PROCESS_UNSPECIFIED = 0;
@@ -40,8 +43,4 @@
     PROCESS_PPAPI_BROKER = 8;
   }
   optional ChromeProcessType chrome_process_type = 4;
-  optional int32 process_priority = 5;
-
-  // To support old UI. New UI should determine default sorting by process_type.
-  optional int32 legacy_sort_index = 3;
 }
diff --git a/protos/perfetto/trace/track_event/source_location.proto b/protos/perfetto/trace/track_event/source_location.proto
deleted file mode 100644
index 39d6bb1..0000000
--- a/protos/perfetto/trace/track_event/source_location.proto
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-// --------------------
-// Interned data types:
-// --------------------
-
-message SourceLocation {
-  optional uint64 iid = 1;
-
-  // We intend to add a binary symbol version of this in the future.
-  optional string file_name = 2;
-  optional string function_name = 3;
-  optional uint32 line_number = 4;
-}
diff --git a/protos/perfetto/trace/track_event/task_execution.proto b/protos/perfetto/trace/track_event/task_execution.proto
index 6eebad9..a4964f8 100644
--- a/protos/perfetto/trace/track_event/task_execution.proto
+++ b/protos/perfetto/trace/track_event/task_execution.proto
@@ -22,5 +22,17 @@
 // TrackEvent arguments describing the execution of a task.
 message TaskExecution {
   // Source location that the task was posted from.
-  optional uint64 posted_from_iid = 1;  // interned SourceLocation.
-}
\ No newline at end of file
+  optional uint32 posted_from_iid = 1;  // interned SourceLocation.
+}
+
+// --------------------
+// Interned data types:
+// --------------------
+
+message SourceLocation {
+  optional uint32 iid = 1;
+
+  // We intend to add a binary symbol version of this in the future.
+  optional string file_name = 2;
+  optional string function_name = 3;
+}
diff --git a/protos/perfetto/trace/track_event/thread_descriptor.proto b/protos/perfetto/trace/track_event/thread_descriptor.proto
index b2d2cb6..d8648ff 100644
--- a/protos/perfetto/trace/track_event/thread_descriptor.proto
+++ b/protos/perfetto/trace/track_event/thread_descriptor.proto
@@ -19,58 +19,30 @@
 
 package perfetto.protos;
 
-// Describes a thread's attributes. Emitted as part of a TrackDescriptor,
-// usually by the thread's trace writer.
+// Periodically emitted data that's common to all events emitted by the same
+// thread, i.e. all events in the same packet sequence. Valid for all subsequent
+// events in the same sequence.
 //
-// Next id: 9.
+// Next id: 8.
 message ThreadDescriptor {
   optional int32 pid = 1;
   optional int32 tid = 2;
 
-  optional string thread_name = 5;
+  // To support old UI. New UI should determine default sorting by thread_type.
+  optional int32 legacy_sort_index = 3;
 
   enum ChromeThreadType {
-    CHROME_THREAD_UNSPECIFIED = 0;
-
-    CHROME_THREAD_MAIN = 1;
-    CHROME_THREAD_IO = 2;
-
-    // Scheduler:
-    CHROME_THREAD_POOL_BG_WORKER = 3;
-    CHROME_THREAD_POOL_FG_WORKER = 4;
-    CHROME_THREAD_POOL_FB_BLOCKING = 5;
-    CHROME_THREAD_POOL_BG_BLOCKING = 6;
-    CHROME_THREAD_POOL_SERVICE = 7;
-
-    // Compositor:
-    CHROME_THREAD_COMPOSITOR = 8;
-    CHROME_THREAD_VIZ_COMPOSITOR = 9;
-    CHROME_THREAD_COMPOSITOR_WORKER = 10;
-
-    // Renderer:
-    CHROME_THREAD_SERVICE_WORKER = 11;
-
-    // Tracing related threads:
-    CHROME_THREAD_MEMORY_INFRA = 50;
-    CHROME_THREAD_SAMPLING_PROFILER = 51;
+    THREAD_UNSPECIFIED = 0;
+    // TODO(eseckler): Add thread types.
   };
   optional ChromeThreadType chrome_thread_type = 4;
 
-  // ---------------------------------------------------------------------------
-  // Deprecated / legacy fields, which will be removed in the future:
-  // ---------------------------------------------------------------------------
-
-  // Deprecated. Use ClockSnapshot in combination with TracePacket's timestamp
-  // and timestamp_clock_id fields instead.
-  optional int64 reference_timestamp_us = 6;
+  // TODO(eseckler): Replace this with ChromeThreadType where possible.
+  optional string thread_name = 5;
 
   // Absolute reference values. Clock values in subsequent TrackEvents can be
   // encoded accumulatively and relative to these. This reduces their var-int
   // encoding size.
-  // TODO(eseckler): Deprecated. Replace these with ClockSnapshot encoding.
+  optional int64 reference_timestamp_us = 6;
   optional int64 reference_thread_time_us = 7;
-  optional int64 reference_thread_instruction_count = 8;
-
-  // To support old UI. New UI should determine default sorting by thread_type.
-  optional int32 legacy_sort_index = 3;
 }
diff --git a/protos/perfetto/trace/track_event/track_descriptor.proto b/protos/perfetto/trace/track_event/track_descriptor.proto
deleted file mode 100644
index a9ba7be..0000000
--- a/protos/perfetto/trace/track_event/track_descriptor.proto
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-import "protos/perfetto/trace/track_event/process_descriptor.proto";
-import "protos/perfetto/trace/track_event/thread_descriptor.proto";
-
-package perfetto.protos;
-
-// Defines a track for TrackEvents. Slices and instant events on the same track
-// will be nested based on their timestamps, see TrackEvent::Type.
-//
-// A TrackDescriptor only needs to be emitted by one trace writer / producer and
-// is valid for the entirety of the trace. To ensure the descriptor isn't lost
-// when the ring buffer wraps, it should be reemitted whenever incremental state
-// is cleared.
-//
-// As a fallback, TrackEvents emitted without an explicit track association will
-// be associated with an implicit trace-global track (uuid = 0), see also
-// |TrackEvent::track_uuid|. It is possible but not necessary to emit a
-// TrackDescriptor for this implicit track.
-//
-// Next id: 1.
-message TrackDescriptor {
-  // Unique ID that identifies this track. This ID is global to the whole trace.
-  // Producers should ensure that it is unlikely to clash with IDs emitted by
-  // other producers. A value of 0 denotes the implicit trace-global track.
-  //
-  // For example, legacy TRACE_EVENT macros may use a hash involving the async
-  // event id + id_scope, pid, and/or tid to compute this ID.
-  optional uint64 uuid = 1;
-
-  // TODO(eseckler): Support track hierarchies.
-  // uint64 parent_uuid = X;
-
-  // Name of the track.
-  optional string name = 2;
-
-  // Associate the track with a process or thread - the UI will draw this track
-  // in the context of the process/thread.
-  optional ProcessDescriptor process = 3;
-  optional ThreadDescriptor thread = 4;
-}
diff --git a/protos/perfetto/trace/track_event/track_event.proto b/protos/perfetto/trace/track_event/track_event.proto
index c5bd588..6ee2409 100644
--- a/protos/perfetto/trace/track_event/track_event.proto
+++ b/protos/perfetto/trace/track_event/track_event.proto
@@ -17,175 +17,31 @@
 syntax = "proto2";
 option optimize_for = LITE_RUNTIME;
 
-import "protos/perfetto/trace/track_event/debug_annotation.proto";
-import "protos/perfetto/trace/track_event/log_message.proto";
-import "protos/perfetto/trace/track_event/task_execution.proto";
+import "perfetto/trace/track_event/debug_annotation.proto";
+import "perfetto/trace/track_event/task_execution.proto";
 
 package perfetto.protos;
 
-// NOTE: Full TrackEvent support in the client lib and chrome is WIP, thus these
-// protos are still subject to change. Don't depend on them staying as they are.
-
 // Trace events emitted by client instrumentation library (TRACE_EVENT macros),
-// which describe activity on a track, such as a thread or asynchronous event
-// track. The track is specified using separate TrackDescriptor messages and
-// referred to via the track's UUID.
+// which describe activity on a track, such as a thread, task sequence, or
+// asynchronous track.
 //
-// A simple TrackEvent packet specifies a timestamp, category, name and type:
-//   trace_packet {
-//     timestamp: 1000
-//     track_event {
-//       categories: ["my_cat"]
-//       name: "my_event"
-//       type: TYPE_INSTANT
-//      }
-//    }
+// This message is optimized for writing and makes heavy use of data interning
+// and delta encoding (e.g. of timestamps) to reduce data repetition and encoded
+// data size.
 //
-// To associate an event with a custom track (e.g. a thread), the track is
-// defined in a separate packet and referred to from the TrackEvent by its UUID:
-//   trace_packet {
-//     track_descriptor {
-//       track_uuid: 1234
-//       name: "my_track"
+// A TrackEvent exists in the context of its packet sequence (TracePackets
+// emitted by the same producer + writer) and refers to data in preceding
+// TracePackets emitted on the same sequence, both directly and indirectly. For
+// example, interned data entries are emitted as part of a TracePacket and
+// directly referred to from TrackEvents by their interning IDs. Attributes
+// shared by all events on the same sequence (e.g. their thread and process
+// association) are emitted as part of ProcessDescriptor and ThreadDescriptor
+// messages in separate TracePackets instead.
 //
-//       // Optionally, associate the track with a thread.
-//       thread_descriptor {
-//         pid: 10
-//         tid: 10
-//         ..
-//       }
-//     }
-//   }
-//
-// A pair of TYPE_SLICE_BEGIN and _END events form a slice on the track:
-//   trace_packet {
-//     timestamp: 1200
-//     track_event {
-//       track_uuid: 1234
-//       categories: ["my_cat"]
-//       name: "my_slice"
-//       type: TYPE_SLICE_BEGIN
-//     }
-//   }
-//   trace_packet {
-//     timestamp: 1400
-//     track_event {
-//       track_uuid: 1234
-//       type: TYPE_SLICE_END
-//     }
-//   }
-//
-// TrackEvents also support optimizations to reduce data repetition and encoded
-// data size, e.g. through data interning (names, categories, ...) and delta
-// encoding of timestamps/counters. For details, see the InternedData message.
-// Further, default values for attributes of events on the same sequence (e.g.
-// their default track association) can be emitted as part of a
-// TrackEventDefaults message.
-//
-// Next reserved id: 12 (up to 15). Next id: 24.
+// Next reserved id: 7 (up to 15).
+// Next id: 20.
 message TrackEvent {
-  // Names of categories of the event. In the client library, categories are a
-  // way to turn groups of individual events on or off.
-  repeated uint64 category_iids = 3;  // interned EventCategoryName.
-  repeated string categories = 22;    // non-interned variant.
-
-  // Optional name of the event for its display in trace viewer. May be left
-  // unspecified for events with typed arguments.
-  //
-  // Note that metrics should not rely on event names, as they are prone to
-  // changing. Instead, they should use typed arguments to identify the events
-  // they are interested in.
-  oneof name_field {
-    uint64 name_iid = 10;  // interned EventName.
-    string name = 23;      // non-interned variant.
-  }
-
-  // TODO(eseckler): Support using binary symbols for category/event names.
-
-  // Type of the TrackEvent (required if |phase| in LegacyEvent is not set).
-  enum Type {
-    TYPE_UNSPECIFIED = 0;
-
-    // Slice events are events that have a begin and end timestamp, i.e. a
-    // duration. They can be nested similar to a callstack: If, on the same
-    // track, event B begins after event A, but before A ends, B is a child
-    // event of A and will be drawn as a nested event underneath A in the UI.
-    // Note that child events should always end before their parents (e.g. B
-    // before A).
-    //
-    // Each slice event is formed by a pair of BEGIN + END events. The END event
-    // does not need to repeat any TrackEvent fields it has in common with its
-    // corresponding BEGIN event. Arguments and debug annotations of the BEGIN +
-    // END pair will be merged during trace import.
-    //
-    // Note that we deliberately chose not to support COMPLETE events (which
-    // would specify a duration directly) since clients would need to delay
-    // writing them until the slice is completed, which can result in reordered
-    // events in the trace and loss of unfinished events at the end of a trace.
-    TYPE_SLICE_BEGIN = 1;
-    TYPE_SLICE_END = 2;
-
-    // Instant events are nestable events without duration. They can be children
-    // of slice events on the same track.
-    TYPE_INSTANT = 3;
-
-    // TODO(eseckler): Add support for counters.
-  }
-  optional Type type = 9;
-
-  // Identifies the track of the event. The default value may be overridden
-  // using TrackEventDefaults, e.g., to specify the track of the TraceWriter's
-  // sequence (in most cases sequence = one thread). If no value is specified
-  // here or in TrackEventDefaults, the TrackEvent will be associated with an
-  // implicit trace-global track (uuid 0). See TrackDescriptor::uuid.
-  optional uint64 track_uuid = 11;
-
-  // TODO(eseckler): Add flow event support.
-
-  // TODO(eseckler): Encode thread_time and thread_instruction_count using a
-  // ClockSnapshot + clock id instead of ThreadDescriptor's reference values.
-
-  // CPU time for the current thread (e.g., CLOCK_THREAD_CPUTIME_ID) in
-  // microseconds.
-  oneof thread_time {
-    // Delta timestamp value since the last TrackEvent or ThreadDescriptor. To
-    // calculate the absolute timestamp value, sum up all delta values of the
-    // preceding TrackEvents since the last ThreadDescriptor and add the sum to
-    // the |reference_timestamp| in ThreadDescriptor. This value should always
-    // be positive.
-    int64 thread_time_delta_us = 2;
-    // This is a one-off absolute value that does not affect delta timestamp
-    // computation in subsequent TrackEvents.
-    int64 thread_time_absolute_us = 17;
-  }
-
-  // Value of the instruction counter for the current thread.
-  oneof thread_instruction_count {
-    // Same encoding as |thread_time| field above.
-    int64 thread_instruction_count_delta = 8;
-    int64 thread_instruction_count_absolute = 20;
-  }
-
-  // ---------------------------------------------------------------------------
-  // TrackEvent arguments:
-  // ---------------------------------------------------------------------------
-
-  // Unstable key/value annotations shown in the trace viewer but not intended
-  // for metrics use.
-  repeated DebugAnnotation debug_annotations = 4;
-
-  // Typed event arguments:
-  optional TaskExecution task_execution = 5;
-  optional LogMessage log_message = 21;
-  // New argument types go here :)
-
-  // ---------------------------------------------------------------------------
-  // Deprecated / legacy event fields, which will be removed in the future:
-  // ---------------------------------------------------------------------------
-
-  // Deprecated. Use the |timestamp| and |timestamp_clock_id| fields in
-  // TracePacket instead.
-  //
   // Timestamp in microseconds (usually CLOCK_MONOTONIC).
   oneof timestamp {
     // Delta timestamp value since the last TrackEvent or ThreadDescriptor. To
@@ -200,24 +56,44 @@
     int64 timestamp_absolute_us = 16;
   }
 
+  // CPU time for the current thread (e.g., CLOCK_THREAD_CPUTIME_ID) in
+  // microseconds.
+  oneof thread_time {
+    // Same encoding as |timestamp| fields above.
+    int64 thread_time_delta_us = 2;
+    // TODO(eseckler): Consider removing absolute thread time support. It's
+    // currently required to support writing PHASE_COMPLETE events out-of-order,
+    // but shouldn't be required anymore when we split them into begin/end.
+    int64 thread_time_absolute_us = 17;
+  }
+
+  // We intend to add a binary symbol version of this in the future.
+  repeated uint32 category_iids = 3;  // interned EventCategoryName.
+
+  // TODO(eseckler): May also want a debug_name for untyped debug-only events.
+
+  // Unstable key/value annotations shown in the trace viewer but not intended
+  // for metrics use.
+  repeated DebugAnnotation debug_annotations = 4;
+
+  // Typed event arguments:
+  optional TaskExecution task_execution = 5;
+  // TODO(eseckler): New argument types go here :)
+
   // Apart from {category, time, thread time, tid, pid}, other legacy trace
   // event attributes are initially simply proxied for conversion to a JSON
   // trace. We intend to gradually transition these attributes to similar native
   // features in TrackEvent (e.g. async + flow events), or deprecate them
   // without replacement where transition is unsuitable.
   //
-  // Next reserved id: 16 (up to 16).
+  // Next reserved id: 15 (up to 16).
   // Next id: 20.
   message LegacyEvent {
-    // Deprecated, use TrackEvent::name(_iid) instead.
-    optional uint64 name_iid = 1;  // interned EventName.
+    optional uint32 name_iid = 1;  // interned LegacyEventName.
     optional int32 phase = 2;
     optional int64 duration_us = 3;
     optional int64 thread_duration_us = 4;
 
-    // Elapsed retired instruction count during the event.
-    optional int64 thread_instruction_delta = 15;
-
     reserved 5;  // used to be |flags|.
 
     oneof id {
@@ -264,26 +140,16 @@
   optional LegacyEvent legacy_event = 6;
 }
 
-// Default values for fields of all TrackEvents on the same packet sequence.
-// Should be emitted as part of TracePacketDefaults whenever incremental state
-// is cleared. It's defined here because field IDs should match those of the
-// corresponding fields in TrackEvent.
-message TrackEventDefaults {
-  optional uint64 track_uuid = 10;
-
-  // TODO(eseckler): Support default values for more TrackEvent fields.
-}
-
 // --------------------
 // Interned data types:
 // --------------------
 
 message EventCategory {
-  optional uint64 iid = 1;
+  optional uint32 iid = 1;
   optional string name = 2;
 }
 
-message EventName {
-  optional uint64 iid = 1;
+message LegacyEventName {
+  optional uint32 iid = 1;
   optional string name = 2;
 }
diff --git a/protos/perfetto/trace/trusted_packet.proto b/protos/perfetto/trace/trusted_packet.proto
index 8316994..516766e 100644
--- a/protos/perfetto/trace/trusted_packet.proto
+++ b/protos/perfetto/trace/trusted_packet.proto
@@ -26,11 +26,11 @@
 syntax = "proto3";
 option optimize_for = LITE_RUNTIME;
 
-import "protos/perfetto/common/trace_stats.proto";
-import "protos/perfetto/config/trace_config.proto";
-import "protos/perfetto/trace/clock_snapshot.proto";
-import "protos/perfetto/trace/system_info.proto";
-import "protos/perfetto/trace/trigger.proto";
+import "perfetto/common/trace_stats.proto";
+import "perfetto/config/trace_config.proto";
+import "perfetto/trace/clock_snapshot.proto";
+import "perfetto/trace/system_info.proto";
+import "perfetto/trace/trigger.proto";
 
 package perfetto.protos;
 
diff --git a/protos/perfetto/trace_processor/BUILD.gn b/protos/perfetto/trace_processor/BUILD.gn
index e645a3a..7db997a 100644
--- a/protos/perfetto/trace_processor/BUILD.gn
+++ b/protos/perfetto/trace_processor/BUILD.gn
@@ -12,20 +12,16 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import("../../../gn/perfetto.gni")
 import("../../../gn/proto_library.gni")
 import("proto_files.gni")
 
-perfetto_proto_library("@TYPE@") {
-  proto_generators = [ "zero" ]
+proto_library("lite") {
+  generate_python = false
   sources = []
   foreach(source, trace_processor_protos) {
     sources += [ "$source.proto" ]
   }
-}
-
-perfetto_proto_library("metrics_impl_zero") {
-  proto_generators = [ "zero" ]
-  sources = [
-    "metrics_impl.proto",
-  ]
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
 }
diff --git a/protos/perfetto/trace_processor/metrics_impl.proto b/protos/perfetto/trace_processor/metrics_impl.proto
deleted file mode 100644
index 6ff42f5..0000000
--- a/protos/perfetto/trace_processor/metrics_impl.proto
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-package perfetto.protos;
-
-// The wrapping result of any metric builder function in trace processor. This
-// is an internal implementation detail of trace processor so should not be
-// relied on.
-message ProtoBuilderResult {
-  // Whether the result is a singular proto builder result or the result of
-  // a repeated field builder.
-  optional bool is_repeated = 1;
-  oneof result {
-    SingleBuilderResult single = 2;
-    RepeatedBuilderResult repeated = 3;
-  }
-}
-
-// The result of a repeated field function for a metric proto in trace
-// processor. This is an internal implementation detail of trace processor so
-// should not be relied on.
-message RepeatedBuilderResult {
-  message Value {
-    oneof data {
-      int64 int_value = 1;
-      string string_value = 2;
-      double double_value = 3;
-      bytes bytes_value = 4;
-    }
-  }
-  repeated Value value = 1;
-}
-
-// The result of a builder function for a metric proto in trace processor. This
-// is an internal implementation detail of trace processor so should not be
-// relied on.
-message SingleBuilderResult {
-  // The type of the result. The possible values are given by
-  // FieldDescriptorProto::Type.
-  optional uint32 type = 1;
-
-  // The type name of the result if the result is a message or enum type.
-  optional string type_name = 2;
-
-  // The raw proto bytes of a message.
-  optional bytes protobuf = 3;
-}
diff --git a/protos/perfetto/trace_processor/proto_files.gni b/protos/perfetto/trace_processor/proto_files.gni
index 246b803..20d1529 100644
--- a/protos/perfetto/trace_processor/proto_files.gni
+++ b/protos/perfetto/trace_processor/proto_files.gni
@@ -14,4 +14,8 @@
 
 # This variable is used both by ./BUILD.gn (for the C++ proto codegen) and by
 # //ui/BUIlD.gn (for the TypeScript/JS proto codegen).
-trace_processor_protos = [ "trace_processor" ]
+trace_processor_protos = [
+  "sched",
+  "raw_query",
+  "trace_processor",
+]
diff --git a/protos/perfetto/trace_processor/raw_query.proto b/protos/perfetto/trace_processor/raw_query.proto
new file mode 100644
index 0000000..904b902
--- /dev/null
+++ b/protos/perfetto/trace_processor/raw_query.proto
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package perfetto.protos;
+
+message RawQueryArgs {
+  optional string sql_query = 1;
+
+  // Wall time when the query was queued. Used only for query stats.
+  optional uint64 time_queued_ns = 2;
+}
+
+message RawQueryResult {
+  message ColumnDesc {
+    optional string name = 1;
+    enum Type {
+      UNKNOWN = 0;
+      LONG = 1;
+      DOUBLE = 2;
+      STRING = 3;
+    }
+    optional Type type = 2;
+  }
+  message ColumnValues {
+    // Only one of this field will be filled for each column (according to the
+    // corresponding descriptor) and that one will have precisely |num_records|
+    // elements.
+    repeated int64 long_values = 1;
+    repeated double double_values = 2;
+    repeated string string_values = 3;
+
+    // This will be set to true or false depending on whether the data at the
+    // given index is NULL.
+    repeated bool is_nulls = 4;
+  }
+  repeated ColumnDesc column_descriptors = 1;
+  optional uint64 num_records = 2;
+  repeated ColumnValues columns = 3;
+  optional string error = 4;
+  optional uint64 execution_time_ns = 5;
+}
diff --git a/protos/perfetto/trace_processor/sched.proto b/protos/perfetto/trace_processor/sched.proto
new file mode 100644
index 0000000..ba59999
--- /dev/null
+++ b/protos/perfetto/trace_processor/sched.proto
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package perfetto.protos;
+
+message Sched {
+  // TODO(primiano): fill in next CLs.
+  optional string test = 1;
+}
diff --git a/protos/perfetto/trace_processor/trace_processor.proto b/protos/perfetto/trace_processor/trace_processor.proto
index 45804b7..749dc7c 100644
--- a/protos/perfetto/trace_processor/trace_processor.proto
+++ b/protos/perfetto/trace_processor/trace_processor.proto
@@ -17,69 +17,10 @@
 syntax = "proto2";
 option optimize_for = LITE_RUNTIME;
 
-package perfetto.trace_processor.protos;
+import "perfetto/trace_processor/raw_query.proto";
 
-// This file defines the schema for {,un}marshalling arguments and return values
-// when interfacing to the trace processor binary interface.
+package perfetto.protos;
 
-// The Trace Processor can be used in three modes:
-// 1. Fully native from C++ or directly using trace_processor_shell.
-//    In this case, this file isn't really relevant because no binary
-//    marshalling is involved. Look at include/trace_processor/trace_processor.h
-//    for the public C++ API definition.
-// 2. Using WASM within the HTML ui. In this case these messages are used to
-//    {,un}marshall calls made through the JS<>WASM interop in
-//    src/trace_processor/rpc/wasm_bridge.cc .
-// 3. Using the HTTP+RPC interface, by running trace_processor_shell -D.
-//    In this case these messages are used to {,un}marshall HTTP requests and
-//    response made through src/trace_processor/rpc/httpd.cc .
-
-// Input for the /raw_query endpoint.
-message RawQueryArgs {
-  optional string sql_query = 1;
-
-  // Wall time when the query was queued. Used only for query stats.
-  optional uint64 time_queued_ns = 2;
-}
-
-// Output for the /raw_query endpoint.
-message RawQueryResult {
-  message ColumnDesc {
-    optional string name = 1;
-    enum Type {
-      UNKNOWN = 0;
-      LONG = 1;
-      DOUBLE = 2;
-      STRING = 3;
-    }
-    optional Type type = 2;
-  }
-  message ColumnValues {
-    // Only one of this field will be filled for each column (according to the
-    // corresponding descriptor) and that one will have precisely |num_records|
-    // elements.
-    repeated int64 long_values = 1;
-    repeated double double_values = 2;
-    repeated string string_values = 3;
-
-    // This will be set to true or false depending on whether the data at the
-    // given index is NULL.
-    repeated bool is_nulls = 4;
-  }
-  repeated ColumnDesc column_descriptors = 1;
-  optional uint64 num_records = 2;
-  repeated ColumnValues columns = 3;
-  optional string error = 4;
-  optional uint64 execution_time_ns = 5;
-}
-
-// Input for the /status endpoint.
-message StatusArgs {}
-
-// Output for the /status endpoint.
-message StatusResult {
-  // If present and not empty, a trace is already loaded already. This happens
-  // when using the HTTP+RPC mode nad passing a trace file to the shell, via
-  // trace_processor_shell -D trace_file.pftrace .
-  optional string loaded_trace_name = 1;
+service TraceProcessor {
+  rpc RawQuery(RawQueryArgs) returns (RawQueryResult) {}
 }
diff --git a/protos/third_party/pprof/BUILD.gn b/protos/third_party/pprof/BUILD.gn
index 663ba44..cb74152 100644
--- a/protos/third_party/pprof/BUILD.gn
+++ b/protos/third_party/pprof/BUILD.gn
@@ -12,11 +12,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import("../../../gn/perfetto.gni")
 import("../../../gn/proto_library.gni")
 
-perfetto_proto_library("lite") {
-  proto_generators = [ "lite" ]
+proto_library("lite") {
+  generate_python = false
   sources = [
     "profile.proto",
   ]
+  proto_in_dir = "$perfetto_root_path/protos"
+  proto_out_dir = "$perfetto_root_path/protos"
 }
diff --git a/protos/third_party/pprof/profile.proto b/protos/third_party/pprof/profile.proto
index 30a4f6a..2c4acca 100644
--- a/protos/third_party/pprof/profile.proto
+++ b/protos/third_party/pprof/profile.proto
@@ -38,9 +38,7 @@
 
 syntax = "proto3";
 
-// This is in perfetto.third_party to avoid clashing with potential other
-// copies of this proto.
-package perfetto.third_party.perftools.profiles;
+package perftools.profiles;
 
 option java_package = "com.google.perftools.profiles";
 option java_outer_classname = "ProfileProto";
diff --git a/src/android_internal/BUILD.gn b/src/android_internal/BUILD.gn
index 819532a..5a16997 100644
--- a/src/android_internal/BUILD.gn
+++ b/src/android_internal/BUILD.gn
@@ -14,22 +14,12 @@
 
 import("../../gn/perfetto.gni")
 
-# This target is supported only in in-tree builds of Android. It contains
-# code that is not NDK-clean and references other repos in the Android tree.
-shared_library("libperfetto_android_internal") {
-  deps = [
-    ":android_internal",
-    "../../gn:default_deps",
-  ]
-}
-
 source_set("headers") {
   deps = [
     "../../gn:default_deps",
   ]
   sources = [
     "atrace_hal.h",
-    "dropbox_service.h",
     "health_hal.h",
     "incident_service.h",
     "power_stats_hal.h",
@@ -54,7 +44,7 @@
 # This target proxies calls to Android internal libraries that are not part of
 # the NDK. See README.md.
 source_set("android_internal") {
-  visibility = [ ":libperfetto_android_internal" ]
+  visibility = [ "//:libperfetto_android_internal" ]
   deps = [
     ":headers",
     "../../gn:default_deps",
@@ -62,7 +52,6 @@
   if (perfetto_build_with_android) {
     sources = [
       "atrace_hal.cc",
-      "dropbox_service.cc",
       "health_hal.cc",
       "incident_service.cc",
       "power_stats_hal.cc",
@@ -75,6 +64,8 @@
       "binder",
       "log",
       "hidlbase",
+      "hidltransport",
+      "hwbinder",
       "incident",
       "services",
       "utils",
diff --git a/src/android_internal/dropbox_service.cc b/src/android_internal/dropbox_service.cc
deleted file mode 100644
index 8088028..0000000
--- a/src/android_internal/dropbox_service.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/android_internal/dropbox_service.h"
-
-#include <android/os/DropBoxManager.h>
-#include <utils/StrongPointer.h>
-
-namespace perfetto {
-namespace android_internal {
-
-bool SaveIntoDropbox(const char* tag, int fd) {
-  using android::os::DropBoxManager;
-  android::sp<DropBoxManager> dropbox(new DropBoxManager());
-  auto status = dropbox->addFile(android::String16(tag), fd, /*flags=*/0);
-  return status.isOk();
-}
-
-}  // namespace android_internal
-}  // namespace perfetto
diff --git a/src/android_internal/dropbox_service.h b/src/android_internal/dropbox_service.h
deleted file mode 100644
index 6365355..0000000
--- a/src/android_internal/dropbox_service.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_ANDROID_INTERNAL_DROPBOX_SERVICE_H_
-#define SRC_ANDROID_INTERNAL_DROPBOX_SERVICE_H_
-
-namespace perfetto {
-namespace android_internal {
-
-extern "C" {
-
-// Saves the passed file into Dropbox with the given tag.
-// Takes ownership of the passed file descriptor.
-bool __attribute__((visibility("default")))
-SaveIntoDropbox(const char* tag, int fd);
-
-}  // extern "C"
-
-}  // namespace android_internal
-}  // namespace perfetto
-
-#endif  // SRC_ANDROID_INTERNAL_DROPBOX_SERVICE_H_
diff --git a/src/android_internal/empty_file.cc b/src/android_internal/empty_file.cc
deleted file mode 100644
index 22ffa8f..0000000
--- a/src/android_internal/empty_file.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-// TODO(primiano): this file is here only to have one translation unit for the
-// temporary perfetto_src_tracing_ipc target.
-
-__attribute__((visibility("default"))) void PerfettoNoOp();
-void PerfettoNoOp() {}
diff --git a/src/base/BUILD.gn b/src/base/BUILD.gn
index 0e7a0d0..97abdcf 100644
--- a/src/base/BUILD.gn
+++ b/src/base/BUILD.gn
@@ -14,18 +14,14 @@
 
 import("//build_overrides/build.gni")
 import("../../gn/perfetto.gni")
-import("../../gn/test.gni")
 import("../../gn/wasm.gni")
 
-enable_stack_trace = is_debug && perfetto_build_standalone && !is_wasm
-
 source_set("base") {
   deps = [
     "../../gn:default_deps",
   ]
   public_deps = [
     "../../include/perfetto/base",
-    "../../include/perfetto/ext/base",
   ]
   sources = [
     "file_utils.cc",
@@ -36,16 +32,13 @@
     "string_view.cc",
     "thread_checker.cc",
     "time.cc",
-    "uuid.cc",
     "virtual_destructors.cc",
-    "waitable_event.cc",
-    "watchdog_posix.cc",
   ]
 
   # TODO(brucedawson): Enable these for Windows when possible.
   if (!is_win) {
     sources += [
-      "event_fd.cc",
+      "event.cc",
       "pipe.cc",
       "temp_file.cc",
       "thread_task_runner.cc",
@@ -53,35 +46,57 @@
     ]
   }
 
-  if (enable_stack_trace) {
+  if ((perfetto_build_standalone || perfetto_build_with_android) &&
+      (is_linux || is_android) && !is_wasm) {
+    sources += [ "watchdog_posix.cc" ]
+  }
+  if (is_debug && perfetto_build_standalone && !is_wasm) {
     deps += [ ":debug_crash_stack_trace" ]
   }
 }
 
-if (enable_stack_trace) {
+# The "android_task_runner" should be depended on only by targets that
+# explicitly need it, as it pulls in a dependency on libandroid.so that in turn
+# pulls dozen of other .so(s).
+if (is_android && (perfetto_build_standalone || perfetto_build_with_android)) {
+  source_set("android_task_runner") {
+    deps = [
+      ":base",
+      "../../gn:default_deps",
+    ]
+    sources = [
+      "android_task_runner.cc",
+    ]
+    all_dependent_configs = [ ":android_config" ]
+  }
+
+  config("android_config") {
+    libs = [ "android" ]
+  }
+}
+
+if (is_debug && perfetto_build_standalone && !is_wasm) {
   source_set("debug_crash_stack_trace") {
     sources = [
       "debug_crash_stack_trace.cc",
     ]
     deps = [
       "../../gn:default_deps",
-      "../../include/perfetto/ext/base",
-      "../../include/perfetto/ext/base",
+      "../../include/perfetto/base",
     ]
     if (is_linux || is_android) {
-      deps += [ "../../gn:libbacktrace" ]
+      deps += [ "../../buildtools:libbacktrace" ]
     }
     cflags = [ "-Wno-deprecated" ]
   }
 }
 
-if (enable_perfetto_ipc) {
+if (perfetto_build_with_ipc_layer) {
   # This cannot be in :base as it does not build on WASM.
   source_set("unix_socket") {
     deps = [
       "../../gn:default_deps",
-      "../../include/perfetto/ext/base",
-      "../../include/perfetto/ext/base",
+      "../../include/perfetto/base",
     ]
     sources = [
       "unix_socket.cc",
@@ -94,6 +109,7 @@
   deps = [
     ":base",
     "../../gn:default_deps",
+    "../../gn:gtest_deps",
   ]
   sources = [
     "test/utils.cc",
@@ -111,15 +127,18 @@
   }
 }
 
-perfetto_unittest_source_set("unittests") {
+source_set("unittests") {
   testonly = true
   deps = [
     ":base",
     ":test_support",
     "../../gn:default_deps",
-    "../../gn:gtest_and_gmock",
+    "../../gn:gtest_deps",
   ]
 
+  if (is_android && (perfetto_build_standalone || perfetto_build_with_android)) {
+    deps += [ ":android_task_runner" ]
+  }
   sources = [
     "circular_queue_unittest.cc",
     "no_destructor_unittest.cc",
@@ -131,14 +150,12 @@
     "string_view_unittest.cc",
     "string_writer_unittest.cc",
     "time_unittest.cc",
-    "uuid_unittest.cc",
     "weak_ptr_unittest.cc",
   ]
 
-  # TODO: Enable these for Windows when possible.
+  # TODO(brucedawson): Enable these for Windows when possible.
   if (!is_win) {
     sources += [
-      "metatrace_unittest.cc",
       "task_runner_unittest.cc",
       "temp_file_unittest.cc",
       "thread_checker_unittest.cc",
@@ -147,7 +164,6 @@
     ]
   }
   if (perfetto_build_standalone || perfetto_build_with_android) {
-    # This causes some problems on the chromium waterfall.
     sources += [ "unix_socket_unittest.cc" ]
     if (is_linux || is_android) {
       sources += [ "watchdog_unittest.cc" ]
diff --git a/src/base/android_task_runner.cc b/src/base/android_task_runner.cc
new file mode 100644
index 0000000..aab61d1
--- /dev/null
+++ b/src/base/android_task_runner.cc
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2017 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 "perfetto/base/android_task_runner.h"
+
+#include <errno.h>
+#include <sys/timerfd.h>
+
+namespace perfetto {
+namespace base {
+
+AndroidTaskRunner::AndroidTaskRunner()
+    : looper_(ALooper_prepare(0 /* require callbacks */)),
+      delayed_timer_(
+          timerfd_create(kWallTimeClockSource, TFD_NONBLOCK | TFD_CLOEXEC)) {
+  ALooper_acquire(looper_);
+  PERFETTO_CHECK(delayed_timer_);
+  AddFileDescriptorWatch(immediate_event_.fd(),
+                         std::bind(&AndroidTaskRunner::RunImmediateTask, this));
+  AddFileDescriptorWatch(delayed_timer_.get(),
+                         std::bind(&AndroidTaskRunner::RunDelayedTask, this));
+}
+
+AndroidTaskRunner::~AndroidTaskRunner() {
+  PERFETTO_DCHECK_THREAD(thread_checker_);
+  std::lock_guard<std::mutex> lock(lock_);
+  for (const auto& watch : watch_tasks_) {
+    // ALooper doesn't guarantee that each watch doesn't run one last time if
+    // the file descriptor was already signalled. To guard against this point
+    // the watch to a no-op callback.
+    ALooper_addFd(
+        looper_, watch.first, ALOOPER_POLL_CALLBACK,
+        ALOOPER_EVENT_INPUT | ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP,
+        [](int, int, void*) -> int { return 0; }, nullptr);
+    ALooper_removeFd(looper_, watch.first);
+  }
+  ALooper_release(looper_);
+
+  struct itimerspec time = {};
+  timerfd_settime(delayed_timer_.get(), TFD_TIMER_ABSTIME, &time, nullptr);
+}
+
+void AndroidTaskRunner::Run() {
+  quit_ = false;
+  for (;;) {
+    {
+      std::lock_guard<std::mutex> lock(lock_);
+      if (quit_)
+        break;
+    }
+    ALooper_pollOnce(-1 /* timeout */, nullptr, nullptr, nullptr);
+  }
+}
+
+void AndroidTaskRunner::Quit() {
+  std::lock_guard<std::mutex> lock(lock_);
+  quit_ = true;
+  ALooper_wake(looper_);
+}
+
+bool AndroidTaskRunner::IsIdleForTesting() {
+  PERFETTO_DCHECK_THREAD(thread_checker_);
+  std::lock_guard<std::mutex> lock(lock_);
+  return immediate_tasks_.empty();
+}
+
+void AndroidTaskRunner::RunImmediateTask() {
+  immediate_event_.Clear();
+
+  // If locking overhead becomes an issue, add a separate work queue.
+  bool has_next;
+  std::function<void()> immediate_task;
+  {
+    std::lock_guard<std::mutex> lock(lock_);
+    if (immediate_tasks_.empty())
+      return;
+    immediate_task = std::move(immediate_tasks_.front());
+    immediate_tasks_.pop_front();
+    has_next = !immediate_tasks_.empty();
+  }
+  // Do another pass through the event loop even if we have immediate tasks to
+  // run for fairness.
+  if (has_next)
+    ScheduleImmediateWakeUp();
+  errno = 0;
+  RunTask(immediate_task);
+}
+
+void AndroidTaskRunner::RunDelayedTask() {
+  uint64_t unused = 0;
+  if (read(delayed_timer_.get(), &unused, sizeof(unused)) != sizeof(unused) &&
+      errno != EAGAIN) {
+    PERFETTO_DPLOG("read");
+  }
+
+  std::function<void()> delayed_task;
+  TimeMillis next_wake_up{};
+  {
+    std::lock_guard<std::mutex> lock(lock_);
+    if (delayed_tasks_.empty())
+      return;
+    auto it = delayed_tasks_.begin();
+    PERFETTO_DCHECK(GetWallTimeMs() >= it->first);
+    delayed_task = std::move(it->second);
+    delayed_tasks_.erase(it);
+    if (!delayed_tasks_.empty())
+      next_wake_up = delayed_tasks_.begin()->first;
+  }
+  if (next_wake_up.count())
+    ScheduleDelayedWakeUp(next_wake_up);
+  errno = 0;
+  RunTask(delayed_task);
+}
+
+void AndroidTaskRunner::ScheduleImmediateWakeUp() {
+  immediate_event_.Notify();
+}
+
+void AndroidTaskRunner::ScheduleDelayedWakeUp(TimeMillis time) {
+  PERFETTO_DCHECK(time.count());
+  struct itimerspec wake_up = {};
+  wake_up.it_value = ToPosixTimespec(time);
+  if (timerfd_settime(delayed_timer_.get(), TFD_TIMER_ABSTIME, &wake_up,
+                      nullptr) == -1) {
+    PERFETTO_DPLOG("timerfd_settime");
+  }
+}
+
+void AndroidTaskRunner::PostTask(std::function<void()> task) {
+  bool was_empty;
+  {
+    std::lock_guard<std::mutex> lock(lock_);
+    was_empty = immediate_tasks_.empty();
+    immediate_tasks_.push_back(std::move(task));
+  }
+  if (was_empty)
+    ScheduleImmediateWakeUp();
+}
+
+void AndroidTaskRunner::PostDelayedTask(std::function<void()> task,
+                                        uint32_t delay_ms) {
+  PERFETTO_DCHECK(delay_ms >= 0);
+  TimeMillis runtime = GetWallTimeMs() + TimeMillis(delay_ms);
+  bool is_next = false;
+  {
+    std::lock_guard<std::mutex> lock(lock_);
+    auto it = delayed_tasks_.insert(std::make_pair(runtime, std::move(task)));
+    if (it == delayed_tasks_.begin())
+      is_next = true;
+  }
+  if (is_next)
+    ScheduleDelayedWakeUp(runtime);
+}
+
+void AndroidTaskRunner::AddFileDescriptorWatch(int fd,
+                                               std::function<void()> task) {
+  PERFETTO_DCHECK(fd >= 0);
+  {
+    std::lock_guard<std::mutex> lock(lock_);
+    PERFETTO_DCHECK(!watch_tasks_.count(fd));
+    watch_tasks_[fd] = std::move(task);
+  }
+  // It's safe for the callback to hang on to |this| as everything is
+  // unregistered in the destructor.
+  auto callback = [](int signalled_fd, int events, void* data) -> int {
+    AndroidTaskRunner* task_runner = reinterpret_cast<AndroidTaskRunner*>(data);
+    return task_runner->OnFileDescriptorEvent(signalled_fd, events) ? 1 : 0;
+  };
+  PERFETTO_CHECK(ALooper_addFd(looper_, fd, ALOOPER_POLL_CALLBACK,
+                               ALOOPER_EVENT_INPUT | ALOOPER_EVENT_ERROR |
+                                   ALOOPER_EVENT_HANGUP,
+                               std::move(callback), this) != -1);
+}
+
+bool AndroidTaskRunner::OnFileDescriptorEvent(int signalled_fd, int events) {
+  PERFETTO_DCHECK_THREAD(thread_checker_);
+  if (!(events & (ALOOPER_EVENT_INPUT | ALOOPER_EVENT_ERROR |
+                  ALOOPER_EVENT_HANGUP | ALOOPER_EVENT_INVALID))) {
+    return true;
+  }
+  std::function<void()> task;
+  {
+    std::lock_guard<std::mutex> lock(lock_);
+    auto it = watch_tasks_.find(signalled_fd);
+    if (it == watch_tasks_.end())
+      return false;
+    task = it->second;
+  }
+  errno = 0;
+  RunTask(task);
+  return true;
+}
+
+void AndroidTaskRunner::RemoveFileDescriptorWatch(int fd) {
+  PERFETTO_DCHECK(fd >= 0);
+  {
+    std::lock_guard<std::mutex> lock(lock_);
+    PERFETTO_DCHECK(watch_tasks_.count(fd));
+    watch_tasks_.erase(fd);
+  }
+  ALooper_removeFd(looper_, fd);
+}
+
+bool AndroidTaskRunner::RunsTasksOnCurrentThread() const {
+  return looper_ == ALooper_forThread();
+}
+
+}  // namespace base
+}  // namespace perfetto
diff --git a/src/base/circular_queue_unittest.cc b/src/base/circular_queue_unittest.cc
index 2622094..6fefe0c 100644
--- a/src/base/circular_queue_unittest.cc
+++ b/src/base/circular_queue_unittest.cc
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/circular_queue.h"
+#include "perfetto/base/circular_queue.h"
 
 #include <random>
 
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace base {
diff --git a/src/base/debug_crash_stack_trace.cc b/src/base/debug_crash_stack_trace.cc
index ae857a4..31fe32d 100644
--- a/src/base/debug_crash_stack_trace.cc
+++ b/src/base/debug_crash_stack_trace.cc
@@ -28,7 +28,7 @@
 #include <unwind.h>
 
 #include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/file_utils.h"
+#include "perfetto/base/file_utils.h"
 
 // Some glibc headers hit this when using signals.
 #pragma GCC diagnostic push
diff --git a/src/base/event.cc b/src/base/event.cc
new file mode 100644
index 0000000..4fa6ec0
--- /dev/null
+++ b/src/base/event.cc
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#include <stdint.h>
+#include <unistd.h>
+
+#include "perfetto/base/event.h"
+#include "perfetto/base/logging.h"
+#include "perfetto/base/pipe.h"
+
+#if PERFETTO_USE_EVENTFD()
+#include <sys/eventfd.h>
+#endif
+
+namespace perfetto {
+namespace base {
+
+Event::Event() {
+#if PERFETTO_USE_EVENTFD()
+  fd_.reset(eventfd(/* start value */ 0, EFD_CLOEXEC | EFD_NONBLOCK));
+  PERFETTO_CHECK(fd_);
+#else
+  // Make the pipe non-blocking so that we never block the waking thread (either
+  // the main thread or another one) when scheduling a wake-up.
+  Pipe pipe = Pipe::Create(Pipe::kBothNonBlock);
+  fd_ = std::move(pipe.rd);
+  write_fd_ = std::move(pipe.wr);
+#endif  // !PERFETTO_USE_EVENTFD()
+}
+
+Event::~Event() = default;
+
+void Event::Notify() {
+  const uint64_t value = 1;
+
+#if PERFETTO_USE_EVENTFD()
+  ssize_t ret = write(fd_.get(), &value, sizeof(value));
+#else
+  ssize_t ret = write(write_fd_.get(), &value, sizeof(uint8_t));
+#endif
+
+  if (ret <= 0 && errno != EAGAIN) {
+    PERFETTO_DFATAL("write()");
+  }
+}
+
+void Event::Clear() {
+#if PERFETTO_USE_EVENTFD()
+  uint64_t value;
+  ssize_t ret = read(fd_.get(), &value, sizeof(value));
+#else
+  // Drain the byte(s) written to the wake-up pipe. We can potentially read
+  // more than one byte if several wake-ups have been scheduled.
+  char buffer[16];
+  ssize_t ret = read(fd_.get(), &buffer[0], sizeof(buffer));
+#endif
+  if (ret <= 0 && errno != EAGAIN)
+    PERFETTO_DPLOG("read()");
+}
+
+}  // namespace base
+}  // namespace perfetto
diff --git a/src/base/event_fd.cc b/src/base/event_fd.cc
deleted file mode 100644
index 976db19..0000000
--- a/src/base/event_fd.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.
- */
-
-#include "perfetto/base/build_config.h"
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-
-#include <stdint.h>
-#include <unistd.h>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/event_fd.h"
-#include "perfetto/ext/base/pipe.h"
-#include "perfetto/ext/base/utils.h"
-
-#if PERFETTO_USE_EVENTFD()
-#include <sys/eventfd.h>
-#endif
-
-namespace perfetto {
-namespace base {
-
-EventFd::EventFd() {
-#if PERFETTO_USE_EVENTFD()
-  fd_.reset(eventfd(/* start value */ 0, EFD_CLOEXEC | EFD_NONBLOCK));
-  PERFETTO_CHECK(fd_);
-#else
-  // Make the pipe non-blocking so that we never block the waking thread (either
-  // the main thread or another one) when scheduling a wake-up.
-  Pipe pipe = Pipe::Create(Pipe::kBothNonBlock);
-  fd_ = std::move(pipe.rd);
-  write_fd_ = std::move(pipe.wr);
-#endif  // !PERFETTO_USE_EVENTFD()
-}
-
-EventFd::~EventFd() = default;
-
-void EventFd::Notify() {
-  const uint64_t value = 1;
-
-#if PERFETTO_USE_EVENTFD()
-  ssize_t ret = write(fd_.get(), &value, sizeof(value));
-#else
-  ssize_t ret = write(write_fd_.get(), &value, sizeof(uint8_t));
-#endif
-
-  if (ret <= 0 && errno != EAGAIN) {
-    PERFETTO_DFATAL("write()");
-  }
-}
-
-void EventFd::Clear() {
-#if PERFETTO_USE_EVENTFD()
-  uint64_t value;
-  ssize_t ret = read(fd_.get(), &value, sizeof(value));
-#else
-  // Drain the byte(s) written to the wake-up pipe. We can potentially read
-  // more than one byte if several wake-ups have been scheduled.
-  char buffer[16];
-  ssize_t ret = read(fd_.get(), &buffer[0], sizeof(buffer));
-#endif
-  if (ret <= 0 && errno != EAGAIN)
-    PERFETTO_DPLOG("read()");
-}
-
-}  // namespace base
-}  // namespace perfetto
-
-#endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
diff --git a/src/base/file_utils.cc b/src/base/file_utils.cc
index b8020ad..b417128 100644
--- a/src/base/file_utils.cc
+++ b/src/base/file_utils.cc
@@ -17,13 +17,11 @@
 #include <sys/stat.h>
 
 #include "perfetto/base/build_config.h"
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/scoped_file.h"
 
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) || \
-    PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC)
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 #include <unistd.h>
 #else
 #include <corecrt_io.h>
diff --git a/src/base/metatrace.cc b/src/base/metatrace.cc
index 67d167c..99b787f 100644
--- a/src/base/metatrace.cc
+++ b/src/base/metatrace.cc
@@ -14,132 +14,50 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/metatrace.h"
+#include "perfetto/base/metatrace.h"
 
-#include "perfetto/base/compiler.h"
-#include "perfetto/base/task_runner.h"
+#include <fcntl.h>
+#include <stdlib.h>
+
+#include "perfetto/base/build_config.h"
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/file_utils.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include <corecrt_io.h>
+#endif
 
 namespace perfetto {
-namespace metatrace {
-
-std::atomic<uint32_t> g_enabled_tags{0};
-std::atomic<uint64_t> g_enabled_timestamp{0};
-
-// static members
-constexpr size_t RingBuffer::kCapacity;
-std::array<Record, RingBuffer::kCapacity> RingBuffer::records_;
-std::atomic<bool> RingBuffer::read_task_queued_;
-std::atomic<uint64_t> RingBuffer::wr_index_;
-std::atomic<uint64_t> RingBuffer::rd_index_;
-std::atomic<bool> RingBuffer::has_overruns_;
-Record RingBuffer::bankruptcy_record_;
-
-constexpr uint16_t Record::kTypeMask;
-constexpr uint16_t Record::kTypeCounter;
-constexpr uint16_t Record::kTypeEvent;
+namespace base {
 
 namespace {
-
-// std::function<> is not trivially de/constructible. This struct wraps it in a
-// heap-allocated struct to avoid static initializers.
-struct Delegate {
-  static Delegate* GetInstance() {
-    static Delegate* instance = new Delegate();
-    return instance;
-  }
-
-  base::TaskRunner* task_runner = nullptr;
-  std::function<void()> read_task;
-};
-
+int MaybeOpenTraceFile() {
+  static const char* tracing_path = getenv("PERFETTO_METATRACE_FILE");
+  if (tracing_path == nullptr)
+    return -1;
+  static int fd = open(tracing_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+  return fd;
+}
 }  // namespace
 
-bool Enable(std::function<void()> read_task,
-            base::TaskRunner* task_runner,
-            uint32_t tags) {
-  PERFETTO_DCHECK(read_task);
-  PERFETTO_DCHECK(task_runner->RunsTasksOnCurrentThread());
-  if (g_enabled_tags.load(std::memory_order_acquire))
-    return false;
+constexpr uint32_t MetaTrace::kMainThreadCpu;
 
-  Delegate* dg = Delegate::GetInstance();
-  dg->task_runner = task_runner;
-  dg->read_task = std::move(read_task);
-  RingBuffer::Reset();
-  g_enabled_timestamp.store(TraceTimeNowNs(), std::memory_order_relaxed);
-  g_enabled_tags.store(tags, std::memory_order_release);
-  return true;
+void MetaTrace::WriteEvent(char type, const char* evt_name, size_t cpu) {
+  int fd = MaybeOpenTraceFile();
+  if (fd == -1)
+    return;
+
+  // The JSON event format expects both "pid" and "tid" fields to create
+  // per-process tracks. Here what we really want to achieve is having one track
+  // per cpu. So we just pretend that each CPU is its own process with
+  // pid == tid == cpu.
+  char json[256];
+  int len = sprintf(json,
+                    "{\"ts\": %f, \"cat\": \"PERF\", \"ph\": \"%c\", \"name\": "
+                    "\"%s\", \"pid\": %zu, \"tid\": %zu},\n",
+                    GetWallTimeNs().count() / 1000.0, type, evt_name, cpu, cpu);
+  ignore_result(WriteAll(fd, json, static_cast<size_t>(len)));
 }
 
-void Disable() {
-  g_enabled_tags.store(0, std::memory_order_release);
-  Delegate* dg = Delegate::GetInstance();
-  PERFETTO_DCHECK(!dg->task_runner ||
-                  dg->task_runner->RunsTasksOnCurrentThread());
-  dg->task_runner = nullptr;
-  dg->read_task = nullptr;
-}
-
-// static
-void RingBuffer::Reset() {
-  bankruptcy_record_.clear();
-  for (Record& record : records_)
-    record.clear();
-  wr_index_ = 0;
-  rd_index_ = 0;
-  has_overruns_ = false;
-  read_task_queued_ = false;
-}
-
-// static
-Record* RingBuffer::AppendNewRecord() {
-  auto wr_index = wr_index_.fetch_add(1, std::memory_order_acq_rel);
-
-  // rd_index can only monotonically increase, we don't care if we read an
-  // older value, we'll just hit the slow-path a bit earlier if it happens.
-  auto rd_index = rd_index_.load(std::memory_order_relaxed);
-
-  PERFETTO_DCHECK(wr_index >= rd_index);
-  auto size = wr_index - rd_index;
-  if (PERFETTO_LIKELY(size < kCapacity / 2))
-    return At(wr_index);
-
-  // Slow-path: Enqueue the read task and handle overruns.
-  bool expected = false;
-  if (RingBuffer::read_task_queued_.compare_exchange_strong(expected, true)) {
-    Delegate* dg = Delegate::GetInstance();
-    if (dg->task_runner) {
-      dg->task_runner->PostTask([] {
-        // Meta-tracing might have been disabled in the meantime.
-        auto read_task = Delegate::GetInstance()->read_task;
-        if (read_task)
-          read_task();
-        RingBuffer::read_task_queued_ = false;
-      });
-    }
-  }
-
-  if (PERFETTO_LIKELY(size < kCapacity))
-    return At(wr_index);
-
-  has_overruns_.store(true, std::memory_order_release);
-  wr_index_.fetch_sub(1, std::memory_order_acq_rel);
-
-  // In the case of overflows, threads will race writing on the same memory
-  // location and TSan will rightly complain. This is fine though because nobody
-  // will read the bankruptcy record and it's designed to contain garbage.
-  PERFETTO_ANNOTATE_BENIGN_RACE_SIZED(&bankruptcy_record_, sizeof(Record),
-                                      "nothing reads bankruptcy_record_")
-  return &bankruptcy_record_;
-}
-
-// static
-bool RingBuffer::IsOnValidTaskRunner() {
-  auto* task_runner = Delegate::GetInstance()->task_runner;
-  return task_runner && task_runner->RunsTasksOnCurrentThread();
-}
-
-}  // namespace metatrace
+}  // namespace base
 }  // namespace perfetto
diff --git a/src/base/metatrace_unittest.cc b/src/base/metatrace_unittest.cc
deleted file mode 100644
index 88f1a67..0000000
--- a/src/base/metatrace_unittest.cc
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) 2019 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 <array>
-#include <chrono>
-#include <deque>
-#include <thread>
-
-#include "perfetto/ext/base/metatrace.h"
-#include "src/base/test/test_task_runner.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace {
-
-namespace m = ::perfetto::metatrace;
-using ::testing::Invoke;
-
-class MetatraceTest : public ::testing::Test {
- public:
-  void SetUp() override { m::Disable(); }
-
-  void TearDown() override {
-    task_runner_.RunUntilIdle();
-    m::Disable();
-  }
-
-  void Enable(uint32_t tags) {
-    m::Enable([this] { ReadCallback(); }, &task_runner_, tags);
-  }
-
-  MOCK_METHOD0(ReadCallback, void());
-  base::TestTaskRunner task_runner_;
-};
-
-TEST_F(MetatraceTest, TagEnablingLogic) {
-  EXPECT_CALL(*this, ReadCallback()).Times(0);
-  for (int iteration = 0; iteration < 3; iteration++) {
-    ASSERT_EQ(m::RingBuffer::GetSizeForTesting(), 0u);
-
-    // No events should be traced before enabling.
-    m::TraceCounter(m::TAG_ANY, /*id=*/1, /*value=*/42);
-    { m::ScopedEvent evt(m::TAG_ANY, /*id=*/1); }
-    ASSERT_EQ(m::RingBuffer::GetSizeForTesting(), 0u);
-
-    // Enable tags bit 1 (=2) and 2 (=4) and verify that only those events are
-    // added.
-    auto t_start = metatrace::TraceTimeNowNs();
-    Enable(/*tags=*/2 | 4);
-    m::TraceCounter(/*tag=*/1, /*id=*/42, /*value=*/10);      // No.
-    m::TraceCounter(/*tag=*/2, /*id=*/42, /*value=*/11);      // Yes.
-    m::TraceCounter(/*tag=*/4, /*id=*/42, /*value=*/12);      // Yes.
-    m::TraceCounter(/*tag=*/1 | 2, /*id=*/42, /*value=*/13);  // Yes.
-    m::TraceCounter(/*tag=*/1 | 4, /*id=*/42, /*value=*/14);  // Yes.
-    m::TraceCounter(/*tag=*/2 | 4, /*id=*/42, /*value=*/15);  // Yes.
-    m::TraceCounter(/*tag=*/4 | 8, /*id=*/42, /*value=*/16);  // Yes.
-    m::TraceCounter(/*tag=*/1 | 8, /*id=*/42, /*value=*/17);  // No.
-    m::TraceCounter(m::TAG_ANY, /*id=*/42, /*value=*/18);     // Yes.
-    { m::ScopedEvent evt(/*tag=*/1, /*id=*/20); }             // No.
-    { m::ScopedEvent evt(/*tag=*/8, /*id=*/21); }             // No.
-    { m::ScopedEvent evt(/*tag=*/2, /*id=*/22); }             // Yes.
-    { m::ScopedEvent evt(/*tag=*/4 | 8, /*id=*/23); }         // Yes.
-    { m::ScopedEvent evt(m::TAG_ANY, /*id=*/24); }            // Yes.
-
-    {
-      auto it = m::RingBuffer::GetReadIterator();
-      ASSERT_TRUE(it);
-      ASSERT_EQ(it->counter_value, 11);
-      ASSERT_TRUE(++it);
-      ASSERT_EQ(it->counter_value, 12);
-      ASSERT_TRUE(++it);
-      ASSERT_EQ(it->counter_value, 13);
-      ASSERT_TRUE(++it);
-      ASSERT_EQ(it->counter_value, 14);
-    }
-
-    // Test that destroying and re-creating the iterator resumes reading from
-    // the right place.
-    {
-      auto it = m::RingBuffer::GetReadIterator();
-      ASSERT_TRUE(++it);
-      ASSERT_EQ(it->counter_value, 15);
-      ASSERT_TRUE(++it);
-      ASSERT_EQ(it->counter_value, 16);
-      ASSERT_TRUE(++it);
-      ASSERT_EQ(it->counter_value, 18);
-      ASSERT_TRUE(++it);
-      ASSERT_EQ(it->type_and_id, 22);
-      ASSERT_TRUE(++it);
-      ASSERT_EQ(it->type_and_id, 23);
-      ASSERT_TRUE(++it);
-      ASSERT_EQ(it->type_and_id, 24);
-      ASSERT_FALSE(++it);
-    }
-
-    // Test that we can write pids up to 32 bit TIDs (I observed up to 262144
-    // from /proc/sys/kernel/pid_max) and up to 2 days of timestamps.
-    {
-      auto* record = m::RingBuffer::AppendNewRecord();
-      record->counter_value = 42;
-      constexpr uint64_t kTwoDays = 48ULL * 3600 * 1000 * 1000 * 1000;
-      record->set_timestamp(t_start + kTwoDays);
-      record->thread_id = 0xbabaf00d;
-      record->type_and_id = m::Record::kTypeCounter;
-
-      auto it = m::RingBuffer::GetReadIterator();
-      ASSERT_TRUE(it);
-      ASSERT_EQ(it->timestamp_ns(), t_start + kTwoDays);
-      ASSERT_EQ(it->thread_id, 0xbabaf00d);
-      ASSERT_FALSE(++it);
-    }
-
-    m::Disable();
-  }
-}
-
-// Test that overruns are handled properly and that the writer re-synchronizes
-// after the reader catches up.
-TEST_F(MetatraceTest, HandleOverruns) {
-  int cnt = 0;
-  int exp_cnt = 0;
-  for (size_t iteration = 0; iteration < 3; iteration++) {
-    Enable(m::TAG_ANY);
-    std::string checkpoint_name = "ReadTask " + std::to_string(iteration);
-    auto checkpoint = task_runner_.CreateCheckpoint(checkpoint_name);
-    EXPECT_CALL(*this, ReadCallback()).WillOnce(Invoke(checkpoint));
-
-    for (size_t i = 0; i < m::RingBuffer::kCapacity; i++)
-      m::TraceCounter(/*tag=*/1, /*id=*/42, /*value=*/cnt++);
-    ASSERT_EQ(m::RingBuffer::GetSizeForTesting(), m::RingBuffer::kCapacity);
-    ASSERT_FALSE(m::RingBuffer::has_overruns());
-
-    for (int n = 0; n < 3; n++)
-      m::TraceCounter(/*tag=*/1, /*id=*/42, /*value=*/-1);  // Will overrun.
-
-    ASSERT_TRUE(m::RingBuffer::has_overruns());
-    ASSERT_EQ(m::RingBuffer::GetSizeForTesting(), m::RingBuffer::kCapacity);
-
-    for (auto it = m::RingBuffer::GetReadIterator(); it; ++it)
-      ASSERT_EQ(it->counter_value, exp_cnt++);
-
-    ASSERT_EQ(m::RingBuffer::GetSizeForTesting(), 0u);
-
-    task_runner_.RunUntilCheckpoint(checkpoint_name);
-    m::Disable();
-  }
-}
-
-// Sets up a scenario where the writer writes constantly (however, guaranteeing
-// to not overrun) and the reader catches up. Tests that all events are seen
-// consistently without gaps.
-TEST_F(MetatraceTest, InterleavedReadWrites) {
-  Enable(m::TAG_ANY);
-  constexpr int kMaxValue = m::RingBuffer::kCapacity * 10;
-
-  std::atomic<int> last_value_read{-1};
-  auto read_task = [&last_value_read] {
-    int last = last_value_read;
-    for (auto it = m::RingBuffer::GetReadIterator(); it; ++it) {
-      if (it->type_and_id.load(std::memory_order_acquire) == 0)
-        break;
-      EXPECT_EQ(it->counter_value, last + 1);
-      last = it->counter_value;
-    }
-    // The read pointer is incremented only after destroying the iterator.
-    // Publish the last read value after the loop.
-    last_value_read = last;
-  };
-
-  EXPECT_CALL(*this, ReadCallback()).WillRepeatedly(Invoke(read_task));
-
-  // The writer will write continuously counters from 0 to kMaxValue.
-  auto writer_done = task_runner_.CreateCheckpoint("writer_done");
-  std::thread writer_thread([this, &writer_done, &last_value_read] {
-    for (int i = 0; i < kMaxValue; i++) {
-      m::TraceCounter(/*tag=*/1, /*id=*/1, i);
-      const int kCapacity = static_cast<int>(m::RingBuffer::kCapacity);
-
-      // Wait for the reader to avoid overruns.
-      while (i - last_value_read >= kCapacity - 1)
-        std::this_thread::sleep_for(std::chrono::nanoseconds(1));
-    }
-    task_runner_.PostTask(writer_done);
-  });
-
-  task_runner_.RunUntilCheckpoint("writer_done");
-  writer_thread.join();
-
-  read_task();  // Do a final read pass.
-  EXPECT_FALSE(m::RingBuffer::has_overruns());
-  EXPECT_EQ(last_value_read, kMaxValue - 1);
-}
-
-// Try to hit potential thread races:
-// - Test that the read callback is posted only once per cycle.
-// - Test that the final size of the ring buffeer is sane.
-// - Test that event records are consistent within each thread's event stream.
-TEST_F(MetatraceTest, ThreadRaces) {
-  for (size_t iteration = 0; iteration < 10; iteration++) {
-    Enable(m::TAG_ANY);
-
-    std::string checkpoint_name = "ReadTask " + std::to_string(iteration);
-    auto checkpoint = task_runner_.CreateCheckpoint(checkpoint_name);
-    EXPECT_CALL(*this, ReadCallback()).WillOnce(Invoke(checkpoint));
-
-    auto thread_main = [](uint16_t thd_idx) {
-      for (size_t i = 0; i < m::RingBuffer::kCapacity + 500; i++)
-        m::TraceCounter(/*tag=*/1, thd_idx, static_cast<int>(i));
-    };
-
-    constexpr size_t kNumThreads = 8;
-    std::array<std::thread, kNumThreads> threads;
-    for (size_t thd_idx = 0; thd_idx < kNumThreads; thd_idx++)
-      threads[thd_idx] = std::thread(thread_main, thd_idx);
-
-    for (auto& t : threads)
-      t.join();
-
-    task_runner_.RunUntilCheckpoint(checkpoint_name);
-    ASSERT_EQ(m::RingBuffer::GetSizeForTesting(), m::RingBuffer::kCapacity);
-
-    std::array<int, kNumThreads> last_val{};  // Last value for each thread.
-    for (auto it = m::RingBuffer::GetReadIterator(); it; ++it) {
-      if (it->type_and_id.load(std::memory_order_acquire) == 0)
-        break;
-      using Record = m::Record;
-      ASSERT_EQ(it->type_and_id & Record::kTypeMask, Record::kTypeCounter);
-      auto thd_idx = static_cast<size_t>(it->type_and_id & ~Record::kTypeMask);
-      ASSERT_EQ(it->counter_value, last_val[thd_idx]);
-      last_val[thd_idx]++;
-    }
-
-    m::Disable();
-  }
-}
-
-}  // namespace
-}  // namespace perfetto
diff --git a/src/base/no_destructor_unittest.cc b/src/base/no_destructor_unittest.cc
index 6fb8979..1f99db7 100644
--- a/src/base/no_destructor_unittest.cc
+++ b/src/base/no_destructor_unittest.cc
@@ -17,8 +17,9 @@
 
 #include <vector>
 
-#include "perfetto/ext/base/no_destructor.h"
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/no_destructor.h"
 
 namespace perfetto {
 namespace base {
diff --git a/src/base/optional_unittest.cc b/src/base/optional_unittest.cc
index 9c073ec..f2a26f8 100644
--- a/src/base/optional_unittest.cc
+++ b/src/base/optional_unittest.cc
@@ -19,14 +19,14 @@
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wfloat-equal"
 
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
 #include <memory>
 #include <set>
 #include <string>
 #include <vector>
 
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/utils.h"
-#include "test/gtest_and_gmock.h"
+#include "perfetto/base/optional.h"
 
 using ::testing::ElementsAre;
 
diff --git a/src/base/paged_memory.cc b/src/base/paged_memory.cc
index a214de3..95eebc0 100644
--- a/src/base/paged_memory.cc
+++ b/src/base/paged_memory.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/paged_memory.h"
+#include "perfetto/base/paged_memory.h"
 
 #include <algorithm>
 #include <cmath>
@@ -26,8 +26,7 @@
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/container_annotations.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/utils.h"
 
 namespace perfetto {
 namespace base {
@@ -38,7 +37,7 @@
 
 #if TRACK_COMMITTED_SIZE()
 constexpr size_t kCommitChunkSize = kPageSize * 1024;  // 4mB
-#endif                                                 // TRACK_COMMITTED_SIZE()
+#endif  // TRACK_COMMITTED_SIZE()
 
 }  // namespace
 
@@ -76,20 +75,18 @@
 
 PagedMemory::PagedMemory() {}
 
-// clang-format off
 PagedMemory::PagedMemory(char* p, size_t size) : p_(p), size_(size) {
-  ANNOTATE_NEW_BUFFER(p_, size_, committed_size_)
+  ANNOTATE_NEW_BUFFER(p_, size_, committed_size_);
 }
 
 PagedMemory::PagedMemory(PagedMemory&& other) noexcept {
   *this = other;
   other.p_ = nullptr;
 }
-// clang-format on
 
 PagedMemory& PagedMemory::operator=(PagedMemory&& other) {
-  this->~PagedMemory();
-  new (this) PagedMemory(std::move(other));
+  *this = other;
+  other.p_ = nullptr;
   return *this;
 }
 
@@ -106,7 +103,7 @@
   int res = munmap(start, outer_size);
   PERFETTO_CHECK(res == 0);
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-  ANNOTATE_DELETE_BUFFER(p_, size_, committed_size_)
+  ANNOTATE_DELETE_BUFFER(p_, size_, committed_size_);
 }
 
 bool PagedMemory::AdviseDontNeed(void* p, size_t size) {
@@ -144,12 +141,12 @@
                            PAGE_READWRITE);
   PERFETTO_CHECK(res);
   ANNOTATE_CHANGE_SIZE(p_, size_, committed_size_,
-                       committed_size_ + commit_size)
+                       committed_size_ + commit_size);
   committed_size_ += commit_size;
 #else   // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
   // mmap commits automatically as needed, so we only track here for ASAN.
   committed_size = std::max(committed_size_, committed_size);
-  ANNOTATE_CHANGE_SIZE(p_, size_, committed_size_, committed_size)
+  ANNOTATE_CHANGE_SIZE(p_, size_, committed_size_, committed_size);
   committed_size_ = committed_size;
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 }
diff --git a/src/base/paged_memory_unittest.cc b/src/base/paged_memory_unittest.cc
index 97f1a74..103cf1e 100644
--- a/src/base/paged_memory_unittest.cc
+++ b/src/base/paged_memory_unittest.cc
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/paged_memory.h"
+#include "perfetto/base/paged_memory.h"
 
 #include <stdint.h>
 
+#include "gtest/gtest.h"
 #include "perfetto/base/build_config.h"
 #include "src/base/test/vm_test_utils.h"
-#include "test/gtest_and_gmock.h"
 
 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) && \
     !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) &&    \
diff --git a/src/base/pipe.cc b/src/base/pipe.cc
index c61492f..db7fd3a 100644
--- a/src/base/pipe.cc
+++ b/src/base/pipe.cc
@@ -14,10 +14,7 @@
  * limitations under the License.
  */
 
-#include "perfetto/base/build_config.h"
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-
-#include "perfetto/ext/base/pipe.h"
+#include "perfetto/base/pipe.h"
 
 #include <sys/types.h>
 #include <unistd.h>
@@ -57,5 +54,3 @@
 
 }  // namespace base
 }  // namespace perfetto
-
-#endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
diff --git a/src/base/scoped_file_unittest.cc b/src/base/scoped_file_unittest.cc
index 13f1acb..257b5ca 100644
--- a/src/base/scoped_file_unittest.cc
+++ b/src/base/scoped_file_unittest.cc
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/base/scoped_file.h"
 #include "perfetto/base/build_config.h"
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
@@ -29,7 +29,7 @@
 #define TEST_INVALID_CLOSE
 #endif
 
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace base {
diff --git a/src/base/string_splitter.cc b/src/base/string_splitter.cc
index adf9fc8..aab47b1 100644
--- a/src/base/string_splitter.cc
+++ b/src/base/string_splitter.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/string_splitter.h"
+#include "perfetto/base/string_splitter.h"
 
 #include <utility>
 
diff --git a/src/base/string_splitter_unittest.cc b/src/base/string_splitter_unittest.cc
index eb80d35..c3a3796 100644
--- a/src/base/string_splitter_unittest.cc
+++ b/src/base/string_splitter_unittest.cc
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/string_splitter.h"
+#include "perfetto/base/string_splitter.h"
 
 #include <vector>
 
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace base {
diff --git a/src/base/string_utils.cc b/src/base/string_utils.cc
index 7e11341..41df6b6 100644
--- a/src/base/string_utils.cc
+++ b/src/base/string_utils.cc
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/string_utils.h"
-
-#include <string.h>
+#include "perfetto/base/string_utils.h"
 
 #include <algorithm>
 
@@ -39,25 +37,6 @@
   return haystack.find(needle) != std::string::npos;
 }
 
-size_t Find(const StringView& needle, const StringView& haystack) {
-  if (needle.size() == 0)
-    return 0;
-  if (needle.size() > haystack.size())
-    return std::string::npos;
-  for (size_t i = 0; i < haystack.size() - (needle.size() - 1); ++i) {
-    if (strncmp(haystack.data() + i, needle.data(), needle.size()) == 0)
-      return i;
-  }
-  return std::string::npos;
-}
-
-bool CaseInsensitiveEqual(const std::string& first, const std::string& second) {
-  return first.size() == second.size() &&
-         std::equal(
-             first.begin(), first.end(), second.begin(),
-             [](char a, char b) { return Lowercase(a) == Lowercase(b); });
-}
-
 std::string Join(const std::vector<std::string>& parts,
                  const std::string& delim) {
   std::string acc;
@@ -79,8 +58,7 @@
   size_t next;
   for (;;) {
     next = std::min(text.find(delimiter, start), text.size());
-    if (next > start)
-      output.emplace_back(&text[start], next - start);
+    output.emplace_back(&text[start], next - start);
     start = next + delimiter.size();
     if (start >= text.size())
       break;
@@ -88,56 +66,5 @@
   return output;
 }
 
-std::string StripPrefix(const std::string& str, const std::string& prefix) {
-  return StartsWith(str, prefix) ? str.substr(prefix.size()) : str;
-}
-
-std::string StripSuffix(const std::string& str, const std::string& suffix) {
-  return EndsWith(str, suffix) ? str.substr(0, str.size() - suffix.size())
-                               : str;
-}
-
-std::string ToUpper(const std::string& str) {
-  // Don't use toupper(), it depends on the locale.
-  std::string res(str);
-  auto end = res.end();
-  for (auto c = res.begin(); c != end; ++c)
-    *c = Uppercase(*c);
-  return res;
-}
-
-std::string ToLower(const std::string& str) {
-  // Don't use tolower(), it depends on the locale.
-  std::string res(str);
-  auto end = res.end();
-  for (auto c = res.begin(); c != end; ++c)
-    *c = Lowercase(*c);
-  return res;
-}
-
-std::string ToHex(const char* data, size_t size) {
-  std::string hex(2 * size + 1, 'x');
-  for (size_t i = 0; i < size; ++i) {
-    // snprintf prints 3 characters, the two hex digits and a null byte. As we
-    // write left to write, we keep overwriting the nullbytes, except for the
-    // last call to snprintf.
-    snprintf(&(hex[2 * i]), 3, "%02hhx", data[i]);
-  }
-  // Remove the trailing nullbyte produced by the last snprintf.
-  hex.resize(2 * size);
-  return hex;
-}
-
-std::string StripChars(const std::string& str,
-                       const std::string& chars,
-                       char replacement) {
-  std::string res(str);
-  const char* start = res.c_str();
-  const char* remove = chars.c_str();
-  for (const char* c = strpbrk(start, remove); c; c = strpbrk(c + 1, remove))
-    res[static_cast<uintptr_t>(c - start)] = replacement;
-  return res;
-}
-
 }  // namespace base
 }  // namespace perfetto
diff --git a/src/base/string_utils_unittest.cc b/src/base/string_utils_unittest.cc
index d67976f..bed511f 100644
--- a/src/base/string_utils_unittest.cc
+++ b/src/base/string_utils_unittest.cc
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/string_utils.h"
+#include "perfetto/base/string_utils.h"
 
-#include "test/gtest_and_gmock.h"
-
-#include "perfetto/ext/base/optional.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace base {
@@ -26,84 +25,6 @@
 
 using testing::ElementsAre;
 
-TEST(StringUtilsTest, Lowercase) {
-  EXPECT_EQ(Lowercase('A'), 'a');
-  EXPECT_EQ(Lowercase('a'), 'a');
-  EXPECT_EQ(Lowercase('Z'), 'z');
-  EXPECT_EQ(Lowercase('z'), 'z');
-  EXPECT_EQ(Lowercase('!'), '!');
-}
-
-TEST(StringUtilsTest, Uppercase) {
-  EXPECT_EQ(Uppercase('A'), 'A');
-  EXPECT_EQ(Uppercase('a'), 'A');
-  EXPECT_EQ(Uppercase('Z'), 'Z');
-  EXPECT_EQ(Uppercase('z'), 'Z');
-  EXPECT_EQ(Uppercase('!'), '!');
-}
-
-TEST(StringUtilsTest, CStringToUInt32) {
-  EXPECT_EQ(CStringToUInt32("0"), make_optional<uint32_t>(0U));
-  EXPECT_EQ(CStringToUInt32("1"), make_optional<uint32_t>(1U));
-  EXPECT_EQ(CStringToUInt32("42"), make_optional<uint32_t>(42U));
-  EXPECT_EQ(CStringToUInt32(""), nullopt);
-  EXPECT_EQ(CStringToUInt32("!?"), nullopt);
-  EXPECT_EQ(CStringToUInt32("abc"), nullopt);
-  EXPECT_EQ(CStringToUInt32("123 abc"), nullopt);
-}
-
-TEST(StringUtilsTest, CStringToInt32) {
-  EXPECT_EQ(CStringToInt32("0"), make_optional<int32_t>(0));
-  EXPECT_EQ(CStringToInt32("1"), make_optional<int32_t>(1));
-  EXPECT_EQ(CStringToInt32("-42"), make_optional<int32_t>(-42));
-  EXPECT_EQ(CStringToInt32(""), nullopt);
-  EXPECT_EQ(CStringToInt32("!?"), nullopt);
-  EXPECT_EQ(CStringToInt32("abc"), nullopt);
-  EXPECT_EQ(CStringToInt32("123 abc"), nullopt);
-}
-
-TEST(StringUtilsTest, CStringToDouble) {
-  EXPECT_DOUBLE_EQ(CStringToDouble("0").value(), 0l);
-  EXPECT_DOUBLE_EQ(CStringToDouble("1").value(), 1l);
-  EXPECT_DOUBLE_EQ(CStringToDouble("-42").value(), -42l);
-  EXPECT_DOUBLE_EQ(CStringToDouble("-42.5").value(), -42.5l);
-  EXPECT_EQ(CStringToDouble(""), nullopt);
-  EXPECT_EQ(CStringToDouble("!?"), nullopt);
-  EXPECT_EQ(CStringToDouble("abc"), nullopt);
-  EXPECT_EQ(CStringToDouble("123 abc"), nullopt);
-}
-
-TEST(StringUtilsTest, StringToUInt32) {
-  EXPECT_EQ(StringToUInt32("0"), make_optional<uint32_t>(0U));
-  EXPECT_EQ(StringToUInt32("1"), make_optional<uint32_t>(1U));
-  EXPECT_EQ(StringToUInt32("42"), make_optional<uint32_t>(42U));
-  EXPECT_EQ(StringToUInt32(""), nullopt);
-  EXPECT_EQ(StringToUInt32("!?"), nullopt);
-  EXPECT_EQ(StringToUInt32("abc"), nullopt);
-  EXPECT_EQ(StringToUInt32("123 abc"), nullopt);
-}
-
-TEST(StringUtilsTest, StringToInt32) {
-  EXPECT_EQ(StringToInt32("0"), make_optional<int32_t>(0));
-  EXPECT_EQ(StringToInt32("1"), make_optional<int32_t>(1));
-  EXPECT_EQ(StringToInt32("-42"), make_optional<int32_t>(-42));
-  EXPECT_EQ(StringToInt32(""), nullopt);
-  EXPECT_EQ(StringToInt32("!?"), nullopt);
-  EXPECT_EQ(StringToInt32("abc"), nullopt);
-  EXPECT_EQ(StringToInt32("123 abc"), nullopt);
-}
-
-TEST(StringUtilsTest, StringToDouble) {
-  EXPECT_DOUBLE_EQ(StringToDouble("0").value(), 0l);
-  EXPECT_DOUBLE_EQ(StringToDouble("1").value(), 1l);
-  EXPECT_DOUBLE_EQ(StringToDouble("-42").value(), -42l);
-  EXPECT_DOUBLE_EQ(StringToDouble("-42.5").value(), -42.5l);
-  EXPECT_EQ(StringToDouble(""), nullopt);
-  EXPECT_EQ(StringToDouble("!?"), nullopt);
-  EXPECT_EQ(StringToDouble("abc"), nullopt);
-  EXPECT_EQ(StringToDouble("123 abc"), nullopt);
-}
-
 TEST(StringUtilsTest, StartsWith) {
   EXPECT_TRUE(StartsWith("", ""));
   EXPECT_TRUE(StartsWith("abc", ""));
@@ -126,85 +47,16 @@
   EXPECT_FALSE(EndsWith("", "c"));
 }
 
-TEST(StringUtilsTest, ToHex) {
-  EXPECT_EQ(ToHex(""), "");
-  EXPECT_EQ(ToHex("abc123"), "616263313233");
-}
-
-TEST(StringUtilsTest, CaseInsensitiveEqual) {
-  EXPECT_TRUE(CaseInsensitiveEqual("", ""));
-  EXPECT_TRUE(CaseInsensitiveEqual("abc", "abc"));
-  EXPECT_TRUE(CaseInsensitiveEqual("ABC", "abc"));
-  EXPECT_TRUE(CaseInsensitiveEqual("abc", "ABC"));
-  EXPECT_FALSE(CaseInsensitiveEqual("abc", "AB"));
-  EXPECT_FALSE(CaseInsensitiveEqual("ab", "ABC"));
-}
-
 TEST(StringUtilsTest, SplitString) {
-  EXPECT_THAT(SplitString("", ":"), ElementsAre());
+  EXPECT_THAT(SplitString("", ":"), ElementsAre(""));
   EXPECT_THAT(SplitString("a:b:c", ":"), ElementsAre("a", "b", "c"));
   EXPECT_THAT(SplitString("a::b::c", "::"), ElementsAre("a", "b", "c"));
-  EXPECT_THAT(SplitString("::::a::b::::c::", "::"), ElementsAre("a", "b", "c"));
   EXPECT_THAT(SplitString("abc", ":"), ElementsAre("abc"));
   EXPECT_THAT(SplitString("abc", "::"), ElementsAre("abc"));
   EXPECT_THAT(SplitString("abc", ":"), ElementsAre("abc"));
   EXPECT_THAT(SplitString("abc", "::"), ElementsAre("abc"));
 }
 
-TEST(StringUtilsTest, Strip) {
-  EXPECT_EQ(StripPrefix("abc", ""), "abc");
-  EXPECT_EQ(StripPrefix("abc", "a"), "bc");
-  EXPECT_EQ(StripPrefix("abc", "ab"), "c");
-  EXPECT_EQ(StripPrefix("abc", "abc"), "");
-  EXPECT_EQ(StripPrefix("abc", "abcd"), "abc");
-
-  EXPECT_EQ(StripSuffix("abc", ""), "abc");
-  EXPECT_EQ(StripSuffix("abc", "c"), "ab");
-  EXPECT_EQ(StripSuffix("abc", "bc"), "a");
-  EXPECT_EQ(StripSuffix("abc", "abc"), "");
-  EXPECT_EQ(StripSuffix("abc", "ebcd"), "abc");
-
-  EXPECT_EQ(StripChars("foobar", "", '_'), "foobar");
-  EXPECT_EQ(StripChars("foobar", "x", '_'), "foobar");
-  EXPECT_EQ(StripChars("foobar", "f", '_'), "_oobar");
-  EXPECT_EQ(StripChars("foobar", "o", '_'), "f__bar");
-  EXPECT_EQ(StripChars("foobar", "oa", '_'), "f__b_r");
-  EXPECT_EQ(StripChars("foobar", "fbr", '_'), "_oo_a_");
-  EXPECT_EQ(StripChars("foobar", "froab", '_'), "______");
-}
-
-TEST(StringUtilsTest, Contains) {
-  EXPECT_TRUE(Contains("", ""));
-  EXPECT_TRUE(Contains("abc", ""));
-  EXPECT_TRUE(Contains("abc", "a"));
-  EXPECT_TRUE(Contains("abc", "b"));
-  EXPECT_TRUE(Contains("abc", "c"));
-  EXPECT_TRUE(Contains("abc", "ab"));
-  EXPECT_TRUE(Contains("abc", "bc"));
-  EXPECT_TRUE(Contains("abc", "abc"));
-  EXPECT_FALSE(Contains("abc", "d"));
-  EXPECT_FALSE(Contains("abc", "ac"));
-  EXPECT_FALSE(Contains("abc", "abcd"));
-  EXPECT_FALSE(Contains("", "a"));
-  EXPECT_FALSE(Contains("", "abc"));
-}
-
-TEST(StringUtilsTest, Find) {
-  EXPECT_EQ(Find("", ""), 0u);
-  EXPECT_EQ(Find("", "abc"), 0u);
-  EXPECT_EQ(Find("a", "abc"), 0u);
-  EXPECT_EQ(Find("b", "abc"), 1u);
-  EXPECT_EQ(Find("c", "abc"), 2u);
-  EXPECT_EQ(Find("ab", "abc"), 0u);
-  EXPECT_EQ(Find("bc", "abc"), 1u);
-  EXPECT_EQ(Find("abc", "abc"), 0u);
-  EXPECT_EQ(Find("d", "abc"), std::string::npos);
-  EXPECT_EQ(Find("ac", "abc"), std::string::npos);
-  EXPECT_EQ(Find("abcd", "abc"), std::string::npos);
-  EXPECT_EQ(Find("a", ""), std::string::npos);
-  EXPECT_EQ(Find("abc", ""), std::string::npos);
-}
-
 }  // namespace
 }  // namespace base
 }  // namespace perfetto
diff --git a/src/base/string_view.cc b/src/base/string_view.cc
index 7292546..b10239d 100644
--- a/src/base/string_view.cc
+++ b/src/base/string_view.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/string_view.h"
+#include "perfetto/base/string_view.h"
 
 namespace perfetto {
 namespace base {
diff --git a/src/base/string_view_unittest.cc b/src/base/string_view_unittest.cc
index bb00035..61dd2a6 100644
--- a/src/base/string_view_unittest.cc
+++ b/src/base/string_view_unittest.cc
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/string_view.h"
+#include "perfetto/base/string_view.h"
 
 #include <forward_list>
 #include <unordered_map>
 #include <unordered_set>
 
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace base {
@@ -53,47 +54,22 @@
     EXPECT_TRUE(x == "abc");
     EXPECT_TRUE(x == StringView("abc"));
     EXPECT_TRUE(x != StringView("abcd"));
-    EXPECT_FALSE(x == StringView("aBc"));
-    EXPECT_TRUE(x.CaseInsensitiveEq("aBc"));
-    EXPECT_TRUE(x.CaseInsensitiveEq("AbC"));
-    EXPECT_FALSE(x.CaseInsensitiveEq("AbCd"));
-    EXPECT_FALSE(x.CaseInsensitiveEq("ab"));
-    EXPECT_FALSE(x.CaseInsensitiveEq("abcd"));
-    EXPECT_FALSE(x.CaseInsensitiveEq(""));
   }
 
-  // Test find(char).
+  // Test find().
   EXPECT_EQ(StringView().find('x'), StringView::npos);
   EXPECT_EQ(StringView("").find('x'), StringView::npos);
   EXPECT_EQ(StringView("foo").find('x'), StringView::npos);
   EXPECT_EQ(StringView("foo").find('f'), 0u);
   EXPECT_EQ(StringView("foo").find('o'), 1u);
 
-  // Test rfind(char).
+  // Test rfind().
   EXPECT_EQ(StringView().rfind('x'), StringView::npos);
   EXPECT_EQ(StringView("").rfind('x'), StringView::npos);
   EXPECT_EQ(StringView("foo").rfind('x'), StringView::npos);
   EXPECT_EQ(StringView("foo").rfind('f'), 0u);
   EXPECT_EQ(StringView("foo").rfind('o'), 2u);
 
-  // Test find(const char*).
-  EXPECT_EQ(StringView().find("x"), StringView::npos);
-  EXPECT_EQ(StringView("").find("x"), StringView::npos);
-  EXPECT_EQ(StringView("foo").find("x"), StringView::npos);
-  EXPECT_EQ(StringView("foo").find("foobar"), StringView::npos);
-  EXPECT_EQ(StringView("foo").find("f", 1), StringView::npos);
-  EXPECT_EQ(StringView("foo").find("f"), 0u);
-  EXPECT_EQ(StringView("foo").find("fo"), 0u);
-  EXPECT_EQ(StringView("foo").find("oo"), 1u);
-  EXPECT_EQ(StringView("foo").find("o"), 1u);
-  EXPECT_EQ(StringView("foo").find("o", 2), 2u);
-  EXPECT_EQ(StringView("foo").find("o", 3), StringView::npos);
-  EXPECT_EQ(StringView("foo").find("o", 10), StringView::npos);
-  EXPECT_EQ(StringView("foobar").find("bar", 3), 3u);
-  EXPECT_EQ(StringView("foobar").find("bartender"), StringView::npos);
-  EXPECT_EQ(StringView("foobar").find("bartender", 3), StringView::npos);
-  EXPECT_EQ(StringView("foo").find(""), 0u);  // std::string behaves the same.
-
   // Test substr().
   EXPECT_EQ(StringView().substr(0, 0).ToStdString(), "");
   EXPECT_EQ(StringView().substr(3, 1).ToStdString(), "");
diff --git a/src/base/string_writer_unittest.cc b/src/base/string_writer_unittest.cc
index 1df52bf..f251ba6 100644
--- a/src/base/string_writer_unittest.cc
+++ b/src/base/string_writer_unittest.cc
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/string_writer.h"
+#include "perfetto/base/string_writer.h"
 
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace base {
@@ -36,11 +37,6 @@
   }
   {
     base::StringWriter writer(buffer, sizeof(buffer));
-    writer.AppendUnsignedInt(523);
-    ASSERT_EQ(writer.GetStringView().ToStdString(), "523");
-  }
-  {
-    base::StringWriter writer(buffer, sizeof(buffer));
     writer.AppendPaddedInt<'0', 3>(0);
     ASSERT_EQ(writer.GetStringView().ToStdString(), "000");
   }
@@ -66,11 +62,6 @@
   }
   {
     base::StringWriter writer(buffer, sizeof(buffer));
-    writer.AppendPaddedUnsignedInt<' ', 5>(123);
-    ASSERT_EQ(writer.GetStringView().ToStdString(), "  123");
-  }
-  {
-    base::StringWriter writer(buffer, sizeof(buffer));
     writer.AppendDouble(123.25);
     ASSERT_EQ(writer.GetStringView().ToStdString(), "123.250000");
   }
@@ -84,21 +75,6 @@
     writer.AppendInt(std::numeric_limits<int64_t>::max());
     ASSERT_EQ(writer.GetStringView().ToStdString(), "9223372036854775807");
   }
-  {
-    base::StringWriter writer(buffer, sizeof(buffer));
-    writer.AppendUnsignedInt(std::numeric_limits<uint64_t>::max());
-    ASSERT_EQ(writer.GetStringView().ToStdString(), "18446744073709551615");
-  }
-  {
-    base::StringWriter writer(buffer, sizeof(buffer));
-    writer.AppendBool(true);
-    ASSERT_EQ(writer.GetStringView().ToStdString(), "true");
-  }
-  {
-    base::StringWriter writer(buffer, sizeof(buffer));
-    writer.AppendBool(false);
-    ASSERT_EQ(writer.GetStringView().ToStdString(), "false");
-  }
 
   constexpr char kTestStr[] = "test";
   {
@@ -129,16 +105,13 @@
   base::StringWriter writer(buffer, sizeof(buffer));
   writer.AppendChar('0');
   writer.AppendInt(132545);
-  writer.AppendUnsignedInt(523);
   writer.AppendPaddedInt<'0', 0>(1);
   writer.AppendPaddedInt<'0', 3>(0);
   writer.AppendPaddedInt<'0', 1>(1);
   writer.AppendPaddedInt<'0', 2>(1);
   writer.AppendPaddedInt<'0', 3>(1);
   writer.AppendPaddedInt<' ', 5>(123);
-  writer.AppendPaddedUnsignedInt<' ', 5>(456);
   writer.AppendDouble(123.25);
-  writer.AppendBool(true);
 
   constexpr char kTestStr[] = "test";
   writer.AppendLiteral(kTestStr);
@@ -146,7 +119,7 @@
   writer.AppendString(kTestStr);
 
   ASSERT_EQ(writer.GetStringView().ToStdString(),
-            "01325455231000101001  123  456123.250000truetesttesttest");
+            "01325451000101001  123123.250000testtesttest");
 }
 
 }  // namespace
diff --git a/src/base/task_runner_unittest.cc b/src/base/task_runner_unittest.cc
index a8368b5..46620de 100644
--- a/src/base/task_runner_unittest.cc
+++ b/src/base/task_runner_unittest.cc
@@ -14,17 +14,22 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/unix_task_runner.h"
+#include "perfetto/base/unix_task_runner.h"
+
+#include "gtest/gtest.h"
+#include "perfetto/base/build_config.h"
+#include "perfetto/base/scoped_file.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
+    !PERFETTO_BUILDFLAG(PERFETTO_EMBEDDER_BUILD)
+#include "perfetto/base/android_task_runner.h"
+#endif
 
 #include <thread>
 
-#include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/pipe.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/file_utils.h"
+#include "perfetto/base/pipe.h"
 #include "src/base/test/gtest_test_suite.h"
-#include "test/gtest_and_gmock.h"
 
 namespace perfetto {
 namespace base {
@@ -36,7 +41,12 @@
   T task_runner;
 };
 
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
+    !PERFETTO_BUILDFLAG(PERFETTO_EMBEDDER_BUILD)
+using TaskRunnerTypes = ::testing::Types<AndroidTaskRunner, UnixTaskRunner>;
+#else
 using TaskRunnerTypes = ::testing::Types<UnixTaskRunner>;
+#endif
 
 TYPED_TEST_SUITE(TaskRunnerTest, TaskRunnerTypes);
 
diff --git a/src/base/temp_file.cc b/src/base/temp_file.cc
index 59a5089..e648108 100644
--- a/src/base/temp_file.cc
+++ b/src/base/temp_file.cc
@@ -14,10 +14,7 @@
  * limitations under the License.
  */
 
-#include "perfetto/base/build_config.h"
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-
-#include "perfetto/ext/base/temp_file.h"
+#include "perfetto/base/temp_file.h"
 
 #include <stdlib.h>
 #include <unistd.h>
@@ -44,9 +41,7 @@
   }
   temp_file.path_.append("/perfetto-XXXXXXXX");
   temp_file.fd_.reset(mkstemp(&temp_file.path_[0]));
-  if (PERFETTO_UNLIKELY(!temp_file.fd_)) {
-    PERFETTO_FATAL("Could not create temp file %s", temp_file.path_.c_str());
-  }
+  PERFETTO_CHECK(temp_file.fd_);
   return temp_file;
 }
 
@@ -95,6 +90,3 @@
 
 }  // namespace base
 }  // namespace perfetto
-
-
-#endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
diff --git a/src/base/temp_file_unittest.cc b/src/base/temp_file_unittest.cc
index c2e2f4d..d167b66 100644
--- a/src/base/temp_file_unittest.cc
+++ b/src/base/temp_file_unittest.cc
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/temp_file.h"
+#include "perfetto/base/temp_file.h"
 
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace base {
diff --git a/src/base/test/benchmark_main.cc b/src/base/test/benchmark_main.cc
index e410e52..f904cfc 100644
--- a/src/base/test/benchmark_main.cc
+++ b/src/base/test/benchmark_main.cc
@@ -12,6 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <benchmark/benchmark.h>
+#include "benchmark/benchmark.h"
 
 BENCHMARK_MAIN();
diff --git a/src/base/test/gtest_test_suite.h b/src/base/test/gtest_test_suite.h
index 4d1d550..6bf7758 100644
--- a/src/base/test/gtest_test_suite.h
+++ b/src/base/test/gtest_test_suite.h
@@ -17,7 +17,7 @@
 #ifndef SRC_BASE_TEST_GTEST_TEST_SUITE_H_
 #define SRC_BASE_TEST_GTEST_TEST_SUITE_H_
 
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
 
 // Define newer TEST_SUITE googletest APIs as aliases of the older APIs where
 // necessary. This makes it possible to migrate Perfetto to the newer APIs and
diff --git a/src/base/test/test_task_runner.h b/src/base/test/test_task_runner.h
index 2d970ec..28cb92a 100644
--- a/src/base/test/test_task_runner.h
+++ b/src/base/test/test_task_runner.h
@@ -25,12 +25,24 @@
 #include <string>
 
 #include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/thread_checker.h"
-#include "perfetto/ext/base/unix_task_runner.h"
+#include "perfetto/base/thread_checker.h"
+#include "perfetto/base/unix_task_runner.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
+    !PERFETTO_BUILDFLAG(PERFETTO_EMBEDDER_BUILD)
+#include "perfetto/base/android_task_runner.h"
+#endif
 
 namespace perfetto {
 namespace base {
 
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
+    !PERFETTO_BUILDFLAG(PERFETTO_EMBEDDER_BUILD)
+using PlatformTaskRunner = AndroidTaskRunner;
+#else
+using PlatformTaskRunner = UnixTaskRunner;
+#endif
+
 class TestTaskRunner : public TaskRunner {
  public:
   TestTaskRunner();
@@ -59,7 +71,7 @@
   std::string pending_checkpoint_;
   std::map<std::string, bool> checkpoints_;
 
-  base::UnixTaskRunner task_runner_;
+  PlatformTaskRunner task_runner_;
   ThreadChecker thread_checker_;
 };
 
diff --git a/src/base/test/utils.cc b/src/base/test/utils.cc
index 188038a..9e2ff4c 100644
--- a/src/base/test/utils.cc
+++ b/src/base/test/utils.cc
@@ -33,6 +33,11 @@
 namespace base {
 
 std::string GetTestDataPath(const std::string& path) {
+  char const* test_data_root = getenv("TEST_DATA_ROOT");
+  if (test_data_root) {
+    return std::string(test_data_root) + path;
+  }
+
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
     PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
@@ -44,16 +49,12 @@
   std::string self_path = std::string(buf);
   // Cut binary name.
   self_path = self_path.substr(0, self_path.find_last_of("/"));
-  std::string full_path = self_path + "/../../" + path;
-  if (access(full_path.c_str(), F_OK) == 0)
-    return full_path;
-  full_path = self_path + "/" + path;
-  if (access(full_path.c_str(), F_OK) == 0)
-    return full_path;
-#endif
+  return self_path + "/../../test/data/" + path;
+#else
   // TODO(hjd): Implement on MacOS/Windows
   // Fall back to relative to root dir.
-  return path;
+  return "test/data/" + path;
+#endif
 }
 
 }  // namespace base
diff --git a/src/base/test/utils.h b/src/base/test/utils.h
index c2125e7..b3677b9 100644
--- a/src/base/test/utils.h
+++ b/src/base/test/utils.h
@@ -19,8 +19,10 @@
 
 #include <string>
 
+#include "gtest/gtest.h"
 #include "perfetto/base/logging.h"
 
+#if defined(GTEST_HAS_DEATH_TEST)
 #if PERFETTO_DCHECK_IS_ON()
 
 #define EXPECT_DCHECK_DEATH(statement) EXPECT_DEATH(statement, "PERFETTO_CHECK")
@@ -34,6 +36,7 @@
     GTEST_EXECUTE_STATEMENT_(statement, "PERFETTO_CHECK")
 
 #endif  // PERFETTO_DCHECK_IS_ON()
+#endif  // defined(GTEST_HAS_DEATH_TEST)
 
 namespace perfetto {
 namespace base {
diff --git a/src/base/test/vm_test_utils.cc b/src/base/test/vm_test_utils.cc
index 2efa845..619fcbf 100644
--- a/src/base/test/vm_test_utils.cc
+++ b/src/base/test/vm_test_utils.cc
@@ -17,7 +17,7 @@
 #include "src/base/test/vm_test_utils.h"
 
 #include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/utils.h"
 
 #include <memory>
 
@@ -25,24 +25,22 @@
 #include <string.h>
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#include <vector>
-
 #include <Windows.h>
 #include <Psapi.h>
-#else  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#else
 #include <sys/mman.h>
 #include <sys/stat.h>
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#endif
 
+#include "gtest/gtest.h"
 #include "perfetto/base/build_config.h"
-#include "perfetto/base/logging.h"
 
 namespace perfetto {
 namespace base {
 namespace vm_test_utils {
 
 bool IsMapped(void* start, size_t size) {
-  PERFETTO_CHECK(size % kPageSize == 0);
+  EXPECT_EQ(0u, size % kPageSize);
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
   int retries = 5;
   int number_of_entries = 4000;  // Just a guess.
@@ -63,7 +61,10 @@
     if (QueryWorkingSet(GetCurrentProcess(), &buffer[0], buffer_size))
       break;  // Success
 
-    PERFETTO_CHECK(GetLastError() == ERROR_BAD_LENGTH);
+    if (GetLastError() != ERROR_BAD_LENGTH) {
+      EXPECT_EQ(true, false);
+      return false;
+    }
 
     number_of_entries = ws_info->NumberOfEntries;
 
@@ -71,7 +72,11 @@
     // take that into account. Increasing by 10% should generally be enough.
     number_of_entries *= 1.1;
 
-    PERFETTO_CHECK(--retries > 0);  // If we're looping, eventually fail.
+    if (--retries == 0) {
+      // If we're looping, eventually fail.
+      EXPECT_EQ(true, false);
+      return false;
+    }
   }
 
   void* end = reinterpret_cast<char*>(start) + size;
@@ -107,7 +112,7 @@
   // MacOS instead returns 0 but leaves the page_states empty.
   if (res == -1 && errno == ENOMEM)
     return false;
-  PERFETTO_CHECK(res == 0);
+  EXPECT_EQ(0, res);
   for (size_t i = 0; i < num_pages; i++) {
     if (!(page_states[i] & kIncoreMask))
       return false;
diff --git a/src/base/thread_checker.cc b/src/base/thread_checker.cc
index 501abbb..c723dbe 100644
--- a/src/base/thread_checker.cc
+++ b/src/base/thread_checker.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/thread_checker.h"
+#include "perfetto/base/thread_checker.h"
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 #include <Windows.h>
diff --git a/src/base/thread_checker_unittest.cc b/src/base/thread_checker_unittest.cc
index f63ec5d..b1bdc3d 100644
--- a/src/base/thread_checker_unittest.cc
+++ b/src/base/thread_checker_unittest.cc
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/thread_checker.h"
+#include "perfetto/base/thread_checker.h"
 
 #include <pthread.h>
 
 #include <functional>
 #include <memory>
 
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace base {
diff --git a/src/base/thread_task_runner.cc b/src/base/thread_task_runner.cc
index 0576ee9..a545e6b 100644
--- a/src/base/thread_task_runner.cc
+++ b/src/base/thread_task_runner.cc
@@ -14,10 +14,7 @@
  * limitations under the License.
  */
 
-#include "perfetto/base/build_config.h"
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-
-#include "perfetto/ext/base/thread_task_runner.h"
+#include "perfetto/base/thread_task_runner.h"
 
 #include <condition_variable>
 #include <functional>
@@ -25,7 +22,7 @@
 #include <thread>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/unix_task_runner.h"
+#include "perfetto/base/unix_task_runner.h"
 
 namespace perfetto {
 namespace base {
@@ -82,5 +79,3 @@
 
 }  // namespace base
 }  // namespace perfetto
-
-#endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
diff --git a/src/base/thread_task_runner_unittest.cc b/src/base/thread_task_runner_unittest.cc
index 0e7f2af..823967b 100644
--- a/src/base/thread_task_runner_unittest.cc
+++ b/src/base/thread_task_runner_unittest.cc
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/thread_task_runner.h"
+#include "perfetto/base/thread_task_runner.h"
 
 #include <thread>
 
-#include "perfetto/ext/base/thread_checker.h"
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/thread_checker.h"
 
 namespace perfetto {
 namespace base {
diff --git a/src/base/time.cc b/src/base/time.cc
index 01bf02d..8e22d59 100644
--- a/src/base/time.cc
+++ b/src/base/time.cc
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#include "perfetto/base/time.h"
 #include "perfetto/base/build_config.h"
+#include "perfetto/base/time.h"
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 #include <Windows.h>
diff --git a/src/base/time_unittest.cc b/src/base/time_unittest.cc
index 04b40aa..ee1aa9d 100644
--- a/src/base/time_unittest.cc
+++ b/src/base/time_unittest.cc
@@ -16,7 +16,7 @@
 
 #include "perfetto/base/time.h"
 
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace base {
diff --git a/src/base/unix_socket.cc b/src/base/unix_socket.cc
index e63f978..1a8364f 100644
--- a/src/base/unix_socket.cc
+++ b/src/base/unix_socket.cc
@@ -14,12 +14,10 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/unix_socket.h"
+#include "perfetto/base/unix_socket.h"
 
 #include <errno.h>
 #include <fcntl.h>
-#include <netdb.h>
-#include <netinet/in.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
@@ -34,8 +32,7 @@
 #include "perfetto/base/build_config.h"
 #include "perfetto/base/logging.h"
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/utils.h"
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
 #include <sys/ucred.h>
@@ -51,7 +48,6 @@
 #endif
 
 namespace {
-
 // MSG_NOSIGNAL is not supported on Mac OS X, but in that case the socket is
 // created with SO_NOSIGPIPE (See InitializeSocket()).
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
@@ -67,36 +63,7 @@
 using CBufLenType = socklen_t;
 #endif
 
-// A wrapper around variable-size sockaddr structs.
-// This is solving the following problem: when calling connect() or bind(), the
-// caller needs to take care to allocate the right struct (sockaddr_un for
-// AF_UNIX, sockaddr_in for AF_INET).   Those structs have different sizes and,
-// more importantly, are bigger than the base struct sockaddr.
-struct SockaddrAny {
-  SockaddrAny() : size() {}
-  SockaddrAny(const void* addr, socklen_t sz) : data(new char[sz]), size(sz) {
-    memcpy(data.get(), addr, static_cast<size_t>(size));
-  }
-
-  const struct sockaddr* addr() const {
-    return reinterpret_cast<const struct sockaddr*>(data.get());
-  }
-
-  std::unique_ptr<char[]> data;
-  socklen_t size;
-};
-
-inline int GetSockFamily(SockFamily family) {
-  switch (family) {
-    case SockFamily::kUnix:
-      return AF_UNIX;
-    case SockFamily::kInet:
-      return AF_INET;
-  }
-  PERFETTO_CHECK(false);  // For GCC.
-}
-
-inline int GetSockType(SockType type) {
+inline int GetUnixSockType(SockType type) {
   switch (type) {
     case SockType::kStream:
       return SOCK_STREAM;
@@ -105,42 +72,25 @@
     case SockType::kSeqPacket:
       return SOCK_SEQPACKET;
   }
-  PERFETTO_CHECK(false);  // For GCC.
+  PERFETTO_CHECK(false);
 }
 
-SockaddrAny MakeSockAddr(SockFamily family, const std::string& socket_name) {
-  switch (family) {
-    case SockFamily::kUnix: {
-      struct sockaddr_un saddr {};
-      const size_t name_len = socket_name.size();
-      if (name_len >= sizeof(saddr.sun_path)) {
-        errno = ENAMETOOLONG;
-        return SockaddrAny();
-      }
-      memcpy(saddr.sun_path, socket_name.data(), name_len);
-      if (saddr.sun_path[0] == '@')
-        saddr.sun_path[0] = '\0';
-      saddr.sun_family = AF_UNIX;
-      auto size = static_cast<socklen_t>(
-          __builtin_offsetof(sockaddr_un, sun_path) + name_len + 1);
-      PERFETTO_CHECK(static_cast<size_t>(size) <= sizeof(saddr));
-      return SockaddrAny(&saddr, size);
-    }
-    case SockFamily::kInet: {
-      auto parts = SplitString(socket_name, ":");
-      PERFETTO_CHECK(parts.size() == 2);
-      struct addrinfo* addr_info = nullptr;
-      struct addrinfo hints {};
-      hints.ai_family = AF_INET;
-      PERFETTO_CHECK(getaddrinfo(parts[0].c_str(), parts[1].c_str(), &hints,
-                                 &addr_info) == 0);
-      PERFETTO_CHECK(addr_info->ai_family == AF_INET);
-      SockaddrAny res(addr_info->ai_addr, addr_info->ai_addrlen);
-      freeaddrinfo(addr_info);
-      return res;
-    }
+bool MakeSockAddr(const std::string& socket_name,
+                  sockaddr_un* addr,
+                  socklen_t* addr_size) {
+  memset(addr, 0, sizeof(*addr));
+  const size_t name_len = socket_name.size();
+  if (name_len >= sizeof(addr->sun_path)) {
+    errno = ENAMETOOLONG;
+    return false;
   }
-  PERFETTO_CHECK(false);  // For GCC.
+  memcpy(addr->sun_path, socket_name.data(), name_len);
+  if (addr->sun_path[0] == '@')
+    addr->sun_path[0] = '\0';
+  addr->sun_family = AF_UNIX;
+  *addr_size = static_cast<socklen_t>(
+      __builtin_offsetof(sockaddr_un, sun_path) + name_len + 1);
+  return true;
 }
 
 }  // namespace
@@ -172,39 +122,29 @@
 }
 
 // static
-std::pair<UnixSocketRaw, UnixSocketRaw> UnixSocketRaw::CreatePair(
-    SockFamily family,
-    SockType type) {
+std::pair<UnixSocketRaw, UnixSocketRaw> UnixSocketRaw::CreatePair(SockType t) {
   int fds[2];
-  if (socketpair(GetSockFamily(family), GetSockType(type), 0, fds) != 0)
+  if (socketpair(AF_UNIX, GetUnixSockType(t), 0, fds) != 0)
     return std::make_pair(UnixSocketRaw(), UnixSocketRaw());
 
-  return std::make_pair(UnixSocketRaw(ScopedFile(fds[0]), family, type),
-                        UnixSocketRaw(ScopedFile(fds[1]), family, type));
+  return std::make_pair(UnixSocketRaw(ScopedFile(fds[0]), t),
+                        UnixSocketRaw(ScopedFile(fds[1]), t));
 }
 
 UnixSocketRaw::UnixSocketRaw() = default;
 
-UnixSocketRaw::UnixSocketRaw(SockFamily family, SockType type)
-    : UnixSocketRaw(
-          ScopedFile(socket(GetSockFamily(family), GetSockType(type), 0)),
-          family,
-          type) {}
+UnixSocketRaw::UnixSocketRaw(SockType type)
+    : UnixSocketRaw(ScopedFile(socket(AF_UNIX, GetUnixSockType(type), 0)),
+                    type) {}
 
-UnixSocketRaw::UnixSocketRaw(ScopedFile fd, SockFamily family, SockType type)
-    : fd_(std::move(fd)), family_(family), type_(type) {
+UnixSocketRaw::UnixSocketRaw(ScopedFile fd, SockType type)
+    : fd_(std::move(fd)), type_(type) {
   PERFETTO_CHECK(fd_);
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
   const int no_sigpipe = 1;
   setsockopt(*fd_, SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe, sizeof(no_sigpipe));
 #endif
 
-  if (family == SockFamily::kInet) {
-    int flag = 1;
-    PERFETTO_CHECK(
-        !setsockopt(*fd_, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)));
-  }
-
   // There is no reason why a socket should outlive the process in case of
   // exec() by default, this is just working around a broken unix design.
   int fcntl_res = fcntl(*fd_, F_SETFD, FD_CLOEXEC);
@@ -238,11 +178,12 @@
 
 bool UnixSocketRaw::Bind(const std::string& socket_name) {
   PERFETTO_DCHECK(fd_);
-  SockaddrAny addr = MakeSockAddr(family_, socket_name);
-  if (addr.size == 0)
+  sockaddr_un addr;
+  socklen_t addr_size;
+  if (!MakeSockAddr(socket_name, &addr, &addr_size))
     return false;
 
-  if (bind(*fd_, addr.addr(), addr.size)) {
+  if (bind(*fd_, reinterpret_cast<sockaddr*>(&addr), addr_size)) {
     PERFETTO_DPLOG("bind(%s)", socket_name.c_str());
     return false;
   }
@@ -258,11 +199,13 @@
 
 bool UnixSocketRaw::Connect(const std::string& socket_name) {
   PERFETTO_DCHECK(fd_);
-  SockaddrAny addr = MakeSockAddr(family_, socket_name);
-  if (addr.size == 0)
+  sockaddr_un addr;
+  socklen_t addr_size;
+  if (!MakeSockAddr(socket_name, &addr, &addr_size))
     return false;
 
-  int res = PERFETTO_EINTR(connect(*fd_, addr.addr(), addr.size));
+  int res = PERFETTO_EINTR(
+      connect(*fd_, reinterpret_cast<sockaddr*>(&addr), addr_size));
   if (res && errno != EINPROGRESS)
     return false;
 
@@ -428,36 +371,32 @@
 std::unique_ptr<UnixSocket> UnixSocket::Listen(const std::string& socket_name,
                                                EventListener* event_listener,
                                                TaskRunner* task_runner,
-                                               SockFamily sock_family,
                                                SockType sock_type) {
-  auto sock_raw = UnixSocketRaw::CreateMayFail(sock_family, sock_type);
+  auto sock_raw = UnixSocketRaw::CreateMayFail(sock_type);
   if (!sock_raw || !sock_raw.Bind(socket_name))
     return nullptr;
 
   // Forward the call to the Listen() overload below.
-  return Listen(sock_raw.ReleaseFd(), event_listener, task_runner, sock_family,
-                sock_type);
+  return Listen(sock_raw.ReleaseFd(), event_listener, task_runner, sock_type);
 }
 
 // static
 std::unique_ptr<UnixSocket> UnixSocket::Listen(ScopedFile fd,
                                                EventListener* event_listener,
                                                TaskRunner* task_runner,
-                                               SockFamily sock_family,
                                                SockType sock_type) {
   return std::unique_ptr<UnixSocket>(
       new UnixSocket(event_listener, task_runner, std::move(fd),
-                     State::kListening, sock_family, sock_type));
+                     State::kListening, sock_type));
 }
 
 // static
 std::unique_ptr<UnixSocket> UnixSocket::Connect(const std::string& socket_name,
                                                 EventListener* event_listener,
                                                 TaskRunner* task_runner,
-                                                SockFamily sock_family,
                                                 SockType sock_type) {
   std::unique_ptr<UnixSocket> sock(
-      new UnixSocket(event_listener, task_runner, sock_family, sock_type));
+      new UnixSocket(event_listener, task_runner, sock_type));
   sock->DoConnect(socket_name);
   return sock;
 }
@@ -467,29 +406,25 @@
     ScopedFile fd,
     EventListener* event_listener,
     TaskRunner* task_runner,
-    SockFamily sock_family,
     SockType sock_type) {
   return std::unique_ptr<UnixSocket>(
       new UnixSocket(event_listener, task_runner, std::move(fd),
-                     State::kConnected, sock_family, sock_type));
+                     State::kConnected, sock_type));
 }
 
 UnixSocket::UnixSocket(EventListener* event_listener,
                        TaskRunner* task_runner,
-                       SockFamily sock_family,
                        SockType sock_type)
     : UnixSocket(event_listener,
                  task_runner,
                  ScopedFile(),
                  State::kDisconnected,
-                 sock_family,
                  sock_type) {}
 
 UnixSocket::UnixSocket(EventListener* event_listener,
                        TaskRunner* task_runner,
                        ScopedFile adopt_fd,
                        State adopt_state,
-                       SockFamily sock_family,
                        SockType sock_type)
     : event_listener_(event_listener),
       task_runner_(task_runner),
@@ -497,14 +432,14 @@
   state_ = State::kDisconnected;
   if (adopt_state == State::kDisconnected) {
     PERFETTO_DCHECK(!adopt_fd);
-    sock_raw_ = UnixSocketRaw::CreateMayFail(sock_family, sock_type);
+    sock_raw_ = UnixSocketRaw::CreateMayFail(sock_type);
     if (!sock_raw_) {
       last_error_ = errno;
       return;
     }
   } else if (adopt_state == State::kConnected) {
     PERFETTO_DCHECK(adopt_fd);
-    sock_raw_ = UnixSocketRaw(std::move(adopt_fd), sock_family, sock_type);
+    sock_raw_ = UnixSocketRaw(std::move(adopt_fd), sock_type);
     state_ = State::kConnected;
     ReadPeerCredentials();
   } else if (adopt_state == State::kListening) {
@@ -516,7 +451,7 @@
       return;
     }
 
-    sock_raw_ = UnixSocketRaw(std::move(adopt_fd), sock_family, sock_type);
+    sock_raw_ = UnixSocketRaw(std::move(adopt_fd), sock_type);
     if (!sock_raw_.Listen()) {
       last_error_ = errno;
       PERFETTO_DPLOG("listen()");
@@ -533,7 +468,6 @@
   sock_raw_.SetBlocking(false);
 
   WeakPtr<UnixSocket> weak_ptr = weak_ptr_factory_.GetWeakPtr();
-
   task_runner_->AddFileDescriptorWatch(sock_raw_.fd(), [weak_ptr] {
     if (weak_ptr)
       weak_ptr->OnEvent();
@@ -588,10 +522,6 @@
 }
 
 void UnixSocket::ReadPeerCredentials() {
-  // Peer credentials are supported only on AF_UNIX sockets.
-  if (sock_raw_.family() != SockFamily::kUnix)
-    return;
-
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
   struct ucred user_cred;
@@ -624,7 +554,6 @@
     socklen_t err_len = sizeof(sock_err);
     int res =
         getsockopt(sock_raw_.fd(), SOL_SOCKET, SO_ERROR, &sock_err, &err_len);
-
     if (res == 0 && sock_err == EINPROGRESS)
       return;  // Not connected yet, just a spurious FD watch wakeup.
     if (res == 0 && sock_err == 0) {
@@ -632,7 +561,6 @@
       state_ = State::kConnected;
       return event_listener_->OnConnect(this, true /* connected */);
     }
-    PERFETTO_DLOG("Connection error: %s", strerror(sock_err));
     last_error_ = sock_err;
     Shutdown(false);
     return event_listener_->OnConnect(this, false /* connected */);
@@ -643,15 +571,15 @@
     // There could be more than one incoming connection behind each FD watch
     // notification. Drain'em all.
     for (;;) {
-      struct sockaddr_in cli_addr {};
+      sockaddr_un cli_addr = {};
       socklen_t size = sizeof(cli_addr);
       ScopedFile new_fd(PERFETTO_EINTR(accept(
           sock_raw_.fd(), reinterpret_cast<sockaddr*>(&cli_addr), &size)));
       if (!new_fd)
         return;
-      std::unique_ptr<UnixSocket> new_sock(new UnixSocket(
-          event_listener_, task_runner_, std::move(new_fd), State::kConnected,
-          sock_raw_.family(), sock_raw_.type()));
+      std::unique_ptr<UnixSocket> new_sock(
+          new UnixSocket(event_listener_, task_runner_, std::move(new_fd),
+                         State::kConnected, sock_raw_.type()));
       event_listener_->OnNewIncomingConnection(this, std::move(new_sock));
     }
   }
@@ -683,7 +611,7 @@
     return true;
   }
 
-  // If sendmsg() succeeds but the returned size is < |len| it means that the
+  // If sendmsg() succeds but the returned size is < |len| it means that the
   // endpoint disconnected in the middle of the read, and we managed to send
   // only a portion of the buffer. In this case we should just give up.
 
@@ -695,7 +623,7 @@
     return false;
   }
 
-  // Either the other endpoint disconnected (ECONNRESET) or some other error
+  // Either the the other endpoint disconnect (ECONNRESET) or some other error
   // happened.
   last_error_ = saved_errno;
   PERFETTO_DPLOG("sendmsg() failed");
diff --git a/src/base/unix_socket_unittest.cc b/src/base/unix_socket_unittest.cc
index 138f631..5ea646e 100644
--- a/src/base/unix_socket_unittest.cc
+++ b/src/base/unix_socket_unittest.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/unix_socket.h"
+#include "perfetto/base/unix_socket.h"
 
 #include <signal.h>
 #include <sys/mman.h>
@@ -24,15 +24,16 @@
 #include <list>
 #include <thread>
 
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 #include "perfetto/base/build_config.h"
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/pipe.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/pipe.h"
+#include "perfetto/base/temp_file.h"
+#include "perfetto/base/utils.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/ipc/test/test_socket.h"
-#include "test/gtest_and_gmock.h"
 
 namespace perfetto {
 namespace base {
@@ -84,8 +85,7 @@
 };
 
 TEST_F(UnixSocketTest, ConnectionFailureIfUnreachable) {
-  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_,
-                                 SockFamily::kUnix, SockType::kStream);
+  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_);
   ASSERT_FALSE(cli->is_connected());
   auto checkpoint = task_runner_.CreateCheckpoint("failure");
   EXPECT_CALL(event_listener_, OnConnect(cli.get(), false))
@@ -96,8 +96,7 @@
 // Both server and client should see an OnDisconnect() if the server drops
 // incoming connections immediately as they are created.
 TEST_F(UnixSocketTest, ConnectionImmediatelyDroppedByServer) {
-  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_,
-                                SockFamily::kUnix, SockType::kStream);
+  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_);
   ASSERT_TRUE(srv->is_listening());
 
   // The server will immediately shutdown the connection upon
@@ -112,8 +111,7 @@
           }));
 
   auto checkpoint = task_runner_.CreateCheckpoint("cli_connected");
-  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_,
-                                 SockFamily::kUnix, SockType::kStream);
+  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_);
   EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
       .WillOnce(InvokeWithoutArgs(checkpoint));
   task_runner_.RunUntilCheckpoint("cli_connected");
@@ -128,12 +126,10 @@
 }
 
 TEST_F(UnixSocketTest, ClientAndServerExchangeData) {
-  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_,
-                                SockFamily::kUnix, SockType::kStream);
+  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_);
   ASSERT_TRUE(srv->is_listening());
 
-  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_,
-                                 SockFamily::kUnix, SockType::kStream);
+  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_);
   EXPECT_CALL(event_listener_, OnConnect(cli.get(), true));
   auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
   auto srv_disconnected = task_runner_.CreateCheckpoint("srv_disconnected");
@@ -189,12 +185,10 @@
 constexpr char srv_str[] = "srv>cli";
 
 TEST_F(UnixSocketTest, ClientAndServerExchangeFDs) {
-  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_,
-                                SockFamily::kUnix, SockType::kStream);
+  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_);
   ASSERT_TRUE(srv->is_listening());
 
-  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_,
-                                 SockFamily::kUnix, SockType::kStream);
+  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_);
   EXPECT_CALL(event_listener_, OnConnect(cli.get(), true));
   auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
   auto srv_disconnected = task_runner_.CreateCheckpoint("srv_disconnected");
@@ -273,16 +267,13 @@
 }
 
 TEST_F(UnixSocketTest, ListenWithPassedFileDescriptor) {
-  auto sock_raw =
-      UnixSocketRaw::CreateMayFail(SockFamily::kUnix, SockType::kStream);
+  auto sock_raw = UnixSocketRaw::CreateMayFail(SockType::kStream);
   ASSERT_TRUE(sock_raw.Bind(kSocketName));
   auto fd = sock_raw.ReleaseFd();
-  auto srv = UnixSocket::Listen(std::move(fd), &event_listener_, &task_runner_,
-                                SockFamily::kUnix, SockType::kStream);
+  auto srv = UnixSocket::Listen(std::move(fd), &event_listener_, &task_runner_);
   ASSERT_TRUE(srv->is_listening());
 
-  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_,
-                                 SockFamily::kUnix, SockType::kStream);
+  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_);
   EXPECT_CALL(event_listener_, OnConnect(cli.get(), true));
   auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
   auto srv_disconnected = task_runner_.CreateCheckpoint("srv_disconnected");
@@ -306,8 +297,7 @@
 // Mostly a stress tests. Connects kNumClients clients to the same server and
 // tests that all can exchange data and can see the expected sequence of events.
 TEST_F(UnixSocketTest, SeveralClients) {
-  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_,
-                                SockFamily::kUnix, SockType::kStream);
+  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_);
   ASSERT_TRUE(srv->is_listening());
   constexpr size_t kNumClients = 32;
   std::unique_ptr<UnixSocket> cli[kNumClients];
@@ -323,8 +313,7 @@
       }));
 
   for (size_t i = 0; i < kNumClients; i++) {
-    cli[i] = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_,
-                                 SockFamily::kUnix, SockType::kStream);
+    cli[i] = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_);
     EXPECT_CALL(event_listener_, OnConnect(cli[i].get(), true))
         .WillOnce(Invoke([](UnixSocket* s, bool success) {
           ASSERT_TRUE(success);
@@ -364,8 +353,7 @@
     ASSERT_NE(nullptr, mem);
     memcpy(mem, "shm rocks", 10);
 
-    auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_,
-                                  SockFamily::kUnix, SockType::kStream);
+    auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_);
     ASSERT_TRUE(srv->is_listening());
     // Signal the other process that it can connect.
     ASSERT_EQ(1, base::WriteAll(*pipe.wr, ".", 1));
@@ -390,8 +378,8 @@
     char sync_cmd = '\0';
     ASSERT_EQ(1, PERFETTO_EINTR(read(*pipe.rd, &sync_cmd, 1)));
     ASSERT_EQ('.', sync_cmd);
-    auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_,
-                                   SockFamily::kUnix, SockType::kStream);
+    auto cli =
+        UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_);
     EXPECT_CALL(event_listener_, OnConnect(cli.get(), true));
     auto checkpoint = task_runner_.CreateCheckpoint("change_seen_by_client");
     EXPECT_CALL(event_listener_, OnDataAvailable(cli.get()))
@@ -425,8 +413,7 @@
 // layer needs to rely on this to validate messages received immediately before
 // a client disconnects.
 TEST_F(UnixSocketTest, PeerCredentialsRetainedAfterDisconnect) {
-  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_,
-                                SockFamily::kUnix, SockType::kStream);
+  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_);
   ASSERT_TRUE(srv->is_listening());
   UnixSocket* srv_client_conn = nullptr;
   auto srv_connected = task_runner_.CreateCheckpoint("srv_connected");
@@ -437,13 +424,12 @@
             EXPECT_EQ(geteuid(), static_cast<uint32_t>(srv_conn->peer_uid()));
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-            EXPECT_EQ(getpid(), static_cast<pid_t>(srv_conn->peer_pid()));
+            EXPECT_EQ(getpid(), static_cast<uint32_t>(srv_conn->peer_pid()));
 #endif
             srv_connected();
           }));
   auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
-  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_,
-                                 SockFamily::kUnix, SockType::kStream);
+  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_);
   EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
       .WillOnce(InvokeWithoutArgs(cli_connected));
 
@@ -468,13 +454,12 @@
   EXPECT_EQ(geteuid(), static_cast<uint32_t>(srv_client_conn->peer_uid()));
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  EXPECT_EQ(getpid(), static_cast<pid_t>(srv_client_conn->peer_pid()));
+  EXPECT_EQ(getpid(), static_cast<uint32_t>(srv_client_conn->peer_pid()));
 #endif
 }
 
 TEST_F(UnixSocketTest, BlockingSend) {
-  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_,
-                                SockFamily::kUnix, SockType::kStream);
+  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_);
   ASSERT_TRUE(srv->is_listening());
 
   auto all_frames_done = task_runner_.CreateCheckpoint("all_frames_done");
@@ -501,8 +486,7 @@
   std::thread tx_thread([] {
     TestTaskRunner tx_task_runner;
     MockEventListener tx_events;
-    auto cli = UnixSocket::Connect(kSocketName, &tx_events, &tx_task_runner,
-                                   SockFamily::kUnix, SockType::kStream);
+    auto cli = UnixSocket::Connect(kSocketName, &tx_events, &tx_task_runner);
 
     auto cli_connected = tx_task_runner.CreateCheckpoint("cli_connected");
     EXPECT_CALL(tx_events, OnConnect(cli.get(), true))
@@ -527,8 +511,7 @@
 // sender is in the middle of a large send(), the socket should gracefully give
 // up (i.e. Shutdown()) but not crash.
 TEST_F(UnixSocketTest, ReceiverDisconnectsDuringSend) {
-  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_,
-                                SockFamily::kUnix, SockType::kStream);
+  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_);
   ASSERT_TRUE(srv->is_listening());
   const int kTimeoutMs = 30000;
 
@@ -549,8 +532,7 @@
   std::thread tx_thread([] {
     TestTaskRunner tx_task_runner;
     MockEventListener tx_events;
-    auto cli = UnixSocket::Connect(kSocketName, &tx_events, &tx_task_runner,
-                                   SockFamily::kUnix, SockType::kStream);
+    auto cli = UnixSocket::Connect(kSocketName, &tx_events, &tx_task_runner);
 
     auto cli_connected = tx_task_runner.CreateCheckpoint("cli_connected");
     EXPECT_CALL(tx_events, OnConnect(cli.get(), true))
@@ -592,19 +574,19 @@
   EXPECT_NE(hdr.msg_iov, nullptr);
   EXPECT_EQ(hdr.msg_iov[0].iov_base, &hello[1]);
   EXPECT_EQ(hdr.msg_iov[1].iov_base, &world[0]);
-  EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 2);
+  EXPECT_EQ(hdr.msg_iovlen, 2);
   EXPECT_STREQ(reinterpret_cast<char*>(hdr.msg_iov[0].iov_base), "ello");
   EXPECT_EQ(iov[0].iov_len, base::ArraySize(hello) - 1);
 
   UnixSocketRaw::ShiftMsgHdr(base::ArraySize(hello) - 1, &hdr);
   EXPECT_EQ(hdr.msg_iov, &iov[1]);
-  EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 1);
+  EXPECT_EQ(hdr.msg_iovlen, 1);
   EXPECT_STREQ(reinterpret_cast<char*>(hdr.msg_iov[0].iov_base), world);
   EXPECT_EQ(hdr.msg_iov[0].iov_len, base::ArraySize(world));
 
   UnixSocketRaw::ShiftMsgHdr(base::ArraySize(world), &hdr);
   EXPECT_EQ(hdr.msg_iov, nullptr);
-  EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 0);
+  EXPECT_EQ(hdr.msg_iovlen, 0);
 }
 
 TEST_F(UnixSocketTest, ShiftMsgHdrSendFirstAndPartial) {
@@ -624,13 +606,13 @@
 
   UnixSocketRaw::ShiftMsgHdr(base::ArraySize(hello) + 1, &hdr);
   EXPECT_NE(hdr.msg_iov, nullptr);
-  EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 1);
+  EXPECT_EQ(hdr.msg_iovlen, 1);
   EXPECT_STREQ(reinterpret_cast<char*>(hdr.msg_iov[0].iov_base), "orld");
   EXPECT_EQ(hdr.msg_iov[0].iov_len, base::ArraySize(world) - 1);
 
   UnixSocketRaw::ShiftMsgHdr(base::ArraySize(world) - 1, &hdr);
   EXPECT_EQ(hdr.msg_iov, nullptr);
-  EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 0);
+  EXPECT_EQ(hdr.msg_iovlen, 0);
 }
 
 TEST_F(UnixSocketTest, ShiftMsgHdrSendEverything) {
@@ -651,7 +633,7 @@
   UnixSocketRaw::ShiftMsgHdr(base::ArraySize(world) + base::ArraySize(hello),
                              &hdr);
   EXPECT_EQ(hdr.msg_iov, nullptr);
-  EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 0);
+  EXPECT_EQ(hdr.msg_iovlen, 0);
 }
 
 void Handler(int) {}
@@ -663,8 +645,7 @@
 TEST_F(UnixSocketTest, PartialSendMsgAll) {
   UnixSocketRaw send_sock;
   UnixSocketRaw recv_sock;
-  std::tie(send_sock, recv_sock) =
-      UnixSocketRaw::CreatePair(SockFamily::kUnix, SockType::kStream);
+  std::tie(send_sock, recv_sock) = UnixSocketRaw::CreatePair(SockType::kStream);
   ASSERT_TRUE(send_sock);
   ASSERT_TRUE(recv_sock);
 
@@ -728,7 +709,7 @@
   hdr.msg_iov = iov;
   hdr.msg_iovlen = base::ArraySize(iov);
 
-  ASSERT_EQ(send_sock.SendMsgAll(&hdr), static_cast<ssize_t>(sizeof(send_buf)));
+  ASSERT_EQ(send_sock.SendMsgAll(&hdr), sizeof(send_buf));
   send_sock.Shutdown();
   th.join();
   // Make sure the re-entry logic was actually triggered.
@@ -737,8 +718,7 @@
 }
 
 TEST_F(UnixSocketTest, ReleaseSocket) {
-  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_,
-                                SockFamily::kUnix, SockType::kStream);
+  auto srv = UnixSocket::Listen(kSocketName, &event_listener_, &task_runner_);
   ASSERT_TRUE(srv->is_listening());
   auto connected = task_runner_.CreateCheckpoint("connected");
   UnixSocket* peer = nullptr;
@@ -748,8 +728,7 @@
         connected();
       }));
 
-  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_,
-                                 SockFamily::kUnix, SockType::kStream);
+  auto cli = UnixSocket::Connect(kSocketName, &event_listener_, &task_runner_);
   EXPECT_CALL(event_listener_, OnConnect(cli.get(), true));
   task_runner_.RunUntilCheckpoint("connected");
   srv->Shutdown(true);
@@ -764,62 +743,10 @@
 
   char buf[sizeof("test")];
   ASSERT_TRUE(raw_sock);
-  ASSERT_EQ(raw_sock.Receive(buf, sizeof(buf)),
-            static_cast<ssize_t>(sizeof(buf)));
+  ASSERT_EQ(raw_sock.Receive(buf, sizeof(buf)), sizeof(buf));
   ASSERT_STREQ(buf, "test");
 }
 
-TEST_F(UnixSocketTest, TcpStream) {
-  char host_and_port[32];
-  int attempt = 0;
-  std::unique_ptr<UnixSocket> srv;
-
-  // Try listening on a random port. Some ports might be taken by other syste
-  // services. Do a bunch of attempts on different ports before giving up.
-  do {
-    sprintf(host_and_port, "127.0.0.1:%d", 10000 + (rand() % 10000));
-    srv = UnixSocket::Listen(host_and_port, &event_listener_, &task_runner_,
-                             SockFamily::kInet, SockType::kStream);
-  } while ((!srv || !srv->is_listening()) && attempt++ < 10);
-  ASSERT_TRUE(srv->is_listening());
-
-  constexpr size_t kNumClients = 3;
-  std::unique_ptr<UnixSocket> cli[kNumClients];
-  EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
-      .Times(kNumClients)
-      .WillRepeatedly(Invoke([&](UnixSocket*, UnixSocket* s) {
-        // OnDisconnect() might spuriously happen depending on the dtor order.
-        EXPECT_CALL(event_listener_, OnDisconnect(s)).Times(AtLeast(0));
-        EXPECT_CALL(event_listener_, OnDataAvailable(s))
-            .WillRepeatedly(Invoke([](UnixSocket* cli_sock) {
-              cli_sock->ReceiveString();  // Read connection EOF;
-            }));
-        ASSERT_TRUE(s->Send("welcome", kBlocking));
-      }));
-
-  for (size_t i = 0; i < kNumClients; i++) {
-    cli[i] = UnixSocket::Connect(host_and_port, &event_listener_, &task_runner_,
-                                 SockFamily::kInet, SockType::kStream);
-    // PERFETTO_ILOG("cli : %p", reinterpret_cast<void*>(cli[i].get()));
-    auto checkpoint = task_runner_.CreateCheckpoint(std::to_string(i));
-    EXPECT_CALL(event_listener_, OnDisconnect(cli[i].get())).Times(AtLeast(0));
-    EXPECT_CALL(event_listener_, OnConnect(cli[i].get(), true));
-    EXPECT_CALL(event_listener_, OnDataAvailable(cli[i].get()))
-        .WillRepeatedly(Invoke([checkpoint](UnixSocket* s) {
-          auto str = s->ReceiveString();
-          if (str == "")
-            return;  // Connection EOF.
-          ASSERT_EQ("welcome", str);
-          checkpoint();
-        }));
-  }
-
-  for (size_t i = 0; i < kNumClients; i++) {
-    task_runner_.RunUntilCheckpoint(std::to_string(i));
-    ASSERT_TRUE(Mock::VerifyAndClearExpectations(cli[i].get()));
-  }
-}
-
 // TODO(primiano): add a test to check that in the case of a peer sending a fd
 // and the other end just doing a recv (without taking it), the fd is closed and
 // not left around.
diff --git a/src/base/unix_task_runner.cc b/src/base/unix_task_runner.cc
index 422947f..0b651ae 100644
--- a/src/base/unix_task_runner.cc
+++ b/src/base/unix_task_runner.cc
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-#include "perfetto/base/build_config.h"
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#include "perfetto/base/unix_task_runner.h"
 
-#include "perfetto/ext/base/unix_task_runner.h"
+#include "perfetto/base/build_config.h"
 
 #include <errno.h>
 #include <stdlib.h>
@@ -25,8 +24,6 @@
 
 #include <limits>
 
-#include "perfetto/ext/base/watchdog.h"
-
 namespace perfetto {
 namespace base {
 
@@ -117,10 +114,10 @@
 
   errno = 0;
   if (immediate_task)
-    RunTaskWithWatchdogGuard(immediate_task);
+    RunTask(immediate_task);
   errno = 0;
   if (delayed_task)
-    RunTaskWithWatchdogGuard(delayed_task);
+    RunTask(delayed_task);
 }
 
 void UnixTaskRunner::PostFileDescriptorWatches() {
@@ -166,7 +163,7 @@
     task = it->second.callback;
   }
   errno = 0;
-  RunTaskWithWatchdogGuard(task);
+  RunTask(task);
 }
 
 int UnixTaskRunner::GetDelayMsToNextTaskLocked() const {
@@ -230,5 +227,3 @@
 
 }  // namespace base
 }  // namespace perfetto
-
-#endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
diff --git a/src/base/utils_unittest.cc b/src/base/utils_unittest.cc
index 5fcc27a..1d0f834 100644
--- a/src/base/utils_unittest.cc
+++ b/src/base/utils_unittest.cc
@@ -14,16 +14,17 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/utils.h"
 
 #include <fcntl.h>
 #include <signal.h>
 #include <stdint.h>
 #include <unistd.h>
 
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/pipe.h"
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
+
+#include "perfetto/base/file_utils.h"
+#include "perfetto/base/pipe.h"
 
 namespace perfetto {
 namespace base {
diff --git a/src/base/uuid.cc b/src/base/uuid.cc
deleted file mode 100644
index 5523d62..0000000
--- a/src/base/uuid.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/ext/base/uuid.h"
-
-#include <random>
-
-#include "perfetto/base/time.h"
-
-namespace perfetto {
-namespace base {
-namespace {
-
-constexpr char kHexmap[] = {'0', '1', '2', '3', '4', '5', '6', '7',
-                            '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
-}  // namespace
-
-// See https://www.ietf.org/rfc/rfc4122.txt
-Uuid Uuidv4() {
-  static std::minstd_rand rng(static_cast<uint32_t>(GetBootTimeNs().count()));
-  Uuid uuid;
-  for (size_t i = 0; i < 16; ++i)
-    uuid[i] = static_cast<uint8_t>(rng());
-
-  // version:
-  uuid[6] = (uuid[6] & 0x0f) | 0x40;
-  // clock_seq_hi_and_reserved:
-  uuid[8] = (uuid[8] & 0x3f) | 0x80;
-
-  return uuid;
-}
-
-std::string UuidToString(const Uuid& uuid) {
-  return std::string(reinterpret_cast<const char*>(uuid.data()), uuid.size());
-}
-
-std::string UuidToPrettyString(const Uuid& uuid) {
-  std::string s(uuid.size() * 2 + 4, '-');
-  // Format is 123e4567-e89b-12d3-a456-426655443322.
-  size_t j = 0;
-  for (size_t i = 0; i < uuid.size(); ++i) {
-    if (i == 4 || i == 6 || i == 8 || i == 10)
-      j++;
-    s[2 * i + j] = kHexmap[(uuid[i] & 0xf0) >> 4];
-    s[2 * i + 1 + j] = kHexmap[(uuid[i] & 0x0f)];
-  }
-  return s;
-}
-
-Uuid StringToUuid(const std::string& s) {
-  Uuid uuid;
-  PERFETTO_CHECK(s.size() == uuid.size());
-  for (size_t i = 0; i < uuid.size(); ++i) {
-    uuid[i] = static_cast<uint8_t>(s[i]);
-  }
-  return uuid;
-}
-
-Optional<Uuid> BytesToUuid(const uint8_t* data, size_t size) {
-  Uuid uuid;
-  if (size != uuid.size())
-    return nullopt;
-  for (size_t i = 0; i < uuid.size(); ++i) {
-    uuid[i] = data[i];
-  }
-  return uuid;
-}
-
-}  // namespace base
-}  // namespace perfetto
diff --git a/src/base/uuid_unittest.cc b/src/base/uuid_unittest.cc
deleted file mode 100644
index 7ff37fa..0000000
--- a/src/base/uuid_unittest.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/ext/base/uuid.h"
-
-#include "test/gtest_and_gmock.h"
-
-#include "perfetto/ext/base/optional.h"
-
-namespace perfetto {
-namespace base {
-namespace {
-
-TEST(Uuid, TwoUuidsShouldBeDifferent) {
-  Uuid a = Uuidv4();
-  Uuid b = Uuidv4();
-  EXPECT_NE(a, b);
-}
-
-TEST(Uuid, CanRoundTripUuid) {
-  Uuid uuid = Uuidv4();
-  EXPECT_EQ(StringToUuid(UuidToString(uuid)), uuid);
-}
-
-TEST(Uuid, BytesToUuid) {
-  std::string empty = "";
-  std::string too_short = "abc";
-  std::string uuid = "abcdefghijklmnop";
-
-  EXPECT_EQ(BytesToUuid(empty.data(), empty.size()), nullopt);
-  EXPECT_EQ(BytesToUuid(uuid.data(), uuid.size()),
-            Optional<Uuid>(StringToUuid(uuid)));
-}
-
-TEST(Uuid, UuidToPrettyString) {
-  EXPECT_EQ(
-      UuidToPrettyString(StringToUuid(
-          "\x12\x3e\x45\x67\xe8\x9b\x12\xd3\xa4\x56\x42\x66\x55\x44\x33\x22")),
-      "123e4567-e89b-12d3-a456-426655443322");
-}
-
-}  // namespace
-}  // namespace base
-}  // namespace perfetto
diff --git a/src/base/waitable_event.cc b/src/base/waitable_event.cc
deleted file mode 100644
index c5b5c04..0000000
--- a/src/base/waitable_event.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/ext/base/waitable_event.h"
-
-namespace perfetto {
-namespace base {
-
-WaitableEvent::WaitableEvent() = default;
-WaitableEvent::~WaitableEvent() = default;
-
-void WaitableEvent::Wait() {
-  std::unique_lock<std::mutex> lock(mutex_);
-  return event_.wait(lock, [this] { return notified_; });
-}
-
-void WaitableEvent::Notify() {
-  std::unique_lock<std::mutex> lock(mutex_);
-  notified_ = true;
-  event_.notify_all();
-}
-
-}  // namespace base
-}  // namespace perfetto
diff --git a/src/base/watchdog_posix.cc b/src/base/watchdog_posix.cc
index 401ecdb..dd68455 100644
--- a/src/base/watchdog_posix.cc
+++ b/src/base/watchdog_posix.cc
@@ -14,9 +14,16 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/watchdog.h"
+#include "perfetto/base/build_config.h"
 
-#if PERFETTO_BUILDFLAG(PERFETTO_WATCHDOG)
+// Watchdog is currently not supported on Mac. This ifdef-based exclusion is
+// here only for the Mac build in AOSP. The standalone and chromium builds
+// exclude this file at the GN level. However, propagating the per-os exclusion
+// through our GN -> BP build file translator is not worth the effort for a
+// one-off case.
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
+
+#include "perfetto/base/watchdog_posix.h"
 
 #include <fcntl.h>
 #include <inttypes.h>
@@ -28,8 +35,12 @@
 
 #include "perfetto/base/build_config.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/thread_utils.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/thread_utils.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_EMBEDDER_BUILD)
+#error perfetto::base::Watchdog should not be used in Chromium or embedders
+#endif
 
 namespace perfetto {
 namespace base {
@@ -259,4 +270,4 @@
 }  // namespace base
 }  // namespace perfetto
 
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_WATCHDOG)
+#endif  // PERFETTO_OS_MACOSX
diff --git a/src/base/watchdog_unittest.cc b/src/base/watchdog_unittest.cc
index f3bc850..ec55101 100644
--- a/src/base/watchdog_unittest.cc
+++ b/src/base/watchdog_unittest.cc
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/watchdog.h"
+#include "perfetto/base/watchdog.h"
 
+#include "gtest/gtest.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/paged_memory.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/thread_utils.h"
-#include "test/gtest_and_gmock.h"
+#include "perfetto/base/paged_memory.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/thread_utils.h"
 
 #include <signal.h>
 #include <time.h>
diff --git a/src/base/weak_ptr_unittest.cc b/src/base/weak_ptr_unittest.cc
index 1656574..eebd36d 100644
--- a/src/base/weak_ptr_unittest.cc
+++ b/src/base/weak_ptr_unittest.cc
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/weak_ptr.h"
+#include "perfetto/base/weak_ptr.h"
 
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace base {
diff --git a/src/ipc/BUILD.gn b/src/ipc/BUILD.gn
index ed0ecd2..290da3c 100644
--- a/src/ipc/BUILD.gn
+++ b/src/ipc/BUILD.gn
@@ -12,33 +12,36 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import("../../gn/perfetto.gni")
 import("../../gn/fuzzer.gni")
 import("../../gn/ipc_library.gni")
-import("../../gn/perfetto.gni")
 import("../../gn/proto_library.gni")
-import("../../gn/test.gni")
+
+# For use_libfuzzer.
+if (perfetto_build_standalone || perfetto_build_with_android) {
+  import("//gn/standalone/sanitizers/vars.gni")
+} else {
+  import("//build/config/sanitizers/sanitizers.gni")
+}
 
 # This build file should not be leaked into all embedders. Only select
 # projects should be depending on our IPC layer.
-assert(enable_perfetto_ipc)
+assert(perfetto_build_with_ipc_layer)
 
 source_set("ipc") {
   public_configs = [ "../../gn:default_config" ]
   public_deps = [
-    "../../include/perfetto/ext/ipc",
+    "../../include/perfetto/ipc",
     "../base:unix_socket",
   ]
   deps = [
+    ":wire_protocol",
     "../../gn:default_deps",
-    "../../gn:protobuf_lite",
-    "../../protos/perfetto/ipc:wire_protocol",
     "../base",
   ]
   sources = [
     "buffered_frame_deserializer.cc",
-    "buffered_frame_deserializer.h",
     "client_impl.cc",
-    "client_impl.h",
     "deferred.cc",
     "host_impl.cc",
     "host_impl.h",
@@ -53,19 +56,19 @@
   ]
   deps = [
     ":ipc",
+    ":wire_protocol",
     "../../gn:default_deps",
-    "../../protos/perfetto/ipc:wire_protocol",
   ]
 }
 
-perfetto_unittest_source_set("unittests") {
+source_set("unittests") {
   testonly = true
   deps = [
     ":ipc",
     ":test_messages",
+    ":wire_protocol",
     "../../gn:default_deps",
-    "../../gn:gtest_and_gmock",
-    "../../protos/perfetto/ipc:wire_protocol",
+    "../../gn:gtest_deps",
     "../base",
     "../base:test_support",
   ]
@@ -78,6 +81,15 @@
   ]
 }
 
+proto_library("wire_protocol") {
+  generate_python = false
+  sources = [
+    "wire_protocol.proto",
+  ]
+  proto_in_dir = perfetto_root_path
+  proto_out_dir = perfetto_root_path
+}
+
 ipc_library("test_messages") {
   sources = [
     "test/client_unittest_messages.proto",
@@ -87,12 +99,3 @@
   proto_in_dir = perfetto_root_path
   proto_out_dir = perfetto_root_path
 }
-
-# This is used by Bazel BUILD rules.
-static_library("perfetto_ipc") {
-  complete_static_lib = true
-  deps = [
-    ":ipc",
-    "../../gn:default_deps",
-  ]
-}
diff --git a/src/ipc/buffered_frame_deserializer.cc b/src/ipc/buffered_frame_deserializer.cc
index dc107f7..0a85d96 100644
--- a/src/ipc/buffered_frame_deserializer.cc
+++ b/src/ipc/buffered_frame_deserializer.cc
@@ -22,10 +22,11 @@
 #include <type_traits>
 #include <utility>
 
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/utils.h"
 
-#include "protos/perfetto/ipc/wire_protocol.pb.h"
+#include "src/ipc/wire_protocol.pb.h"
 
 namespace perfetto {
 namespace ipc {
@@ -110,7 +111,7 @@
         // The caller is expected to shut down the socket and give up at this
         // point. If it doesn't do that and insists going on at some point it
         // will hit the capacity check in BeginReceive().
-        PERFETTO_LOG("IPC Frame too large (size %zu)", next_frame_size);
+        PERFETTO_DLOG("Frame too large (size %zu)", next_frame_size);
         return false;
       }
       break;
@@ -166,7 +167,9 @@
   if (size == 0)
     return;
   std::unique_ptr<Frame> frame(new Frame);
-  if (frame->ParseFromArray(data, static_cast<int>(size)))
+  const int sz = static_cast<int>(size);
+  ::google::protobuf::io::ArrayInputStream stream(data, sz);
+  if (frame->ParseFromBoundedZeroCopyStream(&stream, sz))
     decoded_frames_.push_back(std::move(frame));
 }
 
diff --git a/src/ipc/buffered_frame_deserializer.h b/src/ipc/buffered_frame_deserializer.h
index 3aeee1f..a8c3f74 100644
--- a/src/ipc/buffered_frame_deserializer.h
+++ b/src/ipc/buffered_frame_deserializer.h
@@ -24,9 +24,9 @@
 
 #include <sys/mman.h>
 
-#include "perfetto/ext/base/paged_memory.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/ipc/basic_types.h"
+#include "perfetto/base/paged_memory.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/ipc/basic_types.h"
 
 namespace perfetto {
 namespace ipc {
diff --git a/src/ipc/buffered_frame_deserializer_fuzzer.cc b/src/ipc/buffered_frame_deserializer_fuzzer.cc
index 61a818d..ae6525b 100644
--- a/src/ipc/buffered_frame_deserializer_fuzzer.cc
+++ b/src/ipc/buffered_frame_deserializer_fuzzer.cc
@@ -17,10 +17,9 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/utils.h"
 #include "src/ipc/buffered_frame_deserializer.h"
-
-#include "protos/perfetto/ipc/wire_protocol.pb.h"
+#include "src/ipc/wire_protocol.pb.h"
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
 
diff --git a/src/ipc/buffered_frame_deserializer_unittest.cc b/src/ipc/buffered_frame_deserializer_unittest.cc
index 792365b..e38aa7d 100644
--- a/src/ipc/buffered_frame_deserializer_unittest.cc
+++ b/src/ipc/buffered_frame_deserializer_unittest.cc
@@ -19,11 +19,11 @@
 #include <algorithm>
 #include <string>
 
+#include "gtest/gtest.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
-#include "test/gtest_and_gmock.h"
+#include "perfetto/base/utils.h"
 
-#include "protos/perfetto/ipc/wire_protocol.pb.h"
+#include "src/ipc/wire_protocol.pb.h"
 
 namespace perfetto {
 namespace ipc {
diff --git a/src/ipc/client_impl.cc b/src/ipc/client_impl.cc
index b563d95..d648df5 100644
--- a/src/ipc/client_impl.cc
+++ b/src/ipc/client_impl.cc
@@ -23,9 +23,9 @@
 #include <utility>
 
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/ipc/service_descriptor.h"
-#include "perfetto/ext/ipc/service_proxy.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/ipc/service_descriptor.h"
+#include "perfetto/ipc/service_proxy.h"
 
 // TODO(primiano): Add ThreadChecker everywhere.
 
@@ -43,9 +43,8 @@
 
 ClientImpl::ClientImpl(const char* socket_name, base::TaskRunner* task_runner)
     : task_runner_(task_runner), weak_ptr_factory_(this) {
-  sock_ = base::UnixSocket::Connect(socket_name, this, task_runner,
-                                    base::SockFamily::kUnix,
-                                    base::SockType::kStream);
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+  sock_ = base::UnixSocket::Connect(socket_name, this, task_runner);
 }
 
 ClientImpl::~ClientImpl() {
diff --git a/src/ipc/client_impl.h b/src/ipc/client_impl.h
index 71c211f..d071053 100644
--- a/src/ipc/client_impl.h
+++ b/src/ipc/client_impl.h
@@ -17,13 +17,13 @@
 #ifndef SRC_IPC_CLIENT_IMPL_H_
 #define SRC_IPC_CLIENT_IMPL_H_
 
+#include "perfetto/base/scoped_file.h"
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/unix_socket.h"
-#include "perfetto/ext/ipc/client.h"
+#include "perfetto/base/unix_socket.h"
+#include "perfetto/ipc/client.h"
 #include "src/ipc/buffered_frame_deserializer.h"
 
-#include "protos/perfetto/ipc/wire_protocol.pb.h"
+#include "src/ipc/wire_protocol.pb.h"
 
 #include <list>
 #include <map>
diff --git a/src/ipc/client_impl_unittest.cc b/src/ipc/client_impl_unittest.cc
index e8e634e..139702e 100644
--- a/src/ipc/client_impl_unittest.cc
+++ b/src/ipc/client_impl_unittest.cc
@@ -21,16 +21,17 @@
 
 #include <string>
 
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/ext/base/unix_socket.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/ipc/service_descriptor.h"
-#include "perfetto/ext/ipc/service_proxy.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/file_utils.h"
+#include "perfetto/base/temp_file.h"
+#include "perfetto/base/unix_socket.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/ipc/service_descriptor.h"
+#include "perfetto/ipc/service_proxy.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/ipc/buffered_frame_deserializer.h"
 #include "src/ipc/test/test_socket.h"
-#include "test/gtest_and_gmock.h"
 
 #include "src/ipc/test/client_unittest_messages.pb.h"
 
@@ -103,9 +104,7 @@
 
   explicit FakeHost(base::TaskRunner* task_runner) {
     DESTROY_TEST_SOCK(kSockName);
-    listening_sock = base::UnixSocket::Listen(kSockName, this, task_runner,
-                                              base::SockFamily::kUnix,
-                                              base::SockType::kStream);
+    listening_sock = base::UnixSocket::Listen(kSockName, this, task_runner);
     EXPECT_TRUE(listening_sock->is_listening());
   }
   ~FakeHost() override { DESTROY_TEST_SOCK(kSockName); }
diff --git a/src/ipc/deferred.cc b/src/ipc/deferred.cc
index c16604a..5542cd5 100644
--- a/src/ipc/deferred.cc
+++ b/src/ipc/deferred.cc
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/ipc/deferred.h"
+#include "perfetto/ipc/deferred.h"
 
+#include "google/protobuf/message_lite.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
 
 namespace perfetto {
 namespace ipc {
diff --git a/src/ipc/deferred_unittest.cc b/src/ipc/deferred_unittest.cc
index e5ca890..4362c07 100644
--- a/src/ipc/deferred_unittest.cc
+++ b/src/ipc/deferred_unittest.cc
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/ipc/deferred.h"
+#include "perfetto/ipc/deferred.h"
 
+#include "gtest/gtest.h"
 #include "perfetto/base/logging.h"
-#include "test/gtest_and_gmock.h"
 
 #include "src/ipc/test/deferred_unittest_messages.pb.h"
 
@@ -26,7 +26,7 @@
 namespace {
 
 #if PERFETTO_DCHECK_IS_ON()
-#define EXPECT_DCHECK(x) EXPECT_DEATH_IF_SUPPORTED((x), ".*")
+#define EXPECT_DCHECK(x) EXPECT_DEATH_IF_SUPPORTED((x), ".*");
 #else
 #define EXPECT_DCHECK(x) x
 #endif
diff --git a/src/ipc/host_impl.cc b/src/ipc/host_impl.cc
index 0a56b85..0ccdde3 100644
--- a/src/ipc/host_impl.cc
+++ b/src/ipc/host_impl.cc
@@ -22,11 +22,11 @@
 #include <utility>
 
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/ipc/service.h"
-#include "perfetto/ext/ipc/service_descriptor.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/ipc/service.h"
+#include "perfetto/ipc/service_descriptor.h"
 
-#include "protos/perfetto/ipc/wire_protocol.pb.h"
+#include "src/ipc/wire_protocol.pb.h"
 
 // TODO(primiano): put limits on #connections/uid and req. queue (b/69093705).
 
@@ -39,7 +39,7 @@
   std::unique_ptr<HostImpl> host(new HostImpl(socket_name, task_runner));
   if (!host->sock() || !host->sock()->is_listening())
     return nullptr;
-  return std::unique_ptr<Host>(std::move(host));
+  return std::move(host);
 }
 
 // static
@@ -49,23 +49,21 @@
       new HostImpl(std::move(socket_fd), task_runner));
   if (!host->sock() || !host->sock()->is_listening())
     return nullptr;
-  return std::unique_ptr<Host>(std::move(host));
+  return std::move(host);
 }
 
 HostImpl::HostImpl(base::ScopedFile socket_fd, base::TaskRunner* task_runner)
     : task_runner_(task_runner), weak_ptr_factory_(this) {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
   PERFETTO_DCHECK_THREAD(thread_checker_);
-  sock_ = base::UnixSocket::Listen(std::move(socket_fd), this, task_runner_,
-                                   base::SockFamily::kUnix,
-                                   base::SockType::kStream);
+  sock_ = base::UnixSocket::Listen(std::move(socket_fd), this, task_runner_);
 }
 
 HostImpl::HostImpl(const char* socket_name, base::TaskRunner* task_runner)
     : task_runner_(task_runner), weak_ptr_factory_(this) {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
   PERFETTO_DCHECK_THREAD(thread_checker_);
-  sock_ = base::UnixSocket::Listen(socket_name, this, task_runner_,
-                                   base::SockFamily::kUnix,
-                                   base::SockType::kStream);
+  sock_ = base::UnixSocket::Listen(socket_name, this, task_runner_);
 }
 
 HostImpl::~HostImpl() = default;
diff --git a/src/ipc/host_impl.h b/src/ipc/host_impl.h
index 97b5a8b..262da9a 100644
--- a/src/ipc/host_impl.h
+++ b/src/ipc/host_impl.h
@@ -23,10 +23,10 @@
 #include <vector>
 
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/thread_checker.h"
-#include "perfetto/ext/base/unix_socket.h"
-#include "perfetto/ext/ipc/deferred.h"
-#include "perfetto/ext/ipc/host.h"
+#include "perfetto/base/thread_checker.h"
+#include "perfetto/base/unix_socket.h"
+#include "perfetto/ipc/deferred.h"
+#include "perfetto/ipc/host.h"
 #include "src/ipc/buffered_frame_deserializer.h"
 
 namespace perfetto {
diff --git a/src/ipc/host_impl_unittest.cc b/src/ipc/host_impl_unittest.cc
index 0624cd7..121f57b 100644
--- a/src/ipc/host_impl_unittest.cc
+++ b/src/ipc/host_impl_unittest.cc
@@ -18,20 +18,21 @@
 
 #include <memory>
 
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/ext/base/unix_socket.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/ipc/service.h"
-#include "perfetto/ext/ipc/service_descriptor.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/file_utils.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/temp_file.h"
+#include "perfetto/base/unix_socket.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/ipc/service.h"
+#include "perfetto/ipc/service_descriptor.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/ipc/buffered_frame_deserializer.h"
 #include "src/ipc/test/test_socket.h"
-#include "test/gtest_and_gmock.h"
 
-#include "protos/perfetto/ipc/wire_protocol.pb.h"
 #include "src/ipc/test/client_unittest_messages.pb.h"
+#include "src/ipc/wire_protocol.pb.h"
 
 namespace perfetto {
 namespace ipc {
@@ -88,9 +89,7 @@
   MOCK_METHOD0(OnRequestError, void());
 
   explicit FakeClient(base::TaskRunner* task_runner) {
-    sock_ = base::UnixSocket::Connect(kSockName, this, task_runner,
-                                      base::SockFamily::kUnix,
-                                      base::SockType::kStream);
+    sock_ = base::UnixSocket::Connect(kSockName, this, task_runner);
   }
 
   ~FakeClient() override = default;
@@ -286,7 +285,7 @@
 
   // OnFakeMethod1 will:
   // - Do nothing on the 1st call, when |drop_reply| == true.
-  // - Reply on the 2nd call, when |drop_reply| == false.
+  // - Reply on the the 2nd call, when |drop_reply| == false.
   EXPECT_CALL(*fake_service, OnFakeMethod1(_, _))
       .Times(2)
       .WillRepeatedly(Invoke([](const RequestProto& req, DeferredBase* reply) {
@@ -336,15 +335,15 @@
                                                sizeof(kFileContent))),
             sizeof(kFileContent));
   EXPECT_CALL(*fake_service, OnFakeMethod1(_, _))
-      .WillOnce(Invoke(
-          [on_reply_sent, &tx_file](const RequestProto&, DeferredBase* reply) {
-            std::unique_ptr<ReplyProto> reply_args(new ReplyProto());
-            auto async_res = AsyncResult<ProtoMessage>(
-                std::unique_ptr<ProtoMessage>(reply_args.release()));
-            async_res.set_fd(tx_file.fd());
-            reply->Resolve(std::move(async_res));
-            on_reply_sent();
-          }));
+      .WillOnce(Invoke([on_reply_sent, &tx_file](const RequestProto&,
+                                                 DeferredBase* reply) {
+        std::unique_ptr<ReplyProto> reply_args(new ReplyProto());
+        auto async_res = AsyncResult<ProtoMessage>(
+            std::unique_ptr<ProtoMessage>(reply_args.release()));
+        async_res.set_fd(tx_file.fd());
+        reply->Resolve(std::move(async_res));
+        on_reply_sent();
+      }));
   task_runner_->RunUntilCheckpoint("on_reply_sent");
   tx_file.ReleaseFD();
 
diff --git a/src/ipc/protoc_plugin/BUILD.gn b/src/ipc/protoc_plugin/BUILD.gn
index 535f53a..ec88de1 100644
--- a/src/ipc/protoc_plugin/BUILD.gn
+++ b/src/ipc/protoc_plugin/BUILD.gn
@@ -12,15 +12,16 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../gn/perfetto_host_executable.gni")
-
-perfetto_host_executable("ipc_plugin") {
-  sources = [
-    "ipc_plugin.cc",
-  ]
-  deps = [
-    "../../../gn:default_deps",
-    "../../../gn:protoc_lib",
-    "../../../src/base",
-  ]
-}
+if (current_toolchain == host_toolchain) {
+  executable("ipc_plugin") {
+    sources = [
+      "ipc_generator.cc",
+      "ipc_generator.h",
+      "ipc_plugin.cc",
+    ]
+    deps = [
+      "../../../gn:default_deps",
+      "../../../gn:protoc_lib_deps",
+    ]
+  }
+}  # host_toolchain
diff --git a/src/ipc/protoc_plugin/ipc_generator.cc b/src/ipc/protoc_plugin/ipc_generator.cc
new file mode 100644
index 0000000..a981e29
--- /dev/null
+++ b/src/ipc/protoc_plugin/ipc_generator.cc
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2017 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 "src/ipc/protoc_plugin/ipc_generator.h"
+
+#include <functional>
+#include <memory>
+#include <set>
+#include <string>
+
+#include "google/protobuf/compiler/cpp/cpp_options.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/stubs/strutil.h"
+
+namespace perfetto {
+namespace ipc {
+
+using google::protobuf::ServiceDescriptor;
+using google::protobuf::FileDescriptor;
+using google::protobuf::MethodDescriptor;
+using google::protobuf::compiler::GeneratorContext;
+using google::protobuf::io::Printer;
+using google::protobuf::io::ZeroCopyOutputStream;
+
+using google::protobuf::Split;
+using google::protobuf::StripString;
+using google::protobuf::StripSuffixString;
+using google::protobuf::UpperString;
+
+namespace {
+
+static const char kBanner[] = "// DO NOT EDIT. Autogenerated by Perfetto IPC\n";
+
+static const char kHeaderSvcClass[] = R"(
+class $c$ : public ::perfetto::ipc::Service {
+ private:
+  static ::perfetto::ipc::ServiceDescriptor* NewDescriptor();
+
+ public:
+  ~$c$() override;
+
+  static const ::perfetto::ipc::ServiceDescriptor& GetDescriptorStatic();
+
+  // Service implementation.
+  const ::perfetto::ipc::ServiceDescriptor& GetDescriptor() override;
+
+  // Methods from the .proto file
+)";
+
+static const char kHeaderProxyClass[] = R"(
+class $c$Proxy : public ::perfetto::ipc::ServiceProxy {
+ public:
+   explicit $c$Proxy(::perfetto::ipc::ServiceProxy::EventListener*);
+   ~$c$Proxy() override;
+
+  // ServiceProxy implementation.
+  const ::perfetto::ipc::ServiceDescriptor& GetDescriptor() override;
+
+  // Methods from the .proto file
+)";
+
+static const char kCppClassDefinitions[] = R"(
+const ::perfetto::ipc::ServiceDescriptor& $c$::GetDescriptorStatic() {
+  static auto* instance = NewDescriptor();
+  return *instance;
+}
+
+// Host-side definitions.
+$c$::~$c$() = default;
+
+const ::perfetto::ipc::ServiceDescriptor& $c$::GetDescriptor() {
+  return GetDescriptorStatic();
+}
+
+// Client-side definitions.
+$c$Proxy::$c$Proxy(::perfetto::ipc::ServiceProxy::EventListener* event_listener)
+    : ::perfetto::ipc::ServiceProxy(event_listener) {}
+
+$c$Proxy::~$c$Proxy() = default;
+
+const ::perfetto::ipc::ServiceDescriptor& $c$Proxy::GetDescriptor() {
+  return $c$::GetDescriptorStatic();
+}
+)";
+
+static const char kCppMethodDescriptor[] = R"(
+  desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
+     "$m$",
+     &_IPC_Decoder<$i$>,
+     &_IPC_Decoder<$o$>,
+     &_IPC_Invoker<$c$, $i$, $o$, &$c$::$m$>});
+)";
+
+static const char kCppMethod[] = R"(
+void $c$Proxy::$m$(const $i$& request, Deferred$o$ reply, int fd) {
+  BeginInvoke("$m$", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
+              fd);
+}
+)";
+
+std::string StripName(const FileDescriptor& file) {
+  return StripSuffixString(file.name(), ".proto");
+}
+
+std::string GetStubName(const FileDescriptor& file) {
+  return StripName(file) + ".ipc";
+}
+
+void ForEachMethod(const ServiceDescriptor& svc,
+                   std::function<void(const MethodDescriptor&,
+                                      const std::string&,
+                                      const std::string&)> function) {
+  for (int i = 0; i < svc.method_count(); i++) {
+    const MethodDescriptor& method = *svc.method(i);
+    // TODO if the input or output type are in a different namespace we need to
+    // emit the ::fully::qualified::name.
+    std::string input_type = method.input_type()->name();
+    std::string output_type = method.output_type()->name();
+    function(method, input_type, output_type);
+  }
+}
+
+void GenerateServiceHeader(const FileDescriptor& file,
+                           const ServiceDescriptor& svc,
+                           Printer* printer) {
+  printer->Print("\n");
+  std::vector<std::string> namespaces = Split(file.package(), ".");
+  for (const std::string& ns : namespaces)
+    printer->Print("namespace $ns$ {\n", "ns", ns);
+
+  // Generate the host-side declarations.
+  printer->Print(kHeaderSvcClass, "c", svc.name());
+  std::set<std::string> types_seen;
+  ForEachMethod(svc, [&types_seen, printer](const MethodDescriptor& method,
+                                            const std::string& input_type,
+                                            const std::string& output_type) {
+    if (types_seen.count(output_type) == 0) {
+      printer->Print("  using Deferred$o$ = ::perfetto::ipc::Deferred<$o$>;\n",
+                     "o", output_type);
+      types_seen.insert(output_type);
+    }
+    printer->Print("  virtual void $m$(const $i$&, Deferred$o$) = 0;\n\n", "m",
+                   method.name(), "i", input_type, "o", output_type);
+  });
+  printer->Print("};\n\n");
+
+  // Generate the client-side declarations.
+  printer->Print(kHeaderProxyClass, "c", svc.name());
+  types_seen.clear();
+  ForEachMethod(svc, [&types_seen, printer](const MethodDescriptor& method,
+                                            const std::string& input_type,
+                                            const std::string& output_type) {
+    if (types_seen.count(output_type) == 0) {
+      printer->Print("  using Deferred$o$ = ::perfetto::ipc::Deferred<$o$>;\n",
+                     "o", output_type);
+      types_seen.insert(output_type);
+    }
+    printer->Print("  void $m$(const $i$&, Deferred$o$, int fd = -1);\n\n", "m",
+                   method.name(), "i", input_type, "o", output_type);
+  });
+  printer->Print("};\n\n");
+
+  for (auto it = namespaces.rbegin(); it != namespaces.rend(); it++)
+    printer->Print("}  // namespace $ns$\n", "ns", *it);
+
+  printer->Print("\n");
+}
+
+void GenerateServiceCpp(const FileDescriptor& file,
+                        const ServiceDescriptor& svc,
+                        Printer* printer) {
+  printer->Print("\n");
+
+  std::vector<std::string> namespaces = Split(file.package(), ".");
+  for (const std::string& ns : namespaces)
+    printer->Print("namespace $ns$ {\n", "ns", ns);
+
+  printer->Print("::perfetto::ipc::ServiceDescriptor* $c$::NewDescriptor() {\n",
+                 "c", svc.name());
+  printer->Print("  auto* desc = new ::perfetto::ipc::ServiceDescriptor();\n");
+  printer->Print("  desc->service_name = \"$c$\";\n", "c", svc.name());
+
+  ForEachMethod(svc, [&svc, printer](const MethodDescriptor& method,
+                                     const std::string& input_type,
+                                     const std::string& output_type) {
+    printer->Print(kCppMethodDescriptor, "c", svc.name(), "i", input_type, "o",
+                   output_type, "m", method.name());
+  });
+
+  printer->Print("  desc->methods.shrink_to_fit();\n");
+  printer->Print("  return desc;\n");
+  printer->Print("}\n\n");
+
+  printer->Print(kCppClassDefinitions, "c", svc.name());
+
+  ForEachMethod(svc, [&svc, printer](const MethodDescriptor& method,
+                                     const std::string& input_type,
+                                     const std::string& output_type) {
+    printer->Print(kCppMethod, "c", svc.name(), "m", method.name(), "i",
+                   input_type, "o", output_type);
+  });
+
+  for (auto it = namespaces.rbegin(); it != namespaces.rend(); it++)
+    printer->Print("}  // namespace $ns$\n", "ns", *it);
+}
+
+}  // namespace
+
+IPCGenerator::IPCGenerator() = default;
+IPCGenerator::~IPCGenerator() = default;
+
+bool IPCGenerator::Generate(const FileDescriptor* file,
+                            const std::string& /*options*/,
+                            GeneratorContext* context,
+                            std::string* error) const {
+  if (file->options().cc_generic_services()) {
+    *error = "Please set \"cc_generic_service = false\".";
+    return false;
+  }
+
+  const std::unique_ptr<ZeroCopyOutputStream> h_fstream(
+      context->Open(GetStubName(*file) + ".h"));
+  const std::unique_ptr<ZeroCopyOutputStream> cc_fstream(
+      context->Open(GetStubName(*file) + ".cc"));
+
+  // Variables are delimited by $.
+  Printer h_printer(h_fstream.get(), '$');
+  Printer cc_printer(cc_fstream.get(), '$');
+
+  std::string guard = file->package() + "_" + file->name() + "_H_";
+  UpperString(&guard);
+  StripString(&guard, ".-/\\", '_');
+
+  h_printer.Print(kBanner);
+  h_printer.Print("#ifndef $guard$\n#define $guard$\n\n", "guard", guard);
+  h_printer.Print("#include \"$h$\"\n", "h", StripName(*file) + ".pb.h");
+  h_printer.Print("#include \"perfetto/ipc/deferred.h\"\n");
+  h_printer.Print("#include \"perfetto/ipc/service.h\"\n");
+  h_printer.Print("#include \"perfetto/ipc/service_descriptor.h\"\n");
+  h_printer.Print("#include \"perfetto/ipc/service_proxy.h\"\n\n");
+
+  cc_printer.Print(kBanner);
+  cc_printer.Print("#include \"$h$\"\n", "h", GetStubName(*file) + ".h");
+  cc_printer.Print("#include \"perfetto/ipc/codegen_helpers.h\"\n\n");
+  cc_printer.Print("#include <memory>\n");
+
+  for (int i = 0; i < file->service_count(); i++) {
+    const ServiceDescriptor* svc = file->service(i);
+    GenerateServiceHeader(*file, *svc, &h_printer);
+    GenerateServiceCpp(*file, *svc, &cc_printer);
+  }
+
+  h_printer.Print("#endif  // $guard$\n", "guard", guard);
+
+  return true;
+}
+
+}  // namespace ipc
+}  // namespace perfetto
diff --git a/src/ipc/protoc_plugin/ipc_generator.h b/src/ipc/protoc_plugin/ipc_generator.h
new file mode 100644
index 0000000..bdd4d12
--- /dev/null
+++ b/src/ipc/protoc_plugin/ipc_generator.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2017 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 SRC_IPC_PROTOC_PLUGIN_IPC_GENERATOR_H_
+#define SRC_IPC_PROTOC_PLUGIN_IPC_GENERATOR_H_
+
+#include <string>
+
+#include "google/protobuf/compiler/code_generator.h"
+
+namespace perfetto {
+namespace ipc {
+
+class IPCGenerator : public ::google::protobuf::compiler::CodeGenerator {
+ public:
+  explicit IPCGenerator();
+  ~IPCGenerator() override;
+
+  // CodeGenerator implementation
+  bool Generate(const google::protobuf::FileDescriptor* file,
+                const std::string& options,
+                google::protobuf::compiler::GeneratorContext* context,
+                std::string* error) const override;
+};
+
+}  // namespace ipc
+}  // namespace perfetto
+
+#endif  // SRC_IPC_PROTOC_PLUGIN_IPC_GENERATOR_H_
diff --git a/src/ipc/protoc_plugin/ipc_plugin.cc b/src/ipc/protoc_plugin/ipc_plugin.cc
index f3a4372..82d45a4 100644
--- a/src/ipc/protoc_plugin/ipc_plugin.cc
+++ b/src/ipc/protoc_plugin/ipc_plugin.cc
@@ -14,273 +14,8 @@
  * limitations under the License.
  */
 
-#include <functional>
-#include <memory>
-#include <set>
-#include <string>
-
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/plugin.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-
-#include "perfetto/ext/base/string_utils.h"
-
-namespace perfetto {
-namespace ipc {
-namespace {
-
-using google::protobuf::FileDescriptor;
-using google::protobuf::MethodDescriptor;
-using google::protobuf::ServiceDescriptor;
-using google::protobuf::compiler::GeneratorContext;
-using google::protobuf::io::Printer;
-using google::protobuf::io::ZeroCopyOutputStream;
-using perfetto::base::SplitString;
-using perfetto::base::StripChars;
-using perfetto::base::StripSuffix;
-using perfetto::base::ToUpper;
-
-static const char kBanner[] = "// DO NOT EDIT. Autogenerated by Perfetto IPC\n";
-
-static const char kHeaderSvcClass[] = R"(
-class $c$ : public ::perfetto::ipc::Service {
- private:
-  static ::perfetto::ipc::ServiceDescriptor* NewDescriptor();
-
- public:
-  ~$c$() override;
-
-  static const ::perfetto::ipc::ServiceDescriptor& GetDescriptorStatic();
-
-  // Service implementation.
-  const ::perfetto::ipc::ServiceDescriptor& GetDescriptor() override;
-
-  // Methods from the .proto file
-)";
-
-static const char kHeaderProxyClass[] = R"(
-class $c$Proxy : public ::perfetto::ipc::ServiceProxy {
- public:
-   explicit $c$Proxy(::perfetto::ipc::ServiceProxy::EventListener*);
-   ~$c$Proxy() override;
-
-  // ServiceProxy implementation.
-  const ::perfetto::ipc::ServiceDescriptor& GetDescriptor() override;
-
-  // Methods from the .proto file
-)";
-
-static const char kCppClassDefinitions[] = R"(
-const ::perfetto::ipc::ServiceDescriptor& $c$::GetDescriptorStatic() {
-  static auto* instance = NewDescriptor();
-  return *instance;
-}
-
-// Host-side definitions.
-$c$::~$c$() = default;
-
-const ::perfetto::ipc::ServiceDescriptor& $c$::GetDescriptor() {
-  return GetDescriptorStatic();
-}
-
-// Client-side definitions.
-$c$Proxy::$c$Proxy(::perfetto::ipc::ServiceProxy::EventListener* event_listener)
-    : ::perfetto::ipc::ServiceProxy(event_listener) {}
-
-$c$Proxy::~$c$Proxy() = default;
-
-const ::perfetto::ipc::ServiceDescriptor& $c$Proxy::GetDescriptor() {
-  return $c$::GetDescriptorStatic();
-}
-)";
-
-static const char kCppMethodDescriptor[] = R"(
-  desc->methods.emplace_back(::perfetto::ipc::ServiceDescriptor::Method{
-     "$m$",
-     &_IPC_Decoder<$i$>,
-     &_IPC_Decoder<$o$>,
-     &_IPC_Invoker<$c$, $i$, $o$, &$c$::$m$>});
-)";
-
-static const char kCppMethod[] = R"(
-void $c$Proxy::$m$(const $i$& request, Deferred$o$ reply, int fd) {
-  BeginInvoke("$m$", request, ::perfetto::ipc::DeferredBase(std::move(reply)),
-              fd);
-}
-)";
-
-std::string StripName(const FileDescriptor& file) {
-  return StripSuffix(file.name(), ".proto");
-}
-
-std::string GetStubName(const FileDescriptor& file) {
-  return StripName(file) + ".ipc";
-}
-
-void ForEachMethod(const ServiceDescriptor& svc,
-                   std::function<void(const MethodDescriptor&,
-                                      const std::string&,
-                                      const std::string&)> function) {
-  for (int i = 0; i < svc.method_count(); i++) {
-    const MethodDescriptor& method = *svc.method(i);
-    // TODO if the input or output type are in a different namespace we need to
-    // emit the ::fully::qualified::name.
-    std::string input_type = method.input_type()->name();
-    std::string output_type = method.output_type()->name();
-    function(method, input_type, output_type);
-  }
-}
-
-void GenerateServiceHeader(const FileDescriptor& file,
-                           const ServiceDescriptor& svc,
-                           Printer* printer) {
-  printer->Print("\n");
-  std::vector<std::string> namespaces = SplitString(file.package(), ".");
-  for (const std::string& ns : namespaces)
-    printer->Print("namespace $ns$ {\n", "ns", ns);
-
-  // Generate the host-side declarations.
-  printer->Print(kHeaderSvcClass, "c", svc.name());
-  std::set<std::string> types_seen;
-  ForEachMethod(svc, [&types_seen, printer](const MethodDescriptor& method,
-                                            const std::string& input_type,
-                                            const std::string& output_type) {
-    if (types_seen.count(output_type) == 0) {
-      printer->Print("  using Deferred$o$ = ::perfetto::ipc::Deferred<$o$>;\n",
-                     "o", output_type);
-      types_seen.insert(output_type);
-    }
-    printer->Print("  virtual void $m$(const $i$&, Deferred$o$) = 0;\n\n", "m",
-                   method.name(), "i", input_type, "o", output_type);
-  });
-  printer->Print("};\n\n");
-
-  // Generate the client-side declarations.
-  printer->Print(kHeaderProxyClass, "c", svc.name());
-  types_seen.clear();
-  ForEachMethod(svc, [&types_seen, printer](const MethodDescriptor& method,
-                                            const std::string& input_type,
-                                            const std::string& output_type) {
-    if (types_seen.count(output_type) == 0) {
-      printer->Print("  using Deferred$o$ = ::perfetto::ipc::Deferred<$o$>;\n",
-                     "o", output_type);
-      types_seen.insert(output_type);
-    }
-    printer->Print("  void $m$(const $i$&, Deferred$o$, int fd = -1);\n\n", "m",
-                   method.name(), "i", input_type, "o", output_type);
-  });
-  printer->Print("};\n\n");
-
-  for (auto it = namespaces.rbegin(); it != namespaces.rend(); it++)
-    printer->Print("}  // namespace $ns$\n", "ns", *it);
-
-  printer->Print("\n");
-}
-
-void GenerateServiceCpp(const FileDescriptor& file,
-                        const ServiceDescriptor& svc,
-                        Printer* printer) {
-  printer->Print("\n");
-
-  std::vector<std::string> namespaces = SplitString(file.package(), ".");
-  for (const std::string& ns : namespaces)
-    printer->Print("namespace $ns$ {\n", "ns", ns);
-
-  printer->Print("::perfetto::ipc::ServiceDescriptor* $c$::NewDescriptor() {\n",
-                 "c", svc.name());
-  printer->Print("  auto* desc = new ::perfetto::ipc::ServiceDescriptor();\n");
-  printer->Print("  desc->service_name = \"$c$\";\n", "c", svc.name());
-
-  ForEachMethod(svc, [&svc, printer](const MethodDescriptor& method,
-                                     const std::string& input_type,
-                                     const std::string& output_type) {
-    printer->Print(kCppMethodDescriptor, "c", svc.name(), "i", input_type, "o",
-                   output_type, "m", method.name());
-  });
-
-  printer->Print("  desc->methods.shrink_to_fit();\n");
-  printer->Print("  return desc;\n");
-  printer->Print("}\n\n");
-
-  printer->Print(kCppClassDefinitions, "c", svc.name());
-
-  ForEachMethod(svc, [&svc, printer](const MethodDescriptor& method,
-                                     const std::string& input_type,
-                                     const std::string& output_type) {
-    printer->Print(kCppMethod, "c", svc.name(), "m", method.name(), "i",
-                   input_type, "o", output_type);
-  });
-
-  for (auto it = namespaces.rbegin(); it != namespaces.rend(); it++)
-    printer->Print("}  // namespace $ns$\n", "ns", *it);
-}
-
-class IPCGenerator : public ::google::protobuf::compiler::CodeGenerator {
- public:
-  explicit IPCGenerator();
-  ~IPCGenerator() override;
-
-  // CodeGenerator implementation
-  bool Generate(const google::protobuf::FileDescriptor* file,
-                const std::string& options,
-                google::protobuf::compiler::GeneratorContext* context,
-                std::string* error) const override;
-};
-
-IPCGenerator::IPCGenerator() = default;
-IPCGenerator::~IPCGenerator() = default;
-
-bool IPCGenerator::Generate(const FileDescriptor* file,
-                            const std::string& /*options*/,
-                            GeneratorContext* context,
-                            std::string* error) const {
-  if (file->options().cc_generic_services()) {
-    *error = "Please set \"cc_generic_service = false\".";
-    return false;
-  }
-
-  const std::unique_ptr<ZeroCopyOutputStream> h_fstream(
-      context->Open(GetStubName(*file) + ".h"));
-  const std::unique_ptr<ZeroCopyOutputStream> cc_fstream(
-      context->Open(GetStubName(*file) + ".cc"));
-
-  // Variables are delimited by $.
-  Printer h_printer(h_fstream.get(), '$');
-  Printer cc_printer(cc_fstream.get(), '$');
-
-  std::string guard = ToUpper(file->package() + "_" + file->name() + "_H_");
-  guard = StripChars(guard, ".-/\\", '_');
-
-  h_printer.Print(kBanner);
-  h_printer.Print("#ifndef $guard$\n#define $guard$\n\n", "guard", guard);
-  h_printer.Print("#include \"$h$\"\n", "h", StripName(*file) + ".pb.h");
-  h_printer.Print("#include \"perfetto/ext/ipc/deferred.h\"\n");
-  h_printer.Print("#include \"perfetto/ext/ipc/service.h\"\n");
-  h_printer.Print("#include \"perfetto/ext/ipc/service_descriptor.h\"\n");
-  h_printer.Print("#include \"perfetto/ext/ipc/service_proxy.h\"\n\n");
-
-  cc_printer.Print(kBanner);
-  cc_printer.Print("#include \"$h$\"\n", "h", GetStubName(*file) + ".h");
-  cc_printer.Print("#include \"perfetto/ext/ipc/codegen_helpers.h\"\n\n");
-  cc_printer.Print("#include <memory>\n");
-
-  for (int i = 0; i < file->service_count(); i++) {
-    const ServiceDescriptor* svc = file->service(i);
-    GenerateServiceHeader(*file, *svc, &h_printer);
-    GenerateServiceCpp(*file, *svc, &cc_printer);
-  }
-
-  h_printer.Print("#endif  // $guard$\n", "guard", guard);
-
-  return true;
-}
-
-}  // namespace
-}  // namespace ipc
-}  // namespace perfetto
+#include "google/protobuf/compiler/plugin.h"
+#include "src/ipc/protoc_plugin/ipc_generator.h"
 
 int main(int argc, char* argv[]) {
   ::perfetto::ipc::IPCGenerator generator;
diff --git a/src/ipc/service_proxy.cc b/src/ipc/service_proxy.cc
index e416f5f..6a22937 100644
--- a/src/ipc/service_proxy.cc
+++ b/src/ipc/service_proxy.cc
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/ipc/service_proxy.h"
+#include "perfetto/ipc/service_proxy.h"
 
 #include <utility>
 
+#include "google/protobuf/message_lite.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/ipc/service_descriptor.h"
+#include "perfetto/base/weak_ptr.h"
+#include "perfetto/ipc/service_descriptor.h"
 #include "src/ipc/client_impl.h"
 
 namespace perfetto {
diff --git a/src/ipc/test/ipc_integrationtest.cc b/src/ipc/test/ipc_integrationtest.cc
index 02a7e81..9e21128 100644
--- a/src/ipc/test/ipc_integrationtest.cc
+++ b/src/ipc/test/ipc_integrationtest.cc
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/ipc/client.h"
-#include "perfetto/ext/ipc/host.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/ipc/client.h"
+#include "perfetto/ipc/host.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/ipc/test/test_socket.h"
-#include "test/gtest_and_gmock.h"
 
 #include "src/ipc/test/greeter_service.ipc.h"
 #include "src/ipc/test/greeter_service.pb.h"
diff --git a/src/ipc/virtual_destructors.cc b/src/ipc/virtual_destructors.cc
index d16a770..4a4cb04 100644
--- a/src/ipc/virtual_destructors.cc
+++ b/src/ipc/virtual_destructors.cc
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/ipc/client.h"
-#include "perfetto/ext/ipc/host.h"
-#include "perfetto/ext/ipc/service.h"
-#include "perfetto/ext/ipc/service_proxy.h"
+#include "perfetto/ipc/client.h"
+#include "perfetto/ipc/host.h"
+#include "perfetto/ipc/service.h"
+#include "perfetto/ipc/service_proxy.h"
 
 // This translation unit contains the definitions for the destructor of pure
 // virtual interfaces for the current build target. The alternative would be
diff --git a/protos/perfetto/ipc/wire_protocol.proto b/src/ipc/wire_protocol.proto
similarity index 100%
rename from protos/perfetto/ipc/wire_protocol.proto
rename to src/ipc/wire_protocol.proto
diff --git a/src/perfetto_cmd/BUILD.gn b/src/perfetto_cmd/BUILD.gn
index fe6cf12..0f82514 100644
--- a/src/perfetto_cmd/BUILD.gn
+++ b/src/perfetto_cmd/BUILD.gn
@@ -14,47 +14,17 @@
 
 import("../../gn/perfetto.gni")
 import("../../gn/proto_library.gni")
-import("../../gn/test.gni")
 
-# The command line client for Perfetto. Allows to configure / start / stop
-# tracing, acting as a Consumer.
-executable("perfetto") {
-  deps = [
-    ":perfetto_cmd",
-    "../../gn:default_deps",
-  ]
-  sources = [
-    "main.cc",
-  ]
-}
-
-# Tool to finalize long running traces.
-# This connects to traced as a producer and sends the triggers passed on the
-# commandline. This is a subset of what the perfetto binary can do but we
-# need a separate binary for programs that cannot (for good reason) use the
-# additional functionality (for example starting traces via consumer socket)
-# due to selinux rules.
-executable("trigger_perfetto") {
-  deps = [
-    ":trigger_perfetto_cmd",
-    "../../gn:default_deps",
-  ]
-  sources = [
-    "trigger_perfetto_main.cc",
-  ]
-}
-
-# Contains all the implementation but not the main() entry point. This target
-# is shared both by the executable and tests.
 source_set("perfetto_cmd") {
   public_deps = [
     ":protos",
-    "../../include/perfetto/ext/traced",
+    "../../include/perfetto/traced",
   ]
   deps = [
     ":trigger_producer",
+    "../../buildtools:protobuf_lite",
     "../../gn:default_deps",
-    "../../gn:zlib",
+    "../../gn:zlib_deps",
     "../../protos/perfetto/common:lite",
     "../../protos/perfetto/config:lite",
     "../android_internal:lazy_library_loader",
@@ -75,15 +45,20 @@
     "rate_limiter.cc",
     "rate_limiter.h",
   ]
-  if (is_android) {
-    sources += [ "perfetto_cmd_android.cc" ]
+  if (perfetto_build_with_android) {
+    deps += [ "../base:android_task_runner" ]
+    libs = [
+      "binder",
+      "services",
+      "utils",
+    ]
   }
 }
 
 source_set("trigger_perfetto_cmd") {
   public_deps = [
     ":protos",
-    "../../include/perfetto/ext/traced",
+    "../../include/perfetto/traced",
   ]
   deps = [
     ":trigger_producer",
@@ -102,6 +77,7 @@
     "trigger_producer.h",
   ]
   deps = [
+    "../../buildtools:protobuf_lite",
     "../../gn:default_deps",
     "../../protos/perfetto/config:lite",
     "../base",
@@ -109,24 +85,25 @@
   ]
 }
 
-perfetto_proto_library("protos") {
-  proto_generators = [ "lite" ]
+proto_library("protos") {
+  generate_python = false
+  deps = []
   sources = [
     "perfetto_cmd_state.proto",
   ]
-  proto_path = perfetto_root_path
+  proto_in_dir = perfetto_root_path
+  proto_out_dir = perfetto_root_path
 }
 
-perfetto_unittest_source_set("unittests") {
+source_set("unittests") {
   testonly = true
   public_deps = []
   deps = [
     ":perfetto_cmd",
     "../../gn:default_deps",
-    "../../gn:gtest_and_gmock",
-    "../../gn:zlib",
+    "../../gn:gtest_deps",
+    "../../gn:zlib_deps",
     "../../include/perfetto/base",
-    "../../include/perfetto/ext/base",
     "../../protos/perfetto/config:lite",
     "../../protos/perfetto/trace:lite",
     "../protozero",
diff --git a/src/perfetto_cmd/config.h b/src/perfetto_cmd/config.h
index 2d338af..65bad22 100644
--- a/src/perfetto_cmd/config.h
+++ b/src/perfetto_cmd/config.h
@@ -20,7 +20,7 @@
 #include <string>
 #include <utility>
 
-#include "protos/perfetto/config/trace_config.pb.h"
+#include "perfetto/config/trace_config.pb.h"
 
 namespace perfetto {
 
diff --git a/src/perfetto_cmd/config_unittest.cc b/src/perfetto_cmd/config_unittest.cc
index 4096abb..024c42f 100644
--- a/src/perfetto_cmd/config_unittest.cc
+++ b/src/perfetto_cmd/config_unittest.cc
@@ -16,9 +16,10 @@
 
 #include "src/perfetto_cmd/config.h"
 
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
-#include "protos/perfetto/config/trace_config.pb.h"
+#include "perfetto/config/trace_config.pb.h"
 
 namespace perfetto {
 namespace {
@@ -40,43 +41,43 @@
 TEST_F(CreateConfigFromOptionsTest, MilliSeconds) {
   options.time = "2ms";
   ASSERT_TRUE(CreateConfigFromOptions(options, &config));
-  EXPECT_EQ(config.duration_ms(), 2u);
+  EXPECT_EQ(config.duration_ms(), 2);
 }
 
 TEST_F(CreateConfigFromOptionsTest, Seconds) {
   options.time = "100s";
   ASSERT_TRUE(CreateConfigFromOptions(options, &config));
-  EXPECT_EQ(config.duration_ms(), 100 * 1000u);
+  EXPECT_EQ(config.duration_ms(), 100 * 1000);
 }
 
 TEST_F(CreateConfigFromOptionsTest, Minutes) {
   options.time = "2m";
   ASSERT_TRUE(CreateConfigFromOptions(options, &config));
-  EXPECT_EQ(config.duration_ms(), 2 * 60 * 1000u);
+  EXPECT_EQ(config.duration_ms(), 2 * 60 * 1000);
 }
 
 TEST_F(CreateConfigFromOptionsTest, Hours) {
   options.time = "2h";
   ASSERT_TRUE(CreateConfigFromOptions(options, &config));
-  EXPECT_EQ(config.duration_ms(), 2 * 60 * 60 * 1000u);
+  EXPECT_EQ(config.duration_ms(), 2 * 60 * 60 * 1000);
 }
 
 TEST_F(CreateConfigFromOptionsTest, Kilobyte) {
   options.buffer_size = "2kb";
   ASSERT_TRUE(CreateConfigFromOptions(options, &config));
-  EXPECT_EQ(config.buffers().Get(0).size_kb(), 2u);
+  EXPECT_EQ(config.buffers().Get(0).size_kb(), 2);
 }
 
 TEST_F(CreateConfigFromOptionsTest, Megabyte) {
   options.buffer_size = "2mb";
   ASSERT_TRUE(CreateConfigFromOptions(options, &config));
-  EXPECT_EQ(config.buffers().Get(0).size_kb(), 2 * 1024u);
+  EXPECT_EQ(config.buffers().Get(0).size_kb(), 2 * 1024);
 }
 
 TEST_F(CreateConfigFromOptionsTest, Gigabyte) {
   options.buffer_size = "2gb";
   ASSERT_TRUE(CreateConfigFromOptions(options, &config));
-  EXPECT_EQ(config.buffers().Get(0).size_kb(), 2 * 1024 * 1024u);
+  EXPECT_EQ(config.buffers().Get(0).size_kb(), 2 * 1024 * 1024);
 }
 
 TEST_F(CreateConfigFromOptionsTest, BadTrailingSpace) {
@@ -122,12 +123,12 @@
   options.categories.push_back("sched/sched_switch");
   options.atrace_apps.push_back("com.android.chrome");
   ASSERT_TRUE(CreateConfigFromOptions(options, &config));
-  EXPECT_EQ(config.duration_ms(), 60 * 60 * 1000u);
-  EXPECT_EQ(config.flush_period_ms(), 30 * 1000u);
-  EXPECT_EQ(config.max_file_size_bytes(), 1 * 1024 * 1024 * 1024u);
-  EXPECT_EQ(config.buffers().Get(0).size_kb(), 100 * 1024u);
+  EXPECT_EQ(config.duration_ms(), 60 * 60 * 1000);
+  EXPECT_EQ(config.flush_period_ms(), 30 * 1000);
+  EXPECT_EQ(config.max_file_size_bytes(), 1 * 1024 * 1024 * 1024);
+  EXPECT_EQ(config.buffers().Get(0).size_kb(), 100 * 1024);
   EXPECT_EQ(config.data_sources().Get(0).config().name(), "linux.ftrace");
-  EXPECT_EQ(config.data_sources().Get(0).config().target_buffer(), 0u);
+  EXPECT_EQ(config.data_sources().Get(0).config().target_buffer(), 0);
   auto ftrace = config.data_sources().Get(0).config().ftrace_config();
   EXPECT_THAT(ftrace.ftrace_events(), Contains("sched/sched_switch"));
   EXPECT_THAT(ftrace.atrace_categories(), Contains("sw"));
diff --git a/src/perfetto_cmd/main.cc b/src/perfetto_cmd/main.cc
index 0fbdfc4..dc71930 100644
--- a/src/perfetto_cmd/main.cc
+++ b/src/perfetto_cmd/main.cc
@@ -15,7 +15,7 @@
  */
 
 #include <stdio.h>
-#include "perfetto/ext/traced/traced.h"
+#include "perfetto/traced/traced.h"
 
 int main(int argc, char** argv) {
   return perfetto::PerfettoCmdMain(argc, argv);
diff --git a/src/perfetto_cmd/packet_writer.cc b/src/perfetto_cmd/packet_writer.cc
index 9d5a8d6..457ed94 100644
--- a/src/perfetto_cmd/packet_writer.cc
+++ b/src/perfetto_cmd/packet_writer.cc
@@ -26,10 +26,9 @@
 #include <unistd.h>
 #include <zlib.h>
 
-#include "perfetto/ext/base/paged_memory.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
+#include "perfetto/base/paged_memory.h"
 #include "perfetto/protozero/proto_utils.h"
+#include "perfetto/tracing/core/trace_packet.h"
 
 namespace perfetto {
 namespace {
diff --git a/src/perfetto_cmd/packet_writer.h b/src/perfetto_cmd/packet_writer.h
index 11d4f29..cd4fe1b 100644
--- a/src/perfetto_cmd/packet_writer.h
+++ b/src/perfetto_cmd/packet_writer.h
@@ -17,10 +17,9 @@
 #ifndef SRC_PERFETTO_CMD_PACKET_WRITER_H_
 #define SRC_PERFETTO_CMD_PACKET_WRITER_H_
 
-#include <memory>
 #include <vector>
 
-#include <stdio.h>
+#include "perfetto/base/utils.h"
 
 namespace perfetto {
 
diff --git a/src/perfetto_cmd/packet_writer_unittest.cc b/src/perfetto_cmd/packet_writer_unittest.cc
index 5736099..fede449 100644
--- a/src/perfetto_cmd/packet_writer_unittest.cc
+++ b/src/perfetto_cmd/packet_writer_unittest.cc
@@ -21,19 +21,20 @@
 
 #include <random>
 
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
 #include <zlib.h>
 
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
+#include "perfetto/base/file_utils.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/temp_file.h"
+#include "perfetto/tracing/core/trace_packet.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
-#include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/trace.pb.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/test_event.pbzero.h"
+#include "perfetto/trace/trace.pb.h"
+#include "perfetto/trace/trace_packet.pb.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 #include "src/perfetto_cmd/packet_writer.h"
-#include "test/gtest_and_gmock.h"
 
 namespace perfetto {
 namespace {
@@ -44,6 +45,7 @@
 TracePacket CreateTracePacket(F fill_function) {
   protozero::HeapBuffered<TracePacketZero> msg;
   fill_function(msg.get());
+  msg->Finalize();
   std::vector<uint8_t> buf = msg.SerializeAsArray();
   Slice slice = Slice::Allocate(buf.size());
   memcpy(slice.own_data(), buf.data(), buf.size());
@@ -80,11 +82,10 @@
 
 TEST(PacketWriter, FilePacketWriter) {
   base::TempFile tmp = base::TempFile::Create();
-  base::ScopedResource<FILE*, fclose, nullptr> f(
-      fdopen(tmp.ReleaseFD().release(), "wb"));
+  FILE* f = fdopen(tmp.fd(), "wb");
 
   {
-    std::unique_ptr<PacketWriter> writer = CreateFilePacketWriter(*f);
+    std::unique_ptr<PacketWriter> writer = CreateFilePacketWriter(f);
 
     std::vector<perfetto::TracePacket> packets;
 
@@ -96,10 +97,10 @@
     EXPECT_TRUE(writer->WritePackets(std::move(packets)));
   }
 
-  fseek(*f, 0, SEEK_SET);
+  fseek(f, 0, SEEK_SET);
   std::string s;
-  EXPECT_TRUE(base::ReadFileStream(*f, &s));
-  EXPECT_GT(s.size(), 0u);
+  EXPECT_TRUE(base::ReadFileStream(f, &s));
+  EXPECT_GT(s.size(), 0);
 
   protos::Trace trace;
   EXPECT_TRUE(trace.ParseFromString(s));
@@ -108,12 +109,11 @@
 
 TEST(PacketWriter, ZipPacketWriter) {
   base::TempFile tmp = base::TempFile::Create();
-  base::ScopedResource<FILE*, fclose, nullptr> f(
-      fdopen(tmp.ReleaseFD().release(), "wb"));
+  FILE* f = fdopen(tmp.fd(), "wb");
 
   {
     std::unique_ptr<PacketWriter> writer =
-        CreateZipPacketWriter(CreateFilePacketWriter(*f));
+        CreateZipPacketWriter(CreateFilePacketWriter(f));
 
     std::vector<perfetto::TracePacket> packets;
 
@@ -126,15 +126,15 @@
   }
 
   std::string s;
-  fseek(*f, 0, SEEK_SET);
-  EXPECT_TRUE(base::ReadFileStream(*f, &s));
-  EXPECT_GT(s.size(), 0u);
+  fseek(f, 0, SEEK_SET);
+  EXPECT_TRUE(base::ReadFileStream(f, &s));
+  EXPECT_GT(s.size(), 0);
 
   protos::Trace trace;
   EXPECT_TRUE(trace.ParseFromString(s));
 
   const std::string& data = trace.packet().Get(0).compressed_packets();
-  EXPECT_GT(data.size(), 0u);
+  EXPECT_GT(data.size(), 0);
 
   protos::Trace subtrace;
   EXPECT_TRUE(subtrace.ParseFromString(Decompress(data)));
@@ -143,42 +143,39 @@
 
 TEST(PacketWriter, ZipPacketWriter_Empty) {
   base::TempFile tmp = base::TempFile::Create();
-  base::ScopedResource<FILE*, fclose, nullptr> f(
-      fdopen(tmp.ReleaseFD().release(), "wb"));
+  FILE* f = fdopen(tmp.fd(), "wb");
 
   {
     std::unique_ptr<PacketWriter> writer =
-        CreateZipPacketWriter(CreateFilePacketWriter(*f));
+        CreateZipPacketWriter(CreateFilePacketWriter(f));
   }
 
-  EXPECT_EQ(fseek(*f, 0, SEEK_END), 0);
+  EXPECT_EQ(fseek(f, 0, SEEK_END), 0);
 }
 
 TEST(PacketWriter, ZipPacketWriter_EmptyWithEmptyWrite) {
   base::TempFile tmp = base::TempFile::Create();
-  base::ScopedResource<FILE*, fclose, nullptr> f(
-      fdopen(tmp.ReleaseFD().release(), "wb"));
+  FILE* f = fdopen(tmp.fd(), "wb");
 
   {
     std::unique_ptr<PacketWriter> writer =
-        CreateZipPacketWriter(CreateFilePacketWriter(*f));
+        CreateZipPacketWriter(CreateFilePacketWriter(f));
     writer->WritePackets(std::vector<TracePacket>());
     writer->WritePackets(std::vector<TracePacket>());
     writer->WritePackets(std::vector<TracePacket>());
   }
 
-  EXPECT_EQ(fseek(*f, 0, SEEK_END), 0);
+  EXPECT_EQ(fseek(f, 0, SEEK_END), 0);
 }
 
 TEST(PacketWriter, ZipPacketWriter_ShouldCompress) {
   base::TempFile tmp = base::TempFile::Create();
-  base::ScopedResource<FILE*, fclose, nullptr> f(
-      fdopen(tmp.ReleaseFD().release(), "wb"));
+  FILE* f = fdopen(tmp.fd(), "wb");
   size_t uncompressed_size = 0;
 
   {
     std::unique_ptr<PacketWriter> writer =
-        CreateZipPacketWriter(CreateFilePacketWriter(*f));
+        CreateZipPacketWriter(CreateFilePacketWriter(f));
 
     for (size_t i = 0; i < 200; i++) {
       std::vector<perfetto::TracePacket> packets;
@@ -201,10 +198,10 @@
   }
 
   std::string s;
-  EXPECT_LT(fseek(*f, 0, SEEK_END), static_cast<int>(uncompressed_size));
-  fseek(*f, 0, SEEK_SET);
-  EXPECT_TRUE(base::ReadFileStream(*f, &s));
-  EXPECT_GT(s.size(), 0u);
+  EXPECT_LT(fseek(f, 0, SEEK_END), uncompressed_size);
+  fseek(f, 0, SEEK_SET);
+  EXPECT_TRUE(base::ReadFileStream(f, &s));
+  EXPECT_GT(s.size(), 0);
 
   protos::Trace trace;
   EXPECT_TRUE(trace.ParseFromString(s));
@@ -212,8 +209,8 @@
   size_t packet_count = 0;
   for (const auto& packet : trace.packet()) {
     const std::string& data = packet.compressed_packets();
-    EXPECT_GT(data.size(), 0u);
-    EXPECT_LT(data.size(), 500 * 1024u);
+    EXPECT_GT(data.size(), 0);
+    EXPECT_LT(data.size(), 500 * 1024);
     protos::Trace subtrace;
     EXPECT_TRUE(subtrace.ParseFromString(Decompress(data)));
     for (const auto& subpacket : subtrace.packet()) {
@@ -222,13 +219,12 @@
     }
   }
 
-  EXPECT_EQ(packet_count, 200 * 2u);
+  EXPECT_EQ(packet_count, 200 * 2);
 }
 
 TEST(PacketWriter, ZipPacketWriter_ShouldSplitPackets) {
   base::TempFile tmp = base::TempFile::Create();
-  base::ScopedResource<FILE*, fclose, nullptr> f(
-      fdopen(tmp.ReleaseFD().release(), "wb"));
+  FILE* f = fdopen(tmp.fd(), "wb");
 
   std::minstd_rand0 rnd(0);
   std::uniform_int_distribution<> dist(0, 255);
@@ -242,7 +238,7 @@
 
   {
     std::unique_ptr<PacketWriter> writer =
-        CreateZipPacketWriter(CreateFilePacketWriter(*f));
+        CreateZipPacketWriter(CreateFilePacketWriter(f));
 
     for (uint32_t i = 0; i < 1000; i++) {
       std::vector<perfetto::TracePacket> packets;
@@ -260,9 +256,9 @@
   }
 
   std::string s;
-  fseek(*f, 0, SEEK_SET);
-  EXPECT_TRUE(base::ReadFileStream(*f, &s));
-  EXPECT_GT(s.size(), 0u);
+  fseek(f, 0, SEEK_SET);
+  EXPECT_TRUE(base::ReadFileStream(f, &s));
+  EXPECT_GT(s.size(), 0);
 
   protos::Trace trace;
   EXPECT_TRUE(trace.ParseFromString(s));
@@ -270,8 +266,8 @@
   size_t packet_count = 0;
   for (const auto& packet : trace.packet()) {
     const std::string& data = packet.compressed_packets();
-    EXPECT_GT(data.size(), 0u);
-    EXPECT_LT(data.size(), 500 * 1024u);
+    EXPECT_GT(data.size(), 0);
+    EXPECT_LT(data.size(), 500 * 1024);
     protos::Trace subtrace;
     EXPECT_TRUE(subtrace.ParseFromString(Decompress(data)));
     for (const auto& subpacket : subtrace.packet()) {
@@ -279,7 +275,7 @@
     }
   }
 
-  EXPECT_EQ(packet_count, 1000u);
+  EXPECT_EQ(packet_count, 1000);
 }
 
 }  // namespace
diff --git a/src/perfetto_cmd/pbtxt_to_pb.cc b/src/perfetto_cmd/pbtxt_to_pb.cc
index cdb7b73..cc123a9 100644
--- a/src/perfetto_cmd/pbtxt_to_pb.cc
+++ b/src/perfetto_cmd/pbtxt_to_pb.cc
@@ -21,16 +21,16 @@
 
 #include "src/perfetto_cmd/pbtxt_to_pb.h"
 
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/string_view.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/common/descriptor.pb.h"
 #include "perfetto/protozero/message.h"
 #include "perfetto/protozero/message_handle.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
-#include "protos/perfetto/common/descriptor.pb.h"
 #include "src/perfetto_cmd/perfetto_config.descriptor.h"
 
 namespace perfetto {
@@ -41,6 +41,8 @@
 using protos::EnumValueDescriptorProto;
 using protos::FieldDescriptorProto;
 using protos::FileDescriptorSet;
+using ::google::protobuf::io::ZeroCopyInputStream;
+using ::google::protobuf::io::ArrayInputStream;
 
 namespace {
 
@@ -306,18 +308,9 @@
         enum_value_number = enum_value.number();
         break;
       }
-      if (!found_value) {
-        AddError(value,
-                 "Unexpected value '$v' for enum field $k in "
-                 "proto $n",
-                 std::map<std::string, std::string>{
-                     {"$v", value.ToStdString()},
-                     {"$k", key.ToStdString()},
-                     {"$n", descriptor_name()},
-                 });
-        return;
-      }
+      PERFETTO_CHECK(found_value);
       msg()->AppendVarInt<int32_t>(field_id, enum_value_number);
+    } else {
     }
   }
 
@@ -383,8 +376,8 @@
   template <typename T>
   void FixedFloatField(const FieldDescriptorProto* field, Token t) {
     uint32_t field_id = static_cast<uint32_t>(field->number());
-    base::Optional<double> opt_n = base::StringToDouble(t.ToStdString());
-    msg()->AppendFixed<T>(field_id, static_cast<T>(opt_n.value_or(0l)));
+    double n = std::stod(t.ToStdString());
+    msg()->AppendFixed<T>(field_id, static_cast<T>(n));
   }
 
   template <typename T>
@@ -565,8 +558,7 @@
 
       case kReadingNumericValue:
         if (isspace(c) || c == ';' || last_character) {
-          bool keep_last = last_character && !(isspace(c) || c == ';');
-          size_t size = i - value.offset + (keep_last ? 1 : 0);
+          size_t size = i - value.offset + (last_character ? 1 : 0);
           value.txt = base::StringView(input.data() + value.offset, size);
           saw_semicolon_for_this_value = c == ';';
           state = kWaitingForKey;
@@ -596,9 +588,7 @@
 
       case kReadingIdentifierValue:
         if (isspace(c) || c == ';' || c == '#' || last_character) {
-          bool keep_last =
-              last_character && !(isspace(c) || c == ';' || c == '#');
-          size_t size = i - value.offset + (keep_last ? 1 : 0);
+          size_t size = i - value.offset + (last_character ? 1 : 0);
           value.txt = base::StringView(input.data() + value.offset, size);
           comment_till_eol = c == '#';
           saw_semicolon_for_this_value = c == ';';
diff --git a/src/perfetto_cmd/pbtxt_to_pb_unittest.cc b/src/perfetto_cmd/pbtxt_to_pb_unittest.cc
index 65751cc..7f4dbf2 100644
--- a/src/perfetto_cmd/pbtxt_to_pb_unittest.cc
+++ b/src/perfetto_cmd/pbtxt_to_pb_unittest.cc
@@ -19,10 +19,11 @@
 #include <memory>
 #include <string>
 
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-#include "protos/perfetto/config/trace_config.pb.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+#include "perfetto/config/trace_config.pb.h"
 
 namespace perfetto {
 namespace {
@@ -61,7 +62,7 @@
   protos::TraceConfig config = ToProto(R"(
     duration_ms: 1234
   )");
-  EXPECT_EQ(config.duration_ms(), 1234u);
+  EXPECT_EQ(config.duration_ms(), 1234);
 }
 
 TEST(PbtxtToPb, TwoFields) {
@@ -69,53 +70,8 @@
     duration_ms: 1234
     file_write_period_ms: 5678
   )");
-  EXPECT_EQ(config.duration_ms(), 1234u);
-  EXPECT_EQ(config.file_write_period_ms(), 5678u);
-}
-
-TEST(PbtxtToPb, Enum) {
-  protos::TraceConfig config = ToProto(R"(
-compression_type: COMPRESSION_TYPE_DEFLATE
-)");
-  EXPECT_EQ(config.compression_type(), 1);
-}
-
-TEST(PbtxtToPb, LastCharacters) {
-  EXPECT_EQ(ToProto(R"(
-duration_ms: 123;)")
-                .duration_ms(),
-            123u);
-  EXPECT_EQ(ToProto(R"(
-  duration_ms: 123
-)")
-                .duration_ms(),
-            123u);
-  EXPECT_EQ(ToProto(R"(
-  duration_ms: 123#)")
-                .duration_ms(),
-            123u);
-  EXPECT_EQ(ToProto(R"(
-  duration_ms: 123 )")
-                .duration_ms(),
-            123u);
-
-  EXPECT_EQ(ToProto(R"(
-compression_type: COMPRESSION_TYPE_DEFLATE;)")
-                .compression_type(),
-            1);
-  EXPECT_EQ(ToProto(R"(
-compression_type: COMPRESSION_TYPE_DEFLATE
-)")
-                .compression_type(),
-            1);
-  EXPECT_EQ(ToProto(R"(
-  compression_type: COMPRESSION_TYPE_DEFLATE#)")
-                .compression_type(),
-            1);
-  EXPECT_EQ(ToProto(R"(
-  compression_type: COMPRESSION_TYPE_DEFLATE )")
-                .compression_type(),
-            1);
+  EXPECT_EQ(config.duration_ms(), 1234);
+  EXPECT_EQ(config.file_write_period_ms(), 5678);
 }
 
 TEST(PbtxtToPb, Semicolons) {
@@ -123,8 +79,8 @@
     duration_ms: 1234;
     file_write_period_ms: 5678;
   )");
-  EXPECT_EQ(config.duration_ms(), 1234u);
-  EXPECT_EQ(config.file_write_period_ms(), 5678u);
+  EXPECT_EQ(config.duration_ms(), 1234);
+  EXPECT_EQ(config.file_write_period_ms(), 5678);
 }
 
 TEST(PbtxtToPb, NestedMessage) {
@@ -134,7 +90,7 @@
     }
   )");
   ASSERT_EQ(config.buffers().size(), 1);
-  EXPECT_EQ(config.buffers().Get(0).size_kb(), 123u);
+  EXPECT_EQ(config.buffers().Get(0).size_kb(), 123);
 }
 
 TEST(PbtxtToPb, SplitNested) {
@@ -148,9 +104,9 @@
     }
   )");
   ASSERT_EQ(config.buffers().size(), 2);
-  EXPECT_EQ(config.buffers().Get(0).size_kb(), 1u);
-  EXPECT_EQ(config.buffers().Get(1).size_kb(), 2u);
-  EXPECT_EQ(config.duration_ms(), 1000u);
+  EXPECT_EQ(config.buffers().Get(0).size_kb(), 1);
+  EXPECT_EQ(config.buffers().Get(1).size_kb(), 2);
+  EXPECT_EQ(config.duration_ms(), 1000);
 }
 
 TEST(PbtxtToPb, MultipleNestedMessage) {
@@ -163,8 +119,8 @@
     }
   )");
   ASSERT_EQ(config.buffers().size(), 2);
-  EXPECT_EQ(config.buffers().Get(0).size_kb(), 1u);
-  EXPECT_EQ(config.buffers().Get(1).size_kb(), 2u);
+  EXPECT_EQ(config.buffers().Get(0).size_kb(), 1);
+  EXPECT_EQ(config.buffers().Get(1).size_kb(), 2);
 }
 
 TEST(PbtxtToPb, NestedMessageCrossFile) {
@@ -179,7 +135,7 @@
   )");
   ASSERT_EQ(
       config.data_sources().Get(0).config().ftrace_config().drain_period_ms(),
-      42u);
+      42);
 }
 
 TEST(PbtxtToPb, Booleans) {
@@ -251,16 +207,16 @@
   )");
   const auto& fields =
       config.data_sources().Get(0).config().for_testing().dummy_fields();
-  ASSERT_EQ(fields.field_uint32(), 1u);
-  ASSERT_EQ(fields.field_uint64(), 2u);
+  ASSERT_EQ(fields.field_uint32(), 1);
+  ASSERT_EQ(fields.field_uint64(), 2);
   ASSERT_EQ(fields.field_int32(), 3);
   ASSERT_EQ(fields.field_int64(), 4);
-  ASSERT_EQ(fields.field_fixed64(), 5u);
+  ASSERT_EQ(fields.field_fixed64(), 5);
   ASSERT_EQ(fields.field_sfixed64(), 6);
-  ASSERT_EQ(fields.field_fixed32(), 7u);
+  ASSERT_EQ(fields.field_fixed32(), 7);
   ASSERT_EQ(fields.field_sfixed32(), 8);
-  ASSERT_DOUBLE_EQ(fields.field_double(), 9);
-  ASSERT_FLOAT_EQ(fields.field_float(), 10);
+  ASSERT_EQ(fields.field_double(), 9);
+  ASSERT_EQ(fields.field_float(), 10);
   ASSERT_EQ(fields.field_sint64(), 11);
   ASSERT_EQ(fields.field_sint32(), 12);
   ASSERT_EQ(fields.field_string(), "13");
@@ -292,19 +248,19 @@
       config.data_sources().Get(0).config().for_testing().dummy_fields();
   ASSERT_EQ(fields.field_int32(), -1);
   ASSERT_EQ(fields.field_int64(), -2);
-  ASSERT_EQ(fields.field_fixed64(), static_cast<uint64_t>(-3));
+  ASSERT_EQ(fields.field_fixed64(), -3);
   ASSERT_EQ(fields.field_sfixed64(), -4);
-  ASSERT_EQ(fields.field_fixed32(), static_cast<uint32_t>(-5));
+  ASSERT_EQ(fields.field_fixed32(), -5);
   ASSERT_EQ(fields.field_sfixed32(), -6);
-  ASSERT_DOUBLE_EQ(fields.field_double(), -7);
-  ASSERT_FLOAT_EQ(fields.field_float(), -8);
+  ASSERT_EQ(fields.field_double(), -7);
+  ASSERT_EQ(fields.field_float(), -8);
   ASSERT_EQ(fields.field_sint64(), -9);
   ASSERT_EQ(fields.field_sint32(), -10);
 }
 
 TEST(PbtxtToPb, EofEndsNumeric) {
   protos::TraceConfig config = ToProto(R"(duration_ms: 1234)");
-  EXPECT_EQ(config.duration_ms(), 1234u);
+  EXPECT_EQ(config.duration_ms(), 1234);
 }
 
 TEST(PbtxtToPb, EofEndsIdentifier) {
@@ -364,10 +320,10 @@
 
 duration_ms: 10000
 )");
-  EXPECT_EQ(config.duration_ms(), 10000u);
-  EXPECT_EQ(config.buffers().Get(0).size_kb(), 100024u);
+  EXPECT_EQ(config.duration_ms(), 10000);
+  EXPECT_EQ(config.buffers().Get(0).size_kb(), 100024);
   EXPECT_EQ(config.data_sources().Get(0).config().name(), "linux.ftrace");
-  EXPECT_EQ(config.data_sources().Get(0).config().target_buffer(), 0u);
+  EXPECT_EQ(config.data_sources().Get(0).config().target_buffer(), 0);
   EXPECT_EQ(config.producers().Get(0).producer_name(),
             "perfetto.traced_probes");
 }
@@ -517,14 +473,6 @@
            &reporter);
 }
 
-TEST(PbtxtToPb, BadEnumValue) {
-  MockErrorReporter reporter;
-  EXPECT_CALL(reporter, AddError(1, 18, 3,
-                                 "Unexpected value 'FOO' for enum field "
-                                 "compression_type in proto TraceConfig"));
-  ToErrors(R"(compression_type: FOO)", &reporter);
-}
-
 // TODO(hjd): Add these tests.
 // TEST(PbtxtToPb, WrongTypeString)
 // TEST(PbtxtToPb, OverflowOnIntegers)
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index cdf6017..1d73166 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -21,7 +21,6 @@
 #include <signal.h>
 #include <stdio.h>
 #include <sys/stat.h>
-#include <sys/types.h>
 #include <time.h>
 #include <unistd.h>
 
@@ -30,27 +29,39 @@
 #include <iterator>
 #include <sstream>
 
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/logging.h"
+#include "perfetto/base/string_view.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/traced/traced.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/ipc/default_socket.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/common/tracing_service_state.pb.h"
+#include "perfetto/config/trace_config.pb.h"
 #include "perfetto/protozero/proto_utils.h"
+#include "perfetto/traced/traced.h"
+#include "perfetto/tracing/core/basic_types.h"
 #include "perfetto/tracing/core/data_source_config.h"
 #include "perfetto/tracing/core/data_source_descriptor.h"
 #include "perfetto/tracing/core/trace_config.h"
+#include "perfetto/tracing/core/trace_packet.h"
 #include "perfetto/tracing/core/tracing_service_state.h"
 #include "src/perfetto_cmd/config.h"
 #include "src/perfetto_cmd/packet_writer.h"
 #include "src/perfetto_cmd/pbtxt_to_pb.h"
 #include "src/perfetto_cmd/trigger_producer.h"
+#include "src/tracing/ipc/default_socket.h"
 
-#include "protos/perfetto/common/tracing_service_state.pb.h"
-#include "protos/perfetto/config/trace_config.pb.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+#include <sys/sendfile.h>
+
+#include <android/os/DropBoxManager.h>
+#include <utils/Looper.h>
+#include <utils/StrongPointer.h>
+
+#include "src/android_internal/incident_service.h"
+#include "src/android_internal/lazy_library_loader.h"
+#endif  // PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
 
 namespace perfetto {
 namespace {
@@ -117,9 +128,35 @@
   return true;
 }
 
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+static bool StartIncidentReport(const TraceConfig::IncidentReportConfig& cfg) {
+  PERFETTO_LAZY_LOAD(android_internal::StartIncidentReport, start_incident_fn);
+  if (!start_incident_fn)
+    return false;
+  return start_incident_fn(cfg.destination_package().c_str(),
+                           cfg.destination_class().c_str(),
+                           cfg.privacy_level());
+}
+#else
+static bool StartIncidentReport(const TraceConfig::IncidentReportConfig&) {
+  PERFETTO_FATAL("should not be called");
+}
+#endif
+
 }  // namespace
 
-const char* kStateDir = "/data/misc/perfetto-traces";
+// Directory for temporary trace files. Note that this is automatically created
+// by the system by setting setprop persist.traced.enable=1.
+const char* kTempDropBoxTraceDir = "/data/misc/perfetto-traces";
+
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+// If writing into an incident, the trace is written to a hardcoded location
+// that is known to incidentd.
+static const char kIncidentTraceLocation[] =
+    "/data/misc/perfetto-traces/incident-trace";
+static const char kTempIncidentTraceLocation[] =
+    "/data/misc/perfetto-traces/incident-trace.temp";
+#endif
 
 using protozero::proto_utils::MakeTagLengthDelimited;
 using protozero::proto_utils::WriteVarInt;
@@ -170,8 +207,6 @@
 }
 
 int PerfettoCmd::Main(int argc, char** argv) {
-  umask(0000);  // make sure that file creation is not affected by umask.
-
   enum LongOption {
     OPT_ALERT_ID = 1000,
     OPT_CONFIG_ID,
@@ -288,12 +323,13 @@
     }
 
     if (option == OPT_DROPBOX) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-      PERFETTO_CHECK(optarg);
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+      if (!optarg)
+        PERFETTO_FATAL("optarg is null");
       dropbox_tag_ = optarg;
       continue;
 #else
-      PERFETTO_ELOG("--dropbox is supported only on Android");
+      PERFETTO_ELOG("DropBox is only supported with Android tree builds");
       return 1;
 #endif
     }
@@ -450,10 +486,6 @@
     return 1;
   }
 
-  if (trace_config_->trace_uuid().empty() || !dropbox_tag_.empty()) {
-    trace_config_->set_trace_uuid(base::UuidToString(base::Uuidv4()));
-  }
-
   if (!trace_config_->incident_report_config().destination_package().empty()) {
     if (dropbox_tag_.empty()) {
       PERFETTO_ELOG("Unexpected IncidentReportConfig without --dropbox.");
@@ -709,12 +741,9 @@
       bytes_written_ = static_cast<size_t>(sz);
   }
 
-  if (!dropbox_tag_.empty()) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-    SaveTraceIntoDropboxAndIncidentOrCrash();
-#endif
-  } else {
+  if (dropbox_tag_.empty()) {
     trace_out_stream_.reset();
+    did_process_full_trace_ = true;
     if (trace_config_->write_into_file()) {
       // trace_out_path_ might be empty in the case of --attach.
       PERFETTO_LOG("Trace written into the output file");
@@ -722,17 +751,108 @@
       PERFETTO_LOG("Wrote %" PRIu64 " bytes into %s", bytes_written_,
                    trace_out_path_ == "-" ? "stdout" : trace_out_path_.c_str());
     }
+    task_runner_.Quit();
+    return;
+  }
+
+  // Otherwise, write to Dropbox unless there's a special override in the
+  // incident report config.
+  if (!trace_config_->incident_report_config().skip_dropbox()) {
+    if (bytes_written_ == 0) {
+      PERFETTO_LOG("Skipping write to dropbox. Empty trace.");
+    } else {
+      SaveOutputToDropboxOrCrash();
+    }
+  }
+
+  // Optionally save the trace as an incident. This is either in addition to, or
+  // instead of, the Dropbox write.
+  if (!trace_config_->incident_report_config().destination_package().empty()) {
+    if (bytes_written_ == 0) {
+      PERFETTO_LOG("Skipping incident report. Empty trace.");
+    } else {
+      SaveOutputToIncidentTraceOrCrash();
+
+      // Ask incidentd to create a report, which will read the file we just
+      // wrote.
+      PERFETTO_CHECK(
+          StartIncidentReport(trace_config_->incident_report_config()));
+    }
   }
 
   did_process_full_trace_ = true;
   task_runner_.Quit();
 }
 
+void PerfettoCmd::SaveOutputToDropboxOrCrash() {
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+  android::sp<android::os::DropBoxManager> dropbox =
+      new android::os::DropBoxManager();
+  PERFETTO_CHECK(fseek(*trace_out_stream_, 0, SEEK_SET) == 0);
+  // DropBox takes ownership of the file descriptor, so give it a duplicate.
+  // Also we need to give it a read-only copy of the fd or will hit a SELinux
+  // violation (about system_server ending up with a writable FD to our dir).
+  char fdpath[64];
+  sprintf(fdpath, "/proc/self/fd/%d", fileno(*trace_out_stream_));
+  base::ScopedFile read_only_fd(base::OpenFile(fdpath, O_RDONLY));
+  PERFETTO_CHECK(read_only_fd);
+  android::binder::Status status =
+      dropbox->addFile(android::String16(dropbox_tag_.c_str()),
+                       read_only_fd.release(), 0 /* flags */);
+  if (status.isOk()) {
+    PERFETTO_LOG("Wrote %" PRIu64
+                 " bytes (before compression) into DropBox with tag %s",
+                 bytes_written_, dropbox_tag_.c_str());
+  } else {
+    PERFETTO_FATAL("DropBox upload failed: %s", status.toString8().c_str());
+  }
+#endif
+}
+
+// Open a staging file (unlinking the previous instance), copy the trace
+// contents over, then rename to a final hardcoded path (known to incidentd).
+// Such tracing sessions should not normally overlap. We do not use unique
+// unique filenames to avoid creating an unbounded amount of files in case of
+// errors.
+void PerfettoCmd::SaveOutputToIncidentTraceOrCrash() {
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+  PERFETTO_CHECK(unlink(kTempIncidentTraceLocation) == 0 || errno == ENOENT);
+
+  // SELinux constrains the set of readers.
+  base::ScopedFile staging_fd =
+      base::OpenFile(kTempIncidentTraceLocation, O_CREAT | O_RDWR, 0666);
+  PERFETTO_CHECK(staging_fd);
+
+  // Set the desired permissions even if under a umask.
+  PERFETTO_CHECK(fchmod(*staging_fd, 0666) == 0);
+
+  off_t offset = 0;
+  PERFETTO_CHECK(sendfile(*staging_fd, fileno(*trace_out_stream_), &offset,
+                          bytes_written_) == bytes_written_);
+
+  staging_fd.reset();
+  PERFETTO_CHECK(rename(kTempIncidentTraceLocation, kIncidentTraceLocation) ==
+                 0);
+// Note: not calling fsync(2), as we're not interested in the file being
+// consistent in case of a crash.
+#endif
+}
+
 bool PerfettoCmd::OpenOutputFile() {
   base::ScopedFile fd;
   if (!dropbox_tag_.empty()) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-    fd = OpenDropboxTmpFile();
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+    // If we are tracing to DropBox, there's no need to make a
+    // filesystem-visible temporary file.
+    // TODO(skyostil): Fall back to base::TempFile for older devices.
+    fd = base::OpenFile(kTempDropBoxTraceDir, O_TMPFILE | O_RDWR, 0600);
+    if (!fd) {
+      PERFETTO_PLOG("Could not create a temporary trace file in %s",
+                    kTempDropBoxTraceDir);
+      return false;
+    }
+#else
+    PERFETTO_FATAL("Tracing to Dropbox requires the Android build.");
 #endif
   } else if (trace_out_path_ == "-") {
     fd.reset(dup(STDOUT_FILENO));
@@ -850,7 +970,7 @@
     printf("data_sources: {\n");
     printf("  producer_id: %d\n", ds.producer_id());
     printf("  descriptor: {\n");
-    printf("    name: \"%s\"\n", ds.ds_descriptor().name().c_str());
+    printf("    name: \"%s\"\n", ds.descriptor().name().c_str());
     printf("  }\n");
     printf("}\n");
   }
diff --git a/src/perfetto_cmd/perfetto_cmd.h b/src/perfetto_cmd/perfetto_cmd.h
index ce4ef6b..7a98f09 100644
--- a/src/perfetto_cmd/perfetto_cmd.h
+++ b/src/perfetto_cmd/perfetto_cmd.h
@@ -24,24 +24,32 @@
 #include <time.h>
 
 #include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/event_fd.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/unix_task_runner.h"
-#include "perfetto/ext/base/uuid.h"
-#include "perfetto/ext/tracing/core/consumer.h"
-#include "perfetto/ext/tracing/ipc/consumer_ipc_client.h"
+#include "perfetto/base/event.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/unix_task_runner.h"
+#include "perfetto/tracing/core/consumer.h"
+#include "perfetto/tracing/ipc/consumer_ipc_client.h"
 #include "src/perfetto_cmd/rate_limiter.h"
 
 #include "src/perfetto_cmd/perfetto_cmd_state.pb.h"
 
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+#include "perfetto/base/android_task_runner.h"
+#endif  // PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+
 namespace perfetto {
 
 class PacketWriter;
 
-// Directory for local state and temporary files. This is automatically
+// Temporary directory for DropBox traces. Note that this is automatically
 // created by the system by setting setprop persist.traced.enable=1.
-extern const char* kStateDir;
+extern const char* kTempDropBoxTraceDir;
+
+#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
+using PlatformTaskRunner = base::AndroidTaskRunner;
+#else
+using PlatformTaskRunner = base::UnixTaskRunner;
+#endif
 
 class PerfettoCmd : public Consumer {
  public:
@@ -77,14 +85,10 @@
   // within OnTraceDataTimeoutMs of when we expected to.
   void CheckTraceDataTimeout();
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  static base::ScopedFile OpenDropboxTmpFile();
-  void SaveTraceIntoDropboxAndIncidentOrCrash();
   void SaveOutputToDropboxOrCrash();
   void SaveOutputToIncidentTraceOrCrash();
-#endif
 
-  base::UnixTaskRunner task_runner_;
+  PlatformTaskRunner task_runner_;
 
   std::unique_ptr<perfetto::TracingService::ConsumerEndpoint>
       consumer_endpoint_;
@@ -94,7 +98,7 @@
   base::ScopedFstream trace_out_stream_;
 
   std::string trace_out_path_;
-  base::EventFd ctrl_c_evt_;
+  base::Event ctrl_c_evt_;
   std::string dropbox_tag_;
   bool did_process_full_trace_ = false;
   uint64_t bytes_written_ = 0;
diff --git a/src/perfetto_cmd/perfetto_cmd_android.cc b/src/perfetto_cmd/perfetto_cmd_android.cc
deleted file mode 100644
index ee131d9..0000000
--- a/src/perfetto_cmd/perfetto_cmd_android.cc
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.
- */
-
-#include "src/perfetto_cmd/perfetto_cmd.h"
-
-#include <inttypes.h>
-#include <sys/sendfile.h>
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/logging.h"
-#include "perfetto/tracing/core/trace_config.h"
-#include "src/android_internal/dropbox_service.h"
-#include "src/android_internal/incident_service.h"
-#include "src/android_internal/lazy_library_loader.h"
-
-namespace perfetto {
-
-void PerfettoCmd::SaveTraceIntoDropboxAndIncidentOrCrash() {
-  PERFETTO_CHECK(!dropbox_tag_.empty());
-
-  // Otherwise, write to Dropbox unless there's a special override in the
-  // incident report config.
-  if (!trace_config_->incident_report_config().skip_dropbox()) {
-    if (bytes_written_ == 0) {
-      PERFETTO_LOG("Skipping write to dropbox. Empty trace.");
-    } else {
-      SaveOutputToDropboxOrCrash();
-    }
-  }
-
-  // Optionally save the trace as an incident. This is either in addition to, or
-  // instead of, the Dropbox write.
-  if (!trace_config_->incident_report_config().destination_package().empty()) {
-    if (bytes_written_ == 0) {
-      PERFETTO_LOG("Skipping incident report. Empty trace.");
-    } else {
-      SaveOutputToIncidentTraceOrCrash();
-
-      // Ask incidentd to create a report, which will read the file we just
-      // wrote.
-      const auto& cfg = trace_config_->incident_report_config();
-      PERFETTO_LAZY_LOAD(android_internal::StartIncidentReport, incident_fn);
-      PERFETTO_CHECK(incident_fn(cfg.destination_package().c_str(),
-                                 cfg.destination_class().c_str(),
-                                 cfg.privacy_level()));
-    }
-  }
-}
-
-void PerfettoCmd::SaveOutputToDropboxOrCrash() {
-  PERFETTO_CHECK(fseek(*trace_out_stream_, 0, SEEK_SET) == 0);
-
-  // DropBox takes ownership of the file descriptor, so give it a duplicate.
-  // Also we need to give it a read-only copy of the fd or will hit a SELinux
-  // violation (about system_server ending up with a writable FD to our dir).
-  char fdpath[64];
-  sprintf(fdpath, "/proc/self/fd/%d", fileno(*trace_out_stream_));
-  base::ScopedFile read_only_fd(base::OpenFile(fdpath, O_RDONLY));
-  PERFETTO_CHECK(read_only_fd);
-
-  PERFETTO_LAZY_LOAD(android_internal::SaveIntoDropbox, dropbox_fn);
-  if (dropbox_fn(dropbox_tag_.c_str(), read_only_fd.release())) {
-    PERFETTO_LOG("Wrote %" PRIu64
-                 " bytes (before compression) into DropBox with tag %s",
-                 bytes_written_, dropbox_tag_.c_str());
-  } else {
-    PERFETTO_FATAL("DropBox upload failed");
-  }
-}
-
-// Open a staging file (unlinking the previous instance), copy the trace
-// contents over, then rename to a final hardcoded path (known to incidentd).
-// Such tracing sessions should not normally overlap. We do not use unique
-// unique filenames to avoid creating an unbounded amount of files in case of
-// errors.
-void PerfettoCmd::SaveOutputToIncidentTraceOrCrash() {
-  char kIncidentTracePath[256];
-  sprintf(kIncidentTracePath, "%s/incident-trace", kStateDir);
-
-  char kTempIncidentTracePath[256];
-  sprintf(kTempIncidentTracePath, "%s.temp", kIncidentTracePath);
-
-  PERFETTO_CHECK(unlink(kTempIncidentTracePath) == 0 || errno == ENOENT);
-
-  // SELinux constrains the set of readers.
-  base::ScopedFile staging_fd =
-      base::OpenFile(kTempIncidentTracePath, O_CREAT | O_RDWR, 0666);
-  PERFETTO_CHECK(staging_fd);
-  off_t offset = 0;
-  auto wsize = sendfile(*staging_fd, fileno(*trace_out_stream_), &offset,
-                        static_cast<size_t>(bytes_written_));
-  PERFETTO_CHECK(wsize == static_cast<ssize_t>(bytes_written_));
-  staging_fd.reset();
-  PERFETTO_CHECK(rename(kTempIncidentTracePath, kIncidentTracePath) == 0);
-  // Note: not calling fsync(2), as we're not interested in the file being
-  // consistent in case of a crash.
-}
-
-// static
-base::ScopedFile PerfettoCmd::OpenDropboxTmpFile() {
-  // If we are tracing to DropBox, there's no need to make a
-  // filesystem-visible temporary file.
-  auto fd = base::OpenFile(kStateDir, O_TMPFILE | O_RDWR, 0600);
-  if (!fd)
-    PERFETTO_PLOG("Could not create a temporary trace file in %s", kStateDir);
-  return fd;
-}
-
-}  // namespace perfetto
diff --git a/src/perfetto_cmd/perfetto_config.descriptor.h b/src/perfetto_cmd/perfetto_config.descriptor.h
index 00d7547..2999b51 100644
--- a/src/perfetto_cmd/perfetto_config.descriptor.h
+++ b/src/perfetto_cmd/perfetto_config.descriptor.h
@@ -10,1414 +10,998 @@
 // This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
 
 // SHA1(tools/gen_binary_descriptors)
-// 192b582ae52bb07b3d3ba66a94bcfd3127a5f42f
+// e329b1e1e964417db57f83d8ecf081e041923e78
 // SHA1(protos/perfetto/config/perfetto_config.proto)
-// 5cfe80d665da1604176ba404025526c8f293b0f5
+// 5c3f7529f11a8bf2a092b7a6dad77febf5393969
 
 // This is the proto PerfettoConfig encoded as a ProtoFileDescriptor to allow
 // for reflection without libprotobuf full/non-lite protos.
 
 namespace perfetto {
 
-constexpr std::array<uint8_t, 16768> kPerfettoConfigDescriptor{
-    {0x0a, 0xfc, 0x82, 0x01, 0x0a, 0x2c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x63, 0x6f,
-     0x6e, 0x66, 0x69, 0x67, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x93, 0x03, 0x0a, 0x14,
-     0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65,
-     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04,
-     0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
-     0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x13, 0x77, 0x69, 0x6c, 0x6c,
-     0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x6f, 0x6e, 0x5f, 0x73,
-     0x74, 0x6f, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x77,
-     0x69, 0x6c, 0x6c, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x4f, 0x6e, 0x53,
-     0x74, 0x6f, 0x70, 0x12, 0x2f, 0x0a, 0x14, 0x77, 0x69, 0x6c, 0x6c, 0x5f,
-     0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x6f, 0x6e, 0x5f, 0x73, 0x74,
-     0x61, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x77,
-     0x69, 0x6c, 0x6c, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x4f, 0x6e, 0x53,
-     0x74, 0x61, 0x72, 0x74, 0x12, 0x45, 0x0a, 0x1f, 0x68, 0x61, 0x6e, 0x64,
-     0x6c, 0x65, 0x73, 0x5f, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e,
-     0x74, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x6c,
-     0x65, 0x61, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1c, 0x68,
-     0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x49, 0x6e, 0x63, 0x72, 0x65, 0x6d,
-     0x65, 0x6e, 0x74, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6c,
-     0x65, 0x61, 0x72, 0x12, 0x5f, 0x0a, 0x16, 0x67, 0x70, 0x75, 0x5f, 0x63,
-     0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72,
-     0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32,
-     0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x47, 0x70, 0x75, 0x43, 0x6f, 0x75,
-     0x6e, 0x74, 0x65, 0x72, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
-     0x6f, 0x72, 0x42, 0x02, 0x28, 0x01, 0x52, 0x14, 0x67, 0x70, 0x75, 0x43,
-     0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
-     0x70, 0x74, 0x6f, 0x72, 0x12, 0x5f, 0x0a, 0x16, 0x74, 0x72, 0x61, 0x63,
-     0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x64, 0x65, 0x73, 0x63,
-     0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b,
-     0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b,
-     0x45, 0x76, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
-     0x74, 0x6f, 0x72, 0x42, 0x02, 0x28, 0x01, 0x52, 0x14, 0x74, 0x72, 0x61,
-     0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72,
-     0x69, 0x70, 0x74, 0x6f, 0x72, 0x22, 0xf7, 0x0b, 0x0a, 0x14, 0x47, 0x70,
-     0x75, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x44, 0x65, 0x73, 0x63,
-     0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x4a, 0x0a, 0x05, 0x73, 0x70,
-     0x65, 0x63, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2e, 0x47, 0x70, 0x75, 0x43, 0x6f, 0x75, 0x6e, 0x74,
-     0x65, 0x72, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
-     0x2e, 0x47, 0x70, 0x75, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x53,
-     0x70, 0x65, 0x63, 0x52, 0x05, 0x73, 0x70, 0x65, 0x63, 0x73, 0x12, 0x4d,
-     0x0a, 0x06, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x18, 0x02, 0x20, 0x03,
-     0x28, 0x0b, 0x32, 0x35, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x47, 0x70, 0x75,
-     0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x44, 0x65, 0x73, 0x63, 0x72,
-     0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x47, 0x70, 0x75, 0x43, 0x6f, 0x75,
-     0x6e, 0x74, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x06, 0x62,
-     0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x33, 0x0a, 0x16, 0x6d, 0x69, 0x6e,
-     0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x65,
-     0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
-     0x04, 0x52, 0x13, 0x6d, 0x69, 0x6e, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x69,
-     0x6e, 0x67, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4e, 0x73, 0x12, 0x33,
-     0x0a, 0x16, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69,
-     0x6e, 0x67, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6e, 0x73,
-     0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x6d, 0x61, 0x78, 0x53,
-     0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x50, 0x65, 0x72, 0x69, 0x6f,
-     0x64, 0x4e, 0x73, 0x12, 0x44, 0x0a, 0x1e, 0x73, 0x75, 0x70, 0x70, 0x6f,
-     0x72, 0x74, 0x73, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x6d, 0x65,
-     0x6e, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e,
-     0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1c, 0x73, 0x75, 0x70,
-     0x70, 0x6f, 0x72, 0x74, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x6d,
-     0x65, 0x6e, 0x74, 0x65, 0x64, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e,
-     0x67, 0x1a, 0xb7, 0x03, 0x0a, 0x0e, 0x47, 0x70, 0x75, 0x43, 0x6f, 0x75,
-     0x6e, 0x74, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x12, 0x1d, 0x0a, 0x0a,
-     0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01,
-     0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65,
-     0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
-     0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
-     0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
-     0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65,
-     0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a,
-     0x0e, 0x69, 0x6e, 0x74, 0x5f, 0x70, 0x65, 0x61, 0x6b, 0x5f, 0x76, 0x61,
-     0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52,
-     0x0c, 0x69, 0x6e, 0x74, 0x50, 0x65, 0x61, 0x6b, 0x56, 0x61, 0x6c, 0x75,
-     0x65, 0x12, 0x2c, 0x0a, 0x11, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f,
-     0x70, 0x65, 0x61, 0x6b, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06,
-     0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x0f, 0x64, 0x6f, 0x75, 0x62,
-     0x6c, 0x65, 0x50, 0x65, 0x61, 0x6b, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
-     0x5a, 0x0a, 0x0f, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72,
-     0x5f, 0x75, 0x6e, 0x69, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0e,
-     0x32, 0x31, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x47, 0x70, 0x75, 0x43, 0x6f,
-     0x75, 0x6e, 0x74, 0x65, 0x72, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
-     0x74, 0x6f, 0x72, 0x2e, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x55,
-     0x6e, 0x69, 0x74, 0x52, 0x0e, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x61, 0x74,
-     0x6f, 0x72, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x12, 0x5e, 0x0a, 0x11, 0x64,
-     0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75,
-     0x6e, 0x69, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x31,
-     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x47, 0x70, 0x75, 0x43, 0x6f, 0x75, 0x6e,
-     0x74, 0x65, 0x72, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
-     0x72, 0x2e, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x55, 0x6e, 0x69,
-     0x74, 0x52, 0x10, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x61, 0x74,
-     0x6f, 0x72, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x73,
-     0x65, 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x62, 0x79, 0x5f, 0x64, 0x65, 0x66,
-     0x61, 0x75, 0x6c, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f,
-     0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x42, 0x79, 0x44, 0x65, 0x66, 0x61,
-     0x75, 0x6c, 0x74, 0x42, 0x0c, 0x0a, 0x0a, 0x70, 0x65, 0x61, 0x6b, 0x5f,
-     0x76, 0x61, 0x6c, 0x75, 0x65, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x1a,
-     0xaa, 0x01, 0x0a, 0x0f, 0x47, 0x70, 0x75, 0x43, 0x6f, 0x75, 0x6e, 0x74,
-     0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x19, 0x0a, 0x08, 0x62,
-     0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
-     0x0d, 0x52, 0x07, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x64, 0x12, 0x25,
-     0x0a, 0x0e, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x61, 0x70, 0x61,
-     0x63, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d,
-     0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74,
-     0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20,
-     0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a,
-     0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
-     0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63,
-     0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x63,
-     0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x05,
-     0x20, 0x03, 0x28, 0x0d, 0x52, 0x0a, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65,
-     0x72, 0x49, 0x64, 0x73, 0x22, 0xac, 0x04, 0x0a, 0x0b, 0x4d, 0x65, 0x61,
-     0x73, 0x75, 0x72, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x08, 0x0a, 0x04,
-     0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x42, 0x49,
-     0x54, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x49, 0x4c, 0x4f, 0x42,
-     0x49, 0x54, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x4d, 0x45, 0x47, 0x41,
-     0x42, 0x49, 0x54, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x47, 0x49, 0x47,
-     0x41, 0x42, 0x49, 0x54, 0x10, 0x04, 0x12, 0x0b, 0x0a, 0x07, 0x54, 0x45,
-     0x52, 0x41, 0x42, 0x49, 0x54, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x50,
-     0x45, 0x54, 0x41, 0x42, 0x49, 0x54, 0x10, 0x06, 0x12, 0x08, 0x0a, 0x04,
-     0x42, 0x59, 0x54, 0x45, 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08, 0x4b, 0x49,
-     0x4c, 0x4f, 0x42, 0x59, 0x54, 0x45, 0x10, 0x08, 0x12, 0x0c, 0x0a, 0x08,
-     0x4d, 0x45, 0x47, 0x41, 0x42, 0x59, 0x54, 0x45, 0x10, 0x09, 0x12, 0x0c,
-     0x0a, 0x08, 0x47, 0x49, 0x47, 0x41, 0x42, 0x59, 0x54, 0x45, 0x10, 0x0a,
-     0x12, 0x0c, 0x0a, 0x08, 0x54, 0x45, 0x52, 0x41, 0x42, 0x59, 0x54, 0x45,
-     0x10, 0x0b, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x45, 0x54, 0x41, 0x42, 0x59,
-     0x54, 0x45, 0x10, 0x0c, 0x12, 0x09, 0x0a, 0x05, 0x48, 0x45, 0x52, 0x54,
-     0x5a, 0x10, 0x0d, 0x12, 0x0d, 0x0a, 0x09, 0x4b, 0x49, 0x4c, 0x4f, 0x48,
-     0x45, 0x52, 0x54, 0x5a, 0x10, 0x0e, 0x12, 0x0d, 0x0a, 0x09, 0x4d, 0x45,
-     0x47, 0x41, 0x48, 0x45, 0x52, 0x54, 0x5a, 0x10, 0x0f, 0x12, 0x0d, 0x0a,
-     0x09, 0x47, 0x49, 0x47, 0x41, 0x48, 0x45, 0x52, 0x54, 0x5a, 0x10, 0x10,
-     0x12, 0x0d, 0x0a, 0x09, 0x54, 0x45, 0x52, 0x41, 0x48, 0x45, 0x52, 0x54,
-     0x5a, 0x10, 0x11, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x45, 0x54, 0x41, 0x48,
-     0x45, 0x52, 0x54, 0x5a, 0x10, 0x12, 0x12, 0x0e, 0x0a, 0x0a, 0x4e, 0x41,
-     0x4e, 0x4f, 0x53, 0x45, 0x43, 0x4f, 0x4e, 0x44, 0x10, 0x13, 0x12, 0x0f,
-     0x0a, 0x0b, 0x4d, 0x49, 0x43, 0x52, 0x4f, 0x53, 0x45, 0x43, 0x4f, 0x4e,
-     0x44, 0x10, 0x14, 0x12, 0x0f, 0x0a, 0x0b, 0x4d, 0x49, 0x4c, 0x4c, 0x49,
-     0x53, 0x45, 0x43, 0x4f, 0x4e, 0x44, 0x10, 0x15, 0x12, 0x0a, 0x0a, 0x06,
-     0x53, 0x45, 0x43, 0x4f, 0x4e, 0x44, 0x10, 0x16, 0x12, 0x0a, 0x0a, 0x06,
-     0x4d, 0x49, 0x4e, 0x55, 0x54, 0x45, 0x10, 0x17, 0x12, 0x08, 0x0a, 0x04,
-     0x48, 0x4f, 0x55, 0x52, 0x10, 0x18, 0x12, 0x0a, 0x0a, 0x06, 0x56, 0x45,
-     0x52, 0x54, 0x45, 0x58, 0x10, 0x19, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x49,
-     0x58, 0x45, 0x4c, 0x10, 0x1a, 0x12, 0x0c, 0x0a, 0x08, 0x54, 0x52, 0x49,
-     0x41, 0x4e, 0x47, 0x4c, 0x45, 0x10, 0x1b, 0x12, 0x0d, 0x0a, 0x09, 0x50,
-     0x52, 0x49, 0x4d, 0x49, 0x54, 0x49, 0x56, 0x45, 0x10, 0x26, 0x12, 0x0c,
-     0x0a, 0x08, 0x46, 0x52, 0x41, 0x47, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x27,
-     0x12, 0x0d, 0x0a, 0x09, 0x4d, 0x49, 0x4c, 0x4c, 0x49, 0x57, 0x41, 0x54,
-     0x54, 0x10, 0x1c, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x41, 0x54, 0x54, 0x10,
-     0x1d, 0x12, 0x0c, 0x0a, 0x08, 0x4b, 0x49, 0x4c, 0x4f, 0x57, 0x41, 0x54,
-     0x54, 0x10, 0x1e, 0x12, 0x09, 0x0a, 0x05, 0x4a, 0x4f, 0x55, 0x4c, 0x45,
-     0x10, 0x1f, 0x12, 0x08, 0x0a, 0x04, 0x56, 0x4f, 0x4c, 0x54, 0x10, 0x20,
-     0x12, 0x0a, 0x0a, 0x06, 0x41, 0x4d, 0x50, 0x45, 0x52, 0x45, 0x10, 0x21,
-     0x12, 0x0b, 0x0a, 0x07, 0x43, 0x45, 0x4c, 0x53, 0x49, 0x55, 0x53, 0x10,
-     0x22, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x41, 0x48, 0x52, 0x45, 0x4e, 0x48,
-     0x45, 0x49, 0x54, 0x10, 0x23, 0x12, 0x0a, 0x0a, 0x06, 0x4b, 0x45, 0x4c,
-     0x56, 0x49, 0x4e, 0x10, 0x24, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, 0x52,
-     0x43, 0x45, 0x4e, 0x54, 0x10, 0x25, 0x12, 0x0f, 0x0a, 0x0b, 0x49, 0x4e,
-     0x53, 0x54, 0x52, 0x55, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x28, 0x22,
-     0xbc, 0x0a, 0x0a, 0x0a, 0x54, 0x72, 0x61, 0x63, 0x65, 0x53, 0x74, 0x61,
-     0x74, 0x73, 0x12, 0x4a, 0x0a, 0x0c, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72,
-     0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
-     0x32, 0x27, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65,
-     0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72,
-     0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0b, 0x62, 0x75, 0x66, 0x66, 0x65,
-     0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x2f, 0x0a, 0x13, 0x70, 0x72,
-     0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x6e,
-     0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52,
-     0x12, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x43, 0x6f,
-     0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x70,
-     0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x5f, 0x73, 0x65, 0x65,
-     0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x70, 0x72, 0x6f,
-     0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x53, 0x65, 0x65, 0x6e, 0x12, 0x36,
-     0x0a, 0x17, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63,
-     0x65, 0x73, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65,
-     0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x15, 0x64, 0x61, 0x74,
-     0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x67, 0x69,
-     0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x64, 0x61,
-     0x74, 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x5f, 0x73,
-     0x65, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x64,
-     0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x53, 0x65,
-     0x65, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e,
-     0x67, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06,
-     0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e,
-     0x67, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x23, 0x0a,
-     0x0d, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65,
-     0x72, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x74, 0x6f,
-     0x74, 0x61, 0x6c, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x73, 0x12, 0x29,
-     0x0a, 0x10, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x5f, 0x64, 0x69, 0x73,
-     0x63, 0x61, 0x72, 0x64, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04,
-     0x52, 0x0f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x44, 0x69, 0x73, 0x63,
-     0x61, 0x72, 0x64, 0x65, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x61, 0x74,
-     0x63, 0x68, 0x65, 0x73, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64,
-     0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x70, 0x61,
-     0x74, 0x63, 0x68, 0x65, 0x73, 0x44, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64,
-     0x65, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69,
-     0x64, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x0a, 0x20,
-     0x01, 0x28, 0x04, 0x52, 0x0e, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64,
-     0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x1a, 0xd4, 0x06, 0x0a, 0x0b,
-     0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12,
-     0x1f, 0x0a, 0x0b, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69,
-     0x7a, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x62, 0x75,
-     0x66, 0x66, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x23, 0x0a, 0x0d,
-     0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65,
-     0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x62, 0x79, 0x74,
-     0x65, 0x73, 0x57, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x12, 0x2b, 0x0a,
-     0x11, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x77,
-     0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04,
-     0x52, 0x10, 0x62, 0x79, 0x74, 0x65, 0x73, 0x4f, 0x76, 0x65, 0x72, 0x77,
-     0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x79,
-     0x74, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x18, 0x0e, 0x20, 0x01,
-     0x28, 0x04, 0x52, 0x09, 0x62, 0x79, 0x74, 0x65, 0x73, 0x52, 0x65, 0x61,
-     0x64, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
-     0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x74,
-     0x65, 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x70, 0x61,
-     0x64, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x79, 0x74, 0x65, 0x73, 0x57, 0x72,
-     0x69, 0x74, 0x74, 0x65, 0x6e, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x61, 0x64,
-     0x64, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x63,
-     0x6c, 0x65, 0x61, 0x72, 0x65, 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, 0x04,
-     0x52, 0x13, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x79, 0x74,
-     0x65, 0x73, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x65, 0x64, 0x12, 0x25, 0x0a,
-     0x0e, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x5f, 0x77, 0x72, 0x69, 0x74,
-     0x74, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x63,
-     0x68, 0x75, 0x6e, 0x6b, 0x73, 0x57, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e,
-     0x12, 0x29, 0x0a, 0x10, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x5f, 0x72,
-     0x65, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x18, 0x0a, 0x20, 0x01,
-     0x28, 0x04, 0x52, 0x0f, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x52, 0x65,
-     0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x12, 0x2d, 0x0a, 0x12, 0x63,
-     0x68, 0x75, 0x6e, 0x6b, 0x73, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x77, 0x72,
-     0x69, 0x74, 0x74, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52,
-     0x11, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x4f, 0x76, 0x65, 0x72, 0x77,
-     0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x68,
-     0x75, 0x6e, 0x6b, 0x73, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64,
-     0x65, 0x64, 0x18, 0x12, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x63, 0x68,
-     0x75, 0x6e, 0x6b, 0x73, 0x44, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x65,
-     0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x5f,
-     0x72, 0x65, 0x61, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a,
-     0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x52, 0x65, 0x61, 0x64, 0x12, 0x40,
-     0x0a, 0x1d, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x5f, 0x63, 0x6f, 0x6d,
-     0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x6f,
-     0x66, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28,
-     0x04, 0x52, 0x19, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x43, 0x6f, 0x6d,
-     0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x4f, 0x75, 0x74, 0x4f, 0x66, 0x4f,
-     0x72, 0x64, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x77, 0x72, 0x69, 0x74,
-     0x65, 0x5f, 0x77, 0x72, 0x61, 0x70, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
-     0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x77, 0x72, 0x69, 0x74,
-     0x65, 0x57, 0x72, 0x61, 0x70, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2b,
-     0x0a, 0x11, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x5f, 0x73, 0x75,
-     0x63, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28,
-     0x04, 0x52, 0x10, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x53, 0x75,
-     0x63, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x70,
-     0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x65,
-     0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x70, 0x61, 0x74,
-     0x63, 0x68, 0x65, 0x73, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x31,
-     0x0a, 0x14, 0x72, 0x65, 0x61, 0x64, 0x61, 0x68, 0x65, 0x61, 0x64, 0x73,
-     0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x18, 0x07,
-     0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x72, 0x65, 0x61, 0x64, 0x61, 0x68,
-     0x65, 0x61, 0x64, 0x73, 0x53, 0x75, 0x63, 0x63, 0x65, 0x65, 0x64, 0x65,
-     0x64, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x61, 0x64, 0x61, 0x68, 0x65,
-     0x61, 0x64, 0x73, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x08,
-     0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x72, 0x65, 0x61, 0x64, 0x61, 0x68,
-     0x65, 0x61, 0x64, 0x73, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x25,
-     0x0a, 0x0e, 0x61, 0x62, 0x69, 0x5f, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74,
-     0x69, 0x6f, 0x6e, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d,
-     0x61, 0x62, 0x69, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e,
-     0x73, 0x12, 0x37, 0x0a, 0x18, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x77,
-     0x72, 0x69, 0x74, 0x65, 0x72, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74,
-     0x5f, 0x6c, 0x6f, 0x73, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x04, 0x52,
-     0x15, 0x74, 0x72, 0x61, 0x63, 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, 0x72,
-     0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x4c, 0x6f, 0x73, 0x73, 0x22, 0xc8,
-     0x03, 0x0a, 0x13, 0x54, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x53, 0x65,
-     0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x4b,
-     0x0a, 0x09, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x18,
-     0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
-     0x54, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69,
-     0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x64,
-     0x75, 0x63, 0x65, 0x72, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63,
-     0x65, 0x72, 0x73, 0x12, 0x52, 0x0a, 0x0c, 0x64, 0x61, 0x74, 0x61, 0x5f,
-     0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
-     0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63,
-     0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x74,
-     0x61, 0x74, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72,
-     0x63, 0x65, 0x52, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72,
-     0x63, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x75, 0x6d, 0x5f, 0x73,
-     0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
-     0x05, 0x52, 0x0b, 0x6e, 0x75, 0x6d, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f,
-     0x6e, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x6e, 0x75, 0x6d, 0x5f, 0x73, 0x65,
-     0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74,
-     0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x6e, 0x75,
-     0x6d, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x61,
-     0x72, 0x74, 0x65, 0x64, 0x1a, 0x40, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x64,
-     0x75, 0x63, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
-     0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04,
-     0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
-     0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18,
-     0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x75, 0x69, 0x64, 0x1a, 0x79,
-     0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
-     0x12, 0x4a, 0x0a, 0x0d, 0x64, 0x73, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72,
-     0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
-     0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f,
-     0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
-     0x6f, 0x72, 0x52, 0x0c, 0x64, 0x73, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
-     0x70, 0x74, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x64,
-     0x75, 0x63, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
-     0x05, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x49,
-     0x64, 0x22, 0x49, 0x0a, 0x14, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x45, 0x76,
-     0x65, 0x6e, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
-     0x72, 0x12, 0x31, 0x0a, 0x14, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62,
-     0x6c, 0x65, 0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65,
-     0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x61, 0x76, 0x61,
-     0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f,
-     0x72, 0x69, 0x65, 0x73, 0x22, 0xb1, 0x01, 0x0a, 0x10, 0x41, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6f, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69,
-     0x67, 0x12, 0x36, 0x0a, 0x07, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x73,
-     0x18, 0x01, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6f, 0x67, 0x49,
-     0x64, 0x52, 0x06, 0x6c, 0x6f, 0x67, 0x49, 0x64, 0x73, 0x12, 0x3e, 0x0a,
-     0x08, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x72, 0x69, 0x6f, 0x18, 0x03, 0x20,
-     0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6f, 0x67, 0x50, 0x72, 0x69, 0x6f,
-     0x72, 0x69, 0x74, 0x79, 0x52, 0x07, 0x6d, 0x69, 0x6e, 0x50, 0x72, 0x69,
-     0x6f, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f,
-     0x74, 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a,
-     0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x4a, 0x04,
-     0x08, 0x02, 0x10, 0x03, 0x22, 0x6d, 0x0a, 0x0c, 0x43, 0x68, 0x72, 0x6f,
-     0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x21, 0x0a, 0x0c,
-     0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-     0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x63,
-     0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3a, 0x0a, 0x19, 0x70,
-     0x72, 0x69, 0x76, 0x61, 0x63, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65,
-     0x72, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
-     0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x70, 0x72, 0x69, 0x76,
-     0x61, 0x63, 0x79, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67,
-     0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x82, 0x0a, 0x0a, 0x10,
-     0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f,
-     0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
-     0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
-     0x12, 0x23, 0x0a, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x62,
-     0x75, 0x66, 0x66, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52,
-     0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x42, 0x75, 0x66, 0x66, 0x65,
-     0x72, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x64,
-     0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x03,
-     0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x44,
-     0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x26, 0x0a,
-     0x0f, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75,
-     0x74, 0x5f, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d,
-     0x73, 0x74, 0x6f, 0x70, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d,
-     0x73, 0x12, 0x36, 0x0a, 0x17, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f,
-     0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72,
-     0x61, 0x69, 0x6c, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15,
-     0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x74, 0x72, 0x61, 0x47,
-     0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x2c, 0x0a,
-     0x12, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x73,
-     0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28,
-     0x04, 0x52, 0x10, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x53, 0x65,
-     0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x46, 0x0a, 0x0d, 0x66,
-     0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-     0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2e, 0x46, 0x74, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69,
-     0x67, 0x42, 0x02, 0x28, 0x01, 0x52, 0x0c, 0x66, 0x74, 0x72, 0x61, 0x63,
-     0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x50, 0x0a, 0x11, 0x69,
-     0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f,
-     0x6e, 0x66, 0x69, 0x67, 0x18, 0x66, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20,
-     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x6f, 0x64, 0x65, 0x46, 0x69,
-     0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x02, 0x28, 0x01,
-     0x52, 0x0f, 0x69, 0x6e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x43,
-     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x59, 0x0a, 0x14, 0x70, 0x72, 0x6f,
-     0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x63,
-     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x67, 0x20, 0x01, 0x28, 0x0b, 0x32,
-     0x23, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
-     0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-     0x42, 0x02, 0x28, 0x01, 0x52, 0x12, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
-     0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-     0x12, 0x4d, 0x0a, 0x10, 0x73, 0x79, 0x73, 0x5f, 0x73, 0x74, 0x61, 0x74,
-     0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x68, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x53, 0x79, 0x73,
-     0x53, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42,
-     0x02, 0x28, 0x01, 0x52, 0x0e, 0x73, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74,
-     0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f, 0x0a, 0x10, 0x68,
-     0x65, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x66, 0x64, 0x5f, 0x63, 0x6f, 0x6e,
-     0x66, 0x69, 0x67, 0x18, 0x69, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x66,
-     0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x02, 0x28, 0x01, 0x52,
-     0x0f, 0x68, 0x65, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x66, 0x64, 0x43, 0x6f,
-     0x6e, 0x66, 0x69, 0x67, 0x12, 0x50, 0x0a, 0x11, 0x6a, 0x61, 0x76, 0x61,
-     0x5f, 0x68, 0x70, 0x72, 0x6f, 0x66, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
-     0x67, 0x18, 0x6e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2e, 0x4a, 0x61, 0x76, 0x61, 0x48, 0x70, 0x72, 0x6f, 0x66, 0x43,
-     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x02, 0x28, 0x01, 0x52, 0x0f, 0x6a,
-     0x61, 0x76, 0x61, 0x48, 0x70, 0x72, 0x6f, 0x66, 0x43, 0x6f, 0x6e, 0x66,
-     0x69, 0x67, 0x12, 0x59, 0x0a, 0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x5f, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66,
-     0x69, 0x67, 0x18, 0x6a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f,
-     0x77, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x02, 0x28,
-     0x01, 0x52, 0x12, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f,
-     0x77, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x53, 0x0a,
-     0x12, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6c, 0x6f, 0x67,
-     0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x6b, 0x20, 0x01, 0x28,
-     0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+constexpr std::array<uint8_t, 11784> kPerfettoConfigDescriptor{
+    {0x0a, 0x85, 0x5c, 0x0a, 0x25, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22,
+     0xb1, 0x01, 0x0a, 0x10, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c,
+     0x6f, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x07,
+     0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
+     0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
      0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x4c, 0x6f, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-     0x42, 0x02, 0x28, 0x01, 0x52, 0x10, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x4c, 0x6f, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x53,
-     0x0a, 0x12, 0x67, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65,
-     0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x6c, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x47, 0x70, 0x75,
-     0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69,
-     0x67, 0x42, 0x02, 0x28, 0x01, 0x52, 0x10, 0x67, 0x70, 0x75, 0x43, 0x6f,
-     0x75, 0x6e, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
-     0x59, 0x0a, 0x14, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x5f,
-     0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18,
-     0x6d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
-     0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74,
-     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x02, 0x28, 0x01, 0x52, 0x12,
-     0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74,
+     0x6f, 0x69, 0x64, 0x4c, 0x6f, 0x67, 0x49, 0x64, 0x52, 0x06, 0x6c, 0x6f,
+     0x67, 0x49, 0x64, 0x73, 0x12, 0x3e, 0x0a, 0x08, 0x6d, 0x69, 0x6e, 0x5f,
+     0x70, 0x72, 0x69, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23,
+     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+     0x4c, 0x6f, 0x67, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52,
+     0x07, 0x6d, 0x69, 0x6e, 0x50, 0x72, 0x69, 0x6f, 0x12, 0x1f, 0x0a, 0x0b,
+     0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18,
+     0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x74, 0x65,
+     0x72, 0x54, 0x61, 0x67, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22,
+     0x6d, 0x0a, 0x0c, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6e,
+     0x66, 0x69, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x72, 0x61, 0x63, 0x65,
+     0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28,
+     0x09, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66,
+     0x69, 0x67, 0x12, 0x3a, 0x0a, 0x19, 0x70, 0x72, 0x69, 0x76, 0x61, 0x63,
+     0x79, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f,
+     0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
+     0x08, 0x52, 0x17, 0x70, 0x72, 0x69, 0x76, 0x61, 0x63, 0x79, 0x46, 0x69,
+     0x6c, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, 0x6c,
+     0x65, 0x64, 0x22, 0x88, 0x08, 0x0a, 0x10, 0x44, 0x61, 0x74, 0x61, 0x53,
+     0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
+     0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+     0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x74,
+     0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67,
+     0x65, 0x74, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x11,
+     0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69,
+     0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52,
+     0x0f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69,
+     0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x65, 0x6e, 0x61, 0x62,
+     0x6c, 0x65, 0x5f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x67, 0x75, 0x61,
+     0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28,
+     0x08, 0x52, 0x15, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x74,
+     0x72, 0x61, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x73,
+     0x12, 0x2c, 0x0a, 0x12, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x5f,
+     0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04,
+     0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e,
+     0x67, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x42,
+     0x0a, 0x0d, 0x66, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e,
+     0x66, 0x69, 0x67, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2e, 0x46, 0x74, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f,
+     0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x66, 0x74, 0x72, 0x61, 0x63, 0x65,
      0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, 0x0d, 0x63, 0x68,
      0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18,
      0x65, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x65, 0x72, 0x66,
      0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
      0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
      0x52, 0x0c, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x66,
-     0x69, 0x67, 0x12, 0x24, 0x0a, 0x0d, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79,
-     0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0xe8, 0x07, 0x20, 0x01,
-     0x28, 0x09, 0x52, 0x0c, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x43, 0x6f,
-     0x6e, 0x66, 0x69, 0x67, 0x12, 0x3d, 0x0a, 0x0b, 0x66, 0x6f, 0x72, 0x5f,
-     0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x18, 0xe9, 0x07, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x65, 0x73,
-     0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x66, 0x6f, 0x72,
-     0x54, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x4a, 0x0b, 0x08, 0xff, 0xff,
-     0xff, 0x7f, 0x10, 0x80, 0x80, 0x80, 0x80, 0x01, 0x22, 0xd6, 0x02, 0x0a,
-     0x0c, 0x46, 0x74, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69,
-     0x67, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f,
-     0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09,
-     0x52, 0x0c, 0x66, 0x74, 0x72, 0x61, 0x63, 0x65, 0x45, 0x76, 0x65, 0x6e,
-     0x74, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x74, 0x72, 0x61, 0x63, 0x65,
-     0x5f, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18,
-     0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x74, 0x72, 0x61, 0x63,
-     0x65, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12,
-     0x1f, 0x0a, 0x0b, 0x61, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x61, 0x70,
-     0x70, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x74,
-     0x72, 0x61, 0x63, 0x65, 0x41, 0x70, 0x70, 0x73, 0x12, 0x24, 0x0a, 0x0e,
-     0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f,
-     0x6b, 0x62, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x62, 0x75,
-     0x66, 0x66, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x4b, 0x62, 0x12, 0x26,
-     0x0a, 0x0f, 0x64, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x70, 0x65, 0x72, 0x69,
-     0x6f, 0x64, 0x5f, 0x6d, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52,
-     0x0d, 0x64, 0x72, 0x61, 0x69, 0x6e, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64,
-     0x4d, 0x73, 0x12, 0x55, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63,
-     0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28,
-     0x0b, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x46, 0x74, 0x72, 0x61,
-     0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6d,
-     0x70, 0x61, 0x63, 0x74, 0x53, 0x63, 0x68, 0x65, 0x64, 0x43, 0x6f, 0x6e,
-     0x66, 0x69, 0x67, 0x52, 0x0c, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74,
-     0x53, 0x63, 0x68, 0x65, 0x64, 0x1a, 0x2e, 0x0a, 0x12, 0x43, 0x6f, 0x6d,
-     0x70, 0x61, 0x63, 0x74, 0x53, 0x63, 0x68, 0x65, 0x64, 0x43, 0x6f, 0x6e,
-     0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c,
-     0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e,
-     0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x95, 0x03, 0x0a, 0x0f, 0x49, 0x6e,
-     0x6f, 0x64, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69,
-     0x67, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x63, 0x61, 0x6e, 0x5f, 0x69, 0x6e,
-     0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x73, 0x18, 0x01, 0x20,
-     0x01, 0x28, 0x0d, 0x52, 0x0e, 0x73, 0x63, 0x61, 0x6e, 0x49, 0x6e, 0x74,
-     0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x73,
-     0x63, 0x61, 0x6e, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x73,
-     0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x73, 0x63, 0x61, 0x6e,
-     0x44, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x73,
-     0x63, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x73, 0x69,
-     0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x73, 0x63,
-     0x61, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x69, 0x7a, 0x65, 0x12,
-     0x1e, 0x0a, 0x0b, 0x64, 0x6f, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x73, 0x63,
-     0x61, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x64, 0x6f,
-     0x4e, 0x6f, 0x74, 0x53, 0x63, 0x61, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x73,
-     0x63, 0x61, 0x6e, 0x5f, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x70, 0x6f,
-     0x69, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f,
-     0x73, 0x63, 0x61, 0x6e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x6f, 0x69,
-     0x6e, 0x74, 0x73, 0x12, 0x67, 0x0a, 0x13, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
-     0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69,
-     0x6e, 0x67, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x6c, 0x65,
-     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74,
-     0x50, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67,
-     0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
-     0x50, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67,
-     0x1a, 0x57, 0x0a, 0x16, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x6f, 0x69,
-     0x6e, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x74,
-     0x72, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x70,
-     0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
-     0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1d,
-     0x0a, 0x0a, 0x73, 0x63, 0x61, 0x6e, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x73,
-     0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x73, 0x63, 0x61, 0x6e,
-     0x52, 0x6f, 0x6f, 0x74, 0x73, 0x22, 0x81, 0x03, 0x0a, 0x12, 0x41, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x43, 0x6f,
-     0x6e, 0x66, 0x69, 0x67, 0x12, 0x26, 0x0a, 0x0f, 0x62, 0x61, 0x74, 0x74,
-     0x65, 0x72, 0x79, 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x5f, 0x6d, 0x73, 0x18,
-     0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x62, 0x61, 0x74, 0x74, 0x65,
-     0x72, 0x79, 0x50, 0x6f, 0x6c, 0x6c, 0x4d, 0x73, 0x12, 0x5e, 0x0a, 0x10,
-     0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
-     0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x33,
-     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x50, 0x6f, 0x77, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
-     0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74,
-     0x65, 0x72, 0x73, 0x52, 0x0f, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79,
-     0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x13,
-     0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x5f, 0x70, 0x6f, 0x77, 0x65,
-     0x72, 0x5f, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
-     0x08, 0x52, 0x11, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x50, 0x6f,
-     0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x22, 0xb2, 0x01, 0x0a,
-     0x0f, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e,
-     0x74, 0x65, 0x72, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x42, 0x41, 0x54, 0x54,
-     0x45, 0x52, 0x59, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, 0x5f,
-     0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
-     0x00, 0x12, 0x1a, 0x0a, 0x16, 0x42, 0x41, 0x54, 0x54, 0x45, 0x52, 0x59,
-     0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, 0x5f, 0x43, 0x48, 0x41,
-     0x52, 0x47, 0x45, 0x10, 0x01, 0x12, 0x24, 0x0a, 0x20, 0x42, 0x41, 0x54,
-     0x54, 0x45, 0x52, 0x59, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52,
-     0x5f, 0x43, 0x41, 0x50, 0x41, 0x43, 0x49, 0x54, 0x59, 0x5f, 0x50, 0x45,
-     0x52, 0x43, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x42,
+     0x69, 0x67, 0x12, 0x4c, 0x0a, 0x11, 0x69, 0x6e, 0x6f, 0x64, 0x65, 0x5f,
+     0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18,
+     0x66, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x65, 0x72, 0x66,
+     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+     0x49, 0x6e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e,
+     0x66, 0x69, 0x67, 0x52, 0x0f, 0x69, 0x6e, 0x6f, 0x64, 0x65, 0x46, 0x69,
+     0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x55, 0x0a, 0x14,
+     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x74, 0x61, 0x74,
+     0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x67, 0x20, 0x01,
+     0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x50, 0x72, 0x6f,
+     0x63, 0x65, 0x73, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6e,
+     0x66, 0x69, 0x67, 0x52, 0x12, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+     0x53, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
+     0x49, 0x0a, 0x10, 0x73, 0x79, 0x73, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73,
+     0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x68, 0x20, 0x01, 0x28,
+     0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x53, 0x79, 0x73, 0x53,
+     0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e,
+     0x73, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66,
+     0x69, 0x67, 0x12, 0x4b, 0x0a, 0x10, 0x68, 0x65, 0x61, 0x70, 0x70, 0x72,
+     0x6f, 0x66, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x69,
+     0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48,
+     0x65, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x66, 0x64, 0x43, 0x6f, 0x6e, 0x66,
+     0x69, 0x67, 0x52, 0x0f, 0x68, 0x65, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x66,
+     0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x55, 0x0a, 0x14, 0x61,
+     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x70, 0x6f, 0x77, 0x65, 0x72,
+     0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x6a, 0x20, 0x01, 0x28,
+     0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
+     0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66,
+     0x69, 0x67, 0x52, 0x12, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50,
+     0x6f, 0x77, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f,
+     0x0a, 0x12, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6c, 0x6f,
+     0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x6b, 0x20, 0x01,
+     0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
+     0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6f, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+     0x67, 0x52, 0x10, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6f,
+     0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x55, 0x0a, 0x14, 0x70,
+     0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74,
+     0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x6d, 0x20, 0x01, 0x28,
+     0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x50, 0x61, 0x63, 0x6b,
+     0x61, 0x67, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66,
+     0x69, 0x67, 0x52, 0x12, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73,
+     0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x24,
+     0x0a, 0x0d, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x63, 0x6f, 0x6e,
+     0x66, 0x69, 0x67, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c,
+     0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+     0x12, 0x3f, 0x0a, 0x0b, 0x66, 0x6f, 0x72, 0x5f, 0x74, 0x65, 0x73, 0x74,
+     0x69, 0x6e, 0x67, 0x18, 0xff, 0xff, 0xff, 0x7f, 0x20, 0x01, 0x28, 0x0b,
+     0x32, 0x1b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43,
+     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x66, 0x6f, 0x72, 0x54, 0x65,
+     0x73, 0x74, 0x69, 0x6e, 0x67, 0x22, 0xcf, 0x01, 0x0a, 0x0c, 0x46, 0x74,
+     0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x23,
+     0x0a, 0x0d, 0x66, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x65, 0x76, 0x65,
+     0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x66,
+     0x74, 0x72, 0x61, 0x63, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12,
+     0x2b, 0x0a, 0x11, 0x61, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x63, 0x61,
+     0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03,
+     0x28, 0x09, 0x52, 0x10, 0x61, 0x74, 0x72, 0x61, 0x63, 0x65, 0x43, 0x61,
+     0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b,
+     0x61, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x61, 0x70, 0x70, 0x73, 0x18,
+     0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x74, 0x72, 0x61, 0x63,
+     0x65, 0x41, 0x70, 0x70, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x75, 0x66,
+     0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6b, 0x62, 0x18,
+     0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x62, 0x75, 0x66, 0x66, 0x65,
+     0x72, 0x53, 0x69, 0x7a, 0x65, 0x4b, 0x62, 0x12, 0x26, 0x0a, 0x0f, 0x64,
+     0x72, 0x61, 0x69, 0x6e, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f,
+     0x6d, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x64, 0x72,
+     0x61, 0x69, 0x6e, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4d, 0x73, 0x22,
+     0x95, 0x03, 0x0a, 0x0f, 0x49, 0x6e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x6c,
+     0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x28, 0x0a, 0x10, 0x73,
+     0x63, 0x61, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,
+     0x5f, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x73,
+     0x63, 0x61, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d,
+     0x73, 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x63, 0x61, 0x6e, 0x5f, 0x64, 0x65,
+     0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d,
+     0x52, 0x0b, 0x73, 0x63, 0x61, 0x6e, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x4d,
+     0x73, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x63, 0x61, 0x6e, 0x5f, 0x62, 0x61,
+     0x74, 0x63, 0x68, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01,
+     0x28, 0x0d, 0x52, 0x0d, 0x73, 0x63, 0x61, 0x6e, 0x42, 0x61, 0x74, 0x63,
+     0x68, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x64, 0x6f, 0x5f,
+     0x6e, 0x6f, 0x74, 0x5f, 0x73, 0x63, 0x61, 0x6e, 0x18, 0x04, 0x20, 0x01,
+     0x28, 0x08, 0x52, 0x09, 0x64, 0x6f, 0x4e, 0x6f, 0x74, 0x53, 0x63, 0x61,
+     0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x63, 0x61, 0x6e, 0x5f, 0x6d, 0x6f,
+     0x75, 0x6e, 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x05,
+     0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x63, 0x61, 0x6e, 0x4d, 0x6f,
+     0x75, 0x6e, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x67, 0x0a,
+     0x13, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74,
+     0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x03,
+     0x28, 0x0b, 0x32, 0x37, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x6f,
+     0x64, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+     0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x4d,
+     0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
+     0x11, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x4d,
+     0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x1a, 0x57, 0x0a, 0x16, 0x4d, 0x6f,
+     0x75, 0x6e, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x70, 0x70,
+     0x69, 0x6e, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x1e, 0x0a, 0x0a,
+     0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01,
+     0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x70,
+     0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x63, 0x61, 0x6e,
+     0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09,
+     0x52, 0x09, 0x73, 0x63, 0x61, 0x6e, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x22,
+     0x81, 0x03, 0x0a, 0x12, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50,
+     0x6f, 0x77, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x26,
+     0x0a, 0x0f, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x5f, 0x70, 0x6f,
+     0x6c, 0x6c, 0x5f, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52,
+     0x0d, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x6c,
+     0x4d, 0x73, 0x12, 0x5e, 0x0a, 0x10, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72,
+     0x79, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02,
+     0x20, 0x03, 0x28, 0x0e, 0x32, 0x33, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
+     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x43,
+     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72,
+     0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0f, 0x62,
+     0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65,
+     0x72, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63,
+     0x74, 0x5f, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x72, 0x61, 0x69, 0x6c,
+     0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x63, 0x6f, 0x6c,
+     0x6c, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69,
+     0x6c, 0x73, 0x22, 0xb2, 0x01, 0x0a, 0x0f, 0x42, 0x61, 0x74, 0x74, 0x65,
+     0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1f,
+     0x0a, 0x1b, 0x42, 0x41, 0x54, 0x54, 0x45, 0x52, 0x59, 0x5f, 0x43, 0x4f,
+     0x55, 0x4e, 0x54, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43,
+     0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x42,
      0x41, 0x54, 0x54, 0x45, 0x52, 0x59, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54,
-     0x45, 0x52, 0x5f, 0x43, 0x55, 0x52, 0x52, 0x45, 0x4e, 0x54, 0x10, 0x03,
-     0x12, 0x1f, 0x0a, 0x1b, 0x42, 0x41, 0x54, 0x54, 0x45, 0x52, 0x59, 0x5f,
-     0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, 0x5f, 0x43, 0x55, 0x52, 0x52,
-     0x45, 0x4e, 0x54, 0x5f, 0x41, 0x56, 0x47, 0x10, 0x04, 0x22, 0x80, 0x03,
-     0x0a, 0x12, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x53, 0x74, 0x61,
-     0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, 0x06,
-     0x71, 0x75, 0x69, 0x72, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0e,
-     0x32, 0x2a, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65,
-     0x73, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69,
-     0x67, 0x2e, 0x51, 0x75, 0x69, 0x72, 0x6b, 0x73, 0x52, 0x06, 0x71, 0x75,
-     0x69, 0x72, 0x6b, 0x73, 0x12, 0x3c, 0x0a, 0x1b, 0x73, 0x63, 0x61, 0x6e,
-     0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
-     0x65, 0x73, 0x5f, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18,
-     0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x73, 0x63, 0x61, 0x6e, 0x41,
-     0x6c, 0x6c, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x4f,
-     0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65,
-     0x63, 0x6f, 0x72, 0x64, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f,
-     0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52,
-     0x11, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x68, 0x72, 0x65, 0x61,
-     0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x12, 0x70, 0x72,
-     0x6f, 0x63, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x70, 0x6f, 0x6c,
-     0x6c, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f,
-     0x70, 0x72, 0x6f, 0x63, 0x53, 0x74, 0x61, 0x74, 0x73, 0x50, 0x6f, 0x6c,
-     0x6c, 0x4d, 0x73, 0x12, 0x34, 0x0a, 0x17, 0x70, 0x72, 0x6f, 0x63, 0x5f,
-     0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f,
-     0x74, 0x74, 0x6c, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d,
-     0x52, 0x13, 0x70, 0x72, 0x6f, 0x63, 0x53, 0x74, 0x61, 0x74, 0x73, 0x43,
-     0x61, 0x63, 0x68, 0x65, 0x54, 0x74, 0x6c, 0x4d, 0x73, 0x22, 0x55, 0x0a,
-     0x06, 0x51, 0x75, 0x69, 0x72, 0x6b, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x51,
-     0x55, 0x49, 0x52, 0x4b, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43,
-     0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x14, 0x44,
-     0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x49, 0x4e, 0x49, 0x54, 0x49,
-     0x41, 0x4c, 0x5f, 0x44, 0x55, 0x4d, 0x50, 0x10, 0x01, 0x1a, 0x02, 0x08,
-     0x01, 0x12, 0x15, 0x0a, 0x11, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45,
-     0x5f, 0x4f, 0x4e, 0x5f, 0x44, 0x45, 0x4d, 0x41, 0x4e, 0x44, 0x10, 0x02,
-     0x22, 0xf3, 0x03, 0x0a, 0x0e, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74,
-     0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2a, 0x0a, 0x11, 0x6d,
-     0x65, 0x6d, 0x69, 0x6e, 0x66, 0x6f, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f,
-     0x64, 0x5f, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f,
-     0x6d, 0x65, 0x6d, 0x69, 0x6e, 0x66, 0x6f, 0x50, 0x65, 0x72, 0x69, 0x6f,
-     0x64, 0x4d, 0x73, 0x12, 0x4b, 0x0a, 0x10, 0x6d, 0x65, 0x6d, 0x69, 0x6e,
-     0x66, 0x6f, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18,
-     0x02, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
-     0x4d, 0x65, 0x6d, 0x69, 0x6e, 0x66, 0x6f, 0x43, 0x6f, 0x75, 0x6e, 0x74,
-     0x65, 0x72, 0x73, 0x52, 0x0f, 0x6d, 0x65, 0x6d, 0x69, 0x6e, 0x66, 0x6f,
-     0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x28, 0x0a, 0x10,
-     0x76, 0x6d, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f,
-     0x64, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e,
-     0x76, 0x6d, 0x73, 0x74, 0x61, 0x74, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64,
-     0x4d, 0x73, 0x12, 0x48, 0x0a, 0x0f, 0x76, 0x6d, 0x73, 0x74, 0x61, 0x74,
-     0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20,
-     0x03, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x56, 0x6d,
-     0x73, 0x74, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73,
-     0x52, 0x0e, 0x76, 0x6d, 0x73, 0x74, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e,
-     0x74, 0x65, 0x72, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x74, 0x61, 0x74,
-     0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6d, 0x73, 0x18, 0x05,
-     0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x50, 0x65,
-     0x72, 0x69, 0x6f, 0x64, 0x4d, 0x73, 0x12, 0x51, 0x0a, 0x0d, 0x73, 0x74,
-     0x61, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18,
-     0x06, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
-     0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66,
-     0x69, 0x67, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74,
-     0x65, 0x72, 0x73, 0x52, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x43, 0x6f, 0x75,
-     0x6e, 0x74, 0x65, 0x72, 0x73, 0x22, 0x7b, 0x0a, 0x0c, 0x53, 0x74, 0x61,
-     0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x14, 0x0a,
-     0x10, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43,
-     0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x53,
-     0x54, 0x41, 0x54, 0x5f, 0x43, 0x50, 0x55, 0x5f, 0x54, 0x49, 0x4d, 0x45,
-     0x53, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x54, 0x41, 0x54, 0x5f,
-     0x49, 0x52, 0x51, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x53, 0x10, 0x02,
-     0x12, 0x17, 0x0a, 0x13, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x53, 0x4f, 0x46,
-     0x54, 0x49, 0x52, 0x51, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x53, 0x10,
-     0x03, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x46, 0x4f,
-     0x52, 0x4b, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x04, 0x22, 0x9e,
-     0x06, 0x0a, 0x0a, 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69,
-     0x67, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
-     0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
-     0x52, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x75,
-     0x6e, 0x74, 0x12, 0x35, 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x6d, 0x65,
-     0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x73,
-     0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52,
-     0x14, 0x6d, 0x61, 0x78, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73,
-     0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x12, 0x0a,
-     0x04, 0x73, 0x65, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52,
-     0x04, 0x73, 0x65, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x65, 0x73,
-     0x73, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20,
-     0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
-     0x53, 0x69, 0x7a, 0x65, 0x12, 0x33, 0x0a, 0x16, 0x73, 0x65, 0x6e, 0x64,
-     0x5f, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6f, 0x6e, 0x5f, 0x72, 0x65,
-     0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08,
-     0x52, 0x13, 0x73, 0x65, 0x6e, 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f,
-     0x6e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x4a, 0x0a,
-     0x0c, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64,
-     0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-     0x2e, 0x44, 0x75, 0x6d, 0x6d, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73,
-     0x52, 0x0b, 0x64, 0x75, 0x6d, 0x6d, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64,
-     0x73, 0x1a, 0xfb, 0x03, 0x0a, 0x0b, 0x44, 0x75, 0x6d, 0x6d, 0x79, 0x46,
-     0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x69, 0x65,
-     0x6c, 0x64, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x01, 0x20,
-     0x01, 0x28, 0x0d, 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x55, 0x69,
-     0x6e, 0x74, 0x33, 0x32, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x65, 0x6c,
-     0x64, 0x5f, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28,
-     0x05, 0x52, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x49, 0x6e, 0x74, 0x33,
-     0x32, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x75,
-     0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52,
-     0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34,
-     0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x69, 0x6e,
-     0x74, 0x36, 0x34, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x66,
-     0x69, 0x65, 0x6c, 0x64, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x23, 0x0a,
-     0x0d, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64,
-     0x36, 0x34, 0x18, 0x05, 0x20, 0x01, 0x28, 0x06, 0x52, 0x0c, 0x66, 0x69,
-     0x65, 0x6c, 0x64, 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x12, 0x25,
-     0x0a, 0x0e, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x73, 0x66, 0x69, 0x78,
-     0x65, 0x64, 0x36, 0x34, 0x18, 0x06, 0x20, 0x01, 0x28, 0x10, 0x52, 0x0d,
-     0x66, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36,
-     0x34, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x66,
-     0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x18, 0x07, 0x20, 0x01, 0x28, 0x07,
-     0x52, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x46, 0x69, 0x78, 0x65, 0x64,
-     0x33, 0x32, 0x12, 0x25, 0x0a, 0x0e, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f,
-     0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x18, 0x08, 0x20, 0x01,
-     0x28, 0x0f, 0x52, 0x0d, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x66, 0x69,
-     0x78, 0x65, 0x64, 0x33, 0x32, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x69, 0x65,
-     0x6c, 0x64, 0x5f, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x18, 0x09, 0x20,
-     0x01, 0x28, 0x01, 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x6f,
-     0x75, 0x62, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x65, 0x6c,
-     0x64, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28,
-     0x02, 0x52, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x46, 0x6c, 0x6f, 0x61,
-     0x74, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x73,
-     0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x12, 0x52,
-     0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x69, 0x6e, 0x74, 0x36, 0x34,
-     0x12, 0x21, 0x0a, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x73, 0x69,
-     0x6e, 0x74, 0x33, 0x32, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x11, 0x52, 0x0b,
-     0x66, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x12,
-     0x21, 0x0a, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x73, 0x74, 0x72,
-     0x69, 0x6e, 0x67, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66,
-     0x69, 0x65, 0x6c, 0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x1f,
-     0x0a, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65,
-     0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x66, 0x69, 0x65,
-     0x6c, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0xd1, 0x1a, 0x0a, 0x0b,
-     0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
-     0x43, 0x0a, 0x07, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x73, 0x18, 0x01,
-     0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54,
-     0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x42,
-     0x75, 0x66, 0x66, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
-     0x07, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x73, 0x12, 0x4a, 0x0a, 0x0c,
-     0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
-     0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x65, 0x72,
+     0x45, 0x52, 0x5f, 0x43, 0x48, 0x41, 0x52, 0x47, 0x45, 0x10, 0x01, 0x12,
+     0x24, 0x0a, 0x20, 0x42, 0x41, 0x54, 0x54, 0x45, 0x52, 0x59, 0x5f, 0x43,
+     0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, 0x5f, 0x43, 0x41, 0x50, 0x41, 0x43,
+     0x49, 0x54, 0x59, 0x5f, 0x50, 0x45, 0x52, 0x43, 0x45, 0x4e, 0x54, 0x10,
+     0x02, 0x12, 0x1b, 0x0a, 0x17, 0x42, 0x41, 0x54, 0x54, 0x45, 0x52, 0x59,
+     0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, 0x5f, 0x43, 0x55, 0x52,
+     0x52, 0x45, 0x4e, 0x54, 0x10, 0x03, 0x12, 0x1f, 0x0a, 0x1b, 0x42, 0x41,
+     0x54, 0x54, 0x45, 0x52, 0x59, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45,
+     0x52, 0x5f, 0x43, 0x55, 0x52, 0x52, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x56,
+     0x47, 0x10, 0x04, 0x22, 0x80, 0x03, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x63,
+     0x65, 0x73, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66,
+     0x69, 0x67, 0x12, 0x42, 0x0a, 0x06, 0x71, 0x75, 0x69, 0x72, 0x6b, 0x73,
+     0x18, 0x01, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x70, 0x65, 0x72,
      0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-     0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52,
-     0x0b, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
-     0x12, 0x60, 0x0a, 0x14, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x5f,
-     0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
-     0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-     0x2e, 0x42, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61,
-     0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x12, 0x62, 0x75, 0x69, 0x6c,
-     0x74, 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63,
-     0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69,
-     0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52,
-     0x0a, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12,
-     0x36, 0x0a, 0x17, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x65, 0x78,
-     0x74, 0x72, 0x61, 0x5f, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69,
-     0x6c, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x65, 0x6e,
-     0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x74, 0x72, 0x61, 0x47, 0x75, 0x61,
-     0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x57, 0x0a, 0x0d, 0x6c,
-     0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x5f, 0x6d, 0x6f, 0x64, 0x65,
-     0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-     0x2e, 0x4c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x4d, 0x6f, 0x64,
-     0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c,
-     0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x4d, 0x6f, 0x64, 0x65,
-     0x12, 0x49, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72,
-     0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65,
+     0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x53, 0x74, 0x61, 0x74,
+     0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x51, 0x75, 0x69, 0x72,
+     0x6b, 0x73, 0x52, 0x06, 0x71, 0x75, 0x69, 0x72, 0x6b, 0x73, 0x12, 0x3c,
+     0x0a, 0x1b, 0x73, 0x63, 0x61, 0x6e, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x70,
+     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x6f, 0x6e, 0x5f,
+     0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52,
+     0x17, 0x73, 0x63, 0x61, 0x6e, 0x41, 0x6c, 0x6c, 0x50, 0x72, 0x6f, 0x63,
+     0x65, 0x73, 0x73, 0x65, 0x73, 0x4f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74,
+     0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x5f, 0x74,
+     0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18,
+     0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x72, 0x65, 0x63, 0x6f, 0x72,
+     0x64, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73,
+     0x12, 0x2b, 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x63, 0x5f, 0x73, 0x74, 0x61,
+     0x74, 0x73, 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x5f, 0x6d, 0x73, 0x18, 0x04,
+     0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x63, 0x53, 0x74,
+     0x61, 0x74, 0x73, 0x50, 0x6f, 0x6c, 0x6c, 0x4d, 0x73, 0x12, 0x34, 0x0a,
+     0x17, 0x70, 0x72, 0x6f, 0x63, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f,
+     0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x74, 0x74, 0x6c, 0x5f, 0x6d, 0x73,
+     0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x13, 0x70, 0x72, 0x6f, 0x63,
+     0x53, 0x74, 0x61, 0x74, 0x73, 0x43, 0x61, 0x63, 0x68, 0x65, 0x54, 0x74,
+     0x6c, 0x4d, 0x73, 0x22, 0x55, 0x0a, 0x06, 0x51, 0x75, 0x69, 0x72, 0x6b,
+     0x73, 0x12, 0x16, 0x0a, 0x12, 0x51, 0x55, 0x49, 0x52, 0x4b, 0x53, 0x5f,
+     0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
+     0x00, 0x12, 0x1c, 0x0a, 0x14, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45,
+     0x5f, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x5f, 0x44, 0x55, 0x4d,
+     0x50, 0x10, 0x01, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x44,
+     0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x4f, 0x4e, 0x5f, 0x44, 0x45,
+     0x4d, 0x41, 0x4e, 0x44, 0x10, 0x02, 0x22, 0xf3, 0x03, 0x0a, 0x0e, 0x53,
+     0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+     0x67, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x65, 0x6d, 0x69, 0x6e, 0x66, 0x6f,
+     0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6d, 0x73, 0x18, 0x01,
+     0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x6d, 0x65, 0x6d, 0x69, 0x6e, 0x66,
+     0x6f, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4d, 0x73, 0x12, 0x4b, 0x0a,
+     0x10, 0x6d, 0x65, 0x6d, 0x69, 0x6e, 0x66, 0x6f, 0x5f, 0x63, 0x6f, 0x75,
+     0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32,
+     0x20, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4d, 0x65, 0x6d, 0x69, 0x6e, 0x66,
+     0x6f, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0f, 0x6d,
+     0x65, 0x6d, 0x69, 0x6e, 0x66, 0x6f, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65,
+     0x72, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x76, 0x6d, 0x73, 0x74, 0x61, 0x74,
+     0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6d, 0x73, 0x18, 0x03,
+     0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x76, 0x6d, 0x73, 0x74, 0x61, 0x74,
+     0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4d, 0x73, 0x12, 0x48, 0x0a, 0x0f,
+     0x76, 0x6d, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
+     0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x1f, 0x2e,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2e, 0x56, 0x6d, 0x73, 0x74, 0x61, 0x74, 0x43, 0x6f,
+     0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0e, 0x76, 0x6d, 0x73, 0x74,
+     0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x24,
+     0x0a, 0x0e, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f,
+     0x64, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c,
+     0x73, 0x74, 0x61, 0x74, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4d, 0x73,
+     0x12, 0x51, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x75,
+     0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0e, 0x32,
+     0x2c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61,
+     0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x53, 0x74, 0x61,
+     0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0c, 0x73,
+     0x74, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x22,
+     0x7b, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74,
+     0x65, 0x72, 0x73, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x41, 0x54, 0x5f,
+     0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
+     0x00, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x50,
+     0x55, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x53, 0x10, 0x01, 0x12, 0x13, 0x0a,
+     0x0f, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x49, 0x52, 0x51, 0x5f, 0x43, 0x4f,
+     0x55, 0x4e, 0x54, 0x53, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x54,
+     0x41, 0x54, 0x5f, 0x53, 0x4f, 0x46, 0x54, 0x49, 0x52, 0x51, 0x5f, 0x43,
+     0x4f, 0x55, 0x4e, 0x54, 0x53, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x46, 0x4f, 0x52, 0x4b, 0x5f, 0x43, 0x4f, 0x55,
+     0x4e, 0x54, 0x10, 0x04, 0x22, 0x9e, 0x06, 0x0a, 0x0a, 0x54, 0x65, 0x73,
+     0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x23, 0x0a, 0x0d, 0x6d,
+     0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
+     0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6d, 0x65, 0x73, 0x73,
+     0x61, 0x67, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x35, 0x0a, 0x17,
+     0x6d, 0x61, 0x78, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73,
+     0x5f, 0x70, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18,
+     0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, 0x6d, 0x61, 0x78, 0x4d, 0x65,
+     0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63,
+     0x6f, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, 0x65, 0x64, 0x18,
+     0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x65, 0x65, 0x64, 0x12,
+     0x21, 0x0a, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x73,
+     0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6d,
+     0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x33,
+     0x0a, 0x16, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x62, 0x61, 0x74, 0x63, 0x68,
+     0x5f, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
+     0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x73, 0x65, 0x6e, 0x64,
+     0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x6e, 0x52, 0x65, 0x67, 0x69, 0x73,
+     0x74, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x0c, 0x64, 0x75, 0x6d, 0x6d, 0x79,
+     0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28,
+     0x0b, 0x32, 0x27, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x65, 0x73, 0x74,
+     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x75, 0x6d, 0x6d, 0x79,
+     0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x52, 0x0b, 0x64, 0x75, 0x6d, 0x6d,
+     0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x1a, 0xfb, 0x03, 0x0a, 0x0b,
+     0x44, 0x75, 0x6d, 0x6d, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12,
+     0x21, 0x0a, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x75, 0x69, 0x6e,
+     0x74, 0x33, 0x32, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x66,
+     0x69, 0x65, 0x6c, 0x64, 0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x1f,
+     0x0a, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x33,
+     0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x66, 0x69, 0x65,
+     0x6c, 0x64, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x21, 0x0a, 0x0c, 0x66,
+     0x69, 0x65, 0x6c, 0x64, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18,
+     0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64,
+     0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69,
+     0x65, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x04, 0x20,
+     0x01, 0x28, 0x03, 0x52, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x49, 0x6e,
+     0x74, 0x36, 0x34, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x69, 0x65, 0x6c, 0x64,
+     0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x18, 0x05, 0x20, 0x01,
+     0x28, 0x06, 0x52, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x46, 0x69, 0x78,
+     0x65, 0x64, 0x36, 0x34, 0x12, 0x25, 0x0a, 0x0e, 0x66, 0x69, 0x65, 0x6c,
+     0x64, 0x5f, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x18, 0x06,
+     0x20, 0x01, 0x28, 0x10, 0x52, 0x0d, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x53,
+     0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x12, 0x23, 0x0a, 0x0d, 0x66,
+     0x69, 0x65, 0x6c, 0x64, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32,
+     0x18, 0x07, 0x20, 0x01, 0x28, 0x07, 0x52, 0x0c, 0x66, 0x69, 0x65, 0x6c,
+     0x64, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x12, 0x25, 0x0a, 0x0e,
+     0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64,
+     0x33, 0x32, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x0d, 0x66, 0x69,
+     0x65, 0x6c, 0x64, 0x53, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x12,
+     0x21, 0x0a, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x64, 0x6f, 0x75,
+     0x62, 0x6c, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x66,
+     0x69, 0x65, 0x6c, 0x64, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x12, 0x1f,
+     0x0a, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x66, 0x6c, 0x6f, 0x61,
+     0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0a, 0x66, 0x69, 0x65,
+     0x6c, 0x64, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x66,
+     0x69, 0x65, 0x6c, 0x64, 0x5f, 0x73, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18,
+     0x0b, 0x20, 0x01, 0x28, 0x12, 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64,
+     0x53, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x69,
+     0x65, 0x6c, 0x64, 0x5f, 0x73, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x0c,
+     0x20, 0x01, 0x28, 0x11, 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x53,
+     0x69, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x69, 0x65,
+     0x6c, 0x64, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x0d, 0x20,
+     0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x74,
+     0x72, 0x69, 0x6e, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x65, 0x6c,
+     0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28,
+     0x0c, 0x52, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x79, 0x74, 0x65,
+     0x73, 0x22, 0xf4, 0x19, 0x0a, 0x0b, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43,
+     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x43, 0x0a, 0x07, 0x62, 0x75, 0x66,
+     0x66, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29,
+     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f,
+     0x6e, 0x66, 0x69, 0x67, 0x2e, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x43,
+     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x62, 0x75, 0x66, 0x66, 0x65,
+     0x72, 0x73, 0x12, 0x4a, 0x0a, 0x0c, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73,
+     0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
+     0x32, 0x27, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65,
+     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53,
+     0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x53,
+     0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x60, 0x0a, 0x14, 0x62, 0x75,
+     0x69, 0x6c, 0x74, 0x69, 0x6e, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73,
+     0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b,
+     0x32, 0x2e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65,
+     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x74,
+     0x69, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
+     0x52, 0x12, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x44, 0x61, 0x74,
+     0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b,
+     0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18,
+     0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61, 0x74,
+     0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x65, 0x6e, 0x61,
+     0x62, 0x6c, 0x65, 0x5f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x67, 0x75,
+     0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x01,
+     0x28, 0x08, 0x52, 0x15, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78,
+     0x74, 0x72, 0x61, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c,
+     0x73, 0x12, 0x57, 0x0a, 0x0d, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77,
+     0x6e, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e,
+     0x32, 0x32, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65,
+     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x6f, 0x63, 0x6b, 0x64,
+     0x6f, 0x77, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61,
+     0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f,
+     0x77, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x49, 0x0a, 0x09, 0x70, 0x72,
+     0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28,
+     0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63,
+     0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x72, 0x6f, 0x64,
+     0x75, 0x63, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09,
+     0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x12, 0x54, 0x0a,
+     0x0f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61,
+     0x64, 0x61, 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b,
+     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f,
+     0x6e, 0x66, 0x69, 0x67, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x64, 0x4d,
+     0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0e, 0x73, 0x74, 0x61,
+     0x74, 0x73, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12,
+     0x26, 0x0a, 0x0f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x69, 0x6e, 0x74,
+     0x6f, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08,
+     0x52, 0x0d, 0x77, 0x72, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x6f, 0x46,
+     0x69, 0x6c, 0x65, 0x12, 0x2f, 0x0a, 0x14, 0x66, 0x69, 0x6c, 0x65, 0x5f,
+     0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64,
+     0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x66,
+     0x69, 0x6c, 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, 0x50, 0x65, 0x72, 0x69,
+     0x6f, 0x64, 0x4d, 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x6d, 0x61, 0x78, 0x5f,
+     0x66, 0x69, 0x6c, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79,
+     0x74, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x6d,
+     0x61, 0x78, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79,
+     0x74, 0x65, 0x73, 0x12, 0x60, 0x0a, 0x13, 0x67, 0x75, 0x61, 0x72, 0x64,
+     0x72, 0x61, 0x69, 0x6c, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
+     0x65, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70,
+     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+     0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66,
+     0x69, 0x67, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c,
+     0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x12, 0x67,
+     0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4f, 0x76, 0x65, 0x72,
+     0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65, 0x66,
+     0x65, 0x72, 0x72, 0x65, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18,
+     0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x64, 0x65, 0x66, 0x65, 0x72,
+     0x72, 0x65, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x26, 0x0a, 0x0f,
+     0x66, 0x6c, 0x75, 0x73, 0x68, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64,
+     0x5f, 0x6d, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x66,
+     0x6c, 0x75, 0x73, 0x68, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4d, 0x73,
+     0x12, 0x28, 0x0a, 0x10, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x5f, 0x74, 0x69,
+     0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0e, 0x20, 0x01,
+     0x28, 0x0d, 0x52, 0x0e, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x54, 0x69, 0x6d,
+     0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x6f,
+     0x74, 0x69, 0x66, 0x79, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x75, 0x72,
+     0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6e, 0x6f, 0x74, 0x69,
+     0x66, 0x79, 0x54, 0x72, 0x61, 0x63, 0x65, 0x75, 0x72, 0x12, 0x51, 0x0a,
+     0x0e, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e,
+     0x66, 0x69, 0x67, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e,
+     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+     0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e,
+     0x66, 0x69, 0x67, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43,
+     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x74, 0x72, 0x69, 0x67, 0x67,
+     0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2b, 0x0a, 0x11,
+     0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x72, 0x69,
+     0x67, 0x67, 0x65, 0x72, 0x73, 0x18, 0x12, 0x20, 0x03, 0x28, 0x09, 0x52,
+     0x10, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x54, 0x72, 0x69,
+     0x67, 0x67, 0x65, 0x72, 0x73, 0x12, 0x6d, 0x0a, 0x18, 0x69, 0x6e, 0x63,
+     0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x61,
+     0x74, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x15, 0x20,
+     0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72,
+     0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x49, 0x6e,
+     0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x53, 0x74, 0x61,
+     0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x16, 0x69, 0x6e,
+     0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x53, 0x74, 0x61,
+     0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x37, 0x0a, 0x18,
+     0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x62,
+     0x75, 0x69, 0x6c, 0x64, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67,
+     0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x61, 0x6c, 0x6c, 0x6f,
+     0x77, 0x55, 0x73, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x54, 0x72,
+     0x61, 0x63, 0x69, 0x6e, 0x67, 0x12, 0x2e, 0x0a, 0x13, 0x75, 0x6e, 0x69,
+     0x71, 0x75, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f,
+     0x6e, 0x61, 0x6d, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11,
+     0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f,
+     0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x57, 0x0a, 0x10, 0x63, 0x6f, 0x6d,
+     0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70,
+     0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x70, 0x65,
      0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
      0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69,
-     0x67, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x43, 0x6f,
-     0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63,
-     0x65, 0x72, 0x73, 0x12, 0x54, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x74, 0x73,
-     0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x07,
-     0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54,
-     0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x53,
-     0x74, 0x61, 0x74, 0x73, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
-     0x61, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x64, 0x4d, 0x65, 0x74,
-     0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x72, 0x69,
-     0x74, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x6f, 0x5f, 0x66, 0x69, 0x6c, 0x65,
-     0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x77, 0x72, 0x69, 0x74,
-     0x65, 0x49, 0x6e, 0x74, 0x6f, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x2f, 0x0a,
-     0x14, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f,
-     0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20,
-     0x01, 0x28, 0x0d, 0x52, 0x11, 0x66, 0x69, 0x6c, 0x65, 0x57, 0x72, 0x69,
-     0x74, 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4d, 0x73, 0x12, 0x2d,
-     0x0a, 0x13, 0x6d, 0x61, 0x78, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x73,
-     0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20,
-     0x01, 0x28, 0x04, 0x52, 0x10, 0x6d, 0x61, 0x78, 0x46, 0x69, 0x6c, 0x65,
-     0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x60, 0x0a,
-     0x13, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x5f, 0x6f,
-     0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61,
-     0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x47, 0x75, 0x61,
-     0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69,
-     0x64, 0x65, 0x73, 0x52, 0x12, 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61,
-     0x69, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12,
-     0x25, 0x0a, 0x0e, 0x64, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x5f,
-     0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52,
-     0x0d, 0x64, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x53, 0x74, 0x61,
-     0x72, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x5f,
-     0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6d, 0x73, 0x18, 0x0d, 0x20,
-     0x01, 0x28, 0x0d, 0x52, 0x0d, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x50, 0x65,
-     0x72, 0x69, 0x6f, 0x64, 0x4d, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x6c,
-     0x75, 0x73, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f,
-     0x6d, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x66, 0x6c,
-     0x75, 0x73, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73,
-     0x12, 0x3c, 0x0a, 0x1b, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x6f, 0x75,
-     0x72, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x74, 0x69, 0x6d,
-     0x65, 0x6f, 0x75, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x17, 0x20, 0x01, 0x28,
-     0x0d, 0x52, 0x17, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63,
-     0x65, 0x53, 0x74, 0x6f, 0x70, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
-     0x4d, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79,
-     0x5f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x75, 0x72, 0x18, 0x10, 0x20, 0x01,
-     0x28, 0x08, 0x52, 0x0d, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x54, 0x72,
-     0x61, 0x63, 0x65, 0x75, 0x72, 0x12, 0x51, 0x0a, 0x0e, 0x74, 0x72, 0x69,
-     0x67, 0x67, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18,
-     0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
-     0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
-     0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69,
-     0x67, 0x52, 0x0d, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43, 0x6f,
-     0x6e, 0x66, 0x69, 0x67, 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x63, 0x74, 0x69,
-     0x76, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72,
-     0x73, 0x18, 0x12, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x63, 0x74,
-     0x69, 0x76, 0x61, 0x74, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72,
-     0x73, 0x12, 0x6d, 0x0a, 0x18, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65,
-     0x6e, 0x74, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x63,
-     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32,
-     0x33, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43,
-     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x49, 0x6e, 0x63, 0x72, 0x65, 0x6d,
-     0x65, 0x6e, 0x74, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6f,
-     0x6e, 0x66, 0x69, 0x67, 0x52, 0x16, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x6d,
-     0x65, 0x6e, 0x74, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6f,
-     0x6e, 0x66, 0x69, 0x67, 0x12, 0x37, 0x0a, 0x18, 0x61, 0x6c, 0x6c, 0x6f,
-     0x77, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64,
-     0x5f, 0x74, 0x72, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x18, 0x13, 0x20, 0x01,
-     0x28, 0x08, 0x52, 0x15, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x55, 0x73, 0x65,
-     0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x54, 0x72, 0x61, 0x63, 0x69, 0x6e,
-     0x67, 0x12, 0x2e, 0x0a, 0x13, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x5f,
-     0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
-     0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x75, 0x6e, 0x69, 0x71,
-     0x75, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d,
-     0x65, 0x12, 0x57, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73,
-     0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x18, 0x20,
-     0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72,
-     0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f,
-     0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70,
-     0x65, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69,
-     0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x67, 0x0a, 0x16, 0x69, 0x6e,
-     0x63, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x72,
-     0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x19, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61,
-     0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x49, 0x6e, 0x63,
-     0x69, 0x64, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x43,
-     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x14, 0x69, 0x6e, 0x63, 0x69, 0x64,
-     0x65, 0x6e, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e,
-     0x66, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x72, 0x61, 0x63, 0x65,
-     0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0c, 0x52,
-     0x09, 0x74, 0x72, 0x61, 0x63, 0x65, 0x55, 0x75, 0x69, 0x64, 0x1a, 0xc7,
-     0x01, 0x0a, 0x0c, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x43, 0x6f, 0x6e,
-     0x66, 0x69, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x69, 0x7a, 0x65, 0x5f,
-     0x6b, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x73, 0x69,
-     0x7a, 0x65, 0x4b, 0x62, 0x12, 0x55, 0x0a, 0x0b, 0x66, 0x69, 0x6c, 0x6c,
-     0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28,
-     0x0e, 0x32, 0x34, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63,
-     0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x42, 0x75, 0x66, 0x66,
-     0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x46, 0x69, 0x6c,
-     0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0a, 0x66, 0x69, 0x6c,
-     0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x3b, 0x0a, 0x0a, 0x46,
-     0x69, 0x6c, 0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x0f, 0x0a,
-     0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44,
-     0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x42,
-     0x55, 0x46, 0x46, 0x45, 0x52, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44,
-     0x49, 0x53, 0x43, 0x41, 0x52, 0x44, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x02,
-     0x10, 0x03, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x1a, 0x79, 0x0a, 0x0a,
-     0x44, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x39,
-     0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x44, 0x61, 0x74,
-     0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69,
-     0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x0a,
-     0x14, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x6e, 0x61,
-     0x6d, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20,
-     0x03, 0x28, 0x09, 0x52, 0x12, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65,
-     0x72, 0x4e, 0x61, 0x6d, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a,
-     0xb3, 0x01, 0x0a, 0x11, 0x42, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x44,
-     0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x3c, 0x0a,
-     0x1a, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6c, 0x6f,
-     0x63, 0x6b, 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74,
-     0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x64,
-     0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x53,
-     0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12,
-     0x30, 0x0a, 0x14, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74,
-     0x72, 0x61, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18,
-     0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x64, 0x69, 0x73, 0x61, 0x62,
-     0x6c, 0x65, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69,
-     0x67, 0x12, 0x2e, 0x0a, 0x13, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
-     0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x6e, 0x66, 0x6f,
-     0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x64, 0x69, 0x73, 0x61,
-     0x62, 0x6c, 0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x49, 0x6e, 0x66,
-     0x6f, 0x1a, 0x77, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65,
-     0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x23, 0x0a, 0x0d, 0x70,
-     0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
-     0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x64,
-     0x75, 0x63, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0b,
-     0x73, 0x68, 0x6d, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6b, 0x62, 0x18,
-     0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x73, 0x68, 0x6d, 0x53, 0x69,
-     0x7a, 0x65, 0x4b, 0x62, 0x12, 0x20, 0x0a, 0x0c, 0x70, 0x61, 0x67, 0x65,
-     0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6b, 0x62, 0x18, 0x03, 0x20, 0x01,
-     0x28, 0x0d, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65,
-     0x4b, 0x62, 0x1a, 0xe4, 0x01, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x73,
-     0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a,
-     0x13, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f,
-     0x61, 0x6c, 0x65, 0x72, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x11, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69,
-     0x6e, 0x67, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x49, 0x64, 0x12, 0x32, 0x0a,
-     0x15, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f,
-     0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x75, 0x69, 0x64, 0x18, 0x02,
-     0x20, 0x01, 0x28, 0x05, 0x52, 0x13, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65,
-     0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x55, 0x69,
-     0x64, 0x12, 0x30, 0x0a, 0x14, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72,
-     0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x69,
-     0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x74, 0x72, 0x69,
-     0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69,
-     0x67, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x1a, 0x74, 0x72, 0x69, 0x67, 0x67,
-     0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72,
-     0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20,
-     0x01, 0x28, 0x03, 0x52, 0x18, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72,
-     0x69, 0x6e, 0x67, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
-     0x69, 0x6f, 0x6e, 0x49, 0x64, 0x1a, 0x4c, 0x0a, 0x12, 0x47, 0x75, 0x61,
-     0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69,
-     0x64, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x18, 0x6d, 0x61, 0x78, 0x5f, 0x75,
-     0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x64, 0x61,
-     0x79, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
-     0x04, 0x52, 0x14, 0x6d, 0x61, 0x78, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64,
-     0x50, 0x65, 0x72, 0x44, 0x61, 0x79, 0x42, 0x79, 0x74, 0x65, 0x73, 0x1a,
-     0xa0, 0x03, 0x0a, 0x0d, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43,
-     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x59, 0x0a, 0x0c, 0x74, 0x72, 0x69,
-     0x67, 0x67, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20,
-     0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+     0x67, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f,
+     0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x72,
+     0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x67,
+     0x0a, 0x16, 0x69, 0x6e, 0x63, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x5f, 0x72,
+     0x65, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+     0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x65, 0x72,
+     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+     0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+     0x2e, 0x49, 0x6e, 0x63, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x70,
+     0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x14, 0x69,
+     0x6e, 0x63, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72,
+     0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0xc7, 0x01, 0x0a, 0x0c,
+     0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+     0x12, 0x17, 0x0a, 0x07, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6b, 0x62, 0x18,
+     0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x73, 0x69, 0x7a, 0x65, 0x4b,
+     0x62, 0x12, 0x55, 0x0a, 0x0b, 0x66, 0x69, 0x6c, 0x6c, 0x5f, 0x70, 0x6f,
+     0x6c, 0x69, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x34,
+     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f,
+     0x6e, 0x66, 0x69, 0x67, 0x2e, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x43,
+     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x46, 0x69, 0x6c, 0x6c, 0x50, 0x6f,
+     0x6c, 0x69, 0x63, 0x79, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x6c, 0x50, 0x6f,
+     0x6c, 0x69, 0x63, 0x79, 0x22, 0x3b, 0x0a, 0x0a, 0x46, 0x69, 0x6c, 0x6c,
+     0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e,
+     0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12,
+     0x0f, 0x0a, 0x0b, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x42, 0x55, 0x46, 0x46,
+     0x45, 0x52, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x49, 0x53, 0x43,
+     0x41, 0x52, 0x44, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a,
+     0x04, 0x08, 0x03, 0x10, 0x04, 0x1a, 0x79, 0x0a, 0x0a, 0x44, 0x61, 0x74,
+     0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x63,
+     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+     0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x6f,
+     0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06,
+     0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x0a, 0x14, 0x70, 0x72,
+     0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f,
+     0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09,
+     0x52, 0x12, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x4e, 0x61,
+     0x6d, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0xb3, 0x01, 0x0a,
+     0x11, 0x42, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61,
+     0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x3c, 0x0a, 0x1a, 0x64, 0x69,
+     0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x5f,
+     0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x74, 0x69, 0x6e, 0x67,
+     0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x64, 0x69, 0x73, 0x61,
+     0x62, 0x6c, 0x65, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6e, 0x61, 0x70,
+     0x73, 0x68, 0x6f, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x14,
+     0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x63,
+     0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01,
+     0x28, 0x08, 0x52, 0x12, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x54,
+     0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e,
+     0x0a, 0x13, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x79,
+     0x73, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20,
+     0x01, 0x28, 0x08, 0x52, 0x11, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
+     0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x77,
+     0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x43, 0x6f,
+     0x6e, 0x66, 0x69, 0x67, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x64,
+     0x75, 0x63, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
+     0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65,
+     0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x73, 0x68, 0x6d,
+     0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6b, 0x62, 0x18, 0x02, 0x20, 0x01,
+     0x28, 0x0d, 0x52, 0x09, 0x73, 0x68, 0x6d, 0x53, 0x69, 0x7a, 0x65, 0x4b,
+     0x62, 0x12, 0x20, 0x0a, 0x0c, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69,
+     0x7a, 0x65, 0x5f, 0x6b, 0x62, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52,
+     0x0a, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x4b, 0x62, 0x1a,
+     0xe4, 0x01, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x64, 0x4d, 0x65,
+     0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x13, 0x74, 0x72,
+     0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6c, 0x65,
+     0x72, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
+     0x11, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x41,
+     0x6c, 0x65, 0x72, 0x74, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x74, 0x72,
+     0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e,
+     0x66, 0x69, 0x67, 0x5f, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
+     0x05, 0x52, 0x13, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e,
+     0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x55, 0x69, 0x64, 0x12, 0x30,
+     0x0a, 0x14, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67,
+     0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x03,
+     0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65,
+     0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x49, 0x64,
+     0x12, 0x3c, 0x0a, 0x1a, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69,
+     0x6e, 0x67, 0x5f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+     0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
+     0x52, 0x18, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67,
+     0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+     0x49, 0x64, 0x1a, 0x4c, 0x0a, 0x12, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72,
+     0x61, 0x69, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73,
+     0x12, 0x36, 0x0a, 0x18, 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x70, 0x6c, 0x6f,
+     0x61, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x79, 0x5f, 0x62,
+     0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x14,
+     0x6d, 0x61, 0x78, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x65, 0x72,
+     0x44, 0x61, 0x79, 0x42, 0x79, 0x74, 0x65, 0x73, 0x1a, 0xa0, 0x03, 0x0a,
+     0x0d, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66,
+     0x69, 0x67, 0x12, 0x59, 0x0a, 0x0c, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65,
+     0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e,
+     0x32, 0x36, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65,
+     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67,
+     0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x54, 0x72, 0x69,
+     0x67, 0x67, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0b, 0x74, 0x72,
+     0x69, 0x67, 0x67, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x4e, 0x0a,
+     0x08, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20,
+     0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
      0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72,
      0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x54, 0x72,
      0x69, 0x67, 0x67, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
-     0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x52,
-     0x0b, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65,
-     0x12, 0x4e, 0x0a, 0x08, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x73,
-     0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-     0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66,
-     0x69, 0x67, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x08,
-     0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x73, 0x12, 0x2c, 0x0a, 0x12,
-     0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65,
-     0x6f, 0x75, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d,
-     0x52, 0x10, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x54, 0x69, 0x6d,
-     0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x1a, 0x71, 0x0a, 0x07, 0x54, 0x72,
-     0x69, 0x67, 0x67, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
-     0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
-     0x65, 0x12, 0x2e, 0x0a, 0x13, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65,
-     0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78,
-     0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x64,
-     0x75, 0x63, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x67, 0x65,
-     0x78, 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x64, 0x65,
-     0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d,
-     0x52, 0x0b, 0x73, 0x74, 0x6f, 0x70, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x4d,
-     0x73, 0x22, 0x43, 0x0a, 0x0b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72,
-     0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50,
-     0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a,
-     0x0d, 0x53, 0x54, 0x41, 0x52, 0x54, 0x5f, 0x54, 0x52, 0x41, 0x43, 0x49,
-     0x4e, 0x47, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x4f, 0x50,
-     0x5f, 0x54, 0x52, 0x41, 0x43, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x1a, 0x40,
-     0x0a, 0x16, 0x49, 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61,
-     0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-     0x12, 0x26, 0x0a, 0x0f, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x5f, 0x70, 0x65,
-     0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
-     0x0d, 0x52, 0x0d, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x50, 0x65, 0x72, 0x69,
-     0x6f, 0x64, 0x4d, 0x73, 0x1a, 0xbc, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x63,
-     0x69, 0x64, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x43,
-     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2f, 0x0a, 0x13, 0x64, 0x65, 0x73,
-     0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x63,
-     0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12,
-     0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50,
-     0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x64, 0x65,
-     0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6c,
-     0x61, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x64,
-     0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c,
-     0x61, 0x73, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x76, 0x61,
-     0x63, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01,
-     0x28, 0x05, 0x52, 0x0c, 0x70, 0x72, 0x69, 0x76, 0x61, 0x63, 0x79, 0x4c,
-     0x65, 0x76, 0x65, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x6b, 0x69, 0x70,
-     0x5f, 0x64, 0x72, 0x6f, 0x70, 0x62, 0x6f, 0x78, 0x18, 0x04, 0x20, 0x01,
-     0x28, 0x08, 0x52, 0x0b, 0x73, 0x6b, 0x69, 0x70, 0x44, 0x72, 0x6f, 0x70,
-     0x62, 0x6f, 0x78, 0x22, 0x55, 0x0a, 0x15, 0x4c, 0x6f, 0x63, 0x6b, 0x64,
-     0x6f, 0x77, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61,
-     0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x4f, 0x43, 0x4b,
-     0x44, 0x4f, 0x57, 0x4e, 0x5f, 0x55, 0x4e, 0x43, 0x48, 0x41, 0x4e, 0x47,
-     0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x4f, 0x43, 0x4b,
-     0x44, 0x4f, 0x57, 0x4e, 0x5f, 0x43, 0x4c, 0x45, 0x41, 0x52, 0x10, 0x01,
-     0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x4f, 0x43, 0x4b, 0x44, 0x4f, 0x57, 0x4e,
-     0x5f, 0x53, 0x45, 0x54, 0x10, 0x02, 0x22, 0x51, 0x0a, 0x0f, 0x43, 0x6f,
-     0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70,
-     0x65, 0x12, 0x20, 0x0a, 0x1c, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53,
-     0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e,
+     0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x08, 0x74, 0x72, 0x69,
+     0x67, 0x67, 0x65, 0x72, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x72, 0x69,
+     0x67, 0x67, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
+     0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x74,
+     0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75,
+     0x74, 0x4d, 0x73, 0x1a, 0x71, 0x0a, 0x07, 0x54, 0x72, 0x69, 0x67, 0x67,
+     0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
+     0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2e,
+     0x0a, 0x13, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x6e,
+     0x61, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x02, 0x20,
+     0x01, 0x28, 0x09, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65,
+     0x72, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x22,
+     0x0a, 0x0d, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79,
+     0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x73,
+     0x74, 0x6f, 0x70, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x73, 0x22, 0x43,
+     0x0a, 0x0b, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x4d, 0x6f, 0x64,
+     0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49,
+     0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x54,
+     0x41, 0x52, 0x54, 0x5f, 0x54, 0x52, 0x41, 0x43, 0x49, 0x4e, 0x47, 0x10,
+     0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x4f, 0x50, 0x5f, 0x54, 0x52,
+     0x41, 0x43, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x1a, 0x40, 0x0a, 0x16, 0x49,
+     0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x53, 0x74,
+     0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x26, 0x0a,
+     0x0f, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f,
+     0x64, 0x5f, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d,
+     0x63, 0x6c, 0x65, 0x61, 0x72, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4d,
+     0x73, 0x1a, 0xbc, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x63, 0x69, 0x64, 0x65,
+     0x6e, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66,
+     0x69, 0x67, 0x12, 0x2f, 0x0a, 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e,
+     0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67,
+     0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x64, 0x65, 0x73,
+     0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x63, 0x6b,
+     0x61, 0x67, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x64, 0x65, 0x73, 0x74, 0x69,
+     0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73,
+     0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x64, 0x65, 0x73, 0x74,
+     0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x61, 0x73, 0x73,
+     0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x76, 0x61, 0x63, 0x79, 0x5f,
+     0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
+     0x0c, 0x70, 0x72, 0x69, 0x76, 0x61, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65,
+     0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x64, 0x72,
+     0x6f, 0x70, 0x62, 0x6f, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52,
+     0x0b, 0x73, 0x6b, 0x69, 0x70, 0x44, 0x72, 0x6f, 0x70, 0x62, 0x6f, 0x78,
+     0x22, 0x55, 0x0a, 0x15, 0x4c, 0x6f, 0x63, 0x6b, 0x64, 0x6f, 0x77, 0x6e,
+     0x4d, 0x6f, 0x64, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f,
+     0x6e, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x4f, 0x43, 0x4b, 0x44, 0x4f, 0x57,
+     0x4e, 0x5f, 0x55, 0x4e, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x44, 0x10,
+     0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x4f, 0x43, 0x4b, 0x44, 0x4f, 0x57,
+     0x4e, 0x5f, 0x43, 0x4c, 0x45, 0x41, 0x52, 0x10, 0x01, 0x12, 0x10, 0x0a,
+     0x0c, 0x4c, 0x4f, 0x43, 0x4b, 0x44, 0x4f, 0x57, 0x4e, 0x5f, 0x53, 0x45,
+     0x54, 0x10, 0x02, 0x22, 0x51, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x70, 0x72,
+     0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20,
+     0x0a, 0x1c, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f,
+     0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
+     0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18,
+     0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f,
+     0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x46, 0x4c, 0x41, 0x54, 0x45,
+     0x10, 0x01, 0x4a, 0x04, 0x08, 0x0f, 0x10, 0x10, 0x22, 0xe4, 0x03, 0x0a,
+     0x0f, 0x48, 0x65, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x66, 0x64, 0x43, 0x6f,
+     0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x61, 0x6d, 0x70,
+     0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
+     0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
+     0x04, 0x52, 0x15, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x49,
+     0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73,
+     0x12, 0x27, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f,
+     0x63, 0x6d, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28,
+     0x09, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6d,
+     0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64,
+     0x18, 0x04, 0x20, 0x03, 0x28, 0x04, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12,
+     0x10, 0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08,
+     0x52, 0x03, 0x61, 0x6c, 0x6c, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x6b, 0x69,
+     0x70, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x5f, 0x70, 0x72, 0x65,
+     0x66, 0x69, 0x78, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x73,
+     0x6b, 0x69, 0x70, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x50, 0x72, 0x65,
+     0x66, 0x69, 0x78, 0x12, 0x6b, 0x0a, 0x16, 0x63, 0x6f, 0x6e, 0x74, 0x69,
+     0x6e, 0x75, 0x6f, 0x75, 0x73, 0x5f, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x63,
+     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32,
+     0x35, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x70, 0x72,
+     0x6f, 0x66, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f,
+     0x6e, 0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d, 0x70,
+     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x14, 0x63, 0x6f, 0x6e, 0x74,
+     0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d, 0x70, 0x43, 0x6f,
+     0x6e, 0x66, 0x69, 0x67, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x68, 0x6d, 0x65,
+     0x6d, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73,
+     0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x73, 0x68, 0x6d, 0x65,
+     0x6d, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x21,
+     0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6c, 0x69, 0x65,
+     0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x62, 0x6c,
+     0x6f, 0x63, 0x6b, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x1a, 0x64, 0x0a,
+     0x14, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44,
+     0x75, 0x6d, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x22, 0x0a,
+     0x0d, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x70, 0x68, 0x61, 0x73, 0x65, 0x5f,
+     0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x64, 0x75,
+     0x6d, 0x70, 0x50, 0x68, 0x61, 0x73, 0x65, 0x4d, 0x73, 0x12, 0x28, 0x0a,
+     0x10, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,
+     0x61, 0x6c, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52,
+     0x0e, 0x64, 0x75, 0x6d, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
+     0x6c, 0x4d, 0x73, 0x22, 0x44, 0x0a, 0x12, 0x50, 0x61, 0x63, 0x6b, 0x61,
+     0x67, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+     0x67, 0x12, 0x2e, 0x0a, 0x13, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
+     0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72,
+     0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x70, 0x61, 0x63, 0x6b,
+     0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65,
+     0x72, 0x2a, 0x8e, 0x01, 0x0a, 0x0c, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+     0x64, 0x4c, 0x6f, 0x67, 0x49, 0x64, 0x12, 0x0f, 0x0a, 0x0b, 0x4c, 0x49,
+     0x44, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12,
+     0x0d, 0x0a, 0x09, 0x4c, 0x49, 0x44, 0x5f, 0x52, 0x41, 0x44, 0x49, 0x4f,
+     0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x4c, 0x49, 0x44, 0x5f, 0x45, 0x56,
+     0x45, 0x4e, 0x54, 0x53, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x4c, 0x49,
+     0x44, 0x5f, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x10, 0x03, 0x12, 0x0d,
+     0x0a, 0x09, 0x4c, 0x49, 0x44, 0x5f, 0x43, 0x52, 0x41, 0x53, 0x48, 0x10,
+     0x04, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x49, 0x44, 0x5f, 0x53, 0x54, 0x41,
+     0x54, 0x53, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x49, 0x44, 0x5f,
+     0x53, 0x45, 0x43, 0x55, 0x52, 0x49, 0x54, 0x59, 0x10, 0x06, 0x12, 0x0e,
+     0x0a, 0x0a, 0x4c, 0x49, 0x44, 0x5f, 0x4b, 0x45, 0x52, 0x4e, 0x45, 0x4c,
+     0x10, 0x07, 0x2a, 0x9b, 0x01, 0x0a, 0x12, 0x41, 0x6e, 0x64, 0x72, 0x6f,
+     0x69, 0x64, 0x4c, 0x6f, 0x67, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74,
+     0x79, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x55, 0x4e,
      0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12,
-     0x1c, 0x0a, 0x18, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49,
-     0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x46, 0x4c,
-     0x41, 0x54, 0x45, 0x10, 0x01, 0x4a, 0x04, 0x08, 0x0f, 0x10, 0x10, 0x22,
-     0xed, 0x04, 0x0a, 0x0f, 0x48, 0x65, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x66,
-     0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x17, 0x73,
-     0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6e, 0x74, 0x65,
-     0x72, 0x76, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01,
-     0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69,
-     0x6e, 0x67, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x42, 0x79,
-     0x74, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x63, 0x65,
-     0x73, 0x73, 0x5f, 0x63, 0x6d, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x02,
-     0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
-     0x73, 0x43, 0x6d, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x10, 0x0a, 0x03,
-     0x70, 0x69, 0x64, 0x18, 0x04, 0x20, 0x03, 0x28, 0x04, 0x52, 0x03, 0x70,
-     0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x05, 0x20,
-     0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x6c, 0x6c, 0x12, 0x2c, 0x0a, 0x12,
-     0x73, 0x6b, 0x69, 0x70, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x5f,
-     0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09,
-     0x52, 0x10, 0x73, 0x6b, 0x69, 0x70, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c,
-     0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x6b, 0x0a, 0x16, 0x63, 0x6f,
-     0x6e, 0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x5f, 0x64, 0x75, 0x6d,
-     0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x35, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61,
-     0x70, 0x70, 0x72, 0x6f, 0x66, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-     0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44,
-     0x75, 0x6d, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x14, 0x63,
-     0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d,
-     0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x28, 0x0a, 0x10, 0x73,
-     0x68, 0x6d, 0x65, 0x6d, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79,
-     0x74, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x73,
-     0x68, 0x6d, 0x65, 0x6d, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65,
-     0x73, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63,
-     0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52,
-     0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74,
-     0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74,
-     0x75, 0x70, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6e, 0x6f,
-     0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x6e,
-     0x6f, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x0b, 0x20,
-     0x01, 0x28, 0x08, 0x52, 0x09, 0x6e, 0x6f, 0x52, 0x75, 0x6e, 0x6e, 0x69,
-     0x6e, 0x67, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x64, 0x6c, 0x65, 0x5f, 0x61,
-     0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0c,
-     0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x64, 0x6c, 0x65, 0x41, 0x6c,
-     0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a,
-     0x0b, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x61, 0x78,
-     0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x64, 0x75, 0x6d, 0x70,
-     0x41, 0x74, 0x4d, 0x61, 0x78, 0x1a, 0x64, 0x0a, 0x14, 0x43, 0x6f, 0x6e,
-     0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d, 0x70, 0x43,
-     0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x22, 0x0a, 0x0d, 0x64, 0x75, 0x6d,
-     0x70, 0x5f, 0x70, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x05,
-     0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x64, 0x75, 0x6d, 0x70, 0x50, 0x68,
-     0x61, 0x73, 0x65, 0x4d, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x64, 0x75, 0x6d,
-     0x70, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d,
-     0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x64, 0x75, 0x6d,
-     0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x73, 0x22,
-     0x9f, 0x02, 0x0a, 0x0f, 0x4a, 0x61, 0x76, 0x61, 0x48, 0x70, 0x72, 0x6f,
-     0x66, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x27, 0x0a, 0x0f, 0x70,
-     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x6d, 0x64, 0x6c, 0x69,
-     0x6e, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x72,
-     0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6d, 0x64, 0x6c, 0x69, 0x6e, 0x65,
-     0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28,
-     0x04, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x6b, 0x0a, 0x16, 0x63, 0x6f,
-     0x6e, 0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x5f, 0x64, 0x75, 0x6d,
-     0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x35, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61, 0x76,
-     0x61, 0x48, 0x70, 0x72, 0x6f, 0x66, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-     0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44,
-     0x75, 0x6d, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x14, 0x63,
-     0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d,
-     0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x64, 0x0a, 0x14, 0x43,
-     0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d,
-     0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x22, 0x0a, 0x0d, 0x64,
-     0x75, 0x6d, 0x70, 0x5f, 0x70, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x6d, 0x73,
-     0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x64, 0x75, 0x6d, 0x70,
-     0x50, 0x68, 0x61, 0x73, 0x65, 0x4d, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x64,
-     0x75, 0x6d, 0x70, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,
-     0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x64,
-     0x75, 0x6d, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d,
-     0x73, 0x22, 0xb8, 0x01, 0x0a, 0x10, 0x47, 0x70, 0x75, 0x43, 0x6f, 0x75,
-     0x6e, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2a,
-     0x0a, 0x11, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x5f, 0x70, 0x65,
-     0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
-     0x04, 0x52, 0x0f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x50, 0x65,
-     0x72, 0x69, 0x6f, 0x64, 0x4e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f,
-     0x75, 0x6e, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20,
-     0x03, 0x28, 0x0d, 0x52, 0x0a, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
-     0x49, 0x64, 0x73, 0x12, 0x33, 0x0a, 0x15, 0x69, 0x6e, 0x73, 0x74, 0x72,
-     0x75, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x61, 0x6d, 0x70,
-     0x6c, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14,
-     0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64,
-     0x53, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x12, 0x22, 0x0a, 0x0d,
-     0x66, 0x69, 0x78, 0x5f, 0x67, 0x70, 0x75, 0x5f, 0x63, 0x6c, 0x6f, 0x63,
-     0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x66, 0x69, 0x78,
-     0x47, 0x70, 0x75, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x44, 0x0a, 0x12,
-     0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74,
-     0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e, 0x0a, 0x13, 0x70, 0x61,
-     0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x66,
-     0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52,
-     0x11, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65,
-     0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2a, 0x8e, 0x01, 0x0a, 0x0c, 0x41,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6f, 0x67, 0x49, 0x64, 0x12,
-     0x0f, 0x0a, 0x0b, 0x4c, 0x49, 0x44, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55,
-     0x4c, 0x54, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x49, 0x44, 0x5f,
-     0x52, 0x41, 0x44, 0x49, 0x4f, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x4c,
-     0x49, 0x44, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x53, 0x10, 0x02, 0x12,
-     0x0e, 0x0a, 0x0a, 0x4c, 0x49, 0x44, 0x5f, 0x53, 0x59, 0x53, 0x54, 0x45,
-     0x4d, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x49, 0x44, 0x5f, 0x43,
-     0x52, 0x41, 0x53, 0x48, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x49,
-     0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x53, 0x10, 0x05, 0x12, 0x10, 0x0a,
-     0x0c, 0x4c, 0x49, 0x44, 0x5f, 0x53, 0x45, 0x43, 0x55, 0x52, 0x49, 0x54,
-     0x59, 0x10, 0x06, 0x12, 0x0e, 0x0a, 0x0a, 0x4c, 0x49, 0x44, 0x5f, 0x4b,
-     0x45, 0x52, 0x4e, 0x45, 0x4c, 0x10, 0x07, 0x2a, 0x9b, 0x01, 0x0a, 0x12,
-     0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6f, 0x67, 0x50, 0x72,
-     0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x52,
-     0x49, 0x4f, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
-     0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x50, 0x52, 0x49, 0x4f,
-     0x5f, 0x55, 0x4e, 0x55, 0x53, 0x45, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a,
-     0x0c, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x56, 0x45, 0x52, 0x42, 0x4f, 0x53,
-     0x45, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x52, 0x49, 0x4f, 0x5f,
-     0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x50,
-     0x52, 0x49, 0x4f, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x04, 0x12, 0x0d,
-     0x0a, 0x09, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x10,
-     0x05, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x45, 0x52,
-     0x52, 0x4f, 0x52, 0x10, 0x06, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x52, 0x49,
-     0x4f, 0x5f, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10, 0x07, 0x2a, 0xbf, 0x06,
-     0x0a, 0x0f, 0x4d, 0x65, 0x6d, 0x69, 0x6e, 0x66, 0x6f, 0x43, 0x6f, 0x75,
-     0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d,
-     0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49,
-     0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45,
-     0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x5f, 0x54, 0x4f,
-     0x54, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x4d,
-     0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x5f, 0x46, 0x52, 0x45,
-     0x45, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
-     0x46, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x5f, 0x41, 0x56, 0x41, 0x49, 0x4c,
-     0x41, 0x42, 0x4c, 0x45, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x4d, 0x45,
-     0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x42, 0x55, 0x46, 0x46, 0x45, 0x52,
-     0x53, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
-     0x46, 0x4f, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x44, 0x10, 0x05, 0x12,
-     0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53,
-     0x57, 0x41, 0x50, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x44, 0x10, 0x06,
-     0x12, 0x12, 0x0a, 0x0e, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
-     0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x07, 0x12, 0x14, 0x0a, 0x10,
-     0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x49, 0x4e, 0x41, 0x43,
-     0x54, 0x49, 0x56, 0x45, 0x10, 0x08, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45,
-     0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45,
-     0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x09, 0x12, 0x19, 0x0a, 0x15, 0x4d,
-     0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54,
-     0x49, 0x56, 0x45, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x0a, 0x12, 0x17,
-     0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x43,
-     0x54, 0x49, 0x56, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x0b, 0x12,
-     0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x49,
-     0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45,
-     0x10, 0x0c, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46,
-     0x4f, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c,
-     0x45, 0x10, 0x0d, 0x12, 0x13, 0x0a, 0x0f, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
-     0x46, 0x4f, 0x5f, 0x4d, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x0e,
+     0x0f, 0x0a, 0x0b, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x55, 0x4e, 0x55, 0x53,
+     0x45, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x52, 0x49, 0x4f,
+     0x5f, 0x56, 0x45, 0x52, 0x42, 0x4f, 0x53, 0x45, 0x10, 0x02, 0x12, 0x0e,
+     0x0a, 0x0a, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x44, 0x45, 0x42, 0x55, 0x47,
+     0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x49,
+     0x4e, 0x46, 0x4f, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x52, 0x49,
+     0x4f, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x05, 0x12, 0x0e, 0x0a, 0x0a,
+     0x50, 0x52, 0x49, 0x4f, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x06,
+     0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x52, 0x49, 0x4f, 0x5f, 0x46, 0x41, 0x54,
+     0x41, 0x4c, 0x10, 0x07, 0x2a, 0xbf, 0x06, 0x0a, 0x0f, 0x4d, 0x65, 0x6d,
+     0x69, 0x6e, 0x66, 0x6f, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73,
+     0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
+     0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
+     0x00, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
+     0x5f, 0x4d, 0x45, 0x4d, 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x10, 0x01,
+     0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
+     0x4d, 0x45, 0x4d, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x10, 0x02, 0x12, 0x19,
+     0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x45,
+     0x4d, 0x5f, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, 0x45, 0x10,
+     0x03, 0x12, 0x13, 0x0a, 0x0f, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
+     0x5f, 0x42, 0x55, 0x46, 0x46, 0x45, 0x52, 0x53, 0x10, 0x04, 0x12, 0x12,
+     0x0a, 0x0e, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x41,
+     0x43, 0x48, 0x45, 0x44, 0x10, 0x05, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45,
+     0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x57, 0x41, 0x50, 0x5f, 0x43,
+     0x41, 0x43, 0x48, 0x45, 0x44, 0x10, 0x06, 0x12, 0x12, 0x0a, 0x0e, 0x4d,
+     0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56,
+     0x45, 0x10, 0x07, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
+     0x46, 0x4f, 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10,
+     0x08, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
+     0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x41, 0x4e, 0x4f, 0x4e,
+     0x10, 0x09, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46,
+     0x4f, 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x41,
+     0x4e, 0x4f, 0x4e, 0x10, 0x0a, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d,
+     0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f,
+     0x46, 0x49, 0x4c, 0x45, 0x10, 0x0b, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45,
+     0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49,
+     0x56, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x0c, 0x12, 0x17, 0x0a,
+     0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x55, 0x4e, 0x45,
+     0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x0d, 0x12, 0x13,
+     0x0a, 0x0f, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x4c,
+     0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x0e, 0x12, 0x16, 0x0a, 0x12, 0x4d,
+     0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x57, 0x41, 0x50, 0x5f,
+     0x54, 0x4f, 0x54, 0x41, 0x4c, 0x10, 0x0f, 0x12, 0x15, 0x0a, 0x11, 0x4d,
+     0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x57, 0x41, 0x50, 0x5f,
+     0x46, 0x52, 0x45, 0x45, 0x10, 0x10, 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x45,
+     0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x44, 0x49, 0x52, 0x54, 0x59, 0x10,
+     0x11, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
+     0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x12,
      0x12, 0x16, 0x0a, 0x12, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
-     0x53, 0x57, 0x41, 0x50, 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x10, 0x0f,
-     0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
-     0x53, 0x57, 0x41, 0x50, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x10, 0x10, 0x12,
-     0x11, 0x0a, 0x0d, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x44,
-     0x49, 0x52, 0x54, 0x59, 0x10, 0x11, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45,
-     0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x42,
-     0x41, 0x43, 0x4b, 0x10, 0x12, 0x12, 0x16, 0x0a, 0x12, 0x4d, 0x45, 0x4d,
-     0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x5f, 0x50, 0x41,
-     0x47, 0x45, 0x53, 0x10, 0x13, 0x12, 0x12, 0x0a, 0x0e, 0x4d, 0x45, 0x4d,
-     0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x41, 0x50, 0x50, 0x45, 0x44, 0x10,
-     0x14, 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
-     0x5f, 0x53, 0x48, 0x4d, 0x45, 0x4d, 0x10, 0x15, 0x12, 0x10, 0x0a, 0x0c,
-     0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x4c, 0x41, 0x42,
-     0x10, 0x16, 0x12, 0x1c, 0x0a, 0x18, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46,
-     0x4f, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x5f, 0x52, 0x45, 0x43, 0x4c, 0x41,
-     0x49, 0x4d, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x17, 0x12, 0x1e, 0x0a, 0x1a,
-     0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x4c, 0x41, 0x42,
-     0x5f, 0x55, 0x4e, 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x41, 0x42,
-     0x4c, 0x45, 0x10, 0x18, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x45, 0x4d, 0x49,
-     0x4e, 0x46, 0x4f, 0x5f, 0x4b, 0x45, 0x52, 0x4e, 0x45, 0x4c, 0x5f, 0x53,
-     0x54, 0x41, 0x43, 0x4b, 0x10, 0x19, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45,
-     0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x5f, 0x54,
-     0x41, 0x42, 0x4c, 0x45, 0x53, 0x10, 0x1a, 0x12, 0x18, 0x0a, 0x14, 0x4d,
-     0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49,
-     0x54, 0x5f, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x10, 0x1b, 0x12, 0x17, 0x0a,
-     0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4f, 0x4d,
-     0x4d, 0x49, 0x54, 0x45, 0x44, 0x5f, 0x41, 0x53, 0x10, 0x1c, 0x12, 0x19,
-     0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x56, 0x4d,
-     0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x10,
-     0x1d, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
-     0x5f, 0x56, 0x4d, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x55, 0x53, 0x45,
-     0x44, 0x10, 0x1e, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
-     0x46, 0x4f, 0x5f, 0x56, 0x4d, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x43,
-     0x48, 0x55, 0x4e, 0x4b, 0x10, 0x1f, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45,
-     0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4d, 0x41, 0x5f, 0x54, 0x4f,
-     0x54, 0x41, 0x4c, 0x10, 0x20, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x4d,
-     0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4d, 0x41, 0x5f, 0x46, 0x52, 0x45,
-     0x45, 0x10, 0x21, 0x2a, 0xc6, 0x15, 0x0a, 0x0e, 0x56, 0x6d, 0x73, 0x74,
-     0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x16,
-     0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x53,
-     0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18,
-     0x0a, 0x14, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
-     0x46, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x01,
-     0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e,
-     0x52, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x42, 0x41, 0x54, 0x43,
-     0x48, 0x10, 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41,
-     0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56,
-     0x45, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15,
-     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x43,
-     0x54, 0x49, 0x56, 0x45, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x04, 0x12,
-     0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
-     0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x46, 0x49,
-     0x4c, 0x45, 0x10, 0x05, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45,
-     0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x06, 0x12, 0x19, 0x0a, 0x15, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x55, 0x4e, 0x45,
-     0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x07, 0x12, 0x13,
-     0x0a, 0x0f, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
-     0x4d, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x4e, 0x4f,
-     0x4e, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x09, 0x12, 0x14, 0x0a,
-     0x10, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x4d,
-     0x41, 0x50, 0x50, 0x45, 0x44, 0x10, 0x0a, 0x12, 0x18, 0x0a, 0x14, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x46, 0x49, 0x4c,
-     0x45, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x0b, 0x12, 0x13, 0x0a,
-     0x0f, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44,
-     0x49, 0x52, 0x54, 0x59, 0x10, 0x0c, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d,
-     0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x57, 0x52, 0x49, 0x54,
-     0x45, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x0d, 0x12, 0x1e, 0x0a, 0x1a, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x4c, 0x41,
+     0x41, 0x4e, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x13,
+     0x12, 0x12, 0x0a, 0x0e, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
+     0x4d, 0x41, 0x50, 0x50, 0x45, 0x44, 0x10, 0x14, 0x12, 0x11, 0x0a, 0x0d,
+     0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x48, 0x4d, 0x45,
+     0x4d, 0x10, 0x15, 0x12, 0x10, 0x0a, 0x0c, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
+     0x46, 0x4f, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x10, 0x16, 0x12, 0x1c, 0x0a,
+     0x18, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x4c, 0x41,
      0x42, 0x5f, 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x41, 0x42, 0x4c,
-     0x45, 0x10, 0x0e, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41,
-     0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x5f, 0x55, 0x4e,
-     0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x41, 0x42, 0x4c, 0x45, 0x10,
-     0x0f, 0x12, 0x1e, 0x0a, 0x1a, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
-     0x4e, 0x52, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x41, 0x42, 0x4c,
-     0x45, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x10, 0x12, 0x1a, 0x0a,
-     0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x4b,
+     0x45, 0x10, 0x17, 0x12, 0x1e, 0x0a, 0x1a, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
+     0x46, 0x4f, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x5f, 0x55, 0x4e, 0x52, 0x45,
+     0x43, 0x4c, 0x41, 0x49, 0x4d, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x18, 0x12,
+     0x18, 0x0a, 0x14, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4b,
      0x45, 0x52, 0x4e, 0x45, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x43, 0x4b, 0x10,
-     0x11, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
-     0x4e, 0x52, 0x5f, 0x4f, 0x56, 0x45, 0x52, 0x48, 0x45, 0x41, 0x44, 0x10,
-     0x12, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
-     0x4e, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10,
-     0x13, 0x12, 0x14, 0x0a, 0x10, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
-     0x4e, 0x52, 0x5f, 0x42, 0x4f, 0x55, 0x4e, 0x43, 0x45, 0x10, 0x14, 0x12,
-     0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
-     0x5f, 0x56, 0x4d, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x57, 0x52, 0x49, 0x54,
-     0x45, 0x10, 0x15, 0x12, 0x26, 0x0a, 0x22, 0x56, 0x4d, 0x53, 0x54, 0x41,
-     0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x56, 0x4d, 0x53, 0x43, 0x41, 0x4e, 0x5f,
-     0x49, 0x4d, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x54, 0x45, 0x5f, 0x52, 0x45,
-     0x43, 0x4c, 0x41, 0x49, 0x4d, 0x10, 0x16, 0x12, 0x1c, 0x0a, 0x18, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x57, 0x52, 0x49,
-     0x54, 0x45, 0x42, 0x41, 0x43, 0x4b, 0x5f, 0x54, 0x45, 0x4d, 0x50, 0x10,
-     0x17, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+     0x19, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
+     0x5f, 0x50, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x53,
+     0x10, 0x1a, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46,
+     0x4f, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x5f, 0x4c, 0x49, 0x4d,
+     0x49, 0x54, 0x10, 0x1b, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49,
+     0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x45, 0x44,
+     0x5f, 0x41, 0x53, 0x10, 0x1c, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d,
+     0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x56, 0x4d, 0x41, 0x4c, 0x4c, 0x4f, 0x43,
+     0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x10, 0x1d, 0x12, 0x18, 0x0a, 0x14,
+     0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x56, 0x4d, 0x41, 0x4c,
+     0x4c, 0x4f, 0x43, 0x5f, 0x55, 0x53, 0x45, 0x44, 0x10, 0x1e, 0x12, 0x19,
+     0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x56, 0x4d,
+     0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x43, 0x48, 0x55, 0x4e, 0x4b, 0x10,
+     0x1f, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
+     0x5f, 0x43, 0x4d, 0x41, 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x10, 0x20,
+     0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
+     0x43, 0x4d, 0x41, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x10, 0x21, 0x2a, 0xff,
+     0x14, 0x0a, 0x0e, 0x56, 0x6d, 0x73, 0x74, 0x61, 0x74, 0x43, 0x6f, 0x75,
+     0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
+     0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x5f,
+     0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x56,
+     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x4c, 0x4c,
+     0x4f, 0x43, 0x5f, 0x42, 0x41, 0x54, 0x43, 0x48, 0x10, 0x02, 0x12, 0x1b,
+     0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
+     0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x41, 0x4e, 0x4f,
+     0x4e, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41,
+     0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f,
+     0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x04, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d,
+     0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x49, 0x4e, 0x41, 0x43,
+     0x54, 0x49, 0x56, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x05, 0x12,
+     0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
+     0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45,
+     0x10, 0x06, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x4e, 0x52, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41,
+     0x42, 0x4c, 0x45, 0x10, 0x07, 0x12, 0x13, 0x0a, 0x0f, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x4d, 0x4c, 0x4f, 0x43, 0x4b,
+     0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x47,
+     0x45, 0x53, 0x10, 0x09, 0x12, 0x14, 0x0a, 0x10, 0x56, 0x4d, 0x53, 0x54,
+     0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x4d, 0x41, 0x50, 0x50, 0x45, 0x44,
+     0x10, 0x0a, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x4e, 0x52, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x50, 0x41, 0x47,
+     0x45, 0x53, 0x10, 0x0b, 0x12, 0x13, 0x0a, 0x0f, 0x56, 0x4d, 0x53, 0x54,
+     0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44, 0x49, 0x52, 0x54, 0x59, 0x10,
+     0x0c, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+     0x4e, 0x52, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x42, 0x41, 0x43, 0x4b,
+     0x10, 0x0d, 0x12, 0x1e, 0x0a, 0x1a, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x5f, 0x52, 0x45, 0x43,
+     0x4c, 0x41, 0x49, 0x4d, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x0e, 0x12, 0x20,
+     0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
+     0x53, 0x4c, 0x41, 0x42, 0x5f, 0x55, 0x4e, 0x52, 0x45, 0x43, 0x4c, 0x41,
+     0x49, 0x4d, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x0f, 0x12, 0x1e, 0x0a, 0x1a,
+     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x50, 0x41,
+     0x47, 0x45, 0x5f, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x41, 0x47,
+     0x45, 0x53, 0x10, 0x10, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54,
+     0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x4b, 0x45, 0x52, 0x4e, 0x45, 0x4c,
+     0x5f, 0x53, 0x54, 0x41, 0x43, 0x4b, 0x10, 0x11, 0x12, 0x16, 0x0a, 0x12,
+     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x4f, 0x56,
+     0x45, 0x52, 0x48, 0x45, 0x41, 0x44, 0x10, 0x12, 0x12, 0x16, 0x0a, 0x12,
+     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x55, 0x4e,
+     0x53, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x13, 0x12, 0x14, 0x0a, 0x10,
+     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x42, 0x4f,
+     0x55, 0x4e, 0x43, 0x45, 0x10, 0x14, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d,
+     0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x56, 0x4d, 0x53, 0x43,
+     0x41, 0x4e, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x10, 0x15, 0x12, 0x26,
+     0x0a, 0x22, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
+     0x56, 0x4d, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x49, 0x4d, 0x4d, 0x45, 0x44,
+     0x49, 0x41, 0x54, 0x45, 0x5f, 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d,
+     0x10, 0x16, 0x12, 0x1c, 0x0a, 0x18, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x4e, 0x52, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x42, 0x41, 0x43,
+     0x4b, 0x5f, 0x54, 0x45, 0x4d, 0x50, 0x10, 0x17, 0x12, 0x1b, 0x0a, 0x17,
+     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x49, 0x53,
+     0x4f, 0x4c, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10,
+     0x18, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
      0x4e, 0x52, 0x5f, 0x49, 0x53, 0x4f, 0x4c, 0x41, 0x54, 0x45, 0x44, 0x5f,
-     0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x18, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d,
-     0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x49, 0x53, 0x4f, 0x4c,
-     0x41, 0x54, 0x45, 0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x19, 0x12,
-     0x13, 0x0a, 0x0f, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
-     0x5f, 0x53, 0x48, 0x4d, 0x45, 0x4d, 0x10, 0x1a, 0x12, 0x15, 0x0a, 0x11,
-     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44, 0x49,
-     0x52, 0x54, 0x49, 0x45, 0x44, 0x10, 0x1b, 0x12, 0x15, 0x0a, 0x11, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x57, 0x52, 0x49,
-     0x54, 0x54, 0x45, 0x4e, 0x10, 0x1c, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d,
-     0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x50, 0x41, 0x47, 0x45,
-     0x53, 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x1d, 0x12,
-     0x1d, 0x0a, 0x19, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x57, 0x4f,
-     0x52, 0x4b, 0x49, 0x4e, 0x47, 0x53, 0x45, 0x54, 0x5f, 0x52, 0x45, 0x46,
-     0x41, 0x55, 0x4c, 0x54, 0x10, 0x1e, 0x12, 0x1e, 0x0a, 0x1a, 0x56, 0x4d,
+     0x46, 0x49, 0x4c, 0x45, 0x10, 0x19, 0x12, 0x13, 0x0a, 0x0f, 0x56, 0x4d,
+     0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x48, 0x4d, 0x45,
+     0x4d, 0x10, 0x1a, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41,
+     0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44, 0x49, 0x52, 0x54, 0x49, 0x45, 0x44,
+     0x10, 0x1b, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x4e, 0x52, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x54, 0x45, 0x4e, 0x10,
+     0x1c, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+     0x4e, 0x52, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x5f, 0x53, 0x43, 0x41,
+     0x4e, 0x4e, 0x45, 0x44, 0x10, 0x1d, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x4d,
      0x53, 0x54, 0x41, 0x54, 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x49, 0x4e, 0x47,
-     0x53, 0x45, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45,
-     0x10, 0x1f, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
-     0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x49, 0x4e, 0x47, 0x53, 0x45, 0x54, 0x5f,
-     0x4e, 0x4f, 0x44, 0x45, 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x10,
-     0x20, 0x12, 0x28, 0x0a, 0x24, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
-     0x4e, 0x52, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e,
-     0x53, 0x50, 0x41, 0x52, 0x45, 0x4e, 0x54, 0x5f, 0x48, 0x55, 0x47, 0x45,
-     0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x21, 0x12, 0x16, 0x0a, 0x12, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x46, 0x52, 0x45,
-     0x45, 0x5f, 0x43, 0x4d, 0x41, 0x10, 0x22, 0x12, 0x17, 0x0a, 0x13, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x57, 0x41,
-     0x50, 0x43, 0x41, 0x43, 0x48, 0x45, 0x10, 0x23, 0x12, 0x1d, 0x0a, 0x19,
-     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44, 0x49,
-     0x52, 0x54, 0x59, 0x5f, 0x54, 0x48, 0x52, 0x45, 0x53, 0x48, 0x4f, 0x4c,
-     0x44, 0x10, 0x24, 0x12, 0x28, 0x0a, 0x24, 0x56, 0x4d, 0x53, 0x54, 0x41,
-     0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44, 0x49, 0x52, 0x54, 0x59, 0x5f, 0x42,
-     0x41, 0x43, 0x4b, 0x47, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x54, 0x48,
-     0x52, 0x45, 0x53, 0x48, 0x4f, 0x4c, 0x44, 0x10, 0x25, 0x12, 0x11, 0x0a,
-     0x0d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x50, 0x47,
-     0x49, 0x4e, 0x10, 0x26, 0x12, 0x12, 0x0a, 0x0e, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x50, 0x47, 0x50, 0x47, 0x4f, 0x55, 0x54, 0x10, 0x27,
+     0x53, 0x45, 0x54, 0x5f, 0x52, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10,
+     0x1e, 0x12, 0x1e, 0x0a, 0x1a, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+     0x57, 0x4f, 0x52, 0x4b, 0x49, 0x4e, 0x47, 0x53, 0x45, 0x54, 0x5f, 0x41,
+     0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x1f, 0x12, 0x21, 0x0a,
+     0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x57, 0x4f, 0x52, 0x4b,
+     0x49, 0x4e, 0x47, 0x53, 0x45, 0x54, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x52,
+     0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x10, 0x20, 0x12, 0x28, 0x0a, 0x24,
+     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x4e,
+     0x4f, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x50, 0x41, 0x52, 0x45,
+     0x4e, 0x54, 0x5f, 0x48, 0x55, 0x47, 0x45, 0x50, 0x41, 0x47, 0x45, 0x53,
+     0x10, 0x21, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x4e, 0x52, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x5f, 0x43, 0x4d, 0x41,
+     0x10, 0x22, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x57, 0x41, 0x50, 0x43, 0x41, 0x43, 0x48,
+     0x45, 0x10, 0x23, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x4d, 0x53, 0x54, 0x41,
+     0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44, 0x49, 0x52, 0x54, 0x59, 0x5f, 0x54,
+     0x48, 0x52, 0x45, 0x53, 0x48, 0x4f, 0x4c, 0x44, 0x10, 0x24, 0x12, 0x28,
+     0x0a, 0x24, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
+     0x44, 0x49, 0x52, 0x54, 0x59, 0x5f, 0x42, 0x41, 0x43, 0x4b, 0x47, 0x52,
+     0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x54, 0x48, 0x52, 0x45, 0x53, 0x48, 0x4f,
+     0x4c, 0x44, 0x10, 0x25, 0x12, 0x11, 0x0a, 0x0d, 0x56, 0x4d, 0x53, 0x54,
+     0x41, 0x54, 0x5f, 0x50, 0x47, 0x50, 0x47, 0x49, 0x4e, 0x10, 0x26, 0x12,
+     0x12, 0x0a, 0x0e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
+     0x50, 0x47, 0x4f, 0x55, 0x54, 0x10, 0x27, 0x12, 0x17, 0x0a, 0x13, 0x56,
+     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x50, 0x47, 0x4f, 0x55,
+     0x54, 0x43, 0x4c, 0x45, 0x41, 0x4e, 0x10, 0x28, 0x12, 0x11, 0x0a, 0x0d,
+     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x53, 0x57, 0x50, 0x49,
+     0x4e, 0x10, 0x29, 0x12, 0x12, 0x0a, 0x0e, 0x56, 0x4d, 0x53, 0x54, 0x41,
+     0x54, 0x5f, 0x50, 0x53, 0x57, 0x50, 0x4f, 0x55, 0x54, 0x10, 0x2a, 0x12,
+     0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
+     0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x2b, 0x12,
+     0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
+     0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c,
+     0x10, 0x2c, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x50, 0x47, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x4d, 0x4f, 0x56,
+     0x41, 0x42, 0x4c, 0x45, 0x10, 0x2d, 0x12, 0x11, 0x0a, 0x0d, 0x56, 0x4d,
+     0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x46, 0x52, 0x45, 0x45, 0x10,
+     0x2e, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+     0x50, 0x47, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x2f,
      0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50,
-     0x47, 0x50, 0x47, 0x4f, 0x55, 0x54, 0x43, 0x4c, 0x45, 0x41, 0x4e, 0x10,
-     0x28, 0x12, 0x11, 0x0a, 0x0d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
-     0x50, 0x53, 0x57, 0x50, 0x49, 0x4e, 0x10, 0x29, 0x12, 0x12, 0x0a, 0x0e,
-     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x53, 0x57, 0x50, 0x4f,
-     0x55, 0x54, 0x10, 0x2a, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x50, 0x47, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x44,
-     0x4d, 0x41, 0x10, 0x2b, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x50, 0x47, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x4e,
-     0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x2c, 0x12, 0x1a, 0x0a, 0x16, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x41, 0x4c, 0x4c, 0x4f,
-     0x43, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x2d, 0x12,
-     0x11, 0x0a, 0x0d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
-     0x46, 0x52, 0x45, 0x45, 0x10, 0x2e, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d,
-     0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x41, 0x43, 0x54, 0x49, 0x56,
-     0x41, 0x54, 0x45, 0x10, 0x2f, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53,
-     0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x44, 0x45, 0x41, 0x43, 0x54, 0x49,
-     0x56, 0x41, 0x54, 0x45, 0x10, 0x30, 0x12, 0x12, 0x0a, 0x0e, 0x56, 0x4d,
-     0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x46, 0x41, 0x55, 0x4c, 0x54,
-     0x10, 0x31, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
-     0x5f, 0x50, 0x47, 0x4d, 0x41, 0x4a, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10,
-     0x32, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
-     0x50, 0x47, 0x52, 0x45, 0x46, 0x49, 0x4c, 0x4c, 0x5f, 0x44, 0x4d, 0x41,
-     0x10, 0x33, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
-     0x5f, 0x50, 0x47, 0x52, 0x45, 0x46, 0x49, 0x4c, 0x4c, 0x5f, 0x4e, 0x4f,
-     0x52, 0x4d, 0x41, 0x4c, 0x10, 0x34, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d,
-     0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x52, 0x45, 0x46, 0x49, 0x4c,
-     0x4c, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x35, 0x12,
-     0x1d, 0x0a, 0x19, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
-     0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44,
-     0x5f, 0x44, 0x4d, 0x41, 0x10, 0x36, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d,
+     0x47, 0x44, 0x45, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10,
+     0x30, 0x12, 0x12, 0x0a, 0x0e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+     0x50, 0x47, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x31, 0x12, 0x15, 0x0a,
+     0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x4d, 0x41,
+     0x4a, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x32, 0x12, 0x17, 0x0a, 0x13,
+     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x52, 0x45, 0x46,
+     0x49, 0x4c, 0x4c, 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x33, 0x12, 0x1a, 0x0a,
+     0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x52, 0x45,
+     0x46, 0x49, 0x4c, 0x4c, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10,
+     0x34, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+     0x50, 0x47, 0x52, 0x45, 0x46, 0x49, 0x4c, 0x4c, 0x5f, 0x4d, 0x4f, 0x56,
+     0x41, 0x42, 0x4c, 0x45, 0x10, 0x35, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x4d,
      0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c,
-     0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4e, 0x4f, 0x52, 0x4d,
-     0x41, 0x4c, 0x10, 0x37, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x4b,
-     0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c,
-     0x45, 0x10, 0x38, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x4d, 0x53, 0x54, 0x41,
-     0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x44, 0x49,
-     0x52, 0x45, 0x43, 0x54, 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x39, 0x12, 0x20,
-     0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53,
-     0x54, 0x45, 0x41, 0x4c, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f,
-     0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x3a, 0x12, 0x21, 0x0a, 0x1d,
-     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45,
-     0x41, 0x4c, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x4d, 0x4f,
-     0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x3b, 0x12, 0x1c, 0x0a, 0x18, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e,
      0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x44, 0x4d, 0x41, 0x10,
-     0x3c, 0x12, 0x1f, 0x0a, 0x1b, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
-     0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50,
-     0x44, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x3d, 0x12, 0x20,
-     0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53,
-     0x43, 0x41, 0x4e, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4d,
-     0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x3e, 0x12, 0x1c, 0x0a, 0x18,
+     0x36, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+     0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x4b, 0x53, 0x57, 0x41,
+     0x50, 0x44, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x37, 0x12,
+     0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
+     0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44,
+     0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x38, 0x12, 0x1d,
+     0x0a, 0x19, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53,
+     0x54, 0x45, 0x41, 0x4c, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f,
+     0x44, 0x4d, 0x41, 0x10, 0x39, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f,
+     0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41,
+     0x4c, 0x10, 0x3a, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41,
+     0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x44, 0x49,
+     0x52, 0x45, 0x43, 0x54, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45,
+     0x10, 0x3b, 0x12, 0x1c, 0x0a, 0x18, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x4b, 0x53, 0x57, 0x41,
+     0x50, 0x44, 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x3c, 0x12, 0x1f, 0x0a, 0x1b,
      0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41,
-     0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x44, 0x4d, 0x41,
-     0x10, 0x3f, 0x12, 0x1f, 0x0a, 0x1b, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
-     0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45,
-     0x43, 0x54, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x40, 0x12,
-     0x20, 0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
-     0x53, 0x43, 0x41, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f,
-     0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x41, 0x12, 0x21, 0x0a,
-     0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43,
-     0x41, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x54, 0x48,
-     0x52, 0x4f, 0x54, 0x54, 0x4c, 0x45, 0x10, 0x42, 0x12, 0x17, 0x0a, 0x13,
-     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x49, 0x4e, 0x4f,
-     0x44, 0x45, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x10, 0x43, 0x12, 0x18, 0x0a,
-     0x14, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x53, 0x4c, 0x41, 0x42,
-     0x53, 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x44, 0x12,
-     0x1c, 0x0a, 0x18, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4b, 0x53,
-     0x57, 0x41, 0x50, 0x44, 0x5f, 0x49, 0x4e, 0x4f, 0x44, 0x45, 0x53, 0x54,
-     0x45, 0x41, 0x4c, 0x10, 0x45, 0x12, 0x27, 0x0a, 0x23, 0x56, 0x4d, 0x53,
-     0x54, 0x41, 0x54, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4c,
-     0x4f, 0x57, 0x5f, 0x57, 0x4d, 0x41, 0x52, 0x4b, 0x5f, 0x48, 0x49, 0x54,
-     0x5f, 0x51, 0x55, 0x49, 0x43, 0x4b, 0x4c, 0x59, 0x10, 0x46, 0x12, 0x28,
-     0x0a, 0x24, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4b, 0x53, 0x57,
-     0x41, 0x50, 0x44, 0x5f, 0x48, 0x49, 0x47, 0x48, 0x5f, 0x57, 0x4d, 0x41,
-     0x52, 0x4b, 0x5f, 0x48, 0x49, 0x54, 0x5f, 0x51, 0x55, 0x49, 0x43, 0x4b,
-     0x4c, 0x59, 0x10, 0x47, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x4f, 0x55, 0x54, 0x52, 0x55,
-     0x4e, 0x10, 0x48, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41,
-     0x54, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x53, 0x54, 0x41, 0x4c, 0x4c,
-     0x10, 0x49, 0x12, 0x14, 0x0a, 0x10, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
-     0x5f, 0x50, 0x47, 0x52, 0x4f, 0x54, 0x41, 0x54, 0x45, 0x44, 0x10, 0x4a,
-     0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x44,
-     0x52, 0x4f, 0x50, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x43, 0x41, 0x43, 0x48,
-     0x45, 0x10, 0x4b, 0x12, 0x14, 0x0a, 0x10, 0x56, 0x4d, 0x53, 0x54, 0x41,
-     0x54, 0x5f, 0x44, 0x52, 0x4f, 0x50, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x10,
-     0x4c, 0x12, 0x1c, 0x0a, 0x18, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
-     0x50, 0x47, 0x4d, 0x49, 0x47, 0x52, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x55,
-     0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x4d, 0x12, 0x19, 0x0a, 0x15, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x4d, 0x49, 0x47, 0x52,
-     0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x10, 0x4e, 0x12, 0x22,
-     0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d,
-     0x50, 0x41, 0x43, 0x54, 0x5f, 0x4d, 0x49, 0x47, 0x52, 0x41, 0x54, 0x45,
-     0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x4f, 0x12, 0x1f,
-     0x0a, 0x1b, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d,
-     0x50, 0x41, 0x43, 0x54, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x5f, 0x53, 0x43,
-     0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x50, 0x12, 0x1b, 0x0a, 0x17, 0x56,
+     0x4e, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4e, 0x4f, 0x52,
+     0x4d, 0x41, 0x4c, 0x10, 0x3d, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x4b,
+     0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c,
+     0x45, 0x10, 0x3e, 0x12, 0x1c, 0x0a, 0x18, 0x56, 0x4d, 0x53, 0x54, 0x41,
+     0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x44, 0x49, 0x52,
+     0x45, 0x43, 0x54, 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x3f, 0x12, 0x1f, 0x0a,
+     0x1b, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43,
+     0x41, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x4e, 0x4f,
+     0x52, 0x4d, 0x41, 0x4c, 0x10, 0x40, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d,
+     0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f,
+     0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42,
+     0x4c, 0x45, 0x10, 0x41, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54,
+     0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x44, 0x49,
+     0x52, 0x45, 0x43, 0x54, 0x5f, 0x54, 0x48, 0x52, 0x4f, 0x54, 0x54, 0x4c,
+     0x45, 0x10, 0x42, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41,
+     0x54, 0x5f, 0x50, 0x47, 0x49, 0x4e, 0x4f, 0x44, 0x45, 0x53, 0x54, 0x45,
+     0x41, 0x4c, 0x10, 0x43, 0x12, 0x18, 0x0a, 0x14, 0x56, 0x4d, 0x53, 0x54,
+     0x41, 0x54, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x53, 0x5f, 0x53, 0x43, 0x41,
+     0x4e, 0x4e, 0x45, 0x44, 0x10, 0x44, 0x12, 0x1c, 0x0a, 0x18, 0x56, 0x4d,
+     0x53, 0x54, 0x41, 0x54, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f,
+     0x49, 0x4e, 0x4f, 0x44, 0x45, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x10, 0x45,
+     0x12, 0x27, 0x0a, 0x23, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4b,
+     0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4c, 0x4f, 0x57, 0x5f, 0x57, 0x4d,
+     0x41, 0x52, 0x4b, 0x5f, 0x48, 0x49, 0x54, 0x5f, 0x51, 0x55, 0x49, 0x43,
+     0x4b, 0x4c, 0x59, 0x10, 0x46, 0x12, 0x28, 0x0a, 0x24, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x48,
+     0x49, 0x47, 0x48, 0x5f, 0x57, 0x4d, 0x41, 0x52, 0x4b, 0x5f, 0x48, 0x49,
+     0x54, 0x5f, 0x51, 0x55, 0x49, 0x43, 0x4b, 0x4c, 0x59, 0x10, 0x47, 0x12,
+     0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x41,
+     0x47, 0x45, 0x4f, 0x55, 0x54, 0x52, 0x55, 0x4e, 0x10, 0x48, 0x12, 0x15,
+     0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x41, 0x4c, 0x4c,
+     0x4f, 0x43, 0x53, 0x54, 0x41, 0x4c, 0x4c, 0x10, 0x49, 0x12, 0x14, 0x0a,
+     0x10, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x52, 0x4f,
+     0x54, 0x41, 0x54, 0x45, 0x44, 0x10, 0x4a, 0x12, 0x19, 0x0a, 0x15, 0x56,
+     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x44, 0x52, 0x4f, 0x50, 0x5f, 0x50,
+     0x41, 0x47, 0x45, 0x43, 0x41, 0x43, 0x48, 0x45, 0x10, 0x4b, 0x12, 0x14,
+     0x0a, 0x10, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x44, 0x52, 0x4f,
+     0x50, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x10, 0x4c, 0x12, 0x1c, 0x0a, 0x18,
+     0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x4d, 0x49, 0x47,
+     0x52, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53,
+     0x10, 0x4d, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x50, 0x47, 0x4d, 0x49, 0x47, 0x52, 0x41, 0x54, 0x45, 0x5f, 0x46,
+     0x41, 0x49, 0x4c, 0x10, 0x4e, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f,
+     0x4d, 0x49, 0x47, 0x52, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x43, 0x41, 0x4e,
+     0x4e, 0x45, 0x44, 0x10, 0x4f, 0x12, 0x1f, 0x0a, 0x1b, 0x56, 0x4d, 0x53,
+     0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f,
+     0x46, 0x52, 0x45, 0x45, 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44,
+     0x10, 0x50, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f, 0x49, 0x53, 0x4f,
+     0x4c, 0x41, 0x54, 0x45, 0x44, 0x10, 0x51, 0x12, 0x18, 0x0a, 0x14, 0x56,
      0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43,
-     0x54, 0x5f, 0x49, 0x53, 0x4f, 0x4c, 0x41, 0x54, 0x45, 0x44, 0x10, 0x51,
-     0x12, 0x18, 0x0a, 0x14, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43,
-     0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x4c, 0x4c,
-     0x10, 0x52, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
-     0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f, 0x46, 0x41, 0x49,
-     0x4c, 0x10, 0x53, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41,
-     0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f, 0x53, 0x55,
-     0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x54, 0x12, 0x1e, 0x0a, 0x1a, 0x56,
-     0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43,
-     0x54, 0x5f, 0x44, 0x41, 0x45, 0x4d, 0x4f, 0x4e, 0x5f, 0x57, 0x41, 0x4b,
-     0x45, 0x10, 0x55, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41,
-     0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c,
-     0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x43, 0x55, 0x4c, 0x4c, 0x45, 0x44,
-     0x10, 0x56, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
-     0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45,
-     0x5f, 0x50, 0x47, 0x53, 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44,
-     0x10, 0x57, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
-     0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45,
-     0x5f, 0x50, 0x47, 0x53, 0x5f, 0x52, 0x45, 0x53, 0x43, 0x55, 0x45, 0x44,
-     0x10, 0x58, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
-     0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45,
-     0x5f, 0x50, 0x47, 0x53, 0x5f, 0x4d, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44,
-     0x10, 0x59, 0x12, 0x24, 0x0a, 0x20, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
-     0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45,
-     0x5f, 0x50, 0x47, 0x53, 0x5f, 0x4d, 0x55, 0x4e, 0x4c, 0x4f, 0x43, 0x4b,
-     0x45, 0x44, 0x10, 0x5a, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42,
-     0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x43, 0x4c, 0x45, 0x41, 0x52,
-     0x45, 0x44, 0x10, 0x5b, 0x12, 0x23, 0x0a, 0x1f, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42,
-     0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x53, 0x54, 0x52, 0x41, 0x4e,
-     0x44, 0x45, 0x44, 0x10, 0x5c, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53,
-     0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x5a, 0x53, 0x50, 0x41, 0x47,
-     0x45, 0x53, 0x10, 0x5d, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x49, 0x4f, 0x4e, 0x5f, 0x48, 0x45,
-     0x41, 0x50, 0x10, 0x5e, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54,
-     0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x47, 0x50, 0x55, 0x5f, 0x48, 0x45,
-     0x41, 0x50, 0x10, 0x5f}};
+     0x54, 0x5f, 0x53, 0x54, 0x41, 0x4c, 0x4c, 0x10, 0x52, 0x12, 0x17, 0x0a,
+     0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50,
+     0x41, 0x43, 0x54, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x10, 0x53, 0x12, 0x1a,
+     0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d,
+     0x50, 0x41, 0x43, 0x54, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53,
+     0x10, 0x54, 0x12, 0x1e, 0x0a, 0x1a, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+     0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f, 0x44, 0x41, 0x45,
+     0x4d, 0x4f, 0x4e, 0x5f, 0x57, 0x41, 0x4b, 0x45, 0x10, 0x55, 0x12, 0x21,
+     0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45,
+     0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53,
+     0x5f, 0x43, 0x55, 0x4c, 0x4c, 0x45, 0x44, 0x10, 0x56, 0x12, 0x22, 0x0a,
+     0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56,
+     0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f,
+     0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x57, 0x12, 0x22, 0x0a,
+     0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56,
+     0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f,
+     0x52, 0x45, 0x53, 0x43, 0x55, 0x45, 0x44, 0x10, 0x58, 0x12, 0x22, 0x0a,
+     0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56,
+     0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f,
+     0x4d, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x59, 0x12, 0x24, 0x0a,
+     0x20, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56,
+     0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f,
+     0x4d, 0x55, 0x4e, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x5a, 0x12,
+     0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e,
+     0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47,
+     0x53, 0x5f, 0x43, 0x4c, 0x45, 0x41, 0x52, 0x45, 0x44, 0x10, 0x5b, 0x12,
+     0x23, 0x0a, 0x1f, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e,
+     0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x50, 0x47,
+     0x53, 0x5f, 0x53, 0x54, 0x52, 0x41, 0x4e, 0x44, 0x45, 0x44, 0x10, 0x5c}};
 
 }  // namespace perfetto
 
diff --git a/src/perfetto_cmd/rate_limiter.cc b/src/perfetto_cmd/rate_limiter.cc
index 1693d0e..56f34c4 100644
--- a/src/perfetto_cmd/rate_limiter.cc
+++ b/src/perfetto_cmd/rate_limiter.cc
@@ -20,10 +20,10 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/utils.h"
 #include "src/perfetto_cmd/perfetto_cmd.h"
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
@@ -106,8 +106,9 @@
   }
 
   // If we've uploaded in the last 5mins we shouldn't trace now.
-  if ((now_in_s - state_.last_trace_timestamp()) < kCooldownInSeconds) {
-    PERFETTO_LOG("Guardrail: Uploaded to DropBox in the last 5mins.");
+  if (state_.last_trace_timestamp() != 0 &&
+      (now_in_s - state_.last_trace_timestamp()) < kCooldownInSeconds) {
+    PERFETTO_ELOG("Guardrail: Uploaded to DropBox in the last 5mins.");
     if (!args.ignore_guardrails)
       return false;
   }
@@ -164,7 +165,7 @@
 }
 
 std::string RateLimiter::GetStateFilePath() const {
-  return std::string(kStateDir) + "/.guardraildata";
+  return std::string(kTempDropBoxTraceDir) + "/.guardraildata";
 }
 
 bool RateLimiter::StateFileExists() {
diff --git a/src/perfetto_cmd/rate_limiter_unittest.cc b/src/perfetto_cmd/rate_limiter_unittest.cc
index 48507f4..81521cf 100644
--- a/src/perfetto_cmd/rate_limiter_unittest.cc
+++ b/src/perfetto_cmd/rate_limiter_unittest.cc
@@ -18,12 +18,13 @@
 
 #include <stdio.h>
 
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/file_utils.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/temp_file.h"
+#include "perfetto/base/utils.h"
 
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 using testing::_;
 using testing::NiceMock;
diff --git a/src/perfetto_cmd/trigger_perfetto.cc b/src/perfetto_cmd/trigger_perfetto.cc
index cd22ea2..c6e3a14 100644
--- a/src/perfetto_cmd/trigger_perfetto.cc
+++ b/src/perfetto_cmd/trigger_perfetto.cc
@@ -20,8 +20,8 @@
 #include <vector>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/unix_task_runner.h"
-#include "perfetto/ext/traced/traced.h"
+#include "perfetto/base/unix_task_runner.h"
+#include "perfetto/traced/traced.h"
 #include "src/perfetto_cmd/trigger_producer.h"
 
 namespace perfetto {
diff --git a/src/perfetto_cmd/trigger_perfetto_main.cc b/src/perfetto_cmd/trigger_perfetto_main.cc
index 01173bf..3ba5581 100644
--- a/src/perfetto_cmd/trigger_perfetto_main.cc
+++ b/src/perfetto_cmd/trigger_perfetto_main.cc
@@ -15,7 +15,7 @@
  */
 
 #include <stdio.h>
-#include "perfetto/ext/traced/traced.h"
+#include "perfetto/traced/traced.h"
 
 int main(int argc, char** argv) {
   return perfetto::TriggerPerfettoMain(argc, argv);
diff --git a/src/perfetto_cmd/trigger_producer.cc b/src/perfetto_cmd/trigger_producer.cc
index b121c6a..c84716f 100644
--- a/src/perfetto_cmd/trigger_producer.cc
+++ b/src/perfetto_cmd/trigger_producer.cc
@@ -19,9 +19,9 @@
 #include <memory>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/tracing/core/producer.h"
-#include "perfetto/ext/tracing/ipc/default_socket.h"
-#include "perfetto/ext/tracing/ipc/producer_ipc_client.h"
+#include "perfetto/tracing/core/producer.h"
+#include "perfetto/tracing/ipc/producer_ipc_client.h"
+#include "src/tracing/ipc/default_socket.h"
 
 namespace perfetto {
 
diff --git a/src/perfetto_cmd/trigger_producer.h b/src/perfetto_cmd/trigger_producer.h
index d12c178..6abab0e 100644
--- a/src/perfetto_cmd/trigger_producer.h
+++ b/src/perfetto_cmd/trigger_producer.h
@@ -21,9 +21,9 @@
 #include <vector>
 
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/tracing/core/producer.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
+#include "perfetto/base/weak_ptr.h"
+#include "perfetto/tracing/core/producer.h"
+#include "perfetto/tracing/core/tracing_service.h"
 
 namespace perfetto {
 
diff --git a/src/profiling/memory/BUILD.gn b/src/profiling/memory/BUILD.gn
index 9ef32c2..44fbce6 100644
--- a/src/profiling/memory/BUILD.gn
+++ b/src/profiling/memory/BUILD.gn
@@ -12,74 +12,22 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../gn/fuzzer.gni")
 import("../../../gn/perfetto.gni")
-import("../../../gn/test.gni")
+import("../../../gn/fuzzer.gni")
+import("//build_overrides/build.gni")
 
-assert(enable_perfetto_heapprofd)
-
-# The Android heap profiling daemon.
-executable("heapprofd") {
-  deps = [
-    "../../../gn:default_deps",
-    "../../../protos/perfetto/trace:zero",
-    "../../../src/base",
-    "../../../src/base:unix_socket",
-    "../../../src/profiling/memory:daemon",
-    "../../../src/profiling/memory:wire_protocol",
-    "../../../src/tracing:ipc",
-  ]
-  sources = [
-    "main.cc",
-  ]
+# For use_libfuzzer.
+if (!build_with_chromium) {
+  import("//gn/standalone/sanitizers/vars.gni")
+} else {
+  import("//build/config/sanitizers/sanitizers.gni")
 }
 
-# This library gets loaded into (and executes in) arbitrary android processes.
-# Logging must be non-allocating. This is achieved by defining
-# PERFETTO_ANDROID_ASYNC_SAFE_LOG, which needs to be set for all perfetto code
-# being compiled for this library. When generating Android.bp, the |cflags|
-# entry on this target is sufficient (as all sources are flattened into a
-# single bp target). However this is not correctly reflected in the gn
-# structure (which is a tree of targets) as the dependencies would not pick
-# up the flag (and thus use the wrong logging macro).
-#
-# This builds only in the Android tree, when using the generated Android.bp.
-if (perfetto_build_with_android) {
-  shared_library("heapprofd_client") {
-    configs -= [ "//gn/standalone:android_liblog" ]
-    cflags = [ "-DPERFETTO_ANDROID_ASYNC_SAFE_LOG" ]
-    deps = [
-      ":malloc_hooks",
-    ]
-  }
-
-  # This will export publicly visible symbols for the malloc_hooks.
-  source_set("malloc_hooks") {
-    deps = [
-      ":client",
-      ":proc_utils",
-      ":scoped_spinlock",
-      ":wire_protocol",
-      "../../../gn:default_deps",
-      "../../base",
-      "../../base:unix_socket",
-    ]
-    cflags = [
-      "-isystem",
-      rebase_path("../../../buildtools/bionic/libc", root_build_dir),
-    ]
-    sources = [
-      "malloc_hooks.cc",
-    ]
-  }
-}  # if (perfetto_build_with_android)
-
 source_set("wire_protocol") {
-  public_deps = [
-    "../../../gn:libunwindstack",
-  ]
+  public_configs = [ "../../../buildtools:libunwindstack_config" ]
   deps = [
     ":ring_buffer",
+    "../../../buildtools:libunwindstack",
     "../../../gn:default_deps",
     "../../base",
     "../../base:unix_socket",
@@ -93,7 +41,6 @@
 source_set("proc_utils") {
   deps = [
     "../../../gn:default_deps",
-    "../../../include/perfetto/profiling:normalize",
     "../../base",
   ]
   sources = [
@@ -130,7 +77,7 @@
   deps = [
     ":ring_buffer",
     "../../../gn:default_deps",
-    "../../../gn:gtest_and_gmock",
+    "../../../gn:gtest_deps",
     "../../base",
   ]
   sources = [
@@ -139,60 +86,49 @@
 }
 
 source_set("daemon") {
+  public_configs = [ "../../../buildtools:libunwindstack_config" ]
   deps = [
     ":proc_utils",
     ":ring_buffer",
     ":scoped_spinlock",
     ":wire_protocol",
+    "../../../buildtools:libunwindstack",
     "../../../gn:default_deps",
-    "../../../protos/perfetto/config/profiling:lite",
     "../../base",
     "../../base:unix_socket",
     "../../tracing",
     "../../tracing:ipc",
   ]
   public_deps = [
-    "../../../gn:libunwindstack",
-    "../../../protos/perfetto/config/profiling:cpp",
     "../../../protos/perfetto/trace:zero",
-    "../../../protos/perfetto/trace/interned_data:zero",
     "../../../protos/perfetto/trace/profiling:zero",
   ]
   sources = [
     "bookkeeping.cc",
     "bookkeeping.h",
-    "bookkeeping_dump.cc",
-    "bookkeeping_dump.h",
     "heapprofd_producer.cc",
     "heapprofd_producer.h",
     "interner.h",
-    "java_hprof_producer.cc",
-    "java_hprof_producer.h",
-    "page_idle_checker.cc",
-    "page_idle_checker.h",
     "system_property.cc",
     "system_property.h",
     "unwinding.cc",
     "unwinding.h",
     "unwound_messages.h",
-    "utils.cc",
-    "utils.h",
   ]
 }
 
 source_set("client") {
+  public_configs = [ "../../../buildtools:libunwindstack_config" ]
   deps = [
     ":proc_utils",
     ":ring_buffer",
     ":scoped_spinlock",
     ":wire_protocol",
+    "../../../buildtools:libunwindstack",
     "../../../gn:default_deps",
     "../../base",
     "../../base:unix_socket",
   ]
-  public_deps = [
-    "../../../gn:libunwindstack",
-  ]
   sources = [
     "client.cc",
     "client.h",
@@ -200,7 +136,8 @@
   ]
 }
 
-perfetto_unittest_source_set("unittests") {
+source_set("unittests") {
+  public_configs = [ "../../../buildtools:libunwindstack_config" ]
   testonly = true
   deps = [
     ":client",
@@ -208,9 +145,7 @@
     ":proc_utils",
     ":wire_protocol",
     "../../../gn:default_deps",
-    "../../../gn:gtest_and_gmock",
-    "../../../gn:libunwindstack",
-    "../../../include/perfetto/profiling:normalize",
+    "../../../gn:gtest_deps",
     "../../base",
     "../../base:test_support",
     "../../tracing",
@@ -220,7 +155,6 @@
     "client_unittest.cc",
     "heapprofd_producer_unittest.cc",
     "interner_unittest.cc",
-    "page_idle_checker_unittest.cc",
     "proc_utils_unittest.cc",
     "sampler_unittest.cc",
     "system_property_unittest.cc",
@@ -230,16 +164,14 @@
 }
 
 source_set("end_to_end_tests") {
+  public_configs = [ "../../../buildtools:libunwindstack_config" ]
   testonly = true
   deps = [
     ":client",
     ":daemon",
     ":wire_protocol",
     "../../../gn:default_deps",
-    "../../../gn:gtest_and_gmock",
-    "../../../gn:libunwindstack",
-    "../../../include/perfetto/protozero",
-    "../../../protos/perfetto/config/profiling:zero",
+    "../../../gn:gtest_deps",
     "../../../test:test_helper",
     "../../base",
     "../../base:test_support",
@@ -252,6 +184,26 @@
   }
 }
 
+# This will export publicly visibile symbols for the malloc_hooks.
+source_set("malloc_hooks") {
+  deps = [
+    ":client",
+    ":proc_utils",
+    ":scoped_spinlock",
+    ":wire_protocol",
+    "../../../gn:default_deps",
+    "../../base",
+    "../../base:unix_socket",
+  ]
+  cflags = [
+    "-isystem",
+    rebase_path("../../../buildtools/bionic/libc", root_build_dir),
+  ]
+  sources = [
+    "malloc_hooks.cc",
+  ]
+}
+
 perfetto_fuzzer_test("unwinding_fuzzer") {
   testonly = true
   sources = [
diff --git a/src/profiling/memory/CHANGELOG.md b/src/profiling/memory/CHANGELOG.md
deleted file mode 100644
index 56f64b5..0000000
--- a/src/profiling/memory/CHANGELOG.md
+++ /dev/null
@@ -1,12 +0,0 @@
-# Changes from Android 10
-
-## New features
-* Allow to specify whether profiling should only be done for existing processes
-  or only for newly spawned ones using `no_startup` or `no_running` in
-  `HeapprofdConfig`.
-* Allow to get the number of bytes that were allocated at a callstack but then
-  not used.
-* Allow to dump the maximum, rather than at the time of the dump.
-
-## Bugfixes
-* Fixed heapprofd on x86.
diff --git a/src/profiling/memory/bookkeeping.cc b/src/profiling/memory/bookkeeping.cc
index bd6ee97..04cc33d 100644
--- a/src/profiling/memory/bookkeeping.cc
+++ b/src/profiling/memory/bookkeeping.cc
@@ -21,17 +21,32 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/base/scoped_file.h"
 
 namespace perfetto {
 namespace profiling {
+namespace {
+using ::perfetto::protos::pbzero::ProfilePacket;
+// This needs to be lower than the maximum acceptable chunk size, because this
+// is checked *before* writing another submessage. We conservatively assume
+// submessages can be up to 100k here for a 500k chunk size.
+// DropBox has a 500k chunk limit, and each chunk needs to parse as a proto.
+uint32_t kPacketSizeThreshold = 400000;
+}
+
+GlobalCallstackTrie::Node* GlobalCallstackTrie::Node::GetOrCreateChild(
+    const Interned<Frame>& loc) {
+  Node* child = children_.Get(loc);
+  if (!child)
+    child = children_.Emplace(loc, this);
+  return child;
+}
 
 void HeapTracker::RecordMalloc(const std::vector<FrameData>& callstack,
                                uint64_t address,
-                               uint64_t sample_size,
-                               uint64_t alloc_size,
+                               uint64_t size,
                                uint64_t sequence_number,
                                uint64_t timestamp) {
   auto it = allocations_.find(address);
@@ -50,20 +65,19 @@
       if (alloc.sequence_number > committed_sequence_number_) {
         // Only count the previous allocation if it hasn't already been
         // committed to avoid double counting it.
-        AddToCallstackAllocations(timestamp, alloc);
+        alloc.AddToCallstackAllocations();
       }
 
-      SubtractFromCallstackAllocations(alloc);
+      alloc.SubtractFromCallstackAllocations();
       GlobalCallstackTrie::Node* node = callsites_->CreateCallsite(callstack);
-      alloc.sample_size = sample_size;
-      alloc.alloc_size = alloc_size;
+      alloc.total_size = size;
       alloc.sequence_number = sequence_number;
       alloc.SetCallstackAllocations(MaybeCreateCallstackAllocations(node));
     }
   } else {
     GlobalCallstackTrie::Node* node = callsites_->CreateCallsite(callstack);
     allocations_.emplace(address,
-                         Allocation(sample_size, alloc_size, sequence_number,
+                         Allocation(size, sequence_number,
                                     MaybeCreateCallstackAllocations(node)));
   }
 
@@ -103,9 +117,9 @@
 
   Allocation& value = leaf_it->second;
   if (value.sequence_number == sequence_number) {
-    AddToCallstackAllocations(operation.timestamp, value);
+    value.AddToCallstackAllocations();
   } else if (value.sequence_number < sequence_number) {
-    SubtractFromCallstackAllocations(value);
+    value.SubtractFromCallstackAllocations();
     allocations_.erase(leaf_it);
   }
   // else (value.sequence_number > sequence_number:
@@ -116,8 +130,54 @@
   //  be treated as a no-op.
 }
 
+void HeapTracker::Dump(
+    std::function<void(ProfilePacket::ProcessHeapSamples*)> fill_process_header,
+    DumpState* dump_state) {
+  // There are two reasons we remove the unused callstack allocations on the
+  // next iteration of Dump:
+  // * We need to remove them after the callstacks were dumped, which currently
+  //   happens after the allocations are dumped.
+  // * This way, we do not destroy and recreate callstacks as frequently.
+  for (auto it_and_alloc : dead_callstack_allocations_) {
+    auto& it = it_and_alloc.first;
+    uint64_t allocated = it_and_alloc.second;
+    const CallstackAllocations& alloc = it->second;
+    if (alloc.allocs == 0 && alloc.allocation_count == allocated)
+      callstack_allocations_.erase(it);
+  }
+  dead_callstack_allocations_.clear();
+
+  if (dump_state->currently_written() > kPacketSizeThreshold)
+    dump_state->NewProfilePacket();
+
+  ProfilePacket::ProcessHeapSamples* proto =
+      dump_state->current_profile_packet->add_process_dumps();
+  fill_process_header(proto);
+  proto->set_timestamp(committed_timestamp_);
+  for (auto it = callstack_allocations_.begin();
+       it != callstack_allocations_.end(); ++it) {
+    if (dump_state->currently_written() > kPacketSizeThreshold) {
+      dump_state->NewProfilePacket();
+      proto = dump_state->current_profile_packet->add_process_dumps();
+      fill_process_header(proto);
+      proto->set_timestamp(committed_timestamp_);
+    }
+
+    const CallstackAllocations& alloc = it->second;
+    dump_state->callstacks_to_dump.emplace(alloc.node);
+    ProfilePacket::HeapSample* sample = proto->add_samples();
+    sample->set_callstack_id(alloc.node->id());
+    sample->set_self_allocated(alloc.allocated);
+    sample->set_self_freed(alloc.freed);
+    sample->set_alloc_count(alloc.allocation_count);
+    sample->set_free_count(alloc.free_count);
+
+    if (alloc.allocs == 0)
+      dead_callstack_allocations_.emplace_back(it, alloc.allocation_count);
+  }
+}
+
 uint64_t HeapTracker::GetSizeForTesting(const std::vector<FrameData>& stack) {
-  PERFETTO_DCHECK(!dump_at_max_mode_);
   GlobalCallstackTrie::Node* node = callsites_->CreateCallsite(stack);
   // Hack to make it go away again if it wasn't used before.
   // This is only good because this is used for testing only.
@@ -128,31 +188,7 @@
     return 0;
   }
   const CallstackAllocations& alloc = it->second;
-  return alloc.value.totals.allocated - alloc.value.totals.freed;
-}
-
-uint64_t HeapTracker::GetMaxForTesting(const std::vector<FrameData>& stack) {
-  PERFETTO_DCHECK(dump_at_max_mode_);
-  GlobalCallstackTrie::Node* node = callsites_->CreateCallsite(stack);
-  // Hack to make it go away again if it wasn't used before.
-  // This is only good because this is used for testing only.
-  GlobalCallstackTrie::IncrementNode(node);
-  GlobalCallstackTrie::DecrementNode(node);
-  auto it = callstack_allocations_.find(node);
-  if (it == callstack_allocations_.end()) {
-    return 0;
-  }
-  const CallstackAllocations& alloc = it->second;
-  return alloc.value.retain_max.max;
-}
-
-GlobalCallstackTrie::Node* GlobalCallstackTrie::GetOrCreateChild(
-    Node* self,
-    const Interned<Frame>& loc) {
-  Node* child = self->children_.Get(loc);
-  if (!child)
-    child = self->children_.Emplace(loc, ++next_callstack_id_, self);
-  return child;
+  return alloc.allocated - alloc.freed;
 }
 
 std::vector<Interned<Frame>> GlobalCallstackTrie::BuildCallstack(
@@ -169,7 +205,7 @@
     const std::vector<FrameData>& callstack) {
   Node* node = &root_;
   for (const FrameData& loc : callstack) {
-    node = GetOrCreateChild(node, InternCodeLocation(loc));
+    node = node->GetOrCreateChild(InternCodeLocation(loc));
   }
   return node;
 }
@@ -198,8 +234,7 @@
 
 Interned<Frame> GlobalCallstackTrie::InternCodeLocation(const FrameData& loc) {
   Mapping map(string_interner_.Intern(loc.build_id));
-  map.exact_offset = loc.frame.map_exact_offset;
-  map.start_offset = loc.frame.map_elf_start_offset;
+  map.offset = loc.frame.map_elf_start_offset;
   map.start = loc.frame.map_start;
   map.end = loc.frame.map_end;
   map.load_bias = loc.frame.map_load_bias;
@@ -223,5 +258,59 @@
   return frame_interner_.Intern(frame);
 }
 
+void DumpState::WriteMap(const Interned<Mapping> map) {
+  auto map_it_and_inserted = dumped_mappings.emplace(map.id());
+  if (map_it_and_inserted.second) {
+    for (const Interned<std::string>& str : map->path_components)
+      WriteString(str);
+
+    WriteString(map->build_id);
+
+    if (currently_written() > kPacketSizeThreshold)
+      NewProfilePacket();
+
+    auto mapping = current_profile_packet->add_mappings();
+    mapping->set_id(map.id());
+    mapping->set_offset(map->offset);
+    mapping->set_start(map->start);
+    mapping->set_end(map->end);
+    mapping->set_load_bias(map->load_bias);
+    mapping->set_build_id(map->build_id.id());
+    for (const Interned<std::string>& str : map->path_components)
+      mapping->add_path_string_ids(str.id());
+  }
+}
+
+void DumpState::WriteFrame(Interned<Frame> frame) {
+  WriteMap(frame->mapping);
+  WriteString(frame->function_name);
+  bool inserted;
+  std::tie(std::ignore, inserted) = dumped_frames.emplace(frame.id());
+  if (inserted) {
+    if (currently_written() > kPacketSizeThreshold)
+      NewProfilePacket();
+
+    auto frame_proto = current_profile_packet->add_frames();
+    frame_proto->set_id(frame.id());
+    frame_proto->set_function_name_id(frame->function_name.id());
+    frame_proto->set_mapping_id(frame->mapping.id());
+    frame_proto->set_rel_pc(frame->rel_pc);
+  }
+}
+
+void DumpState::WriteString(const Interned<std::string>& str) {
+  bool inserted;
+  std::tie(std::ignore, inserted) = dumped_strings.emplace(str.id());
+  if (inserted) {
+    if (currently_written() > kPacketSizeThreshold)
+      NewProfilePacket();
+
+    auto interned_string = current_profile_packet->add_strings();
+    interned_string->set_id(str.id());
+    interned_string->set_str(reinterpret_cast<const uint8_t*>(str->c_str()),
+                             str->size());
+  }
+}
+
 }  // namespace profiling
 }  // namespace perfetto
diff --git a/src/profiling/memory/bookkeeping.h b/src/profiling/memory/bookkeeping.h
index c157e07..fe706ca 100644
--- a/src/profiling/memory/bookkeeping.h
+++ b/src/profiling/memory/bookkeeping.h
@@ -17,13 +17,17 @@
 #ifndef SRC_PROFILING_MEMORY_BOOKKEEPING_H_
 #define SRC_PROFILING_MEMORY_BOOKKEEPING_H_
 
+#include <functional>
 #include <map>
 #include <string>
 #include <vector>
 
+#include "perfetto/base/lookup_set.h"
+#include "perfetto/base/string_splitter.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/lookup_set.h"
-#include "perfetto/ext/base/string_splitter.h"
+#include "perfetto/trace/profiling/profile_packet.pbzero.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/tracing/core/trace_writer.h"
 #include "src/profiling/memory/interner.h"
 #include "src/profiling/memory/unwound_messages.h"
 
@@ -97,26 +101,21 @@
   Mapping(Interned<std::string> b) : build_id(std::move(b)) {}
 
   Interned<std::string> build_id;
-  uint64_t exact_offset = 0;
-  uint64_t start_offset = 0;
+  uint64_t offset = 0;
   uint64_t start = 0;
   uint64_t end = 0;
   uint64_t load_bias = 0;
   std::vector<Interned<std::string>> path_components{};
 
   bool operator<(const Mapping& other) const {
-    return std::tie(build_id, exact_offset, start_offset, start, end, load_bias,
-                    path_components) <
-           std::tie(other.build_id, other.exact_offset, other.start_offset,
-                    other.start, other.end, other.load_bias,
-                    other.path_components);
+    return std::tie(build_id, offset, start, end, load_bias, path_components) <
+           std::tie(other.build_id, other.offset, other.start, other.end,
+                    other.load_bias, other.path_components);
   }
   bool operator==(const Mapping& other) const {
-    return std::tie(build_id, exact_offset, start_offset, start, end, load_bias,
-                    path_components) ==
-           std::tie(other.build_id, other.exact_offset, other.start_offset,
-                    other.start, other.end, other.load_bias,
-                    other.path_components);
+    return std::tie(build_id, offset, start, end, load_bias, path_components) ==
+           std::tie(other.build_id, other.offset, other.start, other.end,
+                    other.load_bias, other.path_components);
   }
 };
 
@@ -167,19 +166,16 @@
     // This is opaque except to GlobalCallstackTrie.
     friend class GlobalCallstackTrie;
 
-    Node(Interned<Frame> frame) : Node(std::move(frame), 0, nullptr) {}
-    Node(Interned<Frame> frame, uint64_t id)
-        : Node(std::move(frame), id, nullptr) {}
-    Node(Interned<Frame> frame, uint64_t id, Node* parent)
-        : id_(id), parent_(parent), location_(std::move(frame)) {}
+    Node(Interned<Frame> frame) : Node(std::move(frame), nullptr) {}
+    Node(Interned<Frame> frame, Node* parent)
+        : parent_(parent), location_(std::move(frame)) {}
 
-    uint64_t id() const { return id_; }
+    uintptr_t id() const { return reinterpret_cast<uintptr_t>(this); }
 
    private:
     Node* GetOrCreateChild(const Interned<Frame>& loc);
 
     uint64_t ref_count_ = 0;
-    uint64_t id_;
     Node* const parent_;
     const Interned<Frame> location_;
     base::LookupSet<Node, const Interned<Frame>, &Node::location_> children_;
@@ -189,10 +185,6 @@
   GlobalCallstackTrie(const GlobalCallstackTrie&) = delete;
   GlobalCallstackTrie& operator=(const GlobalCallstackTrie&) = delete;
 
-  // Moving this would invalidate the back pointers to the root_ node.
-  GlobalCallstackTrie(GlobalCallstackTrie&&) = delete;
-  GlobalCallstackTrie& operator=(GlobalCallstackTrie&&) = delete;
-
   Node* CreateCallsite(const std::vector<FrameData>& locs);
   static void DecrementNode(Node* node);
   static void IncrementNode(Node* node);
@@ -200,8 +192,6 @@
   std::vector<Interned<Frame>> BuildCallstack(const Node* node) const;
 
  private:
-  Node* GetOrCreateChild(Node* self, const Interned<Frame>& loc);
-
   Interned<Frame> InternCodeLocation(const FrameData& loc);
   Interned<Frame> MakeRootFrame();
 
@@ -209,35 +199,101 @@
   Interner<Mapping> mapping_interner_;
   Interner<Frame> frame_interner_;
 
-  uint64_t next_callstack_id_ = 0;
+  Node root_{MakeRootFrame()};
+};
 
-  Node root_{MakeRootFrame(), ++next_callstack_id_};
+struct DumpState {
+  DumpState(TraceWriter* tw, uint64_t* ni) : trace_writer(tw), next_index(ni) {
+    last_written = trace_writer->written();
+
+    current_trace_packet = trace_writer->NewTracePacket();
+    current_trace_packet->set_timestamp(
+        static_cast<uint64_t>(base::GetBootTimeNs().count()));
+    current_profile_packet = current_trace_packet->set_profile_packet();
+    current_profile_packet->set_index((*next_index)++);
+
+    // Explicitly reserve intern ID 0 for the empty string, so unset string
+    // fields get mapped to this.
+    auto interned_string = current_profile_packet->add_strings();
+    constexpr const uint8_t kEmptyString[] = "";
+    interned_string->set_id(0);
+    interned_string->set_str(kEmptyString, 0);
+  }
+
+  void WriteMap(const Interned<Mapping> map);
+  void WriteFrame(const Interned<Frame> frame);
+  void WriteString(const Interned<std::string>& str);
+
+  std::set<InternID> dumped_strings;
+  std::set<InternID> dumped_frames;
+  std::set<InternID> dumped_mappings;
+
+  std::set<GlobalCallstackTrie::Node*> callstacks_to_dump;
+
+  TraceWriter* trace_writer;
+  protos::pbzero::ProfilePacket* current_profile_packet;
+  TraceWriter::TracePacketHandle current_trace_packet;
+  uint64_t* next_index;
+  uint64_t last_written = 0;
+
+  void NewProfilePacket() {
+    PERFETTO_DLOG("New profile packet after %" PRIu64 " bytes. Total: %" PRIu64
+                  ", before %" PRIu64,
+                  trace_writer->written() - last_written,
+                  trace_writer->written(), last_written);
+    current_profile_packet->set_continued(true);
+    last_written = trace_writer->written();
+
+    current_trace_packet->Finalize();
+    current_trace_packet = trace_writer->NewTracePacket();
+    current_trace_packet->set_timestamp(
+        static_cast<uint64_t>(base::GetBootTimeNs().count()));
+    current_profile_packet = current_trace_packet->set_profile_packet();
+    current_profile_packet->set_index((*next_index)++);
+  }
+
+  uint64_t currently_written() {
+    return trace_writer->written() - last_written;
+  }
 };
 
 // Snapshot for memory allocations of a particular process. Shares callsites
 // with other processes.
 class HeapTracker {
  public:
-  struct CallstackMaxAllocations {
-    uint64_t max;
-    uint64_t cur;
-  };
-  struct CallstackTotalAllocations {
-    uint64_t allocated;
-    uint64_t freed;
-  };
+  // Caller needs to ensure that callsites outlives the HeapTracker.
+  explicit HeapTracker(GlobalCallstackTrie* callsites)
+      : callsites_(callsites) {}
 
+  void RecordMalloc(const std::vector<FrameData>& stack,
+                    uint64_t address,
+                    uint64_t size,
+                    uint64_t sequence_number,
+                    uint64_t timestamp);
+  void Dump(
+      std::function<void(protos::pbzero::ProfilePacket::ProcessHeapSamples*)>
+          fill_process_header,
+      DumpState* dump_state);
+  void RecordFree(uint64_t address,
+                  uint64_t sequence_number,
+                  uint64_t timestamp) {
+    RecordOperation(sequence_number, {address, timestamp});
+  }
+
+  uint64_t GetSizeForTesting(const std::vector<FrameData>& stack);
+  uint64_t GetTimestampForTesting() { return committed_timestamp_; }
+
+ private:
   // Sum of all the allocations for a given callstack.
   struct CallstackAllocations {
     CallstackAllocations(GlobalCallstackTrie::Node* n) : node(n) {}
 
     uint64_t allocs = 0;
+
+    uint64_t allocated = 0;
+    uint64_t freed = 0;
     uint64_t allocation_count = 0;
     uint64_t free_count = 0;
-    union {
-      CallstackMaxAllocations retain_max;
-      CallstackTotalAllocations totals;
-    } value = {};
 
     GlobalCallstackTrie::Node* const node;
 
@@ -248,85 +304,31 @@
     }
   };
 
-  // Caller needs to ensure that callsites outlives the HeapTracker.
-  explicit HeapTracker(GlobalCallstackTrie* callsites, bool dump_at_max_mode)
-      : callsites_(callsites), dump_at_max_mode_(dump_at_max_mode) {}
-
-  void RecordMalloc(const std::vector<FrameData>& stack,
-                    uint64_t address,
-                    uint64_t sample_size,
-                    uint64_t alloc_size,
-                    uint64_t sequence_number,
-                    uint64_t timestamp);
-
-  template <typename F>
-  void GetCallstackAllocations(F fn) {
-    // There are two reasons we remove the unused callstack allocations on the
-    // next iteration of Dump:
-    // * We need to remove them after the callstacks were dumped, which
-    //   currently happens after the allocations are dumped.
-    // * This way, we do not destroy and recreate callstacks as frequently.
-    for (auto it_and_alloc : dead_callstack_allocations_) {
-      auto& it = it_and_alloc.first;
-      uint64_t allocated = it_and_alloc.second;
-      const CallstackAllocations& alloc = it->second;
-      if (alloc.allocs == 0 && alloc.allocation_count == allocated)
-        callstack_allocations_.erase(it);
-    }
-    dead_callstack_allocations_.clear();
-
-    for (auto it = callstack_allocations_.begin();
-         it != callstack_allocations_.end(); ++it) {
-      const CallstackAllocations& alloc = it->second;
-      fn(alloc);
-
-      if (alloc.allocs == 0)
-        dead_callstack_allocations_.emplace_back(it, alloc.allocation_count);
-    }
-  }
-
-  template <typename F>
-  void GetAllocations(F fn) {
-    for (const auto& addr_and_allocation : allocations_) {
-      const Allocation& alloc = addr_and_allocation.second;
-      fn(addr_and_allocation.first, alloc.sample_size, alloc.alloc_size,
-         alloc.callstack_allocations()->node->id());
-    }
-  }
-
-  void RecordFree(uint64_t address,
-                  uint64_t sequence_number,
-                  uint64_t timestamp) {
-    RecordOperation(sequence_number, {address, timestamp});
-  }
-
-  uint64_t committed_timestamp() { return committed_timestamp_; }
-  uint64_t max_timestamp() { return max_timestamp_; }
-
-  uint64_t GetSizeForTesting(const std::vector<FrameData>& stack);
-  uint64_t GetMaxForTesting(const std::vector<FrameData>& stack);
-  uint64_t GetTimestampForTesting() { return committed_timestamp_; }
-
- private:
   struct Allocation {
-    Allocation(uint64_t size,
-               uint64_t asize,
-               uint64_t seq,
-               CallstackAllocations* csa)
-        : sample_size(size), alloc_size(asize), sequence_number(seq) {
+    Allocation(uint64_t size, uint64_t seq, CallstackAllocations* csa)
+        : total_size(size), sequence_number(seq) {
       SetCallstackAllocations(csa);
     }
 
     Allocation() = default;
     Allocation(const Allocation&) = delete;
     Allocation(Allocation&& other) noexcept {
-      sample_size = other.sample_size;
-      alloc_size = other.alloc_size;
+      total_size = other.total_size;
       sequence_number = other.sequence_number;
       callstack_allocations_ = other.callstack_allocations_;
       other.callstack_allocations_ = nullptr;
     }
 
+    void AddToCallstackAllocations() {
+      callstack_allocations_->allocation_count++;
+      callstack_allocations_->allocated += total_size;
+    }
+
+    void SubtractFromCallstackAllocations() {
+      callstack_allocations_->free_count++;
+      callstack_allocations_->freed += total_size;
+    }
+
     ~Allocation() { SetCallstackAllocations(nullptr); }
 
     void SetCallstackAllocations(CallstackAllocations* callstack_allocations) {
@@ -341,8 +343,7 @@
       return callstack_allocations_;
     }
 
-    uint64_t sample_size;
-    uint64_t alloc_size;
+    uint64_t total_size;
     uint64_t sequence_number;
 
    private:
@@ -381,48 +382,6 @@
   void CommitOperation(uint64_t sequence_number,
                        const PendingOperation& operation);
 
-  void AddToCallstackAllocations(uint64_t ts, const Allocation& alloc) {
-    alloc.callstack_allocations()->allocation_count++;
-    if (dump_at_max_mode_) {
-      current_unfreed_ += alloc.sample_size;
-      alloc.callstack_allocations()->value.retain_max.cur += alloc.sample_size;
-
-      if (current_unfreed_ <= max_unfreed_)
-        return;
-
-      if (max_sequence_number_ == alloc.sequence_number - 1) {
-        alloc.callstack_allocations()->value.retain_max.max =
-            // We know the only CallstackAllocation that has max != cur is the
-            // one we just updated.
-            alloc.callstack_allocations()->value.retain_max.cur;
-      } else {
-        for (auto& p : callstack_allocations_) {
-          // We need to reset max = cur for every CallstackAllocation, as we
-          // do not know which ones have changed since the last max.
-          // TODO(fmayer): Add an index to speed this up
-          CallstackAllocations& csa = p.second;
-          csa.value.retain_max.max = csa.value.retain_max.cur;
-        }
-      }
-      max_sequence_number_ = alloc.sequence_number;
-      max_unfreed_ = current_unfreed_;
-      max_timestamp_ = ts;
-    } else {
-      alloc.callstack_allocations()->value.totals.allocated +=
-          alloc.sample_size;
-    }
-  }
-
-  void SubtractFromCallstackAllocations(const Allocation& alloc) {
-    alloc.callstack_allocations()->free_count++;
-    if (dump_at_max_mode_) {
-      current_unfreed_ -= alloc.sample_size;
-      alloc.callstack_allocations()->value.retain_max.cur -= alloc.sample_size;
-    } else {
-      alloc.callstack_allocations()->value.totals.freed += alloc.sample_size;
-    }
-  }
-
   // We cannot use an interner here, because after the last allocation goes
   // away, we still need to keep the CallstackAllocations around until the next
   // dump.
@@ -448,13 +407,6 @@
   // The sequence number all mallocs and frees have been handled up to.
   uint64_t committed_sequence_number_ = 0;
   GlobalCallstackTrie* callsites_;
-
-  const bool dump_at_max_mode_ = false;
-  // The following members are only used if dump_at_max_mode_ == true.
-  uint64_t max_sequence_number_ = 0;
-  uint64_t current_unfreed_ = 0;
-  uint64_t max_unfreed_ = 0;
-  uint64_t max_timestamp_ = 0;
 };
 
 }  // namespace profiling
@@ -468,8 +420,7 @@
   result_type operator()(const argument_type& mapping) {
     size_t h =
         std::hash<::perfetto::profiling::InternID>{}(mapping.build_id.id());
-    h ^= std::hash<uint64_t>{}(mapping.exact_offset);
-    h ^= std::hash<uint64_t>{}(mapping.start_offset);
+    h ^= std::hash<uint64_t>{}(mapping.offset);
     h ^= std::hash<uint64_t>{}(mapping.start);
     h ^= std::hash<uint64_t>{}(mapping.end);
     h ^= std::hash<uint64_t>{}(mapping.load_bias);
diff --git a/src/profiling/memory/bookkeeping_dump.cc b/src/profiling/memory/bookkeeping_dump.cc
deleted file mode 100644
index 6f72074..0000000
--- a/src/profiling/memory/bookkeeping_dump.cc
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/profiling/memory/bookkeeping_dump.h"
-
-namespace perfetto {
-namespace profiling {
-namespace {
-using ::perfetto::protos::pbzero::Callstack;
-using ::perfetto::protos::pbzero::ProfilePacket;
-// This needs to be lower than the maximum acceptable chunk size, because this
-// is checked *before* writing another submessage. We conservatively assume
-// submessages can be up to 100k here for a 500k chunk size.
-// DropBox has a 500k chunk limit, and each chunk needs to parse as a proto.
-uint32_t kPacketSizeThreshold = 400000;
-}  // namespace
-
-void WriteFixedInternings(TraceWriter* trace_writer) {
-  constexpr const uint8_t kEmptyString[] = "";
-  // Explicitly reserve intern ID 0 for the empty string, so unset string
-  // fields get mapped to this.
-  auto packet = trace_writer->NewTracePacket();
-  auto* interned_data = packet->set_interned_data();
-  auto interned_string = interned_data->add_build_ids();
-  interned_string->set_iid(0);
-  interned_string->set_str(kEmptyString, 0);
-
-  interned_string = interned_data->add_mapping_paths();
-  interned_string->set_iid(0);
-  interned_string->set_str(kEmptyString, 0);
-
-  interned_string = interned_data->add_function_names();
-  interned_string->set_iid(0);
-  interned_string->set_str(kEmptyString, 0);
-
-  packet->set_incremental_state_cleared(true);
-}
-
-void DumpState::WriteMap(const Interned<Mapping> map) {
-  auto map_it_and_inserted = intern_state_->dumped_mappings_.emplace(map.id());
-  if (map_it_and_inserted.second) {
-    for (const Interned<std::string>& str : map->path_components)
-      WriteMappingPathString(str);
-
-    WriteBuildIDString(map->build_id);
-
-    auto mapping = GetCurrentInternedData()->add_mappings();
-    mapping->set_iid(map.id());
-    mapping->set_exact_offset(map->exact_offset);
-    mapping->set_start_offset(map->start_offset);
-    mapping->set_start(map->start);
-    mapping->set_end(map->end);
-    mapping->set_load_bias(map->load_bias);
-    mapping->set_build_id(map->build_id.id());
-    for (const Interned<std::string>& str : map->path_components)
-      mapping->add_path_string_ids(str.id());
-  }
-}
-
-void DumpState::WriteFrame(Interned<Frame> frame) {
-  WriteMap(frame->mapping);
-  WriteFunctionNameString(frame->function_name);
-  bool inserted;
-  std::tie(std::ignore, inserted) =
-      intern_state_->dumped_frames_.emplace(frame.id());
-  if (inserted) {
-    auto frame_proto = GetCurrentInternedData()->add_frames();
-    frame_proto->set_iid(frame.id());
-    frame_proto->set_function_name_id(frame->function_name.id());
-    frame_proto->set_mapping_id(frame->mapping.id());
-    frame_proto->set_rel_pc(frame->rel_pc);
-  }
-}
-
-void DumpState::WriteBuildIDString(const Interned<std::string>& str) {
-  auto it_and_inserted = intern_state_->dumped_strings_.emplace(str.id(), 0);
-  auto it = it_and_inserted.first;
-  // This is for the rare case that the same string is used as two different
-  // types (e.g. a function name that matches a path segment). In that case
-  // we need to emit the string as all of its types.
-  if ((it->second & kDumpedBuildID) == 0) {
-    auto interned_string = GetCurrentInternedData()->add_build_ids();
-    interned_string->set_iid(str.id());
-    interned_string->set_str(reinterpret_cast<const uint8_t*>(str->c_str()),
-                             str->size());
-    it->second |= kDumpedBuildID;
-  }
-}
-
-void DumpState::WriteMappingPathString(const Interned<std::string>& str) {
-  auto it_and_inserted = intern_state_->dumped_strings_.emplace(str.id(), 0);
-  auto it = it_and_inserted.first;
-  // This is for the rare case that the same string is used as two different
-  // types (e.g. a function name that matches a path segment). In that case
-  // we need to emit the string as all of its types.
-  if ((it->second & kDumpedMappingPath) == 0) {
-    auto interned_string = GetCurrentInternedData()->add_mapping_paths();
-    interned_string->set_iid(str.id());
-    interned_string->set_str(reinterpret_cast<const uint8_t*>(str->c_str()),
-                             str->size());
-    it->second |= kDumpedMappingPath;
-  }
-}
-
-void DumpState::WriteFunctionNameString(const Interned<std::string>& str) {
-  auto it_and_inserted = intern_state_->dumped_strings_.emplace(str.id(), 0);
-  auto it = it_and_inserted.first;
-  // This is for the rare case that the same string is used as two different
-  // types (e.g. a function name that matches a path segment). In that case
-  // we need to emit the string as all of its types.
-  if ((it->second & kDumpedFunctionName) == 0) {
-    auto interned_string = GetCurrentInternedData()->add_function_names();
-    interned_string->set_iid(str.id());
-    interned_string->set_str(reinterpret_cast<const uint8_t*>(str->c_str()),
-                             str->size());
-    it->second |= kDumpedFunctionName;
-  }
-}
-
-void DumpState::WriteAllocation(const HeapTracker::CallstackAllocations& alloc,
-                                bool dump_at_max_mode) {
-  if (intern_state_->dumped_callstacks_.find(alloc.node->id()) ==
-      intern_state_->dumped_callstacks_.end())
-    callstacks_to_dump_.emplace(alloc.node);
-
-  auto* heap_samples = GetCurrentProcessHeapSamples();
-  ProfilePacket::HeapSample* sample = heap_samples->add_samples();
-  sample->set_callstack_id(alloc.node->id());
-  if (dump_at_max_mode) {
-    sample->set_self_max(alloc.value.retain_max.max);
-  } else {
-    sample->set_self_allocated(alloc.value.totals.allocated);
-    sample->set_self_freed(alloc.value.totals.freed);
-  }
-  sample->set_alloc_count(alloc.allocation_count);
-  sample->set_free_count(alloc.free_count);
-
-  auto it = current_process_idle_allocs_.find(alloc.node->id());
-  if (it != current_process_idle_allocs_.end())
-    sample->set_self_idle(it->second);
-}
-
-void DumpState::DumpCallstacks(GlobalCallstackTrie* callsites) {
-  // We need a way to signal to consumers when they have fully consumed the
-  // InternedData they need to understand the sequence of continued
-  // ProfilePackets. The way we do that is to mark the last ProfilePacket as
-  // continued, then emit the InternedData, and then an empty ProfilePacket
-  // to terminate the sequence.
-  //
-  // This is why we set_continued at the beginning of this function, and
-  // MakeProfilePacket at the end.
-  if (current_trace_packet_)
-    current_profile_packet_->set_continued(true);
-  for (GlobalCallstackTrie::Node* node : callstacks_to_dump_) {
-    // There need to be two separate loops over built_callstack because
-    // protozero cannot interleave different messages.
-    auto built_callstack = callsites->BuildCallstack(node);
-    for (const Interned<Frame>& frame : built_callstack)
-      WriteFrame(frame);
-    Callstack* callstack = GetCurrentInternedData()->add_callstacks();
-    callstack->set_iid(node->id());
-    for (const Interned<Frame>& frame : built_callstack)
-      callstack->add_frame_ids(frame.id());
-
-    intern_state_->dumped_callstacks_.emplace(node->id());
-  }
-  MakeProfilePacket();
-}
-
-void DumpState::AddIdleBytes(uint64_t callstack_id, uint64_t bytes) {
-  current_process_idle_allocs_[callstack_id] += bytes;
-}
-
-ProfilePacket::ProcessHeapSamples* DumpState::GetCurrentProcessHeapSamples() {
-  if (currently_written() > kPacketSizeThreshold) {
-    if (current_profile_packet_)
-      current_profile_packet_->set_continued(true);
-    MakeProfilePacket();
-  }
-
-  if (current_process_heap_samples_ == nullptr) {
-    current_process_heap_samples_ =
-        current_profile_packet_->add_process_dumps();
-    current_process_fill_header_(current_process_heap_samples_);
-  }
-
-  return current_process_heap_samples_;
-}
-
-protos::pbzero::InternedData* DumpState::GetCurrentInternedData() {
-  if (currently_written() > kPacketSizeThreshold)
-    MakeTracePacket();
-
-  if (current_interned_data_ == nullptr)
-    current_interned_data_ = current_trace_packet_->set_interned_data();
-
-  return current_interned_data_;
-}
-
-}  // namespace profiling
-}  // namespace perfetto
diff --git a/src/profiling/memory/bookkeeping_dump.h b/src/profiling/memory/bookkeeping_dump.h
deleted file mode 100644
index 517d02c..0000000
--- a/src/profiling/memory/bookkeeping_dump.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_PROFILING_MEMORY_BOOKKEEPING_DUMP_H_
-#define SRC_PROFILING_MEMORY_BOOKKEEPING_DUMP_H_
-
-#include <functional>
-#include <set>
-
-#include <inttypes.h>
-
-#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
-#include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
-#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-#include "perfetto/ext/tracing/core/trace_writer.h"
-
-#include "src/profiling/memory/bookkeeping.h"
-#include "src/profiling/memory/interner.h"
-
-namespace perfetto {
-namespace profiling {
-
-void WriteFixedInternings(TraceWriter* trace_writer);
-
-constexpr int kDumpedBuildID = 1 << 0;
-constexpr int kDumpedMappingPath = 1 << 1;
-constexpr int kDumpedFunctionName = 1 << 2;
-
-class DumpState {
- public:
-  class InternState {
-   private:
-    friend class DumpState;
-
-    std::map<InternID, int> dumped_strings_;
-    std::set<InternID> dumped_frames_;
-    std::set<InternID> dumped_mappings_;
-    std::set<uint64_t> dumped_callstacks_;
-
-    uint64_t next_index_ = 0;
-  };
-
-  DumpState(
-      TraceWriter* trace_writer,
-      std::function<void(protos::pbzero::ProfilePacket::ProcessHeapSamples*)>
-          process_fill_header,
-      InternState* intern_state)
-      : trace_writer_(trace_writer),
-        intern_state_(intern_state),
-        current_process_fill_header_(std::move(process_fill_header)) {
-    MakeProfilePacket();
-  }
-
-  // This should be a temporary object, only used on the stack for dumping a
-  // single process.
-  DumpState(const DumpState&) = delete;
-  DumpState& operator=(const DumpState&) = delete;
-  DumpState(DumpState&&) = delete;
-  DumpState& operator=(DumpState&&) = delete;
-
-  void AddIdleBytes(uint64_t callstack_id, uint64_t bytes);
-
-  void WriteAllocation(const HeapTracker::CallstackAllocations& alloc,
-                       bool dump_at_max_mode);
-  void DumpCallstacks(GlobalCallstackTrie* callsites);
-
- private:
-  void WriteMap(const Interned<Mapping> map);
-  void WriteFrame(const Interned<Frame> frame);
-  void WriteBuildIDString(const Interned<std::string>& str);
-  void WriteMappingPathString(const Interned<std::string>& str);
-  void WriteFunctionNameString(const Interned<std::string>& str);
-
-  void MakeTracePacket() {
-    last_written_ = trace_writer_->written();
-
-    if (current_trace_packet_)
-      current_trace_packet_->Finalize();
-    current_trace_packet_ = trace_writer_->NewTracePacket();
-    current_trace_packet_->set_timestamp(
-        static_cast<uint64_t>(base::GetBootTimeNs().count()));
-    current_profile_packet_ = nullptr;
-    current_interned_data_ = nullptr;
-    current_process_heap_samples_ = nullptr;
-  }
-
-  void MakeProfilePacket() {
-    MakeTracePacket();
-
-    current_profile_packet_ = current_trace_packet_->set_profile_packet();
-    current_profile_packet_->set_index(intern_state_->next_index_++);
-  }
-
-  uint64_t currently_written() {
-    return trace_writer_->written() - last_written_;
-  }
-
-  protos::pbzero::ProfilePacket::ProcessHeapSamples*
-  GetCurrentProcessHeapSamples();
-  protos::pbzero::InternedData* GetCurrentInternedData();
-
-  std::set<GlobalCallstackTrie::Node*> callstacks_to_dump_;
-
-  TraceWriter* trace_writer_;
-  InternState* intern_state_;
-
-  protos::pbzero::ProfilePacket* current_profile_packet_ = nullptr;
-  protos::pbzero::InternedData* current_interned_data_ = nullptr;
-  TraceWriter::TracePacketHandle current_trace_packet_;
-  protos::pbzero::ProfilePacket::ProcessHeapSamples*
-      current_process_heap_samples_ = nullptr;
-  std::function<void(protos::pbzero::ProfilePacket::ProcessHeapSamples*)>
-      current_process_fill_header_;
-  std::map<uint64_t /* callstack_id */, uint64_t> current_process_idle_allocs_;
-
-  uint64_t last_written_ = 0;
-};
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // SRC_PROFILING_MEMORY_BOOKKEEPING_DUMP_H_
diff --git a/src/profiling/memory/bookkeeping_unittest.cc b/src/profiling/memory/bookkeeping_unittest.cc
index 940e23c..a990f65 100644
--- a/src/profiling/memory/bookkeeping_unittest.cc
+++ b/src/profiling/memory/bookkeeping_unittest.cc
@@ -16,7 +16,8 @@
 
 #include "src/profiling/memory/bookkeeping.h"
 
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace profiling {
@@ -52,118 +53,74 @@
   return res;
 }
 
-TEST(BookkeepingTest, EmptyStack) {
-  uint64_t sequence_number = 1;
-  GlobalCallstackTrie c;
-  HeapTracker hd(&c, false);
-
-  hd.RecordMalloc({}, 0x1, 5, 5, sequence_number, 100 * sequence_number);
-  sequence_number++;
-  hd.RecordFree(0x1, sequence_number, 100 * sequence_number);
-  hd.GetCallstackAllocations([](const HeapTracker::CallstackAllocations&) {});
-}
-
-TEST(BookkeepingTest, Replace) {
-  uint64_t sequence_number = 1;
-  GlobalCallstackTrie c;
-  HeapTracker hd(&c, false);
-
-  hd.RecordMalloc(stack(), 1, 5, 5, sequence_number, 100 * sequence_number);
-  sequence_number++;
-  hd.RecordMalloc(stack2(), 1, 2, 2, sequence_number, 100 * sequence_number);
-
-  // Call GetCallstackAllocations twice to force GC of old CallstackAllocations.
-  hd.GetCallstackAllocations([](const HeapTracker::CallstackAllocations&) {});
-  hd.GetCallstackAllocations([](const HeapTracker::CallstackAllocations&) {});
-}
-
 TEST(BookkeepingTest, Basic) {
   uint64_t sequence_number = 1;
   GlobalCallstackTrie c;
-  HeapTracker hd(&c, false);
+  HeapTracker hd(&c);
 
-  hd.RecordMalloc(stack(), 0x1, 5, 5, sequence_number, 100 * sequence_number);
+  hd.RecordMalloc(stack(), 1, 5, sequence_number, 100 * sequence_number);
   sequence_number++;
-  hd.RecordMalloc(stack2(), 0x2, 2, 2, sequence_number, 100 * sequence_number);
+  hd.RecordMalloc(stack2(), 2, 2, sequence_number, 100 * sequence_number);
   sequence_number++;
-  ASSERT_EQ(hd.GetSizeForTesting(stack()), 5u);
-  ASSERT_EQ(hd.GetSizeForTesting(stack2()), 2u);
+  ASSERT_EQ(hd.GetSizeForTesting(stack()), 5);
+  ASSERT_EQ(hd.GetSizeForTesting(stack2()), 2);
   ASSERT_EQ(hd.GetTimestampForTesting(), 100 * (sequence_number - 1));
-  hd.RecordFree(0x2, sequence_number, 100 * sequence_number);
+  hd.RecordFree(2, sequence_number, 100 * sequence_number);
   sequence_number++;
-  ASSERT_EQ(hd.GetSizeForTesting(stack()), 5u);
-  ASSERT_EQ(hd.GetSizeForTesting(stack2()), 0u);
+  ASSERT_EQ(hd.GetSizeForTesting(stack()), 5);
+  ASSERT_EQ(hd.GetSizeForTesting(stack2()), 0);
   ASSERT_EQ(hd.GetTimestampForTesting(), 100 * (sequence_number - 1));
-  hd.RecordFree(0x1, sequence_number, 100 * sequence_number);
+  hd.RecordFree(1, sequence_number, 100 * sequence_number);
   sequence_number++;
-  ASSERT_EQ(hd.GetSizeForTesting(stack()), 0u);
-  ASSERT_EQ(hd.GetSizeForTesting(stack2()), 0u);
+  ASSERT_EQ(hd.GetSizeForTesting(stack()), 0);
+  ASSERT_EQ(hd.GetSizeForTesting(stack2()), 0);
   ASSERT_EQ(hd.GetTimestampForTesting(), 100 * (sequence_number - 1));
 }
 
-TEST(BookkeepingTest, Max) {
-  uint64_t sequence_number = 1;
-  GlobalCallstackTrie c;
-  HeapTracker hd(&c, true);
-
-  hd.RecordMalloc(stack(), 0x1, 5, 5, sequence_number, 100 * sequence_number);
-  sequence_number++;
-  hd.RecordMalloc(stack2(), 0x2, 2, 2, sequence_number, 100 * sequence_number);
-  sequence_number++;
-  hd.RecordFree(0x2, sequence_number, 100 * sequence_number);
-  sequence_number++;
-  hd.RecordFree(0x1, sequence_number, 100 * sequence_number);
-  sequence_number++;
-  ASSERT_EQ(hd.max_timestamp(), 200u);
-  ASSERT_EQ(hd.GetMaxForTesting(stack()), 5u);
-  ASSERT_EQ(hd.GetMaxForTesting(stack2()), 2u);
-}
-
 TEST(BookkeepingTest, TwoHeapTrackers) {
   uint64_t sequence_number = 1;
   GlobalCallstackTrie c;
-  HeapTracker hd(&c, false);
+  HeapTracker hd(&c);
   {
-    HeapTracker hd2(&c, false);
+    HeapTracker hd2(&c);
 
-    hd.RecordMalloc(stack(), 0x1, 5, 5, sequence_number, 100 * sequence_number);
-    hd2.RecordMalloc(stack(), 0x2, 2, 2, sequence_number,
-                     100 * sequence_number);
+    hd.RecordMalloc(stack(), 1, 5, sequence_number, 100 * sequence_number);
+    hd2.RecordMalloc(stack(), 2, 2, sequence_number, 100 * sequence_number);
     sequence_number++;
-    ASSERT_EQ(hd2.GetSizeForTesting(stack()), 2u);
-    ASSERT_EQ(hd.GetSizeForTesting(stack()), 5u);
+    ASSERT_EQ(hd2.GetSizeForTesting(stack()), 2);
+    ASSERT_EQ(hd.GetSizeForTesting(stack()), 5);
     ASSERT_EQ(hd.GetTimestampForTesting(), 100 * (sequence_number - 1));
   }
-  ASSERT_EQ(hd.GetSizeForTesting(stack()), 5u);
+  ASSERT_EQ(hd.GetSizeForTesting(stack()), 5);
 }
 
 TEST(BookkeepingTest, ReplaceAlloc) {
   uint64_t sequence_number = 1;
   GlobalCallstackTrie c;
-  HeapTracker hd(&c, false);
+  HeapTracker hd(&c);
 
-  hd.RecordMalloc(stack(), 0x1, 5, 5, sequence_number, 100 * sequence_number);
+  hd.RecordMalloc(stack(), 1, 5, sequence_number, 100 * sequence_number);
   sequence_number++;
-  hd.RecordMalloc(stack2(), 0x1, 2, 2, sequence_number, 100 * sequence_number);
+  hd.RecordMalloc(stack2(), 1, 2, sequence_number, 100 * sequence_number);
   sequence_number++;
-  EXPECT_EQ(hd.GetSizeForTesting(stack()), 0u);
-  EXPECT_EQ(hd.GetSizeForTesting(stack2()), 2u);
+  EXPECT_EQ(hd.GetSizeForTesting(stack()), 0);
+  EXPECT_EQ(hd.GetSizeForTesting(stack2()), 2);
   ASSERT_EQ(hd.GetTimestampForTesting(), 100 * (sequence_number - 1));
 }
 
 TEST(BookkeepingTest, OutOfOrder) {
   GlobalCallstackTrie c;
-  HeapTracker hd(&c, false);
+  HeapTracker hd(&c);
 
-  hd.RecordMalloc(stack(), 0x1, 5, 5, 2, 2);
-  hd.RecordMalloc(stack2(), 0x1, 2, 2, 1, 1);
-  EXPECT_EQ(hd.GetSizeForTesting(stack()), 5u);
-  EXPECT_EQ(hd.GetSizeForTesting(stack2()), 0u);
+  hd.RecordMalloc(stack(), 1, 5, 2, 2);
+  hd.RecordMalloc(stack2(), 1, 2, 1, 1);
+  EXPECT_EQ(hd.GetSizeForTesting(stack()), 5);
+  EXPECT_EQ(hd.GetSizeForTesting(stack2()), 0);
 }
 
 TEST(BookkeepingTest, ManyAllocations) {
   GlobalCallstackTrie c;
-  HeapTracker hd(&c, false);
+  HeapTracker hd(&c);
 
   std::vector<std::pair<uint64_t, uint64_t>> batch_frees;
 
@@ -175,10 +132,10 @@
     }
 
     uint64_t addr = sequence_number;
-    hd.RecordMalloc(stack(), addr, 5, 5, sequence_number, sequence_number);
+    hd.RecordMalloc(stack(), addr, 5, sequence_number, sequence_number);
     sequence_number++;
     batch_frees.emplace_back(addr, sequence_number++);
-    ASSERT_THAT(hd.GetSizeForTesting(stack()), AnyOf(Eq(0u), Eq(5u)));
+    ASSERT_THAT(hd.GetSizeForTesting(stack()), AnyOf(Eq(0), Eq(5)));
   }
 }
 
@@ -186,11 +143,8 @@
   std::vector<FrameData> s = stack();
   std::vector<FrameData> s2 = stack2();
 
-  enum OperationType { kAlloc, kFree, kDump };
-
   struct Operation {
     uint64_t sequence_number;
-    OperationType type;
     uint64_t address;
     uint64_t bytes;                       // 0 for free
     const std::vector<FrameData>* stack;  // nullptr for free
@@ -200,14 +154,13 @@
       return sequence_number < other.sequence_number;
     }
   } operations[] = {
-      {1, kAlloc, 0x1, 5, &s},       //
-      {2, kAlloc, 0x1, 10, &s2},     //
-      {3, kFree, 0x01, 0, nullptr},  //
-      {4, kFree, 0x02, 0, nullptr},  //
-      {5, kFree, 0x03, 0, nullptr},  //
-      {6, kAlloc, 0x3, 2, &s},       //
-      {7, kAlloc, 0x4, 3, &s2},      //
-      {0, kDump, 0x00, 0, nullptr},  //
+      {1, 1, 5, &s},       //
+      {2, 1, 10, &s2},     //
+      {3, 1, 0, nullptr},  //
+      {4, 2, 0, nullptr},  //
+      {5, 3, 0, nullptr},  //
+      {6, 3, 2, &s},       //
+      {7, 4, 3, &s2},      //
   };
 
   uint64_t s_size = 2;
@@ -215,21 +168,18 @@
 
   do {
     GlobalCallstackTrie c;
-    HeapTracker hd(&c, false);
+    HeapTracker hd(&c);
 
     for (auto it = std::begin(operations); it != std::end(operations); ++it) {
       const Operation& operation = *it;
 
-      if (operation.type == OperationType::kFree) {
+      if (operation.bytes == 0) {
         hd.RecordFree(operation.address, operation.sequence_number,
                       100 * operation.sequence_number);
-      } else if (operation.type == OperationType::kAlloc) {
-        hd.RecordMalloc(*operation.stack, operation.address, operation.bytes,
-                        operation.bytes, operation.sequence_number,
-                        100 * operation.sequence_number);
       } else {
-        hd.GetCallstackAllocations(
-            [](const HeapTracker::CallstackAllocations&) {});
+        hd.RecordMalloc(*operation.stack, operation.address, operation.bytes,
+                        operation.sequence_number,
+                        100 * operation.sequence_number);
       }
     }
     ASSERT_EQ(hd.GetSizeForTesting(s), s_size);
diff --git a/src/profiling/memory/client.cc b/src/profiling/memory/client.cc
index 420da4c..37453d1 100644
--- a/src/profiling/memory/client.cc
+++ b/src/profiling/memory/client.cc
@@ -34,11 +34,11 @@
 #include <new>
 
 #include "perfetto/base/logging.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/thread_utils.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/thread_utils.h"
-#include "perfetto/ext/base/unix_socket.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/unix_socket.h"
+#include "perfetto/base/utils.h"
 #include "src/profiling/memory/sampler.h"
 #include "src/profiling/memory/scoped_spinlock.h"
 #include "src/profiling/memory/wire_protocol.h"
@@ -101,8 +101,7 @@
 // static
 base::Optional<base::UnixSocketRaw> Client::ConnectToHeapprofd(
     const std::string& sock_name) {
-  auto sock = base::UnixSocketRaw::CreateMayFail(base::SockFamily::kUnix,
-                                                 base::SockType::kStream);
+  auto sock = base::UnixSocketRaw::CreateMayFail(base::SockType::kStream);
   if (!sock || !sock.Connect(sock_name)) {
     PERFETTO_PLOG("Failed to connect to %s", sock_name.c_str());
     return base::nullopt;
@@ -123,7 +122,7 @@
     base::UnixSocketRaw sock,
     UnhookedAllocator<Client> unhooked_allocator) {
   if (!sock) {
-    PERFETTO_DFATAL_OR_ELOG("Socket not connected.");
+    PERFETTO_DFATAL("Socket not connected.");
     return nullptr;
   }
 
@@ -143,38 +142,28 @@
     prctl(PR_SET_DUMPABLE, 1);
   }
 
-  size_t num_send_fds = kHandshakeSize;
-
   base::ScopedFile maps(base::OpenFile("/proc/self/maps", O_RDONLY));
   if (!maps) {
-    PERFETTO_DFATAL_OR_ELOG("Failed to open /proc/self/maps");
+    PERFETTO_DFATAL("Failed to open /proc/self/maps");
     return nullptr;
   }
   base::ScopedFile mem(base::OpenFile("/proc/self/mem", O_RDONLY));
   if (!mem) {
-    PERFETTO_DFATAL_OR_ELOG("Failed to open /proc/self/mem");
+    PERFETTO_DFATAL("Failed to open /proc/self/mem");
     return nullptr;
   }
-
-  base::ScopedFile page_idle(base::OpenFile("/proc/self/page_idle", O_RDWR));
-  if (!page_idle) {
-    PERFETTO_LOG("Failed to open /proc/self/page_idle. Continuing.");
-    num_send_fds = kHandshakeSize - 1;
-  }
-
   // Restore original dumpability value if we overrode it.
   unset_dumpable.reset();
 
   int fds[kHandshakeSize];
   fds[kHandshakeMaps] = *maps;
   fds[kHandshakeMem] = *mem;
-  fds[kHandshakePageIdle] = *page_idle;
 
   // Send an empty record to transfer fds for /proc/self/maps and
   // /proc/self/mem.
-  if (sock.Send(kSingleByte, sizeof(kSingleByte), fds, num_send_fds) !=
+  if (sock.Send(kSingleByte, sizeof(kSingleByte), fds, kHandshakeSize) !=
       sizeof(kSingleByte)) {
-    PERFETTO_DFATAL_OR_ELOG("Failed to send file descriptors.");
+    PERFETTO_DFATAL("Failed to send file descriptors.");
     return nullptr;
   }
 
@@ -202,13 +191,13 @@
   }
 
   if (!shmem_fd) {
-    PERFETTO_DFATAL_OR_ELOG("Did not receive shmem fd.");
+    PERFETTO_DFATAL("Did not receive shmem fd.");
     return nullptr;
   }
 
   auto shmem = SharedRingBuffer::Attach(std::move(shmem_fd));
   if (!shmem || !shmem->is_valid()) {
-    PERFETTO_DFATAL_OR_ELOG("Failed to attach to shmem.");
+    PERFETTO_DFATAL("Failed to attach to shmem.");
     return nullptr;
   }
 
@@ -258,8 +247,8 @@
 //               +------------+    |
 //               |  main      |    v
 // stackbase +-> +------------+ 0xffff
-bool Client::RecordMalloc(uint64_t sample_size,
-                          uint64_t alloc_size,
+bool Client::RecordMalloc(uint64_t alloc_size,
+                          uint64_t total_size,
                           uint64_t alloc_address) {
   if (PERFETTO_UNLIKELY(getpid() != pid_at_creation_)) {
     PERFETTO_LOG("Detected post-fork child situation, stopping profiling.");
@@ -271,13 +260,13 @@
   const char* stacktop = reinterpret_cast<char*>(__builtin_frame_address(0));
   unwindstack::AsmGetRegs(metadata.register_data);
 
-  if (PERFETTO_UNLIKELY(stackbase < stacktop)) {
-    PERFETTO_DFATAL_OR_ELOG("Stackbase >= stacktop.");
+  if (stackbase < stacktop) {
+    PERFETTO_DFATAL("Stackbase >= stacktop.");
     return false;
   }
 
   uint64_t stack_size = static_cast<uint64_t>(stackbase - stacktop);
-  metadata.sample_size = sample_size;
+  metadata.total_size = total_size;
   metadata.alloc_size = alloc_size;
   metadata.alloc_address = alloc_address;
   metadata.stack_pointer = reinterpret_cast<uint64_t>(stacktop);
diff --git a/src/profiling/memory/client.h b/src/profiling/memory/client.h
index d32f2e8..72b9c6c 100644
--- a/src/profiling/memory/client.h
+++ b/src/profiling/memory/client.h
@@ -25,7 +25,7 @@
 #include <mutex>
 #include <vector>
 
-#include "perfetto/ext/base/unix_socket.h"
+#include "perfetto/base/unix_socket.h"
 #include "src/profiling/memory/sampler.h"
 #include "src/profiling/memory/shared_ring_buffer.h"
 #include "src/profiling/memory/unhooked_allocator.h"
@@ -65,8 +65,8 @@
   static base::Optional<base::UnixSocketRaw> ConnectToHeapprofd(
       const std::string& sock_name);
 
-  bool RecordMalloc(uint64_t sample_size,
-                    uint64_t alloc_size,
+  bool RecordMalloc(uint64_t alloc_size,
+                    uint64_t total_size,
                     uint64_t alloc_address);
 
   // Add address to buffer of deallocations. Flushes the buffer if necessary.
diff --git a/src/profiling/memory/client_unittest.cc b/src/profiling/memory/client_unittest.cc
index e2f0500..e5ed201 100644
--- a/src/profiling/memory/client_unittest.cc
+++ b/src/profiling/memory/client_unittest.cc
@@ -16,11 +16,11 @@
 
 #include "src/profiling/memory/client.h"
 
-#include <thread>
+#include "gtest/gtest.h"
+#include "perfetto/base/thread_utils.h"
+#include "perfetto/base/unix_socket.h"
 
-#include "perfetto/ext/base/thread_utils.h"
-#include "perfetto/ext/base/unix_socket.h"
-#include "test/gtest_and_gmock.h"
+#include <thread>
 
 namespace perfetto {
 namespace profiling {
diff --git a/src/profiling/memory/heapprofd_end_to_end_test.cc b/src/profiling/memory/heapprofd_end_to_end_test.cc
index 42e666f..c498ae3 100644
--- a/src/profiling/memory/heapprofd_end_to_end_test.cc
+++ b/src/profiling/memory/heapprofd_end_to_end_test.cc
@@ -14,35 +14,41 @@
  * limitations under the License.
  */
 
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/build_config.h"
+#include "perfetto/base/pipe.h"
+#include "src/base/test/test_task_runner.h"
+#include "test/test_helper.h"
+
+#include "src/profiling/memory/heapprofd_producer.h"
+#include "src/tracing/ipc/default_socket.h"
+
+#include <sys/system_properties.h>
+
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
-#include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/pipe.h"
-#include "perfetto/ext/tracing/ipc/default_socket.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "src/base/test/test_task_runner.h"
-#include "src/profiling/memory/heapprofd_producer.h"
-#include "test/gtest_and_gmock.h"
-#include "test/test_helper.h"
-
-#include "protos/perfetto/config/profiling/heapprofd_config.pbzero.h"
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-#include <sys/system_properties.h>
+// This test only works when run on Android using an Android Q version of
+// Bionic.
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#error "This test can only be used on Android."
 #endif
 
 namespace perfetto {
 namespace profiling {
 namespace {
 
+// If we're building on Android and starting the daemons ourselves,
+// create the sockets in a world-writable location.
+#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
+constexpr const char* kTestProducerSockName "/data/local/tmp/traced_producer";
+#endif
+
 constexpr useconds_t kMsToUs = 1000;
 
-constexpr auto kTracingDisabledTimeoutMs = 30000;
-constexpr auto kWaitForReadDataTimeoutMs = 10000;
-
 using ::testing::AnyOf;
-using ::testing::Bool;
 using ::testing::Eq;
 
 class HeapprofdDelegate : public ThreadDelegate {
@@ -62,10 +68,9 @@
   std::unique_ptr<HeapprofdProducer> producer_;
 };
 
+constexpr const char* kEnableHeapprofdProperty = "persist.heapprofd.enable";
 constexpr const char* kHeapprofdModeProperty = "heapprofd.userdebug.mode";
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-
 std::string ReadProperty(const std::string& name, std::string def) {
   const prop_info* pi = __system_property_find(name.c_str());
   if (pi) {
@@ -79,7 +84,7 @@
   return def;
 }
 
-int SetModeProperty(std::string* value) {
+int __attribute__((unused)) SetModeProperty(std::string* value) {
   if (value) {
     __system_property_set(kHeapprofdModeProperty, value->c_str());
     delete value;
@@ -101,25 +106,14 @@
       new std::string(prev_property_value));
 }
 
-#else
-std::string ReadProperty(const std::string&, std::string) {
-  PERFETTO_FATAL("Only works on Android.");
+int __attribute__((unused)) SetEnableProperty(std::string* value) {
+  if (value) {
+    __system_property_set(kEnableHeapprofdProperty, value->c_str());
+    delete value;
+  }
+  return 0;
 }
 
-int SetModeProperty(std::string*) {
-  PERFETTO_FATAL("Only works on Android.");
-}
-
-base::ScopedResource<std::string*, SetModeProperty, nullptr> EnableFork() {
-  PERFETTO_FATAL("Only works on Android.");
-}
-
-base::ScopedResource<std::string*, SetModeProperty, nullptr> DisableFork() {
-  PERFETTO_FATAL("Only works on Android.");
-}
-
-#endif
-
 constexpr size_t kStartupAllocSize = 10;
 
 void AllocateAndFree(size_t bytes) {
@@ -191,11 +185,7 @@
          "unwinding_time_us: " + FormatHistogram(stats.unwinding_time_us());
 }
 
-std::string TestSuffix(const ::testing::TestParamInfo<bool>& info) {
-  return info.param ? "ForkMode" : "CentralMode";
-}
-
-class HeapprofdEndToEnd : public ::testing::TestWithParam<bool> {
+class HeapprofdEndToEnd : public ::testing::Test {
  public:
   HeapprofdEndToEnd() {
     // This is not needed for correctness, but works around a init behavior that
@@ -203,29 +193,19 @@
     // and then set to 1 again too quickly, init decides that the service is
     // "restarting" and waits before restarting it.
     usleep(50000);
-    bool should_fork = GetParam();
-    if (should_fork) {
-      fork_prop_ = EnableFork();
-      PERFETTO_CHECK(ReadProperty(kHeapprofdModeProperty, "") == "fork");
-    } else {
-      fork_prop_ = DisableFork();
-      PERFETTO_CHECK(ReadProperty(kHeapprofdModeProperty, "") == "");
-    }
   }
 
  protected:
   base::TestTaskRunner task_runner;
-  base::ScopedResource<std::string*, SetModeProperty, nullptr> fork_prop_{
-      nullptr};
 
   std::unique_ptr<TestHelper> Trace(const TraceConfig& trace_config) {
     auto helper = GetHelper(&task_runner);
 
     helper->StartTracing(trace_config);
-    helper->WaitForTracingDisabled(kTracingDisabledTimeoutMs);
+    helper->WaitForTracingDisabled(20000);
 
     helper->ReadData();
-    helper->WaitForReadData(0, kWaitForReadDataTimeoutMs);
+    helper->WaitForReadData();
     return helper;
   }
 
@@ -249,10 +229,10 @@
         if (dump.pid() != pid)
           continue;
         for (const auto& sample : dump.samples()) {
-          EXPECT_EQ(sample.self_allocated() % alloc_size, 0u);
-          EXPECT_EQ(sample.self_freed() % alloc_size, 0u);
+          EXPECT_EQ(sample.self_allocated() % alloc_size, 0);
+          EXPECT_EQ(sample.self_freed() % alloc_size, 0);
           EXPECT_THAT(sample.self_allocated() - sample.self_freed(),
-                      AnyOf(Eq(0u), Eq(alloc_size)));
+                      AnyOf(Eq(0), Eq(alloc_size)));
         }
       }
     }
@@ -303,10 +283,10 @@
         profile_packets++;
       }
     }
-    EXPECT_GT(profile_packets, 0u);
-    EXPECT_GT(samples, 0u);
-    EXPECT_GT(last_allocated, 0u);
-    EXPECT_GT(last_freed, 0u);
+    EXPECT_GT(profile_packets, 0);
+    EXPECT_GT(samples, 0);
+    EXPECT_GT(last_allocated, 0);
+    EXPECT_GT(last_freed, 0);
   }
 
   void ValidateOnlyPID(TestHelper* helper, uint64_t pid) {
@@ -318,655 +298,781 @@
         dumps++;
       }
     }
-    EXPECT_GT(dumps, 0u);
+    EXPECT_GT(dumps, 0);
   }
-};
 
-TEST_P(HeapprofdEndToEnd, Smoke) {
-  constexpr size_t kAllocSize = 1024;
+#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
+  TaskRunnerThread producer_thread("perfetto.prd");
+  producer_thread.Start(std::unique_ptr<HeapprofdDelegate>(
+      new HeapprofdDelegate(kTestProducerSockName)));
+#endif
 
-  pid_t pid = ForkContinuousMalloc(kAllocSize);
+  void Smoke() {
+    constexpr size_t kAllocSize = 1024;
 
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(10 * 1024);
-  trace_config.set_duration_ms(2000);
-  trace_config.set_data_source_stop_timeout_ms(10000);
+    pid_t pid = ForkContinuousMalloc(kAllocSize);
 
-  auto* ds_config = trace_config.add_data_sources()->mutable_config();
-  ds_config->set_name("android.heapprofd");
-  ds_config->set_target_buffer(0);
+    TraceConfig trace_config;
+    trace_config.add_buffers()->set_size_kb(10 * 1024);
+    trace_config.set_duration_ms(2000);
+    trace_config.set_flush_timeout_ms(10000);
 
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_pid(static_cast<uint64_t>(pid));
-  heapprofd_config->set_all(false);
-  auto* cont_config = heapprofd_config->set_continuous_dump_config();
-  cont_config->set_dump_phase_ms(0);
-  cont_config->set_dump_interval_ms(100);
-  ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
+    auto* ds_config = trace_config.add_data_sources()->mutable_config();
+    ds_config->set_name("android.heapprofd");
+    ds_config->set_target_buffer(0);
 
-  auto helper = Trace(trace_config);
-  PrintStats(helper.get());
-  ValidateHasSamples(helper.get(), static_cast<uint64_t>(pid));
-  ValidateOnlyPID(helper.get(), static_cast<uint64_t>(pid));
-  ValidateSampleSizes(helper.get(), static_cast<uint64_t>(pid), kAllocSize);
+    auto* heapprofd_config = ds_config->mutable_heapprofd_config();
+    heapprofd_config->set_sampling_interval_bytes(1);
+    *heapprofd_config->add_pid() = static_cast<uint64_t>(pid);
+    heapprofd_config->set_all(false);
+    heapprofd_config->mutable_continuous_dump_config()->set_dump_phase_ms(0);
+    heapprofd_config->mutable_continuous_dump_config()->set_dump_interval_ms(
+        100);
 
-  PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
-  PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
-}
+    auto helper = Trace(trace_config);
+    PrintStats(helper.get());
+    ValidateHasSamples(helper.get(), static_cast<uint64_t>(pid));
+    ValidateOnlyPID(helper.get(), static_cast<uint64_t>(pid));
+    ValidateSampleSizes(helper.get(), static_cast<uint64_t>(pid), kAllocSize);
 
-TEST_P(HeapprofdEndToEnd, TwoProcesses) {
-  constexpr size_t kAllocSize = 1024;
-  constexpr size_t kAllocSize2 = 7;
+    PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
+    PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
+  }
 
-  pid_t pid = ForkContinuousMalloc(kAllocSize);
-  pid_t pid2 = ForkContinuousMalloc(kAllocSize2);
+  void TwoProcesses() {
+    constexpr size_t kAllocSize = 1024;
+    constexpr size_t kAllocSize2 = 7;
 
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(10 * 1024);
-  trace_config.set_duration_ms(2000);
-  trace_config.set_data_source_stop_timeout_ms(10000);
+    pid_t pid = ForkContinuousMalloc(kAllocSize);
+    pid_t pid2 = ForkContinuousMalloc(kAllocSize2);
 
-  auto* ds_config = trace_config.add_data_sources()->mutable_config();
-  ds_config->set_name("android.heapprofd");
-  ds_config->set_target_buffer(0);
+    TraceConfig trace_config;
+    trace_config.add_buffers()->set_size_kb(10 * 1024);
+    trace_config.set_duration_ms(2000);
+    trace_config.set_flush_timeout_ms(10000);
 
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_pid(static_cast<uint64_t>(pid));
-  heapprofd_config->add_pid(static_cast<uint64_t>(pid2));
-  heapprofd_config->set_all(false);
-  ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
+    auto* ds_config = trace_config.add_data_sources()->mutable_config();
+    ds_config->set_name("android.heapprofd");
+    ds_config->set_target_buffer(0);
 
-  auto helper = Trace(trace_config);
-  PrintStats(helper.get());
-  ValidateHasSamples(helper.get(), static_cast<uint64_t>(pid));
-  ValidateSampleSizes(helper.get(), static_cast<uint64_t>(pid), kAllocSize);
-  ValidateHasSamples(helper.get(), static_cast<uint64_t>(pid2));
-  ValidateSampleSizes(helper.get(), static_cast<uint64_t>(pid2), kAllocSize2);
+    auto* heapprofd_config = ds_config->mutable_heapprofd_config();
+    heapprofd_config->set_sampling_interval_bytes(1);
+    *heapprofd_config->add_pid() = static_cast<uint64_t>(pid);
+    *heapprofd_config->add_pid() = static_cast<uint64_t>(pid2);
+    heapprofd_config->set_all(false);
 
-  PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
-  PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
-  PERFETTO_CHECK(kill(pid2, SIGKILL) == 0);
-  PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid2, nullptr, 0)) == pid2);
-}
+    auto helper = Trace(trace_config);
+    PrintStats(helper.get());
+    ValidateHasSamples(helper.get(), static_cast<uint64_t>(pid));
+    ValidateSampleSizes(helper.get(), static_cast<uint64_t>(pid), kAllocSize);
+    ValidateHasSamples(helper.get(), static_cast<uint64_t>(pid2));
+    ValidateSampleSizes(helper.get(), static_cast<uint64_t>(pid2), kAllocSize2);
 
-TEST_P(HeapprofdEndToEnd, FinalFlush) {
-  constexpr size_t kAllocSize = 1024;
+    PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
+    PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
+    PERFETTO_CHECK(kill(pid2, SIGKILL) == 0);
+    PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid2, nullptr, 0)) == pid2);
+  }
 
-  pid_t pid = ForkContinuousMalloc(kAllocSize);
+  void FinalFlush() {
+    constexpr size_t kAllocSize = 1024;
 
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(10 * 1024);
-  trace_config.set_duration_ms(2000);
-  trace_config.set_data_source_stop_timeout_ms(10000);
+    pid_t pid = ForkContinuousMalloc(kAllocSize);
 
-  auto* ds_config = trace_config.add_data_sources()->mutable_config();
-  ds_config->set_name("android.heapprofd");
-  ds_config->set_target_buffer(0);
+    TraceConfig trace_config;
+    trace_config.add_buffers()->set_size_kb(10 * 1024);
+    trace_config.set_duration_ms(2000);
+    trace_config.set_flush_timeout_ms(10000);
 
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_pid(static_cast<uint64_t>(pid));
-  heapprofd_config->set_all(false);
-  ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
+    auto* ds_config = trace_config.add_data_sources()->mutable_config();
+    ds_config->set_name("android.heapprofd");
+    ds_config->set_target_buffer(0);
 
-  auto helper = Trace(trace_config);
-  PrintStats(helper.get());
-  ValidateHasSamples(helper.get(), static_cast<uint64_t>(pid));
-  ValidateOnlyPID(helper.get(), static_cast<uint64_t>(pid));
-  ValidateSampleSizes(helper.get(), static_cast<uint64_t>(pid), kAllocSize);
+    auto* heapprofd_config = ds_config->mutable_heapprofd_config();
+    heapprofd_config->set_sampling_interval_bytes(1);
+    *heapprofd_config->add_pid() = static_cast<uint64_t>(pid);
+    heapprofd_config->set_all(false);
 
-  PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
-  PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
-}
+    auto helper = Trace(trace_config);
+    PrintStats(helper.get());
+    ValidateHasSamples(helper.get(), static_cast<uint64_t>(pid));
+    ValidateOnlyPID(helper.get(), static_cast<uint64_t>(pid));
+    ValidateSampleSizes(helper.get(), static_cast<uint64_t>(pid), kAllocSize);
 
-TEST_P(HeapprofdEndToEnd, NativeStartup) {
-  auto helper = GetHelper(&task_runner);
+    PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
+    PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
+  }
 
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(10 * 1024);
-  trace_config.set_duration_ms(5000);
-  trace_config.set_data_source_stop_timeout_ms(10000);
+  void NativeStartup() {
+    auto helper = GetHelper(&task_runner);
 
-  auto* ds_config = trace_config.add_data_sources()->mutable_config();
-  ds_config->set_name("android.heapprofd");
+    TraceConfig trace_config;
+    trace_config.add_buffers()->set_size_kb(10 * 1024);
+    trace_config.set_duration_ms(5000);
+    trace_config.set_flush_timeout_ms(10000);
 
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_process_cmdline("heapprofd_continuous_malloc");
-  heapprofd_config->set_all(false);
-  ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
+    auto* ds_config = trace_config.add_data_sources()->mutable_config();
+    ds_config->set_name("android.heapprofd");
 
-  helper->StartTracing(trace_config);
+    auto* heapprofd_config = ds_config->mutable_heapprofd_config();
+    heapprofd_config->set_sampling_interval_bytes(1);
+    *heapprofd_config->add_process_cmdline() = "heapprofd_continuous_malloc";
+    heapprofd_config->set_all(false);
 
-  // Wait to guarantee that the process forked below is hooked by the profiler
-  // by virtue of the startup check, and not by virtue of being seen as a
-  // running process. This sleep is here to prevent that, accidentally, the
-  // test gets to the fork()+exec() too soon, before the heap profiling daemon
-  // has received the trace config.
-  sleep(1);
+    helper->StartTracing(trace_config);
 
-  // Make sure the forked process does not get reparented to init.
-  setsid();
-  pid_t pid = fork();
-  switch (pid) {
-    case -1:
-      PERFETTO_FATAL("Failed to fork.");
-    case 0: {
-      const char* envp[] = {"HEAPPROFD_TESTING_RUN_MALLOC=1", nullptr};
-      int null = open("/dev/null", O_RDWR);
-      dup2(null, STDIN_FILENO);
-      dup2(null, STDOUT_FILENO);
-      dup2(null, STDERR_FILENO);
-      PERFETTO_CHECK(execle("/proc/self/exe", "heapprofd_continuous_malloc",
-                            nullptr, envp) == 0);
-      break;
+    // Wait to guarantee that the process forked below is hooked by the profiler
+    // by virtue of the startup check, and not by virtue of being seen as a
+    // running process. This sleep is here to prevent that, accidentally, the
+    // test gets to the fork()+exec() too soon, before the heap profiling daemon
+    // has received the trace config.
+    sleep(1);
+
+    // Make sure the forked process does not get reparented to init.
+    setsid();
+    pid_t pid = fork();
+    switch (pid) {
+      case -1:
+        PERFETTO_FATAL("Failed to fork.");
+      case 0: {
+        const char* envp[] = {"HEAPPROFD_TESTING_RUN_MALLOC=1", nullptr};
+        int null = open("/dev/null", O_RDWR);
+        dup2(null, STDIN_FILENO);
+        dup2(null, STDOUT_FILENO);
+        dup2(null, STDERR_FILENO);
+        PERFETTO_CHECK(execle("/proc/self/exe", "heapprofd_continuous_malloc",
+                              nullptr, envp) == 0);
+        break;
+      }
+      default:
+        break;
     }
-    default:
-      break;
-  }
 
-  helper->WaitForTracingDisabled(kTracingDisabledTimeoutMs);
+    helper->WaitForTracingDisabled(20000);
 
-  helper->ReadData();
-  helper->WaitForReadData(0, kWaitForReadDataTimeoutMs);
+    helper->ReadData();
+    helper->WaitForReadData();
 
-  PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
-  PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
+    PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
+    PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
 
-  const auto& packets = helper->trace();
-  ASSERT_GT(packets.size(), 0u);
-  size_t profile_packets = 0;
-  size_t samples = 0;
-  uint64_t total_allocated = 0;
-  uint64_t total_freed = 0;
-  for (const protos::TracePacket& packet : packets) {
-    if (packet.has_profile_packet() &&
-        packet.profile_packet().process_dumps().size() > 0) {
-      const auto& dumps = packet.profile_packet().process_dumps();
-      ASSERT_EQ(dumps.size(), 1);
-      const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
-      EXPECT_EQ(static_cast<pid_t>(dump.pid()), pid);
-      profile_packets++;
-      for (const auto& sample : dump.samples()) {
-        samples++;
-        total_allocated += sample.self_allocated();
-        total_freed += sample.self_freed();
+    const auto& packets = helper->trace();
+    ASSERT_GT(packets.size(), 0u);
+    size_t profile_packets = 0;
+    size_t samples = 0;
+    uint64_t total_allocated = 0;
+    uint64_t total_freed = 0;
+    for (const protos::TracePacket& packet : packets) {
+      if (packet.has_profile_packet() &&
+          packet.profile_packet().process_dumps().size() > 0) {
+        const auto& dumps = packet.profile_packet().process_dumps();
+        ASSERT_EQ(dumps.size(), 1);
+        const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
+        EXPECT_EQ(dump.pid(), pid);
+        profile_packets++;
+        for (const auto& sample : dump.samples()) {
+          samples++;
+          total_allocated += sample.self_allocated();
+          total_freed += sample.self_freed();
+        }
       }
     }
+    EXPECT_EQ(profile_packets, 1);
+    EXPECT_GT(samples, 0);
+    EXPECT_GT(total_allocated, 0);
+    EXPECT_GT(total_freed, 0);
   }
-  EXPECT_EQ(profile_packets, 1u);
-  EXPECT_GT(samples, 0u);
-  EXPECT_GT(total_allocated, 0u);
-  EXPECT_GT(total_freed, 0u);
-}
 
-TEST_P(HeapprofdEndToEnd, NativeStartupDenormalizedCmdline) {
-  auto helper = GetHelper(&task_runner);
+  void NativeStartupDenormalizedCmdline() {
+    auto helper = GetHelper(&task_runner);
 
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(10 * 1024);
-  trace_config.set_duration_ms(5000);
-  trace_config.set_data_source_stop_timeout_ms(10000);
+    TraceConfig trace_config;
+    trace_config.add_buffers()->set_size_kb(10 * 1024);
+    trace_config.set_duration_ms(5000);
+    trace_config.set_flush_timeout_ms(10000);
 
-  auto* ds_config = trace_config.add_data_sources()->mutable_config();
-  ds_config->set_name("android.heapprofd");
+    auto* ds_config = trace_config.add_data_sources()->mutable_config();
+    ds_config->set_name("android.heapprofd");
 
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_process_cmdline("heapprofd_continuous_malloc@1.2.3");
-  heapprofd_config->set_all(false);
-  ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
+    auto* heapprofd_config = ds_config->mutable_heapprofd_config();
+    heapprofd_config->set_sampling_interval_bytes(1);
+    *heapprofd_config->add_process_cmdline() =
+        "heapprofd_continuous_malloc@something";
+    heapprofd_config->set_all(false);
 
-  helper->StartTracing(trace_config);
+    helper->StartTracing(trace_config);
 
-  // Wait to guarantee that the process forked below is hooked by the profiler
-  // by virtue of the startup check, and not by virtue of being seen as a
-  // running process. This sleep is here to prevent that, accidentally, the
-  // test gets to the fork()+exec() too soon, before the heap profiling daemon
-  // has received the trace config.
-  sleep(1);
+    // Wait to guarantee that the process forked below is hooked by the profiler
+    // by virtue of the startup check, and not by virtue of being seen as a
+    // running process. This sleep is here to prevent that, accidentally, the
+    // test gets to the fork()+exec() too soon, before the heap profiling daemon
+    // has received the trace config.
+    sleep(1);
 
-  // Make sure the forked process does not get reparented to init.
-  setsid();
-  pid_t pid = fork();
-  switch (pid) {
-    case -1:
-      PERFETTO_FATAL("Failed to fork.");
-    case 0: {
-      const char* envp[] = {"HEAPPROFD_TESTING_RUN_MALLOC=1", nullptr};
-      int null = open("/dev/null", O_RDWR);
-      dup2(null, STDIN_FILENO);
-      dup2(null, STDOUT_FILENO);
-      dup2(null, STDERR_FILENO);
-      PERFETTO_CHECK(execle("/proc/self/exe", "heapprofd_continuous_malloc",
-                            nullptr, envp) == 0);
-      break;
+    // Make sure the forked process does not get reparented to init.
+    setsid();
+    pid_t pid = fork();
+    switch (pid) {
+      case -1:
+        PERFETTO_FATAL("Failed to fork.");
+      case 0: {
+        const char* envp[] = {"HEAPPROFD_TESTING_RUN_MALLOC=1", nullptr};
+        int null = open("/dev/null", O_RDWR);
+        dup2(null, STDIN_FILENO);
+        dup2(null, STDOUT_FILENO);
+        dup2(null, STDERR_FILENO);
+        PERFETTO_CHECK(execle("/proc/self/exe", "heapprofd_continuous_malloc",
+                              nullptr, envp) == 0);
+        break;
+      }
+      default:
+        break;
     }
-    default:
-      break;
-  }
 
-  helper->WaitForTracingDisabled(kTracingDisabledTimeoutMs);
+    helper->WaitForTracingDisabled(20000);
 
-  helper->ReadData();
-  helper->WaitForReadData(0, kWaitForReadDataTimeoutMs);
+    helper->ReadData();
+    helper->WaitForReadData();
 
-  PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
-  PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
+    PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
+    PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
 
-  const auto& packets = helper->trace();
-  ASSERT_GT(packets.size(), 0u);
-  size_t profile_packets = 0;
-  size_t samples = 0;
-  uint64_t total_allocated = 0;
-  uint64_t total_freed = 0;
-  for (const protos::TracePacket& packet : packets) {
-    if (packet.has_profile_packet() &&
-        packet.profile_packet().process_dumps().size() > 0) {
-      const auto& dumps = packet.profile_packet().process_dumps();
-      ASSERT_EQ(dumps.size(), 1);
-      const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
-      EXPECT_EQ(static_cast<pid_t>(dump.pid()), pid);
-      profile_packets++;
-      for (const auto& sample : dump.samples()) {
-        samples++;
-        total_allocated += sample.self_allocated();
-        total_freed += sample.self_freed();
+    const auto& packets = helper->trace();
+    ASSERT_GT(packets.size(), 0u);
+    size_t profile_packets = 0;
+    size_t samples = 0;
+    uint64_t total_allocated = 0;
+    uint64_t total_freed = 0;
+    for (const protos::TracePacket& packet : packets) {
+      if (packet.has_profile_packet() &&
+          packet.profile_packet().process_dumps().size() > 0) {
+        const auto& dumps = packet.profile_packet().process_dumps();
+        ASSERT_EQ(dumps.size(), 1);
+        const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
+        EXPECT_EQ(dump.pid(), pid);
+        profile_packets++;
+        for (const auto& sample : dump.samples()) {
+          samples++;
+          total_allocated += sample.self_allocated();
+          total_freed += sample.self_freed();
+        }
       }
     }
+    EXPECT_EQ(profile_packets, 1);
+    EXPECT_GT(samples, 0);
+    EXPECT_GT(total_allocated, 0);
+    EXPECT_GT(total_freed, 0);
   }
-  EXPECT_EQ(profile_packets, 1u);
-  EXPECT_GT(samples, 0u);
-  EXPECT_GT(total_allocated, 0u);
-  EXPECT_GT(total_freed, 0u);
-}
 
-TEST_P(HeapprofdEndToEnd, DiscoverByName) {
-  auto helper = GetHelper(&task_runner);
+  void DiscoverByName() {
+    auto helper = GetHelper(&task_runner);
 
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(10 * 1024);
-  trace_config.set_duration_ms(5000);
-  trace_config.set_data_source_stop_timeout_ms(10000);
+    TraceConfig trace_config;
+    trace_config.add_buffers()->set_size_kb(10 * 1024);
+    trace_config.set_duration_ms(5000);
+    trace_config.set_flush_timeout_ms(10000);
 
-  auto* ds_config = trace_config.add_data_sources()->mutable_config();
-  ds_config->set_name("android.heapprofd");
+    auto* ds_config = trace_config.add_data_sources()->mutable_config();
+    ds_config->set_name("android.heapprofd");
 
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_process_cmdline("heapprofd_continuous_malloc");
-  heapprofd_config->set_all(false);
-  ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
+    auto* heapprofd_config = ds_config->mutable_heapprofd_config();
+    heapprofd_config->set_sampling_interval_bytes(1);
+    *heapprofd_config->add_process_cmdline() = "heapprofd_continuous_malloc";
+    heapprofd_config->set_all(false);
 
-  // Make sure the forked process does not get reparented to init.
-  setsid();
-  pid_t pid = fork();
-  switch (pid) {
-    case -1:
-      PERFETTO_FATAL("Failed to fork.");
-    case 0: {
-      const char* envp[] = {"HEAPPROFD_TESTING_RUN_MALLOC=1", nullptr};
-      int null = open("/dev/null", O_RDWR);
-      dup2(null, STDIN_FILENO);
-      dup2(null, STDOUT_FILENO);
-      dup2(null, STDERR_FILENO);
-      PERFETTO_CHECK(execle("/proc/self/exe", "heapprofd_continuous_malloc",
-                            nullptr, envp) == 0);
-      break;
+    // Make sure the forked process does not get reparented to init.
+    setsid();
+    pid_t pid = fork();
+    switch (pid) {
+      case -1:
+        PERFETTO_FATAL("Failed to fork.");
+      case 0: {
+        const char* envp[] = {"HEAPPROFD_TESTING_RUN_MALLOC=1", nullptr};
+        int null = open("/dev/null", O_RDWR);
+        dup2(null, STDIN_FILENO);
+        dup2(null, STDOUT_FILENO);
+        dup2(null, STDERR_FILENO);
+        PERFETTO_CHECK(execle("/proc/self/exe", "heapprofd_continuous_malloc",
+                              nullptr, envp) == 0);
+        break;
+      }
+      default:
+        break;
     }
-    default:
-      break;
-  }
 
-  // Wait to make sure process is fully initialized, so we do not accidentally
-  // match it by the startup logic.
-  sleep(1);
+    // Wait to make sure process is fully initialized, so we do not accidentally
+    // match it by the startup logic.
+    sleep(1);
 
-  helper->StartTracing(trace_config);
-  helper->WaitForTracingDisabled(kTracingDisabledTimeoutMs);
+    helper->StartTracing(trace_config);
+    helper->WaitForTracingDisabled(20000);
 
-  helper->ReadData();
-  helper->WaitForReadData(0, kWaitForReadDataTimeoutMs);
+    helper->ReadData();
+    helper->WaitForReadData();
 
-  PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
-  PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
+    PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
+    PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
 
-  const auto& packets = helper->trace();
-  ASSERT_GT(packets.size(), 0u);
-  size_t profile_packets = 0;
-  size_t samples = 0;
-  uint64_t total_allocated = 0;
-  uint64_t total_freed = 0;
-  for (const protos::TracePacket& packet : packets) {
-    if (packet.has_profile_packet() &&
-        packet.profile_packet().process_dumps().size() > 0) {
-      const auto& dumps = packet.profile_packet().process_dumps();
-      ASSERT_EQ(dumps.size(), 1);
-      const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
-      EXPECT_EQ(static_cast<pid_t>(dump.pid()), pid);
-      profile_packets++;
-      for (const auto& sample : dump.samples()) {
-        samples++;
-        total_allocated += sample.self_allocated();
-        total_freed += sample.self_freed();
+    const auto& packets = helper->trace();
+    ASSERT_GT(packets.size(), 0u);
+    size_t profile_packets = 0;
+    size_t samples = 0;
+    uint64_t total_allocated = 0;
+    uint64_t total_freed = 0;
+    for (const protos::TracePacket& packet : packets) {
+      if (packet.has_profile_packet() &&
+          packet.profile_packet().process_dumps().size() > 0) {
+        const auto& dumps = packet.profile_packet().process_dumps();
+        ASSERT_EQ(dumps.size(), 1);
+        const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
+        EXPECT_EQ(dump.pid(), pid);
+        profile_packets++;
+        for (const auto& sample : dump.samples()) {
+          samples++;
+          total_allocated += sample.self_allocated();
+          total_freed += sample.self_freed();
+        }
       }
     }
+    EXPECT_EQ(profile_packets, 1);
+    EXPECT_GT(samples, 0);
+    EXPECT_GT(total_allocated, 0);
+    EXPECT_GT(total_freed, 0);
   }
-  EXPECT_EQ(profile_packets, 1u);
-  EXPECT_GT(samples, 0u);
-  EXPECT_GT(total_allocated, 0u);
-  EXPECT_GT(total_freed, 0u);
-}
 
-TEST_P(HeapprofdEndToEnd, DiscoverByNameDenormalizedCmdline) {
-  auto helper = GetHelper(&task_runner);
+  void DiscoverByNameDenormalizedCmdline() {
+    auto helper = GetHelper(&task_runner);
 
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(10 * 1024);
-  trace_config.set_duration_ms(5000);
-  trace_config.set_data_source_stop_timeout_ms(10000);
+    TraceConfig trace_config;
+    trace_config.add_buffers()->set_size_kb(10 * 1024);
+    trace_config.set_duration_ms(5000);
+    trace_config.set_flush_timeout_ms(10000);
 
-  auto* ds_config = trace_config.add_data_sources()->mutable_config();
-  ds_config->set_name("android.heapprofd");
+    auto* ds_config = trace_config.add_data_sources()->mutable_config();
+    ds_config->set_name("android.heapprofd");
 
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_process_cmdline("heapprofd_continuous_malloc@1.2.3");
-  heapprofd_config->set_all(false);
-  ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
+    auto* heapprofd_config = ds_config->mutable_heapprofd_config();
+    heapprofd_config->set_sampling_interval_bytes(1);
+    *heapprofd_config->add_process_cmdline() =
+        "heapprofd_continuous_malloc@something";
+    heapprofd_config->set_all(false);
 
-  // Make sure the forked process does not get reparented to init.
-  setsid();
-  pid_t pid = fork();
-  switch (pid) {
-    case -1:
-      PERFETTO_FATAL("Failed to fork.");
-    case 0: {
-      const char* envp[] = {"HEAPPROFD_TESTING_RUN_MALLOC=1", nullptr};
-      int null = open("/dev/null", O_RDWR);
-      dup2(null, STDIN_FILENO);
-      dup2(null, STDOUT_FILENO);
-      dup2(null, STDERR_FILENO);
-      PERFETTO_CHECK(execle("/proc/self/exe", "heapprofd_continuous_malloc",
-                            nullptr, envp) == 0);
-      break;
+    // Make sure the forked process does not get reparented to init.
+    setsid();
+    pid_t pid = fork();
+    switch (pid) {
+      case -1:
+        PERFETTO_FATAL("Failed to fork.");
+      case 0: {
+        const char* envp[] = {"HEAPPROFD_TESTING_RUN_MALLOC=1", nullptr};
+        int null = open("/dev/null", O_RDWR);
+        dup2(null, STDIN_FILENO);
+        dup2(null, STDOUT_FILENO);
+        dup2(null, STDERR_FILENO);
+        PERFETTO_CHECK(execle("/proc/self/exe", "heapprofd_continuous_malloc",
+                              nullptr, envp) == 0);
+        break;
+      }
+      default:
+        break;
     }
-    default:
-      break;
-  }
 
-  // Wait to make sure process is fully initialized, so we do not accidentally
-  // match it by the startup logic.
-  sleep(1);
+    // Wait to make sure process is fully initialized, so we do not accidentally
+    // match it by the startup logic.
+    sleep(1);
 
-  helper->StartTracing(trace_config);
-  helper->WaitForTracingDisabled(kTracingDisabledTimeoutMs);
+    helper->StartTracing(trace_config);
+    helper->WaitForTracingDisabled(20000);
 
-  helper->ReadData();
-  helper->WaitForReadData(0, kWaitForReadDataTimeoutMs);
+    helper->ReadData();
+    helper->WaitForReadData();
 
-  PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
-  PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
+    PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
+    PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
 
-  const auto& packets = helper->trace();
-  ASSERT_GT(packets.size(), 0u);
-  size_t profile_packets = 0;
-  size_t samples = 0;
-  uint64_t total_allocated = 0;
-  uint64_t total_freed = 0;
-  for (const protos::TracePacket& packet : packets) {
-    if (packet.has_profile_packet() &&
-        packet.profile_packet().process_dumps().size() > 0) {
-      const auto& dumps = packet.profile_packet().process_dumps();
-      ASSERT_EQ(dumps.size(), 1);
-      const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
-      EXPECT_EQ(static_cast<pid_t>(dump.pid()), pid);
-      profile_packets++;
-      for (const auto& sample : dump.samples()) {
-        samples++;
-        total_allocated += sample.self_allocated();
-        total_freed += sample.self_freed();
+    const auto& packets = helper->trace();
+    ASSERT_GT(packets.size(), 0u);
+    size_t profile_packets = 0;
+    size_t samples = 0;
+    uint64_t total_allocated = 0;
+    uint64_t total_freed = 0;
+    for (const protos::TracePacket& packet : packets) {
+      if (packet.has_profile_packet() &&
+          packet.profile_packet().process_dumps().size() > 0) {
+        const auto& dumps = packet.profile_packet().process_dumps();
+        ASSERT_EQ(dumps.size(), 1);
+        const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
+        EXPECT_EQ(dump.pid(), pid);
+        profile_packets++;
+        for (const auto& sample : dump.samples()) {
+          samples++;
+          total_allocated += sample.self_allocated();
+          total_freed += sample.self_freed();
+        }
       }
     }
+    EXPECT_EQ(profile_packets, 1);
+    EXPECT_GT(samples, 0);
+    EXPECT_GT(total_allocated, 0);
+    EXPECT_GT(total_freed, 0);
   }
-  EXPECT_EQ(profile_packets, 1u);
-  EXPECT_GT(samples, 0u);
-  EXPECT_GT(total_allocated, 0u);
-  EXPECT_GT(total_freed, 0u);
-}
 
-TEST_P(HeapprofdEndToEnd, ReInit) {
-  constexpr size_t kFirstIterationBytes = 5;
-  constexpr size_t kSecondIterationBytes = 7;
+  void ReInit() {
+    constexpr uint64_t kFirstIterationBytes = 5;
+    constexpr uint64_t kSecondIterationBytes = 7;
 
-  base::Pipe signal_pipe = base::Pipe::Create(base::Pipe::kBothNonBlock);
-  base::Pipe ack_pipe = base::Pipe::Create(base::Pipe::kBothBlock);
+    base::Pipe signal_pipe = base::Pipe::Create(base::Pipe::kBothNonBlock);
+    base::Pipe ack_pipe = base::Pipe::Create(base::Pipe::kBothBlock);
 
-  setsid();
-  pid_t pid = fork();
-  switch (pid) {
-    case -1:
-      PERFETTO_FATAL("Failed to fork.");
-    case 0: {
-      size_t bytes = kFirstIterationBytes;
-      signal_pipe.wr.reset();
-      ack_pipe.rd.reset();
-      for (;;) {
-        AllocateAndFree(bytes);
-        char buf[1];
-        if (bool(signal_pipe.rd) &&
-            read(*signal_pipe.rd, buf, sizeof(buf)) == 0) {
-          // make sure the client has noticed that the session has stopped
+    pid_t pid = fork();
+    switch (pid) {
+      case -1:
+        PERFETTO_FATAL("Failed to fork.");
+      case 0: {
+        uint64_t bytes = kFirstIterationBytes;
+        signal_pipe.wr.reset();
+        ack_pipe.rd.reset();
+        for (;;) {
           AllocateAndFree(bytes);
+          char buf[1];
+          if (bool(signal_pipe.rd) &&
+              read(*signal_pipe.rd, buf, sizeof(buf)) == 0) {
+            // make sure the client has noticed that the session has stopped
+            AllocateAndFree(bytes);
 
-          bytes = kSecondIterationBytes;
-          signal_pipe.rd.reset();
-          ack_pipe.wr.reset();
+            bytes = kSecondIterationBytes;
+            signal_pipe.rd.reset();
+            ack_pipe.wr.reset();
+          }
+          usleep(10 * kMsToUs);
+        }
+        PERFETTO_FATAL("Should be unreachable");
+      }
+      default:
+        break;
+    }
+
+    signal_pipe.rd.reset();
+    ack_pipe.wr.reset();
+
+    TraceConfig trace_config;
+    trace_config.add_buffers()->set_size_kb(10 * 1024);
+    trace_config.set_duration_ms(2000);
+    trace_config.set_flush_timeout_ms(10000);
+
+    auto* ds_config = trace_config.add_data_sources()->mutable_config();
+    ds_config->set_name("android.heapprofd");
+    ds_config->set_target_buffer(0);
+
+    auto* heapprofd_config = ds_config->mutable_heapprofd_config();
+    heapprofd_config->set_sampling_interval_bytes(1);
+    *heapprofd_config->add_pid() = static_cast<uint64_t>(pid);
+    heapprofd_config->set_all(false);
+
+    auto helper = Trace(trace_config);
+    PrintStats(helper.get());
+    ValidateHasSamples(helper.get(), static_cast<uint64_t>(pid));
+    ValidateOnlyPID(helper.get(), static_cast<uint64_t>(pid));
+    ValidateSampleSizes(helper.get(), static_cast<uint64_t>(pid),
+                        kFirstIterationBytes);
+
+    signal_pipe.wr.reset();
+    char buf[1];
+    ASSERT_EQ(read(*ack_pipe.rd, buf, sizeof(buf)), 0);
+    ack_pipe.rd.reset();
+
+    // A brief sleep to allow the client to notice that the profiling session is
+    // to be torn down (as it rejects concurrent sessions).
+    usleep(100 * kMsToUs);
+
+    PERFETTO_LOG("HeapprofdEndToEnd::Reinit: Starting second");
+    helper = Trace(trace_config);
+    PrintStats(helper.get());
+    ValidateHasSamples(helper.get(), static_cast<uint64_t>(pid));
+    ValidateOnlyPID(helper.get(), static_cast<uint64_t>(pid));
+    ValidateSampleSizes(helper.get(), static_cast<uint64_t>(pid),
+                        kSecondIterationBytes);
+
+    PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
+    PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
+  }
+
+  void ConcurrentSession() {
+    constexpr size_t kAllocSize = 1024;
+
+    pid_t pid = ForkContinuousMalloc(kAllocSize);
+
+    TraceConfig trace_config;
+    trace_config.add_buffers()->set_size_kb(10 * 1024);
+    trace_config.set_duration_ms(5000);
+    trace_config.set_flush_timeout_ms(10000);
+
+    auto* ds_config = trace_config.add_data_sources()->mutable_config();
+    ds_config->set_name("android.heapprofd");
+    ds_config->set_target_buffer(0);
+
+    auto* heapprofd_config = ds_config->mutable_heapprofd_config();
+    heapprofd_config->set_sampling_interval_bytes(1);
+    *heapprofd_config->add_pid() = static_cast<uint64_t>(pid);
+    heapprofd_config->set_all(false);
+    heapprofd_config->mutable_continuous_dump_config()->set_dump_phase_ms(0);
+    heapprofd_config->mutable_continuous_dump_config()->set_dump_interval_ms(
+        100);
+
+    auto helper = GetHelper(&task_runner);
+    helper->StartTracing(trace_config);
+    sleep(1);
+    auto helper_concurrent = GetHelper(&task_runner);
+    helper_concurrent->StartTracing(trace_config);
+
+    helper->WaitForTracingDisabled(20000);
+    helper->ReadData();
+    helper->WaitForReadData();
+    PrintStats(helper.get());
+    ValidateHasSamples(helper.get(), static_cast<uint64_t>(pid));
+    ValidateOnlyPID(helper.get(), static_cast<uint64_t>(pid));
+    ValidateSampleSizes(helper.get(), static_cast<uint64_t>(pid), kAllocSize);
+    ValidateRejectedConcurrent(helper_concurrent.get(),
+                               static_cast<uint64_t>(pid), false);
+
+    helper_concurrent->WaitForTracingDisabled(20000);
+    helper_concurrent->ReadData();
+    helper_concurrent->WaitForReadData();
+    PrintStats(helper.get());
+    ValidateOnlyPID(helper_concurrent.get(), static_cast<uint64_t>(pid));
+    ValidateRejectedConcurrent(helper_concurrent.get(),
+                               static_cast<uint64_t>(pid), true);
+
+    PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
+    PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
+  }
+
+  // TODO(rsavitski): fold exit status assertions into existing tests where
+  // possible.
+  void NativeProfilingActiveAtProcessExit() {
+    constexpr uint64_t kTestAllocSize = 128;
+    base::Pipe start_pipe = base::Pipe::Create(base::Pipe::kBothBlock);
+
+    pid_t pid = fork();
+    if (pid == 0) {  // child
+      start_pipe.rd.reset();
+      start_pipe.wr.reset();
+      for (int i = 0; i < 200; i++) {
+        // malloc and leak, otherwise the free batching will cause us to filter
+        // out the allocations (as we don't see the interleaved frees).
+        volatile char* x = static_cast<char*>(malloc(kTestAllocSize));
+        if (x) {
+          x[0] = 'x';
         }
         usleep(10 * kMsToUs);
       }
-      PERFETTO_FATAL("Should be unreachable");
+      exit(0);
     }
-    default:
-      break;
-  }
 
-  signal_pipe.rd.reset();
-  ack_pipe.wr.reset();
-
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(10 * 1024);
-  trace_config.set_duration_ms(2000);
-  trace_config.set_data_source_stop_timeout_ms(10000);
-
-  auto* ds_config = trace_config.add_data_sources()->mutable_config();
-  ds_config->set_name("android.heapprofd");
-  ds_config->set_target_buffer(0);
-
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_pid(static_cast<uint64_t>(pid));
-  heapprofd_config->set_all(false);
-  ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
-
-  auto helper = Trace(trace_config);
-  PrintStats(helper.get());
-  ValidateHasSamples(helper.get(), static_cast<uint64_t>(pid));
-  ValidateOnlyPID(helper.get(), static_cast<uint64_t>(pid));
-  ValidateSampleSizes(helper.get(), static_cast<uint64_t>(pid),
-                      kFirstIterationBytes);
-
-  signal_pipe.wr.reset();
-  char buf[1];
-  ASSERT_EQ(read(*ack_pipe.rd, buf, sizeof(buf)), 0);
-  ack_pipe.rd.reset();
-
-  // A brief sleep to allow the client to notice that the profiling session is
-  // to be torn down (as it rejects concurrent sessions).
-  usleep(500 * kMsToUs);
-
-  PERFETTO_LOG("HeapprofdEndToEnd::Reinit: Starting second");
-  helper = Trace(trace_config);
-  PrintStats(helper.get());
-  ValidateHasSamples(helper.get(), static_cast<uint64_t>(pid));
-  ValidateOnlyPID(helper.get(), static_cast<uint64_t>(pid));
-  ValidateSampleSizes(helper.get(), static_cast<uint64_t>(pid),
-                      kSecondIterationBytes);
-
-  PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
-  PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
-}
-
-TEST_P(HeapprofdEndToEnd, ConcurrentSession) {
-  constexpr size_t kAllocSize = 1024;
-
-  pid_t pid = ForkContinuousMalloc(kAllocSize);
-
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(10 * 1024);
-  trace_config.set_duration_ms(5000);
-  trace_config.set_data_source_stop_timeout_ms(10000);
-
-  auto* ds_config = trace_config.add_data_sources()->mutable_config();
-  ds_config->set_name("android.heapprofd");
-  ds_config->set_target_buffer(0);
-
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_pid(static_cast<uint64_t>(pid));
-  heapprofd_config->set_all(false);
-  auto* cont_config = heapprofd_config->set_continuous_dump_config();
-  cont_config->set_dump_phase_ms(0);
-  cont_config->set_dump_interval_ms(100);
-  ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
-
-  auto helper = GetHelper(&task_runner);
-  helper->StartTracing(trace_config);
-  sleep(1);
-  auto helper_concurrent = GetHelper(&task_runner);
-  helper_concurrent->StartTracing(trace_config);
-
-  helper->WaitForTracingDisabled(kTracingDisabledTimeoutMs);
-  helper->ReadData();
-  helper->WaitForReadData(0, kWaitForReadDataTimeoutMs);
-  PrintStats(helper.get());
-  ValidateHasSamples(helper.get(), static_cast<uint64_t>(pid));
-  ValidateOnlyPID(helper.get(), static_cast<uint64_t>(pid));
-  ValidateSampleSizes(helper.get(), static_cast<uint64_t>(pid), kAllocSize);
-  ValidateRejectedConcurrent(helper_concurrent.get(),
-                             static_cast<uint64_t>(pid), false);
-
-  helper_concurrent->WaitForTracingDisabled(kTracingDisabledTimeoutMs);
-  helper_concurrent->ReadData();
-  helper_concurrent->WaitForReadData(0, kWaitForReadDataTimeoutMs);
-  PrintStats(helper.get());
-  ValidateOnlyPID(helper_concurrent.get(), static_cast<uint64_t>(pid));
-  ValidateRejectedConcurrent(helper_concurrent.get(),
-                             static_cast<uint64_t>(pid), true);
-
-  PERFETTO_CHECK(kill(pid, SIGKILL) == 0);
-  PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, nullptr, 0)) == pid);
-}
-
-// TODO(rsavitski): fold exit status assertions into existing tests where
-// possible.
-TEST_P(HeapprofdEndToEnd, NativeProfilingActiveAtProcessExit) {
-  constexpr uint64_t kTestAllocSize = 128;
-  base::Pipe start_pipe = base::Pipe::Create(base::Pipe::kBothBlock);
-
-  setsid();
-  pid_t pid = fork();
-  if (pid == 0) {  // child
-    start_pipe.rd.reset();
+    ASSERT_NE(pid, -1) << "Failed to fork.";
     start_pipe.wr.reset();
-    for (int i = 0; i < 200; i++) {
-      // malloc and leak, otherwise the free batching will cause us to filter
-      // out the allocations (as we don't see the interleaved frees).
-      volatile char* x = static_cast<char*>(malloc(kTestAllocSize));
-      if (x) {
-        x[0] = 'x';
-      }
-      usleep(10 * kMsToUs);
-    }
-    exit(0);
-  }
 
-  ASSERT_NE(pid, -1) << "Failed to fork.";
-  start_pipe.wr.reset();
+    // Construct tracing config (without starting profiling).
+    auto helper = GetHelper(&task_runner);
+    TraceConfig trace_config;
+    trace_config.add_buffers()->set_size_kb(10 * 1024);
+    trace_config.set_duration_ms(5000);
+    trace_config.set_flush_timeout_ms(10000);
 
-  // Construct tracing config (without starting profiling).
-  auto helper = GetHelper(&task_runner);
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(10 * 1024);
-  trace_config.set_duration_ms(5000);
-  trace_config.set_data_source_stop_timeout_ms(10000);
+    auto* ds_config = trace_config.add_data_sources()->mutable_config();
+    ds_config->set_name("android.heapprofd");
 
-  auto* ds_config = trace_config.add_data_sources()->mutable_config();
-  ds_config->set_name("android.heapprofd");
+    auto* heapprofd_config = ds_config->mutable_heapprofd_config();
+    heapprofd_config->set_sampling_interval_bytes(1);
+    *heapprofd_config->add_pid() = static_cast<uint64_t>(pid);
 
-  protozero::HeapBuffered<protos::pbzero::HeapprofdConfig> heapprofd_config;
-  heapprofd_config->set_sampling_interval_bytes(1);
-  heapprofd_config->add_pid(static_cast<uint64_t>(pid));
-  ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
+    // Wait for child to have been scheduled at least once.
+    char buf[1] = {};
+    ASSERT_EQ(PERFETTO_EINTR(read(*start_pipe.rd, buf, sizeof(buf))), 0);
+    start_pipe.rd.reset();
 
-  // Wait for child to have been scheduled at least once.
-  char buf[1] = {};
-  ASSERT_EQ(PERFETTO_EINTR(read(*start_pipe.rd, buf, sizeof(buf))), 0);
-  start_pipe.rd.reset();
+    // Trace until child exits.
+    helper->StartTracing(trace_config);
 
-  // Trace until child exits.
-  helper->StartTracing(trace_config);
+    siginfo_t siginfo = {};
+    int wait_ret = PERFETTO_EINTR(
+        waitid(P_PID, static_cast<id_t>(pid), &siginfo, WEXITED));
+    ASSERT_FALSE(wait_ret) << "Failed to waitid.";
 
-  siginfo_t siginfo = {};
-  int wait_ret =
-      PERFETTO_EINTR(waitid(P_PID, static_cast<id_t>(pid), &siginfo, WEXITED));
-  ASSERT_FALSE(wait_ret) << "Failed to waitid.";
+    // Assert that the child exited successfully.
+    EXPECT_EQ(siginfo.si_code, CLD_EXITED) << "Child did not exit by itself.";
+    EXPECT_EQ(siginfo.si_status, 0) << "Child's exit status not successful.";
 
-  // Assert that the child exited successfully.
-  EXPECT_EQ(siginfo.si_code, CLD_EXITED) << "Child did not exit by itself.";
-  EXPECT_EQ(siginfo.si_status, 0) << "Child's exit status not successful.";
+    // Assert that we did profile the process.
+    helper->FlushAndWait(2000);
+    helper->DisableTracing();
+    helper->WaitForTracingDisabled(10000);
+    helper->ReadData();
+    helper->WaitForReadData();
 
-  // Assert that we did profile the process.
-  helper->FlushAndWait(2000);
-  helper->DisableTracing();
-  helper->WaitForTracingDisabled(kTracingDisabledTimeoutMs);
-  helper->ReadData();
-  helper->WaitForReadData(0, kWaitForReadDataTimeoutMs);
-
-  const auto& packets = helper->trace();
-  ASSERT_GT(packets.size(), 0u);
-  size_t profile_packets = 0;
-  size_t samples = 0;
-  uint64_t total_allocated = 0;
-  for (const protos::TracePacket& packet : packets) {
-    if (packet.has_profile_packet() &&
-        packet.profile_packet().process_dumps().size() > 0) {
-      const auto& dumps = packet.profile_packet().process_dumps();
-      ASSERT_EQ(dumps.size(), 1);
-      const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
-      EXPECT_EQ(static_cast<pid_t>(dump.pid()), pid);
-      profile_packets++;
-      for (const auto& sample : dump.samples()) {
-        samples++;
-        total_allocated += sample.self_allocated();
+    const auto& packets = helper->trace();
+    ASSERT_GT(packets.size(), 0u);
+    size_t profile_packets = 0;
+    size_t samples = 0;
+    uint64_t total_allocated = 0;
+    for (const protos::TracePacket& packet : packets) {
+      if (packet.has_profile_packet() &&
+          packet.profile_packet().process_dumps().size() > 0) {
+        const auto& dumps = packet.profile_packet().process_dumps();
+        ASSERT_EQ(dumps.size(), 1);
+        const protos::ProfilePacket_ProcessHeapSamples& dump = dumps.Get(0);
+        EXPECT_EQ(dump.pid(), pid);
+        profile_packets++;
+        for (const auto& sample : dump.samples()) {
+          samples++;
+          total_allocated += sample.self_allocated();
+        }
       }
     }
+    EXPECT_EQ(profile_packets, 1);
+    EXPECT_GT(samples, 0);
+    EXPECT_GT(total_allocated, 0);
   }
-  EXPECT_EQ(profile_packets, 1u);
-  EXPECT_GT(samples, 0u);
-  EXPECT_GT(total_allocated, 0u);
+};
+
+// TODO(b/118428762): look into unwinding issues on x86.
+#if defined(__i386__) || defined(__x86_64__)
+#define MAYBE_SKIP(x) DISABLED_##x
+#else
+#define MAYBE_SKIP(x) x
+#endif
+
+TEST_F(HeapprofdEndToEnd, MAYBE_SKIP(Smoke_Central)) {
+  auto prop = DisableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "");
+  Smoke();
 }
 
-// This test only works when run on Android using an Android Q version of
-// Bionic.
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-    PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
-INSTANTIATE_TEST_CASE_P(DISABLED_Run, HeapprofdEndToEnd, Bool(), TestSuffix);
-#else
-INSTANTIATE_TEST_CASE_P(Run, HeapprofdEndToEnd, Bool(), TestSuffix);
-#endif
+TEST_F(HeapprofdEndToEnd, MAYBE_SKIP(TwoProcesses_Fork)) {
+  // RAII handle that resets to central mode when out of scope.
+  auto prop = EnableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "fork");
+  TwoProcesses();
+}
+
+TEST_F(HeapprofdEndToEnd, MAYBE_SKIP(TwoProcesses_Central)) {
+  auto prop = DisableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "");
+  TwoProcesses();
+}
+
+TEST_F(HeapprofdEndToEnd, MAYBE_SKIP(Smoke_Fork)) {
+  // RAII handle that resets to central mode when out of scope.
+  auto prop = EnableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "fork");
+  Smoke();
+}
+
+TEST_F(HeapprofdEndToEnd, MAYBE_SKIP(FinalFlush_Central)) {
+  auto prop = DisableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "");
+  FinalFlush();
+}
+
+TEST_F(HeapprofdEndToEnd, MAYBE_SKIP(FinalFlush_Fork)) {
+  // RAII handle that resets to central mode when out of scope.
+  auto prop = EnableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "fork");
+  FinalFlush();
+}
+
+TEST_F(HeapprofdEndToEnd, MAYBE_SKIP(NativeStartup_Central)) {
+  auto prop = DisableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "");
+  NativeStartup();
+}
+
+TEST_F(HeapprofdEndToEnd, MAYBE_SKIP(NativeStartup_Fork)) {
+  // RAII handle that resets to central mode when out of scope.
+  auto prop = EnableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "fork");
+  NativeStartup();
+}
+
+TEST_F(HeapprofdEndToEnd,
+       MAYBE_SKIP(NativeStartupDenormalizedCmdline_Central)) {
+  auto prop = DisableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "");
+  NativeStartupDenormalizedCmdline();
+}
+
+TEST_F(HeapprofdEndToEnd, MAYBE_SKIP(NativeStartupDenormalizedCmdline_Fork)) {
+  // RAII handle that resets to central mode when out of scope.
+  auto prop = EnableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "fork");
+  NativeStartupDenormalizedCmdline();
+}
+
+TEST_F(HeapprofdEndToEnd, MAYBE_SKIP(DiscoverByName_Central)) {
+  auto prop = DisableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "");
+  DiscoverByName();
+}
+
+TEST_F(HeapprofdEndToEnd, MAYBE_SKIP(DiscoverByName_Fork)) {
+  // RAII handle that resets to central mode when out of scope.
+  auto prop = EnableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "fork");
+  DiscoverByName();
+}
+
+TEST_F(HeapprofdEndToEnd,
+       MAYBE_SKIP(DiscoverByNameDenormalizedCmdline_Central)) {
+  auto prop = DisableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "");
+  DiscoverByNameDenormalizedCmdline();
+}
+
+TEST_F(HeapprofdEndToEnd, MAYBE_SKIP(DiscoverByNameDenormalizedCmdline_Fork)) {
+  auto prop = DisableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "");
+  DiscoverByNameDenormalizedCmdline();
+}
+
+TEST_F(HeapprofdEndToEnd, MAYBE_SKIP(ReInit_Central)) {
+  auto prop = DisableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "");
+  ReInit();
+}
+
+TEST_F(HeapprofdEndToEnd, MAYBE_SKIP(ReInit_Fork)) {
+  // RAII handle that resets to central mode when out of scope.
+  auto prop = EnableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "fork");
+  ReInit();
+}
+
+TEST_F(HeapprofdEndToEnd, MAYBE_SKIP(ConcurrentSession_Central)) {
+  auto prop = DisableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "");
+  ConcurrentSession();
+}
+
+TEST_F(HeapprofdEndToEnd, MAYBE_SKIP(ConcurrentSession_Fork)) {
+  // RAII handle that resets to central mode when out of scope.
+  auto prop = EnableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "fork");
+  ConcurrentSession();
+}
+
+TEST_F(HeapprofdEndToEnd,
+       MAYBE_SKIP(NativeProfilingActiveAtProcessExit_Central)) {
+  auto prop = DisableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "");
+  NativeProfilingActiveAtProcessExit();
+}
+
+TEST_F(HeapprofdEndToEnd, MAYBE_SKIP(NativeProfilingActiveAtProcessExit_Fork)) {
+  // RAII handle that resets to central mode when out of scope.
+  auto prop = EnableFork();
+  ASSERT_EQ(ReadProperty(kHeapprofdModeProperty, ""), "fork");
+  NativeProfilingActiveAtProcessExit();
+}
 
 }  // namespace
 }  // namespace profiling
diff --git a/src/profiling/memory/heapprofd_producer.cc b/src/profiling/memory/heapprofd_producer.cc
index c10adc3..60067b2 100644
--- a/src/profiling/memory/heapprofd_producer.cc
+++ b/src/profiling/memory/heapprofd_producer.cc
@@ -16,21 +16,19 @@
 
 #include "src/profiling/memory/heapprofd_producer.h"
 
-#include <algorithm>
-
 #include <inttypes.h>
 #include <signal.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
 
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/thread_task_runner.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "perfetto/ext/tracing/ipc/producer_ipc_client.h"
+#include "perfetto/base/file_utils.h"
+#include "perfetto/base/string_utils.h"
+#include "perfetto/base/thread_task_runner.h"
 #include "perfetto/tracing/core/data_source_config.h"
 #include "perfetto/tracing/core/data_source_descriptor.h"
+#include "perfetto/tracing/core/trace_writer.h"
+#include "perfetto/tracing/ipc/producer_ipc_client.h"
 
 namespace perfetto {
 namespace profiling {
@@ -49,6 +47,13 @@
 constexpr uint64_t kDefaultShmemSize = 8 * 1048576;  // ~8 MB
 constexpr uint64_t kMaxShmemSize = 500 * 1048576;    // ~500 MB
 
+ClientConfiguration MakeClientConfiguration(const DataSourceConfig& cfg) {
+  ClientConfiguration client_config;
+  client_config.interval = cfg.heapprofd_config().sampling_interval_bytes();
+  client_config.block_client = cfg.heapprofd_config().block_client();
+  return client_config;
+}
+
 std::vector<UnwindingWorker> MakeUnwindingWorkers(HeapprofdProducer* delegate,
                                                   size_t n) {
   std::vector<UnwindingWorker> ret;
@@ -121,9 +126,35 @@
       mode_(mode),
       unwinding_workers_(MakeUnwindingWorkers(this, kUnwinderThreads)),
       socket_delegate_(this),
-      weak_factory_(this) {}
+      weak_factory_(this) {
+  if (mode == HeapprofdMode::kCentral) {
+    listening_socket_ = MakeListeningSocket();
+  }
+}
 
-HeapprofdProducer::~HeapprofdProducer() = default;
+HeapprofdProducer::~HeapprofdProducer() {
+  // We only borrowed this from the environment variable.
+  // UnixSocket always owns the socket, so we need to manually release it
+  // here.
+  if (mode_ == HeapprofdMode::kCentral && bool(listening_socket_))
+    listening_socket_->ReleaseSocket().ReleaseFd().release();
+}
+
+std::unique_ptr<base::UnixSocket> HeapprofdProducer::MakeListeningSocket() {
+  const char* sock_fd = getenv(kHeapprofdSocketEnvVar);
+  if (sock_fd == nullptr) {
+    unlink(kHeapprofdSocketFile);
+    return base::UnixSocket::Listen(kHeapprofdSocketFile, &socket_delegate_,
+                                    task_runner_);
+  }
+  char* end;
+  int raw_fd = static_cast<int>(strtol(sock_fd, &end, 10));
+  if (*end != '\0')
+    PERFETTO_FATAL("Invalid %s. Expected decimal integer.",
+                   kHeapprofdSocketEnvVar);
+  return base::UnixSocket::Listen(base::ScopedFile(raw_fd), &socket_delegate_,
+                                  task_runner_);
+}
 
 void HeapprofdProducer::SetTargetProcess(pid_t target_pid,
                                          std::string target_cmdline,
@@ -137,7 +168,7 @@
   PERFETTO_DCHECK(mode_ == HeapprofdMode::kChild);
   auto socket = base::UnixSocket::AdoptConnected(
       std::move(inherited_fd_), &socket_delegate_, task_runner_,
-      base::SockFamily::kUnix, base::SockType::kStream);
+      base::SockType::kStream);
 
   HandleClientConnection(std::move(socket), target_process_);
 }
@@ -151,7 +182,6 @@
 
   DataSourceDescriptor desc;
   desc.set_name(kHeapprofdDataSource);
-  desc.set_will_notify_on_stop(true);
   endpoint_->RegisterDataSource(desc);
 }
 
@@ -288,29 +318,28 @@
 void HeapprofdProducer::OnTracingSetup() {}
 
 void HeapprofdProducer::SetupDataSource(DataSourceInstanceID id,
-                                        const DataSourceConfig& ds_config) {
+                                        const DataSourceConfig& cfg) {
   PERFETTO_DLOG("Setting up data source.");
-  if (mode_ == HeapprofdMode::kChild && ds_config.enable_extra_guardrails()) {
+  if (mode_ == HeapprofdMode::kChild && cfg.enable_extra_guardrails()) {
     PERFETTO_ELOG("enable_extra_guardrails is not supported on user.");
     return;
   }
 
-  HeapprofdConfig heapprofd_config;
-  heapprofd_config.ParseRawProto(ds_config.heapprofd_config_raw());
-
+  const HeapprofdConfig& heapprofd_config = cfg.heapprofd_config();
   if (heapprofd_config.all() && !heapprofd_config.pid().empty())
     PERFETTO_ELOG("No point setting all and pid");
   if (heapprofd_config.all() && !heapprofd_config.process_cmdline().empty())
     PERFETTO_ELOG("No point setting all and process_cmdline");
 
-  if (ds_config.name() != kHeapprofdDataSource) {
+  if (cfg.name() != kHeapprofdDataSource) {
     PERFETTO_DLOG("Invalid data source name.");
     return;
   }
 
-  if (data_sources_.find(id) != data_sources_.end()) {
-    PERFETTO_DFATAL_OR_ELOG(
-        "Received duplicated data source instance id: %" PRIu64, id);
+  auto it = data_sources_.find(id);
+  if (it != data_sources_.end()) {
+    PERFETTO_DFATAL("Received duplicated data source instance id: %" PRIu64,
+                    id);
     return;
   }
 
@@ -330,7 +359,7 @@
       PERFETTO_LOG("Child mode skipping concurrent data source.");
 
       // Manually write one ProfilePacket about the rejected session.
-      auto buffer_id = static_cast<BufferID>(ds_config.target_buffer());
+      auto buffer_id = static_cast<BufferID>(cfg.target_buffer());
       auto trace_writer = endpoint_->CreateTraceWriter(buffer_id);
       auto trace_packet = trace_writer->NewTracePacket();
       trace_packet->set_timestamp(
@@ -345,17 +374,14 @@
     }
   }
 
-  auto buffer_id = static_cast<BufferID>(ds_config.target_buffer());
-  DataSource data_source(endpoint_->CreateTraceWriter(buffer_id));
+  DataSource data_source;
   data_source.id = id;
-  auto& cli_config = data_source.client_configuration;
-  cli_config.interval = heapprofd_config.sampling_interval_bytes();
-  cli_config.block_client = heapprofd_config.block_client();
+  data_source.client_configuration = MakeClientConfiguration(cfg);
   data_source.config = heapprofd_config;
+  auto buffer_id = static_cast<BufferID>(cfg.target_buffer());
+  data_source.trace_writer = endpoint_->CreateTraceWriter(buffer_id);
   data_source.normalized_cmdlines = std::move(normalized_cmdlines);
-  data_source.stop_timeout_ms = ds_config.stop_timeout_ms();
 
-  WriteFixedInternings(data_source.trace_writer.get());
   data_sources_.emplace(id, std::move(data_source));
   PERFETTO_DLOG("Set up data source.");
 
@@ -372,77 +398,59 @@
   return false;
 }
 
-void HeapprofdProducer::SetStartupProperties(DataSource* data_source) {
-  const HeapprofdConfig& heapprofd_config = data_source->config;
-  if (heapprofd_config.all())
-    data_source->properties.emplace_back(properties_.SetAll());
-
-  for (std::string cmdline : data_source->normalized_cmdlines)
-    data_source->properties.emplace_back(
-        properties_.SetProperty(std::move(cmdline)));
-}
-
-void HeapprofdProducer::SignalRunningProcesses(DataSource* data_source) {
-  const HeapprofdConfig& heapprofd_config = data_source->config;
-
-  std::set<pid_t> pids;
-  if (heapprofd_config.all())
-    FindAllProfilablePids(&pids);
-  for (uint64_t pid : heapprofd_config.pid())
-    pids.emplace(static_cast<pid_t>(pid));
-
-  if (!data_source->normalized_cmdlines.empty())
-    FindPidsForCmdlines(data_source->normalized_cmdlines, &pids);
-
-  for (auto pid_it = pids.cbegin(); pid_it != pids.cend();) {
-    pid_t pid = *pid_it;
-    if (IsPidProfiled(pid)) {
-      PERFETTO_LOG("Rejecting concurrent session for %" PRIdMAX,
-                   static_cast<intmax_t>(pid));
-      data_source->rejected_pids.emplace(pid);
-      pid_it = pids.erase(pid_it);
-      continue;
-    }
-
-    PERFETTO_DLOG("Sending %d to %d", kHeapprofdSignal, pid);
-    if (kill(pid, kHeapprofdSignal) != 0) {
-      PERFETTO_DPLOG("kill");
-    }
-    ++pid_it;
-  }
-  data_source->signaled_pids = std::move(pids);
-}
-
 void HeapprofdProducer::StartDataSource(DataSourceInstanceID id,
-                                        const DataSourceConfig&) {
+                                        const DataSourceConfig& cfg) {
   PERFETTO_DLOG("Start DataSource");
+  const HeapprofdConfig& heapprofd_config = cfg.heapprofd_config();
 
   auto it = data_sources_.find(id);
   if (it == data_sources_.end()) {
     // This is expected in child heapprofd, where we reject uninteresting data
     // sources in SetupDataSource.
     if (mode_ == HeapprofdMode::kCentral) {
-      PERFETTO_DFATAL_OR_ELOG(
+      PERFETTO_DFATAL(
           "Received invalid data source instance to start: %" PRIu64, id);
     }
     return;
   }
-
   DataSource& data_source = it->second;
-  if (data_source.started) {
-    PERFETTO_DFATAL_OR_ELOG(
-        "Trying to start already started data-source: %" PRIu64, id);
-    return;
-  }
-  const HeapprofdConfig& heapprofd_config = data_source.config;
 
   // Central daemon - set system properties for any targets that start later,
   // and signal already-running targets to start the profiling client.
   if (mode_ == HeapprofdMode::kCentral) {
-    if (!heapprofd_config.no_startup())
-      SetStartupProperties(&data_source);
-    if (!heapprofd_config.no_running())
-      SignalRunningProcesses(&data_source);
+    if (heapprofd_config.all())
+      data_source.properties.emplace_back(properties_.SetAll());
+
+    for (std::string cmdline : data_source.normalized_cmdlines)
+      data_source.properties.emplace_back(
+          properties_.SetProperty(std::move(cmdline)));
+
+    std::set<pid_t> pids;
+    if (heapprofd_config.all())
+      FindAllProfilablePids(&pids);
+    for (uint64_t pid : heapprofd_config.pid())
+      pids.emplace(static_cast<pid_t>(pid));
+
+    if (!data_source.normalized_cmdlines.empty())
+      FindPidsForCmdlines(data_source.normalized_cmdlines, &pids);
+
+    for (auto pid_it = pids.cbegin(); pid_it != pids.cend();) {
+      pid_t pid = *pid_it;
+      if (IsPidProfiled(pid)) {
+        PERFETTO_LOG("Rejecting concurrent session for %" PRIdMAX,
+                     static_cast<intmax_t>(pid));
+        data_source.rejected_pids.emplace(pid);
+        pid_it = pids.erase(pid_it);
+        continue;
+      }
+
+      PERFETTO_DLOG("Sending %d to %d", kHeapprofdSignal, pid);
+      if (kill(pid, kHeapprofdSignal) != 0) {
+        PERFETTO_DPLOG("kill");
+      }
+      ++pid_it;
+    }
+    data_source.signaled_pids = std::move(pids);
   }
 
   const auto continuous_dump_config = heapprofd_config.continuous_dump_config();
@@ -457,7 +465,6 @@
         },
         continuous_dump_config.dump_phase_ms());
   }
-  data_source.started = true;
   PERFETTO_DLOG("Started DataSource");
 }
 
@@ -469,61 +476,25 @@
   auto it = data_sources_.find(id);
   if (it == data_sources_.end()) {
     if (mode_ == HeapprofdMode::kCentral)
-      PERFETTO_DFATAL_OR_ELOG(
-          "Trying to stop non existing data source: %" PRIu64, id);
+      PERFETTO_DFATAL("Trying to stop non existing data source: %" PRIu64, id);
     return;
   }
 
   DataSource& data_source = it->second;
-  data_source.shutting_down = true;
-
-  // If no processes connected, or all of them have already disconnected
-  // (and have been dumped) and no PIDs have been rejected,
-  // MaybeFinishDataSource can tear down the data source.
-  if (MaybeFinishDataSource(&data_source))
-    return;
-
-  if (!data_source.rejected_pids.empty()) {
-    auto trace_packet = data_source.trace_writer->NewTracePacket();
-    ProfilePacket* profile_packet = trace_packet->set_profile_packet();
-    for (pid_t rejected_pid : data_source.rejected_pids) {
-      ProfilePacket::ProcessHeapSamples* proto =
-          profile_packet->add_process_dumps();
-      proto->set_pid(static_cast<uint64_t>(rejected_pid));
-      proto->set_rejected_concurrent(true);
-    }
-    trace_packet->Finalize();
-    data_source.rejected_pids.clear();
-    if (MaybeFinishDataSource(&data_source))
-      return;
-  }
-
   for (const auto& pid_and_process_state : data_source.process_states) {
     pid_t pid = pid_and_process_state.first;
     UnwinderForPID(pid).PostDisconnectSocket(pid);
   }
-  auto weak_producer = weak_factory_.GetWeakPtr();
-  task_runner_->PostDelayedTask(
-      [weak_producer, id] {
-        if (!weak_producer)
-          return;
-        auto ds_it = weak_producer->data_sources_.find(id);
-        if (ds_it != weak_producer->data_sources_.end()) {
-          PERFETTO_ELOG("Final dump timed out.");
-          DataSource& ds = ds_it->second;
-          // Do not dump any stragglers, just trigger the Flush and tear down
-          // the data source.
-          ds.process_states.clear();
-          ds.rejected_pids.clear();
-          PERFETTO_CHECK(weak_producer->MaybeFinishDataSource(&ds));
-        }
-      },
-      data_source.stop_timeout_ms);
+
+  data_sources_.erase(it);
+
+  if (mode_ == HeapprofdMode::kChild)
+    TerminateProcess(/*exit_status=*/0);  // does not return
 }
 
 void HeapprofdProducer::DoContinuousDump(DataSourceInstanceID id,
                                          uint32_t dump_interval) {
-  if (!DumpProcessesInDataSource(id))
+  if (!Dump(id, 0 /* flush_id */, false /* is_flush */))
     return;
   auto weak_producer = weak_factory_.GetWeakPtr();
   task_runner_->PostDelayedTask(
@@ -535,73 +506,9 @@
       dump_interval);
 }
 
-void HeapprofdProducer::DumpProcessState(DataSource* data_source,
-                                         pid_t pid,
-                                         ProcessState* process_state) {
-  HeapTracker& heap_tracker = process_state->heap_tracker;
-
-  bool from_startup =
-      data_source->signaled_pids.find(pid) == data_source->signaled_pids.cend();
-  uint64_t dump_timestamp;
-  if (data_source->config.dump_at_max())
-    dump_timestamp = heap_tracker.max_timestamp();
-  else
-    dump_timestamp = heap_tracker.committed_timestamp();
-  auto new_heapsamples = [pid, from_startup, dump_timestamp, process_state](
-                             ProfilePacket::ProcessHeapSamples* proto) {
-    proto->set_pid(static_cast<uint64_t>(pid));
-    proto->set_timestamp(dump_timestamp);
-    proto->set_from_startup(from_startup);
-    proto->set_disconnected(process_state->disconnected);
-    proto->set_buffer_overran(process_state->buffer_overran);
-    proto->set_buffer_corrupted(process_state->buffer_corrupted);
-    auto* stats = proto->set_stats();
-    stats->set_unwinding_errors(process_state->unwinding_errors);
-    stats->set_heap_samples(process_state->heap_samples);
-    stats->set_map_reparses(process_state->map_reparses);
-    stats->set_total_unwinding_time_us(process_state->total_unwinding_time_us);
-    auto* unwinding_hist = stats->set_unwinding_time_us();
-    for (const auto& p : process_state->unwinding_time_us.GetData()) {
-      auto* bucket = unwinding_hist->add_buckets();
-      if (p.first == LogHistogram::kMaxBucket)
-        bucket->set_max_bucket(true);
-      else
-        bucket->set_upper_limit(p.first);
-      bucket->set_count(p.second);
-    }
-  };
-
-  DumpState dump_state(data_source->trace_writer.get(),
-                       std::move(new_heapsamples), &data_source->intern_state);
-
-  if (process_state->page_idle_checker) {
-    PageIdleChecker& page_idle_checker = *process_state->page_idle_checker;
-    heap_tracker.GetAllocations([&dump_state, &page_idle_checker](
-                                    uint64_t addr, uint64_t,
-                                    uint64_t alloc_size,
-                                    uint64_t callstack_id) {
-      int64_t idle =
-          page_idle_checker.OnIdlePage(addr, static_cast<size_t>(alloc_size));
-      if (idle < 0) {
-        PERFETTO_PLOG("OnIdlePage.");
-        return;
-      }
-      if (idle > 0)
-        dump_state.AddIdleBytes(callstack_id, static_cast<uint64_t>(idle));
-    });
-  }
-
-  heap_tracker.GetCallstackAllocations(
-      [&dump_state,
-       &data_source](const HeapTracker::CallstackAllocations& alloc) {
-        dump_state.WriteAllocation(alloc, data_source->config.dump_at_max());
-      });
-  if (process_state->page_idle_checker)
-    process_state->page_idle_checker->MarkPagesIdle();
-  dump_state.DumpCallstacks(&callsites_);
-}
-
-bool HeapprofdProducer::DumpProcessesInDataSource(DataSourceInstanceID id) {
+bool HeapprofdProducer::Dump(DataSourceInstanceID id,
+                             FlushRequestID flush_id,
+                             bool has_flush_id) {
   auto it = data_sources_.find(id);
   if (it == data_sources_.end()) {
     PERFETTO_LOG(
@@ -610,19 +517,79 @@
   }
   DataSource& data_source = it->second;
 
+  DumpState dump_state(data_source.trace_writer.get(),
+                       &data_source.next_index_);
+
+  for (pid_t rejected_pid : data_source.rejected_pids) {
+    ProfilePacket::ProcessHeapSamples* proto =
+        dump_state.current_profile_packet->add_process_dumps();
+    proto->set_pid(static_cast<uint64_t>(rejected_pid));
+    proto->set_rejected_concurrent(true);
+  }
+
   for (std::pair<const pid_t, ProcessState>& pid_and_process_state :
        data_source.process_states) {
     pid_t pid = pid_and_process_state.first;
     ProcessState& process_state = pid_and_process_state.second;
-    DumpProcessState(&data_source, pid, &process_state);
+    HeapTracker& heap_tracker = process_state.heap_tracker;
+    bool from_startup =
+        data_source.signaled_pids.find(pid) == data_source.signaled_pids.cend();
+    auto new_heapsamples = [pid, from_startup, &process_state](
+                               ProfilePacket::ProcessHeapSamples* proto) {
+      proto->set_pid(static_cast<uint64_t>(pid));
+      proto->set_from_startup(from_startup);
+      proto->set_disconnected(process_state.disconnected);
+      proto->set_buffer_overran(process_state.buffer_overran);
+      proto->set_buffer_corrupted(process_state.buffer_corrupted);
+      auto* stats = proto->set_stats();
+      stats->set_unwinding_errors(process_state.unwinding_errors);
+      stats->set_heap_samples(process_state.heap_samples);
+      stats->set_map_reparses(process_state.map_reparses);
+      stats->set_total_unwinding_time_us(process_state.total_unwinding_time_us);
+      auto* unwinding_hist = stats->set_unwinding_time_us();
+      for (const auto& p : process_state.unwinding_time_us.GetData()) {
+        auto* bucket = unwinding_hist->add_buckets();
+        if (p.first == LogHistogram::kMaxBucket)
+          bucket->set_max_bucket(true);
+        else
+          bucket->set_upper_limit(p.first);
+        bucket->set_count(p.second);
+      }
+    };
+    heap_tracker.Dump(std::move(new_heapsamples), &dump_state);
   }
 
+  for (GlobalCallstackTrie::Node* node : dump_state.callstacks_to_dump) {
+    // There need to be two separate loops over built_callstack because
+    // protozero cannot interleave different messages.
+    auto built_callstack = callsites_.BuildCallstack(node);
+    for (const Interned<Frame>& frame : built_callstack)
+      dump_state.WriteFrame(frame);
+    ProfilePacket::Callstack* callstack =
+        dump_state.current_profile_packet->add_callstacks();
+    callstack->set_id(node->id());
+    for (const Interned<Frame>& frame : built_callstack)
+      callstack->add_frame_ids(frame.id());
+  }
+
+  dump_state.current_trace_packet->Finalize();
+  if (has_flush_id) {
+    auto weak_producer = weak_factory_.GetWeakPtr();
+    auto callback = [weak_producer, flush_id] {
+      if (weak_producer)
+        return weak_producer->task_runner_->PostTask([weak_producer, flush_id] {
+          if (weak_producer)
+            return weak_producer->FinishDataSourceFlush(flush_id);
+        });
+    };
+    data_source.trace_writer->Flush(std::move(callback));
+  }
   return true;
 }
 
 void HeapprofdProducer::DumpAll() {
   for (const auto& id_and_data_source : data_sources_) {
-    if (!DumpProcessesInDataSource(id_and_data_source.first))
+    if (!Dump(id_and_data_source.first, 0 /* flush_id */, false /* is_flush */))
       PERFETTO_DLOG("Failed to dump %" PRIu64, id_and_data_source.first);
   }
 }
@@ -636,34 +603,14 @@
   size_t& flush_in_progress = flushes_in_progress_[flush_id];
   PERFETTO_DCHECK(flush_in_progress == 0);
   flush_in_progress = num_ids;
-  for (size_t i = 0; i < num_ids; ++i) {
-    auto it = data_sources_.find(ids[i]);
-    if (it == data_sources_.end()) {
-      PERFETTO_DFATAL_OR_ELOG("Trying to flush unknown data-source %" PRIu64,
-                              ids[i]);
-      continue;
-    }
-    DataSource& data_source = it->second;
-    auto weak_producer = weak_factory_.GetWeakPtr();
-
-    auto callback = [weak_producer, flush_id] {
-      if (weak_producer)
-        // Reposting because this task runner could be on a different thread
-        // than the IPC task runner.
-        return weak_producer->task_runner_->PostTask([weak_producer, flush_id] {
-          if (weak_producer)
-            return weak_producer->FinishDataSourceFlush(flush_id);
-        });
-    };
-    data_source.trace_writer->Flush(std::move(callback));
-  }
+  for (size_t i = 0; i < num_ids; ++i)
+    Dump(ids[i], flush_id, true);
 }
 
 void HeapprofdProducer::FinishDataSourceFlush(FlushRequestID flush_id) {
   auto it = flushes_in_progress_.find(flush_id);
   if (it == flushes_in_progress_.end()) {
-    PERFETTO_DFATAL_OR_ELOG("FinishDataSourceFlush id invalid: %" PRIu64,
-                            flush_id);
+    PERFETTO_DFATAL("FinishDataSourceFlush id invalid: %" PRIu64, flush_id);
     return;
   }
   size_t& flush_in_progress = it->second;
@@ -676,7 +623,7 @@
 void HeapprofdProducer::SocketDelegate::OnDisconnect(base::UnixSocket* self) {
   auto it = producer_->pending_processes_.find(self->peer_pid());
   if (it == producer_->pending_processes_.end()) {
-    PERFETTO_DFATAL_OR_ELOG("Unexpected disconnect.");
+    PERFETTO_DFATAL("Unexpected disconnect.");
     return;
   }
 
@@ -699,7 +646,7 @@
     base::UnixSocket* self) {
   auto it = producer_->pending_processes_.find(self->peer_pid());
   if (it == producer_->pending_processes_.end()) {
-    PERFETTO_DFATAL_OR_ELOG("Unexpected data.");
+    PERFETTO_DFATAL("Unexpected data.");
     return;
   }
 
@@ -709,9 +656,7 @@
   char buf[1];
   self->Receive(buf, sizeof(buf), fds, base::ArraySize(fds));
 
-  static_assert(kHandshakeSize == 3, "change if and else if below.");
-  // We deliberately do not check for fds[kHandshakePageIdle] so we can
-  // degrade gracefully on kernels that do not have the file yet.
+  static_assert(kHandshakeSize == 2, "change if below.");
   if (fds[kHandshakeMaps] && fds[kHandshakeMem]) {
     auto ds_it =
         producer_->data_sources_.find(pending_process.data_source_instance_id);
@@ -719,31 +664,10 @@
       producer_->pending_processes_.erase(it);
       return;
     }
+
     DataSource& data_source = ds_it->second;
-
-    if (data_source.shutting_down) {
-      producer_->pending_processes_.erase(it);
-      PERFETTO_LOG("Got handshake for DS that is shutting down. Rejecting.");
-      return;
-    }
-
-    auto it_and_inserted = data_source.process_states.emplace(
-        std::piecewise_construct, std::forward_as_tuple(self->peer_pid()),
-        std::forward_as_tuple(&producer_->callsites_,
-                              data_source.config.dump_at_max()));
-
-    ProcessState& process_state = it_and_inserted.first->second;
-    if (data_source.config.idle_allocations()) {
-      if (fds[kHandshakePageIdle]) {
-        process_state.page_idle_checker =
-            PageIdleChecker(std::move(fds[kHandshakePageIdle]));
-      } else {
-        PERFETTO_ELOG(
-            "Idle page tracking requested but did not receive "
-            "page_idle file. Continuing without idle page tracking. Please "
-            "check your kernel version.");
-      }
-    }
+    data_source.process_states.emplace(self->peer_pid(),
+                                       &producer_->callsites_);
 
     PERFETTO_DLOG("%d: Received FDs.", self->peer_pid());
     int raw_fd = pending_process.shmem.fd();
@@ -756,20 +680,19 @@
     handoff_data.data_source_instance_id =
         pending_process.data_source_instance_id;
     handoff_data.sock = self->ReleaseSocket();
-    handoff_data.maps_fd = std::move(fds[kHandshakeMaps]);
-    handoff_data.mem_fd = std::move(fds[kHandshakeMem]);
+    for (size_t i = 0; i < kHandshakeSize; ++i)
+      handoff_data.fds[i] = std::move(fds[i]);
     handoff_data.shmem = std::move(pending_process.shmem);
     handoff_data.client_config = data_source.client_configuration;
 
     producer_->UnwinderForPID(self->peer_pid())
         .PostHandoffSocket(std::move(handoff_data));
     producer_->pending_processes_.erase(it);
-  } else if (fds[kHandshakeMaps] || fds[kHandshakeMem] ||
-             fds[kHandshakePageIdle]) {
-    PERFETTO_DFATAL_OR_ELOG("%d: Received partial FDs.", self->peer_pid());
+  } else if (fds[kHandshakeMaps] || fds[kHandshakeMem]) {
+    PERFETTO_DFATAL("%d: Received partial FDs.", self->peer_pid());
     producer_->pending_processes_.erase(it);
   } else {
-    PERFETTO_ELOG("%d: Received no FDs.", self->peer_pid());
+    PERFETTO_DLOG("%d: Received no FDs.", self->peer_pid());
   }
 }
 
@@ -809,7 +732,7 @@
   if (shmem_size > kMaxShmemSize)
     shmem_size = kMaxShmemSize;
 
-  auto shmem = SharedRingBuffer::Create(static_cast<size_t>(shmem_size));
+  auto shmem = SharedRingBuffer::Create(shmem_size);
   if (!shmem || !shmem->is_valid()) {
     PERFETTO_LOG("Failed to create shared memory.");
     return;
@@ -817,7 +740,7 @@
 
   pid_t peer_pid = new_connection->peer_pid();
   if (peer_pid != process.pid) {
-    PERFETTO_DFATAL_OR_ELOG("Invalid PID connected.");
+    PERFETTO_DFATAL("Invalid PID connected.");
     return;
   }
 
@@ -900,8 +823,7 @@
   process_state.total_unwinding_time_us += alloc_rec.unwinding_time_us;
 
   heap_tracker.RecordMalloc(alloc_rec.frames, alloc_metadata.alloc_address,
-                            alloc_metadata.sample_size,
-                            alloc_metadata.alloc_size,
+                            alloc_metadata.total_size,
                             alloc_metadata.sequence_number,
                             alloc_metadata.clock_monotonic_coarse_timestamp);
 }
@@ -927,7 +849,7 @@
   const FreeBatchEntry* entries = free_batch.entries;
   uint64_t num_entries = free_batch.num_entries;
   if (num_entries > kFreeBatchSize) {
-    PERFETTO_DFATAL_OR_ELOG("Malformed free page.");
+    PERFETTO_DFATAL("Malformed free page.");
     return;
   }
   for (size_t i = 0; i < num_entries; ++i) {
@@ -937,38 +859,11 @@
   }
 }
 
-bool HeapprofdProducer::MaybeFinishDataSource(DataSource* ds) {
-  if (!ds->process_states.empty() || !ds->rejected_pids.empty() ||
-      !ds->shutting_down) {
-    return false;
-  }
-  DataSourceInstanceID ds_id = ds->id;
-  auto weak_producer = weak_factory_.GetWeakPtr();
-  ds->trace_writer->Flush([weak_producer, ds_id] {
-    if (!weak_producer)
-      return;
-
-    weak_producer->endpoint_->NotifyDataSourceStopped(ds_id);
-    weak_producer->data_sources_.erase(ds_id);
-
-    if (weak_producer->mode_ == HeapprofdMode::kChild) {
-      // Post this as a task to allow NotifyDataSourceStopped to post tasks.
-      weak_producer->task_runner_->PostTask([weak_producer] {
-        if (!weak_producer)
-          return;
-        weak_producer->TerminateProcess(
-            /*exit_status=*/0);  // does not return
-      });
-    }
-  });
-  return true;
-}
-
 void HeapprofdProducer::HandleSocketDisconnected(
-    DataSourceInstanceID ds_id,
+    DataSourceInstanceID id,
     pid_t pid,
     SharedRingBuffer::Stats stats) {
-  auto it = data_sources_.find(ds_id);
+  auto it = data_sources_.find(id);
   if (it == data_sources_.end())
     return;
   DataSource& ds = it->second;
@@ -977,15 +872,14 @@
   if (process_state_it == ds.process_states.end())
     return;
   ProcessState& process_state = process_state_it->second;
-  process_state.disconnected = !ds.shutting_down;
-  process_state.buffer_overran =
-      stats.num_writes_overflow > 0 && !ds.config.block_client();
+  process_state.disconnected = true;
+  process_state.buffer_overran = stats.num_writes_overflow > 0;
   process_state.buffer_corrupted =
       stats.num_writes_corrupt > 0 || stats.num_reads_corrupt > 0;
 
-  DumpProcessState(&ds, pid, &process_state);
-  ds.process_states.erase(pid);
-  MaybeFinishDataSource(&ds);
+  // TODO(fmayer): Dump on process disconnect rather than data source
+  // destruction. This prevents us needing to hold onto the bookkeeping data
+  // after the process disconnected.
 }
 
 }  // namespace profiling
diff --git a/src/profiling/memory/heapprofd_producer.h b/src/profiling/memory/heapprofd_producer.h
index e1299ae..567cca0 100644
--- a/src/profiling/memory/heapprofd_producer.h
+++ b/src/profiling/memory/heapprofd_producer.h
@@ -17,31 +17,25 @@
 #ifndef SRC_PROFILING_MEMORY_HEAPPROFD_PRODUCER_H_
 #define SRC_PROFILING_MEMORY_HEAPPROFD_PRODUCER_H_
 
-#include <array>
 #include <functional>
 #include <map>
-#include <vector>
 
+#include "perfetto/base/optional.h"
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/unix_socket.h"
-#include "perfetto/ext/base/unix_task_runner.h"
+#include "perfetto/base/unix_socket.h"
+#include "perfetto/base/unix_task_runner.h"
 
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/producer.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
+#include "perfetto/tracing/core/basic_types.h"
 #include "perfetto/tracing/core/data_source_config.h"
+#include "perfetto/tracing/core/producer.h"
+#include "perfetto/tracing/core/trace_writer.h"
+#include "perfetto/tracing/core/tracing_service.h"
 
 #include "src/profiling/memory/bookkeeping.h"
-#include "src/profiling/memory/bookkeeping_dump.h"
-#include "src/profiling/memory/page_idle_checker.h"
 #include "src/profiling/memory/proc_utils.h"
 #include "src/profiling/memory/system_property.h"
 #include "src/profiling/memory/unwinding.h"
 
-#include "protos/perfetto/config/profiling/heapprofd_config.gen.h"
-
 namespace perfetto {
 namespace profiling {
 
@@ -155,10 +149,6 @@
   void SetProducerEndpoint(
       std::unique_ptr<TracingService::ProducerEndpoint> endpoint);
 
-  base::UnixSocket::EventListener& socket_delegate() {
-    return socket_delegate_;
-  }
-
  private:
   // State of the connection to tracing service (traced).
   enum State {
@@ -169,8 +159,7 @@
   };
 
   struct ProcessState {
-    ProcessState(GlobalCallstackTrie* callsites, bool dump_at_max_mode)
-        : heap_tracker(callsites, dump_at_max_mode) {}
+    ProcessState(GlobalCallstackTrie* callsites) : heap_tracker(callsites) {}
     bool disconnected = false;
     bool buffer_overran = false;
     bool buffer_corrupted = false;
@@ -182,13 +171,9 @@
     uint64_t total_unwinding_time_us = 0;
     LogHistogram unwinding_time_us;
     HeapTracker heap_tracker;
-
-    base::Optional<PageIdleChecker> page_idle_checker;
   };
 
   struct DataSource {
-    DataSource(std::unique_ptr<TraceWriter> tw) : trace_writer(std::move(tw)) {}
-
     DataSourceInstanceID id;
     std::unique_ptr<TraceWriter> trace_writer;
     HeapprofdConfig config;
@@ -198,10 +183,7 @@
     std::set<pid_t> rejected_pids;
     std::map<pid_t, ProcessState> process_states;
     std::vector<std::string> normalized_cmdlines;
-    DumpState::InternState intern_state;
-    bool shutting_down = false;
-    bool started = false;
-    uint32_t stop_timeout_ms;
+    uint64_t next_index_ = 0;
   };
 
   struct PendingProcess {
@@ -219,9 +201,9 @@
   void IncreaseConnectionBackoff();
 
   void FinishDataSourceFlush(FlushRequestID flush_id);
-  bool DumpProcessesInDataSource(DataSourceInstanceID id);
-  void DumpProcessState(DataSource* ds, pid_t pid, ProcessState* process);
-
+  bool Dump(DataSourceInstanceID id,
+            FlushRequestID flush_id,
+            bool has_flush_id);
   void DoContinuousDump(DataSourceInstanceID id, uint32_t dump_interval);
 
   UnwindingWorker& UnwinderForPID(pid_t);
@@ -229,8 +211,8 @@
   DataSource* GetDataSourceForProcess(const Process& proc);
   void RecordOtherSourcesAsRejected(DataSource* active_ds, const Process& proc);
 
-  void SetStartupProperties(DataSource* data_source);
-  void SignalRunningProcesses(DataSource* data_source);
+  // Specific to mode_ == kCentral
+  std::unique_ptr<base::UnixSocket> MakeListeningSocket();
 
   // Specific to mode_ == kChild
   void TerminateProcess(int exit_status);
@@ -241,8 +223,6 @@
   // Specific to mode_ == kChild
   void AdoptTargetProcessSocket();
 
-  bool MaybeFinishDataSource(DataSource* ds);
-
   // Class state:
 
   // Task runner is owned by the main thread.
@@ -274,6 +254,9 @@
   std::map<DataSourceInstanceID, DataSource> data_sources_;
   std::vector<UnwindingWorker> unwinding_workers_;
 
+  // Specific to mode_ == kCentral
+  std::unique_ptr<base::UnixSocket> listening_socket_;
+
   // Specific to mode_ == kChild
   Process target_process_{base::kInvalidPid, ""};
   // This is a valid FD only between SetTargetProcess and
diff --git a/src/profiling/memory/heapprofd_producer_unittest.cc b/src/profiling/memory/heapprofd_producer_unittest.cc
index 66bd452..e3cb229 100644
--- a/src/profiling/memory/heapprofd_producer_unittest.cc
+++ b/src/profiling/memory/heapprofd_producer_unittest.cc
@@ -16,11 +16,14 @@
 
 #include "src/profiling/memory/heapprofd_producer.h"
 
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/commit_data_request.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "perfetto/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/commit_data_request.h"
 #include "perfetto/tracing/core/data_source_descriptor.h"
+
 #include "src/base/test/test_task_runner.h"
-#include "test/gtest_and_gmock.h"
 
 namespace perfetto {
 namespace profiling {
@@ -39,8 +42,7 @@
 
   MOCK_CONST_METHOD0(shared_memory, SharedMemory*());
   MOCK_CONST_METHOD0(shared_buffer_page_size_kb, size_t());
-  MOCK_METHOD2(CreateTraceWriter,
-               std::unique_ptr<TraceWriter>(BufferID, BufferExhaustedPolicy));
+  MOCK_METHOD1(CreateTraceWriter, std::unique_ptr<TraceWriter>(BufferID));
   MOCK_METHOD0(GetInProcessShmemArbiter, SharedMemoryArbiter*());
   MOCK_METHOD1(ActivateTriggers, void(const std::vector<std::string>&));
 
diff --git a/src/profiling/memory/interner.h b/src/profiling/memory/interner.h
index 2d3c677..e67fcb5 100644
--- a/src/profiling/memory/interner.h
+++ b/src/profiling/memory/interner.h
@@ -27,14 +27,14 @@
 namespace perfetto {
 namespace profiling {
 
-using InternID = uint32_t;
+using InternID = uint64_t;
 
 template <typename T>
 class Interner {
  private:
   struct Entry {
     template <typename... U>
-    Entry(Interner<T>* in, InternID i, U... args)
+    Entry(Interner<T>* in, uint64_t i, U... args)
         : data(std::forward<U...>(args...)), id(i), interner(in) {}
 
     bool operator<(const Entry& other) const { return data < other.data; }
@@ -47,8 +47,8 @@
     };
 
     const T data;
-    InternID id;
     size_t ref_count = 0;
+    uint64_t id;
     Interner<T>* interner;
   };
 
@@ -121,7 +121,7 @@
     if (--entry->ref_count == 0)
       entries_.erase(*entry);
   }
-  InternID next_id = 1;
+  uint64_t next_id = 1;
   std::unordered_set<Entry, typename Entry::Hash> entries_;
   static_assert(sizeof(Interned) == sizeof(void*),
                 "interned things should be small");
diff --git a/src/profiling/memory/interner_unittest.cc b/src/profiling/memory/interner_unittest.cc
index e43b348..6b239fd 100644
--- a/src/profiling/memory/interner_unittest.cc
+++ b/src/profiling/memory/interner_unittest.cc
@@ -16,7 +16,8 @@
 
 #include "src/profiling/memory/interner.h"
 
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace profiling {
@@ -28,7 +29,7 @@
     Interned<std::string> interned_str = interner.Intern("foo");
     ASSERT_EQ(interned_str.data(), "foo");
   }
-  ASSERT_EQ(interner.entry_count_for_testing(), 0u);
+  ASSERT_EQ(interner.entry_count_for_testing(), 0);
 }
 
 TEST(InternerStringTest, TwoStrings) {
@@ -39,7 +40,7 @@
     ASSERT_EQ(interned_str.data(), "foo");
     ASSERT_EQ(other_interned_str.data(), "bar");
   }
-  ASSERT_EQ(interner.entry_count_for_testing(), 0u);
+  ASSERT_EQ(interner.entry_count_for_testing(), 0);
 }
 
 TEST(InternerStringTest, TwoReferences) {
@@ -48,10 +49,10 @@
     Interned<std::string> interned_str = interner.Intern("foo");
     ASSERT_EQ(interned_str.data(), "foo");
     Interned<std::string> interned_str2 = interner.Intern("foo");
-    ASSERT_EQ(interner.entry_count_for_testing(), 1u);
+    ASSERT_EQ(interner.entry_count_for_testing(), 1);
     ASSERT_EQ(interned_str2.data(), "foo");
   }
-  ASSERT_EQ(interner.entry_count_for_testing(), 0u);
+  ASSERT_EQ(interner.entry_count_for_testing(), 0);
 }
 
 TEST(InternerStringTest, Move) {
@@ -60,10 +61,10 @@
     Interned<std::string> interned_str = interner.Intern("foo");
     {
       Interned<std::string> interned_str2(std::move(interned_str));
-      ASSERT_EQ(interner.entry_count_for_testing(), 1u);
+      ASSERT_EQ(interner.entry_count_for_testing(), 1);
       ASSERT_EQ(interned_str2.data(), "foo");
     }
-    ASSERT_EQ(interner.entry_count_for_testing(), 0u);
+    ASSERT_EQ(interner.entry_count_for_testing(), 0);
   }
 }
 
@@ -73,10 +74,10 @@
     Interned<std::string> interned_str = interner.Intern("foo");
     {
       Interned<std::string> interned_str2(interned_str);
-      ASSERT_EQ(interner.entry_count_for_testing(), 1u);
+      ASSERT_EQ(interner.entry_count_for_testing(), 1);
       ASSERT_EQ(interned_str2.data(), "foo");
     }
-    ASSERT_EQ(interner.entry_count_for_testing(), 1u);
+    ASSERT_EQ(interner.entry_count_for_testing(), 1);
     ASSERT_EQ(interned_str.data(), "foo");
   }
 }
@@ -87,10 +88,10 @@
     Interned<std::string> interned_str = interner.Intern("foo");
     {
       Interned<std::string> interned_str2 = std::move(interned_str);
-      ASSERT_EQ(interner.entry_count_for_testing(), 1u);
+      ASSERT_EQ(interner.entry_count_for_testing(), 1);
       ASSERT_EQ(interned_str2.data(), "foo");
     }
-    ASSERT_EQ(interner.entry_count_for_testing(), 0u);
+    ASSERT_EQ(interner.entry_count_for_testing(), 0);
   }
 }
 
@@ -100,10 +101,10 @@
     Interned<std::string> interned_str = interner.Intern("foo");
     {
       Interned<std::string> interned_str2 = interned_str;
-      ASSERT_EQ(interner.entry_count_for_testing(), 1u);
+      ASSERT_EQ(interner.entry_count_for_testing(), 1);
       ASSERT_EQ(interned_str2.data(), "foo");
     }
-    ASSERT_EQ(interner.entry_count_for_testing(), 1u);
+    ASSERT_EQ(interner.entry_count_for_testing(), 1);
     ASSERT_EQ(interned_str.data(), "foo");
   }
 }
@@ -125,7 +126,7 @@
     Interned<std::string> other_interned_str = interner.Intern("bar");
     ASSERT_EQ(interned_str.id() + 1, other_interned_str.id());
   }
-  ASSERT_EQ(interner.entry_count_for_testing(), 0u);
+  ASSERT_EQ(interner.entry_count_for_testing(), 0);
 }
 
 }  // namespace
diff --git a/src/profiling/memory/java_hprof.h b/src/profiling/memory/java_hprof.h
deleted file mode 100644
index 2e1d5f6..0000000
--- a/src/profiling/memory/java_hprof.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_PROFILING_MEMORY_JAVA_HPROF_H_
-#define SRC_PROFILING_MEMORY_JAVA_HPROF_H_
-
-#include "perfetto/ext/tracing/core/producer.h"
-
-namespace perfetto {
-namespace profiling {
-
-class JavaHprofProducer : public Producer {
- public:
-  // Producer Impl:
-  void OnConnect() override;
-  void OnDisconnect() override;
-  void SetupDataSource(DataSourceInstanceID, const DataSourceConfig&) override;
-  void StartDataSource(DataSourceInstanceID, const DataSourceConfig&) override;
-  void StopDataSource(DataSourceInstanceID) override;
-  void OnTracingSetup() override {}
-  void Flush(FlushRequestID,
-             const DataSourceInstanceID* data_source_ids,
-             size_t num_data_sources) override;
-  void ClearIncrementalState(const DataSourceInstanceID* /*data_source_ids*/,
-                             size_t /*num_data_sources*/) override {}
-  // TODO(fmayer): Refactor once/if we have generic reconnect logic.
-  void ConnectWithRetries(const char* socket_name);
-  void SetProducerEndpoint(
-      std::unique_ptr<TracingService::ProducerEndpoint> endpoint);
-
- private:
-  // State of the connection to tracing service (traced).
-  enum State {
-    kNotStarted = 0,
-    kNotConnected,
-    kConnecting,
-    kConnected,
-  };
-
-  void ConnectService();
-  void Restart();
-
-  // State of connection to the tracing service.
-  State state_ = kNotStarted;
-  uint32_t connection_backoff_ms_ = 0;
-  const char* producer_sock_name_ = nullptr;
-};
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // SRC_PROFILING_MEMORY_JAVA_HPROF_H_
diff --git a/src/profiling/memory/java_hprof_producer.cc b/src/profiling/memory/java_hprof_producer.cc
deleted file mode 100644
index 82346ec..0000000
--- a/src/profiling/memory/java_hprof_producer.cc
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/profiling/memory/java_hprof_producer.h"
-
-#include <signal.h>
-
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "src/profiling/memory/proc_utils.h"
-
-namespace perfetto {
-namespace profiling {
-namespace {
-
-constexpr int kJavaHeapprofdSignal = __SIGRTMIN + 6;
-constexpr uint32_t kInitialConnectionBackoffMs = 100;
-constexpr uint32_t kMaxConnectionBackoffMs = 30 * 1000;
-constexpr const char* kJavaHprofDataSource = "android.java_hprof";
-
-}  // namespace
-
-void JavaHprofProducer::DoContinuousDump(DataSourceInstanceID id,
-                                         uint32_t dump_interval) {
-  auto it = data_sources_.find(id);
-  if (it == data_sources_.end())
-    return;
-  const DataSource& ds = it->second;
-  SignalDataSource(ds);
-  auto weak_producer = weak_factory_.GetWeakPtr();
-  task_runner_->PostDelayedTask(
-      [weak_producer, id, dump_interval] {
-        if (!weak_producer)
-          return;
-        weak_producer->DoContinuousDump(id, dump_interval);
-      },
-      dump_interval);
-}
-
-// static
-void JavaHprofProducer::SignalDataSource(const DataSource& ds) {
-  const std::set<pid_t>& pids = ds.pids;
-  for (pid_t pid : pids) {
-    PERFETTO_DLOG("Sending %d to %d", kJavaHeapprofdSignal, pid);
-    if (kill(pid, kJavaHeapprofdSignal) != 0) {
-      PERFETTO_DPLOG("kill");
-    }
-  }
-}
-
-void JavaHprofProducer::IncreaseConnectionBackoff() {
-  connection_backoff_ms_ *= 2;
-  if (connection_backoff_ms_ > kMaxConnectionBackoffMs)
-    connection_backoff_ms_ = kMaxConnectionBackoffMs;
-}
-
-void JavaHprofProducer::ResetConnectionBackoff() {
-  connection_backoff_ms_ = kInitialConnectionBackoffMs;
-}
-
-void JavaHprofProducer::SetupDataSource(DataSourceInstanceID id,
-                                        const DataSourceConfig& ds_config) {
-  if (data_sources_.find(id) != data_sources_.end()) {
-    PERFETTO_DFATAL_OR_ELOG("Duplicate data source: %" PRIu64, id);
-    return;
-  }
-  JavaHprofConfig config;
-  config.ParseRawProto(ds_config.java_hprof_config_raw());
-  DataSource ds;
-  ds.id = id;
-  for (uint64_t pid : config.pid())
-    ds.pids.emplace(static_cast<pid_t>(pid));
-  auto normalized_cmdlines = NormalizeCmdlines(config.process_cmdline());
-  FindPidsForCmdlines(normalized_cmdlines, &ds.pids);
-  ds.config = std::move(config);
-  data_sources_.emplace(id, std::move(ds));
-}
-
-void JavaHprofProducer::StartDataSource(DataSourceInstanceID id,
-                                        const DataSourceConfig&) {
-  auto it = data_sources_.find(id);
-  if (it == data_sources_.end()) {
-    PERFETTO_DFATAL_OR_ELOG("Starting invalid data source: %" PRIu64, id);
-    return;
-  }
-  const DataSource& ds = it->second;
-  const auto continuous_dump_config = ds.config.continuous_dump_config();
-  uint32_t dump_interval = continuous_dump_config.dump_interval_ms();
-  if (dump_interval) {
-    auto weak_producer = weak_factory_.GetWeakPtr();
-    task_runner_->PostDelayedTask(
-        [weak_producer, id, dump_interval] {
-          if (!weak_producer)
-            return;
-          weak_producer->DoContinuousDump(id, dump_interval);
-        },
-        continuous_dump_config.dump_phase_ms());
-  }
-  SignalDataSource(ds);
-}
-
-void JavaHprofProducer::StopDataSource(DataSourceInstanceID id) {
-  auto it = data_sources_.find(id);
-  if (it == data_sources_.end()) {
-    PERFETTO_DFATAL_OR_ELOG("Stopping invalid data source: %" PRIu64, id);
-    return;
-  }
-  data_sources_.erase(it);
-}
-
-void JavaHprofProducer::Flush(FlushRequestID flush_id,
-                              const DataSourceInstanceID*,
-                              size_t) {
-  endpoint_->NotifyFlushComplete(flush_id);
-}
-
-void JavaHprofProducer::OnConnect() {
-  PERFETTO_DCHECK(state_ == kConnecting);
-  state_ = kConnected;
-  ResetConnectionBackoff();
-  PERFETTO_LOG("Connected to the service.");
-
-  DataSourceDescriptor desc;
-  desc.set_name(kJavaHprofDataSource);
-  endpoint_->RegisterDataSource(desc);
-}
-
-void JavaHprofProducer::Restart() {
-  // We lost the connection with the tracing service. At this point we need
-  // to reset all the data sources. Trying to handle that manually is going to
-  // be error prone. What we do here is simply destroy the instance and
-  // recreate it again.
-  base::TaskRunner* task_runner = task_runner_;
-  const char* socket_name = producer_sock_name_;
-
-  // Invoke destructor and then the constructor again.
-  this->~JavaHprofProducer();
-  new (this) JavaHprofProducer(task_runner);
-
-  ConnectWithRetries(socket_name);
-}
-
-void JavaHprofProducer::ConnectWithRetries(const char* socket_name) {
-  PERFETTO_DCHECK(state_ == kNotStarted);
-  state_ = kNotConnected;
-
-  ResetConnectionBackoff();
-  producer_sock_name_ = socket_name;
-  ConnectService();
-}
-
-void JavaHprofProducer::SetProducerEndpoint(
-    std::unique_ptr<TracingService::ProducerEndpoint> endpoint) {
-  PERFETTO_DCHECK(state_ == kNotConnected || state_ == kNotStarted);
-  state_ = kConnecting;
-  endpoint_ = std::move(endpoint);
-}
-
-void JavaHprofProducer::ConnectService() {
-  SetProducerEndpoint(ProducerIPCClient::Connect(
-      producer_sock_name_, this, "android.java_hprof", task_runner_));
-}
-
-void JavaHprofProducer::OnDisconnect() {
-  PERFETTO_DCHECK(state_ == kConnected || state_ == kConnecting);
-  PERFETTO_LOG("Disconnected from tracing service");
-
-  auto weak_producer = weak_factory_.GetWeakPtr();
-  if (state_ == kConnected)
-    return task_runner_->PostTask([weak_producer] {
-      if (!weak_producer)
-        return;
-      weak_producer->Restart();
-    });
-
-  state_ = kNotConnected;
-  IncreaseConnectionBackoff();
-  task_runner_->PostDelayedTask(
-      [weak_producer] {
-        if (!weak_producer)
-          return;
-        weak_producer->ConnectService();
-      },
-      connection_backoff_ms_);
-}
-
-}  // namespace profiling
-}  // namespace perfetto
diff --git a/src/profiling/memory/java_hprof_producer.h b/src/profiling/memory/java_hprof_producer.h
deleted file mode 100644
index cabdeae..0000000
--- a/src/profiling/memory/java_hprof_producer.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_PROFILING_MEMORY_JAVA_HPROF_PRODUCER_H_
-#define SRC_PROFILING_MEMORY_JAVA_HPROF_PRODUCER_H_
-
-#include <memory>
-#include <set>
-#include <vector>
-
-#include "perfetto/ext/base/unix_task_runner.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/tracing/core/producer.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
-#include "perfetto/ext/tracing/ipc/producer_ipc_client.h"
-#include "perfetto/tracing/core/data_source_config.h"
-#include "perfetto/tracing/core/data_source_descriptor.h"
-
-#include "protos/perfetto/config/profiling/java_hprof_config.gen.h"
-
-namespace perfetto {
-namespace profiling {
-
-class JavaHprofProducer : public Producer {
- public:
-  JavaHprofProducer(base::TaskRunner* task_runner)
-      : task_runner_(task_runner), weak_factory_(this) {}
-
-  // Producer Impl:
-  void OnConnect() override;
-  void OnDisconnect() override;
-  void SetupDataSource(DataSourceInstanceID, const DataSourceConfig&) override;
-  void StartDataSource(DataSourceInstanceID, const DataSourceConfig&) override;
-  void StopDataSource(DataSourceInstanceID) override;
-  void OnTracingSetup() override {}
-  void Flush(FlushRequestID,
-             const DataSourceInstanceID* data_source_ids,
-             size_t num_data_sources) override;
-  void ClearIncrementalState(const DataSourceInstanceID* /*data_source_ids*/,
-                             size_t /*num_data_sources*/) override {}
-  // TODO(fmayer): Refactor once/if we have generic reconnect logic.
-  void ConnectWithRetries(const char* socket_name);
-  void SetProducerEndpoint(
-      std::unique_ptr<TracingService::ProducerEndpoint> endpoint);
-
- private:
-  // State of the connection to tracing service (traced).
-  enum State {
-    kNotStarted = 0,
-    kNotConnected,
-    kConnecting,
-    kConnected,
-  };
-
-  struct DataSource {
-    DataSourceInstanceID id;
-    std::set<pid_t> pids;
-    JavaHprofConfig config;
-  };
-
-  void ConnectService();
-  void Restart();
-  void ResetConnectionBackoff();
-  void IncreaseConnectionBackoff();
-
-  void DoContinuousDump(DataSourceInstanceID id, uint32_t dump_interval);
-  static void SignalDataSource(const DataSource& ds);
-
-  // State of connection to the tracing service.
-  State state_ = kNotStarted;
-  uint32_t connection_backoff_ms_ = 0;
-  const char* producer_sock_name_ = nullptr;
-
-  base::TaskRunner* const task_runner_;
-  std::unique_ptr<TracingService::ProducerEndpoint> endpoint_;
-
-  std::map<DataSourceInstanceID, DataSource> data_sources_;
-
-  base::WeakPtrFactory<JavaHprofProducer> weak_factory_;  // Keep last.
-};
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // SRC_PROFILING_MEMORY_JAVA_HPROF_PRODUCER_H_
diff --git a/src/profiling/memory/main.cc b/src/profiling/memory/main.cc
index ff5ac97..a134930 100644
--- a/src/profiling/memory/main.cc
+++ b/src/profiling/memory/main.cc
@@ -23,16 +23,15 @@
 #include <getopt.h>
 #include <signal.h>
 
-#include "perfetto/ext/base/event_fd.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/unix_socket.h"
-#include "perfetto/ext/base/watchdog.h"
-#include "perfetto/ext/tracing/ipc/default_socket.h"
+#include "perfetto/base/event.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/unix_socket.h"
+#include "perfetto/base/watchdog.h"
 #include "src/profiling/memory/heapprofd_producer.h"
-#include "src/profiling/memory/java_hprof_producer.h"
 #include "src/profiling/memory/wire_protocol.h"
+#include "src/tracing/ipc/default_socket.h"
 
-#include "perfetto/ext/base/unix_task_runner.h"
+#include "perfetto/base/unix_task_runner.h"
 
 // TODO(rsavitski): the task runner watchdog spawns a thread (normally for
 // tracking cpu/mem usage) that we don't strictly need.
@@ -46,19 +45,7 @@
                         base::ScopedFile inherited_sock_fd);
 int StartCentralHeapprofd();
 
-int GetListeningSocket() {
-  const char* sock_fd = getenv(kHeapprofdSocketEnvVar);
-  if (sock_fd == nullptr)
-    PERFETTO_FATAL("Did not inherit socket from init.");
-  char* end;
-  int raw_fd = static_cast<int>(strtol(sock_fd, &end, 10));
-  if (*end != '\0')
-    PERFETTO_FATAL("Invalid %s. Expected decimal integer.",
-                   kHeapprofdSocketEnvVar);
-  return raw_fd;
-}
-
-base::EventFd* g_dump_evt = nullptr;
+base::Event* g_dump_evt = nullptr;
 
 int HeapprofdMain(int argc, char** argv) {
   bool cleanup_crash = false;
@@ -152,17 +139,12 @@
 int StartCentralHeapprofd() {
   // We set this up before launching any threads, so we do not have to use a
   // std::atomic for g_dump_evt.
-  g_dump_evt = new base::EventFd();
+  g_dump_evt = new base::Event();
 
   base::UnixTaskRunner task_runner;
   base::Watchdog::GetInstance()->Start();  // crash on exceedingly long tasks
   HeapprofdProducer producer(HeapprofdMode::kCentral, &task_runner);
 
-  int listening_raw_socket = GetListeningSocket();
-  auto listening_socket = base::UnixSocket::Listen(
-      base::ScopedFile(listening_raw_socket), &producer.socket_delegate(),
-      &task_runner, base::SockFamily::kUnix, base::SockType::kStream);
-
   struct sigaction action = {};
   action.sa_handler = [](int) { g_dump_evt->Notify(); };
   // Allow to trigger a full dump by sending SIGUSR1 to heapprofd.
@@ -173,10 +155,6 @@
     producer.DumpAll();
   });
   producer.ConnectWithRetries(GetProducerSocket());
-  // TODO(fmayer): Create one producer that manages both heapprofd and Java
-  // producers, so we do not have two connections to traced.
-  JavaHprofProducer java_producer(&task_runner);
-  java_producer.ConnectWithRetries(GetProducerSocket());
   task_runner.Run();
   return 0;
 }
diff --git a/src/profiling/memory/malloc_hooks.cc b/src/profiling/memory/malloc_hooks.cc
index 7f6d1c3..904c6c1 100644
--- a/src/profiling/memory/malloc_hooks.cc
+++ b/src/profiling/memory/malloc_hooks.cc
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-#include <android/fdsan.h>
-#include <bionic/malloc.h>
 #include <inttypes.h>
 #include <malloc.h>
+#include <private/bionic_malloc.h>
 #include <private/bionic_malloc_dispatch.h>
 #include <stddef.h>
 #include <stdio.h>
@@ -32,9 +31,9 @@
 
 #include "perfetto/base/build_config.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/no_destructor.h"
-#include "perfetto/ext/base/unix_socket.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/no_destructor.h"
+#include "perfetto/base/unix_socket.h"
+#include "perfetto/base/utils.h"
 #include "src/profiling/memory/client.h"
 #include "src/profiling/memory/proc_utils.h"
 #include "src/profiling/memory/scoped_spinlock.h"
@@ -84,12 +83,12 @@
 int HEAPPROFD_ADD_PREFIX(_posix_memalign)(void** memptr,
                                           size_t alignment,
                                           size_t size);
-int HEAPPROFD_ADD_PREFIX(_malloc_iterate)(uintptr_t base,
-                                          size_t size,
-                                          void (*callback)(uintptr_t base,
-                                                           size_t size,
-                                                           void* arg),
-                                          void* arg);
+int HEAPPROFD_ADD_PREFIX(_iterate)(uintptr_t base,
+                                   size_t size,
+                                   void (*callback)(uintptr_t base,
+                                                    size_t size,
+                                                    void* arg),
+                                   void* arg);
 void HEAPPROFD_ADD_PREFIX(_malloc_disable)();
 void HEAPPROFD_ADD_PREFIX(_malloc_enable)();
 
@@ -146,17 +145,11 @@
 }
 
 int CloneWithoutSigchld() {
-  auto ret = clone(nullptr, nullptr, 0, nullptr);
-  if (ret == 0)
-    android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_DISABLED);
-  return ret;
+  return clone(nullptr, nullptr, 0, nullptr);
 }
 
 int ForklikeClone() {
-  auto ret = clone(nullptr, nullptr, SIGCHLD, nullptr);
-  if (ret == 0)
-    android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_DISABLED);
-  return ret;
+  return clone(nullptr, nullptr, SIGCHLD, nullptr);
 }
 
 // Like daemon(), but using clone to avoid invoking pthread_atfork(3) handlers.
@@ -248,11 +241,8 @@
 
   perfetto::base::Optional<perfetto::base::UnixSocketRaw> sock =
       Client::ConnectToHeapprofd(perfetto::profiling::kHeapprofdSocketFile);
-  if (!sock) {
-    PERFETTO_ELOG("Failed to connect to %s.",
-                  perfetto::profiling::kHeapprofdSocketFile);
+  if (!sock)
     return nullptr;
-  }
   return Client::CreateAndHandshake(std::move(sock.value()),
                                     unhooked_allocator);
 }
@@ -263,7 +253,7 @@
   perfetto::base::UnixSocketRaw parent_sock;
   perfetto::base::UnixSocketRaw child_sock;
   std::tie(parent_sock, child_sock) = perfetto::base::UnixSocketRaw::CreatePair(
-      perfetto::base::SockFamily::kUnix, perfetto::base::SockType::kStream);
+      perfetto::base::SockType::kStream);
 
   if (!parent_sock || !child_sock) {
     PERFETTO_PLOG("Failed to create socketpair.");
@@ -461,7 +451,7 @@
     client = g_client.ref();  // owning copy
   }                           // unlock
 
-  if (!client->RecordMalloc(sampled_alloc_sz, size,
+  if (!client->RecordMalloc(size, sampled_alloc_sz,
                             reinterpret_cast<uint64_t>(addr))) {
     ShutdownLazy();
   }
@@ -477,7 +467,7 @@
 void* HEAPPROFD_ADD_PREFIX(_calloc)(size_t nmemb, size_t size) {
   const MallocDispatch* dispatch = GetDispatch();
   void* addr = dispatch->calloc(nmemb, size);
-  MaybeSampleAllocation(size, addr);
+  MaybeSampleAllocation(nmemb * size, addr);
   return addr;
 }
 
@@ -574,11 +564,7 @@
   if (size == 0 || sampled_alloc_sz == 0)
     return addr;
 
-  // We do not reach this point without a valid client, because in that case
-  // sampled_alloc_sz == 0.
-  PERFETTO_DCHECK(client);
-
-  if (!client->RecordMalloc(sampled_alloc_sz, size,
+  if (!client->RecordMalloc(size, sampled_alloc_sz,
                             reinterpret_cast<uint64_t>(addr))) {
     ShutdownLazy();
   }
@@ -620,12 +606,12 @@
   return dispatch->malloc_info(options, fp);
 }
 
-int HEAPPROFD_ADD_PREFIX(_malloc_iterate)(uintptr_t,
-                                          size_t,
-                                          void (*)(uintptr_t base,
-                                                   size_t size,
-                                                   void* arg),
-                                          void*) {
+int HEAPPROFD_ADD_PREFIX(_iterate)(uintptr_t,
+                                   size_t,
+                                   void (*)(uintptr_t base,
+                                            size_t size,
+                                            void* arg),
+                                   void*) {
   return 0;
 }
 
diff --git a/src/profiling/memory/page_idle_checker.cc b/src/profiling/memory/page_idle_checker.cc
deleted file mode 100644
index 7e639b5..0000000
--- a/src/profiling/memory/page_idle_checker.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/profiling/memory/page_idle_checker.h"
-#include "perfetto/ext/base/utils.h"
-#include "src/profiling/memory/utils.h"
-
-#include <inttypes.h>
-#include <vector>
-
-namespace perfetto {
-namespace profiling {
-
-// TODO(fmayer): Be smarter about batching reads and writes to page_idle.
-
-int64_t PageIdleChecker::OnIdlePage(uint64_t addr, size_t size) {
-  uint64_t page_nr = addr / base::kPageSize;
-  uint64_t end_page_nr = (addr + size) / base::kPageSize;
-  // The trailing division will have rounded down, unless the end is at a page
-  // boundary. Add one page if we rounded down.
-  if ((addr + size) % base::kPageSize != 0)
-    end_page_nr++;
-
-  size_t pages = static_cast<size_t>(end_page_nr - page_nr);
-
-  int64_t idle_mem = 0;
-  for (size_t i = 0; i < pages; ++i) {
-    int idle = IsPageIdle(page_nr + i);
-    if (idle == -1)
-      continue;
-
-    if (idle) {
-      if (i == 0)
-        idle_mem += GetFirstPageShare(addr, size);
-      else if (i == pages - 1)
-        idle_mem += GetLastPageShare(addr, size);
-      else
-        idle_mem += base::kPageSize;
-    } else {
-      touched_virt_page_nrs_.emplace(page_nr + i);
-    }
-  }
-  return idle_mem;
-}
-
-void PageIdleChecker::MarkPagesIdle() {
-  for (uint64_t virt_page_nr : touched_virt_page_nrs_)
-    MarkPageIdle(virt_page_nr);
-  touched_virt_page_nrs_.clear();
-}
-
-void PageIdleChecker::MarkPageIdle(uint64_t virt_page_nr) {
-  // The file implements a bitmap where each bit corresponds to a memory page.
-  // The bitmap is represented by an array of 8-byte integers, and the page at
-  // PFN #i is mapped to bit #i%64 of array element #i/64, byte order i
-  // native. When a bit is set, the corresponding page is idle.
-  //
-  // The kernel ORs the value written with the existing bitmap, so we do not
-  // override previously written values.
-  // See https://www.kernel.org/doc/Documentation/vm/idle_page_tracking.txt
-  off64_t offset = 8 * (virt_page_nr / 64);
-  size_t bit_offset = virt_page_nr % 64;
-  uint64_t bit_pattern = 1 << bit_offset;
-  if (WriteAtOffsetClobberSeekPos(*page_idle_fd_, &bit_pattern,
-                                  sizeof(bit_pattern), offset) !=
-      static_cast<ssize_t>(sizeof(bit_pattern))) {
-    PERFETTO_PLOG("Failed to write bit pattern at %" PRIi64 ".", offset);
-  }
-}
-
-int PageIdleChecker::IsPageIdle(uint64_t virt_page_nr) {
-  off64_t offset = 8 * (virt_page_nr / 64);
-  size_t bit_offset = virt_page_nr % 64;
-  uint64_t bit_pattern;
-  if (ReadAtOffsetClobberSeekPos(*page_idle_fd_, &bit_pattern,
-                                 sizeof(bit_pattern), offset) !=
-      static_cast<ssize_t>(sizeof(bit_pattern))) {
-    PERFETTO_PLOG("Failed to read bit pattern at %" PRIi64 ".", offset);
-    return -1;
-  }
-  return static_cast<int>(bit_pattern & (1 << bit_offset));
-}
-
-uint64_t GetFirstPageShare(uint64_t addr, size_t size) {
-  // Our allocation is xxxx in this illustration:
-  //         +----------------------------------------------+
-  //         |             xxxxxxxxxx|xxxxxx                |
-  //         |             xxxxxxxxxx|xxxxxx                |
-  //         |             xxxxxxxxxx|xxxxxx                |
-  //         +-------------+---------------+----------------+
-  //         ^             ^         ^     ^
-  //         +             +         +     +
-  // page_aligned_addr  addr        end    addr + size
-  uint64_t page_aligned_addr = (addr / base::kPageSize) * base::kPageSize;
-  uint64_t end = page_aligned_addr + base::kPageSize;
-  if (end > addr + size) {
-    // The whole allocation is on the first page.
-    return size;
-  }
-
-  return base::kPageSize - (addr - page_aligned_addr);
-}
-
-uint64_t GetLastPageShare(uint64_t addr, size_t size) {
-  uint64_t last_page_size = (addr + size) % base::kPageSize;
-  if (last_page_size == 0) {
-    // Address ends at a page boundary, the whole last page is idle.
-    return base::kPageSize;
-  } else {
-    // Address does not end at a page boundary, only a subset of the last
-    // page should be attributed to this allocation.
-    return last_page_size;
-  }
-}
-
-}  // namespace profiling
-}  // namespace perfetto
diff --git a/src/profiling/memory/page_idle_checker.h b/src/profiling/memory/page_idle_checker.h
deleted file mode 100644
index f9c73cd..0000000
--- a/src/profiling/memory/page_idle_checker.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_PROFILING_MEMORY_PAGE_IDLE_CHECKER_H_
-#define SRC_PROFILING_MEMORY_PAGE_IDLE_CHECKER_H_
-
-#include <set>
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "perfetto/ext/base/scoped_file.h"
-
-namespace perfetto {
-namespace profiling {
-
-uint64_t GetFirstPageShare(uint64_t addr, size_t size);
-uint64_t GetLastPageShare(uint64_t addr, size_t size);
-
-class PageIdleChecker {
- public:
-  PageIdleChecker(base::ScopedFile page_idle_fd)
-      : page_idle_fd_(std::move(page_idle_fd)) {}
-
-  // Return number of bytes of allocation of size bytes starting at alloc that
-  // are on unreferenced pages.
-  // Return -1 on error.
-  int64_t OnIdlePage(uint64_t addr, size_t size);
-
-  void MarkPagesIdle();
-
- private:
-  void MarkPageIdle(uint64_t virt_page_nr);
-  // Return 1 if page is idle, 0 if it is not idle, or -1 on error.
-  int IsPageIdle(uint64_t virt_page_nr);
-
-  std::set<uint64_t> touched_virt_page_nrs_;
-
-  base::ScopedFile page_idle_fd_;
-};
-
-}  // namespace profiling
-}  // namespace perfetto
-
-#endif  // SRC_PROFILING_MEMORY_PAGE_IDLE_CHECKER_H_
diff --git a/src/profiling/memory/page_idle_checker_unittest.cc b/src/profiling/memory/page_idle_checker_unittest.cc
deleted file mode 100644
index ee751e9..0000000
--- a/src/profiling/memory/page_idle_checker_unittest.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/profiling/memory/page_idle_checker.h"
-
-#include "perfetto/ext/base/utils.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace profiling {
-namespace {
-
-TEST(PageIdleCheckerTest, AllOnFirstPageAligned) {
-  EXPECT_EQ(GetFirstPageShare(0, 10), 10u);
-}
-
-TEST(PageIdleCheckerTest, AllOnFirstPageUnAligned) {
-  EXPECT_EQ(GetFirstPageShare(10, 10), 10u);
-}
-
-TEST(PageIdleCheckerTest, WholeFirstPageAligned) {
-  EXPECT_EQ(GetFirstPageShare(0, base::kPageSize + 10), base::kPageSize);
-  EXPECT_EQ(GetLastPageShare(0, base::kPageSize + 10), 10u);
-}
-
-TEST(PageIdleCheckerTest, WholeLastPageAligned) {
-  EXPECT_EQ(GetFirstPageShare(0, 3 * base::kPageSize), base::kPageSize);
-  EXPECT_EQ(GetLastPageShare(0, 3 * base::kPageSize), base::kPageSize);
-}
-
-TEST(PageIdleCheckerTest, SomeFirstAndLast) {
-  EXPECT_EQ(GetFirstPageShare(10, 3 * base::kPageSize + 10),
-            base::kPageSize - 10);
-  EXPECT_EQ(GetLastPageShare(10, 3 * base::kPageSize + 10), 20u);
-}
-
-}  // namespace
-}  // namespace profiling
-}  // namespace perfetto
diff --git a/src/profiling/memory/proc_utils.cc b/src/profiling/memory/proc_utils.cc
index 02f2c7d..baef7ad 100644
--- a/src/profiling/memory/proc_utils.cc
+++ b/src/profiling/memory/proc_utils.cc
@@ -20,13 +20,29 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/profiling/normalize.h"
+#include "perfetto/base/file_utils.h"
 
 namespace perfetto {
 namespace profiling {
 namespace {
 
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
+
+const char* FindChar(const char* s, char c, size_t n) {
+  std::string str(s, n);
+  auto idx = str.rfind(c);
+  if (idx == std::string::npos)
+    return nullptr;
+  return s + n;
+}
+
+void* memrchr(const void* s, int c, size_t n) {
+  return static_cast<void*>(const_cast<char*>(
+      FindChar(static_cast<const char*>(s), static_cast<char>(c), n)));
+}
+
+#endif
+
 bool GetProcFile(pid_t pid, const char* file, char* filename_buf, size_t size) {
   ssize_t written = snprintf(filename_buf, size, "/proc/%d/%s", pid, file);
   if (written < 0 || static_cast<size_t>(written) >= size) {
@@ -41,6 +57,38 @@
 
 }  // namespace
 
+bool NormalizeCmdLine(char* cmdline, size_t size, std::string* name) {
+  char* first_arg = static_cast<char*>(memchr(cmdline, '\0', size));
+  if (first_arg == nullptr) {
+    PERFETTO_DLOG("Overflow reading cmdline");
+    errno = EOVERFLOW;
+    return false;
+  }
+  // For consistency with what we do with Java app cmdlines, trim everything
+  // after the @ sign of the first arg.
+  char* first_at = static_cast<char*>(memchr(cmdline, '@', size));
+  if (first_at != nullptr && first_at < first_arg) {
+    *first_at = '\0';
+    first_arg = first_at;
+  }
+  char* start = static_cast<char*>(
+      memrchr(cmdline, '/', static_cast<size_t>(first_arg - cmdline)));
+  if (start == first_arg) {
+    // The first argument ended in a slash.
+    PERFETTO_DLOG("cmdline ends in /");
+    errno = EINVAL;
+    return false;
+  } else if (start == nullptr) {
+    start = cmdline;
+  } else {
+    // Skip the /.
+    start++;
+  }
+  size_t name_size = static_cast<size_t>(first_arg - start);
+  name->assign(start, name_size);
+  return true;
+}
+
 std::vector<std::string> NormalizeCmdlines(
     const std::vector<std::string>& cmdlines) {
   std::vector<std::string> normalized_cmdlines;
@@ -48,15 +96,12 @@
     // Add nullbyte to make sure it's a C string.
     cmdline.resize(cmdline.size() + 1, '\0');
     std::string normalized;
-    char* cmdline_cstr = &(cmdline[0]);
-    ssize_t size = NormalizeCmdLine(&cmdline_cstr, cmdline.size());
-    if (size == -1) {
-      PERFETTO_PLOG("Failed to normalize cmdline %s. Skipping.",
+    if (!NormalizeCmdLine(&(cmdline[0]), cmdline.size(), &normalized)) {
+      PERFETTO_ELOG("Failed to normalize cmdline %s. Skipping.",
                     cmdline.c_str());
       continue;
     }
-    normalized_cmdlines.emplace_back(
-        std::string(cmdline_cstr, static_cast<size_t>(size)));
+    normalized_cmdlines.emplace_back(std::move(normalized));
   }
   return normalized_cmdlines;
 }
@@ -68,17 +113,13 @@
   std::string filename = "/proc/" + std::to_string(pid) + "/cmdline";
   base::ScopedFile fd(base::OpenFile(filename, O_RDONLY | O_CLOEXEC));
   if (!fd) {
-    // We do not expect errors other than permission errors here.
-    if (errno != EPERM && errno != EACCES)
-      PERFETTO_PLOG("Failed to open %s", filename.c_str());
-    else
-      PERFETTO_DPLOG("Failed to open %s", filename.c_str());
+    PERFETTO_DLOG("Failed to open %s", filename.c_str());
     return false;
   }
   char cmdline[512];
   ssize_t rd = read(*fd, cmdline, sizeof(cmdline) - 1);
   if (rd == -1) {
-    PERFETTO_DPLOG("Failed to read %s", filename.c_str());
+    PERFETTO_DLOG("Failed to read %s", filename.c_str());
     return false;
   }
 
@@ -97,12 +138,7 @@
   }
 
   cmdline[rd] = '\0';
-  char* cmdline_start = cmdline;
-  ssize_t size = NormalizeCmdLine(&cmdline_start, static_cast<size_t>(rd));
-  if (size == -1)
-    return false;
-  name->assign(cmdline_start, static_cast<size_t>(size));
-  return true;
+  return NormalizeCmdLine(cmdline, static_cast<size_t>(rd), name);
 }
 
 void FindAllProfilablePids(std::set<pid_t>* pids) {
diff --git a/src/profiling/memory/proc_utils.h b/src/profiling/memory/proc_utils.h
index e123194..4700cf2 100644
--- a/src/profiling/memory/proc_utils.h
+++ b/src/profiling/memory/proc_utils.h
@@ -21,7 +21,7 @@
 #include <set>
 #include <vector>
 
-#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/base/scoped_file.h"
 
 namespace perfetto {
 namespace profiling {
@@ -30,7 +30,7 @@
 void ForEachPid(Fn callback) {
   base::ScopedDir proc_dir(opendir("/proc"));
   if (!proc_dir) {
-    PERFETTO_DFATAL_OR_ELOG("Failed to open /proc");
+    PERFETTO_DFATAL("Failed to open /proc");
     return;
   }
   struct dirent* entry;
@@ -43,6 +43,7 @@
   }
 }
 
+bool NormalizeCmdLine(char* cmdline, size_t size, std::string* name);
 std::vector<std::string> NormalizeCmdlines(
     const std::vector<std::string>& cmdlines);
 
diff --git a/src/profiling/memory/proc_utils_unittest.cc b/src/profiling/memory/proc_utils_unittest.cc
index 6c0065c..9421d9c 100644
--- a/src/profiling/memory/proc_utils_unittest.cc
+++ b/src/profiling/memory/proc_utils_unittest.cc
@@ -15,10 +15,9 @@
  */
 
 #include "src/profiling/memory/proc_utils.h"
-#include "perfetto/profiling/normalize.h"
 
-#include "perfetto/ext/base/utils.h"
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace profiling {
@@ -27,77 +26,25 @@
 using ::testing::Contains;
 using ::testing::Not;
 
-std::string NormalizeToString(char* cmdline, size_t size) {
-  ssize_t new_size = NormalizeCmdLine(&cmdline, size);
-  if (new_size == -1)
-    return "";
-  return std::string(cmdline, static_cast<size_t>(new_size));
-}
-
 TEST(ProcUtilsTest, NormalizeNoop) {
-  char kCmdline[] = "surfaceflinger";
-  EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "surfaceflinger");
-}
-
-TEST(ProcUtilsTest, NormalizeTwoArgs) {
-  char kCmdline[] = "surfaceflinger\0--foo";
-  EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "surfaceflinger");
+  char kCmdline[] = "surfaceflinger\0";
+  std::string name;
+  ASSERT_TRUE(NormalizeCmdLine(kCmdline, sizeof(kCmdline), &name));
+  EXPECT_EQ(name, "surfaceflinger");
 }
 
 TEST(ProcUtilsTest, NormalizePath) {
-  char kCmdline[] = "/system/bin/surfaceflinger";
-  EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "surfaceflinger");
+  char kCmdline[] = "/system/bin/surfaceflinger\0";
+  std::string name;
+  ASSERT_TRUE(NormalizeCmdLine(kCmdline, sizeof(kCmdline), &name));
+  EXPECT_EQ(name, "surfaceflinger");
 }
 
 TEST(ProcUtilsTest, NormalizeAt) {
-  char kCmdline[] = "some.app@2.0";
-  EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "some.app");
-}
-
-TEST(ProcUtilsTest, NormalizeEmpty) {
-  char kCmdline[] = "";
-  EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "");
-}
-
-TEST(ProcUtilsTest, NormalizeTrailingAt) {
-  char kCmdline[] = "foo@";
-  EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "foo");
-}
-
-TEST(ProcUtilsTest, NormalizeOnlyTrailingAt) {
-  char kCmdline[] = "@";
-  EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "");
-}
-
-TEST(ProcUtilsTest, NormalizeTrailingSlash) {
-  char kCmdline[] = "foo/";
-  EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "");
-}
-
-TEST(ProcUtilsTest, NormalizeOnlySlash) {
-  char kCmdline[] = "/";
-  EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "");
-}
-
-TEST(ProcUtilsTest, NormalizeTwoArgsSlash) {
-  char kCmdline[] = "surfaceflinger/\0--foo";
-  EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "");
-}
-
-TEST(ProcUtilsTest, NormalizeEmptyFirstArg) {
-  char kCmdline[] = "\0--foo";
-  EXPECT_EQ(NormalizeToString(kCmdline, sizeof(kCmdline)), "");
-}
-
-TEST(ProcUtilsTest, NormalizeNoNullTerminated) {
-  char kCmdline[] = {'f'};
-  char* cmdline = kCmdline;
-  EXPECT_EQ(NormalizeCmdLine(&cmdline, sizeof(kCmdline)), -1);
-}
-
-TEST(ProcUtilsTest, NormalizeZeroLength) {
-  char* cmdline = nullptr;
-  EXPECT_EQ(NormalizeCmdLine(&cmdline, 0), -1);
+  char kCmdline[] = "some.app@2.0\0";
+  std::string name;
+  ASSERT_TRUE(NormalizeCmdLine(kCmdline, sizeof(kCmdline), &name));
+  EXPECT_EQ(name, "some.app");
 }
 
 TEST(ProcUtilsTest, FindProfilablePids) {
diff --git a/src/profiling/memory/sampler.h b/src/profiling/memory/sampler.h
index 6740d17..0108634 100644
--- a/src/profiling/memory/sampler.h
+++ b/src/profiling/memory/sampler.h
@@ -22,7 +22,7 @@
 #include <atomic>
 #include <random>
 
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/utils.h"
 
 namespace perfetto {
 namespace profiling {
@@ -54,7 +54,7 @@
   size_t SampleSize(size_t alloc_sz) {
     if (PERFETTO_UNLIKELY(alloc_sz >= sampling_interval_))
       return alloc_sz;
-    return static_cast<size_t>(sampling_interval_ * NumberOfSamples(alloc_sz));
+    return sampling_interval_ * NumberOfSamples(alloc_sz);
   }
 
  private:
diff --git a/src/profiling/memory/sampler_unittest.cc b/src/profiling/memory/sampler_unittest.cc
index db903ff..4e53f24 100644
--- a/src/profiling/memory/sampler_unittest.cc
+++ b/src/profiling/memory/sampler_unittest.cc
@@ -16,9 +16,9 @@
 
 #include "src/profiling/memory/sampler.h"
 
-#include <thread>
+#include "gtest/gtest.h"
 
-#include "test/gtest_and_gmock.h"
+#include <thread>
 
 namespace perfetto {
 namespace profiling {
@@ -26,19 +26,19 @@
 
 TEST(SamplerTest, TestLarge) {
   Sampler sampler(512);
-  EXPECT_EQ(sampler.SampleSize(1024), 1024u);
+  EXPECT_EQ(sampler.SampleSize(1024), 1024);
 }
 
 TEST(SamplerTest, TestSmall) {
   Sampler sampler(512);
-  EXPECT_EQ(sampler.SampleSize(511), 512u);
+  EXPECT_EQ(sampler.SampleSize(511), 512);
 }
 
 TEST(SamplerTest, TestSequence) {
   Sampler sampler(1);
-  EXPECT_EQ(sampler.SampleSize(3), 3u);
-  EXPECT_EQ(sampler.SampleSize(7), 7u);
-  EXPECT_EQ(sampler.SampleSize(5), 5u);
+  EXPECT_EQ(sampler.SampleSize(3), 3);
+  EXPECT_EQ(sampler.SampleSize(7), 7);
+  EXPECT_EQ(sampler.SampleSize(5), 5);
 }
 
 }  // namespace
diff --git a/src/profiling/memory/scoped_spinlock.cc b/src/profiling/memory/scoped_spinlock.cc
index c306d79..de9ef59 100644
--- a/src/profiling/memory/scoped_spinlock.cc
+++ b/src/profiling/memory/scoped_spinlock.cc
@@ -20,7 +20,7 @@
 
 #include <atomic>
 
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/utils.h"
 
 namespace {
 // Wait for ~1s before timing out (+- spurious wakeups from the sleeps).
diff --git a/src/profiling/memory/scoped_spinlock.h b/src/profiling/memory/scoped_spinlock.h
index 67d8bd1..612c151 100644
--- a/src/profiling/memory/scoped_spinlock.h
+++ b/src/profiling/memory/scoped_spinlock.h
@@ -18,7 +18,7 @@
 #define SRC_PROFILING_MEMORY_SCOPED_SPINLOCK_H_
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/utils.h"
 
 #include <atomic>
 #include <new>
diff --git a/src/profiling/memory/shared_ring_buffer.cc b/src/profiling/memory/shared_ring_buffer.cc
index 99a9c89..f7da664 100644
--- a/src/profiling/memory/shared_ring_buffer.cc
+++ b/src/profiling/memory/shared_ring_buffer.cc
@@ -26,8 +26,8 @@
 #include <unistd.h>
 
 #include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/temp_file.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/temp_file.h"
 #include "src/profiling/memory/scoped_spinlock.h"
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
@@ -174,7 +174,7 @@
   PERFETTO_DCHECK(spinlock.locked());
   Buffer result;
 
-  base::Optional<PointerPositions> opt_pos = GetPointerPositions();
+  base::Optional<PointerPositions> opt_pos = GetPointerPositions(spinlock);
   if (!opt_pos) {
     meta_->stats.num_writes_corrupt++;
     errno = EBADF;
@@ -201,18 +201,13 @@
 
   result.size = size;
   result.data = wr_ptr + kHeaderSize;
+  meta_->write_pos += size_with_header;
   meta_->stats.bytes_written += size;
   meta_->stats.num_writes_succeeded++;
-
-  // We can make this a relaxed store, as this gets picked up by the acquire
-  // load in GetPointerPositions (and the release store below).
+  // By making this a release store, we can save grabbing the spinlock in
+  // EndWrite.
   reinterpret_cast<std::atomic<uint32_t>*>(wr_ptr)->store(
-      0, std::memory_order_relaxed);
-
-  // This needs to happen after the store above, so the reader never observes an
-  // incorrect byte count. This is matched by the acquire load in
-  // GetPointerPositions.
-  meta_->write_pos.fetch_add(size_with_header, std::memory_order_release);
+      0, std::memory_order_release);
   return result;
 }
 
@@ -221,18 +216,14 @@
     return;
   uint8_t* wr_ptr = buf.data - kHeaderSize;
   PERFETTO_DCHECK(reinterpret_cast<uintptr_t>(wr_ptr) % kAlignment == 0);
-
-  // This needs to release to make sure the reader sees the payload written
-  // between the BeginWrite and EndWrite calls.
-  //
-  // This is matched by the acquire load in BeginRead where it reads the
-  // record's size.
   reinterpret_cast<std::atomic<uint32_t>*>(wr_ptr)->store(
       static_cast<uint32_t>(buf.size), std::memory_order_release);
 }
 
 SharedRingBuffer::Buffer SharedRingBuffer::BeginRead() {
-  base::Optional<PointerPositions> opt_pos = GetPointerPositions();
+  ScopedSpinlock spinlock(&meta_->spinlock, ScopedSpinlock::Mode::Blocking);
+
+  base::Optional<PointerPositions> opt_pos = GetPointerPositions(spinlock);
   if (!opt_pos) {
     meta_->stats.num_reads_corrupt++;
     errno = EBADF;
@@ -277,8 +268,9 @@
 void SharedRingBuffer::EndRead(Buffer buf) {
   if (!buf)
     return;
+  ScopedSpinlock spinlock(&meta_->spinlock, ScopedSpinlock::Mode::Blocking);
   size_t size_with_header = base::AlignUp<kAlignment>(buf.size + kHeaderSize);
-  meta_->read_pos.fetch_add(size_with_header, std::memory_order_relaxed);
+  meta_->read_pos += size_with_header;
   meta_->stats.num_reads_succeeded++;
 }
 
diff --git a/src/profiling/memory/shared_ring_buffer.h b/src/profiling/memory/shared_ring_buffer.h
index 0c5492f..0e68661 100644
--- a/src/profiling/memory/shared_ring_buffer.h
+++ b/src/profiling/memory/shared_ring_buffer.h
@@ -17,9 +17,9 @@
 #ifndef SRC_PROFILING_MEMORY_SHARED_RING_BUFFER_H_
 #define SRC_PROFILING_MEMORY_SHARED_RING_BUFFER_H_
 
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/unix_socket.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/optional.h"
+#include "perfetto/base/unix_socket.h"
+#include "perfetto/base/utils.h"
 #include "src/profiling/memory/scoped_spinlock.h"
 
 #include <atomic>
@@ -124,16 +124,10 @@
   // Exposed for fuzzers.
   struct MetadataPage {
     alignas(uint64_t) std::atomic<bool> spinlock;
-    std::atomic<uint64_t> read_pos;
-    std::atomic<uint64_t> write_pos;
+    uint64_t read_pos;
+    uint64_t write_pos;
 
     std::atomic<uint64_t> failed_spinlocks;
-    // For stats that are only accessed by a single thread or under the
-    // spinlock, members of this struct are directly modified. Other stats use
-    // the atomics above this struct.
-    //
-    // When the user requests stats, the atomics above get copied into this
-    // struct, which is then returned.
     Stats stats;
   };
 
@@ -155,16 +149,13 @@
   void Initialize(base::ScopedFile mem_fd);
   bool IsCorrupt(const PointerPositions& pos);
 
-  inline base::Optional<PointerPositions> GetPointerPositions() {
+  inline base::Optional<PointerPositions> GetPointerPositions(
+      const ScopedSpinlock& lock) {
+    PERFETTO_DCHECK(lock.locked());
+
     PointerPositions pos;
-    // We need to acquire load the write_pos to make sure we observe a
-    // consistent ring buffer in BeginRead, otherwise it is possible that we
-    // observe the write_pos increment, but not the size field write of the
-    // payload.
-    //
-    // This is matched by a release at the end of BeginWrite.
-    pos.write_pos = meta_->write_pos.load(std::memory_order_acquire);
-    pos.read_pos = meta_->read_pos.load(std::memory_order_relaxed);
+    pos.read_pos = meta_->read_pos;
+    pos.write_pos = meta_->write_pos;
 
     base::Optional<PointerPositions> result;
     if (IsCorrupt(pos))
diff --git a/src/profiling/memory/shared_ring_buffer_fuzzer.cc b/src/profiling/memory/shared_ring_buffer_fuzzer.cc
index 0fd03ce..a874a0f 100644
--- a/src/profiling/memory/shared_ring_buffer_fuzzer.cc
+++ b/src/profiling/memory/shared_ring_buffer_fuzzer.cc
@@ -17,8 +17,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/temp_file.h"
+#include "perfetto/base/file_utils.h"
+#include "perfetto/base/temp_file.h"
 #include "src/profiling/memory/shared_ring_buffer.h"
 
 namespace perfetto {
diff --git a/src/profiling/memory/shared_ring_buffer_unittest.cc b/src/profiling/memory/shared_ring_buffer_unittest.cc
index df1bc5c..46ee3c7 100644
--- a/src/profiling/memory/shared_ring_buffer_unittest.cc
+++ b/src/profiling/memory/shared_ring_buffer_unittest.cc
@@ -22,8 +22,8 @@
 #include <thread>
 #include <unordered_map>
 
-#include "perfetto/ext/base/optional.h"
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/optional.h"
 
 namespace perfetto {
 namespace profiling {
@@ -61,13 +61,13 @@
 
   {
     auto buf_and_size = rd->BeginRead();
-    ASSERT_EQ(buf_and_size.size, 4u);
+    ASSERT_EQ(buf_and_size.size, 4);
     ASSERT_STREQ(reinterpret_cast<const char*>(&buf_and_size.data[0]), "foo");
     rd->EndRead(std::move(buf_and_size));
   }
   {
     auto buf_and_size = rd->BeginRead();
-    ASSERT_EQ(buf_and_size.size, 4u);
+    ASSERT_EQ(buf_and_size.size, 4);
     ASSERT_STREQ(reinterpret_cast<const char*>(&buf_and_size.data[0]), "bar");
     rd->EndRead(std::move(buf_and_size));
   }
@@ -75,7 +75,7 @@
   for (int i = 0; i < 3; i++) {
     auto buf_and_size = rd->BeginRead();
     ASSERT_EQ(buf_and_size.data, nullptr);
-    ASSERT_EQ(buf_and_size.size, 0u);
+    ASSERT_EQ(buf_and_size.size, 0);
   }
 
   // Test extremely large writes (fill the buffer)
@@ -204,7 +204,7 @@
     std::uniform_int_distribution<size_t> dist(1, base::kPageSize * 8);
     for (int i = 0; i < 1000; i++) {
       size_t size = dist(rnd_engine);
-      ASSERT_GT(size, 0u);
+      ASSERT_GT(size, 0);
       std::string data;
       data.resize(size);
       std::generate(data.begin(), data.end(), rnd_engine);
@@ -230,7 +230,7 @@
           continue;
         }
       }
-      ASSERT_GT(buf_and_size.size, 0u);
+      ASSERT_GT(buf_and_size.size, 0);
       std::string data = ToString(buf_and_size);
       std::lock_guard<std::mutex> lock(mutex);
       expected_contents[std::move(data)]--;
diff --git a/src/profiling/memory/shared_ring_buffer_write_fuzzer.cc b/src/profiling/memory/shared_ring_buffer_write_fuzzer.cc
index be5bbb9..1bdd925 100644
--- a/src/profiling/memory/shared_ring_buffer_write_fuzzer.cc
+++ b/src/profiling/memory/shared_ring_buffer_write_fuzzer.cc
@@ -17,8 +17,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/temp_file.h"
+#include "perfetto/base/file_utils.h"
+#include "perfetto/base/temp_file.h"
 #include "src/profiling/memory/shared_ring_buffer.h"
 
 namespace perfetto {
diff --git a/src/profiling/memory/system_property.cc b/src/profiling/memory/system_property.cc
index a2fda64..f585666 100644
--- a/src/profiling/memory/system_property.cc
+++ b/src/profiling/memory/system_property.cc
@@ -17,7 +17,6 @@
 #include "src/profiling/memory/system_property.h"
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
 #include <sys/system_properties.h>
@@ -117,8 +116,7 @@
       nullptr);
   PERFETTO_DCHECK(r == 0);
 #else
-  PERFETTO_DFATAL_OR_ELOG(
-      "Cannot ResetHeapprofdProperties on out-of-tree builds.");
+  PERFETTO_DFATAL("Cannot ResetHeapprofdProperties on out-of-tree builds.");
 #endif
 }
 
@@ -143,7 +141,7 @@
 void SystemProperties::UnsetProperty(const std::string& name) {
   auto it = properties_.find(name);
   if (it == properties_.end()) {
-    PERFETTO_DFATAL_OR_ELOG("Unsetting unknown property.");
+    PERFETTO_DFATAL("Unsetting unknown property.");
     return;
   }
   if (--(it->second) == 0) {
diff --git a/src/profiling/memory/system_property_unittest.cc b/src/profiling/memory/system_property_unittest.cc
index 90a015b..2bf16ab 100644
--- a/src/profiling/memory/system_property_unittest.cc
+++ b/src/profiling/memory/system_property_unittest.cc
@@ -16,7 +16,8 @@
 
 #include "src/profiling/memory/system_property.h"
 
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace profiling {
diff --git a/src/profiling/memory/unwinding.cc b/src/profiling/memory/unwinding.cc
index 6b030c0..31b9a9c 100644
--- a/src/profiling/memory/unwinding.cc
+++ b/src/profiling/memory/unwinding.cc
@@ -44,14 +44,12 @@
 
 #include <procinfo/process_map.h>
 
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/logging.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/string_utils.h"
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/thread_task_runner.h"
-
-#include "src/profiling/memory/utils.h"
+#include "perfetto/base/thread_task_runner.h"
 #include "src/profiling/memory/wire_protocol.h"
 
 namespace perfetto {
@@ -72,49 +70,54 @@
 static std::vector<std::string> kSkipMaps{"heapprofd_client.so"};
 #pragma GCC diagnostic pop
 
-size_t GetRegsSize(unwindstack::Regs* regs) {
-  if (regs->Is32Bit())
-    return sizeof(uint32_t) * regs->total_regs();
-  return sizeof(uint64_t) * regs->total_regs();
+std::unique_ptr<unwindstack::Regs> CreateFromRawData(unwindstack::ArchEnum arch,
+                                                     void* raw_data) {
+  std::unique_ptr<unwindstack::Regs> ret;
+  // unwindstack::RegsX::Read returns a raw ptr which we are expected to free.
+  switch (arch) {
+    case unwindstack::ARCH_X86:
+      ret.reset(unwindstack::RegsX86::Read(raw_data));
+      break;
+    case unwindstack::ARCH_X86_64:
+      ret.reset(unwindstack::RegsX86_64::Read(raw_data));
+      break;
+    case unwindstack::ARCH_ARM:
+      ret.reset(unwindstack::RegsArm::Read(raw_data));
+      break;
+    case unwindstack::ARCH_ARM64:
+      ret.reset(unwindstack::RegsArm64::Read(raw_data));
+      break;
+    case unwindstack::ARCH_MIPS:
+      ret.reset(unwindstack::RegsMips::Read(raw_data));
+      break;
+    case unwindstack::ARCH_MIPS64:
+      ret.reset(unwindstack::RegsMips64::Read(raw_data));
+      break;
+    case unwindstack::ARCH_UNKNOWN:
+      ret.reset(nullptr);
+      break;
+  }
+  return ret;
 }
 
-void ReadFromRawData(unwindstack::Regs* regs, void* raw_data) {
-  memcpy(regs->RawData(), raw_data, GetRegsSize(regs));
+// Behaves as a pread64, emulating it if not already exposed by the standard
+// library. Safe to use on 32bit platforms for addresses with the top bit set.
+// Clobbers the |fd| seek position if emulating.
+ssize_t ReadAtOffsetClobberSeekPos(int fd,
+                                   void* buf,
+                                   size_t count,
+                                   uint64_t addr) {
+#ifdef __BIONIC__
+  return pread64(fd, buf, count, static_cast<off64_t>(addr));
+#else
+  if (lseek64(fd, static_cast<off64_t>(addr), SEEK_SET) == -1)
+    return -1;
+  return read(fd, buf, count);
+#endif
 }
 
 }  // namespace
 
-std::unique_ptr<unwindstack::Regs> CreateRegsFromRawData(
-    unwindstack::ArchEnum arch,
-    void* raw_data) {
-  std::unique_ptr<unwindstack::Regs> ret;
-  switch (arch) {
-    case unwindstack::ARCH_X86:
-      ret.reset(new unwindstack::RegsX86());
-      break;
-    case unwindstack::ARCH_X86_64:
-      ret.reset(new unwindstack::RegsX86_64());
-      break;
-    case unwindstack::ARCH_ARM:
-      ret.reset(new unwindstack::RegsArm());
-      break;
-    case unwindstack::ARCH_ARM64:
-      ret.reset(new unwindstack::RegsArm64());
-      break;
-    case unwindstack::ARCH_MIPS:
-      ret.reset(new unwindstack::RegsMips());
-      break;
-    case unwindstack::ARCH_MIPS64:
-      ret.reset(new unwindstack::RegsMips64());
-      break;
-    case unwindstack::ARCH_UNKNOWN:
-      break;
-  }
-  if (ret)
-    ReadFromRawData(ret.get(), raw_data);
-  return ret;
-}
-
 StackOverlayMemory::StackOverlayMemory(std::shared_ptr<unwindstack::Memory> mem,
                                        uint64_t sp,
                                        uint8_t* stack,
@@ -134,8 +137,7 @@
 FDMemory::FDMemory(base::ScopedFile mem_fd) : mem_fd_(std::move(mem_fd)) {}
 
 size_t FDMemory::Read(uint64_t addr, void* dst, size_t size) {
-  ssize_t rd = ReadAtOffsetClobberSeekPos(*mem_fd_, dst, size,
-                                          static_cast<off64_t>(addr));
+  ssize_t rd = ReadAtOffsetClobberSeekPos(*mem_fd_, dst, size, addr);
   if (rd == -1) {
     PERFETTO_DPLOG("read of %zu at offset %" PRIu64, size, addr);
     return 0;
@@ -176,8 +178,8 @@
 
 bool DoUnwind(WireMessage* msg, UnwindingMetadata* metadata, AllocRecord* out) {
   AllocMetadata* alloc_metadata = msg->alloc_header;
-  std::unique_ptr<unwindstack::Regs> regs(CreateRegsFromRawData(
-      alloc_metadata->arch, alloc_metadata->register_data));
+  std::unique_ptr<unwindstack::Regs> regs(
+      CreateFromRawData(alloc_metadata->arch, alloc_metadata->register_data));
   if (regs == nullptr) {
     PERFETTO_DLOG("Unable to construct unwindstack::Regs");
     unwindstack::FrameData frame_data{};
@@ -206,9 +208,6 @@
     if (attempt > 0) {
       PERFETTO_DLOG("Reparsing maps");
       metadata->ReparseMaps();
-      // Regs got invalidated by libuwindstack's speculative jump.
-      // Reset.
-      ReadFromRawData(regs.get(), alloc_metadata->register_data);
       out->reparsed_map = true;
 #if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
       unwinder.SetJitDebug(metadata->jit_debug.get(), regs->Arch());
@@ -248,12 +247,22 @@
   // TODO(fmayer): Maybe try to drain shmem one last time.
   auto it = client_data_.find(self->peer_pid());
   if (it == client_data_.end()) {
-    PERFETTO_DFATAL_OR_ELOG("Disconnected unexpected socket.");
+    PERFETTO_DFATAL("Disconnected unexpecter socket.");
     return;
   }
   ClientData& client_data = it->second;
   SharedRingBuffer& shmem = client_data.shmem;
 
+  // Currently, these stats are used to determine whether the application
+  // disconnected due to an error condition (i.e. buffer overflow) or
+  // volutarily. Because a buffer overflow leads to an immediate disconnect, we
+  // do not need these stats when heapprofd tears down the tracing session.
+  //
+  // TODO(fmayer): We should make it that normal disconnects also go through
+  // this code path, so we can write other stats to the result. This will also
+  // allow us to free the bookkeeping data earlier for processes that exit
+  // during the session. See TODO in
+  // HeapprofdProducer::HandleSocketDisconnected.
   SharedRingBuffer::Stats stats = {};
   {
     auto lock = shmem.AcquireLock(ScopedSpinlock::Mode::Try);
@@ -294,6 +303,8 @@
   bool repost_task = false;
   for (i = 0; i < kUnwindBatchSize; ++i) {
     uint64_t reparses_before = client_data.metadata.reparses;
+    // TODO(fmayer): Allow spinlock acquisition to fail and repost Task if it
+    // did.
     buf = shmem.BeginRead();
     if (!buf)
       break;
@@ -330,7 +341,7 @@
   // char* has stronger guarantees regarding aliasing.
   // see https://timsong-cpp.github.io/cppwp/n3337/basic.lval#10.8
   if (!ReceiveWireMessage(reinterpret_cast<char*>(buf.data), buf.size, &msg)) {
-    PERFETTO_DFATAL_OR_ELOG("Failed to receive wire message.");
+    PERFETTO_DFATAL("Failed to receive wire message.");
     return;
   }
 
@@ -352,7 +363,7 @@
     memcpy(&rec.free_batch, msg.free_header, sizeof(*msg.free_header));
     delegate->PostFreeRecord(std::move(rec));
   } else {
-    PERFETTO_DFATAL_OR_ELOG("Invalid record type.");
+    PERFETTO_DFATAL("Invalid record type.");
   }
 }
 
@@ -372,11 +383,12 @@
 void UnwindingWorker::HandleHandoffSocket(HandoffData handoff_data) {
   auto sock = base::UnixSocket::AdoptConnected(
       handoff_data.sock.ReleaseFd(), this, this->thread_task_runner_.get(),
-      base::SockFamily::kUnix, base::SockType::kStream);
+      base::SockType::kStream);
   pid_t peer_pid = sock->peer_pid();
 
-  UnwindingMetadata metadata(peer_pid, std::move(handoff_data.maps_fd),
-                             std::move(handoff_data.mem_fd));
+  UnwindingMetadata metadata(peer_pid,
+                             std::move(handoff_data.fds[kHandshakeMaps]),
+                             std::move(handoff_data.fds[kHandshakeMem]));
   ClientData client_data{
       handoff_data.data_source_instance_id,
       std::move(sock),
@@ -395,14 +407,7 @@
 }
 
 void UnwindingWorker::HandleDisconnectSocket(pid_t pid) {
-  auto it = client_data_.find(pid);
-  if (it == client_data_.end()) {
-    PERFETTO_DFATAL_OR_ELOG("Trying to disconnect unknown socket.");
-    return;
-  }
-  ClientData& client_data = it->second;
-  // Shutdown and call OnDisconnect handler.
-  client_data.sock->Shutdown(/* notify= */ true);
+  client_data_.erase(pid);
 }
 
 UnwindingWorker::Delegate::~Delegate() = default;
diff --git a/src/profiling/memory/unwinding.h b/src/profiling/memory/unwinding.h
index 39216fe..0adde32 100644
--- a/src/profiling/memory/unwinding.h
+++ b/src/profiling/memory/unwinding.h
@@ -27,9 +27,9 @@
 #include <unwindstack/JitDebug.h>
 #endif
 
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/thread_task_runner.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/thread_task_runner.h"
+#include "perfetto/tracing/core/basic_types.h"
 #include "src/profiling/memory/bookkeeping.h"
 #include "src/profiling/memory/unwound_messages.h"
 #include "src/profiling/memory/wire_protocol.h"
@@ -37,10 +37,6 @@
 namespace perfetto {
 namespace profiling {
 
-std::unique_ptr<unwindstack::Regs> CreateRegsFromRawData(
-    unwindstack::ArchEnum arch,
-    void* raw_data);
-
 // Read /proc/[pid]/maps from an open file descriptor.
 // TODO(fmayer): Figure out deduplication to other maps.
 class FileDescriptorMaps : public unwindstack::Maps {
@@ -110,8 +106,7 @@
             new unwindstack::DexFiles(fd_mem)))
 #endif
   {
-    bool parsed = maps.Parse();
-    PERFETTO_DCHECK(parsed);
+    PERFETTO_CHECK(maps.Parse());
   }
   void ReparseMaps() {
     reparses++;
@@ -152,8 +147,7 @@
   struct HandoffData {
     DataSourceInstanceID data_source_instance_id;
     base::UnixSocketRaw sock;
-    base::ScopedFile maps_fd;
-    base::ScopedFile mem_fd;
+    base::ScopedFile fds[kHandshakeSize];
     SharedRingBuffer shmem;
     ClientConfiguration client_config;
   };
@@ -171,7 +165,7 @@
   void OnDisconnect(base::UnixSocket* self) override;
   void OnNewIncomingConnection(base::UnixSocket*,
                                std::unique_ptr<base::UnixSocket>) override {
-    PERFETTO_DFATAL_OR_ELOG("This should not happen.");
+    PERFETTO_DFATAL("This should not happen.");
   }
   void OnDataAvailable(base::UnixSocket* self) override;
 
diff --git a/src/profiling/memory/unwinding_fuzzer.cc b/src/profiling/memory/unwinding_fuzzer.cc
index c2046b0..a80e039 100644
--- a/src/profiling/memory/unwinding_fuzzer.cc
+++ b/src/profiling/memory/unwinding_fuzzer.cc
@@ -17,8 +17,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/tracing/core/basic_types.h"
 #include "src/profiling/memory/shared_ring_buffer.h"
 #include "src/profiling/memory/unwinding.h"
 #include "src/profiling/memory/unwound_messages.h"
diff --git a/src/profiling/memory/unwinding_unittest.cc b/src/profiling/memory/unwinding_unittest.cc
index b52a7ce..bcefbbd 100644
--- a/src/profiling/memory/unwinding_unittest.cc
+++ b/src/profiling/memory/unwinding_unittest.cc
@@ -15,17 +15,19 @@
  */
 
 #include "src/profiling/memory/unwinding.h"
+#include "perfetto/base/scoped_file.h"
+#include "src/profiling/memory/client.h"
+#include "src/profiling/memory/wire_protocol.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 #include <cxxabi.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <unwindstack/RegsGetLocal.h>
 
-#include "perfetto/ext/base/scoped_file.h"
-#include "src/profiling/memory/client.h"
-#include "src/profiling/memory/wire_protocol.h"
-#include "test/gtest_and_gmock.h"
+#include <unwindstack/RegsGetLocal.h>
 
 namespace perfetto {
 namespace profiling {
@@ -39,7 +41,7 @@
       std::make_shared<FDMemory>(std::move(proc_mem)));
   StackOverlayMemory memory(mem, 0u, fake_stack, 1);
   uint8_t buf[1] = {};
-  ASSERT_EQ(memory.Read(0u, buf, 1), 1u);
+  ASSERT_EQ(memory.Read(0u, buf, 1), 1);
   ASSERT_EQ(buf[0], 120);
 }
 
@@ -53,7 +55,7 @@
       std::make_shared<FDMemory>(std::move(proc_mem)));
   StackOverlayMemory memory(mem, 0u, fake_stack, 1);
   uint8_t buf[1] = {1};
-  ASSERT_EQ(memory.Read(reinterpret_cast<uint64_t>(&value), buf, 1), 1u);
+  ASSERT_EQ(memory.Read(reinterpret_cast<uint64_t>(&value), buf, 1), 1);
   ASSERT_EQ(buf[0], value);
 }
 
@@ -68,27 +70,11 @@
   ASSERT_EQ(map_info->name, "[stack]");
 }
 
-void __attribute__((noinline)) AssertFunctionOffset() {
-  constexpr auto kMaxFunctionSize = 1000u;
-  // Need to zero-initialize to make MSAN happy. MSAN does not see the writes
-  // from AsmGetRegs (as it is in assembly) and complains otherwise.
-  char reg_data[kMaxRegisterDataSize] = {};
-  unwindstack::AsmGetRegs(reg_data);
-  auto regs = CreateRegsFromRawData(unwindstack::Regs::CurrentArch(), reg_data);
-  ASSERT_GT(regs->pc(), reinterpret_cast<uint64_t>(&AssertFunctionOffset));
-  ASSERT_LT(regs->pc() - reinterpret_cast<uint64_t>(&AssertFunctionOffset),
-            kMaxFunctionSize);
-}
-
-TEST(UnwindingTest, TestFunctionOffset) {
-  AssertFunctionOffset();
-}
-
 // This is needed because ASAN thinks copying the whole stack is a buffer
 // underrun.
 void __attribute__((noinline))
 UnsafeMemcpy(void* dst, const void* src, size_t n)
-    __attribute__((no_sanitize("address", "hwaddress", "memory"))) {
+    __attribute__((no_sanitize("address", "hwaddress"))) {
   const uint8_t* from = reinterpret_cast<const uint8_t*>(src);
   uint8_t* to = reinterpret_cast<uint8_t*>(dst);
   for (size_t i = 0; i < n; ++i)
@@ -106,16 +92,13 @@
 
   const char* stackbase = GetThreadStackBase();
   const char* stacktop = reinterpret_cast<char*>(__builtin_frame_address(0));
-  // Need to zero-initialize to make MSAN happy. MSAN does not see the writes
-  // from AsmGetRegs (as it is in assembly) and complains otherwise.
-  memset(metadata->register_data, 0, sizeof(metadata->register_data));
   unwindstack::AsmGetRegs(metadata->register_data);
 
   if (stackbase < stacktop) {
-    PERFETTO_FATAL("Stacktop >= stackbase.");
+    PERFETTO_DFATAL("Stacktop >= stackbase.");
     return {nullptr, nullptr};
   }
-  size_t stack_size = static_cast<size_t>(stackbase - stacktop);
+  uint64_t stack_size = static_cast<uint64_t>(stackbase - stacktop);
 
   metadata->alloc_size = 10;
   metadata->alloc_address = 0x10;
@@ -134,45 +117,27 @@
   return {std::move(payload), std::move(metadata)};
 }
 
-TEST(UnwindingTest, DoUnwind) {
-  base::ScopedFile proc_maps(base::OpenFile("/proc/self/maps", O_RDONLY));
-  base::ScopedFile proc_mem(base::OpenFile("/proc/self/mem", O_RDONLY));
-  GlobalCallstackTrie callsites;
-  UnwindingMetadata metadata(getpid(), std::move(proc_maps),
-                             std::move(proc_mem));
-  WireMessage msg;
-  auto record = GetRecord(&msg);
-  AllocRecord out;
-  ASSERT_TRUE(DoUnwind(&msg, &metadata, &out));
-  ASSERT_GT(out.frames.size(), 0u);
-  int st;
-  std::unique_ptr<char, base::FreeDeleter> demangled(abi::__cxa_demangle(
-      out.frames[0].frame.function_name.c_str(), nullptr, nullptr, &st));
-  ASSERT_EQ(st, 0) << "mangled: " << demangled.get()
-                   << ", frames: " << out.frames.size();
-  ASSERT_STREQ(demangled.get(),
-               "perfetto::profiling::(anonymous "
-               "namespace)::GetRecord(perfetto::profiling::WireMessage*)");
-}
+// TODO(rsavitski): Investigate TSAN unwinding.
+#if defined(THREAD_SANITIZER)
+#define MAYBE_DoUnwind DISABLED_DoUnwind
+#else
+#define MAYBE_DoUnwind DoUnwind
+#endif
 
-TEST(UnwindingTest, DoUnwindReparse) {
+TEST(UnwindingTest, MAYBE_DoUnwind) {
   base::ScopedFile proc_maps(base::OpenFile("/proc/self/maps", O_RDONLY));
   base::ScopedFile proc_mem(base::OpenFile("/proc/self/mem", O_RDONLY));
   GlobalCallstackTrie callsites;
   UnwindingMetadata metadata(getpid(), std::move(proc_maps),
                              std::move(proc_mem));
-  // Force reparse in DoUnwind.
-  metadata.maps.Reset();
   WireMessage msg;
   auto record = GetRecord(&msg);
   AllocRecord out;
   ASSERT_TRUE(DoUnwind(&msg, &metadata, &out));
-  ASSERT_GT(out.frames.size(), 0u);
   int st;
   std::unique_ptr<char, base::FreeDeleter> demangled(abi::__cxa_demangle(
       out.frames[0].frame.function_name.c_str(), nullptr, nullptr, &st));
-  ASSERT_EQ(st, 0) << "mangled: " << demangled.get()
-                   << ", frames: " << out.frames.size();
+  ASSERT_EQ(st, 0);
   ASSERT_STREQ(demangled.get(),
                "perfetto::profiling::(anonymous "
                "namespace)::GetRecord(perfetto::profiling::WireMessage*)");
diff --git a/src/profiling/memory/utils.cc b/src/profiling/memory/utils.cc
deleted file mode 100644
index b424192..0000000
--- a/src/profiling/memory/utils.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/profiling/memory/utils.h"
-
-namespace perfetto {
-namespace profiling {
-
-// Behaves as a pread64, emulating it if not already exposed by the standard
-// library. Safe to use on 32bit platforms for addresses with the top bit set.
-// Clobbers the |fd| seek position if emulating.
-ssize_t ReadAtOffsetClobberSeekPos(int fd,
-                                   void* buf,
-                                   size_t count,
-                                   off64_t addr) {
-#ifdef __BIONIC__
-  return pread64(fd, buf, count, addr);
-#else
-  if (lseek64(fd, addr, SEEK_SET) == -1)
-    return -1;
-  return read(fd, buf, count);
-#endif
-}
-
-// Behaves as a pread64, emulating it if not already exposed by the standard
-// library.
-// Clobbers the |fd| seek position if emulating.
-ssize_t WriteAtOffsetClobberSeekPos(int fd,
-                                    void* buf,
-                                    size_t count,
-                                    off64_t addr) {
-#ifdef __BIONIC__
-  return pwrite64(fd, buf, count, addr);
-#else
-  if (lseek64(fd, addr, SEEK_SET) == -1)
-    return -1;
-  return write(fd, buf, count);
-#endif
-}
-
-}  // namespace profiling
-}  // namespace perfetto
diff --git a/src/profiling/memory/utils.h b/src/profiling/memory/utils.h
deleted file mode 100644
index 5e375c9..0000000
--- a/src/profiling/memory/utils.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_PROFILING_MEMORY_UTILS_H_
-#define SRC_PROFILING_MEMORY_UTILS_H_
-
-#include <unistd.h>
-
-namespace perfetto {
-namespace profiling {
-
-ssize_t ReadAtOffsetClobberSeekPos(int fd,
-                                   void* buf,
-                                   size_t count,
-                                   off64_t addr);
-
-ssize_t WriteAtOffsetClobberSeekPos(int fd,
-                                    void* buf,
-                                    size_t count,
-                                    off64_t addr);
-}
-}  // namespace perfetto
-
-#endif  // SRC_PROFILING_MEMORY_UTILS_H_
diff --git a/src/profiling/memory/wire_protocol.cc b/src/profiling/memory/wire_protocol.cc
index 6d561c3..67b0f38 100644
--- a/src/profiling/memory/wire_protocol.cc
+++ b/src/profiling/memory/wire_protocol.cc
@@ -17,8 +17,8 @@
 #include "src/profiling/memory/wire_protocol.h"
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/unix_socket.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/unix_socket.h"
+#include "perfetto/base/utils.h"
 
 #include <sys/socket.h>
 #include <sys/types.h>
@@ -60,7 +60,7 @@
     iovecs[1].iov_base = msg.free_header;
     iovecs[1].iov_len = sizeof(*msg.free_header);
   } else {
-    PERFETTO_DFATAL_OR_ELOG("Neither alloc_header nor free_header set.");
+    PERFETTO_DFATAL("Neither alloc_header nor free_header set.");
     errno = EINVAL;
     return false;
   }
@@ -87,10 +87,10 @@
       errno = EAGAIN;
       return false;
     }
-    buf = shmem->BeginWrite(lock, static_cast<size_t>(total_size));
+    buf = shmem->BeginWrite(lock, total_size);
   }
   if (!buf) {
-    PERFETTO_DLOG("Buffer overflow.");
+    PERFETTO_DFATAL("Buffer overflow.");
     shmem->EndWrite(std::move(buf));
     errno = EAGAIN;
     return false;
@@ -111,7 +111,7 @@
   RecordType* record_type;
   char* end = buf + size;
   if (!ViewAndAdvance<RecordType>(&buf, &record_type, end)) {
-    PERFETTO_DFATAL_OR_ELOG("Cannot read record type.");
+    PERFETTO_DFATAL("Cannot read record type.");
     return false;
   }
 
@@ -121,22 +121,22 @@
 
   if (*record_type == RecordType::Malloc) {
     if (!ViewAndAdvance<AllocMetadata>(&buf, &out->alloc_header, end)) {
-      PERFETTO_DFATAL_OR_ELOG("Cannot read alloc header.");
+      PERFETTO_DFATAL("Cannot read alloc header.");
       return false;
     }
     out->payload = buf;
     if (buf > end) {
-      PERFETTO_DFATAL_OR_ELOG("Receive buffer overflowed");
+      PERFETTO_DFATAL("Buffer overflowed");
       return false;
     }
     out->payload_size = static_cast<size_t>(end - buf);
   } else if (*record_type == RecordType::Free) {
     if (!ViewAndAdvance<FreeBatch>(&buf, &out->free_header, end)) {
-      PERFETTO_DFATAL_OR_ELOG("Cannot read free header.");
+      PERFETTO_DFATAL("Cannot read free header.");
       return false;
     }
   } else {
-    PERFETTO_DFATAL_OR_ELOG("Invalid record type.");
+    PERFETTO_DFATAL("Invalid record type.");
     return false;
   }
   return true;
diff --git a/src/profiling/memory/wire_protocol.h b/src/profiling/memory/wire_protocol.h
index 3ca21d9..a0e13be 100644
--- a/src/profiling/memory/wire_protocol.h
+++ b/src/profiling/memory/wire_protocol.h
@@ -22,12 +22,12 @@
 
 #include <inttypes.h>
 #include <unwindstack/Elf.h>
-#include <unwindstack/MachineArm.h>
-#include <unwindstack/MachineArm64.h>
-#include <unwindstack/MachineMips.h>
-#include <unwindstack/MachineMips64.h>
-#include <unwindstack/MachineX86.h>
-#include <unwindstack/MachineX86_64.h>
+#include <unwindstack/UserArm.h>
+#include <unwindstack/UserArm64.h>
+#include <unwindstack/UserMips.h>
+#include <unwindstack/UserMips64.h>
+#include <unwindstack/UserX86.h>
+#include <unwindstack/UserX86_64.h>
 
 #include "src/profiling/memory/shared_ring_buffer.h"
 
@@ -69,12 +69,12 @@
       constexpr_max(
         constexpr_max(
             constexpr_max(
-              sizeof(uint32_t) * unwindstack::ARM_REG_LAST,
-              sizeof(uint64_t) * unwindstack::ARM64_REG_LAST),
-            sizeof(uint32_t) * unwindstack::X86_REG_LAST),
-          sizeof(uint64_t) * unwindstack::X86_64_REG_LAST),
-        sizeof(uint32_t) * unwindstack::MIPS_REG_LAST),
-      sizeof(uint64_t) * unwindstack::MIPS64_REG_LAST
+              sizeof(unwindstack::arm_user_regs),
+              sizeof(unwindstack::arm64_user_regs)),
+            sizeof(unwindstack::x86_user_regs)),
+          sizeof(unwindstack::x86_64_user_regs)),
+        sizeof(unwindstack::mips_user_regs)),
+      sizeof(unwindstack::mips64_user_regs)
   );
 // clang-format on
 
@@ -90,7 +90,7 @@
   // Size of the allocation that was made.
   uint64_t alloc_size;
   // Total number of bytes attributed to this allocation.
-  uint64_t sample_size;
+  uint64_t total_size;
   // Pointer returned by malloc(2) for this allocation.
   uint64_t alloc_address;
   // Current value of the stack pointer.
@@ -99,7 +99,8 @@
   uint64_t stack_pointer_offset;
   uint64_t clock_monotonic_coarse_timestamp;
   alignas(uint64_t) char register_data[kMaxRegisterDataSize];
-  // CPU architecture of the client.
+  // CPU architecture of the client. This determines the size of the
+  // register data that follows this struct.
   unwindstack::ArchEnum arch;
 };
 
@@ -118,9 +119,8 @@
 
 enum HandshakeFDs : size_t {
   kHandshakeMaps = 0,
-  kHandshakeMem,
-  kHandshakePageIdle,
-  kHandshakeSize,
+  kHandshakeMem = 1,
+  kHandshakeSize = 2,
 };
 
 struct WireMessage {
diff --git a/src/profiling/memory/wire_protocol_unittest.cc b/src/profiling/memory/wire_protocol_unittest.cc
index 462ea06..189cba0 100644
--- a/src/profiling/memory/wire_protocol_unittest.cc
+++ b/src/profiling/memory/wire_protocol_unittest.cc
@@ -15,14 +15,15 @@
  */
 
 #include "src/profiling/memory/wire_protocol.h"
+#include "perfetto/base/logging.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/unix_socket.h"
 
 #include <sys/socket.h>
 #include <sys/types.h>
 
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/unix_socket.h"
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace profiling {
@@ -56,10 +57,8 @@
   int sv[2];
   PERFETTO_CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0);
   base::UnixSocketRaw send_sock(base::ScopedFile(sv[0]),
-                                base::SockFamily::kUnix,
                                 base::SockType::kStream);
   base::UnixSocketRaw recv_sock(base::ScopedFile(sv[1]),
-                                base::SockFamily::kUnix,
                                 base::SockType::kStream);
   char msg[] = "a";
   PERFETTO_CHECK(send_sock.Send(msg, sizeof(msg), &fd, 1));
diff --git a/src/protozero/BUILD.gn b/src/protozero/BUILD.gn
index b2cc13a..1197437 100644
--- a/src/protozero/BUILD.gn
+++ b/src/protozero/BUILD.gn
@@ -15,7 +15,7 @@
 import("../../gn/fuzzer.gni")
 import("../../gn/perfetto.gni")
 import("../../gn/proto_library.gni")
-import("../../gn/test.gni")
+import("../../gn/protozero_library.gni")
 
 source_set("protozero") {
   public_configs = [ "../../gn:default_config" ]
@@ -24,13 +24,12 @@
   ]
   deps = [
     "../../gn:default_deps",
-    "../../include/perfetto/base",
-    "../../include/perfetto/ext/base",  # TODO(primiano): remove this
+    "../../gn:gtest_prod_config",
+    "../base",
   ]
   sources = [
     "message.cc",
     "message_handle.cc",
-    "packed_repeated_fields.cc",
     "proto_decoder.cc",
     "scattered_heap_buffer.cc",
     "scattered_stream_null_delegate.cc",
@@ -38,26 +37,26 @@
   ]
 }
 
-static_library("libprotozero") {
-  complete_static_lib = true
-  deps = [
-    ":protozero",
-  ]
+if (!build_with_chromium) {
+  static_library("libprotozero") {
+    deps = [
+      ":protozero",
+    ]
+  }
 }
 
-perfetto_unittest_source_set("unittests") {
+source_set("unittests") {
   testonly = true
   deps = [
     ":protozero",
     ":testing_messages_lite",
     ":testing_messages_zero",
     "../../gn:default_deps",
-    "../../gn:gtest_and_gmock",
+    "../../gn:gtest_deps",
     "../base",
     "../base:test_support",
   ]
   sources = [
-    "copyable_ptr_unittest.cc",
     "message_handle_unittest.cc",
     "message_unittest.cc",
     "proto_decoder_unittest.cc",
@@ -71,18 +70,25 @@
 
 # Generates both xxx.pbzero.h and xxx.pb.h (official proto).
 
-perfetto_proto_library("testing_messages_@TYPE@") {
-  proto_generators = [
-    "lite",
-    "zero",
-  ]
-  sources = [
-    "test/example_proto/library.proto",
-    "test/example_proto/library_internals/galaxies.proto",
-    "test/example_proto/test_messages.proto",
-    "test/example_proto/upper_import.proto",
-  ]
-  proto_path = perfetto_root_path
+testing_proto_sources = [
+  "test/example_proto/library.proto",
+  "test/example_proto/library_internals/galaxies.proto",
+  "test/example_proto/test_messages.proto",
+  "test/example_proto/upper_import.proto",
+]
+
+protozero_library("testing_messages_zero") {
+  sources = testing_proto_sources
+  proto_in_dir = perfetto_root_path
+  proto_out_dir = perfetto_root_path
+  generator_plugin_options = "wrapper_namespace=pbzero"
+}
+
+proto_library("testing_messages_lite") {
+  generate_python = false
+  sources = testing_proto_sources
+  proto_in_dir = perfetto_root_path
+  proto_out_dir = perfetto_root_path
 }
 
 perfetto_fuzzer_test("protozero_decoder_fuzzer") {
@@ -92,6 +98,5 @@
   deps = [
     ":protozero",
     "../../gn:default_deps",
-    "../base",
   ]
 }
diff --git a/src/protozero/copyable_ptr_unittest.cc b/src/protozero/copyable_ptr_unittest.cc
deleted file mode 100644
index d9be950..0000000
--- a/src/protozero/copyable_ptr_unittest.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/protozero/copyable_ptr.h"
-
-#include "test/gtest_and_gmock.h"
-
-namespace protozero {
-namespace {
-
-struct X {
-  X() = default;
-  X(const X&) = default;
-  X& operator=(const X&) = default;
-  ~X() { val = -1; }
-
-  friend bool operator==(const X& lhs, const X& rhs) {
-    return lhs.val == rhs.val;
-  }
-
-  // Deliberately unusual implementation.
-  friend bool operator!=(const X& lhs, const X& rhs) {
-    return lhs.val == rhs.val * -1;
-  }
-
-  int val = 0;
-};
-
-TEST(CopyablePtrTest, CopyOperators) {
-  CopyablePtr<X> p1;
-  p1->val = 1;
-  ASSERT_NE(p1.get(), nullptr);
-  ASSERT_EQ(&*p1, p1.get());
-
-  CopyablePtr<X> p2(p1);
-  EXPECT_NE(p1.get(), nullptr);
-  EXPECT_NE(p2.get(), nullptr);
-  EXPECT_NE(p1.get(), p2.get());
-
-  p2->val = 2;
-  EXPECT_EQ(p1->val, 1);
-  EXPECT_EQ(p2->val, 2);
-
-  {
-    CopyablePtr<X> p3;
-    p3 = p1;
-    EXPECT_EQ(p3->val, 1);
-
-    p3 = p2;
-    EXPECT_EQ(p3->val, 2);
-
-    p3->val = 3;
-    EXPECT_EQ(p3->val, 3);
-  }
-
-  EXPECT_EQ(p1->val, 1);
-  EXPECT_EQ(p2->val, 2);
-}
-
-TEST(CopyablePtrTest, MoveOperators) {
-  CopyablePtr<X> p1;
-  p1->val = 1;
-
-  CopyablePtr<X> p2(std::move(p1));
-  EXPECT_EQ(p2->val, 1);
-
-  // The moved-from object needs to stay valid and non-null.
-  EXPECT_EQ(p1->val, 0);
-  {
-    CopyablePtr<X> p3;
-    p3->val = 3;
-    p1 = std::move(p3);
-    EXPECT_EQ(p1->val, 3);
-    EXPECT_EQ(p3->val, 0);
-  }
-  EXPECT_EQ(p1->val, 3);
-}
-
-TEST(CopyablePtrTest, DeepCompare) {
-  CopyablePtr<X> p1;
-  p1->val = 1;
-
-  CopyablePtr<X> p2;
-  p2->val = 2;
-
-  CopyablePtr<X> p3;
-  p3->val = -2;
-
-  EXPECT_NE(p1.get(), p2.get());
-  EXPECT_NE(p1.get(), p3.get());
-
-  EXPECT_FALSE(p1 == p2);
-  EXPECT_FALSE(p1 == p3);
-  EXPECT_FALSE(p2 == p3);
-
-  EXPECT_FALSE(p1 != p2);  // The operator!= is special, see above.
-  EXPECT_TRUE(p2 != p3);
-
-  p1->val = -2;
-  EXPECT_TRUE(p1 != p2);
-  EXPECT_FALSE(p1 == p2);
-}
-
-}  // namespace
-}  // namespace protozero
diff --git a/src/protozero/message_handle_unittest.cc b/src/protozero/message_handle_unittest.cc
index 7f0ee08..1ca4c28 100644
--- a/src/protozero/message_handle_unittest.cc
+++ b/src/protozero/message_handle_unittest.cc
@@ -16,8 +16,8 @@
 
 #include "perfetto/protozero/message_handle.h"
 
+#include "gtest/gtest.h"
 #include "perfetto/protozero/message.h"
-#include "test/gtest_and_gmock.h"
 
 namespace protozero {
 
diff --git a/src/protozero/message_unittest.cc b/src/protozero/message_unittest.cc
index d75dcd0..c61bc56 100644
--- a/src/protozero/message_unittest.cc
+++ b/src/protozero/message_unittest.cc
@@ -22,10 +22,10 @@
 #include <utility>
 #include <vector>
 
+#include "gtest/gtest.h"
 #include "perfetto/base/logging.h"
 #include "src/base/test/utils.h"
 #include "src/protozero/test/fake_scattered_buffer.h"
-#include "test/gtest_and_gmock.h"
 
 namespace protozero {
 
diff --git a/src/protozero/packed_repeated_fields.cc b/src/protozero/packed_repeated_fields.cc
deleted file mode 100644
index b0e23c5..0000000
--- a/src/protozero/packed_repeated_fields.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2017 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 "perfetto/protozero/packed_repeated_fields.h"
-
-#include "perfetto/ext/base/utils.h"
-
-namespace protozero {
-
-// static
-constexpr size_t PackedBufferBase::kOnStackStorageSize;
-
-void PackedBufferBase::GrowSlowpath() {
-  size_t write_off = static_cast<size_t>(write_ptr_ - storage_begin_);
-  size_t old_size = static_cast<size_t>(storage_end_ - storage_begin_);
-  size_t new_size = old_size < 65536 ? (old_size * 2) : (old_size * 3 / 2);
-  new_size = perfetto::base::AlignUp<4096>(new_size);
-  std::unique_ptr<uint8_t[]> new_buf(new uint8_t[new_size]);
-  memcpy(new_buf.get(), storage_begin_, old_size);
-  heap_buf_ = std::move(new_buf);
-  storage_begin_ = heap_buf_.get();
-  storage_end_ = storage_begin_ + new_size;
-  write_ptr_ = storage_begin_ + write_off;
-}
-
-void PackedBufferBase::Reset() {
-  heap_buf_.reset();
-  storage_begin_ = reinterpret_cast<uint8_t*>(&stack_buf_[0]);
-  storage_end_ = reinterpret_cast<uint8_t*>(&stack_buf_[kOnStackStorageSize]);
-  write_ptr_ = storage_begin_;
-}
-
-}  // namespace protozero
diff --git a/src/protozero/proto_decoder.cc b/src/protozero/proto_decoder.cc
index bd563fb..4eddec7 100644
--- a/src/protozero/proto_decoder.cc
+++ b/src/protozero/proto_decoder.cc
@@ -17,10 +17,9 @@
 #include "perfetto/protozero/proto_decoder.h"
 
 #include <string.h>
-#include <limits>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/utils.h"
 #include "perfetto/protozero/proto_utils.h"
 
 namespace protozero {
@@ -57,7 +56,7 @@
     return res;
 
   uint64_t preamble = 0;
-  if (PERFETTO_LIKELY(*pos < 0x80)) {  // Fastpath for fields with ID < 16.
+  if (PERFETTO_LIKELY(*pos < 0x80)) {  // Fastpath for fields with ID < 32.
     preamble = *(pos++);
   } else {
     pos = ParseVarInt(pos, end, &preamble);
@@ -129,7 +128,7 @@
   }
 
   if (PERFETTO_UNLIKELY(field_id > std::numeric_limits<uint16_t>::max())) {
-    // PERFETTO_DFATAL("Cannot parse proto field ids > 0xFFFF");
+    PERFETTO_DFATAL("Cannot parse proto field ids > 0xFFFF");
     return res;
   }
 
diff --git a/src/protozero/proto_decoder_unittest.cc b/src/protozero/proto_decoder_unittest.cc
index 1a63cef..2f5ab53 100644
--- a/src/protozero/proto_decoder_unittest.cc
+++ b/src/protozero/proto_decoder_unittest.cc
@@ -16,17 +16,12 @@
 
 #include "perfetto/protozero/proto_decoder.h"
 
-#include "perfetto/ext/base/utils.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/utils.h"
 #include "perfetto/protozero/message.h"
 #include "perfetto/protozero/proto_utils.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
-#include "test/gtest_and_gmock.h"
-
-#include "src/protozero/test/example_proto/test_messages.pb.h"
-#include "src/protozero/test/example_proto/test_messages.pbzero.h"
-
-namespace pbtest = foo::bar::pbzero;  // Generated by the protozero plugin.
-namespace pbgold = foo::bar;  // Generated by the official protobuf compiler.
 
 namespace protozero {
 namespace {
@@ -83,10 +78,9 @@
   auto used_range = delegate.slices()[0].GetUsedRange();
 
   TypedProtoDecoder<2, true> tpd(used_range.begin, used_range.size());
-  auto it = tpd.GetRepeated<int32_t>(/*field_id=*/2);
+  auto it = tpd.GetRepeated(/*field_id=*/2);
   EXPECT_TRUE(it);
-  EXPECT_EQ(it.field().as_int32(), 10);
-  EXPECT_EQ(*it, 10);
+  EXPECT_EQ(it->as_int32(), 10);
   EXPECT_FALSE(++it);
 }
 
@@ -102,10 +96,10 @@
   std::vector<uint8_t> data = delegate.StitchSlices();
 
   TypedProtoDecoder<2, true> tpd(data.data(), data.size());
-  auto it = tpd.GetRepeated<int32_t>(/*field_id=*/2);
+  auto it = tpd.GetRepeated(/*field_id=*/2);
   for (int i = 0; i < 2000; i++) {
     EXPECT_TRUE(it);
-    EXPECT_EQ(*it, i);
+    EXPECT_EQ(it->as_int32(), i);
     ++it;
   }
   EXPECT_FALSE(it);
@@ -114,7 +108,7 @@
 TEST(ProtoDecoderTest, NoRepeatedField) {
   uint8_t buf[] = {0x01};
   TypedProtoDecoder<2, true> tpd(buf, 1);
-  auto it = tpd.GetRepeated<int32_t>(/*field_id=*/1);
+  auto it = tpd.GetRepeated(/*field_id=*/1);
   EXPECT_FALSE(it);
   EXPECT_FALSE(tpd.Get(2).valid());
 }
@@ -157,19 +151,19 @@
   EXPECT_EQ(tpd.Get(3).as_int32(), 30);
 
   // But when iterating we should see values in the original order.
-  auto it = tpd.GetRepeated<int32_t>(1);
-  EXPECT_EQ(*it, 10);
-  EXPECT_EQ(*++it, 11);
+  auto it = tpd.GetRepeated(1);
+  EXPECT_EQ(it->as_int32(), 10);
+  EXPECT_EQ((++it)->as_int32(), 11);
   EXPECT_FALSE(++it);
 
-  it = tpd.GetRepeated<int32_t>(2);
-  EXPECT_EQ(*it++, 20);
-  EXPECT_EQ(*it++, 21);
-  EXPECT_EQ(*it++, 22);
-  EXPECT_FALSE(it);
+  it = tpd.GetRepeated(2);
+  EXPECT_EQ(it->as_int32(), 20);
+  EXPECT_EQ((++it)->as_int32(), 21);
+  EXPECT_EQ((++it)->as_int32(), 22);
+  EXPECT_FALSE(++it);
 
-  it = tpd.GetRepeated<int32_t>(3);
-  EXPECT_EQ(*it, 30);
+  it = tpd.GetRepeated(3);
+  EXPECT_EQ(it->as_int32(), 30);
   EXPECT_FALSE(++it);
 }
 
@@ -225,8 +219,8 @@
 
   // Test float and doubles decoding.
   const char buf[] = "\x0d\x00\x00\xa0\x3f\x11\x00\x00\x00\x00\x00\x42\x8f\xc0";
-  TypedProtoDecoder<2, false> decoder(reinterpret_cast<const uint8_t*>(buf),
-                                      sizeof(buf));
+  TypedProtoDecoder<2, 0> decoder(reinterpret_cast<const uint8_t*>(buf),
+                                  sizeof(buf));
   EXPECT_FLOAT_EQ(decoder.Get(1).as_float(), 1.25f);
   EXPECT_DOUBLE_EQ(decoder.Get(2).as_double(), -1000.25);
 }
@@ -243,269 +237,5 @@
   EXPECT_FALSE(field2);
 }
 
-TEST(ProtoDecoderTest, MoveTypedDecoder) {
-  HeapBuffered<Message> message;
-  message->AppendVarInt(/*field_id=*/1, 10);
-  std::vector<uint8_t> proto = message.SerializeAsArray();
-
-  // Construct a decoder that uses inline storage (i.e., the fields are stored
-  // within the object itself).
-  using Decoder = TypedProtoDecoder<32, false>;
-  std::unique_ptr<Decoder> decoder(new Decoder(proto.data(), proto.size()));
-  ASSERT_GE(reinterpret_cast<uintptr_t>(&decoder->at<1>()),
-            reinterpret_cast<uintptr_t>(decoder.get()));
-  ASSERT_LT(reinterpret_cast<uintptr_t>(&decoder->at<1>()),
-            reinterpret_cast<uintptr_t>(decoder.get()) + sizeof(Decoder));
-
-  // Move the decoder into another object and deallocate the original object.
-  Decoder decoder2(std::move(*decoder));
-  decoder.reset();
-
-  // Check that the contents got moved correctly.
-  EXPECT_EQ(decoder2.Get(1).as_int32(), 10);
-  ASSERT_GE(reinterpret_cast<uintptr_t>(&decoder2.at<1>()),
-            reinterpret_cast<uintptr_t>(&decoder2));
-  ASSERT_LT(reinterpret_cast<uintptr_t>(&decoder2.at<1>()),
-            reinterpret_cast<uintptr_t>(&decoder2) + sizeof(Decoder));
-}
-
-TEST(ProtoDecoderTest, PackedRepeatedVarint) {
-  std::vector<int32_t> values = {42, 255, 0, -1};
-
-  // serialize using protobuf library
-  pbgold::PackedRepeatedFields msg;
-  for (auto v : values)
-    msg.add_field_int32(v);
-  std::string serialized = msg.SerializeAsString();
-
-  // decode using TypedProtoDecoder directly
-  {
-    constexpr int kFieldId =
-        pbtest::PackedRepeatedFields::kFieldInt32FieldNumber;
-    TypedProtoDecoder<kFieldId, false> decoder(
-        reinterpret_cast<const uint8_t*>(serialized.data()), serialized.size());
-    ASSERT_TRUE(decoder.at<kFieldId>().valid());
-    bool parse_error = false;
-    auto packed_it =
-        decoder.GetPackedRepeated<proto_utils::ProtoWireType::kVarInt, int32_t>(
-            kFieldId, &parse_error);
-
-    std::vector<int32_t> decoded_values;
-    for (; packed_it; ++packed_it) {
-      auto v = *packed_it;
-      decoded_values.push_back(v);
-    }
-    ASSERT_EQ(values, decoded_values);
-    ASSERT_FALSE(parse_error);
-  }
-
-  // decode using plugin-generated accessor
-  {
-    auto decoder = pbtest::PackedRepeatedFields::Decoder(serialized);
-    ASSERT_TRUE(decoder.has_field_int32());
-
-    bool parse_error = false;
-    std::vector<int32_t> decoded_values;
-    for (auto packed_it = decoder.field_int32(&parse_error); packed_it;
-         ++packed_it) {
-      auto v = *packed_it;
-      decoded_values.push_back(v);
-    }
-    ASSERT_EQ(values, decoded_values);
-    ASSERT_FALSE(parse_error);
-  }
-
-  // unset field case
-  pbgold::PackedRepeatedFields empty_msg;
-  std::string empty_serialized = empty_msg.SerializeAsString();
-  auto decoder = pbtest::PackedRepeatedFields::Decoder(empty_serialized);
-  ASSERT_FALSE(decoder.has_field_int32());
-  bool parse_error = false;
-  auto packed_it = decoder.field_int32(&parse_error);
-  ASSERT_FALSE(bool(packed_it));
-  ASSERT_FALSE(parse_error);
-}
-
-TEST(ProtoDecoderTest, PackedRepeatedFixed32) {
-  std::vector<uint32_t> values = {42, 255, 0, 1};
-
-  // serialize using protobuf library
-  pbgold::PackedRepeatedFields msg;
-  for (auto v : values)
-    msg.add_field_fixed32(v);
-  std::string serialized = msg.SerializeAsString();
-
-  // decode using TypedProtoDecoder directly
-  {
-    constexpr int kFieldId =
-        pbtest::PackedRepeatedFields::kFieldFixed32FieldNumber;
-    TypedProtoDecoder<kFieldId, false> decoder(
-        reinterpret_cast<const uint8_t*>(serialized.data()), serialized.size());
-    bool parse_error = false;
-    auto packed_it =
-        decoder
-            .GetPackedRepeated<proto_utils::ProtoWireType::kFixed32, uint32_t>(
-                kFieldId, &parse_error);
-
-    std::vector<uint32_t> decoded_values;
-    for (; packed_it; ++packed_it) {
-      auto v = *packed_it;
-      decoded_values.push_back(v);
-    }
-    ASSERT_EQ(values, decoded_values);
-    ASSERT_FALSE(parse_error);
-  }
-
-  // decode using plugin-generated accessor
-  {
-    auto decoder = pbtest::PackedRepeatedFields::Decoder(serialized);
-    ASSERT_TRUE(decoder.has_field_fixed32());
-
-    bool parse_error = false;
-    std::vector<uint32_t> decoded_values;
-    for (auto packed_it = decoder.field_fixed32(&parse_error); packed_it;
-         packed_it++) {
-      auto v = *packed_it;
-      decoded_values.push_back(v);
-    }
-    ASSERT_EQ(values, decoded_values);
-    ASSERT_FALSE(parse_error);
-  }
-
-  // unset field case
-  pbgold::PackedRepeatedFields empty_msg;
-  std::string empty_serialized = empty_msg.SerializeAsString();
-  auto decoder = pbtest::PackedRepeatedFields::Decoder(empty_serialized);
-  ASSERT_FALSE(decoder.has_field_fixed32());
-  bool parse_error = false;
-  auto packed_it = decoder.field_fixed32(&parse_error);
-  ASSERT_FALSE(bool(packed_it));
-  ASSERT_FALSE(parse_error);
-}
-
-TEST(ProtoDecoderTest, PackedRepeatedFixed64) {
-  std::vector<int64_t> values = {42, 255, 0, -1};
-
-  // serialize using protobuf library
-  pbgold::PackedRepeatedFields msg;
-  for (auto v : values)
-    msg.add_field_sfixed64(v);
-  std::string serialized = msg.SerializeAsString();
-
-  // decode using TypedProtoDecoder directly
-  {
-    constexpr int kFieldId =
-        pbtest::PackedRepeatedFields::kFieldSfixed64FieldNumber;
-    TypedProtoDecoder<kFieldId, false> decoder(
-        reinterpret_cast<const uint8_t*>(serialized.data()), serialized.size());
-    bool parse_error = false;
-    auto packed_it =
-        decoder
-            .GetPackedRepeated<proto_utils::ProtoWireType::kFixed64, int64_t>(
-                kFieldId, &parse_error);
-
-    std::vector<int64_t> decoded_values;
-    for (; packed_it; ++packed_it) {
-      auto v = *packed_it;
-      decoded_values.push_back(v);
-    }
-    ASSERT_EQ(values, decoded_values);
-    ASSERT_FALSE(parse_error);
-  }
-
-  // decode using plugin-generated accessor
-  {
-    auto decoder = pbtest::PackedRepeatedFields::Decoder(serialized);
-    ASSERT_TRUE(decoder.has_field_sfixed64());
-
-    bool parse_error = false;
-    std::vector<int64_t> decoded_values;
-    for (auto packed_it = decoder.field_sfixed64(&parse_error); packed_it;
-         packed_it++) {
-      auto v = *packed_it;
-      decoded_values.push_back(v);
-    }
-    ASSERT_EQ(values, decoded_values);
-    ASSERT_FALSE(parse_error);
-  }
-
-  // unset field case
-  pbgold::PackedRepeatedFields empty_msg;
-  std::string empty_serialized = empty_msg.SerializeAsString();
-  auto decoder = pbtest::PackedRepeatedFields::Decoder(empty_serialized);
-  ASSERT_FALSE(decoder.has_field_sfixed64());
-  bool parse_error = false;
-  auto packed_it = decoder.field_sfixed64(&parse_error);
-  ASSERT_FALSE(bool(packed_it));
-  ASSERT_FALSE(parse_error);
-}
-
-TEST(ProtoDecoderTest, ZeroLengthPackedRepeatedField) {
-  HeapBuffered<pbtest::PackedRepeatedFields> msg;
-  PackedVarInt buf;
-  msg->set_field_int32(buf);
-  std::string serialized = msg.SerializeAsString();
-
-  // Encoded as 2 bytes: tag/field, and a length of zero.
-  EXPECT_EQ(2u, serialized.size());
-
-  // Appears empty when decoded.
-  auto decoder = pbtest::PackedRepeatedFields::Decoder(serialized);
-  ASSERT_TRUE(decoder.has_field_int32());
-  bool parse_error = false;
-  auto packed_it = decoder.field_int32(&parse_error);
-  ASSERT_FALSE(bool(packed_it));
-  ASSERT_FALSE(parse_error);
-}
-
-TEST(ProtoDecoderTest, MalformedPackedFixedBuffer) {
-  // Encode a fixed32 field where the length is not a multiple of 4 bytes.
-  HeapBuffered<pbtest::PackedRepeatedFields> msg;
-  PackedFixedSizeInt<uint32_t> buf;
-  buf.Append(1);
-  buf.Append(2);
-  buf.Append(3);
-  const uint8_t* data = buf.data();
-  size_t size = buf.size();
-  size_t invalid_size = size - 2;
-  constexpr int kFieldId =
-      pbtest::PackedRepeatedFields::kFieldFixed32FieldNumber;
-  msg->AppendBytes(kFieldId, data, invalid_size);
-  std::string serialized = msg.SerializeAsString();
-
-  // Iterator indicates parse error.
-  auto decoder = pbtest::PackedRepeatedFields::Decoder(serialized);
-  ASSERT_TRUE(decoder.has_field_fixed32());
-  bool parse_error = false;
-  for (auto packed_it = decoder.field_fixed32(&parse_error); packed_it;
-       packed_it++) {
-  }
-  ASSERT_TRUE(parse_error);
-}
-
-TEST(ProtoDecoderTest, MalformedPackedVarIntBuffer) {
-  // Encode a varint field with the last varint chopped off partway.
-  HeapBuffered<pbtest::PackedRepeatedFields> msg;
-  PackedVarInt buf;
-  buf.Append(1024);
-  buf.Append(2048);
-  buf.Append(4096);
-  const uint8_t* data = buf.data();
-  size_t size = buf.size();
-  size_t invalid_size = size - 1;
-  constexpr int kFieldId = pbtest::PackedRepeatedFields::kFieldInt32FieldNumber;
-  msg->AppendBytes(kFieldId, data, invalid_size);
-  std::string serialized = msg.SerializeAsString();
-
-  // Iterator indicates parse error.
-  auto decoder = pbtest::PackedRepeatedFields::Decoder(serialized);
-  ASSERT_TRUE(decoder.has_field_int32());
-  bool parse_error = false;
-  for (auto packed_it = decoder.field_int32(&parse_error); packed_it;
-       packed_it++) {
-  }
-  ASSERT_TRUE(parse_error);
-}
-
 }  // namespace
 }  // namespace protozero
diff --git a/src/protozero/proto_utils_unittest.cc b/src/protozero/proto_utils_unittest.cc
index 9d56d07..ad63258 100644
--- a/src/protozero/proto_utils_unittest.cc
+++ b/src/protozero/proto_utils_unittest.cc
@@ -18,9 +18,9 @@
 
 #include <limits>
 
+#include "gtest/gtest.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
-#include "test/gtest_and_gmock.h"
+#include "perfetto/base/utils.h"
 
 namespace protozero {
 namespace proto_utils {
diff --git a/src/protozero/protoc_plugin/BUILD.gn b/src/protozero/protoc_plugin/BUILD.gn
index 4a9c7f4..da15b1f 100644
--- a/src/protozero/protoc_plugin/BUILD.gn
+++ b/src/protozero/protoc_plugin/BUILD.gn
@@ -12,31 +12,16 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../gn/perfetto_host_executable.gni")
-
-# The plugin that generates zero-copy serializers and deserializers. Those are
-# the xxx.pbzero.h headers used all over the codebase.
-perfetto_host_executable("protozero_plugin") {
-  sources = [
-    "protozero_plugin.cc",
-  ]
-  deps = [
-    "../../../gn:default_deps",
-    "../../../gn:protoc_lib",
-    "../../../src/base",
-  ]
-}
-
-# The plugin that generates standalone C++ objects from protos (xxx.gen.h).
-# This is used for core classes traced needs to know about such as
-# DataSourceDescriptor.
-perfetto_host_executable("cppgen_plugin") {
-  sources = [
-    "cppgen_plugin.cc",
-  ]
-  deps = [
-    "../../../gn:default_deps",
-    "../../../gn:protoc_lib",
-    "../../../src/base",
-  ]
-}
+if (current_toolchain == host_toolchain) {
+  executable("protoc_plugin") {
+    sources = [
+      "protozero_generator.cc",
+      "protozero_generator.h",
+      "protozero_plugin.cc",
+    ]
+    deps = [
+      "../../../gn:default_deps",
+      "../../../gn:protoc_lib_deps",
+    ]
+  }
+}  # host_toolchain
diff --git a/src/protozero/protoc_plugin/cppgen_plugin.cc b/src/protozero/protoc_plugin/cppgen_plugin.cc
deleted file mode 100644
index e50c01e..0000000
--- a/src/protozero/protoc_plugin/cppgen_plugin.cc
+++ /dev/null
@@ -1,581 +0,0 @@
-/*
- * Copyright (C) 2017 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 <stdio.h>
-#include <stdlib.h>
-
-#include <fstream>
-#include <iostream>
-#include <set>
-#include <stack>
-#include <vector>
-
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/importer.h>
-#include <google/protobuf/compiler/plugin.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/util/field_comparator.h>
-#include <google/protobuf/util/message_differencer.h>
-
-#include "perfetto/ext/base/string_utils.h"
-
-namespace protozero {
-namespace {
-
-using namespace google::protobuf;
-using namespace google::protobuf::compiler;
-using namespace google::protobuf::io;
-using perfetto::base::SplitString;
-using perfetto::base::StripChars;
-using perfetto::base::StripSuffix;
-using perfetto::base::ToUpper;
-
-static constexpr auto TYPE_MESSAGE = FieldDescriptor::TYPE_MESSAGE;
-
-static const char kHeader[] =
-    "// DO NOT EDIT. Autogenerated by Perfetto cppgen_plugin\n";
-
-std::string GetProtoHeader(const FileDescriptor* file) {
-  return StripSuffix(file->name(), ".proto") + ".pb.h";
-}
-
-template <typename T = Descriptor>
-std::string GetFullName(const T* msg, bool with_namespace = false) {
-  std::string full_type;
-  full_type.append(msg->name());
-  for (const Descriptor* par = msg->containing_type(); par;
-       par = par->containing_type()) {
-    full_type.insert(0, par->name() + "_");
-  }
-  if (with_namespace) {
-    std::vector<std::string> namespaces =
-        SplitString(msg->file()->package(), ".");
-    for (auto it = namespaces.rbegin(); it != namespaces.rend(); it++) {
-      full_type.insert(0, *it + "::");
-    }
-  }
-  return full_type;
-}
-
-class CppObjGenerator : public ::google::protobuf::compiler::CodeGenerator {
- public:
-  CppObjGenerator();
-  ~CppObjGenerator() override;
-
-  // CodeGenerator implementation
-  bool Generate(const google::protobuf::FileDescriptor* file,
-                const std::string& options,
-                GeneratorContext* context,
-                std::string* error) const override;
-
- private:
-  std::string GetCppType(const FieldDescriptor* field, bool constref) const;
-  void GenEnum(const EnumDescriptor*, Printer*) const;
-  void GenEnumAliases(const EnumDescriptor*, Printer*) const;
-  void GenClassDecl(const Descriptor*, Printer*) const;
-  void GenClassDef(const Descriptor*, Printer*) const;
-};
-
-CppObjGenerator::CppObjGenerator() = default;
-CppObjGenerator::~CppObjGenerator() = default;
-
-bool CppObjGenerator::Generate(const google::protobuf::FileDescriptor* file,
-                               const std::string& /*options*/,
-                               GeneratorContext* context,
-                               std::string* error) const {
-  auto get_file_name = [](const FileDescriptor* proto) {
-    return StripSuffix(proto->name(), ".proto") + ".gen";
-  };
-
-  const std::unique_ptr<ZeroCopyOutputStream> h_fstream(
-      context->Open(get_file_name(file) + ".h"));
-  const std::unique_ptr<ZeroCopyOutputStream> cc_fstream(
-      context->Open(get_file_name(file) + ".cc"));
-
-  // Variables are delimited by $.
-  Printer h_printer(h_fstream.get(), '$');
-  Printer cc_printer(cc_fstream.get(), '$');
-
-  std::string include_guard = file->package() + "_" + file->name() + "_CPP_H_";
-  include_guard = ToUpper(include_guard);
-  include_guard = StripChars(include_guard, ".-/\\", '_');
-
-  h_printer.Print(kHeader);
-  h_printer.Print("#ifndef $g$\n#define $g$\n\n", "g", include_guard);
-  h_printer.Print("#include <stdint.h>\n");
-  h_printer.Print("#include <vector>\n");
-  h_printer.Print("#include <string>\n");
-  h_printer.Print("#include <type_traits>\n\n");
-  h_printer.Print("#include \"perfetto/protozero/copyable_ptr.h\"\n");
-  h_printer.Print("#include \"perfetto/base/export.h\"\n\n");
-
-  cc_printer.Print(kHeader);
-  cc_printer.Print("#pragma GCC diagnostic push\n");
-  cc_printer.Print("#pragma GCC diagnostic ignored \"-Wfloat-equal\"\n");
-
-  // Generate includes for translated types of dependencies.
-
-  // Figure out the subset of imports that are used only for lazy fields. We
-  // won't emit a C++ #include for them. This code is overly aggressive at
-  // removing imports: it rules them out as soon as it sees one lazy field
-  // whose type is defined in that import. A 100% correct solution would require
-  // to check that *all* dependent types for a given import are lazy before
-  // excluding that. In practice we don't need that because we don't use imports
-  // for both lazy and non-lazy fields.
-  std::set<std::string> lazy_imports;
-  for (int m = 0; m < file->message_type_count(); m++) {
-    const Descriptor* msg = file->message_type(m);
-    for (int i = 0; i < msg->field_count(); i++) {
-      const FieldDescriptor* field = msg->field(i);
-      if (field->options().lazy()) {
-        lazy_imports.insert(field->message_type()->file()->name());
-      }
-    }
-  }
-
-  // Include the .pb.h for the current file.
-  cc_printer.Print("\n#include \"$f$\"\n", "f", GetProtoHeader(file));
-
-  // Recursively traverse all imports and turn them into #include(s).
-  std::vector<const FileDescriptor*> imports_to_visit;
-  std::set<const FileDescriptor*> imports_visited;
-  imports_to_visit.push_back(file);
-
-  while (!imports_to_visit.empty()) {
-    const FileDescriptor* cur = imports_to_visit.back();
-    imports_to_visit.pop_back();
-    imports_visited.insert(cur);
-    cc_printer.Print("#include \"$f$.h\"\n", "f", get_file_name(cur));
-    for (int i = 0; i < cur->dependency_count(); i++) {
-      const FileDescriptor* dep = cur->dependency(i);
-      if (imports_visited.count(dep) || lazy_imports.count(dep->name()))
-        continue;
-      imports_to_visit.push_back(dep);
-    }
-  }
-
-  // Compute all nested types to generate forward declarations later.
-
-  std::set<const Descriptor*> all_types_seen;  // All deps
-  std::set<const EnumDescriptor*> all_enums_seen;
-
-  // We track the types additionally in vectors to guarantee a stable order in
-  // the generated output.
-  std::vector<const Descriptor*> local_types;  // Cur .proto file only.
-  std::vector<const Descriptor*> all_types;    // All deps
-  std::vector<const EnumDescriptor*> local_enums;
-  std::vector<const EnumDescriptor*> all_enums;
-
-  auto add_enum = [&local_enums, &all_enums, &all_enums_seen,
-                   &file](const EnumDescriptor* enum_desc) {
-    if (all_enums_seen.count(enum_desc))
-      return;
-    all_enums_seen.insert(enum_desc);
-    all_enums.push_back(enum_desc);
-    if (enum_desc->file() == file)
-      local_enums.push_back(enum_desc);
-  };
-
-  std::stack<const Descriptor*> recursion_stack;
-  for (int i = 0; i < file->message_type_count(); i++)
-    recursion_stack.push(file->message_type(i));
-
-  while (!recursion_stack.empty()) {
-    const Descriptor* msg = recursion_stack.top();
-    recursion_stack.pop();
-    if (all_types_seen.count(msg))
-      continue;
-    all_types_seen.insert(msg);
-    all_types.push_back(msg);
-    if (msg->file() == file)
-      local_types.push_back(msg);
-
-    for (int i = 0; i < msg->nested_type_count(); i++)
-      recursion_stack.push(msg->nested_type(i));
-
-    for (int i = 0; i < msg->enum_type_count(); i++)
-      add_enum(msg->enum_type(i));
-
-    for (int i = 0; i < msg->field_count(); i++) {
-      const FieldDescriptor* field = msg->field(i);
-      if (field->has_default_value()) {
-        *error = "field " + field->name() +
-                 ": Explicitly declared default values are not supported";
-        return false;
-      }
-      if (field->options().lazy() &&
-          (field->is_repeated() || field->type() != TYPE_MESSAGE)) {
-        *error = "[lazy=true] is supported only on non-repeated fields\n";
-        return false;
-      }
-
-      if (field->type() == TYPE_MESSAGE && !field->options().lazy())
-        recursion_stack.push(field->message_type());
-
-      if (field->type() == FieldDescriptor::TYPE_ENUM)
-        add_enum(field->enum_type());
-    }
-  }  //  while (!recursion_stack.empty())
-
-  // Generate forward declarations in the header for proto types.
-  h_printer.Print("// Forward declarations for protobuf types.\n");
-  std::vector<std::string> namespaces = SplitString(file->package(), ".");
-  for (size_t i = 0; i < namespaces.size(); i++)
-    h_printer.Print("namespace $n$ {\n", "n", namespaces[i]);
-
-  for (const Descriptor* msg : all_types)
-    h_printer.Print("class $n$;\n", "n", GetFullName(msg));
-
-  for (size_t i = 0; i < namespaces.size(); i++)
-    h_printer.Print("}\n");
-
-  h_printer.Print("\nnamespace perfetto {\n");
-  cc_printer.Print("\nnamespace perfetto {\n");
-
-  // Generate fwd declarations for C++ types.
-  for (const EnumDescriptor* enm : all_enums) {
-    h_printer.Print("enum $n$ : int;\n", "n", GetFullName(enm));
-  }
-
-  for (const Descriptor* msg : all_types)
-    h_printer.Print("class $n$;\n", "n", GetFullName(msg));
-
-  // Generate declarations and definitions.
-  for (const EnumDescriptor* enm : local_enums)
-    GenEnum(enm, &h_printer);
-
-  for (const Descriptor* msg : local_types) {
-    GenClassDecl(msg, &h_printer);
-    GenClassDef(msg, &cc_printer);
-  }
-
-  cc_printer.Print("}  // namespace perfetto\n");
-  cc_printer.Print("#pragma GCC diagnostic pop\n");
-
-  h_printer.Print("}  // namespace perfetto\n");
-  h_printer.Print("\n#endif  // $g$\n", "g", include_guard);
-
-  return true;
-}
-
-std::string CppObjGenerator::GetCppType(const FieldDescriptor* field,
-                                        bool constref) const {
-  switch (field->type()) {
-    case FieldDescriptor::TYPE_DOUBLE:
-      return "double";
-    case FieldDescriptor::TYPE_FLOAT:
-      return "float";
-    case FieldDescriptor::TYPE_FIXED32:
-    case FieldDescriptor::TYPE_UINT32:
-      return "uint32_t";
-    case FieldDescriptor::TYPE_SFIXED32:
-    case FieldDescriptor::TYPE_INT32:
-    case FieldDescriptor::TYPE_SINT32:
-      return "int32_t";
-    case FieldDescriptor::TYPE_FIXED64:
-    case FieldDescriptor::TYPE_UINT64:
-      return "uint64_t";
-    case FieldDescriptor::TYPE_SFIXED64:
-    case FieldDescriptor::TYPE_SINT64:
-    case FieldDescriptor::TYPE_INT64:
-      return "int64_t";
-    case FieldDescriptor::TYPE_BOOL:
-      return "bool";
-    case FieldDescriptor::TYPE_STRING:
-    case FieldDescriptor::TYPE_BYTES:
-      return constref ? "const std::string&" : "std::string";
-    case FieldDescriptor::TYPE_MESSAGE:
-      assert(!field->options().lazy());
-      return constref ? "const " + GetFullName(field->message_type()) + "&"
-                      : GetFullName(field->message_type());
-    case FieldDescriptor::TYPE_ENUM:
-      return GetFullName(field->enum_type());
-    case FieldDescriptor::TYPE_GROUP:
-      abort();
-  }
-  abort();  // for gcc
-}
-
-void CppObjGenerator::GenEnum(const EnumDescriptor* enum_desc,
-                              Printer* p) const {
-  std::string full_name = GetFullName(enum_desc);
-  p->Print("enum $f$ : int {\n", "f", full_name);
-  for (int e = 0; e < enum_desc->value_count(); e++) {
-    const EnumValueDescriptor* value = enum_desc->value(e);
-    p->Print("  $f$_$n$ = $v$,\n", "f", full_name, "n", value->name(), "v",
-             std::to_string(value->number()));
-  }
-  p->Print("};\n");
-}
-
-void CppObjGenerator::GenEnumAliases(const EnumDescriptor* enum_desc,
-                                     Printer* p) const {
-  std::string full_name = GetFullName(enum_desc);
-  for (int e = 0; e < enum_desc->value_count(); e++) {
-    const EnumValueDescriptor* value = enum_desc->value(e);
-    p->Print("static constexpr auto $n$ = $f$_$n$;\n", "f", full_name, "n",
-             value->name());
-  }
-}
-
-void CppObjGenerator::GenClassDecl(const Descriptor* msg, Printer* p) const {
-  std::string full_name = GetFullName(msg);
-  p->Print("\nclass PERFETTO_EXPORT $n$ {\n", "n", full_name);
-  p->Print(" public:\n");
-  p->Indent();
-
-  // Do a first pass to generate aliases for nested types.
-  // e.g., using Foo = Parent_Foo;
-  for (int i = 0; i < msg->nested_type_count(); i++) {
-    const Descriptor* nested_msg = msg->nested_type(i);
-    p->Print("using $n$ = $f$;\n", "n", nested_msg->name(), "f",
-             GetFullName(nested_msg));
-  }
-  for (int i = 0; i < msg->enum_type_count(); i++) {
-    const EnumDescriptor* nested_enum = msg->enum_type(i);
-    p->Print("using $n$ = $f$;\n", "n", nested_enum->name(), "f",
-             GetFullName(nested_enum));
-    GenEnumAliases(nested_enum, p);
-  }
-
-  p->Print("$n$();\n", "n", full_name);
-  p->Print("~$n$();\n", "n", full_name);
-  p->Print("$n$($n$&&) noexcept;\n", "n", full_name);
-  p->Print("$n$& operator=($n$&&);\n", "n", full_name);
-  p->Print("$n$(const $n$&);\n", "n", full_name);
-  p->Print("$n$& operator=(const $n$&);\n", "n", full_name);
-  p->Print("bool operator==(const $n$&) const;\n", "n", full_name);
-  p->Print(
-      "bool operator!=(const $n$& other) const { return !(*this == other); }\n",
-      "n", full_name);
-  p->Print("\n");
-
-  std::string proto_type = GetFullName(msg, true);
-  p->Print("// Raw proto decoding.\n");
-  p->Print("void ParseRawProto(const std::string&);\n");
-  p->Print("// Conversion methods from/to the corresponding protobuf types.\n");
-  p->Print("void FromProto(const $p$&);\n", "p", proto_type);
-  p->Print("void ToProto($p$*) const;\n", "p", proto_type);
-
-  // Generate accessors.
-  for (int i = 0; i < msg->field_count(); i++) {
-    const FieldDescriptor* field = msg->field(i);
-    p->Print("\n");
-    if (field->options().lazy()) {
-      p->Print("const std::string& $n$_raw() const { return $n$_; }\n", "n",
-               field->lowercase_name());
-      p->Print("void set_$n$_raw(const std::string& raw) { $n$_ = raw; }\n",
-               "n", field->lowercase_name());
-    } else if (!field->is_repeated()) {
-      if (field->type() == TYPE_MESSAGE) {
-        p->Print("$t$ $n$() const { return *$n$_; }\n", "t",
-                 GetCppType(field, true), "n", field->lowercase_name());
-        p->Print("$t$* mutable_$n$() { return $n$_.get(); }\n", "t",
-                 GetCppType(field, false), "n", field->lowercase_name());
-      } else {
-        p->Print("$t$ $n$() const { return $n$_; }\n", "t",
-                 GetCppType(field, true), "n", field->lowercase_name());
-        p->Print("void set_$n$($t$ value) { $n$_ = value; }\n", "t",
-                 GetCppType(field, true), "n", field->lowercase_name());
-        if (field->type() == FieldDescriptor::TYPE_BYTES) {
-          p->Print(
-              "void set_$n$(const void* p, size_t s) { "
-              "$n$_.assign(reinterpret_cast<const char*>(p), s); }\n",
-              "n", field->lowercase_name());
-        }
-      }
-    } else {  // is_repeated()
-      p->Print(
-          "int $n$_size() const { return static_cast<int>($n$_.size()); }\n",
-          "t", GetCppType(field, false), "n", field->lowercase_name());
-      p->Print("const std::vector<$t$>& $n$() const { return $n$_; }\n", "t",
-               GetCppType(field, false), "n", field->lowercase_name());
-      p->Print("std::vector<$t$>* mutable_$n$() { return &$n$_; }\n", "t",
-               GetCppType(field, false), "n", field->lowercase_name());
-      p->Print("void clear_$n$() { $n$_.clear(); }\n", "n",
-               field->lowercase_name());
-      p->Print("$t$* add_$n$() { $n$_.emplace_back(); return &$n$_.back(); }\n",
-               "t", GetCppType(field, false), "n", field->lowercase_name());
-    }
-  }
-  p->Outdent();
-  p->Print("\n private:\n");
-  p->Indent();
-
-  // Generate fields.
-  for (int i = 0; i < msg->field_count(); i++) {
-    const FieldDescriptor* field = msg->field(i);
-    if (field->options().lazy()) {
-      p->Print("std::string $n$_;  // [lazy=true]\n", "n",
-               field->lowercase_name());
-    } else if (!field->is_repeated()) {
-      std::string type = GetCppType(field, false);
-      if (field->type() == TYPE_MESSAGE) {
-        type = "::protozero::CopyablePtr<" + type + ">";
-        p->Print("$t$ $n$_;\n", "t", type, "n", field->lowercase_name());
-      } else {
-        p->Print("$t$ $n$_{};\n", "t", type, "n", field->lowercase_name());
-      }
-    } else {  // is_repeated()
-      p->Print("std::vector<$t$> $n$_;\n", "t", GetCppType(field, false), "n",
-               field->lowercase_name());
-    }
-  }
-  p->Print("\n");
-  p->Print("// Allows to preserve unknown protobuf fields for compatibility\n");
-  p->Print("// with future versions of .proto files.\n");
-  p->Print("std::string unknown_fields_;\n");
-  p->Outdent();
-  p->Print("};\n\n");
-}
-
-void CppObjGenerator::GenClassDef(const Descriptor* msg, Printer* p) const {
-  p->Print("\n");
-  std::string full_name = GetFullName(msg);
-
-  p->Print("$n$::$n$() = default;\n", "n", full_name);
-  p->Print("$n$::~$n$() = default;\n", "n", full_name);
-  p->Print("$n$::$n$(const $n$&) = default;\n", "n", full_name);
-  p->Print("$n$& $n$::operator=(const $n$&) = default;\n", "n", full_name);
-  p->Print("$n$::$n$($n$&&) noexcept = default;\n", "n", full_name);
-  p->Print("$n$& $n$::operator=($n$&&) = default;\n", "n", full_name);
-
-  p->Print("\n");
-
-  // Comparison operator
-  p->Print("bool $n$::operator==(const $n$& other) const {\n", "n", full_name);
-  p->Indent();
-
-  p->Print("return unknown_fields_ == other.unknown_fields_");
-  for (int i = 0; i < msg->field_count(); i++)
-    p->Print("\n && $n$_ == other.$n$_", "n", msg->field(i)->lowercase_name());
-  p->Print(";");
-  p->Outdent();
-  p->Print("\n}\n\n");
-
-  std::string proto_type = GetFullName(msg, true);
-
-  // Genrate the ParseRawProto() method definition.
-  p->Print("void $f$::ParseRawProto(const std::string& raw) {\n", "f",
-           full_name);
-  p->Indent();
-  p->Print("$p$ proto;\n", "p", proto_type);
-  p->Print("proto.ParseFromString(raw);\n");
-  p->Print("FromProto(proto);\n");
-  p->Outdent();
-  p->Print("}\n\n");
-
-  // Genrate the FromProto() method definition.
-  p->Print("void $f$::FromProto(const $p$& proto) {\n", "f", full_name, "p",
-           proto_type);
-  p->Indent();
-  for (int i = 0; i < msg->field_count(); i++) {
-    p->Print("\n");
-    const FieldDescriptor* field = msg->field(i);
-    if (field->options().lazy()) {
-      p->Print("$n$_ = proto.$n$().SerializeAsString();\n", "n",
-               field->lowercase_name());
-    } else if (!field->is_repeated()) {
-      if (field->type() == TYPE_MESSAGE) {
-        p->Print("$n$_->FromProto(proto.$n$());\n", "n",
-                 field->lowercase_name());
-      } else {
-        p->Print(
-            "static_assert(sizeof($n$_) == sizeof(proto.$n$()), \"size "
-            "mismatch\");\n",
-            "n", field->lowercase_name());
-        p->Print("$n$_ = static_cast<decltype($n$_)>(proto.$n$());\n", "n",
-                 field->lowercase_name());
-      }
-    } else {  // is_repeated()
-      p->Print("$n$_.clear();\n", "n", field->lowercase_name());
-      p->Print("for (const auto& field : proto.$n$()) {\n", "n",
-               field->lowercase_name());
-      p->Print("  $n$_.emplace_back();\n", "n", field->lowercase_name());
-      if (field->type() == TYPE_MESSAGE) {
-        p->Print("  $n$_.back().FromProto(field);\n", "n",
-                 field->lowercase_name());
-      } else {
-        p->Print(
-            "static_assert(sizeof($n$_.back()) == sizeof(proto.$n$(0)), \"size "
-            "mismatch\");\n",
-            "n", field->lowercase_name());
-        p->Print(
-            "  $n$_.back() = static_cast<decltype($n$_)::value_type>(field);\n",
-            "n", field->lowercase_name());
-      }
-      p->Print("}\n");
-    }
-  }
-  p->Print("unknown_fields_ = proto.unknown_fields();\n");
-  p->Outdent();
-  p->Print("}\n\n");
-
-  // Genrate the ToProto() method definition.
-  p->Print("void $f$::ToProto($p$* proto) const {\n", "f", full_name, "p",
-           proto_type);
-  p->Indent();
-  p->Print("proto->Clear();\n");
-  for (int i = 0; i < msg->field_count(); i++) {
-    p->Print("\n");
-    const FieldDescriptor* field = msg->field(i);
-    if (field->options().lazy()) {
-      p->Print("proto->mutable_$n$()->ParseFromString($n$_);\n", "n",
-               field->lowercase_name());
-    } else if (!field->is_repeated()) {
-      if (field->type() == TYPE_MESSAGE) {
-        p->Print("$n$_->ToProto(proto->mutable_$n$());\n", "n",
-                 field->lowercase_name());
-      } else {
-        p->Print(
-            "static_assert(sizeof($n$_) == sizeof(proto->$n$()), \"size "
-            "mismatch\");\n",
-            "n", field->lowercase_name());
-        p->Print("proto->set_$n$(static_cast<decltype(proto->$n$())>($n$_));\n",
-                 "n", field->lowercase_name());
-      }
-    } else {  // is_repeated()
-      p->Print("for (const auto& it : $n$_) {\n", "n", field->lowercase_name());
-      if (field->type() == TYPE_MESSAGE) {
-        p->Print("  auto* entry = proto->add_$n$();\n", "n",
-                 field->lowercase_name());
-        p->Print("  it.ToProto(entry);\n");
-      } else {
-        p->Print(
-            "  proto->add_$n$(static_cast<decltype(proto->$n$(0))>(it));\n",
-            "n", field->lowercase_name());
-        p->Print(
-            "static_assert(sizeof(it) == sizeof(proto->$n$(0)), \"size "
-            "mismatch\");\n",
-            "n", field->lowercase_name());
-      }
-      p->Print("}\n");
-    }
-  }
-  p->Print("*(proto->mutable_unknown_fields()) = unknown_fields_;\n");
-  p->Outdent();
-  p->Print("}\n\n");
-}
-
-}  // namespace
-}  // namespace protozero
-
-int main(int argc, char** argv) {
-  ::protozero::CppObjGenerator generator;
-  return google::protobuf::compiler::PluginMain(argc, argv, &generator);
-}
diff --git a/src/protozero/protoc_plugin/protozero_generator.cc b/src/protozero/protoc_plugin/protozero_generator.cc
new file mode 100644
index 0000000..0ef0aff
--- /dev/null
+++ b/src/protozero/protoc_plugin/protozero_generator.cc
@@ -0,0 +1,713 @@
+/*
+ * Copyright (C) 2017 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 "src/protozero/protoc_plugin/protozero_generator.h"
+
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/stubs/strutil.h"
+
+namespace protozero {
+
+using google::protobuf::Descriptor;  // Message descriptor.
+using google::protobuf::EnumDescriptor;
+using google::protobuf::EnumValueDescriptor;
+using google::protobuf::FieldDescriptor;
+using google::protobuf::FileDescriptor;
+using google::protobuf::compiler::GeneratorContext;
+using google::protobuf::io::Printer;
+using google::protobuf::io::ZeroCopyOutputStream;
+
+using google::protobuf::Split;
+using google::protobuf::StripPrefixString;
+using google::protobuf::StripString;
+using google::protobuf::StripSuffixString;
+using google::protobuf::UpperString;
+
+namespace {
+
+// Keep this value in sync with ProtoDecoder::kMaxDecoderFieldId. If they go out
+// of sync pbzero.h files will stop compiling, hitting the at() static_assert.
+// Not worth an extra dependency.
+constexpr int kMaxDecoderFieldId = 999;
+
+void Assert(bool condition) {
+  if (!condition)
+    __builtin_trap();
+}
+
+struct FileDescriptorComp {
+  bool operator()(const FileDescriptor* lhs, const FileDescriptor* rhs) const {
+    int comp = lhs->name().compare(rhs->name());
+    Assert(comp != 0 || lhs == rhs);
+    return comp < 0;
+  }
+};
+
+struct DescriptorComp {
+  bool operator()(const Descriptor* lhs, const Descriptor* rhs) const {
+    int comp = lhs->full_name().compare(rhs->full_name());
+    Assert(comp != 0 || lhs == rhs);
+    return comp < 0;
+  }
+};
+
+struct EnumDescriptorComp {
+  bool operator()(const EnumDescriptor* lhs, const EnumDescriptor* rhs) const {
+    int comp = lhs->full_name().compare(rhs->full_name());
+    Assert(comp != 0 || lhs == rhs);
+    return comp < 0;
+  }
+};
+
+inline std::string ProtoStubName(const FileDescriptor* proto) {
+  return StripSuffixString(proto->name(), ".proto") + ".pbzero";
+}
+
+class GeneratorJob {
+ public:
+  GeneratorJob(const FileDescriptor* file, Printer* stub_h_printer)
+      : source_(file), stub_h_(stub_h_printer) {}
+
+  bool GenerateStubs() {
+    Preprocess();
+    GeneratePrologue();
+    for (const EnumDescriptor* enumeration : enums_)
+      GenerateEnumDescriptor(enumeration);
+    for (const Descriptor* message : messages_)
+      GenerateMessageDescriptor(message);
+    GenerateEpilogue();
+    return error_.empty();
+  }
+
+  void SetOption(const std::string& name, const std::string& value) {
+    if (name == "wrapper_namespace") {
+      wrapper_namespace_ = value;
+    } else {
+      Abort(std::string() + "Unknown plugin option '" + name + "'.");
+    }
+  }
+
+  // If generator fails to produce stubs for a particular proto definitions
+  // it finishes with undefined output and writes the first error occured.
+  const std::string& GetFirstError() const { return error_; }
+
+ private:
+  // Only the first error will be recorded.
+  void Abort(const std::string& reason) {
+    if (error_.empty())
+      error_ = reason;
+  }
+
+  // Get full name (including outer descriptors) of proto descriptor.
+  template <class T>
+  inline std::string GetDescriptorName(const T* descriptor) {
+    if (!package_.empty()) {
+      return StripPrefixString(descriptor->full_name(), package_ + ".");
+    } else {
+      return descriptor->full_name();
+    }
+  }
+
+  // Get C++ class name corresponding to proto descriptor.
+  // Nested names are splitted by underscores. Underscores in type names aren't
+  // prohibited but not recommended in order to avoid name collisions.
+  template <class T>
+  inline std::string GetCppClassName(const T* descriptor, bool full = false) {
+    std::string name = GetDescriptorName(descriptor);
+    StripString(&name, ".", '_');
+    if (full)
+      name = full_namespace_prefix_ + name;
+    return name;
+  }
+
+  inline std::string GetFieldNumberConstant(const FieldDescriptor* field) {
+    std::string name = field->camelcase_name();
+    if (!name.empty()) {
+      name.at(0) = static_cast<char>(toupper(name.at(0)));
+      name = "k" + name + "FieldNumber";
+    } else {
+      // Protoc allows fields like 'bool _ = 1'.
+      Abort("Empty field name in camel case notation.");
+    }
+    return name;
+  }
+
+  // Small enums can be written faster without involving VarInt encoder.
+  inline bool IsTinyEnumField(const FieldDescriptor* field) {
+    if (field->type() != FieldDescriptor::TYPE_ENUM)
+      return false;
+    const EnumDescriptor* enumeration = field->enum_type();
+
+    for (int i = 0; i < enumeration->value_count(); ++i) {
+      int32_t value = enumeration->value(i)->number();
+      if (value < 0 || value > 0x7F)
+        return false;
+    }
+    return true;
+  }
+
+  void CollectDescriptors() {
+    // Collect message descriptors in DFS order.
+    std::vector<const Descriptor*> stack;
+    for (int i = 0; i < source_->message_type_count(); ++i)
+      stack.push_back(source_->message_type(i));
+
+    while (!stack.empty()) {
+      const Descriptor* message = stack.back();
+      stack.pop_back();
+      messages_.push_back(message);
+      for (int i = 0; i < message->nested_type_count(); ++i) {
+        stack.push_back(message->nested_type(i));
+      }
+    }
+
+    // Collect enums.
+    for (int i = 0; i < source_->enum_type_count(); ++i)
+      enums_.push_back(source_->enum_type(i));
+
+    for (const Descriptor* message : messages_) {
+      for (int i = 0; i < message->enum_type_count(); ++i) {
+        enums_.push_back(message->enum_type(i));
+      }
+    }
+  }
+
+  void CollectDependencies() {
+    // Public import basically means that callers only need to import this
+    // proto in order to use the stuff publicly imported by this proto.
+    for (int i = 0; i < source_->public_dependency_count(); ++i)
+      public_imports_.insert(source_->public_dependency(i));
+
+    if (source_->weak_dependency_count() > 0)
+      Abort("Weak imports are not supported.");
+
+    // Sanity check. Collect public imports (of collected imports) in DFS order.
+    // Visibilty for current proto:
+    // - all imports listed in current proto,
+    // - public imports of everything imported (recursive).
+    std::vector<const FileDescriptor*> stack;
+    for (int i = 0; i < source_->dependency_count(); ++i) {
+      const FileDescriptor* import = source_->dependency(i);
+      stack.push_back(import);
+      if (public_imports_.count(import) == 0) {
+        private_imports_.insert(import);
+      }
+    }
+
+    while (!stack.empty()) {
+      const FileDescriptor* import = stack.back();
+      stack.pop_back();
+      // Having imports under different packages leads to unnecessary
+      // complexity with namespaces.
+      if (import->package() != package_)
+        Abort("Imported proto must be in the same package.");
+
+      for (int i = 0; i < import->public_dependency_count(); ++i) {
+        stack.push_back(import->public_dependency(i));
+      }
+    }
+
+    // Collect descriptors of messages and enums used in current proto.
+    // It will be used to generate necessary forward declarations and performed
+    // sanity check guarantees that everything lays in the same namespace.
+    for (const Descriptor* message : messages_) {
+      for (int i = 0; i < message->field_count(); ++i) {
+        const FieldDescriptor* field = message->field(i);
+
+        if (field->type() == FieldDescriptor::TYPE_MESSAGE) {
+          if (public_imports_.count(field->message_type()->file()) == 0) {
+            // Avoid multiple forward declarations since
+            // public imports have been already included.
+            referenced_messages_.insert(field->message_type());
+          }
+        } else if (field->type() == FieldDescriptor::TYPE_ENUM) {
+          if (public_imports_.count(field->enum_type()->file()) == 0) {
+            referenced_enums_.insert(field->enum_type());
+          }
+        }
+      }
+    }
+  }
+
+  void Preprocess() {
+    // Package name maps to a series of namespaces.
+    package_ = source_->package();
+    namespaces_ = Split(package_, ".");
+    if (!wrapper_namespace_.empty())
+      namespaces_.push_back(wrapper_namespace_);
+
+    full_namespace_prefix_ = "::";
+    for (const std::string& ns : namespaces_)
+      full_namespace_prefix_ += ns + "::";
+
+    CollectDescriptors();
+    CollectDependencies();
+  }
+
+  // Print top header, namespaces and forward declarations.
+  void GeneratePrologue() {
+    std::string greeting =
+        "// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.\n";
+    std::string guard = package_ + "_" + source_->name() + "_H_";
+    UpperString(&guard);
+    StripString(&guard, ".-/\\", '_');
+
+    stub_h_->Print(
+        "$greeting$\n"
+        "#ifndef $guard$\n"
+        "#define $guard$\n\n"
+        "#include <stddef.h>\n"
+        "#include <stdint.h>\n\n"
+        "#include \"perfetto/base/export.h\"\n"
+        "#include \"perfetto/protozero/proto_decoder.h\"\n"
+        "#include \"perfetto/protozero/message.h\"\n",
+        "greeting", greeting, "guard", guard);
+
+    // Print includes for public imports.
+    for (const FileDescriptor* dependency : public_imports_) {
+      // Dependency name could contain slashes but importing from upper-level
+      // directories is not possible anyway since build system processes each
+      // proto file individually. Hence proto lookup path is always equal to the
+      // directory where particular proto file is located and protoc does not
+      // allow reference to upper directory (aka ..) in import path.
+      //
+      // Laconically said:
+      // - source_->name() may never have slashes,
+      // - dependency->name() may have slashes but always refers to inner path.
+      stub_h_->Print("#include \"$name$.h\"\n", "name",
+                     ProtoStubName(dependency));
+    }
+    stub_h_->Print("\n");
+
+    // Print namespaces.
+    for (const std::string& ns : namespaces_) {
+      stub_h_->Print("namespace $ns$ {\n", "ns", ns);
+    }
+    stub_h_->Print("\n");
+
+    // Print forward declarations.
+    for (const Descriptor* message : referenced_messages_) {
+      stub_h_->Print("class $class$;\n", "class", GetCppClassName(message));
+    }
+    for (const EnumDescriptor* enumeration : referenced_enums_) {
+      stub_h_->Print("enum $class$ : int32_t;\n", "class",
+                     GetCppClassName(enumeration));
+    }
+    stub_h_->Print("\n");
+  }
+
+  void GenerateEnumDescriptor(const EnumDescriptor* enumeration) {
+    stub_h_->Print("enum $class$ : int32_t {\n", "class",
+                   GetCppClassName(enumeration));
+    stub_h_->Indent();
+
+    std::string value_name_prefix;
+    if (enumeration->containing_type() != nullptr)
+      value_name_prefix = GetCppClassName(enumeration) + "_";
+
+    for (int i = 0; i < enumeration->value_count(); ++i) {
+      const EnumValueDescriptor* value = enumeration->value(i);
+      stub_h_->Print("$name$ = $number$,\n", "name",
+                     value_name_prefix + value->name(), "number",
+                     std::to_string(value->number()));
+    }
+
+    stub_h_->Outdent();
+    stub_h_->Print("};\n\n");
+  }
+
+  void GenerateSimpleFieldDescriptor(const FieldDescriptor* field) {
+    std::map<std::string, std::string> setter;
+    setter["id"] = std::to_string(field->number());
+    setter["name"] = field->name();
+    setter["action"] = field->is_repeated() ? "add" : "set";
+
+    std::string appender;
+    std::string cpp_type;
+
+    switch (field->type()) {
+      case FieldDescriptor::TYPE_BOOL: {
+        appender = "AppendTinyVarInt";
+        cpp_type = "bool";
+        break;
+      }
+      case FieldDescriptor::TYPE_INT32: {
+        appender = "AppendVarInt";
+        cpp_type = "int32_t";
+        break;
+      }
+      case FieldDescriptor::TYPE_INT64: {
+        appender = "AppendVarInt";
+        cpp_type = "int64_t";
+        break;
+      }
+      case FieldDescriptor::TYPE_UINT32: {
+        appender = "AppendVarInt";
+        cpp_type = "uint32_t";
+        break;
+      }
+      case FieldDescriptor::TYPE_UINT64: {
+        appender = "AppendVarInt";
+        cpp_type = "uint64_t";
+        break;
+      }
+      case FieldDescriptor::TYPE_SINT32: {
+        appender = "AppendSignedVarInt";
+        cpp_type = "int32_t";
+        break;
+      }
+      case FieldDescriptor::TYPE_SINT64: {
+        appender = "AppendSignedVarInt";
+        cpp_type = "int64_t";
+        break;
+      }
+      case FieldDescriptor::TYPE_FIXED32: {
+        appender = "AppendFixed";
+        cpp_type = "uint32_t";
+        break;
+      }
+      case FieldDescriptor::TYPE_FIXED64: {
+        appender = "AppendFixed";
+        cpp_type = "uint64_t";
+        break;
+      }
+      case FieldDescriptor::TYPE_SFIXED32: {
+        appender = "AppendFixed";
+        cpp_type = "int32_t";
+        break;
+      }
+      case FieldDescriptor::TYPE_SFIXED64: {
+        appender = "AppendFixed";
+        cpp_type = "int64_t";
+        break;
+      }
+      case FieldDescriptor::TYPE_FLOAT: {
+        appender = "AppendFixed";
+        cpp_type = "float";
+        break;
+      }
+      case FieldDescriptor::TYPE_DOUBLE: {
+        appender = "AppendFixed";
+        cpp_type = "double";
+        break;
+      }
+      case FieldDescriptor::TYPE_ENUM: {
+        appender = IsTinyEnumField(field) ? "AppendTinyVarInt" : "AppendVarInt";
+        cpp_type = GetCppClassName(field->enum_type(), true);
+        break;
+      }
+      case FieldDescriptor::TYPE_STRING: {
+        appender = "AppendString";
+        cpp_type = "const char*";
+        break;
+      }
+      case FieldDescriptor::TYPE_BYTES: {
+        stub_h_->Print(
+            setter,
+            "void $action$_$name$(const uint8_t* data, size_t size) {\n"
+            "  AppendBytes($id$, data, size);\n"
+            "}\n");
+        return;
+      }
+      case FieldDescriptor::TYPE_GROUP:
+      case FieldDescriptor::TYPE_MESSAGE: {
+        Abort("Unsupported field type.");
+        return;
+      }
+    }
+    setter["appender"] = appender;
+    setter["cpp_type"] = cpp_type;
+    stub_h_->Print(setter,
+                   "void $action$_$name$($cpp_type$ value) {\n"
+                   "  $appender$($id$, value);\n"
+                   "}\n");
+
+    // For strings also generate a variant for non-null terminated strings.
+    if (field->type() == FieldDescriptor::TYPE_STRING) {
+      stub_h_->Print(setter,
+                     "// Doesn't check for null terminator.\n"
+                     "// Expects |value| to be at least |size| long.\n"
+                     "void $action$_$name$($cpp_type$ value, size_t size) {\n"
+                     "  AppendBytes($id$, value, size);\n"
+                     "}\n");
+    }
+  }
+
+  void GenerateNestedMessageFieldDescriptor(const FieldDescriptor* field) {
+    std::string action = field->is_repeated() ? "add" : "set";
+    std::string inner_class = GetCppClassName(field->message_type());
+    stub_h_->Print(
+        "template <typename T = $inner_class$> T* $action$_$name$() {\n"
+        "  return BeginNestedMessage<T>($id$);\n"
+        "}\n\n",
+        "id", std::to_string(field->number()), "name", field->name(), "action",
+        action, "inner_class", inner_class);
+  }
+
+  void GenerateDecoder(const Descriptor* message) {
+    int max_field_id = 0;
+    bool has_repeated_fields = false;
+    for (int i = 0; i < message->field_count(); ++i) {
+      const FieldDescriptor* field = message->field(i);
+      if (field->number() > kMaxDecoderFieldId)
+        continue;
+      max_field_id = std::max(max_field_id, field->number());
+      if (field->is_repeated())
+        has_repeated_fields = true;
+    }
+
+    stub_h_->Print(
+        "class Decoder : public "
+        "::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/$max$, "
+        "/*HAS_REPEATED_FIELDS=*/$rep$> {\n",
+        "max", std::to_string(max_field_id), "rep",
+        has_repeated_fields ? "true" : "false");
+    stub_h_->Print(" public:\n");
+    stub_h_->Indent();
+    stub_h_->Print(
+        "Decoder(const uint8_t* data, size_t len) "
+        ": TypedProtoDecoder(data, len) {}\n");
+
+    for (int i = 0; i < message->field_count(); ++i) {
+      const FieldDescriptor* field = message->field(i);
+      if (field->is_packed()) {
+        Abort("Packed repeated fields are not supported.");
+        return;
+      }
+
+      if (field->number() > max_field_id) {
+        stub_h_->Print("// field $name$ omitted because its id is too high\n",
+                       "name", field->name());
+        continue;
+      }
+      std::string getter;
+      std::string cpp_type;
+      switch (field->type()) {
+        case FieldDescriptor::TYPE_BOOL:
+          getter = "as_bool";
+          cpp_type = "bool";
+          break;
+        case FieldDescriptor::TYPE_SFIXED32:
+        case FieldDescriptor::TYPE_SINT32:
+        case FieldDescriptor::TYPE_INT32:
+          getter = "as_int32";
+          cpp_type = "int32_t";
+          break;
+        case FieldDescriptor::TYPE_SFIXED64:
+        case FieldDescriptor::TYPE_SINT64:
+        case FieldDescriptor::TYPE_INT64:
+          getter = "as_int64";
+          cpp_type = "int64_t";
+          break;
+        case FieldDescriptor::TYPE_FIXED32:
+        case FieldDescriptor::TYPE_UINT32:
+          getter = "as_uint32";
+          cpp_type = "uint32_t";
+          break;
+        case FieldDescriptor::TYPE_FIXED64:
+        case FieldDescriptor::TYPE_UINT64:
+          getter = "as_uint64";
+          cpp_type = "uint64_t";
+          break;
+        case FieldDescriptor::TYPE_FLOAT:
+          getter = "as_float";
+          cpp_type = "float";
+          break;
+        case FieldDescriptor::TYPE_DOUBLE:
+          getter = "as_double";
+          cpp_type = "double";
+          break;
+        case FieldDescriptor::TYPE_ENUM:
+          getter = "as_int32";
+          cpp_type = "int32_t";
+          break;
+        case FieldDescriptor::TYPE_STRING:
+          getter = "as_string";
+          cpp_type = "::protozero::ConstChars";
+          break;
+        case FieldDescriptor::TYPE_MESSAGE:
+        case FieldDescriptor::TYPE_BYTES:
+          getter = "as_bytes";
+          cpp_type = "::protozero::ConstBytes";
+          break;
+        case FieldDescriptor::TYPE_GROUP:
+          continue;
+      }
+
+      stub_h_->Print("bool has_$name$() const { return at<$id$>().valid(); }\n",
+                     "name", field->name(), "id",
+                     std::to_string(field->number()));
+
+      if (field->is_repeated()) {
+        stub_h_->Print(
+            "::protozero::RepeatedFieldIterator $name$() const { return "
+            "GetRepeated($id$); }\n",
+            "name", field->name(), "id", std::to_string(field->number()));
+      } else {
+        stub_h_->Print(
+            "$cpp_type$ $name$() const { return at<$id$>().$getter$(); }\n",
+            "name", field->name(), "id", std::to_string(field->number()),
+            "cpp_type", cpp_type, "getter", getter);
+      }
+    }
+    stub_h_->Outdent();
+    stub_h_->Print("};\n");
+  }
+
+  void GenerateConstantsForMessageFields(const Descriptor* message) {
+    const bool has_fields = (message->field_count() > 0);
+
+    // Field number constants.
+    if (has_fields) {
+      stub_h_->Print("enum : int32_t {\n");
+      stub_h_->Indent();
+
+      for (int i = 0; i < message->field_count(); ++i) {
+        const FieldDescriptor* field = message->field(i);
+        stub_h_->Print("$name$ = $id$,\n", "name",
+                       GetFieldNumberConstant(field), "id",
+                       std::to_string(field->number()));
+      }
+      stub_h_->Outdent();
+      stub_h_->Print("};\n");
+    }
+  }
+
+  void GenerateMessageDescriptor(const Descriptor* message) {
+    stub_h_->Print(
+        "class PERFETTO_EXPORT $name$ : public ::protozero::Message {\n"
+        " public:\n",
+        "name", GetCppClassName(message));
+    stub_h_->Indent();
+
+    GenerateConstantsForMessageFields(message);
+    GenerateDecoder(message);
+
+    // Using statements for nested messages.
+    for (int i = 0; i < message->nested_type_count(); ++i) {
+      const Descriptor* nested_message = message->nested_type(i);
+      stub_h_->Print("using $local_name$ = $global_name$;\n", "local_name",
+                     nested_message->name(), "global_name",
+                     GetCppClassName(nested_message, true));
+    }
+
+    // Using statements for nested enums.
+    for (int i = 0; i < message->enum_type_count(); ++i) {
+      const EnumDescriptor* nested_enum = message->enum_type(i);
+      stub_h_->Print("using $local_name$ = $global_name$;\n", "local_name",
+                     nested_enum->name(), "global_name",
+                     GetCppClassName(nested_enum, true));
+    }
+
+    // Values of nested enums.
+    for (int i = 0; i < message->enum_type_count(); ++i) {
+      const EnumDescriptor* nested_enum = message->enum_type(i);
+      std::string value_name_prefix = GetCppClassName(nested_enum) + "_";
+
+      for (int j = 0; j < nested_enum->value_count(); ++j) {
+        const EnumValueDescriptor* value = nested_enum->value(j);
+        stub_h_->Print("static const $class$ $name$ = $full_name$;\n", "class",
+                       nested_enum->name(), "name", value->name(), "full_name",
+                       value_name_prefix + value->name());
+      }
+    }
+
+    // Field descriptors.
+    for (int i = 0; i < message->field_count(); ++i) {
+      const FieldDescriptor* field = message->field(i);
+      if (field->is_packed()) {
+        Abort("Packed repeated fields are not supported.");
+        return;
+      }
+      if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
+        GenerateSimpleFieldDescriptor(field);
+      } else {
+        GenerateNestedMessageFieldDescriptor(field);
+      }
+    }
+
+    stub_h_->Outdent();
+    stub_h_->Print("};\n\n");
+  }
+
+  void GenerateEpilogue() {
+    for (unsigned i = 0; i < namespaces_.size(); ++i) {
+      stub_h_->Print("} // Namespace.\n");
+    }
+    stub_h_->Print("#endif  // Include guard.\n");
+  }
+
+  const FileDescriptor* const source_;
+  Printer* const stub_h_;
+  std::string error_;
+
+  std::string package_;
+  std::string wrapper_namespace_;
+  std::vector<std::string> namespaces_;
+  std::string full_namespace_prefix_;
+  std::vector<const Descriptor*> messages_;
+  std::vector<const EnumDescriptor*> enums_;
+
+  // The custom *Comp comparators are to ensure determinism of the generator.
+  std::set<const FileDescriptor*, FileDescriptorComp> public_imports_;
+  std::set<const FileDescriptor*, FileDescriptorComp> private_imports_;
+  std::set<const Descriptor*, DescriptorComp> referenced_messages_;
+  std::set<const EnumDescriptor*, EnumDescriptorComp> referenced_enums_;
+};
+
+}  // namespace
+
+ProtoZeroGenerator::ProtoZeroGenerator() {}
+
+ProtoZeroGenerator::~ProtoZeroGenerator() {}
+
+bool ProtoZeroGenerator::Generate(const FileDescriptor* file,
+                                  const std::string& options,
+                                  GeneratorContext* context,
+                                  std::string* error) const {
+  const std::unique_ptr<ZeroCopyOutputStream> stub_h_file_stream(
+      context->Open(ProtoStubName(file) + ".h"));
+  const std::unique_ptr<ZeroCopyOutputStream> stub_cc_file_stream(
+      context->Open(ProtoStubName(file) + ".cc"));
+
+  // Variables are delimited by $.
+  Printer stub_h_printer(stub_h_file_stream.get(), '$');
+  GeneratorJob job(file, &stub_h_printer);
+
+  Printer stub_cc_printer(stub_cc_file_stream.get(), '$');
+  stub_cc_printer.Print("// Intentionally empty\n");
+
+  // Parse additional options.
+  for (const std::string& option : Split(options, ",")) {
+    std::vector<std::string> option_pair = Split(option, "=");
+    job.SetOption(option_pair[0], option_pair[1]);
+  }
+
+  if (!job.GenerateStubs()) {
+    *error = job.GetFirstError();
+    return false;
+  }
+  return true;
+}
+
+}  // namespace protozero
diff --git a/src/protozero/protoc_plugin/protozero_generator.h b/src/protozero/protoc_plugin/protozero_generator.h
new file mode 100644
index 0000000..a9f7a70
--- /dev/null
+++ b/src/protozero/protoc_plugin/protozero_generator.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 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 SRC_PROTOZERO_PROTOC_PLUGIN_PROTOZERO_GENERATOR_H_
+#define SRC_PROTOZERO_PROTOC_PLUGIN_PROTOZERO_GENERATOR_H_
+
+#include <string>
+
+#include "google/protobuf/compiler/code_generator.h"
+
+namespace protozero {
+
+class ProtoZeroGenerator : public ::google::protobuf::compiler::CodeGenerator {
+ public:
+  explicit ProtoZeroGenerator();
+  ~ProtoZeroGenerator() override;
+
+  // CodeGenerator implementation
+  bool Generate(const google::protobuf::FileDescriptor* file,
+                const std::string& options,
+                google::protobuf::compiler::GeneratorContext* context,
+                std::string* error) const override;
+};
+
+}  // namespace protozero
+
+#endif  // SRC_PROTOZERO_PROTOC_PLUGIN_PROTOZERO_GENERATOR_H_
diff --git a/src/protozero/protoc_plugin/protozero_plugin.cc b/src/protozero/protoc_plugin/protozero_plugin.cc
index 72d380c..7d9d6a3 100644
--- a/src/protozero/protoc_plugin/protozero_plugin.cc
+++ b/src/protozero/protoc_plugin/protozero_plugin.cc
@@ -14,837 +14,8 @@
  * limitations under the License.
  */
 
-#include <limits>
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/plugin.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-
-#include "perfetto/ext/base/string_utils.h"
-
-namespace protozero {
-namespace {
-
-using google::protobuf::Descriptor;
-using google::protobuf::EnumDescriptor;
-using google::protobuf::EnumValueDescriptor;
-using google::protobuf::FieldDescriptor;
-using google::protobuf::FileDescriptor;
-using google::protobuf::compiler::GeneratorContext;
-using google::protobuf::io::Printer;
-using google::protobuf::io::ZeroCopyOutputStream;
-using perfetto::base::SplitString;
-using perfetto::base::StripChars;
-using perfetto::base::StripPrefix;
-using perfetto::base::StripSuffix;
-using perfetto::base::ToUpper;
-using perfetto::base::Uppercase;
-
-// Keep this value in sync with ProtoDecoder::kMaxDecoderFieldId. If they go out
-// of sync pbzero.h files will stop compiling, hitting the at() static_assert.
-// Not worth an extra dependency.
-constexpr int kMaxDecoderFieldId = 999;
-
-void Assert(bool condition) {
-  if (!condition)
-    __builtin_trap();
-}
-
-struct FileDescriptorComp {
-  bool operator()(const FileDescriptor* lhs, const FileDescriptor* rhs) const {
-    int comp = lhs->name().compare(rhs->name());
-    Assert(comp != 0 || lhs == rhs);
-    return comp < 0;
-  }
-};
-
-struct DescriptorComp {
-  bool operator()(const Descriptor* lhs, const Descriptor* rhs) const {
-    int comp = lhs->full_name().compare(rhs->full_name());
-    Assert(comp != 0 || lhs == rhs);
-    return comp < 0;
-  }
-};
-
-struct EnumDescriptorComp {
-  bool operator()(const EnumDescriptor* lhs, const EnumDescriptor* rhs) const {
-    int comp = lhs->full_name().compare(rhs->full_name());
-    Assert(comp != 0 || lhs == rhs);
-    return comp < 0;
-  }
-};
-
-inline std::string ProtoStubName(const FileDescriptor* proto) {
-  return StripSuffix(proto->name(), ".proto") + ".pbzero";
-}
-
-class GeneratorJob {
- public:
-  GeneratorJob(const FileDescriptor* file, Printer* stub_h_printer)
-      : source_(file), stub_h_(stub_h_printer) {}
-
-  bool GenerateStubs() {
-    Preprocess();
-    GeneratePrologue();
-    for (const EnumDescriptor* enumeration : enums_)
-      GenerateEnumDescriptor(enumeration);
-    for (const Descriptor* message : messages_)
-      GenerateMessageDescriptor(message);
-    GenerateEpilogue();
-    return error_.empty();
-  }
-
-  void SetOption(const std::string& name, const std::string& value) {
-    if (name == "wrapper_namespace") {
-      wrapper_namespace_ = value;
-    } else {
-      Abort(std::string() + "Unknown plugin option '" + name + "'.");
-    }
-  }
-
-  // If generator fails to produce stubs for a particular proto definitions
-  // it finishes with undefined output and writes the first error occured.
-  const std::string& GetFirstError() const { return error_; }
-
- private:
-  // Only the first error will be recorded.
-  void Abort(const std::string& reason) {
-    if (error_.empty())
-      error_ = reason;
-  }
-
-  // Get full name (including outer descriptors) of proto descriptor.
-  template <class T>
-  inline std::string GetDescriptorName(const T* descriptor) {
-    if (!package_.empty()) {
-      return StripPrefix(descriptor->full_name(), package_ + ".");
-    } else {
-      return descriptor->full_name();
-    }
-  }
-
-  // Get C++ class name corresponding to proto descriptor.
-  // Nested names are splitted by underscores. Underscores in type names aren't
-  // prohibited but not recommended in order to avoid name collisions.
-  template <class T>
-  inline std::string GetCppClassName(const T* descriptor, bool full = false) {
-    std::string name = StripChars(GetDescriptorName(descriptor), ".", '_');
-    if (full)
-      name = full_namespace_prefix_ + name;
-    return name;
-  }
-
-  inline std::string GetFieldNumberConstant(const FieldDescriptor* field) {
-    std::string name = field->camelcase_name();
-    if (!name.empty()) {
-      name.at(0) = Uppercase(name.at(0));
-      name = "k" + name + "FieldNumber";
-    } else {
-      // Protoc allows fields like 'bool _ = 1'.
-      Abort("Empty field name in camel case notation.");
-    }
-    return name;
-  }
-
-  // Small enums can be written faster without involving VarInt encoder.
-  inline bool IsTinyEnumField(const FieldDescriptor* field) {
-    if (field->type() != FieldDescriptor::TYPE_ENUM)
-      return false;
-    const EnumDescriptor* enumeration = field->enum_type();
-
-    for (int i = 0; i < enumeration->value_count(); ++i) {
-      int32_t value = enumeration->value(i)->number();
-      if (value < 0 || value > 0x7F)
-        return false;
-    }
-    return true;
-  }
-
-  // Note: intentionally avoiding depending on protozero sources, as well as
-  // protobuf-internal WireFormat/WireFormatLite classes.
-  const char* FieldTypeToProtozeroWireType(FieldDescriptor::Type proto_type) {
-    switch (proto_type) {
-      case FieldDescriptor::TYPE_INT64:
-      case FieldDescriptor::TYPE_UINT64:
-      case FieldDescriptor::TYPE_INT32:
-      case FieldDescriptor::TYPE_BOOL:
-      case FieldDescriptor::TYPE_UINT32:
-      case FieldDescriptor::TYPE_ENUM:
-      case FieldDescriptor::TYPE_SINT32:
-      case FieldDescriptor::TYPE_SINT64:
-        return "::protozero::proto_utils::ProtoWireType::kVarInt";
-
-      case FieldDescriptor::TYPE_FIXED32:
-      case FieldDescriptor::TYPE_SFIXED32:
-      case FieldDescriptor::TYPE_FLOAT:
-        return "::protozero::proto_utils::ProtoWireType::kFixed32";
-
-      case FieldDescriptor::TYPE_FIXED64:
-      case FieldDescriptor::TYPE_SFIXED64:
-      case FieldDescriptor::TYPE_DOUBLE:
-        return "::protozero::proto_utils::ProtoWireType::kFixed64";
-
-      case FieldDescriptor::TYPE_STRING:
-      case FieldDescriptor::TYPE_MESSAGE:
-      case FieldDescriptor::TYPE_BYTES:
-        return "::protozero::proto_utils::ProtoWireType::kLengthDelimited";
-
-      case FieldDescriptor::TYPE_GROUP:
-        Abort("Groups not supported.");
-    }
-    Abort("Unrecognized FieldDescriptor::Type.");
-    return "";
-  }
-
-  const char* FieldTypeToPackedBufferType(FieldDescriptor::Type proto_type) {
-    switch (proto_type) {
-      case FieldDescriptor::TYPE_INT64:
-      case FieldDescriptor::TYPE_UINT64:
-      case FieldDescriptor::TYPE_INT32:
-      case FieldDescriptor::TYPE_BOOL:
-      case FieldDescriptor::TYPE_UINT32:
-      case FieldDescriptor::TYPE_ENUM:
-      case FieldDescriptor::TYPE_SINT32:
-      case FieldDescriptor::TYPE_SINT64:
-        return "::protozero::PackedVarInt";
-
-      case FieldDescriptor::TYPE_FIXED32:
-        return "::protozero::PackedFixedSizeInt<uint32_t>";
-      case FieldDescriptor::TYPE_SFIXED32:
-        return "::protozero::PackedFixedSizeInt<int32_t>";
-      case FieldDescriptor::TYPE_FLOAT:
-        return "::protozero::PackedFixedSizeInt<float>";
-
-      case FieldDescriptor::TYPE_FIXED64:
-        return "::protozero::PackedFixedSizeInt<uint64_t>";
-      case FieldDescriptor::TYPE_SFIXED64:
-        return "::protozero::PackedFixedSizeInt<int64_t>";
-      case FieldDescriptor::TYPE_DOUBLE:
-        return "::protozero::PackedFixedSizeInt<double>";
-
-      case FieldDescriptor::TYPE_STRING:
-      case FieldDescriptor::TYPE_MESSAGE:
-      case FieldDescriptor::TYPE_BYTES:
-      case FieldDescriptor::TYPE_GROUP:
-        Abort("Unexpected FieldDescritor::Type.");
-    }
-    Abort("Unrecognized FieldDescriptor::Type.");
-    return "";
-  }
-
-  void CollectDescriptors() {
-    // Collect message descriptors in DFS order.
-    std::vector<const Descriptor*> stack;
-    for (int i = 0; i < source_->message_type_count(); ++i)
-      stack.push_back(source_->message_type(i));
-
-    while (!stack.empty()) {
-      const Descriptor* message = stack.back();
-      stack.pop_back();
-      messages_.push_back(message);
-      for (int i = 0; i < message->nested_type_count(); ++i) {
-        stack.push_back(message->nested_type(i));
-      }
-    }
-
-    // Collect enums.
-    for (int i = 0; i < source_->enum_type_count(); ++i)
-      enums_.push_back(source_->enum_type(i));
-
-    for (const Descriptor* message : messages_) {
-      for (int i = 0; i < message->enum_type_count(); ++i) {
-        enums_.push_back(message->enum_type(i));
-      }
-    }
-  }
-
-  void CollectDependencies() {
-    // Public import basically means that callers only need to import this
-    // proto in order to use the stuff publicly imported by this proto.
-    for (int i = 0; i < source_->public_dependency_count(); ++i)
-      public_imports_.insert(source_->public_dependency(i));
-
-    if (source_->weak_dependency_count() > 0)
-      Abort("Weak imports are not supported.");
-
-    // Sanity check. Collect public imports (of collected imports) in DFS order.
-    // Visibilty for current proto:
-    // - all imports listed in current proto,
-    // - public imports of everything imported (recursive).
-    std::vector<const FileDescriptor*> stack;
-    for (int i = 0; i < source_->dependency_count(); ++i) {
-      const FileDescriptor* import = source_->dependency(i);
-      stack.push_back(import);
-      if (public_imports_.count(import) == 0) {
-        private_imports_.insert(import);
-      }
-    }
-
-    while (!stack.empty()) {
-      const FileDescriptor* import = stack.back();
-      stack.pop_back();
-      // Having imports under different packages leads to unnecessary
-      // complexity with namespaces.
-      if (import->package() != package_)
-        Abort("Imported proto must be in the same package.");
-
-      for (int i = 0; i < import->public_dependency_count(); ++i) {
-        stack.push_back(import->public_dependency(i));
-      }
-    }
-
-    // Collect descriptors of messages and enums used in current proto.
-    // It will be used to generate necessary forward declarations and performed
-    // sanity check guarantees that everything lays in the same namespace.
-    for (const Descriptor* message : messages_) {
-      for (int i = 0; i < message->field_count(); ++i) {
-        const FieldDescriptor* field = message->field(i);
-
-        if (field->type() == FieldDescriptor::TYPE_MESSAGE) {
-          if (public_imports_.count(field->message_type()->file()) == 0) {
-            // Avoid multiple forward declarations since
-            // public imports have been already included.
-            referenced_messages_.insert(field->message_type());
-          }
-        } else if (field->type() == FieldDescriptor::TYPE_ENUM) {
-          if (public_imports_.count(field->enum_type()->file()) == 0) {
-            referenced_enums_.insert(field->enum_type());
-          }
-        }
-      }
-    }
-  }
-
-  void Preprocess() {
-    // Package name maps to a series of namespaces.
-    package_ = source_->package();
-    namespaces_ = SplitString(package_, ".");
-    if (!wrapper_namespace_.empty())
-      namespaces_.push_back(wrapper_namespace_);
-
-    full_namespace_prefix_ = "::";
-    for (const std::string& ns : namespaces_)
-      full_namespace_prefix_ += ns + "::";
-
-    CollectDescriptors();
-    CollectDependencies();
-  }
-
-  // Print top header, namespaces and forward declarations.
-  void GeneratePrologue() {
-    std::string greeting =
-        "// Autogenerated by the ProtoZero compiler plugin. DO NOT EDIT.\n";
-    std::string guard = package_ + "_" + source_->name() + "_H_";
-    guard = ToUpper(guard);
-    guard = StripChars(guard, ".-/\\", '_');
-
-    stub_h_->Print(
-        "$greeting$\n"
-        "#ifndef $guard$\n"
-        "#define $guard$\n\n"
-        "#include <stddef.h>\n"
-        "#include <stdint.h>\n\n"
-        "#include \"perfetto/protozero/message.h\"\n"
-        "#include \"perfetto/protozero/packed_repeated_fields.h\"\n"
-        "#include \"perfetto/protozero/proto_decoder.h\"\n"
-        "#include \"perfetto/protozero/proto_utils.h\"\n",
-        "greeting", greeting, "guard", guard);
-
-    // Print includes for public imports.
-    for (const FileDescriptor* dependency : public_imports_) {
-      // Dependency name could contain slashes but importing from upper-level
-      // directories is not possible anyway since build system processes each
-      // proto file individually. Hence proto lookup path is always equal to the
-      // directory where particular proto file is located and protoc does not
-      // allow reference to upper directory (aka ..) in import path.
-      //
-      // Laconically said:
-      // - source_->name() may never have slashes,
-      // - dependency->name() may have slashes but always refers to inner path.
-      stub_h_->Print("#include \"$name$.h\"\n", "name",
-                     ProtoStubName(dependency));
-    }
-    stub_h_->Print("\n");
-
-    // Print namespaces.
-    for (const std::string& ns : namespaces_) {
-      stub_h_->Print("namespace $ns$ {\n", "ns", ns);
-    }
-    stub_h_->Print("\n");
-
-    // Print forward declarations.
-    for (const Descriptor* message : referenced_messages_) {
-      stub_h_->Print("class $class$;\n", "class", GetCppClassName(message));
-    }
-    for (const EnumDescriptor* enumeration : referenced_enums_) {
-      stub_h_->Print("enum $class$ : int32_t;\n", "class",
-                     GetCppClassName(enumeration));
-    }
-    stub_h_->Print("\n");
-  }
-
-  void GenerateEnumDescriptor(const EnumDescriptor* enumeration) {
-    stub_h_->Print("enum $class$ : int32_t {\n", "class",
-                   GetCppClassName(enumeration));
-    stub_h_->Indent();
-
-    std::string value_name_prefix;
-    if (enumeration->containing_type() != nullptr)
-      value_name_prefix = GetCppClassName(enumeration) + "_";
-
-    std::string min_name, max_name;
-    int min_val = std::numeric_limits<int>::max();
-    int max_val = -1;
-    for (int i = 0; i < enumeration->value_count(); ++i) {
-      const EnumValueDescriptor* value = enumeration->value(i);
-      stub_h_->Print("$name$ = $number$,\n", "name",
-                     value_name_prefix + value->name(), "number",
-                     std::to_string(value->number()));
-      if (value->number() < min_val) {
-        min_val = value->number();
-        min_name = value_name_prefix + value->name();
-      }
-      if (value->number() > max_val) {
-        max_val = value->number();
-        max_name = value_name_prefix + value->name();
-      }
-    }
-    stub_h_->Outdent();
-    stub_h_->Print("};\n\n");
-    stub_h_->Print("const $class$ $class$_MIN = $min$;\n", "class",
-                   GetCppClassName(enumeration), "min", min_name);
-    stub_h_->Print("const $class$ $class$_MAX = $max$;\n", "class",
-                   GetCppClassName(enumeration), "max", max_name);
-    stub_h_->Print("\n");
-  }
-
-  // Packed repeated fields are encoded as a length-delimited field on the wire,
-  // where the payload is the concatenation of invidually encoded elements.
-  void GeneratePackedRepeatedFieldDescriptor(const FieldDescriptor* field) {
-    std::map<std::string, std::string> setter;
-    setter["id"] = std::to_string(field->number());
-    setter["name"] = field->name();
-    setter["action"] = "set";
-    setter["buffer_type"] = FieldTypeToPackedBufferType(field->type());
-    stub_h_->Print(
-        setter,
-        "void $action$_$name$(const $buffer_type$& packed_buffer) {\n"
-        "  AppendBytes($id$, packed_buffer.data(), packed_buffer.size());\n"
-        "}\n");
-  }
-
-  void GenerateSimpleFieldDescriptor(const FieldDescriptor* field) {
-    std::map<std::string, std::string> setter;
-    setter["id"] = std::to_string(field->number());
-    setter["name"] = field->name();
-    setter["action"] = field->is_repeated() ? "add" : "set";
-
-    std::string appender;
-    std::string cpp_type;
-
-    switch (field->type()) {
-      case FieldDescriptor::TYPE_BOOL: {
-        appender = "AppendTinyVarInt";
-        cpp_type = "bool";
-        break;
-      }
-      case FieldDescriptor::TYPE_INT32: {
-        appender = "AppendVarInt";
-        cpp_type = "int32_t";
-        break;
-      }
-      case FieldDescriptor::TYPE_INT64: {
-        appender = "AppendVarInt";
-        cpp_type = "int64_t";
-        break;
-      }
-      case FieldDescriptor::TYPE_UINT32: {
-        appender = "AppendVarInt";
-        cpp_type = "uint32_t";
-        break;
-      }
-      case FieldDescriptor::TYPE_UINT64: {
-        appender = "AppendVarInt";
-        cpp_type = "uint64_t";
-        break;
-      }
-      case FieldDescriptor::TYPE_SINT32: {
-        appender = "AppendSignedVarInt";
-        cpp_type = "int32_t";
-        break;
-      }
-      case FieldDescriptor::TYPE_SINT64: {
-        appender = "AppendSignedVarInt";
-        cpp_type = "int64_t";
-        break;
-      }
-      case FieldDescriptor::TYPE_FIXED32: {
-        appender = "AppendFixed";
-        cpp_type = "uint32_t";
-        break;
-      }
-      case FieldDescriptor::TYPE_FIXED64: {
-        appender = "AppendFixed";
-        cpp_type = "uint64_t";
-        break;
-      }
-      case FieldDescriptor::TYPE_SFIXED32: {
-        appender = "AppendFixed";
-        cpp_type = "int32_t";
-        break;
-      }
-      case FieldDescriptor::TYPE_SFIXED64: {
-        appender = "AppendFixed";
-        cpp_type = "int64_t";
-        break;
-      }
-      case FieldDescriptor::TYPE_FLOAT: {
-        appender = "AppendFixed";
-        cpp_type = "float";
-        break;
-      }
-      case FieldDescriptor::TYPE_DOUBLE: {
-        appender = "AppendFixed";
-        cpp_type = "double";
-        break;
-      }
-      case FieldDescriptor::TYPE_ENUM: {
-        appender = IsTinyEnumField(field) ? "AppendTinyVarInt" : "AppendVarInt";
-        cpp_type = GetCppClassName(field->enum_type(), true);
-        break;
-      }
-      case FieldDescriptor::TYPE_STRING: {
-        appender = "AppendString";
-        cpp_type = "const char*";
-        break;
-      }
-      case FieldDescriptor::TYPE_BYTES: {
-        stub_h_->Print(
-            setter,
-            "void $action$_$name$(const uint8_t* data, size_t size) {\n"
-            "  AppendBytes($id$, data, size);\n"
-            "}\n");
-        return;
-      }
-      case FieldDescriptor::TYPE_GROUP:
-      case FieldDescriptor::TYPE_MESSAGE: {
-        Abort("Unsupported field type.");
-        return;
-      }
-    }
-    setter["appender"] = appender;
-    setter["cpp_type"] = cpp_type;
-    stub_h_->Print(setter,
-                   "void $action$_$name$($cpp_type$ value) {\n"
-                   "  $appender$($id$, value);\n"
-                   "}\n");
-
-    // For strings also generate a variant for non-null terminated strings.
-    if (field->type() == FieldDescriptor::TYPE_STRING) {
-      stub_h_->Print(setter,
-                     "// Doesn't check for null terminator.\n"
-                     "// Expects |value| to be at least |size| long.\n"
-                     "void $action$_$name$($cpp_type$ value, size_t size) {\n"
-                     "  AppendBytes($id$, value, size);\n"
-                     "}\n");
-    }
-  }
-
-  void GenerateNestedMessageFieldDescriptor(const FieldDescriptor* field) {
-    std::string action = field->is_repeated() ? "add" : "set";
-    std::string inner_class = GetCppClassName(field->message_type());
-    stub_h_->Print(
-        "template <typename T = $inner_class$> T* $action$_$name$() {\n"
-        "  return BeginNestedMessage<T>($id$);\n"
-        "}\n\n",
-        "id", std::to_string(field->number()), "name", field->name(), "action",
-        action, "inner_class", inner_class);
-  }
-
-  void GenerateDecoder(const Descriptor* message) {
-    int max_field_id = 0;
-    bool has_nonpacked_repeated_fields = false;
-    for (int i = 0; i < message->field_count(); ++i) {
-      const FieldDescriptor* field = message->field(i);
-      if (field->number() > kMaxDecoderFieldId)
-        continue;
-      max_field_id = std::max(max_field_id, field->number());
-      if (field->is_repeated() && !field->is_packed())
-        has_nonpacked_repeated_fields = true;
-    }
-
-    std::string class_name = GetCppClassName(message) + "_Decoder";
-    stub_h_->Print(
-        "class $name$ : public "
-        "::protozero::TypedProtoDecoder</*MAX_FIELD_ID=*/$max$, "
-        "/*HAS_NONPACKED_REPEATED_FIELDS=*/$rep$> {\n",
-        "name", class_name, "max", std::to_string(max_field_id), "rep",
-        has_nonpacked_repeated_fields ? "true" : "false");
-    stub_h_->Print(" public:\n");
-    stub_h_->Indent();
-    stub_h_->Print(
-        "$name$(const uint8_t* data, size_t len) "
-        ": TypedProtoDecoder(data, len) {}\n",
-        "name", class_name);
-    stub_h_->Print(
-        "explicit $name$(const std::string& raw) : "
-        "TypedProtoDecoder(reinterpret_cast<const uint8_t*>(raw.data()), "
-        "raw.size()) {}\n",
-        "name", class_name);
-    stub_h_->Print(
-        "explicit $name$(const ::protozero::ConstBytes& raw) : "
-        "TypedProtoDecoder(raw.data, raw.size) {}\n",
-        "name", class_name);
-
-    for (int i = 0; i < message->field_count(); ++i) {
-      const FieldDescriptor* field = message->field(i);
-      if (field->number() > max_field_id) {
-        stub_h_->Print("// field $name$ omitted because its id is too high\n",
-                       "name", field->name());
-        continue;
-      }
-      std::string getter;
-      std::string cpp_type;
-      switch (field->type()) {
-        case FieldDescriptor::TYPE_BOOL:
-          getter = "as_bool";
-          cpp_type = "bool";
-          break;
-        case FieldDescriptor::TYPE_SFIXED32:
-        case FieldDescriptor::TYPE_SINT32:
-        case FieldDescriptor::TYPE_INT32:
-          getter = "as_int32";
-          cpp_type = "int32_t";
-          break;
-        case FieldDescriptor::TYPE_SFIXED64:
-        case FieldDescriptor::TYPE_SINT64:
-        case FieldDescriptor::TYPE_INT64:
-          getter = "as_int64";
-          cpp_type = "int64_t";
-          break;
-        case FieldDescriptor::TYPE_FIXED32:
-        case FieldDescriptor::TYPE_UINT32:
-          getter = "as_uint32";
-          cpp_type = "uint32_t";
-          break;
-        case FieldDescriptor::TYPE_FIXED64:
-        case FieldDescriptor::TYPE_UINT64:
-          getter = "as_uint64";
-          cpp_type = "uint64_t";
-          break;
-        case FieldDescriptor::TYPE_FLOAT:
-          getter = "as_float";
-          cpp_type = "float";
-          break;
-        case FieldDescriptor::TYPE_DOUBLE:
-          getter = "as_double";
-          cpp_type = "double";
-          break;
-        case FieldDescriptor::TYPE_ENUM:
-          getter = "as_int32";
-          cpp_type = "int32_t";
-          break;
-        case FieldDescriptor::TYPE_STRING:
-          getter = "as_string";
-          cpp_type = "::protozero::ConstChars";
-          break;
-        case FieldDescriptor::TYPE_MESSAGE:
-        case FieldDescriptor::TYPE_BYTES:
-          getter = "as_bytes";
-          cpp_type = "::protozero::ConstBytes";
-          break;
-        case FieldDescriptor::TYPE_GROUP:
-          continue;
-      }
-
-      stub_h_->Print("bool has_$name$() const { return at<$id$>().valid(); }\n",
-                     "name", field->name(), "id",
-                     std::to_string(field->number()));
-
-      if (field->is_packed()) {
-        const char* protozero_wire_type =
-            FieldTypeToProtozeroWireType(field->type());
-        stub_h_->Print(
-            "::protozero::PackedRepeatedFieldIterator<$wire_type$, $cpp_type$> "
-            "$name$(bool* parse_error_ptr) const { return "
-            "GetPackedRepeated<$wire_type$, $cpp_type$>($id$, "
-            "parse_error_ptr); }\n",
-            "wire_type", protozero_wire_type, "cpp_type", cpp_type, "name",
-            field->name(), "id", std::to_string(field->number()));
-      } else if (field->is_repeated()) {
-        stub_h_->Print(
-            "::protozero::RepeatedFieldIterator<$cpp_type$> $name$() const { "
-            "return "
-            "GetRepeated<$cpp_type$>($id$); }\n",
-            "name", field->name(), "cpp_type", cpp_type, "id",
-            std::to_string(field->number()));
-      } else {
-        stub_h_->Print(
-            "$cpp_type$ $name$() const { return at<$id$>().$getter$(); }\n",
-            "name", field->name(), "id", std::to_string(field->number()),
-            "cpp_type", cpp_type, "getter", getter);
-      }
-    }
-    stub_h_->Outdent();
-    stub_h_->Print("};\n\n");
-  }
-
-  void GenerateConstantsForMessageFields(const Descriptor* message) {
-    const bool has_fields = (message->field_count() > 0);
-
-    // Field number constants.
-    if (has_fields) {
-      stub_h_->Print("enum : int32_t {\n");
-      stub_h_->Indent();
-
-      for (int i = 0; i < message->field_count(); ++i) {
-        const FieldDescriptor* field = message->field(i);
-        stub_h_->Print("$name$ = $id$,\n", "name",
-                       GetFieldNumberConstant(field), "id",
-                       std::to_string(field->number()));
-      }
-      stub_h_->Outdent();
-      stub_h_->Print("};\n");
-    }
-  }
-
-  void GenerateMessageDescriptor(const Descriptor* message) {
-    GenerateDecoder(message);
-
-    stub_h_->Print(
-        "class $name$ : public ::protozero::Message {\n"
-        " public:\n",
-        "name", GetCppClassName(message));
-    stub_h_->Indent();
-
-    stub_h_->Print("using Decoder = $name$_Decoder;\n", "name",
-                   GetCppClassName(message));
-
-    GenerateConstantsForMessageFields(message);
-
-    // Using statements for nested messages.
-    for (int i = 0; i < message->nested_type_count(); ++i) {
-      const Descriptor* nested_message = message->nested_type(i);
-      stub_h_->Print("using $local_name$ = $global_name$;\n", "local_name",
-                     nested_message->name(), "global_name",
-                     GetCppClassName(nested_message, true));
-    }
-
-    // Using statements for nested enums.
-    for (int i = 0; i < message->enum_type_count(); ++i) {
-      const EnumDescriptor* nested_enum = message->enum_type(i);
-      stub_h_->Print("using $local_name$ = $global_name$;\n", "local_name",
-                     nested_enum->name(), "global_name",
-                     GetCppClassName(nested_enum, true));
-    }
-
-    // Values of nested enums.
-    for (int i = 0; i < message->enum_type_count(); ++i) {
-      const EnumDescriptor* nested_enum = message->enum_type(i);
-      std::string value_name_prefix = GetCppClassName(nested_enum) + "_";
-
-      for (int j = 0; j < nested_enum->value_count(); ++j) {
-        const EnumValueDescriptor* value = nested_enum->value(j);
-        stub_h_->Print("static const $class$ $name$ = $full_name$;\n", "class",
-                       nested_enum->name(), "name", value->name(), "full_name",
-                       value_name_prefix + value->name());
-      }
-    }
-
-    // Field descriptors.
-    for (int i = 0; i < message->field_count(); ++i) {
-      const FieldDescriptor* field = message->field(i);
-      if (field->is_packed()) {
-        GeneratePackedRepeatedFieldDescriptor(field);
-      } else if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
-        GenerateSimpleFieldDescriptor(field);
-      } else {
-        GenerateNestedMessageFieldDescriptor(field);
-      }
-    }
-
-    stub_h_->Outdent();
-    stub_h_->Print("};\n\n");
-  }
-
-  void GenerateEpilogue() {
-    for (unsigned i = 0; i < namespaces_.size(); ++i) {
-      stub_h_->Print("} // Namespace.\n");
-    }
-    stub_h_->Print("#endif  // Include guard.\n");
-  }
-
-  const FileDescriptor* const source_;
-  Printer* const stub_h_;
-  std::string error_;
-
-  std::string package_;
-  std::string wrapper_namespace_;
-  std::vector<std::string> namespaces_;
-  std::string full_namespace_prefix_;
-  std::vector<const Descriptor*> messages_;
-  std::vector<const EnumDescriptor*> enums_;
-
-  // The custom *Comp comparators are to ensure determinism of the generator.
-  std::set<const FileDescriptor*, FileDescriptorComp> public_imports_;
-  std::set<const FileDescriptor*, FileDescriptorComp> private_imports_;
-  std::set<const Descriptor*, DescriptorComp> referenced_messages_;
-  std::set<const EnumDescriptor*, EnumDescriptorComp> referenced_enums_;
-};
-
-class ProtoZeroGenerator : public ::google::protobuf::compiler::CodeGenerator {
- public:
-  explicit ProtoZeroGenerator();
-  ~ProtoZeroGenerator() override;
-
-  // CodeGenerator implementation
-  bool Generate(const google::protobuf::FileDescriptor* file,
-                const std::string& options,
-                GeneratorContext* context,
-                std::string* error) const override;
-};
-
-ProtoZeroGenerator::ProtoZeroGenerator() {}
-
-ProtoZeroGenerator::~ProtoZeroGenerator() {}
-
-bool ProtoZeroGenerator::Generate(const FileDescriptor* file,
-                                  const std::string& options,
-                                  GeneratorContext* context,
-                                  std::string* error) const {
-  const std::unique_ptr<ZeroCopyOutputStream> stub_h_file_stream(
-      context->Open(ProtoStubName(file) + ".h"));
-  const std::unique_ptr<ZeroCopyOutputStream> stub_cc_file_stream(
-      context->Open(ProtoStubName(file) + ".cc"));
-
-  // Variables are delimited by $.
-  Printer stub_h_printer(stub_h_file_stream.get(), '$');
-  GeneratorJob job(file, &stub_h_printer);
-
-  Printer stub_cc_printer(stub_cc_file_stream.get(), '$');
-  stub_cc_printer.Print("// Intentionally empty (crbug.com/998165)\n");
-
-  // Parse additional options.
-  for (const std::string& option : SplitString(options, ",")) {
-    std::vector<std::string> option_pair = SplitString(option, "=");
-    job.SetOption(option_pair[0], option_pair[1]);
-  }
-
-  if (!job.GenerateStubs()) {
-    *error = job.GetFirstError();
-    return false;
-  }
-  return true;
-}
-
-}  // namespace
-}  // namespace protozero
+#include "google/protobuf/compiler/plugin.h"
+#include "src/protozero/protoc_plugin/protozero_generator.h"
 
 int main(int argc, char* argv[]) {
   ::protozero::ProtoZeroGenerator generator;
diff --git a/src/protozero/scattered_heap_buffer.cc b/src/protozero/scattered_heap_buffer.cc
index 389c36e..eb6883ed 100644
--- a/src/protozero/scattered_heap_buffer.cc
+++ b/src/protozero/scattered_heap_buffer.cc
@@ -20,31 +20,20 @@
 
 namespace protozero {
 
-ScatteredHeapBuffer::Slice::Slice()
-    : buffer_(nullptr), size_(0u), unused_bytes_(0u) {}
-
 ScatteredHeapBuffer::Slice::Slice(size_t size)
     : buffer_(std::unique_ptr<uint8_t[]>(new uint8_t[size])),
       size_(size),
       unused_bytes_(size) {
   PERFETTO_DCHECK(size);
-  Clear();
+#if PERFETTO_DCHECK_IS_ON()
+  memset(start(), 0xff, size_);
+#endif  // PERFETTO_DCHECK_IS_ON()
 }
 
 ScatteredHeapBuffer::Slice::Slice(Slice&& slice) noexcept = default;
 
 ScatteredHeapBuffer::Slice::~Slice() = default;
 
-ScatteredHeapBuffer::Slice& ScatteredHeapBuffer::Slice::operator=(Slice&&) =
-    default;
-
-void ScatteredHeapBuffer::Slice::Clear() {
-  unused_bytes_ = size_;
-#if PERFETTO_DCHECK_IS_ON()
-  memset(start(), 0xff, size_);
-#endif  // PERFETTO_DCHECK_IS_ON()
-}
-
 ScatteredHeapBuffer::ScatteredHeapBuffer(size_t initial_slice_size_bytes,
                                          size_t maximum_slice_size_bytes)
     : next_slice_size_(initial_slice_size_bytes),
@@ -59,12 +48,7 @@
   PERFETTO_CHECK(writer_);
   AdjustUsedSizeOfCurrentSlice();
 
-  if (cached_slice_.start()) {
-    slices_.push_back(std::move(cached_slice_));
-    PERFETTO_DCHECK(!cached_slice_.start());
-  } else {
-    slices_.emplace_back(next_slice_size_);
-  }
+  slices_.emplace_back(next_slice_size_);
   next_slice_size_ = std::min(maximum_slice_size_, next_slice_size_ * 2);
   return slices_.back().GetTotalRange();
 }
@@ -72,21 +56,15 @@
 std::vector<uint8_t> ScatteredHeapBuffer::StitchSlices() {
   AdjustUsedSizeOfCurrentSlice();
   std::vector<uint8_t> buffer;
+  size_t i = 0;
   for (const auto& slice : slices_) {
     auto used_range = slice.GetUsedRange();
     buffer.insert(buffer.end(), used_range.begin, used_range.end);
+    i++;
   }
   return buffer;
 }
 
-std::vector<protozero::ContiguousMemoryRange> ScatteredHeapBuffer::GetRanges() {
-  AdjustUsedSizeOfCurrentSlice();
-  std::vector<protozero::ContiguousMemoryRange> ranges;
-  for (const auto& slice : slices_)
-    ranges.push_back(slice.GetUsedRange());
-  return ranges;
-}
-
 void ScatteredHeapBuffer::AdjustUsedSizeOfCurrentSlice() {
   if (!slices_.empty())
     slices_.back().set_unused_bytes(writer_->bytes_available());
@@ -100,12 +78,4 @@
   return total_size;
 }
 
-void ScatteredHeapBuffer::Reset() {
-  if (slices_.empty())
-    return;
-  cached_slice_ = std::move(slices_.front());
-  cached_slice_.Clear();
-  slices_.clear();
-}
-
 }  // namespace protozero
diff --git a/src/protozero/scattered_stream_writer_unittest.cc b/src/protozero/scattered_stream_writer_unittest.cc
index b3ec99c..6a61d33 100644
--- a/src/protozero/scattered_stream_writer_unittest.cc
+++ b/src/protozero/scattered_stream_writer_unittest.cc
@@ -20,9 +20,9 @@
 
 #include <memory>
 
+#include "gtest/gtest.h"
 #include "perfetto/base/logging.h"
 #include "src/protozero/test/fake_scattered_buffer.h"
-#include "test/gtest_and_gmock.h"
 
 namespace protozero {
 namespace {
diff --git a/src/protozero/test/example_proto/test_messages.proto b/src/protozero/test/example_proto/test_messages.proto
index d28b1e8..077b088 100644
--- a/src/protozero/test/example_proto/test_messages.proto
+++ b/src/protozero/test/example_proto/test_messages.proto
@@ -98,9 +98,3 @@
   optional bool U2 = 8;
   optional bool bangBig__ = 9;
 }
-
-message PackedRepeatedFields {
-  repeated int32 field_int32 = 1 [packed = true];
-  repeated fixed32 field_fixed32 = 2 [packed = true];
-  repeated sfixed64 field_sfixed64 = 3 [packed = true];
-}
diff --git a/src/protozero/test/fake_scattered_buffer.cc b/src/protozero/test/fake_scattered_buffer.cc
index 7b65b29..3c48f48 100644
--- a/src/protozero/test/fake_scattered_buffer.cc
+++ b/src/protozero/test/fake_scattered_buffer.cc
@@ -19,7 +19,7 @@
 #include <sstream>
 #include <utility>
 
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
 
 namespace protozero {
 
diff --git a/src/protozero/test/protozero_conformance_unittest.cc b/src/protozero/test/protozero_conformance_unittest.cc
index a374c51..034487f 100644
--- a/src/protozero/test/protozero_conformance_unittest.cc
+++ b/src/protozero/test/protozero_conformance_unittest.cc
@@ -18,10 +18,9 @@
 #include <memory>
 #include <vector>
 
+#include "gtest/gtest.h"
 #include "perfetto/protozero/message_handle.h"
-#include "perfetto/protozero/packed_repeated_fields.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "test/gtest_and_gmock.h"
+#include "src/protozero/test/fake_scattered_buffer.h"
 
 // Autogenerated headers in out/*/gen/
 #include "src/protozero/test/example_proto/library.pbzero.h"
@@ -36,8 +35,45 @@
 
 constexpr size_t kChunkSize = 42;
 
-TEST(ProtoZeroConformanceTest, SimpleFieldsNoNesting) {
-  HeapBuffered<pbtest::EveryField> msg{kChunkSize, kChunkSize};
+class ProtoZeroConformanceTest : public ::testing::Test {
+ public:
+  void SetUp() override {
+    buffer_.reset(new FakeScatteredBuffer(kChunkSize));
+    stream_writer_.reset(new ScatteredStreamWriter(buffer_.get()));
+  }
+
+  void TearDown() override {
+    root_messages_.clear();
+    stream_writer_.reset();
+    buffer_.reset();
+  }
+
+ protected:
+  template <class T>
+  T* CreateMessage() {
+    T* message = new T();
+    root_messages_.push_back(std::unique_ptr<T>(message));
+    message->Reset(stream_writer_.get());
+    return message;
+  }
+
+  size_t GetNumSerializedBytes() {
+    return buffer_->chunks().size() * kChunkSize -
+           stream_writer_->bytes_available();
+  }
+
+  void GetSerializedBytes(size_t start, size_t length, uint8_t* buffer) {
+    return buffer_->GetBytes(start, length, buffer);
+  }
+
+ private:
+  std::unique_ptr<FakeScatteredBuffer> buffer_;
+  std::unique_ptr<ScatteredStreamWriter> stream_writer_;
+  std::vector<std::unique_ptr<Message>> root_messages_;
+};
+
+TEST_F(ProtoZeroConformanceTest, SimpleFieldsNoNesting) {
+  auto* msg = CreateMessage<pbtest::EveryField>();
 
   msg->set_field_int32(-1);
   msg->set_field_int64(-333123456789ll);
@@ -62,9 +98,13 @@
   msg->add_repeated_int32(100);
   msg->add_repeated_int32(2000000);
 
-  std::string serialized = msg.SerializeAsString();
+  size_t msg_size = GetNumSerializedBytes();
+
+  std::unique_ptr<uint8_t[]> msg_binary(new uint8_t[msg_size]);
+  GetSerializedBytes(0, msg_size, msg_binary.get());
+
   pbgold::EveryField gold_msg;
-  gold_msg.ParseFromString(serialized);
+  gold_msg.ParseFromArray(msg_binary.get(), static_cast<int>(msg_size));
 
   EXPECT_EQ(-1, gold_msg.field_int32());
   EXPECT_EQ(-333123456789ll, gold_msg.field_int64());
@@ -89,11 +129,11 @@
   EXPECT_EQ(-1, gold_msg.repeated_int32(1));
   EXPECT_EQ(100, gold_msg.repeated_int32(2));
   EXPECT_EQ(2000000, gold_msg.repeated_int32(3));
-  EXPECT_EQ(serialized.size(), static_cast<size_t>(gold_msg.ByteSize()));
+  EXPECT_EQ(msg_size, static_cast<size_t>(gold_msg.ByteSize()));
 }
 
-TEST(ProtoZeroConformanceTest, NestedMessages) {
-  HeapBuffered<pbtest::NestedA> msg_a{kChunkSize, kChunkSize};
+TEST_F(ProtoZeroConformanceTest, NestedMessages) {
+  auto* msg_a = CreateMessage<pbtest::NestedA>();
 
   pbtest::NestedA::NestedB* msg_b = msg_a->add_repeated_a();
   pbtest::NestedA::NestedB::NestedC* msg_c = msg_b->set_value_b();
@@ -101,25 +141,29 @@
   msg_b = msg_a->add_repeated_a();
   msg_c = msg_a->set_super_nested();
   msg_c->set_value_c(1000);
+  msg_a->Finalize();
 
-  std::string serialized = msg_a.SerializeAsString();
-  EXPECT_EQ(serialized.size(), 26u);
+  size_t msg_size = GetNumSerializedBytes();
+  EXPECT_EQ(26u, msg_size);
+
+  std::unique_ptr<uint8_t[]> msg_binary(new uint8_t[msg_size]);
+  GetSerializedBytes(0, msg_size, msg_binary.get());
 
   pbgold::NestedA gold_msg_a;
-  gold_msg_a.ParseFromString(serialized);
+  gold_msg_a.ParseFromArray(msg_binary.get(), static_cast<int>(msg_size));
   EXPECT_EQ(2, gold_msg_a.repeated_a_size());
   EXPECT_EQ(321, gold_msg_a.repeated_a(0).value_b().value_c());
   EXPECT_FALSE(gold_msg_a.repeated_a(1).has_value_b());
   EXPECT_EQ(1000, gold_msg_a.super_nested().value_c());
 }
 
-TEST(ProtoZeroConformanceTest, Import) {
+TEST(ProtoZeroTest, Simple) {
   // Test the includes for indirect public import: library.pbzero.h ->
   // library_internals/galaxies.pbzero.h -> upper_import.pbzero.h .
   EXPECT_LE(0u, sizeof(pbtest::TrickyPublicImport));
 }
 
-TEST(ProtoZeroConformanceTest, FieldNumbers) {
+TEST(ProtoZeroTest, FieldNumbers) {
   EXPECT_EQ(1, pbtest::CamelCaseFields::kFooBarBazFieldNumber);
   EXPECT_EQ(2, pbtest::CamelCaseFields::kBarBazFieldNumber);
   EXPECT_EQ(3, pbtest::CamelCaseFields::kMooMooFieldNumber);
@@ -131,137 +175,5 @@
   EXPECT_EQ(9, pbtest::CamelCaseFields::kBangBigFieldNumber);
 }
 
-TEST(ProtoZeroConformanceTest, PackedRepeatedVarint) {
-  int values[] = {42, 255, -1};
-
-  HeapBuffered<pbtest::PackedRepeatedFields> msg{kChunkSize, kChunkSize};
-  PackedVarInt buf;
-  for (auto v : values)
-    buf.Append(v);
-  msg->set_field_int32(buf);
-  std::string serialized = msg.SerializeAsString();
-
-  // Serialized as a length-delimited field with a payload of
-  // concatenated varints. So the size should be:
-  // varint(42) -> 1 byte
-  // varint(255) -> 2 bytes
-  // varint(-1) -> 10 bytes
-  // varint(payload length) -> 1 byte
-  // field type & id(1) -> 1 byte
-  // total: 6 bytes
-  EXPECT_EQ(15u, serialized.size());
-  EXPECT_EQ(proto_utils::MakeTagLengthDelimited(
-                pbtest::PackedRepeatedFields::kFieldInt32FieldNumber),
-            static_cast<uint32_t>(serialized[0]));
-
-  // Correctly parsed by the protobuf library.
-  pbgold::PackedRepeatedFields parsed_gold_msg;
-  parsed_gold_msg.ParseFromString(serialized);
-  ASSERT_THAT(parsed_gold_msg.field_int32(), testing::ElementsAreArray(values));
-
-  // Encoded identically by the protobuf library.
-  pbgold::PackedRepeatedFields gold_msg;
-  for (auto v : values)
-    gold_msg.add_field_int32(v);
-  ASSERT_EQ(gold_msg.SerializeAsString(), serialized);
-}
-
-TEST(ProtoZeroConformanceTest, PackedRepeatedFixed32) {
-  uint32_t values[] = {1, 2, 4, 8};
-
-  HeapBuffered<pbtest::PackedRepeatedFields> msg{kChunkSize, kChunkSize};
-  PackedFixedSizeInt<uint32_t> buf;
-  for (auto v : values)
-    buf.Append(v);
-  msg->set_field_fixed32(buf);
-  std::string serialized = msg.SerializeAsString();
-
-  // 4x4 bytes payload + 1 byte length + 1 byte tag & field
-  EXPECT_EQ(18u, serialized.size());
-  EXPECT_EQ(proto_utils::MakeTagLengthDelimited(
-                pbtest::PackedRepeatedFields::kFieldFixed32FieldNumber),
-            static_cast<uint32_t>(serialized[0]));
-
-  // Correctly parsed by the protobuf library.
-  pbgold::PackedRepeatedFields parsed_gold_msg;
-  parsed_gold_msg.ParseFromString(serialized);
-  ASSERT_THAT(parsed_gold_msg.field_fixed32(),
-              testing::ElementsAreArray(values));
-
-  // Encoded identically by the protobuf library.
-  pbgold::PackedRepeatedFields gold_msg;
-  for (auto v : values)
-    gold_msg.add_field_fixed32(v);
-  ASSERT_EQ(gold_msg.SerializeAsString(), serialized);
-}
-
-TEST(ProtoZeroConformanceTest, PackedRepeatedFixed64) {
-  int64_t values[] = {1, -2, 4, -8};
-
-  HeapBuffered<pbtest::PackedRepeatedFields> msg{kChunkSize, kChunkSize};
-  PackedFixedSizeInt<int64_t> buf;
-  for (auto v : values)
-    buf.Append(v);
-  msg->set_field_sfixed64(buf);
-  std::string serialized = msg.SerializeAsString();
-
-  // 4x8 bytes payload + 1 byte length + 1 byte tag & field
-  EXPECT_EQ(34u, serialized.size());
-  EXPECT_EQ(proto_utils::MakeTagLengthDelimited(
-                pbtest::PackedRepeatedFields::kFieldSfixed64FieldNumber),
-            static_cast<uint32_t>(serialized[0]));
-
-  // Correctly parsed by the protobuf library.
-  pbgold::PackedRepeatedFields parsed_gold_msg;
-  parsed_gold_msg.ParseFromString(serialized);
-  ASSERT_THAT(parsed_gold_msg.field_sfixed64(),
-              testing::ElementsAreArray(values));
-
-  // Encoded identically by the protobuf library.
-  pbgold::PackedRepeatedFields gold_msg;
-  for (auto v : values)
-    gold_msg.add_field_sfixed64(v);
-  ASSERT_EQ(gold_msg.SerializeAsString(), serialized);
-}
-
-TEST(ProtoZeroConformanceTest, EmptyPackedRepeatedField) {
-  HeapBuffered<pbtest::PackedRepeatedFields> msg;
-  PackedVarInt buf;
-  msg->set_field_int32(buf);
-  std::string serialized = msg.SerializeAsString();
-
-  // Encoded as 2 bytes: tag/field, and a length of zero.
-  EXPECT_EQ(2u, serialized.size());
-  EXPECT_EQ(proto_utils::MakeTagLengthDelimited(
-                pbtest::PackedRepeatedFields::kFieldInt32FieldNumber),
-            static_cast<uint32_t>(serialized[0]));
-  EXPECT_EQ(0, serialized[1]);
-
-  // Correctly parsed by the protobuf library.
-  pbgold::PackedRepeatedFields parsed_gold_msg;
-  parsed_gold_msg.ParseFromString(serialized);
-  EXPECT_EQ(0, parsed_gold_msg.field_int32_size());
-}
-
-// Tests that the stack -> heap expansion dosn't lose data.
-TEST(ProtoZeroConformanceTest, PackedRepeatedResize) {
-  const int kNumValues = 32768;
-  const int64_t kMultiplier = 10000000;
-  HeapBuffered<pbtest::PackedRepeatedFields> msg{kChunkSize, kChunkSize};
-  PackedFixedSizeInt<int64_t> buf;
-  for (int i = 0; i < kNumValues; i++)
-    buf.Append(i * kMultiplier);
-  msg->set_field_sfixed64(buf);
-  std::string serialized = msg.SerializeAsString();
-
-  // Correctly parsed by the protobuf library.
-  pbgold::PackedRepeatedFields parsed_gold_msg;
-  parsed_gold_msg.ParseFromString(serialized);
-  ASSERT_EQ(parsed_gold_msg.field_sfixed64().size(), kNumValues);
-  for (int i = 0; i < kNumValues; i++) {
-    ASSERT_EQ(parsed_gold_msg.field_sfixed64(i), i * kMultiplier);
-  }
-}
-
 }  // namespace
 }  // namespace protozero
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 80d394d..0a76207 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -14,124 +14,148 @@
 
 import("../../gn/fuzzer.gni")
 import("../../gn/perfetto.gni")
-import("../../gn/perfetto_host_executable.gni")
-import("../../gn/test.gni")
 import("../../gn/wasm.gni")
 
-# Prevent that this file is accidentally included in embedder builds.
-assert(enable_perfetto_trace_processor)
+wasm_lib("trace_processor_wasm") {
+  name = "trace_processor"
+  sources = [
+    "wasm_bridge.cc",
+  ]
+
+  # All the deps below are implicitly xxx($wasm_toolchain) because of the
+  # outer "is_wasm" block.
+  deps = [
+    ":lib",
+    "../../buildtools:sqlite",
+    "../../gn:default_deps",
+    "../../include/perfetto/base",
+    "../../protos/perfetto/trace_processor:lite",
+  ]
+}
 
 # The library which eases processing of Perfetto traces by exposing reading
 # friendly APIs.
-if (enable_perfetto_trace_processor_sqlite) {
-  static_library("trace_processor") {
-    complete_static_lib = true
-    deps = [
-      ":lib",
-    ]
-  }
+static_library("trace_processor") {
+  deps = [
+    ":lib",
+  ]
 }
 
-if (enable_perfetto_ui) {
-  wasm_lib("trace_processor_wasm") {
-    name = "trace_processor"
-    deps = [
-      ":lib",
-      "../../gn:default_deps",
-      "../base",
-      "rpc:wasm_bridge",
-    ]
-  }
-}
-
-source_set("storage") {
+source_set("lib") {
   sources = [
+    "android_logs_table.cc",
+    "android_logs_table.h",
+    "args_table.cc",
+    "args_table.h",
     "args_tracker.cc",
     "args_tracker.h",
-    "binder_tracker.cc",
-    "binder_tracker.h",
     "chunked_trace_reader.h",
     "clock_tracker.cc",
     "clock_tracker.h",
+    "counter_definitions_table.cc",
+    "counter_definitions_table.h",
+    "counter_values_table.cc",
+    "counter_values_table.h",
     "event_tracker.cc",
     "event_tracker.h",
-    "forwarding_trace_parser.cc",
-    "forwarding_trace_parser.h",
+    "filtered_row_index.cc",
+    "filtered_row_index.h",
+    "ftrace_descriptors.cc",
+    "ftrace_descriptors.h",
+    "ftrace_utils.cc",
     "ftrace_utils.h",
-    "gzip_trace_parser.cc",
-    "gzip_trace_parser.h",
+    "fuchsia_provider_view.cc",
+    "fuchsia_provider_view.h",
+    "fuchsia_trace_parser.cc",
+    "fuchsia_trace_parser.h",
+    "fuchsia_trace_tokenizer.cc",
+    "fuchsia_trace_tokenizer.h",
+    "fuchsia_trace_utils.cc",
+    "fuchsia_trace_utils.h",
     "heap_profile_tracker.cc",
     "heap_profile_tracker.h",
-    "importers/ftrace/ftrace_descriptors.h",
-    "importers/ftrace/ftrace_module.h",
-    "importers/ftrace/ftrace_parser.h",
-    "importers/ftrace/ftrace_tokenizer.h",
-    "importers/ftrace/sched_event_tracker.h",
-    "importers/fuchsia/fuchsia_provider_view.h",
-    "importers/proto/android_probes_module.h",
-    "importers/proto/android_probes_parser.h",
-    "importers/proto/graphics_event_module.h",
-    "importers/proto/graphics_event_parser.h",
-    "importers/proto/heap_graph_module.h",
-    "importers/proto/heap_graph_tracker.h",
-    "importers/proto/heap_graph_walker.h",
-    "importers/proto/packet_sequence_state.h",
-    "importers/proto/proto_importer_module.h",
-    "importers/proto/proto_incremental_state.h",
-    "importers/proto/proto_trace_parser.cc",
-    "importers/proto/proto_trace_parser.h",
-    "importers/proto/proto_trace_tokenizer.cc",
-    "importers/proto/proto_trace_tokenizer.h",
-    "importers/proto/system_probes_module.h",
-    "importers/proto/system_probes_parser.h",
-    "importers/proto/track_event_module.h",
-    "importers/proto/track_event_parser.cc",
-    "importers/proto/track_event_parser.h",
-    "importers/proto/track_event_tokenizer.cc",
-    "importers/proto/track_event_tokenizer.h",
-    "importers/systrace/systrace_parser.h",
-    "importers/systrace/systrace_trace_parser.h",
-    "metadata.h",
+    "instants_table.cc",
+    "instants_table.h",
+    "null_term_string_view.h",
+    "process_table.cc",
+    "process_table.h",
     "process_tracker.cc",
     "process_tracker.h",
+    "proto_incremental_state.h",
+    "proto_trace_parser.cc",
+    "proto_trace_parser.h",
+    "proto_trace_tokenizer.cc",
+    "proto_trace_tokenizer.h",
+    "query_constraints.cc",
+    "query_constraints.h",
+    "raw_table.cc",
+    "raw_table.h",
+    "row_iterators.cc",
+    "row_iterators.h",
+    "sched_slice_table.cc",
+    "sched_slice_table.h",
+    "scoped_db.h",
+    "slice_table.cc",
+    "slice_table.h",
     "slice_tracker.cc",
     "slice_tracker.h",
-    "stack_profile_tracker.cc",
-    "stack_profile_tracker.h",
+    "span_join_operator_table.cc",
+    "span_join_operator_table.h",
+    "sql_stats_table.cc",
+    "sql_stats_table.h",
+    "sqlite3_str_split.cc",
+    "sqlite3_str_split.h",
+    "sqlite_utils.h",
     "stats.h",
+    "stats_table.cc",
+    "stats_table.h",
+    "storage_columns.cc",
+    "storage_columns.h",
+    "storage_schema.cc",
+    "storage_schema.h",
+    "storage_table.cc",
+    "storage_table.h",
+    "string_pool.cc",
+    "string_pool.h",
+    "string_table.cc",
+    "string_table.h",
+    "syscall_tracker.cc",
     "syscall_tracker.h",
-    "timestamped_trace_piece.h",
+    "syscalls_aarch32.h",
+    "syscalls_aarch64.h",
+    "syscalls_armeabi.h",
+    "syscalls_x86_64.h",
+    "table.cc",
+    "table.h",
+    "thread_table.cc",
+    "thread_table.h",
     "trace_blob_view.h",
     "trace_parser.h",
+    "trace_processor.cc",
     "trace_processor_context.cc",
     "trace_processor_context.h",
-    "trace_processor_storage.cc",
-    "trace_processor_storage_impl.cc",
-    "trace_processor_storage_impl.h",
+    "trace_processor_impl.cc",
+    "trace_processor_impl.h",
     "trace_sorter.cc",
     "trace_sorter.h",
     "trace_storage.cc",
     "trace_storage.h",
-    "track_tracker.cc",
-    "track_tracker.h",
-    "variadic.h",
     "virtual_destructors.cc",
-    "vulkan_memory_tracker.h",
+    "window_operator_table.cc",
+    "window_operator_table.h",
   ]
 
   deps = [
-    ":common",
+    "../../buildtools:sqlite",
     "../../gn:default_deps",
-    "../../gn:zlib",
+    "../../include/perfetto/traced:sys_stats_counters",
     "../../protos/perfetto/common:zero",
-    "../../protos/perfetto/config:zero",
+    "../../protos/perfetto/metrics:zero",
+    "../../protos/perfetto/metrics/android:zero",
     "../../protos/perfetto/trace:zero",
     "../../protos/perfetto/trace/android:zero",
-    "../../protos/perfetto/trace/chrome:zero",
     "../../protos/perfetto/trace/ftrace:zero",
-    "../../protos/perfetto/trace/gpu:zero",
     "../../protos/perfetto/trace/interned_data:zero",
-    "../../protos/perfetto/trace/perfetto:zero",
     "../../protos/perfetto/trace/power:zero",
     "../../protos/perfetto/trace/profiling:zero",
     "../../protos/perfetto/trace/ps:zero",
@@ -139,330 +163,121 @@
     "../../protos/perfetto/trace/track_event:zero",
     "../base",
     "../protozero",
-    "tables",
+    "metrics:lib",
   ]
   public_deps = [
-    "../../include/perfetto/trace_processor:storage",
+    "../../include/perfetto/trace_processor",
   ]
-  if (enable_perfetto_trace_processor_json_import) {
+  if (perfetto_build_standalone) {
     sources += [
-      "importers/json/json_trace_parser.cc",
-      "importers/json/json_trace_parser.h",
-      "importers/json/json_trace_tokenizer.cc",
-      "importers/json/json_trace_tokenizer.h",
-      "importers/json/json_trace_utils.cc",
-      "importers/json/json_trace_utils.h",
+      "json_trace_parser.cc",
+      "json_trace_parser.h",
+      "json_trace_tokenizer.cc",
+      "json_trace_tokenizer.h",
+      "json_trace_utils.cc",
+      "json_trace_utils.h",
     ]
-    deps += [ "../../gn:jsoncpp" ]
-  }
-  if (enable_perfetto_trace_processor_ftrace) {
-    sources += [
-      "importers/ftrace/ftrace_descriptors.cc",
-      "importers/ftrace/ftrace_parser.cc",
-      "importers/ftrace/ftrace_tokenizer.cc",
-      "importers/ftrace/sched_event_tracker.cc",
-      "importers/systrace/systrace_parser.cc",
-      "importers/systrace/systrace_trace_parser.cc",
-    ]
-  }
-  if (enable_perfetto_trace_processor_ftrace ||
-      enable_perfetto_trace_processor_fuchsia) {
-    sources += [ "ftrace_utils.cc" ]
-  }
-  if (enable_perfetto_trace_processor_system_probes) {
-    sources += [ "importers/proto/system_probes_parser.cc" ]
-    deps += [ "../../include/perfetto/ext/traced:sys_stats_counters" ]
-  }
-  if (enable_perfetto_trace_processor_android_probes) {
-    sources += [ "importers/proto/android_probes_parser.cc" ]
-  }
-  if (enable_perfetto_trace_processor_heap_graphs) {
-    sources += [
-      "importers/proto/heap_graph_module.cc",
-      "importers/proto/heap_graph_tracker.cc",
-      "importers/proto/heap_graph_walker.cc",
-    ]
-  }
-  if (enable_perfetto_trace_processor_graphics) {
-    sources += [
-      "importers/proto/graphics_event_parser.cc",
-      "vulkan_memory_tracker.cc",
-    ]
-  }
-  if (enable_perfetto_trace_processor_fuchsia) {
-    sources += [
-      "importers/fuchsia/fuchsia_provider_view.cc",
-      "importers/fuchsia/fuchsia_trace_parser.cc",
-      "importers/fuchsia/fuchsia_trace_parser.h",
-      "importers/fuchsia/fuchsia_trace_tokenizer.cc",
-      "importers/fuchsia/fuchsia_trace_tokenizer.h",
-      "importers/fuchsia/fuchsia_trace_utils.cc",
-      "importers/fuchsia/fuchsia_trace_utils.h",
-    ]
-  }
-  if (enable_perfetto_trace_processor_syscalls) {
-    sources += [
-      "syscall_tracker.cc",
-      "syscalls_aarch32.h",
-      "syscalls_aarch64.h",
-      "syscalls_armeabi.h",
-      "syscalls_x86_64.h",
-    ]
+    deps += [ "../../gn:jsoncpp_deps" ]
   }
 }
 
-if (enable_perfetto_trace_processor_json) {
-  source_set("export_json") {
-    sources = [
-      "export_json.cc",
-      "export_json.h",
-    ]
-    deps = [
-      ":storage",
-      "../../gn:default_deps",
-      "../../gn:jsoncpp",
-      "../base",
-    ]
-    public_deps = [
-      "../../include/perfetto/ext/trace_processor:export_json",
-    ]
-  }
-}
-
-if (enable_perfetto_trace_processor_sqlite) {
-  source_set("lib") {
-    sources = [
-      "android_logs_table.cc",
-      "android_logs_table.h",
-      "args_table.cc",
-      "args_table.h",
-      "counter_values_table.cc",
-      "counter_values_table.h",
-      "cpu_profile_stack_sample_table.cc",
-      "cpu_profile_stack_sample_table.h",
-      "filtered_row_index.cc",
-      "filtered_row_index.h",
-      "heap_profile_allocation_table.cc",
-      "heap_profile_allocation_table.h",
-      "instants_table.cc",
-      "instants_table.h",
-      "metadata_table.cc",
-      "metadata_table.h",
-      "process_table.cc",
-      "process_table.h",
-      "raw_table.cc",
-      "raw_table.h",
-      "read_trace.cc",
-      "row_iterators.cc",
-      "row_iterators.h",
-      "sched_slice_table.h",
-      "slice_table.cc",
-      "slice_table.h",
-      "span_join_operator_table.cc",
-      "span_join_operator_table.h",
-      "sql_stats_table.cc",
-      "sql_stats_table.h",
-      "stack_profile_frame_table.cc",
-      "stack_profile_frame_table.h",
-      "stack_profile_mapping_table.cc",
-      "stack_profile_mapping_table.h",
-      "stats_table.cc",
-      "stats_table.h",
-      "storage_columns.cc",
-      "storage_columns.h",
-      "storage_schema.cc",
-      "storage_schema.h",
-      "storage_table.cc",
-      "storage_table.h",
-      "thread_table.cc",
-      "thread_table.h",
-      "trace_processor.cc",
-      "trace_processor_impl.cc",
-      "trace_processor_impl.h",
-      "window_operator_table.cc",
-      "window_operator_table.h",
-    ]
-
-    deps = [
-      ":common",
-      ":storage",
-      "../../gn:default_deps",
-      "../../gn:sqlite",
-      "../../protos/perfetto/trace/ftrace:zero",
-      "../base",
-      "db:lib",
-      "sqlite",
-      "tables",
-    ]
-    public_deps = [
-      "../../include/perfetto/trace_processor",
-    ]
-    if (enable_perfetto_trace_processor_ftrace) {
-      sources += [ "sched_slice_table.cc" ]
-    }
-    if (enable_perfetto_trace_processor_metrics) {
-      deps += [
-        "../../protos/perfetto/metrics:zero",
-        "../../protos/perfetto/metrics/android:zero",
-        "metrics:lib",
-      ]
-    }
-    if (enable_perfetto_trace_processor_json) {
-      deps += [ ":export_json" ]
-    }
-  }
-}
-
-# TODO(lalitm): we need to find a better home for the classes here.
-source_set("common") {
-  sources = [
-    "null_term_string_view.h",
-    "string_pool.cc",
-    "string_pool.h",
-  ]
-
-  deps = [
-    "../../gn:default_deps",
-    "../base",
-    "../protozero",
-  ]
-}
-
-if (enable_perfetto_trace_processor_metrics) {  # shell requires metrics.
-  perfetto_host_executable("trace_processor_shell") {
+if (current_toolchain == host_toolchain) {
+  executable("trace_processor_shell_host") {
     deps = [
       ":lib",
       "../../gn:default_deps",
-      "../../gn:protoc_lib",
       "../base",
-      "metrics:lib",
     ]
-    if (enable_perfetto_version_gen) {
-      deps += [ "../../gn/standalone:gen_git_revision" ]
-    }
-    if (enable_perfetto_trace_processor_linenoise) {
-      deps += [ "../../gn:linenoise" ]
-    }
-    if (enable_perfetto_trace_processor_httpd) {
-      deps += [ "rpc:httpd" ]
+    if (perfetto_build_standalone) {
+      deps += [
+        "../../buildtools:linenoise",
+        "../../gn/standalone:gen_git_revision",
+      ]
     }
     sources = [
-      "proto_to_json.cc",
-      "proto_to_json.h",
       "trace_processor_shell.cc",
     ]
   }
 }
 
-perfetto_unittest_source_set("unittests") {
+copy("trace_processor_shell") {
+  host_out_dir_ = get_label_info(":trace_processor_shell_host($host_toolchain)",
+                                 "root_out_dir")
+  deps = [
+    ":trace_processor_shell_host($host_toolchain)",
+  ]
+  sources = [
+    "${host_out_dir_}/trace_processor_shell_host",
+  ]
+  outputs = [
+    "${root_out_dir}/trace_processor_shell",
+  ]
+}
+
+source_set("unittests") {
   testonly = true
   sources = [
     "clock_tracker_unittest.cc",
     "event_tracker_unittest.cc",
-    "forwarding_trace_parser_unittest.cc",
+    "filtered_row_index_unittest.cc",
+    "ftrace_utils_unittest.cc",
     "heap_profile_tracker_unittest.cc",
-    "importers/proto/proto_trace_parser_unittest.cc",
-    "importers/systrace/systrace_parser_unittest.cc",
     "null_term_string_view_unittest.cc",
+    "process_table_unittest.cc",
     "process_tracker_unittest.cc",
+    "proto_trace_parser_unittest.cc",
+    "query_constraints_unittest.cc",
+    "sched_slice_table_unittest.cc",
     "slice_tracker_unittest.cc",
+    "span_join_operator_table_unittest.cc",
+    "sqlite3_str_split_unittest.cc",
     "string_pool_unittest.cc",
+    "syscall_tracker_unittest.cc",
+    "thread_table_unittest.cc",
+    "trace_processor_impl_unittest.cc",
     "trace_sorter_unittest.cc",
   ]
   deps = [
-    ":common",
-    ":storage",
+    ":lib",
+    "../../buildtools:sqlite",
     "../../gn:default_deps",
-    "../../gn:gtest_and_gmock",
+    "../../gn:gtest_deps",
     "../../protos/perfetto/common:zero",
-    "../../protos/perfetto/trace:minimal_zero",
     "../../protos/perfetto/trace:zero",
-    "../../protos/perfetto/trace/android:zero",
-    "../../protos/perfetto/trace/chrome:zero",
     "../../protos/perfetto/trace/ftrace:zero",
-    "../../protos/perfetto/trace/gpu:zero",
     "../../protos/perfetto/trace/interned_data:zero",
-    "../../protos/perfetto/trace/profiling:zero",
     "../../protos/perfetto/trace/ps:zero",
     "../../protos/perfetto/trace/sys_stats:zero",
     "../../protos/perfetto/trace/track_event:zero",
     "../base",
     "../protozero",
-    "db:unittests",
-    "tables:unittests",
   ]
-  if (enable_perfetto_trace_processor_sqlite) {
+  if (perfetto_build_standalone) {
     sources += [
-      "args_table_unittest.cc",
-      "filtered_row_index_unittest.cc",
-      "metadata_table_unittest.cc",
-      "process_table_unittest.cc",
-      "span_join_operator_table_unittest.cc",
+      "json_trace_tokenizer_unittest.cc",
+      "json_trace_utils_unittest.cc",
     ]
-    deps += [
-      ":lib",
-      "../../gn:sqlite",
-      "sqlite",
-      "sqlite:unittests",
-    ]
-  }
-  if (enable_perfetto_trace_processor_json) {
-    if (enable_perfetto_trace_processor_json_import) {
-      sources += [
-        "importers/json/json_trace_tokenizer_unittest.cc",
-        "importers/json/json_trace_utils_unittest.cc",
-      ]
-      deps += [ "../../gn:jsoncpp" ]
-    }
-    if (!is_win) {
-      # export_json_unittest.cc uses base::TempFile, which is not supported on
-      # windows.
-      sources += [ "export_json_unittest.cc" ]
-      deps += [
-        ":export_json",
-        "../../gn:jsoncpp",
-        "../../include/perfetto/ext/trace_processor:export_json",
-      ]
-    }
-  }
-  if (enable_perfetto_trace_processor_ftrace) {
-    sources += [
-      "ftrace_utils_unittest.cc",
-      "sched_slice_table_unittest.cc",
-      "thread_table_unittest.cc",
-    ]
-  }
-  if (enable_perfetto_trace_processor_heap_graphs) {
-    sources += [ "importers/proto/heap_graph_walker_unittest.cc" ]
-  }
-  if (enable_perfetto_trace_processor_fuchsia) {
-    sources += [ "importers/fuchsia/fuchsia_trace_utils_unittest.cc" ]
-  }
-  if (enable_perfetto_trace_processor_syscalls) {
-    sources += [ "syscall_tracker_unittest.cc" ]
+    deps += [ "../../gn:jsoncpp_deps" ]
   }
 }
 
 source_set("integrationtests") {
   testonly = true
-  sources = []
-  deps = []
-  if (enable_perfetto_trace_processor_sqlite) {
-    sources += [ "trace_database_integrationtest.cc" ]
-    deps += [
-      ":lib",
-      ":storage",
-      "../../gn:default_deps",
-      "../../gn:gtest_and_gmock",
-      "../../protos/perfetto/trace:lite",
-      "../base",
-      "../base:test_support",
-      "sqlite",
-    ]
-
-    if (enable_perfetto_trace_processor_json_import) {
-      deps += [ "../../gn:jsoncpp" ]
-    }
+  sources = [
+    "trace_database_integrationtest.cc",
+  ]
+  deps = [
+    ":lib",
+    "../../buildtools:sqlite",
+    "../../gn:default_deps",
+    "../../gn:gtest_deps",
+    "../../protos/perfetto/trace:lite",
+    "../../protos/perfetto/trace_processor:lite",
+    "../base",
+    "../base:test_support",
+  ]
+  if (perfetto_build_standalone) {
+    deps += [ "../../gn:jsoncpp_deps" ]
   }
 }
 
@@ -472,8 +287,14 @@
     "trace_parsing_fuzzer.cc",
   ]
   deps = [
-    ":storage",
+    ":lib",
+    "../../../../gn:default_deps",
+    "../../buildtools:sqlite",
     "../../gn:default_deps",
+    "../../gn:gtest_deps",
+    "../../protos/perfetto/trace:lite",
+    "../../protos/perfetto/trace_processor:lite",
     "../base",
+    "../base:test_support",
   ]
 }
diff --git a/src/trace_processor/android_logs_table.cc b/src/trace_processor/android_logs_table.cc
index d58508b..ada0da2 100644
--- a/src/trace_processor/android_logs_table.cc
+++ b/src/trace_processor/android_logs_table.cc
@@ -23,7 +23,7 @@
     : storage_(storage) {}
 
 void AndroidLogsTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
-  SqliteTable::Register<AndroidLogsTable>(db, storage, "android_logs");
+  Table::Register<AndroidLogsTable>(db, storage, "android_logs");
 }
 
 StorageSchema AndroidLogsTable::CreateStorageSchema() {
@@ -47,13 +47,14 @@
 int AndroidLogsTable::BestIndex(const QueryConstraints& qc,
                                 BestIndexInfo* info) {
   info->estimated_cost = static_cast<uint32_t>(storage_->android_logs().size());
-  info->sqlite_omit_order_by = true;
+
+  info->order_by_consumed = true;
 
   // Only the string columns are handled by SQLite.
   size_t tag_index = schema().ColumnIndexFromName("tag");
   size_t msg_index = schema().ColumnIndexFromName("msg");
   for (size_t i = 0; i < qc.constraints().size(); i++) {
-    info->constraint_info[i].sqlite_omit =
+    info->omit[i] =
         qc.constraints()[i].iColumn != static_cast<int>(tag_index) &&
         qc.constraints()[i].iColumn != static_cast<int>(msg_index);
   }
diff --git a/src/trace_processor/args_table.cc b/src/trace_processor/args_table.cc
index 64b407c..b628d14 100644
--- a/src/trace_processor/args_table.cc
+++ b/src/trace_processor/args_table.cc
@@ -16,62 +16,27 @@
 
 #include "src/trace_processor/args_table.h"
 
-#include "src/trace_processor/sqlite/sqlite_utils.h"
+#include "src/trace_processor/sqlite_utils.h"
 
 namespace perfetto {
 namespace trace_processor {
 
-namespace {
-PERFETTO_ALWAYS_INLINE
-bool TreatedAsInteger(Variadic v) {
-  return v.type == Variadic::Type::kInt || v.type == Variadic::Type::kBool ||
-         v.type == Variadic::Type::kPointer || v.type == Variadic::Type::kUint;
-}
-
-PERFETTO_ALWAYS_INLINE
-bool TreatedAsString(Variadic v) {
-  return v.type == Variadic::Type::kString || v.type == Variadic::Type::kJson;
-}
-
-PERFETTO_ALWAYS_INLINE
-int64_t AsInt64(Variadic v) {
-  if (v.type == Variadic::Type::kInt)
-    return v.int_value;
-  if (v.type == Variadic::Type::kBool)
-    return static_cast<int64_t>(v.bool_value);
-  if (v.type == Variadic::Type::kUint)
-    return static_cast<int64_t>(v.uint_value);
-  if (v.type == Variadic::Type::kPointer)
-    return static_cast<int64_t>(v.pointer_value);
-  PERFETTO_FATAL("invalid Variadic type");
-}
-
-PERFETTO_ALWAYS_INLINE
-StringId AsStringId(Variadic v) {
-  if (v.type == Variadic::Type::kString)
-    return v.string_value;
-  if (v.type == Variadic::Type::kJson)
-    return v.json_value;
-  PERFETTO_FATAL("invalid Variadic type");
-}
-}  // namespace
-
 ArgsTable::ArgsTable(sqlite3*, const TraceStorage* storage)
     : storage_(storage) {}
 
 void ArgsTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
-  SqliteTable::Register<ArgsTable>(db, storage, "args");
+  Table::Register<ArgsTable>(db, storage, "args");
 }
 
 StorageSchema ArgsTable::CreateStorageSchema() {
   const auto& args = storage_->args();
   return StorageSchema::Builder()
-      .AddOrderedNumericColumn("arg_set_id", &args.set_ids())
+      .AddNumericColumn("arg_set_id", &args.set_ids())
       .AddStringColumn("flat_key", &args.flat_keys(), &storage_->string_pool())
       .AddStringColumn("key", &args.keys(), &storage_->string_pool())
-      .AddColumn<ValueColumn>("int_value", Variadic::Type::kInt, storage_)
-      .AddColumn<ValueColumn>("string_value", Variadic::Type::kString, storage_)
-      .AddColumn<ValueColumn>("real_value", Variadic::Type::kReal, storage_)
+      .AddColumn<ValueColumn>("int_value", VariadicType::kInt, storage_)
+      .AddColumn<ValueColumn>("string_value", VariadicType::kString, storage_)
+      .AddColumn<ValueColumn>("real_value", VariadicType::kReal, storage_)
       .Build({"arg_set_id", "key"});
 }
 
@@ -80,65 +45,48 @@
 }
 
 int ArgsTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
-  if (HasEqConstraint(qc, "arg_set_id")) {
-    info->estimated_cost = 1;
-  } else {
-    info->estimated_cost = static_cast<uint32_t>(storage_->args().args_count());
+  // In the case of an id equality filter, we can do a very efficient lookup.
+  if (qc.constraints().size() == 1) {
+    auto id = static_cast<int>(schema().ColumnIndexFromName("arg_set_id"));
+    const auto& cs = qc.constraints().back();
+    if (cs.iColumn == id && sqlite_utils::IsOpEq(cs.op)) {
+      info->estimated_cost = 1;
+      return SQLITE_OK;
+    }
   }
+
+  // Otherwise, just give the worst case scenario.
+  info->estimated_cost = static_cast<uint32_t>(storage_->args().args_count());
   return SQLITE_OK;
 }
 
 ArgsTable::ValueColumn::ValueColumn(std::string col_name,
-                                    Variadic::Type type,
+                                    VariadicType type,
                                     const TraceStorage* storage)
     : StorageColumn(col_name, false /* hidden */),
       type_(type),
-      storage_(storage) {
-  PERFETTO_CHECK(type == Variadic::Type::kInt ||
-                 type == Variadic::Type::kReal ||
-                 type == Variadic::Type::kString);
-}
+      storage_(storage) {}
 
 void ArgsTable::ValueColumn::ReportResult(sqlite3_context* ctx,
                                           uint32_t row) const {
   const auto& value = storage_->args().arg_values()[row];
+  if (value.type != type_) {
+    sqlite3_result_null(ctx);
+    return;
+  }
+
   switch (type_) {
-    // Integer column, returns all integer-like variadic values (as an int64_t).
-    case Variadic::Type::kInt: {
-      if (!TreatedAsInteger(value)) {
-        sqlite3_result_null(ctx);
-        return;
-      }
-      sqlite_utils::ReportSqliteResult(ctx, AsInt64(value));
-      return;
-    }
-
-      // Float column, returns only float values.
-    case Variadic::Type::kReal: {
-      if (value.type != Variadic::Type::kReal) {
-        sqlite3_result_null(ctx);
-        return;
-      }
+    case VariadicType::kInt:
+      sqlite_utils::ReportSqliteResult(ctx, value.int_value);
+      break;
+    case VariadicType::kReal:
       sqlite_utils::ReportSqliteResult(ctx, value.real_value);
-      return;
-    }
-
-      // String column, returns string & json variadic values (as a string).
-    case Variadic::Type::kString: {
-      if (!TreatedAsString(value)) {
-        sqlite3_result_null(ctx);
-        return;
-      }
-      const char* str = storage_->GetString(AsStringId(value)).c_str();
+      break;
+    case VariadicType::kString: {
+      const char* str = storage_->GetString(value.string_value).c_str();
       sqlite3_result_text(ctx, str, -1, sqlite_utils::kSqliteStatic);
-      return;
+      break;
     }
-
-    case Variadic::Type::kBool:
-    case Variadic::Type::kUint:
-    case Variadic::Type::kPointer:
-    case Variadic::Type::kJson:
-      PERFETTO_FATAL("Unexpected column type");
   }
 }
 
@@ -152,52 +100,37 @@
                                     sqlite3_value* value,
                                     FilteredRowIndex* index) const {
   switch (type_) {
-    // Integer column, returns all integer-like variadic values (as an int64_t).
-    case Variadic::Type::kInt: {
+    case VariadicType::kInt: {
       bool op_is_null = sqlite_utils::IsOpIsNull(op);
       auto predicate = sqlite_utils::CreateNumericPredicate<int64_t>(op, value);
       index->FilterRows(
           [this, predicate, op_is_null](uint32_t row) PERFETTO_ALWAYS_INLINE {
-            const Variadic& arg = storage_->args().arg_values()[row];
-            if (!TreatedAsInteger(arg)) {
-              return op_is_null;
-            }
-            return predicate(AsInt64(arg));
+            const auto& arg = storage_->args().arg_values()[row];
+            return arg.type == type_ ? predicate(arg.int_value) : op_is_null;
           });
       break;
     }
-
-    // Float column, returns only float values.
-    case Variadic::Type::kReal: {
+    case VariadicType::kReal: {
       bool op_is_null = sqlite_utils::IsOpIsNull(op);
       auto predicate = sqlite_utils::CreateNumericPredicate<double>(op, value);
       index->FilterRows(
           [this, predicate, op_is_null](uint32_t row) PERFETTO_ALWAYS_INLINE {
             const auto& arg = storage_->args().arg_values()[row];
-            return arg.type == Variadic::Type::kReal ? predicate(arg.real_value)
-                                                     : op_is_null;
+            return arg.type == type_ ? predicate(arg.real_value) : op_is_null;
           });
       break;
     }
-
-    // String column, returns string & json variadic values (as a string).
-    case Variadic::Type::kString: {
+    case VariadicType::kString: {
       auto predicate = sqlite_utils::CreateStringPredicate(op, value);
-      index->FilterRows(
-          [this, &predicate](uint32_t row) PERFETTO_ALWAYS_INLINE {
-            const auto& arg = storage_->args().arg_values()[row];
-            if (!TreatedAsString(arg)) {
-              return predicate(nullptr);
-            }
-            return predicate(storage_->GetString(AsStringId(arg)).c_str());
-          });
+      index->FilterRows([this,
+                         &predicate](uint32_t row) PERFETTO_ALWAYS_INLINE {
+        const auto& arg = storage_->args().arg_values()[row];
+        return arg.type == type_
+                   ? predicate(storage_->GetString(arg.string_value).c_str())
+                   : predicate(nullptr);
+      });
       break;
     }
-    case Variadic::Type::kBool:
-    case Variadic::Type::kUint:
-    case Variadic::Type::kPointer:
-    case Variadic::Type::kJson:
-      PERFETTO_FATAL("Unexpected column type");
   }
 }
 
@@ -212,53 +145,26 @@
 int ArgsTable::ValueColumn::CompareRefsAsc(uint32_t f, uint32_t s) const {
   const auto& arg_f = storage_->args().arg_values()[f];
   const auto& arg_s = storage_->args().arg_values()[s];
-  switch (type_) {
-    // Integer column, returns all integer-like variadic values (as an int64_t).
-    case Variadic::Type::kInt: {
-      if (TreatedAsInteger(arg_f) && TreatedAsInteger(arg_s)) {
-        return sqlite_utils::CompareValuesAsc(AsInt64(arg_f), AsInt64(arg_s));
-      } else if (TreatedAsInteger(arg_f)) {
-        return 1;  // second value treated as null
-      } else if (TreatedAsInteger(arg_s)) {
-        return -1;  // first value treated as null
-      }
-      return 0;
-    }
 
-    // Float column, returns only float values.
-    case Variadic::Type::kReal: {
-      if (arg_f.type == Variadic::Type::kReal &&
-          arg_s.type == Variadic::Type::kReal) {
+  if (arg_f.type == type_ && arg_s.type == type_) {
+    switch (type_) {
+      case VariadicType::kInt:
+        return sqlite_utils::CompareValuesAsc(arg_f.int_value, arg_s.int_value);
+      case VariadicType::kReal:
         return sqlite_utils::CompareValuesAsc(arg_f.real_value,
                                               arg_s.real_value);
-      } else if (arg_f.type == Variadic::Type::kReal) {
-        return 1;  // second value treated as null
-      } else if (arg_s.type == Variadic::Type::kReal) {
-        return -1;  // first value treated as null
-      }
-      return 0;
-    }
-
-    // String column, returns string & json variadic values (as a string).
-    case Variadic::Type::kString: {
-      if (TreatedAsString(arg_f) && TreatedAsString(arg_s)) {
-        const auto& f_str = storage_->GetString(AsStringId(arg_f));
-        const auto& s_str = storage_->GetString(AsStringId(arg_s));
+      case VariadicType::kString: {
+        const auto& f_str = storage_->GetString(arg_f.string_value);
+        const auto& s_str = storage_->GetString(arg_s.string_value);
         return sqlite_utils::CompareValuesAsc(f_str, s_str);
-      } else if (TreatedAsString(arg_f)) {
-        return 1;  // second value treated as null
-      } else if (TreatedAsString(arg_s)) {
-        return -1;  // first value treated as null
       }
-      return 0;
     }
-    case Variadic::Type::kBool:
-    case Variadic::Type::kUint:
-    case Variadic::Type::kPointer:
-    case Variadic::Type::kJson:
-      PERFETTO_FATAL("Unexpected column type");
+  } else if (arg_s.type == type_) {
+    return -1;
+  } else if (arg_f.type == type_) {
+    return 1;
   }
-  PERFETTO_FATAL("Never reached");  // for gcc
+  return 0;
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/args_table.h b/src/trace_processor/args_table.h
index 8243457..35a3db1 100644
--- a/src/trace_processor/args_table.h
+++ b/src/trace_processor/args_table.h
@@ -19,13 +19,14 @@
 
 #include "src/trace_processor/storage_table.h"
 #include "src/trace_processor/trace_storage.h"
-#include "src/trace_processor/variadic.h"
 
 namespace perfetto {
 namespace trace_processor {
 
 class ArgsTable : public StorageTable {
  public:
+  using VariadicType = TraceStorage::Args::Variadic::Type;
+
   static void RegisterTable(sqlite3* db, const TraceStorage* storage);
 
   ArgsTable(sqlite3*, const TraceStorage*);
@@ -39,7 +40,7 @@
   class ValueColumn final : public StorageColumn {
    public:
     ValueColumn(std::string col_name,
-                Variadic::Type type,
+                VariadicType type,
                 const TraceStorage* storage);
 
     void ReportResult(sqlite3_context* ctx, uint32_t row) const override;
@@ -52,18 +53,14 @@
 
     bool HasOrdering() const override { return false; }
 
-    SqlValue::Type GetType() const override {
+    Table::ColumnType GetType() const override {
       switch (type_) {
-        case Variadic::Type::kInt:
-        case Variadic::Type::kUint:
-        case Variadic::Type::kPointer:
-        case Variadic::Type::kBool:
-          return SqlValue::Type::kLong;
-        case Variadic::Type::kJson:
-        case Variadic::Type::kString:
-          return SqlValue::Type::kString;
-        case Variadic::Type::kReal:
-          return SqlValue::Type::kDouble;
+        case VariadicType::kInt:
+          return Table::ColumnType::kLong;
+        case VariadicType::kReal:
+          return Table::ColumnType::kDouble;
+        case VariadicType::kString:
+          return Table::ColumnType::kString;
       }
       PERFETTO_FATAL("Not reached");  // For gcc
     }
@@ -71,7 +68,7 @@
    private:
     int CompareRefsAsc(uint32_t f, uint32_t s) const;
 
-    Variadic::Type type_;
+    TraceStorage::Args::Variadic::Type type_;
     const TraceStorage* storage_ = nullptr;
   };
 
diff --git a/src/trace_processor/args_table_unittest.cc b/src/trace_processor/args_table_unittest.cc
deleted file mode 100644
index de6bec7..0000000
--- a/src/trace_processor/args_table_unittest.cc
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * 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.
- */
-
-#include "src/trace_processor/args_table.h"
-#include "src/trace_processor/sqlite/scoped_db.h"
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/trace_storage.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-class ArgsTableUnittest : public ::testing::Test {
- public:
-  ArgsTableUnittest() {
-    sqlite3* db = nullptr;
-    PERFETTO_CHECK(sqlite3_initialize() == SQLITE_OK);
-    PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
-    db_.reset(db);
-
-    context_.storage.reset(new TraceStorage());
-    ArgsTable::RegisterTable(db_.get(), context_.storage.get());
-  }
-
-  void PrepareValidStatement(const std::string& sql) {
-    int size = static_cast<int>(sql.size());
-    sqlite3_stmt* stmt;
-    ASSERT_EQ(sqlite3_prepare_v2(*db_, sql.c_str(), size, &stmt, nullptr),
-              SQLITE_OK);
-    stmt_.reset(stmt);
-  }
-
-  const char* GetColumnAsText(int colId) {
-    return reinterpret_cast<const char*>(sqlite3_column_text(*stmt_, colId));
-  }
-
-  void AssertArgRowValues(int arg_set_id,
-                          const char* flat_key,
-                          const char* key,
-                          base::Optional<int64_t> int_value,
-                          base::Optional<const char*> string_value,
-                          base::Optional<double> real_value);
-
- protected:
-  TraceProcessorContext context_;
-  ScopedDb db_;
-  ScopedStmt stmt_;
-};
-
-// Test helper.
-void ArgsTableUnittest::AssertArgRowValues(
-    int arg_set_id,
-    const char* flat_key,
-    const char* key,
-    base::Optional<int64_t> int_value,
-    base::Optional<const char*> string_value,
-    base::Optional<double> real_value) {
-  ASSERT_EQ(sqlite3_column_int(*stmt_, 0), arg_set_id);
-  ASSERT_STREQ(GetColumnAsText(1), flat_key);
-  ASSERT_STREQ(GetColumnAsText(2), key);
-  if (int_value.has_value()) {
-    ASSERT_EQ(sqlite3_column_int64(*stmt_, 3), int_value.value());
-  } else {
-    ASSERT_EQ(sqlite3_column_type(*stmt_, 3), SQLITE_NULL);
-  }
-  if (string_value.has_value()) {
-    ASSERT_STREQ(GetColumnAsText(4), string_value.value());
-  } else {
-    ASSERT_EQ(sqlite3_column_type(*stmt_, 4), SQLITE_NULL);
-  }
-  if (real_value.has_value()) {
-    ASSERT_DOUBLE_EQ(sqlite3_column_double(*stmt_, 5), real_value.value());
-  } else {
-    ASSERT_EQ(sqlite3_column_type(*stmt_, 5), SQLITE_NULL);
-  }
-}
-
-TEST_F(ArgsTableUnittest, IntValue) {
-  static const char kFlatKey[] = "flat_key";
-  static const char kKey[] = "key";
-  static const int kValue = 123;
-
-  TraceStorage::Args::Arg arg;
-  arg.flat_key = context_.storage->InternString(kFlatKey);
-  arg.key = context_.storage->InternString(kKey);
-  arg.value = Variadic::Integer(kValue);
-
-  context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
-
-  PrepareValidStatement("SELECT * FROM args");
-
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  AssertArgRowValues(1, kFlatKey, kKey, kValue, base::nullopt, base::nullopt);
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ArgsTableUnittest, StringValue) {
-  static const char kFlatKey[] = "flat_key";
-  static const char kKey[] = "key";
-  static const char kValue[] = "123";
-
-  TraceStorage::Args::Arg arg;
-  arg.flat_key = context_.storage->InternString(kFlatKey);
-  arg.key = context_.storage->InternString(kKey);
-  arg.value = Variadic::String(context_.storage->InternString(kValue));
-
-  context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
-
-  PrepareValidStatement("SELECT * FROM args");
-
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  AssertArgRowValues(1, kFlatKey, kKey, base::nullopt, kValue, base::nullopt);
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ArgsTableUnittest, RealValue) {
-  static const char kFlatKey[] = "flat_key";
-  static const char kKey[] = "key";
-  static const double kValue = 0.123;
-
-  TraceStorage::Args::Arg arg;
-  arg.flat_key = context_.storage->InternString(kFlatKey);
-  arg.key = context_.storage->InternString(kKey);
-  arg.value = Variadic::Real(kValue);
-
-  context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
-
-  PrepareValidStatement("SELECT * FROM args");
-
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  AssertArgRowValues(1, kFlatKey, kKey, base::nullopt, base::nullopt, kValue);
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ArgsTableUnittest, BoolValueTreatedAsInt) {
-  static const char kFlatKey[] = "flat_key";
-  static const char kKey[] = "key";
-  static const bool kValue = true;
-
-  TraceStorage::Args::Arg arg;
-  arg.flat_key = context_.storage->InternString(kFlatKey);
-  arg.key = context_.storage->InternString(kKey);
-  arg.value = Variadic::Boolean(kValue);
-
-  context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
-
-  // Boolean returned in the "int_value" column, and is comparable to an integer
-  // literal.
-  PrepareValidStatement("SELECT * FROM args WHERE int_value = 1");
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  AssertArgRowValues(1, kFlatKey, kKey, kValue, base::nullopt, base::nullopt);
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ArgsTableUnittest, PointerValueTreatedAsInt) {
-  static const uint64_t kSmallValue = 1ull << 30;
-  static const uint64_t kTopBitSetValue = 1ull << 63;
-
-  TraceStorage::Args::Arg arg;
-  arg.flat_key = context_.storage->InternString("flat_key_small");
-  arg.key = context_.storage->InternString("key_small");
-  arg.value = Variadic::Pointer(kSmallValue);
-
-  TraceStorage::Args::Arg arg2;
-  arg2.flat_key = context_.storage->InternString("flat_key_large");
-  arg2.key = context_.storage->InternString("key_large");
-  arg2.value = Variadic::Pointer(kTopBitSetValue);
-
-  context_.storage->mutable_args()->AddArgSet({arg, arg2}, 0, 2);
-
-  // Pointer returned in the "int_value" column, as a signed 64 bit. And is
-  // comparable to an integer literal.
-
-  static const int64_t kExpectedSmallValue = static_cast<int64_t>(kSmallValue);
-  PrepareValidStatement(std::string("SELECT * FROM args WHERE int_value = ") +
-                        std::to_string(kExpectedSmallValue));
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  AssertArgRowValues(1, "flat_key_small", "key_small", kExpectedSmallValue,
-                     base::nullopt, base::nullopt);
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-
-  static const int64_t kExpectedTopBitSetValue =
-      static_cast<int64_t>(kTopBitSetValue);  // negative
-  PrepareValidStatement(std::string("SELECT * FROM args WHERE int_value = ") +
-                        std::to_string(kExpectedTopBitSetValue));
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  AssertArgRowValues(1, "flat_key_large", "key_large", kExpectedTopBitSetValue,
-                     base::nullopt, base::nullopt);
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ArgsTableUnittest, UintValueTreatedAsInt) {
-  static const uint64_t kSmallValue = 1ull << 30;
-  static const uint64_t kTopBitSetValue = 1ull << 63;
-
-  TraceStorage::Args::Arg arg;
-  arg.flat_key = context_.storage->InternString("flat_key_small");
-  arg.key = context_.storage->InternString("key_small");
-  arg.value = Variadic::UnsignedInteger(kSmallValue);
-
-  TraceStorage::Args::Arg arg2;
-  arg2.flat_key = context_.storage->InternString("flat_key_large");
-  arg2.key = context_.storage->InternString("key_large");
-  arg2.value = Variadic::UnsignedInteger(kTopBitSetValue);
-
-  context_.storage->mutable_args()->AddArgSet({arg, arg2}, 0, 2);
-
-  // Unsigned returned in the "int_value" column, as a signed 64 bit. And is
-  // comparable to an integer literal.
-
-  static const int64_t kExpectedSmallValue = static_cast<int64_t>(kSmallValue);
-  PrepareValidStatement(std::string("SELECT * FROM args WHERE int_value = ") +
-                        std::to_string(kExpectedSmallValue));
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  AssertArgRowValues(1, "flat_key_small", "key_small", kExpectedSmallValue,
-                     base::nullopt, base::nullopt);
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-
-  static const int64_t kExpectedTopBitSetValue =
-      static_cast<int64_t>(kTopBitSetValue);  // negative
-  PrepareValidStatement(std::string("SELECT * FROM args WHERE int_value = ") +
-                        std::to_string(kExpectedTopBitSetValue));
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  AssertArgRowValues(1, "flat_key_large", "key_large", kExpectedTopBitSetValue,
-                     base::nullopt, base::nullopt);
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ArgsTableUnittest, IntegerLikeValuesSortByIntRepresentation) {
-  static const char kFlatKey[] = "flat_key";
-  static const char kKey[] = "key";
-
-  TraceStorage::Args::Arg bool_arg_true;
-  bool_arg_true.flat_key = context_.storage->InternString(kFlatKey);
-  bool_arg_true.key = context_.storage->InternString(kKey);
-  bool_arg_true.value = Variadic::Boolean(true);
-
-  TraceStorage::Args::Arg bool_arg_false;
-  bool_arg_false.flat_key = context_.storage->InternString(kFlatKey);
-  bool_arg_false.key = context_.storage->InternString(kKey);
-  bool_arg_false.value = Variadic::Boolean(false);
-
-  TraceStorage::Args::Arg pointer_arg_42;
-  pointer_arg_42.flat_key = context_.storage->InternString(kFlatKey);
-  pointer_arg_42.key = context_.storage->InternString(kKey);
-  pointer_arg_42.value = Variadic::Pointer(42);
-
-  TraceStorage::Args::Arg unsigned_arg_10;
-  unsigned_arg_10.flat_key = context_.storage->InternString(kFlatKey);
-  unsigned_arg_10.key = context_.storage->InternString(kKey);
-  unsigned_arg_10.value = Variadic::UnsignedInteger(10);
-
-  // treated as null by the int_value column
-  TraceStorage::Args::Arg string_arg;
-  string_arg.flat_key = context_.storage->InternString(kFlatKey);
-  string_arg.key = context_.storage->InternString(kKey);
-  string_arg.value =
-      Variadic::String(context_.storage->InternString("string_content"));
-
-  context_.storage->mutable_args()->AddArgSet(
-      {bool_arg_true, bool_arg_false, pointer_arg_42, unsigned_arg_10,
-       string_arg},
-      0, 5);
-
-  // Ascending sort by int representations:
-  // { null (string), 0 (false), 1 (true), 10, 42 }
-  PrepareValidStatement("SELECT * FROM args ORDER BY int_value ASC");
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  AssertArgRowValues(1, kFlatKey, kKey, base::nullopt, "string_content",
-                     base::nullopt);
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  AssertArgRowValues(1, kFlatKey, kKey, 0, base::nullopt, base::nullopt);
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  AssertArgRowValues(1, kFlatKey, kKey, 1, base::nullopt, base::nullopt);
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  AssertArgRowValues(1, kFlatKey, kKey, 10, base::nullopt, base::nullopt);
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  AssertArgRowValues(1, kFlatKey, kKey, 42, base::nullopt, base::nullopt);
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-
-  // Desceding order.
-  PrepareValidStatement("SELECT * FROM args ORDER BY int_value DESC");
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  AssertArgRowValues(1, kFlatKey, kKey, 42, base::nullopt, base::nullopt);
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  AssertArgRowValues(1, kFlatKey, kKey, 10, base::nullopt, base::nullopt);
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  AssertArgRowValues(1, kFlatKey, kKey, 1, base::nullopt, base::nullopt);
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  AssertArgRowValues(1, kFlatKey, kKey, 0, base::nullopt, base::nullopt);
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  AssertArgRowValues(1, kFlatKey, kKey, base::nullopt, "string_content",
-                     base::nullopt);
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/args_tracker.cc b/src/trace_processor/args_tracker.cc
index 48d6e53..af279c8 100644
--- a/src/trace_processor/args_tracker.cc
+++ b/src/trace_processor/args_tracker.cc
@@ -23,10 +23,6 @@
 
 ArgsTracker::ArgsTracker(TraceProcessorContext* context) : context_(context) {}
 
-ArgsTracker::~ArgsTracker() {
-  Flush();
-}
-
 void ArgsTracker::AddArg(RowId row_id,
                          StringId flat_key,
                          StringId key,
@@ -43,15 +39,12 @@
 void ArgsTracker::Flush() {
   using Arg = TraceStorage::Args::Arg;
 
-  if (args_.empty())
-    return;
-
   // We sort here because a single packet may add multiple args with different
   // rowids.
   auto comparator = [](const Arg& f, const Arg& s) {
     return f.row_id < s.row_id;
   };
-  std::stable_sort(args_.begin(), args_.end(), comparator);
+  std::sort(args_.begin(), args_.end(), comparator);
 
   auto* storage = context_->storage.get();
   for (uint32_t i = 0; i < args_.size();) {
@@ -62,37 +55,17 @@
     while (next_rid_idx < args_.size() && rid == args_[next_rid_idx].row_id)
       next_rid_idx++;
 
-    ArgSetId set_id =
-        storage->mutable_args()->AddArgSet(args_, i, next_rid_idx);
-    auto parsed = TraceStorage::ParseRowId(rid);
-    auto table_id = parsed.first;
-    auto row = parsed.second;
-    switch (table_id) {
+    auto set_id = storage->mutable_args()->AddArgSet(args_, i, next_rid_idx);
+    auto pair = TraceStorage::ParseRowId(rid);
+    switch (pair.first) {
       case TableId::kRawEvents:
-        storage->mutable_raw_events()->set_arg_set_id(row, set_id);
+        storage->mutable_raw_events()->set_arg_set_id(pair.second, set_id);
         break;
       case TableId::kCounterValues:
-        storage->mutable_counter_values()->set_arg_set_id(row, set_id);
+        storage->mutable_counter_values()->set_arg_set_id(pair.second, set_id);
         break;
       case TableId::kInstants:
-        storage->mutable_instants()->set_arg_set_id(row, set_id);
-        break;
-      case TableId::kNestableSlices:
-        storage->mutable_nestable_slices()->set_arg_set_id(row, set_id);
-        break;
-      // Special case: overwrites the metadata table row.
-      case TableId::kMetadataTable:
-        storage->mutable_metadata()->OverwriteMetadata(
-            row, Variadic::Integer(set_id));
-        break;
-      case TableId::kTrack:
-        storage->mutable_track_table()->mutable_source_arg_set_id()->Set(
-            row, set_id);
-        break;
-      case TableId::kVulkanMemoryAllocation:
-        storage->mutable_vulkan_memory_allocations_table()
-            ->mutable_arg_set_id()
-            ->Set(row, set_id);
+        storage->mutable_instants()->set_arg_set_id(pair.second, set_id);
         break;
       default:
         PERFETTO_FATAL("Unsupported table to insert args into");
diff --git a/src/trace_processor/args_tracker.h b/src/trace_processor/args_tracker.h
index 7eb27d7..c01b8e1 100644
--- a/src/trace_processor/args_tracker.h
+++ b/src/trace_processor/args_tracker.h
@@ -19,7 +19,6 @@
 
 #include "src/trace_processor/trace_processor_context.h"
 #include "src/trace_processor/trace_storage.h"
-#include "src/trace_processor/variadic.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -28,16 +27,15 @@
 // allows args to pushed as a group into storage.
 class ArgsTracker {
  public:
+  using Variadic = TraceStorage::Args::Variadic;
+
   explicit ArgsTracker(TraceProcessorContext*);
-  virtual ~ArgsTracker();
 
   // Adds a arg for this row id with the given key and value.
-  // Virtual for testing.
-  virtual void AddArg(RowId row_id, StringId flat_key, StringId key, Variadic);
+  void AddArg(RowId row_id, StringId flat_key, StringId key, Variadic);
 
   // Commits the added args to storage.
-  // Virtual for testing.
-  virtual void Flush();
+  void Flush();
 
  private:
   std::vector<TraceStorage::Args::Arg> args_;
diff --git a/src/trace_processor/binder_tracker.cc b/src/trace_processor/binder_tracker.cc
deleted file mode 100644
index 2bc39535..0000000
--- a/src/trace_processor/binder_tracker.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/binder_tracker.h"
-
-#include "perfetto/base/compiler.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-BinderTracker::BinderTracker(TraceProcessorContext* context)
-    : context_(context) {}
-
-BinderTracker::~BinderTracker() = default;
-
-void BinderTracker::Transaction(int64_t ts, uint32_t pid) {
-  base::ignore_result(context_);
-  base::ignore_result(ts);
-  base::ignore_result(pid);
-}
-
-void BinderTracker::Lock(int64_t ts, uint32_t pid) {
-  base::ignore_result(ts);
-  base::ignore_result(pid);
-}
-
-void BinderTracker::Locked(int64_t ts, uint32_t pid) {
-  base::ignore_result(ts);
-  base::ignore_result(pid);
-}
-
-void BinderTracker::Unlock(int64_t ts, uint32_t pid) {
-  base::ignore_result(ts);
-  base::ignore_result(pid);
-}
-
-void BinderTracker::TransactionReceived(int64_t ts, uint32_t pid) {
-  base::ignore_result(ts);
-  base::ignore_result(pid);
-}
-
-void BinderTracker::TransactionAllocBuf(int64_t ts, uint32_t pid) {
-  base::ignore_result(ts);
-  base::ignore_result(pid);
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/binder_tracker.h b/src/trace_processor/binder_tracker.h
deleted file mode 100644
index c3f1994..0000000
--- a/src/trace_processor/binder_tracker.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_BINDER_TRACKER_H_
-#define SRC_TRACE_PROCESSOR_BINDER_TRACKER_H_
-
-#include <stdint.h>
-
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-class BinderTracker {
- public:
-  explicit BinderTracker(TraceProcessorContext*);
-  virtual ~BinderTracker();
-
-  void Transaction(int64_t timestamp, uint32_t pid);
-  void Locked(int64_t timestamp, uint32_t pid);
-  void Lock(int64_t timestamp, uint32_t pid);
-  void Unlock(int64_t timestamp, uint32_t pid);
-  void TransactionReceived(int64_t timestamp, uint32_t pid);
-  void TransactionAllocBuf(int64_t timestamp, uint32_t pid);
-
- private:
-  TraceProcessorContext* const context_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_BINDER_TRACKER_H_
diff --git a/src/trace_processor/chunked_trace_reader.h b/src/trace_processor/chunked_trace_reader.h
index f09967d..26a6cc3 100644
--- a/src/trace_processor/chunked_trace_reader.h
+++ b/src/trace_processor/chunked_trace_reader.h
@@ -22,9 +22,6 @@
 
 #include <memory>
 
-#include "perfetto/trace_processor/basic_types.h"
-#include "perfetto/trace_processor/status.h"
-
 namespace perfetto {
 namespace trace_processor {
 
@@ -38,7 +35,9 @@
   // caller to match line/protos boundaries. The parser class has to deal with
   // intermediate buffering lines/protos that span across different chunks.
   // The buffer size is guaranteed to be > 0.
-  virtual util::Status Parse(std::unique_ptr<uint8_t[]>, size_t) = 0;
+  // Returns true if the data has been succesfully parsed, false if some
+  // unrecoverable parsing error happened and no more chunks should be pushed.
+  virtual bool Parse(std::unique_ptr<uint8_t[]>, size_t) = 0;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/clock_tracker.cc b/src/trace_processor/clock_tracker.cc
index 87559e0..5692373 100644
--- a/src/trace_processor/clock_tracker.cc
+++ b/src/trace_processor/clock_tracker.cc
@@ -16,209 +16,62 @@
 
 #include "src/trace_processor/clock_tracker.h"
 
-#include <inttypes.h>
-
 #include <algorithm>
-#include <queue>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/hash.h"
 #include "src/trace_processor/trace_processor_context.h"
 #include "src/trace_processor/trace_storage.h"
 
-#include "protos/perfetto/trace/clock_snapshot.pbzero.h"
-
 namespace perfetto {
 namespace trace_processor {
 
-using Clock = protos::pbzero::ClockSnapshot::Clock;
-
-ClockTracker::ClockTracker(TraceProcessorContext* ctx)
-    : context_(ctx), trace_time_clock_id_(Clock::BOOTTIME) {}
-
+ClockTracker::ClockTracker(TraceProcessorContext* ctx) : context_(ctx) {}
 ClockTracker::~ClockTracker() = default;
 
-void ClockTracker::AddSnapshot(const std::map<ClockId, int64_t>& clocks) {
-  const auto snapshot_id = cur_snapshot_id_++;
-
-  // Compute the fingerprint of the snapshot by hashing all clock ids. This is
-  // used by the clock pathfinding logic.
-  base::Hash hasher;
-  for (const auto& id_and_ts : clocks)
-    hasher.Update(id_and_ts.first);
-  const auto snapshot_hash = static_cast<SnapshotHash>(hasher.digest());
-
-  // Add a new entry in each clock's snapshot vector.
-  for (const auto& id_and_ts : clocks) {
-    ClockId clock_id = id_and_ts.first;
-    ClockDomain& clock = clocks_[clock_id];
-    const int64_t timestamp_ns = clock.ToNs(id_and_ts.second);
-    ClockSnapshots& vect = clock.snapshots[snapshot_hash];
-
-    // Clock ids in the range [64, 128) are sequence-scoped and must be
-    // translated to global ids via SeqScopedClockIdToGlobal() before calling
-    // this function.
-    PERFETTO_DCHECK(!IsReservedSeqScopedClockId(clock_id));
-
-    // Snapshot IDs must be always monotonic.
-    PERFETTO_DCHECK(vect.snapshot_ids.empty() ||
-                    vect.snapshot_ids.back() < snapshot_id);
-
-    if (!vect.timestamps_ns.empty() &&
-        timestamp_ns <= vect.timestamps_ns.back()) {
-      // Clock is not monotonic.
-
-      if (clock_id == trace_time_clock_id_) {
-        // The trace clock cannot be non-monotonic.
-        PERFETTO_ELOG(
-            "Clock sync error: the trace clock (id=%" PRIu64
-            ") is not "
-            "monotonic at snapshot %" PRIu32 ". %" PRId64 " not > %" PRId64 ".",
-            clock_id, snapshot_id, timestamp_ns, vect.timestamps_ns.back());
-        context_->storage->IncrementStats(stats::invalid_clock_snapshots);
+void ClockTracker::SyncClocks(ClockDomain domain,
+                              int64_t clock_time_ns,
+                              int64_t trace_time_ns) {
+  ClockSnapshotVector& snapshots = clocks_[domain];
+  if (!snapshots.empty()) {
+    // The trace clock (typically CLOCK_BOOTTIME) must be monotonic.
+    if (trace_time_ns <= snapshots.back().trace_time_ns) {
+      PERFETTO_ELOG("Trace time in clock snapshot is moving backwards");
+      context_->storage->IncrementStats(stats::clock_snapshot_not_monotonic);
+      return;
+    }
+    if (clock_time_ns <= snapshots.back().clock_time_ns) {
+      if (domain == ClockDomain::kMonotonic) {
+        PERFETTO_ELOG("CLOCK_MONOTONIC in clock snapshot is moving backwards");
+        context_->storage->IncrementStats(stats::clock_snapshot_not_monotonic);
         return;
       }
-
-      // For the other clocks the best thing we can do is mark it as
-      // non-monotonic and refuse to use it as a source clock in the resolution
-      // graph. We can still use it as a target clock, but not viceversa.
-      // The concrete example is the CLOCK_REALTIME going 1h backwards during
-      // daylight saving. We can still answer the question "what was the
-      // REALTIME timestamp when BOOTTIME was X?" but we can't answer the
-      // opposite question because there can be two valid BOOTTIME(s) for the
-      // same REALTIME instant because of the 1:many relationship.
-      non_monotonic_clocks_.insert(clock_id);
-
-      // Erase all edges from the graph that start from this clock (but keep the
-      // ones that end on this clock).
-      auto begin = graph_.lower_bound(ClockGraphEdge{clock_id, 0, 0});
-      auto end = graph_.lower_bound(ClockGraphEdge{clock_id + 1, 0, 0});
-      graph_.erase(begin, end);
-    }
-    vect.snapshot_ids.emplace_back(snapshot_id);
-    vect.timestamps_ns.emplace_back(timestamp_ns);
-  }
-
-  // Create graph edges for all the possible tuples of clocks in this snapshot.
-  // If the snapshot contains clock a, b, c, d create edges [ab, ac, ad, bc, bd,
-  // cd] and the symmetrical ones [ba, ca, da, bc, db, dc].
-  // This is to store the information: Clock A is syncable to Clock B via the
-  // snapshots of type (hash).
-  // Clocks that were previously marked as non-monotonic won't be added as
-  // valid sources.
-  for (auto it1 = clocks.begin(); it1 != clocks.end(); ++it1) {
-    auto it2 = it1;
-    ++it2;
-    for (; it2 != clocks.end(); ++it2) {
-      if (!non_monotonic_clocks_.count(it1->first))
-        graph_.emplace(it1->first, it2->first, snapshot_hash);
-
-      if (!non_monotonic_clocks_.count(it2->first))
-        graph_.emplace(it2->first, it1->first, snapshot_hash);
+      // This can happen in other clocks, for instance CLOCK_REALTIME if
+      // adjusting the timezone or during daylight saving. In this case the most
+      // reasonable thing we can do is obliterating all the past snapshots.
+      while (!snapshots.empty() &&
+             snapshots.back().clock_time_ns >= clock_time_ns) {
+        snapshots.pop_back();
+      }
     }
   }
+  snapshots.emplace_back(ClockSnapshot{clock_time_ns, trace_time_ns});
 }
 
-// Finds the shortest clock resolution path in the graph that allows to
-// translate a timestamp from |src| to |target| clocks.
-// The return value looks like the following: "If you want to convert a
-// timestamp from clock C1 to C2 you need to first convert C1 -> C3 using the
-// snapshot hash A, then convert C3 -> C2 via snapshot hash B".
-ClockTracker::ClockPath ClockTracker::FindPath(ClockId src, ClockId target) {
-  // This is a classic breadth-first search. Each node in the queue holds also
-  // the full path to reach that node.
-  // We assume the graph is acyclic, if it isn't the ClockPath::kMaxLen will
-  // stop the search anyways.
-  PERFETTO_CHECK(src != target);
-  std::queue<ClockPath> queue;
-  queue.emplace(src);
-
-  while (!queue.empty()) {
-    ClockPath cur_path = queue.front();
-    queue.pop();
-
-    const ClockId cur_clock_id = cur_path.last;
-    if (cur_clock_id == target)
-      return cur_path;
-
-    if (cur_path.len >= ClockPath::kMaxLen)
-      continue;
-
-    // Expore all the adjacent clocks.
-    // The lower_bound() below returns an iterator to the first edge that starts
-    // on |cur_clock_id|. The edges are sorted by (src, target, hash).
-    for (auto it = std::lower_bound(graph_.begin(), graph_.end(),
-                                    ClockGraphEdge(cur_clock_id, 0, 0));
-         it != graph_.end() && std::get<0>(*it) == cur_clock_id; ++it) {
-      ClockId next_clock_id = std::get<1>(*it);
-      SnapshotHash hash = std::get<2>(*it);
-      queue.push(ClockPath(cur_path, next_clock_id, hash));
-    }
-  }
-  return ClockPath();  // invalid path.
-}
-
-base::Optional<int64_t> ClockTracker::Convert(ClockId src_clock_id,
-                                              int64_t src_timestamp,
-                                              ClockId target_clock_id) {
-  // TODO(primiano): optimization: I bet A simple LRU cache of the form
-  // (src_clock_id, target_clock_id, latest_timestamp, translation_ns) might
-  // speed up most conversion allowing to skip FindPath and the iterations.
-
-  PERFETTO_DCHECK(!IsReservedSeqScopedClockId(src_clock_id));
-  PERFETTO_DCHECK(!IsReservedSeqScopedClockId(target_clock_id));
-
-  ClockPath path = FindPath(src_clock_id, target_clock_id);
-  if (!path.valid()) {
+base::Optional<int64_t> ClockTracker::ToTraceTime(ClockDomain domain,
+                                                  int64_t clock_time_ns) {
+  ClockSnapshotVector& snapshots = clocks_[domain];
+  if (snapshots.empty()) {
     context_->storage->IncrementStats(stats::clock_sync_failure);
     return base::nullopt;
   }
-
-  // Iterate trough the path found and translate timestamps onto the new clock
-  // domain on each step, until the target domain is reached.
-  int64_t ns = GetClock(src_clock_id).ToNs(src_timestamp);
-  for (uint32_t i = 0; i < path.len; ++i) {
-    const ClockGraphEdge edge = path.at(i);
-    const ClockDomain& cur_clock = GetClock(std::get<0>(edge));
-    const ClockDomain& next_clock = GetClock(std::get<1>(edge));
-    const SnapshotHash hash = std::get<2>(edge);
-
-    // Find the closest timestamp within the snapshots of the source clock.
-    const ClockSnapshots& cur_snap = cur_clock.GetSnapshot(hash);
-    const auto& ts_vec = cur_snap.timestamps_ns;
-    auto it = std::upper_bound(ts_vec.begin(), ts_vec.end(), ns);
-    if (it != ts_vec.begin())
-      --it;
-
-    // Now lookup the snapshot id that matches the closest timestamp.
-    size_t index = static_cast<size_t>(std::distance(ts_vec.begin(), it));
-    PERFETTO_DCHECK(index < ts_vec.size());
-    PERFETTO_DCHECK(cur_snap.snapshot_ids.size() == ts_vec.size());
-    uint32_t snapshot_id = cur_snap.snapshot_ids[index];
-
-    // And use that to retrieve the corresponding time in the next clock domain.
-    // The snapshot id must exist in the target clock domain. If it doesn't
-    // either the hash logic or the pathfinding logic are bugged.
-    const ClockSnapshots& next_snap = next_clock.GetSnapshot(hash);
-    auto next_it = std::lower_bound(next_snap.snapshot_ids.begin(),
-                                    next_snap.snapshot_ids.end(), snapshot_id);
-    PERFETTO_DCHECK(next_it != next_snap.snapshot_ids.end() &&
-                    *next_it == snapshot_id);
-    size_t next_index = static_cast<size_t>(
-        std::distance(next_snap.snapshot_ids.begin(), next_it));
-    PERFETTO_DCHECK(next_index < next_snap.snapshot_ids.size());
-    int64_t next_timestamp_ns = next_snap.timestamps_ns[next_index];
-
-    // The translated timestamp is the relative delta of the source timestamp
-    // from the closest snapshot found (ns - *it), plus the timestamp in
-    // the new clock domain for the same snapshot id.
-    ns = (ns - *it) + next_timestamp_ns;
-
-    // The last clock in the path must be the target clock.
-    PERFETTO_DCHECK(i < path.len - 1 || std::get<1>(edge) == target_clock_id);
-  }
-
-  return ns;
+  static auto comparator = [](int64_t lhs, const ClockSnapshot& rhs) {
+    return lhs < rhs.clock_time_ns;
+  };
+  auto it = std::upper_bound(snapshots.begin(), snapshots.end(), clock_time_ns,
+                             comparator);
+  if (it != snapshots.begin())
+    it--;
+  return it->trace_time_ns + (clock_time_ns - it->clock_time_ns);
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/clock_tracker.h b/src/trace_processor/clock_tracker.h
index 6c83bb1..98104de 100644
--- a/src/trace_processor/clock_tracker.h
+++ b/src/trace_processor/clock_tracker.h
@@ -20,206 +20,54 @@
 #include <stdint.h>
 
 #include <array>
-#include <map>
-#include <set>
 #include <vector>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/optional.h"
+#include "perfetto/base/optional.h"
 
 namespace perfetto {
 namespace trace_processor {
 
 class TraceProcessorContext;
 
-// This class handles synchronization of timestamps across different clock
-// domains. This includes multi-hop conversions from two clocks A and D, e.g.
-// A->B -> B->C -> C->D, even if we never saw a snapshot that contains A and D
-// at the same time.
-// The API is fairly simple (but the inner operation is not):
-// - AddSnapshot(map<clock_id, timestamp>): pushes a set of clocks that have
-//   been snapshotted at the same time (within technical limits).
-// - Convert(src_clock_id, src_timestamp, target_clock_id):
-//   converts a timestamp between two clock domains.
-//
-// Concepts:
-// - Snapshot hash:
-//   As new snapshots are pushed via AddSnapshot() we compute a snapshot hash.
-//   Such hash is the hash(clock_ids) (only IDs, not their timestamps) and is
-//   used to find other snapshots that involve the same clock domains.
-//   Two clock snapshots have the same hash iff they snapshot the same set of
-//   clocks (the order of clocks is irrelevant).
-//   This hash is used to efficiently go from the clock graph pathfinder to the
-//   time-series obtained by appending the various snapshots.
-// - Snapshot id:
-//   A simple monotonic counter that is incremented on each AddSnapshot() call.
-//
-// Data structures:
-//  - For each clock domain:
-//    - For each snapshot hash:
-//      - A logic vector of (snapshot_id, timestamp) tuples (physically stored
-//        as two vectors of the same length instead of a vector of pairs).
-// This allows to efficiently binary search timestamps within a clock domain
-// that were obtained through a particular snapshot.
-//
-// - A graph of edges (source_clock, target_clock) -> snapshot hash.
-//
-// Operation:
-// Upon each AddSnapshot() call, we incrementally build an unweighted, directed
-// graph, which has clock domains as nodes.
-// The graph is timestamp-oblivious. As long as we see one snapshot that
-// connects two clocks, we assume we'll always be able to convert between them.
-// This graph is queried by the Convert() function to figure out the shortest
-// path between clock domain, possibly involving hopping through snapshots of
-// different type (i.e. different hash).
-//
-// Example:
-
-// We see a snapshot, with hash S1, for clocks (A,B,C). We build the edges in
-// the graph: A->B, B->C, A->C (and the symmetrical ones). In other words we
-// keep track of the fact that we can convert between any of them using S1.
-// Later we get another snapshot containing (C,E), this snapshot will have a
-// different hash (S2, because Hash(C,E) != Hash(A,B,C)) and will add the edges
-// C->E, E->C [via S2] to the graph.
-// At this point when we are asked to convert a timestamp from A to E, or
-// viceversa, we use a simple BFS to figure out a conversion path that is:
-// A->C [via S1] + C->E [via S2].
-//
-// Visually:
-// Assume we make the following calls:
-//  - AddSnapshot(A:10, B:100)
-//  - AddSnapshot(A:20, C:2000)
-//  - AddSnapshot(B:400, C:5000)
-//  - AddSnapshot(A:30, B:300)
-
-// And assume Hash(A,B) = S1, H(A,C) = S2, H(B,C) = S3
-// The vectors in the tracker will look as follows:
-// Clock A:
-//   S1        {t:10, id:1}                                      {t:30, id:4}
-//   S2        |               {t:20, id:2}                      |
-//             |               |                                 |
-// Clock B:    |               |                                 |
-//   S1        {t:100, id:1}   |                                 {t:300, id:4}
-//   S3                        |                  {t:400, id:3}
-//                             |                  |
-// Clock C:                    |                  |
-//   S2                        {t: 2000, id: 2}   |
-//   S3                                           {t:5000, id:3}
+enum ClockDomain : uint32_t {
+  kBootTime,   // Monotonic, counts also time in suspend mode.
+  kMonotonic,  // Monotonic, doesn't advance when the device is suspended.
+  kRealTime,   // Real time clock, can move backward (e.g. NTP adjustements).
+  kNumClockDomains
+};
 
 class ClockTracker {
  public:
-  using ClockId = uint64_t;
-
-  // IDs in the range [64, 128) are reserved for sequence-scoped clock ids.
-  // They can't be passed directly in ClockTracker calls and must be resolved
-  // to 64-bit global clock ids by calling SeqScopedClockIdToGlobal().
-  static bool IsReservedSeqScopedClockId(ClockId clock_id) {
-    return clock_id >= 64 && clock_id < 128;
-  }
-
-  // Converts a sequence-scoped clock ids to a global clock id that can be
-  // passed as argument to ClockTracker functions.
-  static ClockId SeqScopedClockIdToGlobal(uint32_t seq_id, uint32_t clock_id) {
-    PERFETTO_DCHECK(IsReservedSeqScopedClockId(clock_id));
-    return (static_cast<uint64_t>(seq_id) << 32) | clock_id;
-  }
-
   explicit ClockTracker(TraceProcessorContext*);
   virtual ~ClockTracker();
 
-  // Appends a new snapshot for the given clock domains.
-  // This is typically called by the code that reads the ClockSnapshot packet.
-  void AddSnapshot(const std::map<ClockId, int64_t>&);
+  // Push a snapshot that tells what is the corresponding trace time for the
+  // given |clock_time_ns| in the given clock domain. This is typically called
+  // by the code that reads the ClockSnapshot packet.
+  void SyncClocks(ClockDomain, int64_t clock_time_ns, int64_t trace_time_ns);
 
-  base::Optional<int64_t> Convert(ClockId src_clock_id,
-                                  int64_t src_timestamp,
-                                  ClockId target_clock_id);
+  // Converts the passed time in the given clock domain to the global trace
+  // time (CLOCK_BOOTTIME for Android traces).
+  base::Optional<int64_t> ToTraceTime(ClockDomain, int64_t clock_time_ns);
 
-  base::Optional<int64_t> ToTraceTime(ClockId clock_id, int64_t timestamp) {
-    if (clock_id == trace_time_clock_id_)
-      return timestamp;
-    return Convert(clock_id, timestamp, trace_time_clock_id_);
-  }
-
-  void SetTraceTimeClock(ClockId clock_id) {
-    PERFETTO_DCHECK(!IsReservedSeqScopedClockId(clock_id));
-    trace_time_clock_id_ = clock_id;
+  int64_t GetFirstTimestamp(ClockDomain domain) const {
+    PERFETTO_DCHECK(!clocks_[domain].empty());
+    return clocks_[domain].front().clock_time_ns;
   }
 
  private:
-  using SnapshotHash = uint32_t;
-
-  // 0th argument is the source clock, 1st argument is the target clock.
-  using ClockGraphEdge = std::tuple<ClockId, ClockId, SnapshotHash>;
-
-  // A value-type object that carries the information about the path between
-  // two clock domains. It's used by the BFS algorithm.
-  struct ClockPath {
-    static constexpr size_t kMaxLen = 4;
-    ClockPath() = default;
-    ClockPath(const ClockPath&) = default;
-
-    // Constructs an invalid path with just a source node.
-    explicit ClockPath(ClockId clock_id) : last(clock_id) {}
-
-    // Constructs a path by appending a node to |prefix|.
-    // If |prefix| = [A,B] and clock_id = C, then |this| = [A,B,C].
-    ClockPath(const ClockPath& prefix, ClockId clock_id, SnapshotHash hash) {
-      PERFETTO_DCHECK(prefix.len < kMaxLen);
-      len = prefix.len + 1;
-      path = prefix.path;
-      path[prefix.len] = ClockGraphEdge{prefix.last, clock_id, hash};
-      last = clock_id;
-    }
-
-    bool valid() const { return len > 0; }
-    const ClockGraphEdge& at(uint32_t i) const {
-      PERFETTO_DCHECK(i < len);
-      return path[i];
-    }
-
-    uint32_t len = 0;
-    ClockId last = 0;
-    std::array<ClockGraphEdge, kMaxLen> path;  // Deliberately uninitialized.
-  };
-
-  struct ClockSnapshots {
-    // Invariant: both vectors have the same length.
-    std::vector<uint32_t> snapshot_ids;
-    std::vector<int64_t> timestamps_ns;
-  };
-
-  struct ClockDomain {
-    // One time-series for each hash.
-    std::map<SnapshotHash, ClockSnapshots> snapshots;
-
-    // TODO(primiano): support other resolutions.
-    int64_t ToNs(int64_t timestamp) const { return timestamp * 1; }
-
-    const ClockSnapshots& GetSnapshot(uint32_t hash) const {
-      auto it = snapshots.find(hash);
-      PERFETTO_DCHECK(it != snapshots.end());
-      return it->second;
-    }
-  };
-
   ClockTracker(const ClockTracker&) = delete;
   ClockTracker& operator=(const ClockTracker&) = delete;
 
-  ClockPath FindPath(ClockId src, ClockId target);
-
-  const ClockDomain& GetClock(ClockId clock_id) const {
-    auto it = clocks_.find(clock_id);
-    PERFETTO_DCHECK(it != clocks_.end());
-    return it->second;
-  }
+  struct ClockSnapshot {
+    int64_t clock_time_ns;
+    int64_t trace_time_ns;
+  };
 
   TraceProcessorContext* const context_;
-  ClockId trace_time_clock_id_ = 0;
-  std::map<ClockId, ClockDomain> clocks_;
-  std::set<ClockGraphEdge> graph_;
-  std::set<ClockId> non_monotonic_clocks_;
-  uint32_t cur_snapshot_id_ = 0;
+  using ClockSnapshotVector = std::vector<ClockSnapshot>;
+  std::array<ClockSnapshotVector, kNumClockDomains> clocks_;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/clock_tracker_unittest.cc b/src/trace_processor/clock_tracker_unittest.cc
index 824728b..848c0e2 100644
--- a/src/trace_processor/clock_tracker_unittest.cc
+++ b/src/trace_processor/clock_tracker_unittest.cc
@@ -15,147 +15,73 @@
  */
 
 #include "src/trace_processor/clock_tracker.h"
-
-#include "perfetto/ext/base/optional.h"
+#include "perfetto/base/optional.h"
 #include "src/trace_processor/trace_processor_context.h"
 #include "src/trace_processor/trace_storage.h"
-#include "test/gtest_and_gmock.h"
 
-#include "protos/perfetto/trace/clock_snapshot.pbzero.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace trace_processor {
 namespace {
 
 using ::testing::NiceMock;
-using Clock = protos::pbzero::ClockSnapshot::Clock;
-
-constexpr auto REALTIME = Clock::REALTIME;
-constexpr auto BOOTTIME = Clock::BOOTTIME;
-constexpr auto MONOTONIC = Clock::MONOTONIC;
-constexpr auto MONOTONIC_COARSE = Clock::MONOTONIC_COARSE;
-constexpr auto MONOTONIC_RAW = Clock::MONOTONIC_RAW;
-
-class ClockTrackerTest : public ::testing::Test {
+class MockTraceStorage : public TraceStorage {
  public:
-  ClockTrackerTest() { context_.storage.reset(new TraceStorage()); }
-
-  TraceProcessorContext context_;
-  ClockTracker ct_{&context_};
+  MockTraceStorage() : TraceStorage() {}
 };
 
-TEST_F(ClockTrackerTest, ClockDomainConversions) {
-  EXPECT_EQ(ct_.ToTraceTime(Clock::REALTIME, 0), base::nullopt);
+TEST(ClockTrackerTest, ClockDomainConversions) {
+  TraceProcessorContext context;
+  context.storage.reset(new NiceMock<MockTraceStorage>());
+  ClockTracker ct(&context);
 
-  ct_.AddSnapshot({{REALTIME, 10}, {BOOTTIME, 10010}});
-  ct_.AddSnapshot({{REALTIME, 20}, {BOOTTIME, 20220}});
-  ct_.AddSnapshot({{REALTIME, 30}, {BOOTTIME, 30030}});
-  ct_.AddSnapshot({{MONOTONIC, 1000}, {BOOTTIME, 100000}});
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kRealTime, 0), base::nullopt);
 
-  EXPECT_EQ(ct_.ToTraceTime(REALTIME, 0), 10000);
-  EXPECT_EQ(ct_.ToTraceTime(REALTIME, 1), 10001);
-  EXPECT_EQ(ct_.ToTraceTime(REALTIME, 9), 10009);
-  EXPECT_EQ(ct_.ToTraceTime(REALTIME, 10), 10010);
-  EXPECT_EQ(ct_.ToTraceTime(REALTIME, 11), 10011);
-  EXPECT_EQ(ct_.ToTraceTime(REALTIME, 19), 10019);
-  EXPECT_EQ(ct_.ToTraceTime(REALTIME, 20), 20220);
-  EXPECT_EQ(ct_.ToTraceTime(REALTIME, 21), 20221);
-  EXPECT_EQ(ct_.ToTraceTime(REALTIME, 29), 20229);
-  EXPECT_EQ(ct_.ToTraceTime(REALTIME, 30), 30030);
-  EXPECT_EQ(ct_.ToTraceTime(REALTIME, 40), 30040);
+  ct.SyncClocks(ClockDomain::kRealTime, 10, 10010);
+  ct.SyncClocks(ClockDomain::kRealTime, 20, 20220);
+  ct.SyncClocks(ClockDomain::kRealTime, 30, 30030);
+  ct.SyncClocks(ClockDomain::kMonotonic, 1000, 100000);
 
-  EXPECT_EQ(ct_.ToTraceTime(MONOTONIC, 0), 100000 - 1000);
-  EXPECT_EQ(ct_.ToTraceTime(MONOTONIC, 999), 100000 - 1);
-  EXPECT_EQ(ct_.ToTraceTime(MONOTONIC, 1000), 100000);
-  EXPECT_EQ(ct_.ToTraceTime(MONOTONIC, 1e6),
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kRealTime, 0), 10000);
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kRealTime, 1), 10001);
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kRealTime, 9), 10009);
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kRealTime, 10), 10010);
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kRealTime, 11), 10011);
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kRealTime, 19), 10019);
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kRealTime, 20), 20220);
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kRealTime, 21), 20221);
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kRealTime, 29), 20229);
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kRealTime, 30), 30030);
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kRealTime, 40), 30040);
+
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kMonotonic, 0), 100000 - 1000);
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kMonotonic, 999), 100000 - 1);
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kMonotonic, 1000), 100000);
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kMonotonic, 1e6),
             static_cast<int64_t>(100000 - 1000 + 1e6));
 }
 
-// When a clock moves backwards conversions *from* that clock are forbidden
-// but conversions *to* that clock should still work.
-// Think to the case of REALTIME going backwards from 3AM to 2AM during DST day.
-// You can't convert 2.10AM REALTIME to BOOTTIME because there are two possible
-// answers, but you can still unambiguosly convert BOOTTIME into REALTIME.
-TEST_F(ClockTrackerTest, RealTimeClockMovingBackwards) {
-  ct_.AddSnapshot({{BOOTTIME, 10010}, {REALTIME, 10}});
+TEST(ClockTrackerTest, RealTimeClockMovingBackwards) {
+  TraceProcessorContext context;
+  ClockTracker ct(&context);
 
-  // At this point conversions are still possible in both ways because we
-  // haven't broken monotonicity yet.
-  EXPECT_EQ(ct_.Convert(REALTIME, 11, BOOTTIME), 10011);
+  ct.SyncClocks(ClockDomain::kRealTime, 10, 10010);
+  ct.SyncClocks(ClockDomain::kRealTime, 20, 10020);
+  ct.SyncClocks(ClockDomain::kRealTime, 40, 30040);
+  ct.SyncClocks(ClockDomain::kRealTime, 30, 40030);
 
-  ct_.AddSnapshot({{BOOTTIME, 10020}, {REALTIME, 20}});
-  ct_.AddSnapshot({{BOOTTIME, 30040}, {REALTIME, 40}});
-  ct_.AddSnapshot({{BOOTTIME, 40030}, {REALTIME, 30}});
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kRealTime, 11), 10011);
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kRealTime, 29), 10029);
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kRealTime, 30), 40030);
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kRealTime, 40), 40040);
 
-  // Now only BOOTIME -> REALTIME conversion should be possible.
-  EXPECT_FALSE(ct_.Convert(REALTIME, 11, BOOTTIME));
-  EXPECT_EQ(ct_.Convert(BOOTTIME, 10011, REALTIME), 11);
-  EXPECT_EQ(ct_.Convert(BOOTTIME, 10029, REALTIME), 29);
-  EXPECT_EQ(ct_.Convert(BOOTTIME, 40030, REALTIME), 30);
-  EXPECT_EQ(ct_.Convert(BOOTTIME, 40040, REALTIME), 40);
+  ct.SyncClocks(ClockDomain::kRealTime, 50, 50000);
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kRealTime, 55), 50005);
 
-  ct_.AddSnapshot({{BOOTTIME, 50000}, {REALTIME, 50}});
-  EXPECT_EQ(ct_.Convert(BOOTTIME, 50005, REALTIME), 55);
-
-  ct_.AddSnapshot({{BOOTTIME, 60020}, {REALTIME, 20}});
-  EXPECT_EQ(ct_.Convert(BOOTTIME, 60020, REALTIME), 20);
-}
-
-// Simulate the following scenario:
-// MONOTONIC = MONOTONIC_COARSE + 10
-// BOOTTIME = MONOTONIC + 1000 (until T=200)
-// BOOTTIME = MONOTONIC + 2000 (from T=200)
-// Then resolve MONOTONIC_COARSE. This requires a two-level resolution:
-// MONOTONIC_COARSE -> MONOTONIC -> BOOTTIME.
-TEST_F(ClockTrackerTest, ChainedResolutionSimple) {
-  ct_.AddSnapshot({{MONOTONIC_COARSE, 1}, {MONOTONIC, 11}});
-  ct_.AddSnapshot({{MONOTONIC, 100}, {BOOTTIME, 1100}});
-  ct_.AddSnapshot({{MONOTONIC, 200}, {BOOTTIME, 2200}});
-
-  EXPECT_EQ(ct_.Convert(MONOTONIC, 100, MONOTONIC_COARSE), 90);
-  EXPECT_EQ(ct_.Convert(MONOTONIC_COARSE, 20, MONOTONIC), 30);
-
-  // MONOTONIC_COARSE@100 == MONOTONIC@110 == BOOTTIME@1100.
-  EXPECT_EQ(ct_.ToTraceTime(MONOTONIC, 110), 1110);
-  EXPECT_EQ(*ct_.ToTraceTime(MONOTONIC_COARSE, 100), 100 + 10 + 1000);
-  EXPECT_EQ(*ct_.ToTraceTime(MONOTONIC_COARSE, 202), 202 + 10 + 2000);
-}
-
-TEST_F(ClockTrackerTest, ChainedResolutionHard) {
-  // MONOTONIC_COARSE = MONOTONIC_RAW - 1.
-  ct_.AddSnapshot({{MONOTONIC_RAW, 10}, {MONOTONIC_COARSE, 9}});
-
-  // MONOTONIC = MONOTONIC_COARSE - 50.
-  ct_.AddSnapshot({{MONOTONIC_COARSE, 100}, {MONOTONIC, 50}});
-
-  // BOOTTIME = MONOTONIC + 1000 until T=100 (see below).
-  ct_.AddSnapshot({{MONOTONIC, 1}, {BOOTTIME, 1001}, {REALTIME, 10001}});
-
-  // BOOTTIME = MONOTONIC + 2000 from T=100.
-  // At the same time, REALTIME goes backwards.
-  ct_.AddSnapshot({{MONOTONIC, 101}, {BOOTTIME, 2101}, {REALTIME, 9101}});
-
-  // 1-hop conversions.
-  EXPECT_EQ(ct_.Convert(MONOTONIC_RAW, 2, MONOTONIC_COARSE), 1);
-  EXPECT_EQ(ct_.Convert(MONOTONIC_COARSE, 1, MONOTONIC_RAW), 2);
-  EXPECT_EQ(ct_.Convert(MONOTONIC_RAW, 100001, MONOTONIC_COARSE), 100000);
-  EXPECT_EQ(ct_.Convert(MONOTONIC_COARSE, 100000, MONOTONIC_RAW), 100001);
-
-  // 2-hop conversions (MONOTONIC_RAW <-> MONOTONIC_COARSE <-> MONOTONIC).
-  // From above, MONOTONIC = (MONOTONIC_RAW - 1) - 50.
-  EXPECT_EQ(ct_.Convert(MONOTONIC_RAW, 53, MONOTONIC), 53 - 1 - 50);
-  EXPECT_EQ(ct_.Convert(MONOTONIC, 2, MONOTONIC_RAW), 2 + 1 + 50);
-
-  // 3-hop conversions (as above + BOOTTIME)
-  EXPECT_EQ(ct_.Convert(MONOTONIC_RAW, 53, BOOTTIME), 53 - 1 - 50 + 1000);
-  EXPECT_EQ(ct_.Convert(BOOTTIME, 1002, MONOTONIC_RAW), 1002 - 1000 + 1 + 50);
-
-  EXPECT_EQ(*ct_.Convert(MONOTONIC_RAW, 753, BOOTTIME), 753 - 1 - 50 + 2000);
-  EXPECT_EQ(ct_.Convert(BOOTTIME, 2702, MONOTONIC_RAW), 2702 - 2000 + 1 + 50);
-
-  // 3-hop conversion to REALTIME, one way only (REALTIME goes backwards).
-  EXPECT_EQ(*ct_.Convert(MONOTONIC_RAW, 53, REALTIME), 53 - 1 - 50 + 10000);
-  EXPECT_EQ(*ct_.Convert(MONOTONIC_RAW, 753, REALTIME), 753 - 1 - 50 + 9000);
+  ct.SyncClocks(ClockDomain::kRealTime, 11, 60011);
+  EXPECT_EQ(ct.ToTraceTime(ClockDomain::kRealTime, 20), 60020);
 }
 
 }  // namespace
diff --git a/src/trace_processor/counter_definitions_table.cc b/src/trace_processor/counter_definitions_table.cc
new file mode 100644
index 0000000..4c4add8
--- /dev/null
+++ b/src/trace_processor/counter_definitions_table.cc
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2019 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 "src/trace_processor/counter_definitions_table.h"
+
+#include <string>
+
+#include "src/trace_processor/storage_columns.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+CounterDefinitionsTable::CounterDefinitionsTable(sqlite3*,
+                                                 const TraceStorage* storage)
+    : storage_(storage) {}
+
+void CounterDefinitionsTable::RegisterTable(sqlite3* db,
+                                            const TraceStorage* storage) {
+  Table::Register<CounterDefinitionsTable>(db, storage, "counter_definitions");
+}
+
+StorageSchema CounterDefinitionsTable::CreateStorageSchema() {
+  const auto& cs = storage_->counter_definitions();
+  return StorageSchema::Builder()
+      .AddGenericNumericColumn("counter_id", RowAccessor())
+      .AddStringColumn("name", &cs.name_ids(), &storage_->string_pool())
+      .AddNumericColumn("ref", &cs.refs())
+      .AddStringColumn("ref_type", &cs.types(), &GetRefTypeStringMap())
+      .Build({"counter_id"});
+}
+
+uint32_t CounterDefinitionsTable::RowCount() {
+  return storage_->counter_definitions().size();
+}
+
+int CounterDefinitionsTable::BestIndex(const QueryConstraints& qc,
+                                       BestIndexInfo* info) {
+  info->estimated_cost = EstimateCost(qc);
+
+  // Only the string columns are handled by SQLite
+  size_t name_index = schema().ColumnIndexFromName("name");
+  size_t ref_type_index = schema().ColumnIndexFromName("ref_type");
+  info->order_by_consumed = true;
+  for (size_t i = 0; i < qc.constraints().size(); i++) {
+    auto col = static_cast<size_t>(qc.constraints()[i].iColumn);
+    info->omit[i] = col != name_index && col != ref_type_index;
+  }
+
+  return SQLITE_OK;
+}
+
+uint32_t CounterDefinitionsTable::EstimateCost(const QueryConstraints& qc) {
+  // If there is a constraint on the counter id, we can efficiently filter
+  // to a single row.
+  if (HasEqConstraint(qc, "counter_id"))
+    return 1;
+
+  auto eq_name = HasEqConstraint(qc, "name");
+  auto eq_ref = HasEqConstraint(qc, "ref");
+  auto eq_ref_type = HasEqConstraint(qc, "ref_type");
+
+  // If there is a constraint on all three columns, we are going to only return
+  // exaclty one row for sure so make the cost 1.
+  if (eq_name && eq_ref && eq_ref_type)
+    return 1;
+  else if (eq_name && eq_ref)
+    return 10;
+  else if (eq_name)
+    return 100;
+  return RowCount();
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/counter_definitions_table.h b/src/trace_processor/counter_definitions_table.h
new file mode 100644
index 0000000..539eaac
--- /dev/null
+++ b/src/trace_processor/counter_definitions_table.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_COUNTER_DEFINITIONS_TABLE_H_
+#define SRC_TRACE_PROCESSOR_COUNTER_DEFINITIONS_TABLE_H_
+
+#include "src/trace_processor/storage_table.h"
+#include "src/trace_processor/trace_storage.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class CounterDefinitionsTable : public StorageTable {
+ public:
+  static void RegisterTable(sqlite3* db, const TraceStorage* storage);
+
+  CounterDefinitionsTable(sqlite3*, const TraceStorage*);
+
+  // StorageTable implementation.
+  StorageSchema CreateStorageSchema() override;
+  uint32_t RowCount() override;
+  int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
+
+ private:
+  uint32_t EstimateCost(const QueryConstraints&);
+
+  const TraceStorage* const storage_;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_COUNTER_DEFINITIONS_TABLE_H_
diff --git a/src/trace_processor/counter_values_table.cc b/src/trace_processor/counter_values_table.cc
index 7176fd3..7398b2b 100644
--- a/src/trace_processor/counter_values_table.cc
+++ b/src/trace_processor/counter_values_table.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 9 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.
@@ -24,14 +24,15 @@
 
 void CounterValuesTable::RegisterTable(sqlite3* db,
                                        const TraceStorage* storage) {
-  SqliteTable::Register<CounterValuesTable>(db, storage, "counter");
+  Table::Register<CounterValuesTable>(db, storage, "counter_values");
 }
 
 StorageSchema CounterValuesTable::CreateStorageSchema() {
   const auto& cs = storage_->counter_values();
   return StorageSchema::Builder()
       .AddGenericNumericColumn("id", RowIdAccessor(TableId::kCounterValues))
-      .AddNumericColumn("track_id", &cs.track_ids(), &cs.rows_for_track_id())
+      .AddNumericColumn("counter_id", &cs.counter_ids(),
+                        &cs.rows_for_counter_id())
       .AddOrderedNumericColumn("ts", &cs.timestamps())
       .AddNumericColumn("value", &cs.values())
       .AddNumericColumn("arg_set_id", &cs.arg_set_ids())
@@ -45,15 +46,17 @@
 int CounterValuesTable::BestIndex(const QueryConstraints& qc,
                                   BestIndexInfo* info) {
   info->estimated_cost = EstimateCost(qc);
-  info->sqlite_omit_order_by = true;
-  for (auto& c_info : info->constraint_info)
-    c_info.sqlite_omit = true;
+
+  info->order_by_consumed = true;
+  for (size_t i = 0; i < qc.constraints().size(); i++) {
+    info->omit[i] = true;
+  }
 
   return SQLITE_OK;
 }
 
 uint32_t CounterValuesTable::EstimateCost(const QueryConstraints& qc) {
-  if (HasEqConstraint(qc, "track_id"))
+  if (HasEqConstraint(qc, "counter_id"))
     return RowCount() / 100;
   return RowCount();
 }
diff --git a/src/trace_processor/cpu_profile_stack_sample_table.cc b/src/trace_processor/cpu_profile_stack_sample_table.cc
deleted file mode 100644
index 1226020..0000000
--- a/src/trace_processor/cpu_profile_stack_sample_table.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/cpu_profile_stack_sample_table.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-CpuProfileStackSampleTable::CpuProfileStackSampleTable(
-    sqlite3*,
-    const TraceStorage* storage)
-    : storage_(storage) {}
-
-void CpuProfileStackSampleTable::RegisterTable(sqlite3* db,
-                                               const TraceStorage* storage) {
-  SqliteTable::Register<CpuProfileStackSampleTable>(db, storage,
-                                                    "cpu_profile_stack_sample");
-}
-
-StorageSchema CpuProfileStackSampleTable::CreateStorageSchema() {
-  const auto& allocs = storage_->cpu_profile_stack_samples();
-  return StorageSchema::Builder()
-      .AddGenericNumericColumn("id", RowAccessor())
-      .AddOrderedNumericColumn("ts", &allocs.timestamps())
-      .AddNumericColumn("callsite_id", &allocs.callsite_ids())
-      .AddNumericColumn("utid", &allocs.utids())
-      .Build({"id"});
-}
-
-uint32_t CpuProfileStackSampleTable::RowCount() {
-  return storage_->cpu_profile_stack_samples().size();
-}
-
-int CpuProfileStackSampleTable::BestIndex(const QueryConstraints& qc,
-                                          BestIndexInfo* info) {
-  info->sqlite_omit_order_by = true;
-  info->estimated_cost = HasEqConstraint(qc, "id") ? 1 : RowCount();
-  return SQLITE_OK;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/cpu_profile_stack_sample_table.h b/src/trace_processor/cpu_profile_stack_sample_table.h
deleted file mode 100644
index e422d75..0000000
--- a/src/trace_processor/cpu_profile_stack_sample_table.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_CPU_PROFILE_STACK_SAMPLE_TABLE_H_
-#define SRC_TRACE_PROCESSOR_CPU_PROFILE_STACK_SAMPLE_TABLE_H_
-
-#include "src/trace_processor/storage_table.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class CpuProfileStackSampleTable : public StorageTable {
- public:
-  static void RegisterTable(sqlite3* db, const TraceStorage* storage);
-
-  CpuProfileStackSampleTable(sqlite3*, const TraceStorage*);
-
-  // StorageTable implementation.
-  StorageSchema CreateStorageSchema() override;
-  uint32_t RowCount() override;
-  int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
-
- private:
-  const TraceStorage* const storage_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_CPU_PROFILE_STACK_SAMPLE_TABLE_H_
diff --git a/src/trace_processor/db/BUILD.gn b/src/trace_processor/db/BUILD.gn
deleted file mode 100644
index 57366d2..0000000
--- a/src/trace_processor/db/BUILD.gn
+++ /dev/null
@@ -1,69 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../../gn/test.gni")
-
-source_set("lib") {
-  sources = [
-    "bit_vector.cc",
-    "bit_vector.h",
-    "bit_vector_iterators.cc",
-    "bit_vector_iterators.h",
-    "column.cc",
-    "column.h",
-    "row_map.cc",
-    "row_map.h",
-    "sparse_vector.h",
-    "table.cc",
-    "table.h",
-    "typed_column.h",
-  ]
-  deps = [
-    "../:common",
-    "../../../gn:default_deps",
-    "../../../include/perfetto/base",
-    "../../../include/perfetto/ext/base",
-    "../../../include/perfetto/trace_processor",
-  ]
-}
-
-perfetto_unittest_source_set("unittests") {
-  testonly = true
-  sources = [
-    "bit_vector_unittest.cc",
-    "row_map_unittest.cc",
-    "sparse_vector_unittest.cc",
-  ]
-  deps = [
-    ":lib",
-    "../../../gn:default_deps",
-    "../../../gn:gtest_and_gmock",
-  ]
-}
-
-if (enable_perfetto_benchmarks) {
-  source_set("benchmarks") {
-    testonly = true
-    deps = [
-      ":lib",
-      "../../../gn:benchmark",
-      "../../../gn:default_deps",
-    ]
-    sources = [
-      "bit_vector_benchmark.cc",
-      "row_map_benchmark.cc",
-      "sparse_vector_benchmark.cc",
-    ]
-  }
-}
diff --git a/src/trace_processor/db/bit_vector.cc b/src/trace_processor/db/bit_vector.cc
deleted file mode 100644
index 0d2f3d8..0000000
--- a/src/trace_processor/db/bit_vector.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/db/bit_vector.h"
-
-#include "src/trace_processor/db/bit_vector_iterators.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-BitVector::BitVector() = default;
-
-BitVector::BitVector(std::initializer_list<bool> init) {
-  for (bool x : init) {
-    if (x) {
-      AppendTrue();
-    } else {
-      AppendFalse();
-    }
-  }
-}
-
-BitVector::BitVector(uint32_t count, bool value) {
-  Resize(count, value);
-}
-
-BitVector::BitVector(std::vector<Block> blocks,
-                     std::vector<uint32_t> counts,
-                     uint32_t size)
-    : size_(size), counts_(std::move(counts)), blocks_(std::move(blocks)) {}
-
-BitVector BitVector::Copy() const {
-  return BitVector(blocks_, counts_, size_);
-}
-
-BitVector::AllBitsIterator BitVector::IterateAllBits() const {
-  return AllBitsIterator(this);
-}
-
-BitVector::SetBitsIterator BitVector::IterateSetBits() const {
-  return SetBitsIterator(this);
-}
-
-void BitVector::UpdateSetBits(const BitVector& other) {
-  PERFETTO_DCHECK(other.size() == GetNumBitsSet());
-
-  // For each set bit in this bitvector, we lookup whether |other| has the
-  // bit set. If not, we clear the bit.
-  for (auto it = IterateSetBits(); it; it.Next()) {
-    if (!other.IsSet(it.ordinal()))
-      it.Clear();
-  }
-
-  // After the loop, we should have precisely the same number of bits
-  // set as |other|.
-  PERFETTO_DCHECK(GetNumBitsSet() == other.GetNumBitsSet());
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/db/bit_vector.h b/src/trace_processor/db/bit_vector.h
deleted file mode 100644
index bed71a6..0000000
--- a/src/trace_processor/db/bit_vector.h
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_DB_BIT_VECTOR_H_
-#define SRC_TRACE_PROCESSOR_DB_BIT_VECTOR_H_
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include <algorithm>
-#include <array>
-#include <vector>
-
-#include "perfetto/base/logging.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace internal {
-
-class BaseIterator;
-class AllBitsIterator;
-class SetBitsIterator;
-
-}  // namespace internal
-
-// A bitvector which compactly stores a vector of bools using a single bit
-// for each bool.
-class BitVector {
- public:
-  using AllBitsIterator = internal::AllBitsIterator;
-  using SetBitsIterator = internal::SetBitsIterator;
-
-  // Creates an empty bitvector.
-  BitVector();
-
-  explicit BitVector(std::initializer_list<bool> init);
-
-  // Creates a bitvector of |count| size filled with |value|.
-  BitVector(uint32_t count, bool value = false);
-
-  // Enable moving bitvectors as they have no unmovable state.
-  BitVector(BitVector&&) noexcept = default;
-  BitVector& operator=(BitVector&&) = default;
-
-  // Create a copy of the bitvector.
-  BitVector Copy() const;
-
-  // Returns the size of the bitvector.
-  uint32_t size() const { return static_cast<uint32_t>(size_); }
-
-  // Returns whether the bit at |idx| is set.
-  bool IsSet(uint32_t idx) const {
-    PERFETTO_DCHECK(idx < size());
-
-    Address a = IndexToAddress(idx);
-    return blocks_[a.block_idx].IsSet(a.block_offset);
-  }
-
-  // Returns the number of set bits in the bitvector.
-  uint32_t GetNumBitsSet() const { return GetNumBitsSet(size()); }
-
-  // Returns the number of set bits between the start of the bitvector
-  // (inclusive) and the index |end| (exclusive).
-  uint32_t GetNumBitsSet(uint32_t end) const {
-    if (end == 0)
-      return 0;
-
-    // Although the external interface we present uses an exclusive |end|,
-    // internally it's a lot nicer to work with an inclusive |end| (mainly
-    // because we get block rollovers on exclusive ends which means we need
-    // to have if checks to ensure we don't overflow the number of blocks).
-    Address addr = IndexToAddress(end - 1);
-    uint32_t idx = addr.block_idx;
-
-    // Add the number of set bits until the start of the block to the number
-    // of set bits until the end address inside the block.
-    return counts_[idx] + blocks_[idx].GetNumBitsSet(addr.block_offset);
-  }
-
-  // Returns the index of the |n|th set bit. Should only be called with |n| <
-  // GetNumBitsSet().
-  uint32_t IndexOfNthSet(uint32_t n) const {
-    PERFETTO_DCHECK(n < GetNumBitsSet());
-
-    // First search for the block which, up until the start of it, has more than
-    // n bits set. Note that this should never return |counts.begin()| as
-    // that should always be 0.
-    // TODO(lalitm): investigate whether we can make this faster with small
-    // binary search followed by a linear search instead of binary searching the
-    // full way.
-    auto it = std::upper_bound(counts_.begin(), counts_.end(), n);
-    PERFETTO_DCHECK(it != counts_.begin());
-
-    // Go back one block to find the block which has the bit we are looking for.
-    uint16_t block_idx =
-        static_cast<uint16_t>(std::distance(counts_.begin(), it) - 1);
-
-    // Figure out how many set bits forward we are looking inside the block
-    // by taking away the number of bits at the start of the block from n.
-    uint32_t set_in_block = n - counts_[block_idx];
-
-    // Compute the address of the bit in the block then convert the full
-    // address back to an index.
-    BlockOffset block_offset = blocks_[block_idx].IndexOfNthSet(set_in_block);
-    return AddressToIndex(Address{block_idx, block_offset});
-  }
-
-  // Sets the bit at index |idx| to true.
-  void Set(uint32_t idx) {
-    // Set the bit to the correct value inside the block but store the old
-    // bit to help fix the counts.
-    auto addr = IndexToAddress(idx);
-    bool old_value = blocks_[addr.block_idx].IsSet(addr.block_offset);
-
-    // If the old value was unset, set the bit and add one to the count.
-    if (PERFETTO_LIKELY(!old_value)) {
-      blocks_[addr.block_idx].Set(addr.block_offset);
-
-      uint32_t size = static_cast<uint32_t>(counts_.size());
-      for (uint32_t i = addr.block_idx + 1; i < size; ++i) {
-        counts_[i]++;
-      }
-    }
-  }
-
-  // Sets the bit at index |idx| to false.
-  void Clear(uint32_t idx) {
-    // Set the bit to the correct value inside the block but store the old
-    // bit to help fix the counts.
-    auto addr = IndexToAddress(idx);
-    bool old_value = blocks_[addr.block_idx].IsSet(addr.block_offset);
-
-    // If the old value was set, clear the bit and subtract one from all the
-    // counts.
-    if (PERFETTO_LIKELY(old_value)) {
-      blocks_[addr.block_idx].Clear(addr.block_offset);
-
-      uint32_t size = static_cast<uint32_t>(counts_.size());
-      for (uint32_t i = addr.block_idx + 1; i < size; ++i) {
-        counts_[i]--;
-      }
-    }
-  }
-
-  // Appends true to the bitvector.
-  void AppendTrue() {
-    Address addr = IndexToAddress(size_);
-    uint32_t old_blocks_size = static_cast<uint32_t>(blocks_.size());
-    uint32_t new_blocks_size = addr.block_idx + 1;
-
-    if (PERFETTO_UNLIKELY(new_blocks_size > old_blocks_size)) {
-      uint32_t t = GetNumBitsSet();
-      blocks_.emplace_back();
-      counts_.emplace_back(t);
-    }
-
-    size_++;
-    blocks_[addr.block_idx].Set(addr.block_offset);
-  }
-
-  // Appends false to the bitvector.
-  void AppendFalse() {
-    Address addr = IndexToAddress(size_);
-    uint32_t old_blocks_size = static_cast<uint32_t>(blocks_.size());
-    uint32_t new_blocks_size = addr.block_idx + 1;
-
-    if (PERFETTO_UNLIKELY(new_blocks_size > old_blocks_size)) {
-      uint32_t t = GetNumBitsSet();
-      blocks_.emplace_back();
-      counts_.emplace_back(t);
-    }
-
-    size_++;
-    // We don't need to clear the bit as we ensure that anything after
-    // size_ is always set to false.
-  }
-
-  // Resizes the BitVector to the given |size|.
-  // Truncates the BitVector if |size| < |size()| or fills the new space with
-  // |value| if |size| > |size()|. Calling this method is a noop if |size| ==
-  // |size()|.
-  void Resize(uint32_t size, bool value = false) {
-    uint32_t old_size = size_;
-    if (size == old_size)
-      return;
-
-    // Empty bitvectors should be memory efficient so we don't keep any data
-    // around in the bitvector.
-    if (size == 0) {
-      blocks_.clear();
-      counts_.clear();
-      size_ = 0;
-      return;
-    }
-
-    // Compute the address of the new last bit in the bitvector.
-    Address last_addr = IndexToAddress(size - 1);
-    uint32_t old_blocks_size = static_cast<uint32_t>(counts_.size());
-    uint32_t new_blocks_size = last_addr.block_idx + 1;
-
-    // Then, resize the block and count vectors to have the correct
-    // number of entries.
-    blocks_.resize(new_blocks_size);
-    counts_.resize(new_blocks_size);
-
-    if (size > old_size) {
-      if (value) {
-        // If the new space should be filled with true, then set all the bits
-        // between the address of the old size and the new last address.
-        const Address& start = IndexToAddress(old_size);
-        Set(start, last_addr);
-
-        // We then need to update the counts vector to match the changes we
-        // made to the blocks.
-
-        // We start by adding the bits we set in the first block to the
-        // cummulative count before the range we changed.
-        Address end_of_block = {start.block_idx,
-                                {Block::kWords - 1, BitWord::kBits - 1}};
-        uint32_t count_in_block_after_end =
-            AddressToIndex(end_of_block) - AddressToIndex(start) + 1;
-        uint32_t set_count = GetNumBitsSet() + count_in_block_after_end;
-
-        for (uint32_t i = start.block_idx + 1; i <= last_addr.block_idx; ++i) {
-          // Set the count to the cummulative count so far.
-          counts_[i] = set_count;
-
-          // Add a full block of set bits to the count.
-          set_count += Block::kBits;
-        }
-      } else {
-        // If the newly added bits are false, we just need to update the
-        // counts vector with the current size of the bitvector for all
-        // the newly added blocks.
-        if (new_blocks_size > old_blocks_size) {
-          uint32_t count = GetNumBitsSet();
-          for (uint32_t i = old_blocks_size; i < new_blocks_size; ++i) {
-            counts_[i] = count;
-          }
-        }
-      }
-    } else {
-      // Throw away all the bits after the new last bit. We do this to make
-      // future lookup, append and resize operations not have to worrying about
-      // trailing garbage bits in the last block.
-      blocks_[last_addr.block_idx].ClearAfter(last_addr.block_offset);
-    }
-
-    // Actually update the size.
-    size_ = size;
-  }
-
-  // Updates the ith set bit of this bitvector with the value of
-  // |other.IsSet(i)|.
-  //
-  // This is the best way to batch update all the bits which are set; for
-  // example when filtering rows, we want to filter all rows which are currently
-  // included but ignore rows which have already been excluded.
-  //
-  // For example suppose the following:
-  // this:  1 1 0 0 1 0 1
-  // other: 0 1 1 0
-  // This will change this to the following:
-  // this:  0 1 0 0 1 0 0
-  // TODO(lalitm): investigate whether we should just change this to And.
-  void UpdateSetBits(const BitVector& other);
-
-  // Iterate all the bits in the BitVector.
-  //
-  // Usage:
-  // for (auto it = bv.IterateAllBits(); it; it.Next()) {
-  //   ...
-  // }
-  AllBitsIterator IterateAllBits() const;
-
-  // Iterate all the set bits in the BitVector.
-  //
-  // Usage:
-  // for (auto it = bv.IterateSetBits(); it; it.Next()) {
-  //   ...
-  // }
-  SetBitsIterator IterateSetBits() const;
-
- private:
-  friend class internal::BaseIterator;
-  friend class internal::AllBitsIterator;
-  friend class internal::SetBitsIterator;
-
-  // Represents the offset of a bit within a block.
-  struct BlockOffset {
-    uint16_t word_idx;
-    uint16_t bit_idx;
-  };
-
-  // Represents the address of a bit within the bitvector.
-  struct Address {
-    uint32_t block_idx;
-    BlockOffset block_offset;
-  };
-
-  // Represents the smallest collection of bits we can refer to as
-  // one unit.
-  //
-  // Currently, this is implemented as a 64 bit integer as this is the
-  // largest type which we can assume to be present on all platforms.
-  class BitWord {
-   public:
-    static constexpr uint32_t kBits = 64;
-
-    // Returns whether the bit at the given index is set.
-    bool IsSet(uint32_t idx) const {
-      PERFETTO_DCHECK(idx < kBits);
-      return (word >> idx) & 1ull;
-    }
-
-    // Sets the bit at the given index to true.
-    void Set(uint32_t idx) {
-      PERFETTO_DCHECK(idx < kBits);
-
-      // Or the value for the true shifted up to |idx| with the word.
-      word |= 1ull << idx;
-    }
-
-    // Sets the bit at the given index to false.
-    void Clear(uint32_t idx) {
-      PERFETTO_DCHECK(idx < kBits);
-
-      // And the integer of all bits set apart from |idx| with the word.
-      word &= ~(1ull << idx);
-    }
-
-    // Clears all the bits (i.e. sets the atom to zero).
-    void ClearAll() { word = 0; }
-
-    // Returns the index of the nth set bit.
-    // Undefined if |n| >= |GetNumBitsSet()|.
-    uint16_t IndexOfNthSet(uint32_t n) const {
-      PERFETTO_DCHECK(n < kBits);
-
-      // The below code is very dense but essentially computes the nth set
-      // bit inside |atom| in the "broadword" style of programming (sometimes
-      // referred to as "SIMD within a register").
-      //
-      // Instead of treating a uint64 as an individual unit, broadword
-      // algorithms treat them as a packed vector of uint8. By doing this, they
-      // allow branchless algorithms when considering bits of a uint64.
-      //
-      // In benchmarks, this algorithm has found to be the fastest, portable
-      // way of computing the nth set bit (if we were only targetting new
-      // versions of x64, we could also use pdep + ctz but unfortunately
-      // this would fail on WASM - this about 2.5-3x faster on x64).
-      //
-      // The code below was taken from the paper
-      // http://vigna.di.unimi.it/ftp/papers/Broadword.pdf
-      uint64_t s = word - ((word & 0xAAAAAAAAAAAAAAAA) >> 1);
-      s = (s & 0x3333333333333333) + ((s >> 2) & 0x3333333333333333);
-      s = ((s + (s >> 4)) & 0x0F0F0F0F0F0F0F0F) * L8;
-
-      uint64_t b = (BwLessThan(s, n * L8) >> 7) * L8 >> 53 & ~7ull;
-      uint64_t l = n - ((s << 8) >> b & 0xFF);
-      s = (BwGtZero(((word >> b & 0xFF) * L8) & 0x8040201008040201) >> 7) * L8;
-
-      uint64_t ret = b + ((BwLessThan(s, l * L8) >> 7) * L8 >> 56);
-
-      return static_cast<uint16_t>(ret);
-    }
-
-    // Returns the number of set bits.
-    uint32_t GetNumBitsSet() const {
-      // We use __builtin_popcountll here as it's available natively for the two
-      // targets we care most about (x64 and WASM).
-      return static_cast<uint32_t>(__builtin_popcountll(word));
-    }
-
-    // Returns the number of set bits up to and including the bit at |idx|.
-    uint32_t GetNumBitsSet(uint32_t idx) const {
-      PERFETTO_DCHECK(idx < kBits);
-
-      // We use __builtin_popcountll here as it's available natively for the two
-      // targets we care most about (x64 and WASM).
-      return static_cast<uint32_t>(__builtin_popcountll(WordUntil(idx)));
-    }
-
-    // Retains all bits up to and including the bit at |idx| and clears
-    // all bits after this point.
-    void ClearAfter(uint32_t idx) {
-      PERFETTO_DCHECK(idx < kBits);
-      word = WordUntil(idx);
-    }
-
-    // Sets all bits between the bit at |start| and |end| (inclusive).
-    void Set(uint32_t start, uint32_t end) {
-      uint32_t diff = end - start;
-      word |= (MaskAllBitsSetUntil(diff) << static_cast<uint64_t>(start));
-    }
-
-   private:
-    // Constant with all the low bit of every byte set.
-    static constexpr uint64_t L8 = 0x0101010101010101;
-
-    // Constant with all the high bit of every byte set.
-    static constexpr uint64_t H8 = 0x8080808080808080;
-
-    // Returns a packed uint64 encoding whether each byte of x is less
-    // than each corresponding byte of y.
-    // This is computed in the "broadword" style of programming; see
-    // IndexOfNthSet for details on this.
-    static uint64_t BwLessThan(uint64_t x, uint64_t y) {
-      return (((y | H8) - (x & ~H8)) ^ x ^ y) & H8;
-    }
-
-    // Returns a packed uint64 encoding whether each byte of x is greater
-    // than or equal zero.
-    // This is computed in the "broadword" style of programming; see
-    // IndexOfNthSet for details on this.
-    static uint64_t BwGtZero(uint64_t x) { return (((x | H8) - L8) | x) & H8; }
-
-    // Returns the bits up to and including the bit at |idx|.
-    uint64_t WordUntil(uint32_t idx) const {
-      PERFETTO_DCHECK(idx < kBits);
-
-      // To understand what is happeninng here, consider an example.
-      // Suppose we want to all the bits up to the 7th bit in the atom
-      //               7th
-      //                |
-      //                v
-      // atom: 01010101011111000
-      //
-      // The easiest way to do this would be if we had a mask with only
-      // the bottom 7 bits set:
-      // mask: 00000000001111111
-      uint64_t mask = MaskAllBitsSetUntil(idx);
-
-      // Finish up by anding the the atom with the computed msk.
-      return word & mask;
-    }
-
-    // Return a mask of all the bits up to and including bit at |idx|.
-    static uint64_t MaskAllBitsSetUntil(uint32_t idx) {
-      // Start with 1 and shift it up (idx + 1) bits we get:
-      // top : 00000000010000000
-      uint64_t top = 1ull << ((idx + 1ull) % kBits);
-
-      // We need to handle the case where idx == 63. In this case |top| will be
-      // zero because 1 << ((idx + 1) % 64) == 1 << (64 % 64) == 1.
-      // In this case, we actually want top == 0. We can do this by shifting
-      // down by (idx + 1) / kBits - this will be a noop for every index other
-      // than idx == 63. This should also be free on x86 because of the mod
-      // instruction above.
-      top = top >> ((idx + 1) / kBits);
-
-      // Then if we take away 1, we get precisely the mask we want.
-      return top - 1u;
-    }
-
-    uint64_t word = 0;
-  };
-
-  // Represents a group of bits with a bitcount such that it is
-  // efficient to work on these bits.
-  //
-  // On x86 architectures we generally target for trace processor, the
-  // size of a cache line is 64 bytes (or 512 bits). For this reason,
-  // we make the size of the block contain 8 atoms as 8 * 64 == 512.
-  //
-  // TODO(lalitm): investigate whether we should tune this value for
-  // WASM and ARM.
-  class Block {
-   public:
-    // See class documentation for how these constants are chosen.
-    static constexpr uint32_t kWords = 8;
-    static constexpr uint32_t kBits = kWords * BitWord::kBits;
-
-    // Returns whether the bit at the given address is set.
-    bool IsSet(const BlockOffset& addr) const {
-      PERFETTO_DCHECK(addr.word_idx < kWords);
-
-      return words_[addr.word_idx].IsSet(addr.bit_idx);
-    }
-
-    // Sets the bit at the given address to true.
-    void Set(const BlockOffset& addr) {
-      PERFETTO_DCHECK(addr.word_idx < kWords);
-
-      words_[addr.word_idx].Set(addr.bit_idx);
-    }
-
-    // Sets the bit at the given address to false.
-    void Clear(const BlockOffset& addr) {
-      PERFETTO_DCHECK(addr.word_idx < kWords);
-
-      words_[addr.word_idx].Clear(addr.bit_idx);
-    }
-
-    // Gets the offset of the nth set bit in this block.
-    BlockOffset IndexOfNthSet(uint32_t n) const {
-      uint32_t count = 0;
-      for (uint16_t i = 0; i < kWords; ++i) {
-        // Keep a running count of all the set bits in the atom.
-        uint32_t value = count + words_[i].GetNumBitsSet();
-        if (value <= n) {
-          count = value;
-          continue;
-        }
-
-        // The running count of set bits is more than |n|. That means this atom
-        // contains the bit we are looking for.
-
-        // Take away the number of set bits to the start of this atom from |n|.
-        uint32_t set_in_atom = n - count;
-
-        // Figure out the index of the set bit inside the atom and create the
-        // address of this bit from that.
-        uint16_t bit_idx = words_[i].IndexOfNthSet(set_in_atom);
-        PERFETTO_DCHECK(bit_idx < 64);
-        return BlockOffset{i, bit_idx};
-      }
-      PERFETTO_FATAL("Index out of bounds");
-    }
-
-    // Gets the number of set bits within a block up to and including the bit
-    // at the given address.
-    uint32_t GetNumBitsSet(const BlockOffset& addr) const {
-      PERFETTO_DCHECK(addr.word_idx < kWords);
-
-      // Count all the set bits in the atom until we reach the last atom
-      // index.
-      uint32_t count = 0;
-      for (uint32_t i = 0; i < addr.word_idx; ++i) {
-        count += words_[i].GetNumBitsSet();
-      }
-
-      // For the last atom, only count the bits upto and including the bit
-      // index.
-      return count + words_[addr.word_idx].GetNumBitsSet(addr.bit_idx);
-    }
-
-    // Retains all bits up to and including the bit at |addr| and clears
-    // all bits after this point.
-    void ClearAfter(const BlockOffset& offset) {
-      PERFETTO_DCHECK(offset.word_idx < kWords);
-
-      // In the first atom, keep the bits until the address specified.
-      words_[offset.word_idx].ClearAfter(offset.bit_idx);
-
-      // For all subsequent atoms, we just clear the whole atom.
-      for (uint32_t i = offset.word_idx + 1; i < kWords; ++i) {
-        words_[i].ClearAll();
-      }
-    }
-
-    // Set all the bits between the offsets given by |start| and |end|
-    // (inclusive).
-    void Set(const BlockOffset& start, const BlockOffset& end) {
-      if (start.word_idx == end.word_idx) {
-        // If there is only one word we will change, just set the range within
-        // the word.
-        words_[start.word_idx].Set(start.bit_idx, end.bit_idx);
-        return;
-      }
-
-      // Otherwise, we have more than one word to set. To do this, we will
-      // do this in three steps.
-
-      // First, we set the first word from the start to the end of the word.
-      words_[start.word_idx].Set(start.bit_idx, BitWord::kBits - 1);
-
-      // Next, we set all words (except the last).
-      for (uint32_t i = start.word_idx + 1; i < end.word_idx; ++i) {
-        words_[i].Set(0, BitWord::kBits - 1);
-      }
-
-      // Finally, we set the word block from the start to the end offset.
-      words_[end.word_idx].Set(0, end.bit_idx);
-    }
-
-   private:
-    std::array<BitWord, kWords> words_{};
-  };
-
-  BitVector(std::vector<Block> blocks,
-            std::vector<uint32_t> counts,
-            uint32_t size);
-
-  BitVector(const BitVector&) = delete;
-  BitVector& operator=(const BitVector&) = delete;
-
-  // Set all the bits between the addresses given by |start| and |end|
-  // (inclusive).
-  // Note: this method does not update the counts vector - that is the
-  // responibility of the caller.
-  void Set(const Address& start, const Address& end) {
-    static constexpr BlockOffset kFirstBlockOffset = BlockOffset{0, 0};
-    static constexpr BlockOffset kLastBlockOffset =
-        BlockOffset{Block::kWords - 1, BitWord::kBits - 1};
-
-    if (start.block_idx == end.block_idx) {
-      // If there is only one block we will change, just set the range within
-      // the block.
-      blocks_[start.block_idx].Set(start.block_offset, end.block_offset);
-      return;
-    }
-
-    // Otherwise, we have more than one block to set. To do this, we will
-    // do this in three steps.
-
-    // First, we set the first block from the start to the end of the block.
-    blocks_[start.block_idx].Set(start.block_offset, kLastBlockOffset);
-
-    // Next, we set all blocks (except the last).
-    for (uint32_t i = start.block_idx + 1; i < end.block_idx; ++i) {
-      blocks_[i].Set(kFirstBlockOffset, kLastBlockOffset);
-    }
-
-    // Finally, we set the last block from the start to the end offset.
-    blocks_[end.block_idx].Set(kFirstBlockOffset, end.block_offset);
-  }
-
-  static Address IndexToAddress(uint32_t idx) {
-    Address a;
-    a.block_idx = idx / Block::kBits;
-
-    uint16_t bit_idx_inside_block = idx % Block::kBits;
-    a.block_offset.word_idx = bit_idx_inside_block / BitWord::kBits;
-    a.block_offset.bit_idx = bit_idx_inside_block % BitWord::kBits;
-    return a;
-  }
-
-  static uint32_t AddressToIndex(Address addr) {
-    return addr.block_idx * Block::kBits +
-           addr.block_offset.word_idx * BitWord::kBits +
-           addr.block_offset.bit_idx;
-  }
-
-  uint32_t size_ = 0;
-  std::vector<uint32_t> counts_;
-  std::vector<Block> blocks_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_DB_BIT_VECTOR_H_
diff --git a/src/trace_processor/db/bit_vector_benchmark.cc b/src/trace_processor/db/bit_vector_benchmark.cc
deleted file mode 100644
index 6c896d1..0000000
--- a/src/trace_processor/db/bit_vector_benchmark.cc
+++ /dev/null
@@ -1,247 +0,0 @@
-// Copyright (C) 2019 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 <random>
-
-#include <benchmark/benchmark.h>
-
-#include "src/trace_processor/db/bit_vector.h"
-
-namespace {
-
-using perfetto::trace_processor::BitVector;
-
-}
-
-static void BM_BitVectorAppendTrue(benchmark::State& state) {
-  BitVector bv;
-  for (auto _ : state) {
-    bv.AppendTrue();
-    benchmark::ClobberMemory();
-  }
-}
-BENCHMARK(BM_BitVectorAppendTrue);
-
-static void BM_BitVectorAppendFalse(benchmark::State& state) {
-  BitVector bv;
-  for (auto _ : state) {
-    bv.AppendFalse();
-    benchmark::ClobberMemory();
-  }
-}
-BENCHMARK(BM_BitVectorAppendFalse);
-
-static void BM_BitVectorSet(benchmark::State& state) {
-  static constexpr uint32_t kRandomSeed = 42;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-
-  uint32_t size = static_cast<uint32_t>(state.range(0));
-
-  BitVector bv;
-  for (uint32_t i = 0; i < size; ++i) {
-    if (rnd_engine() % 2) {
-      bv.AppendTrue();
-    } else {
-      bv.AppendFalse();
-    }
-  }
-
-  static constexpr uint32_t kPoolSize = 1024 * 1024;
-  std::vector<bool> bit_pool(kPoolSize);
-  std::vector<uint32_t> row_pool(kPoolSize);
-  for (uint32_t i = 0; i < kPoolSize; ++i) {
-    bit_pool[i] = rnd_engine() % 2;
-    row_pool[i] = rnd_engine() % size;
-  }
-
-  uint32_t pool_idx = 0;
-  for (auto _ : state) {
-    bv.Set(row_pool[pool_idx]);
-    pool_idx = (pool_idx + 1) % kPoolSize;
-    benchmark::ClobberMemory();
-  }
-}
-BENCHMARK(BM_BitVectorSet)
-    ->Arg(64)
-    ->Arg(512)
-    ->Arg(8192)
-    ->Arg(123456)
-    ->Arg(1234567);
-
-static void BM_BitVectorClear(benchmark::State& state) {
-  static constexpr uint32_t kRandomSeed = 42;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-
-  uint32_t size = static_cast<uint32_t>(state.range(0));
-
-  BitVector bv;
-  for (uint32_t i = 0; i < size; ++i) {
-    if (rnd_engine() % 2) {
-      bv.AppendTrue();
-    } else {
-      bv.AppendFalse();
-    }
-  }
-
-  static constexpr uint32_t kPoolSize = 1024 * 1024;
-  std::vector<uint32_t> row_pool(kPoolSize);
-  for (uint32_t i = 0; i < kPoolSize; ++i) {
-    row_pool[i] = rnd_engine() % size;
-  }
-
-  uint32_t pool_idx = 0;
-  for (auto _ : state) {
-    bv.Clear(row_pool[pool_idx]);
-    pool_idx = (pool_idx + 1) % kPoolSize;
-    benchmark::ClobberMemory();
-  }
-}
-BENCHMARK(BM_BitVectorClear)
-    ->Arg(64)
-    ->Arg(512)
-    ->Arg(8192)
-    ->Arg(123456)
-    ->Arg(1234567);
-
-static void BM_BitVectorIndexOfNthSet(benchmark::State& state) {
-  static constexpr uint32_t kRandomSeed = 42;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-
-  uint32_t size = static_cast<uint32_t>(state.range(0));
-
-  BitVector bv;
-  for (uint32_t i = 0; i < size; ++i) {
-    if (rnd_engine() % 2) {
-      bv.AppendTrue();
-    } else {
-      bv.AppendFalse();
-    }
-  }
-
-  static constexpr uint32_t kPoolSize = 1024 * 1024;
-  std::vector<uint32_t> row_pool(kPoolSize);
-  uint32_t set_bit_count = bv.GetNumBitsSet();
-  for (uint32_t i = 0; i < kPoolSize; ++i) {
-    row_pool[i] = rnd_engine() % set_bit_count;
-  }
-
-  uint32_t pool_idx = 0;
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(bv.IndexOfNthSet(row_pool[pool_idx]));
-    pool_idx = (pool_idx + 1) % kPoolSize;
-  }
-}
-BENCHMARK(BM_BitVectorIndexOfNthSet)
-    ->Arg(64)
-    ->Arg(512)
-    ->Arg(8192)
-    ->Arg(123456)
-    ->Arg(1234567);
-
-static void BM_BitVectorGetNumBitsSet(benchmark::State& state) {
-  static constexpr uint32_t kRandomSeed = 42;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-
-  uint32_t size = static_cast<uint32_t>(state.range(0));
-
-  uint32_t count = 0;
-  BitVector bv;
-  for (uint32_t i = 0; i < size; ++i) {
-    bool value = rnd_engine() % 2;
-    if (value) {
-      bv.AppendTrue();
-    } else {
-      bv.AppendFalse();
-    }
-
-    if (value)
-      count++;
-  }
-
-  uint32_t res = count;
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(res &= bv.GetNumBitsSet());
-  }
-  PERFETTO_CHECK(res == count);
-}
-BENCHMARK(BM_BitVectorGetNumBitsSet)
-    ->Arg(64)
-    ->Arg(512)
-    ->Arg(8192)
-    ->Arg(123456)
-    ->Arg(1234567);
-
-static void BM_BitVectorResize(benchmark::State& state) {
-  static constexpr uint32_t kRandomSeed = 42;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-
-  static constexpr uint32_t kPoolSize = 1024 * 1024;
-  static constexpr uint32_t kMaxSize = 1234567;
-
-  std::vector<bool> resize_fill_pool(kPoolSize);
-  std::vector<uint32_t> resize_count_pool(kPoolSize);
-  for (uint32_t i = 0; i < kPoolSize; ++i) {
-    resize_fill_pool[i] = rnd_engine() % 2;
-    resize_count_pool[i] = rnd_engine() % kMaxSize;
-  }
-
-  uint32_t pool_idx = 0;
-  BitVector bv;
-  for (auto _ : state) {
-    bv.Resize(resize_count_pool[pool_idx], resize_fill_pool[pool_idx]);
-    pool_idx = (pool_idx + 1) % kPoolSize;
-    benchmark::ClobberMemory();
-  }
-}
-BENCHMARK(BM_BitVectorResize);
-
-static void BM_BitVectorUpdateSetBits(benchmark::State& state) {
-  static constexpr uint32_t kRandomSeed = 42;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-
-  uint32_t size = static_cast<uint32_t>(state.range(0));
-
-  BitVector bv;
-  BitVector picker;
-  for (uint32_t i = 0; i < size; ++i) {
-    bool value = rnd_engine() % 2;
-    if (value) {
-      bv.AppendTrue();
-
-      bool picker_value = rnd_engine() % 2;
-      if (picker_value) {
-        picker.AppendTrue();
-      } else {
-        picker.AppendFalse();
-      }
-    } else {
-      bv.AppendFalse();
-    }
-  }
-
-  for (auto _ : state) {
-    state.PauseTiming();
-    BitVector copy = bv.Copy();
-    state.ResumeTiming();
-
-    copy.UpdateSetBits(picker);
-    benchmark::ClobberMemory();
-  }
-}
-BENCHMARK(BM_BitVectorUpdateSetBits)
-    ->Arg(64)
-    ->Arg(512)
-    ->Arg(8192)
-    ->Arg(123456)
-    ->Arg(1234567);
diff --git a/src/trace_processor/db/bit_vector_iterators.cc b/src/trace_processor/db/bit_vector_iterators.cc
deleted file mode 100644
index 281384c..0000000
--- a/src/trace_processor/db/bit_vector_iterators.cc
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/db/bit_vector_iterators.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace internal {
-
-BaseIterator::BaseIterator(BitVector* bv) : bv_(bv) {
-  size_ = bv->size();
-
-  if (size_ > 0) {
-    block_ = bv_->blocks_[0];
-  }
-}
-
-BaseIterator::~BaseIterator() {
-  if (size_ > 0) {
-    uint32_t block_idx = index_ / BitVector::Block::kBits;
-    uint32_t last_block_idx = static_cast<uint32_t>(bv_->blocks_.size()) - 1;
-
-    // If |index_| == |size_| and the last index was on a block boundary, we
-    // can end up one block past the end of the bitvector. Take the
-    // min of the block index and the last block
-    OnBlockChange(std::min(block_idx, last_block_idx), last_block_idx);
-  }
-}
-
-void BaseIterator::OnBlockChange(uint32_t old_block, uint32_t new_block) {
-  // If we touched the current block, flush the block to the bitvector.
-  if (is_block_changed_) {
-    bv_->blocks_[old_block] = block_;
-  }
-
-  if (set_bit_count_diff_ != 0) {
-    // If the count of set bits has changed, go through all the counts between
-    // the old and new blocks and modify them.
-    // We only need to go to new_block and not to the end of the bitvector as
-    // the blocks after new_block will either be updated in a future call to
-    // OnBlockChange or in the destructor.
-    for (uint32_t i = old_block + 1; i <= new_block; ++i) {
-      int32_t new_count =
-          static_cast<int32_t>(bv_->counts_[i]) + set_bit_count_diff_;
-      PERFETTO_DCHECK(new_count >= 0);
-
-      bv_->counts_[i] = static_cast<uint32_t>(new_count);
-    }
-  }
-
-  // Reset the changed flag and cache the new block.
-  is_block_changed_ = false;
-  block_ = bv_->blocks_[new_block];
-}
-
-AllBitsIterator::AllBitsIterator(const BitVector* bv)
-    : BaseIterator(const_cast<BitVector*>(bv)) {}
-
-SetBitsIterator::SetBitsIterator(const BitVector* bv)
-    : BaseIterator(const_cast<BitVector*>(bv)) {
-  set_bit_count_ = bv->GetNumBitsSet();
-
-  if (set_bit_count_ > 0) {
-    // Read a batch of set bit indices starting at index 0.
-    ReadSetBitBatch(0);
-
-    // Fast forward the iterator to the first index in the freshly read
-    // batch of set bots.
-    SetIndex(batch_[0]);
-  }
-}
-
-void SetBitsIterator::ReadSetBitBatch(uint32_t start_idx) {
-  PERFETTO_DCHECK(set_bit_index_ % kBatchSize == 0);
-
-  uint32_t set_bit_count_until_i = set_bit_index_;
-  for (uint32_t i = start_idx; i < size(); ++i) {
-    auto addr = BitVector::IndexToAddress(i);
-
-    // Compute the count to the end of the block noting that the last block
-    // needs to use |set_bit_count_| and not the next count in the vector
-    // because that is OOB.
-    uint32_t set_bits_to_end_of_block =
-        addr.block_idx == bv().counts_.size() - 1
-            ? set_bit_count_
-            : bv().counts_[addr.block_idx + 1];
-
-    // Optimization: If the count of set bits to the end of the block is the
-    // same as the count to the current index, we can just skip the whole
-    // block without iterating through the bits inside.
-    if (set_bits_to_end_of_block == set_bit_count_until_i) {
-      static constexpr BitVector::BlockOffset kLastBlockOffset = {
-          BitVector::Block::kWords - 1, BitVector::BitWord::kBits - 1};
-
-      i = BitVector::AddressToIndex({addr.block_idx, kLastBlockOffset});
-      continue;
-    }
-
-    // If the bit is not set, just bail out.
-    const auto& block = bv().blocks_[addr.block_idx];
-    if (!block.IsSet(addr.block_offset))
-      continue;
-
-    // Update |batch_| with the index of the current bit.
-    uint32_t batch_idx = set_bit_count_until_i++ % kBatchSize;
-    batch_[batch_idx] = i;
-
-    // If we've reached as many indicies as the batch can store, just
-    // return.
-    if (PERFETTO_UNLIKELY(batch_idx == kBatchSize - 1))
-      return;
-  }
-
-  // We should only get here when we've managed to read all the set bits.
-  // End of batch should return from the body of the loop.
-  PERFETTO_DCHECK(set_bit_count_until_i == set_bit_count_);
-}
-
-}  // namespace internal
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/db/bit_vector_iterators.h b/src/trace_processor/db/bit_vector_iterators.h
deleted file mode 100644
index 365e8ef..0000000
--- a/src/trace_processor/db/bit_vector_iterators.h
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_DB_BIT_VECTOR_ITERATORS_H_
-#define SRC_TRACE_PROCESSOR_DB_BIT_VECTOR_ITERATORS_H_
-
-#include "src/trace_processor/db/bit_vector.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace internal {
-
-// Base iterator class for all iterators on BitVector.
-//
-// This class implements caching of one Block at a time to reduce pointer
-// chasing. It also defers updating counts on Clear calls until the end of each
-// block.
-class BaseIterator {
- public:
-  BaseIterator(BitVector* bv);
-  ~BaseIterator();
-
-  BaseIterator(BaseIterator&&) noexcept = default;
-  BaseIterator& operator=(BaseIterator&&) = default;
-
-  // Sets the current bit the iterator points to.
-  void Set() {
-    if (!IsSet()) {
-      block_.Set(block_offset());
-
-      is_block_changed_ = true;
-      ++set_bit_count_diff_;
-    }
-  }
-
-  // Clears the current bit the iterator points to.
-  void Clear() {
-    if (IsSet()) {
-      block_.Clear(block_offset());
-
-      is_block_changed_ = true;
-      --set_bit_count_diff_;
-    }
-  }
-
-  // Returns whether the current bit the iterator points to is set.
-  bool IsSet() { return block_.IsSet(block_offset()); }
-
-  // Returns the index of the current bit the iterator points to.
-  uint32_t index() const { return index_; }
-
- protected:
-  // Sets the index this iterator points to the given value.
-  //
-  // This method also performs some extra work on block boundaries
-  // as it caches the block to improve performance by reducing pointer
-  // chasing on every IsSet and Clear calls.
-  void SetIndex(uint32_t index) {
-    // We should always move the index forward.
-    PERFETTO_DCHECK(index >= index_);
-
-    uint32_t old_index = index_;
-    index_ = index;
-
-    // If we've reached the end of the iterator, just bail out.
-    if (index >= size_)
-      return;
-
-    uint32_t old_block = old_index / BitVector::Block::kBits;
-    uint32_t new_block = index / BitVector::Block::kBits;
-
-    // Fast path: we're in the same block so we don't need to do
-    // any other work.
-    if (PERFETTO_LIKELY(old_block == new_block))
-      return;
-
-    // Slow path: we have to change block so this will involve flushing the old
-    // block and counts (if necessary) and caching the new block.
-    OnBlockChange(old_block, new_block);
-  }
-
-  // Handles flushing count changes and modified blocks to the bitvector
-  // and caching the new block.
-  void OnBlockChange(uint32_t old_block, uint32_t new_block);
-
-  uint32_t size() const { return size_; }
-
-  const BitVector& bv() const { return *bv_; }
-
- private:
-  BaseIterator(const BaseIterator&) = delete;
-  BaseIterator& operator=(const BaseIterator&) = delete;
-
-  BitVector::BlockOffset block_offset() const {
-    uint16_t bit_idx_inside_block = index_ % BitVector::Block::kBits;
-
-    BitVector::BlockOffset bo;
-    bo.word_idx = bit_idx_inside_block / BitVector::BitWord::kBits;
-    bo.bit_idx = bit_idx_inside_block % BitVector::BitWord::kBits;
-    return bo;
-  }
-
-  uint32_t index_ = 0;
-  uint32_t size_ = 0;
-
-  bool is_block_changed_ = false;
-  int32_t set_bit_count_diff_ = 0;
-
-  BitVector* bv_ = nullptr;
-
-  BitVector::Block block_{};
-};
-
-// Iterator over all the bits in a bitvector.
-class AllBitsIterator : public BaseIterator {
- public:
-  AllBitsIterator(const BitVector*);
-
-  // Increments the iterator to point to the next bit.
-  void Next() { SetIndex(index() + 1); }
-
-  // Returns whether the iterator is valid.
-  operator bool() const { return index() < size(); }
-};
-
-// Iterator over all the set bits in a bitvector.
-//
-// This iterator works by first finding a batch of indices of set bits.
-// Then, the fast path involves simply incrementing a counter to go to
-// the next index in this batch. On every batch boundary, we hit the
-// slow path where we need to find another n set bits.
-class SetBitsIterator : public BaseIterator {
- public:
-  SetBitsIterator(const BitVector*);
-
-  // Increments the iterator to point to the next set bit.
-  void Next() {
-    // If we are out of bounds, just bail out.
-    if (PERFETTO_UNLIKELY(++set_bit_index_ >= set_bit_count_))
-      return;
-
-    if (PERFETTO_UNLIKELY(set_bit_index_ % kBatchSize == 0))
-      ReadSetBitBatch(batch_.back() + 1);
-
-    SetIndex(batch_[set_bit_index_ % kBatchSize]);
-  }
-
-  // Returns whether the iterator is valid.
-  operator bool() const { return set_bit_index_ < set_bit_count_; }
-
-  // Returns the index of the bit interms of set bits (i.e. how many times
-  // Next() has been called).
-  uint32_t ordinal() const { return set_bit_index_; }
-
- private:
-  static constexpr uint32_t kBatchSize = 1024;
-
-  // Reads a full batch of set bit indices from the bitvector and stores them
-  // in |batch_| below.
-  //
-  // This batch of indices is used on the fast path to quickly jump between
-  // set bits.
-  void ReadSetBitBatch(uint32_t start_idx);
-
-  uint32_t set_bit_index_ = 0;
-  uint32_t set_bit_count_ = 0;
-
-  // Contains an array of indexes; each index points to a set bit in the
-  // bitvector.
-  std::array<uint32_t, kBatchSize> batch_;
-};
-
-}  // namespace internal
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_DB_BIT_VECTOR_ITERATORS_H_
diff --git a/src/trace_processor/db/bit_vector_unittest.cc b/src/trace_processor/db/bit_vector_unittest.cc
deleted file mode 100644
index 7b5aad7..0000000
--- a/src/trace_processor/db/bit_vector_unittest.cc
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/db/bit_vector.h"
-
-#include <random>
-
-#include "src/trace_processor/db/bit_vector_iterators.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-TEST(BitVectorUnittest, CreateAllTrue) {
-  BitVector bv(2049, true);
-
-  // Ensure that a selection of interesting bits are set.
-  ASSERT_TRUE(bv.IsSet(0));
-  ASSERT_TRUE(bv.IsSet(1));
-  ASSERT_TRUE(bv.IsSet(511));
-  ASSERT_TRUE(bv.IsSet(512));
-  ASSERT_TRUE(bv.IsSet(2047));
-  ASSERT_TRUE(bv.IsSet(2048));
-}
-
-TEST(BitVectorUnittest, CreateAllFalse) {
-  BitVector bv(2049, false);
-
-  // Ensure that a selection of interesting bits are cleared.
-  ASSERT_FALSE(bv.IsSet(0));
-  ASSERT_FALSE(bv.IsSet(1));
-  ASSERT_FALSE(bv.IsSet(511));
-  ASSERT_FALSE(bv.IsSet(512));
-  ASSERT_FALSE(bv.IsSet(2047));
-  ASSERT_FALSE(bv.IsSet(2048));
-}
-
-TEST(BitVectorUnittest, Set) {
-  BitVector bv(2049, false);
-  bv.Set(0);
-  bv.Set(1);
-  bv.Set(511);
-  bv.Set(512);
-  bv.Set(2047);
-
-  // Ensure the bits we touched are set.
-  ASSERT_TRUE(bv.IsSet(0));
-  ASSERT_TRUE(bv.IsSet(1));
-  ASSERT_TRUE(bv.IsSet(511));
-  ASSERT_TRUE(bv.IsSet(512));
-  ASSERT_TRUE(bv.IsSet(2047));
-
-  // Ensure that a selection of other interestinng bits are
-  // still cleared.
-  ASSERT_FALSE(bv.IsSet(2));
-  ASSERT_FALSE(bv.IsSet(63));
-  ASSERT_FALSE(bv.IsSet(64));
-  ASSERT_FALSE(bv.IsSet(510));
-  ASSERT_FALSE(bv.IsSet(513));
-  ASSERT_FALSE(bv.IsSet(1023));
-  ASSERT_FALSE(bv.IsSet(1024));
-  ASSERT_FALSE(bv.IsSet(2046));
-  ASSERT_FALSE(bv.IsSet(2048));
-  ASSERT_FALSE(bv.IsSet(2048));
-}
-
-TEST(BitVectorUnittest, Clear) {
-  BitVector bv(2049, true);
-  bv.Clear(0);
-  bv.Clear(1);
-  bv.Clear(511);
-  bv.Clear(512);
-  bv.Clear(2047);
-
-  // Ensure the bits we touched are cleared.
-  ASSERT_FALSE(bv.IsSet(0));
-  ASSERT_FALSE(bv.IsSet(1));
-  ASSERT_FALSE(bv.IsSet(511));
-  ASSERT_FALSE(bv.IsSet(512));
-  ASSERT_FALSE(bv.IsSet(2047));
-
-  // Ensure that a selection of other interestinng bits are
-  // still set.
-  ASSERT_TRUE(bv.IsSet(2));
-  ASSERT_TRUE(bv.IsSet(63));
-  ASSERT_TRUE(bv.IsSet(64));
-  ASSERT_TRUE(bv.IsSet(510));
-  ASSERT_TRUE(bv.IsSet(513));
-  ASSERT_TRUE(bv.IsSet(1023));
-  ASSERT_TRUE(bv.IsSet(1024));
-  ASSERT_TRUE(bv.IsSet(2046));
-  ASSERT_TRUE(bv.IsSet(2048));
-}
-
-TEST(BitVectorUnittest, AppendToEmpty) {
-  BitVector bv;
-  bv.AppendTrue();
-  bv.AppendFalse();
-
-  ASSERT_EQ(bv.size(), 2u);
-  ASSERT_TRUE(bv.IsSet(0));
-  ASSERT_FALSE(bv.IsSet(1));
-}
-
-TEST(BitVectorUnittest, AppendToExisting) {
-  BitVector bv(2046, false);
-  bv.AppendTrue();
-  bv.AppendFalse();
-  bv.AppendTrue();
-  bv.AppendTrue();
-
-  ASSERT_EQ(bv.size(), 2050u);
-  ASSERT_TRUE(bv.IsSet(2046));
-  ASSERT_FALSE(bv.IsSet(2047));
-  ASSERT_TRUE(bv.IsSet(2048));
-  ASSERT_TRUE(bv.IsSet(2049));
-}
-
-TEST(BitVectorUnittest, GetNumBitsSet) {
-  BitVector bv(2049, false);
-  bv.Set(0);
-  bv.Set(1);
-  bv.Set(511);
-  bv.Set(512);
-  bv.Set(2047);
-  bv.Set(2048);
-
-  ASSERT_EQ(bv.GetNumBitsSet(), 6u);
-
-  ASSERT_EQ(bv.GetNumBitsSet(0), 0u);
-  ASSERT_EQ(bv.GetNumBitsSet(1), 1u);
-  ASSERT_EQ(bv.GetNumBitsSet(2), 2u);
-  ASSERT_EQ(bv.GetNumBitsSet(3), 2u);
-  ASSERT_EQ(bv.GetNumBitsSet(511), 2u);
-  ASSERT_EQ(bv.GetNumBitsSet(512), 3u);
-  ASSERT_EQ(bv.GetNumBitsSet(1023), 4u);
-  ASSERT_EQ(bv.GetNumBitsSet(1024), 4u);
-  ASSERT_EQ(bv.GetNumBitsSet(2047), 4u);
-  ASSERT_EQ(bv.GetNumBitsSet(2048), 5u);
-  ASSERT_EQ(bv.GetNumBitsSet(2049), 6u);
-}
-
-TEST(BitVectorUnittest, IndexOfNthSet) {
-  BitVector bv(2050, false);
-  bv.Set(0);
-  bv.Set(1);
-  bv.Set(511);
-  bv.Set(512);
-  bv.Set(2047);
-  bv.Set(2048);
-
-  ASSERT_EQ(bv.IndexOfNthSet(0), 0u);
-  ASSERT_EQ(bv.IndexOfNthSet(1), 1u);
-  ASSERT_EQ(bv.IndexOfNthSet(2), 511u);
-  ASSERT_EQ(bv.IndexOfNthSet(3), 512u);
-  ASSERT_EQ(bv.IndexOfNthSet(4), 2047u);
-  ASSERT_EQ(bv.IndexOfNthSet(5), 2048u);
-}
-
-TEST(BitVectorUnittest, Resize) {
-  BitVector bv(1, false);
-
-  bv.Resize(2, true);
-  ASSERT_EQ(bv.size(), 2u);
-  ASSERT_EQ(bv.IsSet(1), true);
-
-  bv.Resize(2049, false);
-  ASSERT_EQ(bv.size(), 2049u);
-  ASSERT_EQ(bv.IsSet(2), false);
-  ASSERT_EQ(bv.IsSet(2047), false);
-  ASSERT_EQ(bv.IsSet(2048), false);
-
-  // Set these two bits; the first should be preserved and the
-  // second should disappear.
-  bv.Set(512);
-  bv.Set(513);
-
-  bv.Resize(513, false);
-  ASSERT_EQ(bv.size(), 513u);
-  ASSERT_EQ(bv.IsSet(1), true);
-  ASSERT_EQ(bv.IsSet(512), true);
-  ASSERT_EQ(bv.GetNumBitsSet(), 2u);
-
-  // When we resize up, we need to be sure that the set bit from
-  // before we resized down is not still present as a garbage bit.
-  bv.Resize(514, false);
-  ASSERT_EQ(bv.size(), 514u);
-  ASSERT_EQ(bv.IsSet(513), false);
-  ASSERT_EQ(bv.GetNumBitsSet(), 2u);
-}
-
-TEST(BitVectorUnittest, ResizeHasCorrectCount) {
-  BitVector bv(1, false);
-  ASSERT_EQ(bv.GetNumBitsSet(), 0u);
-
-  bv.Resize(1024, true);
-  ASSERT_EQ(bv.GetNumBitsSet(), 1023u);
-}
-
-TEST(BitVectorUnittest, AppendAfterResizeDown) {
-  BitVector bv(2049, false);
-  bv.Set(2048);
-
-  bv.Resize(2048);
-  bv.AppendFalse();
-  ASSERT_EQ(bv.IsSet(2048), false);
-  ASSERT_EQ(bv.GetNumBitsSet(), 0u);
-}
-
-TEST(BitVectorUnittest, UpdateSetBits) {
-  BitVector bv(6, false);
-  bv.Set(1);
-  bv.Set(2);
-  bv.Set(4);
-
-  BitVector picker(3u, true);
-  picker.Clear(1);
-
-  bv.UpdateSetBits(picker);
-
-  ASSERT_TRUE(bv.IsSet(1));
-  ASSERT_FALSE(bv.IsSet(2));
-  ASSERT_TRUE(bv.IsSet(4));
-}
-
-TEST(BitVectorUnittest, IterateAllBitsConst) {
-  BitVector bv;
-  for (uint32_t i = 0; i < 12345; ++i) {
-    if (i % 7 == 0 || i % 13 == 0) {
-      bv.AppendTrue();
-    } else {
-      bv.AppendFalse();
-    }
-  }
-
-  uint32_t i = 0;
-  for (auto it = bv.IterateAllBits(); it; it.Next(), ++i) {
-    ASSERT_EQ(it.IsSet(), i % 7 == 0 || i % 13 == 0);
-    ASSERT_EQ(it.index(), i);
-  }
-}
-
-TEST(BitVectorUnittest, IterateAllBitsSet) {
-  BitVector bv;
-  for (uint32_t i = 0; i < 12345; ++i) {
-    if (i % 7 == 0 || i % 13 == 0) {
-      bv.AppendTrue();
-    } else {
-      bv.AppendFalse();
-    }
-  }
-
-  // Unset every 15th bit.
-  for (auto it = bv.IterateAllBits(); it; it.Next()) {
-    if (it.index() % 15 == 0) {
-      it.Set();
-    }
-  }
-
-  // Go through the iterator manually and check it has updated
-  // to not have every 15th bit set.
-  uint32_t count = 0;
-  for (uint32_t i = 0; i < 12345; ++i) {
-    bool is_set = i % 15 == 0 || i % 7 == 0 || i % 13 == 0;
-
-    ASSERT_EQ(bv.IsSet(i), is_set);
-    ASSERT_EQ(bv.GetNumBitsSet(i), count);
-
-    if (is_set) {
-      ASSERT_EQ(bv.IndexOfNthSet(count++), i);
-    }
-  }
-}
-
-TEST(BitVectorUnittest, IterateAllBitsClear) {
-  BitVector bv;
-  for (uint32_t i = 0; i < 12345; ++i) {
-    if (i % 7 == 0 || i % 13 == 0) {
-      bv.AppendTrue();
-    } else {
-      bv.AppendFalse();
-    }
-  }
-
-  // Unset every 15th bit.
-  for (auto it = bv.IterateAllBits(); it; it.Next()) {
-    if (it.index() % 15 == 0) {
-      it.Clear();
-    }
-  }
-
-  // Go through the iterator manually and check it has updated
-  // to not have every 15th bit set.
-  uint32_t count = 0;
-  for (uint32_t i = 0; i < 12345; ++i) {
-    bool is_set = i % 15 != 0 && (i % 7 == 0 || i % 13 == 0);
-
-    ASSERT_EQ(bv.IsSet(i), is_set);
-    ASSERT_EQ(bv.GetNumBitsSet(i), count);
-
-    if (is_set) {
-      ASSERT_EQ(bv.IndexOfNthSet(count++), i);
-    }
-  }
-}
-
-TEST(BitVectorUnittest, IterateSetBitsConst) {
-  BitVector bv;
-  std::vector<uint32_t> set_indices;
-  for (uint32_t i = 0; i < 12345; ++i) {
-    if (i % 7 == 0 || i % 13 == 0) {
-      bv.AppendTrue();
-      set_indices.emplace_back(i);
-    } else {
-      bv.AppendFalse();
-    }
-  }
-
-  uint32_t i = 0;
-  for (auto it = bv.IterateSetBits(); it; it.Next(), ++i) {
-    ASSERT_EQ(it.IsSet(), true);
-    ASSERT_EQ(it.index(), set_indices[i]);
-  }
-  ASSERT_EQ(i, set_indices.size());
-}
-
-TEST(BitVectorUnittest, IterateSetBitsClear) {
-  BitVector bv;
-  for (uint32_t i = 0; i < 12345; ++i) {
-    if (i % 7 == 0 || i % 13 == 0) {
-      bv.AppendTrue();
-    } else {
-      bv.AppendFalse();
-    }
-  }
-
-  for (auto it = bv.IterateSetBits(); it; it.Next()) {
-    if (it.index() % 15 == 0) {
-      it.Clear();
-    }
-  }
-
-  // Go through the iterator manually and check it has updated
-  // to not have every 15th bit set.
-  uint32_t count = 0;
-  for (uint32_t i = 0; i < 12345; ++i) {
-    bool is_set = i % 15 != 0 && (i % 7 == 0 || i % 13 == 0);
-
-    ASSERT_EQ(bv.IsSet(i), is_set);
-    ASSERT_EQ(bv.GetNumBitsSet(i), count);
-
-    if (is_set) {
-      ASSERT_EQ(bv.IndexOfNthSet(count++), i);
-    }
-  }
-}
-
-TEST(BitVectorUnittest, IterateSetBitsStartsCorrectly) {
-  BitVector bv;
-  bv.AppendFalse();
-  bv.AppendTrue();
-
-  auto it = bv.IterateSetBits();
-  ASSERT_TRUE(it);
-  ASSERT_EQ(it.index(), 1u);
-  ASSERT_TRUE(it.IsSet());
-
-  it.Next();
-  ASSERT_FALSE(it);
-}
-
-TEST(BitVectorUnittest, QueryStressTest) {
-  BitVector bv;
-  std::vector<bool> bool_vec;
-  std::vector<uint32_t> int_vec;
-
-  static constexpr uint32_t kCount = 4096;
-  std::minstd_rand0 rand;
-  for (uint32_t i = 0; i < kCount; ++i) {
-    bool res = rand() % 2u;
-    if (res) {
-      bv.AppendTrue();
-    } else {
-      bv.AppendFalse();
-    }
-    bool_vec.push_back(res);
-    if (res)
-      int_vec.emplace_back(i);
-  }
-
-  auto all_it = bv.IterateAllBits();
-  for (uint32_t i = 0; i < kCount; ++i) {
-    uint32_t count = static_cast<uint32_t>(std::count(
-        bool_vec.begin(), bool_vec.begin() + static_cast<int32_t>(i), true));
-    ASSERT_EQ(bv.IsSet(i), bool_vec[i]);
-    ASSERT_EQ(bv.GetNumBitsSet(i), count);
-
-    ASSERT_TRUE(all_it);
-    ASSERT_EQ(all_it.IsSet(), bool_vec[i]);
-    ASSERT_EQ(all_it.index(), i);
-    all_it.Next();
-  }
-  ASSERT_FALSE(all_it);
-
-  auto set_it = bv.IterateSetBits();
-  for (uint32_t i = 0; i < int_vec.size(); ++i) {
-    ASSERT_EQ(bv.IndexOfNthSet(i), int_vec[i]);
-
-    ASSERT_TRUE(set_it);
-    ASSERT_EQ(set_it.IsSet(), true);
-    ASSERT_EQ(set_it.index(), int_vec[i]);
-    set_it.Next();
-  }
-  ASSERT_FALSE(set_it);
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/db/column.cc b/src/trace_processor/db/column.cc
deleted file mode 100644
index 0fbe66e..0000000
--- a/src/trace_processor/db/column.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/db/column.h"
-
-#include "src/trace_processor/db/table.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-Column::Column(const Column& column,
-               Table* table,
-               uint32_t col_idx,
-               uint32_t row_map_idx)
-    : Column(column.name_,
-             column.type_,
-             column.flags_,
-             table,
-             col_idx,
-             row_map_idx,
-             column.sparse_vector_) {}
-
-Column::Column(const char* name,
-               ColumnType type,
-               uint32_t flags,
-               Table* table,
-               uint32_t col_idx,
-               uint32_t row_map_idx,
-               void* sparse_vector)
-    : type_(type),
-      sparse_vector_(sparse_vector),
-      name_(name),
-      flags_(flags),
-      table_(table),
-      col_idx_(col_idx),
-      row_map_idx_(row_map_idx),
-      string_pool_(table->string_pool_) {}
-
-Column Column::IdColumn(Table* table, uint32_t col_idx, uint32_t row_map_idx) {
-  return Column("id", ColumnType::kId,
-                Flag::kId | Flag::kSorted | Flag::kNonNull, table, col_idx,
-                row_map_idx, nullptr);
-}
-
-const RowMap& Column::row_map() const {
-  return table_->row_maps_[row_map_idx_];
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/db/column.h b/src/trace_processor/db/column.h
deleted file mode 100644
index fdcce59..0000000
--- a/src/trace_processor/db/column.h
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_DB_COLUMN_H_
-#define SRC_TRACE_PROCESSOR_DB_COLUMN_H_
-
-#include <stdint.h>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/trace_processor/basic_types.h"
-#include "src/trace_processor/db/row_map.h"
-#include "src/trace_processor/db/sparse_vector.h"
-#include "src/trace_processor/string_pool.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Represents the possible filter operations on a column.
-enum class FilterOp {
-  kEq,
-  kNe,
-  kGt,
-  kLt,
-  kGe,
-  kLe,
-  kIsNull,
-  kIsNotNull,
-  kLike,
-};
-
-// Represents a constraint on a column.
-struct Constraint {
-  uint32_t col_idx;
-  FilterOp op;
-  SqlValue value;
-};
-
-// Represents an order by operation on a column.
-struct Order {
-  uint32_t col_idx;
-  bool desc;
-};
-
-// Represents a column which is to be joined on.
-struct JoinKey {
-  uint32_t col_idx;
-};
-
-class Table;
-
-// Represents a named, strongly typed list of data.
-class Column {
- public:
-  // Flags which indicate properties of the data in the column. These features
-  // are used to speed up column methods like filtering/sorting.
-  enum Flag : uint32_t {
-    // Indicates that this column has no special properties.
-    kNoFlag = 0,
-
-    // Indiciates that the column is an "id" column. Specifically, this means
-    // the backing data for this column has the property that data[i] = i;
-    //
-    // Note: generally, this flag should not be passed by users of this class.
-    // Instead they should use the Column::IdColumn method to create an id
-    // column.
-    kId = 1 << 0,
-
-    // Indicates the data in the column is sorted. This can be used to speed
-    // up filtering and skip sorting.
-    kSorted = 1 << 1,
-
-    // Indicates the data in the column is non-null. That is, the SparseVector
-    // passed in will never have any null entries. This is only used for
-    // numeric columns (string columns and id columns both have special
-    // handling which ignores this flag).
-    //
-    // This is used to speed up filters as we can safely index SparseVector
-    // directly if this flag is set.
-    kNonNull = 1 << 2
-  };
-
-  template <typename T>
-  Column(const char* name,
-         SparseVector<T>* storage,
-         /* Flag */ uint32_t flags,
-         Table* table,
-         uint32_t col_idx,
-         uint32_t row_map_idx)
-      : Column(name,
-               ToColumnType<T>(),
-               flags,
-               table,
-               col_idx,
-               row_map_idx,
-               storage) {}
-
-  // Create a Column has the same name and is backed by the same data as
-  // |column| but is associated to a different table.
-  Column(const Column& column,
-         Table* table,
-         uint32_t col_idx,
-         uint32_t row_map_idx);
-
-  // Columns are movable but not copyable.
-  Column(Column&&) noexcept = default;
-  Column& operator=(Column&&) = default;
-
-  // Creates a Column which returns the index as the value of the row.
-  static Column IdColumn(Table* table, uint32_t col_idx, uint32_t row_map_idx);
-
-  // Gets the value of the Column at the given |row|.
-  SqlValue Get(uint32_t row) const { return GetAtIdx(row_map().Get(row)); }
-
-  // Returns the row containing the given value in the Column.
-  base::Optional<uint32_t> IndexOf(SqlValue value) const {
-    switch (type_) {
-      // TODO(lalitm): investigate whether we could make this more efficient
-      // by first checking the type of the column and comparing explicitly
-      // based on that type.
-      case ColumnType::kInt32:
-      case ColumnType::kUint32:
-      case ColumnType::kInt64:
-      case ColumnType::kString: {
-        for (uint32_t i = 0; i < row_map().size(); i++) {
-          if (Get(i) == value)
-            return i;
-        }
-        return base::nullopt;
-      }
-      case ColumnType::kId: {
-        if (value.type != SqlValue::Type::kLong)
-          return base::nullopt;
-        return row_map().IndexOf(static_cast<uint32_t>(value.long_value));
-      }
-    }
-    PERFETTO_FATAL("For GCC");
-  }
-
-  // Updates the given RowMap by only keeping rows where this column meets the
-  // given filter constraint.
-  void FilterInto(FilterOp op, SqlValue value, RowMap* rm) const {
-    // TODO(lalitm): add special logic here to deal with kId and kSorted flags.
-    if (type_ == ColumnType::kId && op == FilterOp::kEq) {
-      auto opt_idx = IndexOf(value);
-      if (opt_idx) {
-        rm->Intersect(RowMap::SingleRow(*opt_idx));
-      } else {
-        rm->Intersect(RowMap());
-      }
-      return;
-    }
-    switch (type_) {
-      case ColumnType::kInt32: {
-        if (IsNullable()) {
-          FilterIntoLongSlow<int32_t, true /* is_nullable */>(op, value, rm);
-        } else {
-          FilterIntoLongSlow<int32_t, false /* is_nullable */>(op, value, rm);
-        }
-        break;
-      }
-      case ColumnType::kUint32: {
-        if (IsNullable()) {
-          FilterIntoLongSlow<uint32_t, true /* is_nullable */>(op, value, rm);
-        } else {
-          FilterIntoLongSlow<uint32_t, false /* is_nullable */>(op, value, rm);
-        }
-        break;
-      }
-      case ColumnType::kInt64: {
-        if (IsNullable()) {
-          FilterIntoLongSlow<int64_t, true /* is_nullable */>(op, value, rm);
-        } else {
-          FilterIntoLongSlow<int64_t, false /* is_nullable */>(op, value, rm);
-        }
-        break;
-      }
-      case ColumnType::kString: {
-        FilterIntoStringSlow(op, value, rm);
-        break;
-      }
-      case ColumnType::kId: {
-        FilterIntoIdSlow(op, value, rm);
-        break;
-      }
-    }
-  }
-
-  // Returns true if this column is considered an id column.
-  bool IsId() const { return (flags_ & Flag::kId) != 0; }
-
-  // Returns true if this column is a nullable column.
-  bool IsNullable() const { return (flags_ & Flag::kNonNull) == 0; }
-
-  const RowMap& row_map() const;
-  const char* name() const { return name_; }
-  SqlValue::Type type() const {
-    switch (type_) {
-      case ColumnType::kInt32:
-      case ColumnType::kUint32:
-      case ColumnType::kInt64:
-      case ColumnType::kId:
-        return SqlValue::Type::kLong;
-      case ColumnType::kString:
-        return SqlValue::Type::kString;
-    }
-    PERFETTO_FATAL("For GCC");
-  }
-
-  // Returns a Constraint for each type of filter operation for this Column.
-  Constraint eq(SqlValue value) const {
-    return Constraint{col_idx_, FilterOp::kEq, value};
-  }
-  Constraint gt(SqlValue value) const {
-    return Constraint{col_idx_, FilterOp::kGt, value};
-  }
-  Constraint lt(SqlValue value) const {
-    return Constraint{col_idx_, FilterOp::kLt, value};
-  }
-  Constraint ne(SqlValue value) const {
-    return Constraint{col_idx_, FilterOp::kNe, value};
-  }
-  Constraint ge(SqlValue value) const {
-    return Constraint{col_idx_, FilterOp::kGe, value};
-  }
-  Constraint le(SqlValue value) const {
-    return Constraint{col_idx_, FilterOp::kLe, value};
-  }
-  Constraint is_not_null() const {
-    return Constraint{col_idx_, FilterOp::kIsNotNull, SqlValue()};
-  }
-  Constraint is_null() const {
-    return Constraint{col_idx_, FilterOp::kIsNull, SqlValue()};
-  }
-
-  // Returns an Order for each Order type for this Column.
-  Order ascending() const { return Order{col_idx_, false}; }
-  Order descending() const { return Order{col_idx_, true}; }
-
-  // Returns the JoinKey for this Column.
-  JoinKey join_key() const { return JoinKey{col_idx_}; }
-
- protected:
-  NullTermStringView GetStringPoolStringAtIdx(uint32_t idx) const {
-    return string_pool_->Get(sparse_vector<StringPool::Id>().GetNonNull(idx));
-  }
-
-  template <typename T>
-  SparseVector<T>* mutable_sparse_vector() {
-    PERFETTO_DCHECK(ToColumnType<T>() == type_);
-    return static_cast<SparseVector<T>*>(sparse_vector_);
-  }
-
-  template <typename T>
-  const SparseVector<T>& sparse_vector() const {
-    PERFETTO_DCHECK(ToColumnType<T>() == type_);
-    return *static_cast<const SparseVector<T>*>(sparse_vector_);
-  }
-
- private:
-  enum class ColumnType {
-    // Standard primitive types.
-    kInt32,
-    kUint32,
-    kInt64,
-    kString,
-
-    // Types generated on the fly.
-    kId,
-  };
-
-  friend class Table;
-
-  Column(const char* name,
-         ColumnType type,
-         uint32_t flags,
-         Table* table,
-         uint32_t col_idx,
-         uint32_t row_map_idx,
-         void* sparse_vector);
-
-  Column(const Column&) = delete;
-  Column& operator=(const Column&) = delete;
-
-  // Gets the value of the Column at the given |row|.
-  SqlValue GetAtIdx(uint32_t idx) const {
-    switch (type_) {
-      case ColumnType::kInt32: {
-        auto opt_value = sparse_vector<int32_t>().Get(idx);
-        return opt_value ? SqlValue::Long(*opt_value) : SqlValue();
-      }
-      case ColumnType::kUint32: {
-        auto opt_value = sparse_vector<uint32_t>().Get(idx);
-        return opt_value ? SqlValue::Long(*opt_value) : SqlValue();
-      }
-      case ColumnType::kInt64: {
-        auto opt_value = sparse_vector<int64_t>().Get(idx);
-        return opt_value ? SqlValue::Long(*opt_value) : SqlValue();
-      }
-      case ColumnType::kString: {
-        auto str = GetStringPoolStringAtIdx(idx).c_str();
-        return str == nullptr ? SqlValue() : SqlValue::String(str);
-      }
-      case ColumnType::kId:
-        return SqlValue::Long(idx);
-    }
-    PERFETTO_FATAL("For GCC");
-  }
-
-  template <typename T, bool is_nullable>
-  void FilterIntoLongSlow(FilterOp op, SqlValue value, RowMap* rm) const {
-    if (op == FilterOp::kIsNull) {
-      PERFETTO_DCHECK(value.is_null());
-      if (is_nullable) {
-        row_map().FilterInto(rm, [this](uint32_t row) {
-          return !sparse_vector<T>().Get(row).has_value();
-        });
-      } else {
-        rm->Intersect(RowMap());
-      }
-      return;
-    } else if (op == FilterOp::kIsNotNull) {
-      PERFETTO_DCHECK(value.is_null());
-      if (is_nullable) {
-        row_map().FilterInto(rm, [this](uint32_t row) {
-          return sparse_vector<T>().Get(row).has_value();
-        });
-      }
-      return;
-    }
-
-    int64_t long_value = value.long_value;
-    switch (op) {
-      case FilterOp::kLt:
-        row_map().FilterInto(rm, [this, long_value](uint32_t idx) {
-          if (is_nullable)
-            return sparse_vector<T>().Get(idx) < long_value;
-          return sparse_vector<T>().GetNonNull(idx) < long_value;
-        });
-        break;
-      case FilterOp::kEq:
-        row_map().FilterInto(rm, [this, long_value](uint32_t idx) {
-          if (is_nullable)
-            return sparse_vector<T>().Get(idx) == long_value;
-          return sparse_vector<T>().GetNonNull(idx) == long_value;
-        });
-        break;
-      case FilterOp::kGt:
-        row_map().FilterInto(rm, [this, long_value](uint32_t idx) {
-          if (is_nullable)
-            return sparse_vector<T>().Get(idx) > long_value;
-          return sparse_vector<T>().GetNonNull(idx) > long_value;
-        });
-        break;
-      case FilterOp::kNe:
-        row_map().FilterInto(rm, [this, long_value](uint32_t idx) {
-          if (is_nullable)
-            return sparse_vector<T>().GetNonNull(idx) != long_value;
-          return sparse_vector<T>().Get(idx) != long_value;
-        });
-        break;
-      case FilterOp::kLe:
-        row_map().FilterInto(rm, [this, long_value](uint32_t idx) {
-          if (is_nullable)
-            return sparse_vector<T>().GetNonNull(idx) <= long_value;
-          return sparse_vector<T>().Get(idx) <= long_value;
-        });
-        break;
-      case FilterOp::kGe:
-        row_map().FilterInto(rm, [this, long_value](uint32_t idx) {
-          if (is_nullable)
-            return sparse_vector<T>().GetNonNull(idx) >= long_value;
-          return sparse_vector<T>().Get(idx) >= long_value;
-        });
-        break;
-      case FilterOp::kLike:
-        rm->Intersect(RowMap());
-        break;
-      case FilterOp::kIsNull:
-      case FilterOp::kIsNotNull:
-        PERFETTO_FATAL("Should be handled above");
-    }
-  }
-
-  void FilterIntoStringSlow(FilterOp op, SqlValue value, RowMap* rm) const {
-    if (op == FilterOp::kIsNull) {
-      PERFETTO_DCHECK(value.is_null());
-      row_map().FilterInto(rm, [this](uint32_t row) {
-        return GetStringPoolStringAtIdx(row).data() == nullptr;
-      });
-      return;
-    } else if (op == FilterOp::kIsNotNull) {
-      PERFETTO_DCHECK(value.is_null());
-      row_map().FilterInto(rm, [this](uint32_t row) {
-        return GetStringPoolStringAtIdx(row).data() == nullptr;
-      });
-      return;
-    }
-
-    NullTermStringView str_value = value.string_value;
-    switch (op) {
-      case FilterOp::kLt:
-        row_map().FilterInto(rm, [this, str_value](uint32_t idx) {
-          return GetStringPoolStringAtIdx(idx) < str_value;
-        });
-        break;
-      case FilterOp::kEq:
-        row_map().FilterInto(rm, [this, str_value](uint32_t idx) {
-          return GetStringPoolStringAtIdx(idx) == str_value;
-        });
-        break;
-      case FilterOp::kGt:
-        row_map().FilterInto(rm, [this, str_value](uint32_t idx) {
-          return GetStringPoolStringAtIdx(idx) > str_value;
-        });
-        break;
-      case FilterOp::kNe:
-        row_map().FilterInto(rm, [this, str_value](uint32_t idx) {
-          return GetStringPoolStringAtIdx(idx) != str_value;
-        });
-        break;
-      case FilterOp::kLe:
-        row_map().FilterInto(rm, [this, str_value](uint32_t idx) {
-          return GetStringPoolStringAtIdx(idx) <= str_value;
-        });
-        break;
-      case FilterOp::kGe:
-        row_map().FilterInto(rm, [this, str_value](uint32_t idx) {
-          return GetStringPoolStringAtIdx(idx) >= str_value;
-        });
-        break;
-      case FilterOp::kLike:
-        // TODO(lalitm): either call through to SQLite or reimplement
-        // like ourselves.
-        PERFETTO_DLOG("Ignoring like constraint on string column");
-        break;
-      case FilterOp::kIsNull:
-      case FilterOp::kIsNotNull:
-        PERFETTO_FATAL("Should be handled above");
-    }
-  }
-
-  void FilterIntoIdSlow(FilterOp op, SqlValue value, RowMap* rm) const {
-    if (op == FilterOp::kIsNull) {
-      PERFETTO_DCHECK(value.is_null());
-      row_map().FilterInto(rm, [](uint32_t) { return false; });
-      return;
-    } else if (op == FilterOp::kIsNotNull) {
-      PERFETTO_DCHECK(value.is_null());
-      row_map().FilterInto(rm, [](uint32_t) { return true; });
-      return;
-    }
-
-    uint32_t id_value = static_cast<uint32_t>(value.long_value);
-    switch (op) {
-      case FilterOp::kLt:
-        row_map().FilterInto(
-            rm, [id_value](uint32_t idx) { return idx < id_value; });
-        break;
-      case FilterOp::kEq:
-        row_map().FilterInto(
-            rm, [id_value](uint32_t idx) { return idx == id_value; });
-        break;
-      case FilterOp::kGt:
-        row_map().FilterInto(
-            rm, [id_value](uint32_t idx) { return idx > id_value; });
-        break;
-      case FilterOp::kNe:
-        row_map().FilterInto(
-            rm, [id_value](uint32_t idx) { return idx != id_value; });
-        break;
-      case FilterOp::kLe:
-        row_map().FilterInto(
-            rm, [id_value](uint32_t idx) { return idx <= id_value; });
-        break;
-      case FilterOp::kGe:
-        row_map().FilterInto(
-            rm, [id_value](uint32_t idx) { return idx >= id_value; });
-        break;
-      case FilterOp::kLike:
-        rm->Intersect(RowMap());
-        break;
-      case FilterOp::kIsNull:
-      case FilterOp::kIsNotNull:
-        PERFETTO_FATAL("Should be handled above");
-    }
-  }
-
-  template <typename T>
-  static ColumnType ToColumnType() {
-    if (std::is_same<T, uint32_t>::value) {
-      return ColumnType::kUint32;
-    } else if (std::is_same<T, int64_t>::value) {
-      return ColumnType::kInt64;
-    } else if (std::is_same<T, int32_t>::value) {
-      return ColumnType::kInt32;
-    } else if (std::is_same<T, StringPool::Id>::value) {
-      return ColumnType::kString;
-    } else {
-      PERFETTO_FATAL("Unsupported type of column");
-    }
-  }
-
-  // type_ is used to cast sparse_vector_ to the correct type.
-  ColumnType type_ = ColumnType::kInt64;
-  void* sparse_vector_ = nullptr;
-
-  const char* name_ = nullptr;
-  uint32_t flags_ = Flag::kNoFlag;
-  const Table* table_ = nullptr;
-  uint32_t col_idx_ = 0;
-  uint32_t row_map_idx_ = 0;
-  const StringPool* string_pool_ = nullptr;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_DB_COLUMN_H_
diff --git a/src/trace_processor/db/row_map.cc b/src/trace_processor/db/row_map.cc
deleted file mode 100644
index cb16e4d..0000000
--- a/src/trace_processor/db/row_map.cc
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/db/row_map.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-
-RowMap SelectRangeWithRange(uint32_t start,
-                            uint32_t end,
-                            uint32_t selector_start,
-                            uint32_t selector_end) {
-  PERFETTO_DCHECK(start <= end);
-  PERFETTO_DCHECK(selector_start <= selector_end);
-  PERFETTO_DCHECK(selector_end <= end - start);
-
-  return RowMap(start + selector_start, start + selector_end);
-}
-
-RowMap SelectRangeWithBv(uint32_t start,
-                         uint32_t end,
-                         const BitVector& selector) {
-  PERFETTO_DCHECK(start <= end);
-  PERFETTO_DCHECK(end - start == selector.size());
-
-  // If |start| == 0 and |end - start| == |selector.size()| (which is a
-  // precondition for this function), the BitVector we generate is going to be
-  // exactly |selector|.
-  //
-  // This is a fast path for the common situation where, post-filtering,
-  // SelectRows is called on all the table RowMaps with a BitVector. The self
-  // RowMap will always be a range so we expect this case to be hit at least
-  // once every filter operation.
-  if (start == 0u)
-    return RowMap(selector.Copy());
-
-  BitVector bv(start, false);
-  bv.Resize(end, true);
-  bv.UpdateSetBits(selector);
-  return RowMap(std::move(bv));
-}
-
-RowMap SelectRangeWithIv(uint32_t start,
-                         uint32_t end,
-                         const std::vector<uint32_t>& selector) {
-  PERFETTO_DCHECK(start <= end);
-
-  std::vector<uint32_t> iv(selector.size());
-  for (uint32_t i = 0; i < selector.size(); ++i) {
-    PERFETTO_DCHECK(selector[i] < end - start);
-    iv[i] = selector[i] + start;
-  }
-  return RowMap(std::move(iv));
-}
-
-RowMap SelectBvWithRange(const BitVector& bv,
-                         uint32_t selector_start,
-                         uint32_t selector_end) {
-  PERFETTO_DCHECK(selector_start <= selector_end);
-  PERFETTO_DCHECK(selector_end <= bv.GetNumBitsSet());
-
-  BitVector ret = bv.Copy();
-  for (auto it = ret.IterateSetBits(); it; it.Next()) {
-    auto set_idx = it.ordinal();
-    if (set_idx < selector_start || set_idx >= selector_end)
-      it.Clear();
-  }
-  return RowMap(std::move(ret));
-}
-
-RowMap SelectBvWithBv(const BitVector& bv, const BitVector& selector) {
-  BitVector ret = bv.Copy();
-  ret.UpdateSetBits(selector);
-  return RowMap(std::move(ret));
-}
-
-RowMap SelectBvWithIv(const BitVector& bv,
-                      const std::vector<uint32_t>& selector) {
-  std::vector<uint32_t> iv(selector.size());
-  for (uint32_t i = 0; i < selector.size(); ++i) {
-    // TODO(lalitm): this is pretty inefficient.
-    iv[i] = bv.IndexOfNthSet(selector[i]);
-  }
-  return RowMap(std::move(iv));
-}
-
-RowMap SelectIvWithRange(const std::vector<uint32_t>& iv,
-                         uint32_t selector_start,
-                         uint32_t selector_end) {
-  PERFETTO_DCHECK(selector_start <= selector_end);
-  PERFETTO_DCHECK(selector_end <= iv.size());
-
-  std::vector<uint32_t> ret(selector_end - selector_start);
-  for (uint32_t i = selector_start; i < selector_end; ++i) {
-    ret[i - selector_start] = iv[i];
-  }
-  return RowMap(std::move(ret));
-}
-
-RowMap SelectIvWithBv(const std::vector<uint32_t>& iv,
-                      const BitVector& selector) {
-  std::vector<uint32_t> copy = iv;
-  uint32_t idx = 0;
-  auto it = std::remove_if(
-      copy.begin(), copy.end(),
-      [&idx, &selector](uint32_t) { return !selector.IsSet(idx++); });
-  copy.erase(it, copy.end());
-  return RowMap(std::move(copy));
-}
-
-RowMap SelectIvWithIv(const std::vector<uint32_t>& iv,
-                      const std::vector<uint32_t>& selector) {
-  std::vector<uint32_t> ret(selector.size());
-  for (uint32_t i = 0; i < selector.size(); ++i) {
-    PERFETTO_DCHECK(selector[i] < iv.size());
-    ret[i] = iv[selector[i]];
-  }
-  return RowMap(std::move(ret));
-}
-
-}  // namespace
-
-RowMap::RowMap() : RowMap(0, 0) {}
-
-RowMap::RowMap(uint32_t start, uint32_t end)
-    : mode_(Mode::kRange), start_idx_(start), end_idx_(end) {}
-
-RowMap::RowMap(BitVector bit_vector)
-    : mode_(Mode::kBitVector), bit_vector_(std::move(bit_vector)) {}
-
-RowMap::RowMap(std::vector<uint32_t> vec)
-    : mode_(Mode::kIndexVector), index_vector_(std::move(vec)) {}
-
-RowMap RowMap::Copy() const {
-  switch (mode_) {
-    case Mode::kRange:
-      return RowMap(start_idx_, end_idx_);
-    case Mode::kBitVector:
-      return RowMap(bit_vector_.Copy());
-    case Mode::kIndexVector:
-      return RowMap(index_vector_);
-  }
-  PERFETTO_FATAL("For GCC");
-}
-
-RowMap RowMap::SelectRowsSlow(const RowMap& selector) const {
-  // Pick the strategy based on the selector as there is more common code
-  // between selectors of the same mode than between the RowMaps being
-  // selected of the same mode.
-  switch (selector.mode_) {
-    case Mode::kRange:
-      switch (mode_) {
-        case Mode::kRange:
-          return SelectRangeWithRange(start_idx_, end_idx_, selector.start_idx_,
-                                      selector.end_idx_);
-        case Mode::kBitVector:
-          return SelectBvWithRange(bit_vector_, selector.start_idx_,
-                                   selector.end_idx_);
-        case Mode::kIndexVector:
-          return SelectIvWithRange(index_vector_, selector.start_idx_,
-                                   selector.end_idx_);
-      }
-      break;
-    case Mode::kBitVector:
-      switch (mode_) {
-        case Mode::kRange:
-          return SelectRangeWithBv(start_idx_, end_idx_, selector.bit_vector_);
-        case Mode::kBitVector:
-          return SelectBvWithBv(bit_vector_, selector.bit_vector_);
-        case Mode::kIndexVector:
-          return SelectIvWithBv(index_vector_, selector.bit_vector_);
-      }
-      break;
-    case Mode::kIndexVector:
-      switch (mode_) {
-        case Mode::kRange:
-          return SelectRangeWithIv(start_idx_, end_idx_,
-                                   selector.index_vector_);
-        case Mode::kBitVector:
-          return SelectBvWithIv(bit_vector_, selector.index_vector_);
-        case Mode::kIndexVector:
-          return SelectIvWithIv(index_vector_, selector.index_vector_);
-      }
-      break;
-  }
-  PERFETTO_FATAL("For GCC");
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/db/row_map.h b/src/trace_processor/db/row_map.h
deleted file mode 100644
index 53264da..0000000
--- a/src/trace_processor/db/row_map.h
+++ /dev/null
@@ -1,551 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_DB_ROW_MAP_H_
-#define SRC_TRACE_PROCESSOR_DB_ROW_MAP_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/optional.h"
-#include "src/trace_processor/db/bit_vector.h"
-#include "src/trace_processor/db/bit_vector_iterators.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Stores a list of row indicies in a space efficient manner. One or more
-// columns can refer to the same RowMap. The RowMap defines the access pattern
-// to iterate on rows.
-//
-// Implementation details:
-//
-// Behind the scenes, this class is impelemented using one of three backing
-// data-structures:
-// 1. A start and end index (internally named 'range')
-// 1. BitVector
-// 2. std::vector<uint32_t> (internally named IndexVector).
-//
-// Generally the preference for data structures is range > BitVector >
-// std::vector<uint32>; this ordering is based mainly on memory efficiency as we
-// expect RowMaps to be large.
-//
-// However, BitVector and std::vector<uint32_t> allow things which are not
-// possible with the data-structures preferred to them:
-//  * a range (as the name suggests) can only store a compact set of indices
-//  with no holes. A BitVector works around this limitation by storing a 1 at an
-//  index where that row is part of the RowMap and 0 otherwise.
-//  * as soon as ordering or duplicate rows come into play, we cannot use a
-//   BitVector anymore as ordering/duplicate row information cannot be captured
-//   by a BitVector.
-//
-// For small, sparse RowMaps, it is possible that a std::vector<uint32_t> is
-// more efficient than a BitVector; in this case, we will make a best effort
-// switch to it but the cases where this happens is not precisely defined.
-class RowMap {
- private:
-  // We need to declare these iterator classes before RowMap::Iterator as it
-  // depends on them. However, we don't want to make these public so keep them
-  // under a special private section.
-
-  // Iterator for ranged mode of RowMap.
-  // This class should act as a drop-in replacement for
-  // BitVector::SetBitsIterator.
-  class RangeIterator {
-   public:
-    RangeIterator(const RowMap* rm) : rm_(rm), index_(rm->start_idx_) {}
-
-    void Next() { ++index_; }
-
-    operator bool() const { return index_ < rm_->end_idx_; }
-
-    uint32_t index() const { return index_; }
-
-    uint32_t ordinal() const { return index_ - rm_->start_idx_; }
-
-   private:
-    const RowMap* rm_ = nullptr;
-    uint32_t index_ = 0;
-  };
-
-  // Iterator for index vector mode of RowMap.
-  // This class should act as a drop-in replacement for
-  // BitVector::SetBitsIterator.
-  class IndexVectorIterator {
-   public:
-    IndexVectorIterator(const RowMap* rm) : rm_(rm) {}
-
-    void Next() { ++ordinal_; }
-
-    operator bool() const { return ordinal_ < rm_->index_vector_.size(); }
-
-    uint32_t index() const { return rm_->index_vector_[ordinal_]; }
-
-    uint32_t ordinal() const { return ordinal_; }
-
-   private:
-    const RowMap* rm_ = nullptr;
-    uint32_t ordinal_ = 0;
-  };
-
- public:
-  // Allows efficient iteration over the rows of a RowMap.
-  //
-  // Note: you should usually prefer to use the methods on RowMap directly (if
-  // they exist for the task being attempted) to avoid the lookup for the mode
-  // of the RowMap on every method call.
-  class Iterator {
-   public:
-    Iterator(const RowMap* rm) : rm_(rm) {
-      switch (rm->mode_) {
-        case Mode::kRange:
-          range_it_.reset(new RangeIterator(rm));
-          break;
-        case Mode::kBitVector:
-          set_bits_it_.reset(
-              new BitVector::SetBitsIterator(rm->bit_vector_.IterateSetBits()));
-          break;
-        case Mode::kIndexVector:
-          iv_it_.reset(new IndexVectorIterator(rm));
-          break;
-      }
-    }
-
-    // Forwards the iterator to the next row of the RowMap.
-    void Next() {
-      switch (rm_->mode_) {
-        case Mode::kRange:
-          range_it_->Next();
-          break;
-        case Mode::kBitVector:
-          set_bits_it_->Next();
-          break;
-        case Mode::kIndexVector:
-          iv_it_->Next();
-          break;
-      }
-    }
-
-    // Returns if the iterator is still valid.
-    operator bool() const {
-      switch (rm_->mode_) {
-        case Mode::kRange:
-          return *range_it_;
-        case Mode::kBitVector:
-          return *set_bits_it_;
-        case Mode::kIndexVector:
-          return *iv_it_;
-      }
-      PERFETTO_FATAL("For GCC");
-    }
-
-    // Returns the row pointed to by this iterator.
-    uint32_t row() const {
-      // RowMap uses the row/index nomenclature for referring to the mapping
-      // from index to a row (as the name suggests). However, the data
-      // structures used by RowMap use the index/ordinal naming (because they
-      // don't have the concept of a "row"). Switch the naming here.
-      switch (rm_->mode_) {
-        case Mode::kRange:
-          return range_it_->index();
-        case Mode::kBitVector:
-          return set_bits_it_->index();
-        case Mode::kIndexVector:
-          return iv_it_->index();
-      }
-      PERFETTO_FATAL("For GCC");
-    }
-
-    // Returns the index of the row the iterator points to.
-    uint32_t index() const {
-      // RowMap uses the row/index nomenclature for referring to the mapping
-      // from index to a row (as the name suggests). However, the data
-      // structures used by RowMap use the index/ordinal naming (because they
-      // don't have the concept of a "row"). Switch the naming here.
-      switch (rm_->mode_) {
-        case Mode::kRange:
-          return range_it_->ordinal();
-        case Mode::kBitVector:
-          return set_bits_it_->ordinal();
-        case Mode::kIndexVector:
-          return iv_it_->ordinal();
-      }
-      PERFETTO_FATAL("For GCC");
-    }
-
-   private:
-    // Only one of the below will be non-null depending on the mode of the
-    // RowMap.
-    std::unique_ptr<RangeIterator> range_it_;
-    std::unique_ptr<BitVector::SetBitsIterator> set_bits_it_;
-    std::unique_ptr<IndexVectorIterator> iv_it_;
-
-    const RowMap* rm_ = nullptr;
-  };
-
-  // Creates an empty RowMap.
-  // By default this will be implemented using a range.
-  RowMap();
-
-  // Creates a RowMap containing the range of rows between |start| and |end|
-  // i.e. all rows between |start| (inclusive) and |end| (exclusive).
-  explicit RowMap(uint32_t start, uint32_t end);
-
-  // Creates a RowMap backed by a BitVector.
-  explicit RowMap(BitVector bit_vector);
-
-  // Creates a RowMap backed by an std::vector<uint32_t>.
-  explicit RowMap(std::vector<uint32_t> vec);
-
-  // Creates a RowMap containing just |row|.
-  // By default this will be implemented using a range.
-  static RowMap SingleRow(uint32_t row) { return RowMap(row, row + 1); }
-
-  // Creates a copy of the RowMap.
-  // We have an explicit copy function because RowMap can hold onto large chunks
-  // of memory and we want to be very explicit when making a copy to avoid
-  // accidental leaks and copies.
-  RowMap Copy() const;
-
-  // Returns the size of the RowMap; that is the number of rows in the RowMap.
-  uint32_t size() const {
-    switch (mode_) {
-      case Mode::kRange:
-        return end_idx_ - start_idx_;
-      case Mode::kBitVector:
-        return bit_vector_.GetNumBitsSet();
-      case Mode::kIndexVector:
-        return static_cast<uint32_t>(index_vector_.size());
-    }
-    PERFETTO_FATAL("For GCC");
-  }
-
-  // Returns the row at index |row|.
-  uint32_t Get(uint32_t idx) const {
-    PERFETTO_DCHECK(idx < size());
-    switch (mode_) {
-      case Mode::kRange:
-        return start_idx_ + idx;
-      case Mode::kBitVector:
-        return bit_vector_.IndexOfNthSet(idx);
-      case Mode::kIndexVector:
-        return index_vector_[idx];
-    }
-    PERFETTO_FATAL("For GCC");
-  }
-
-  // Returns whether the RowMap contains the given row.
-  bool Contains(uint32_t row) const {
-    switch (mode_) {
-      case Mode::kRange: {
-        return row >= start_idx_ && row < end_idx_;
-      }
-      case Mode::kBitVector: {
-        return row < bit_vector_.size() && bit_vector_.IsSet(row);
-      }
-      case Mode::kIndexVector: {
-        auto it = std::find(index_vector_.begin(), index_vector_.end(), row);
-        return it != index_vector_.end();
-      }
-    }
-    PERFETTO_FATAL("For GCC");
-  }
-
-  // Returns the first index of the given |row| in the RowMap.
-  base::Optional<uint32_t> IndexOf(uint32_t row) const {
-    switch (mode_) {
-      case Mode::kRange: {
-        if (row < start_idx_ || row >= end_idx_)
-          return base::nullopt;
-        return row - start_idx_;
-      }
-      case Mode::kBitVector: {
-        return row < bit_vector_.size() && bit_vector_.IsSet(row)
-                   ? base::make_optional(bit_vector_.GetNumBitsSet(row))
-                   : base::nullopt;
-      }
-      case Mode::kIndexVector: {
-        auto it = std::find(index_vector_.begin(), index_vector_.end(), row);
-        return it != index_vector_.end()
-                   ? base::make_optional(static_cast<uint32_t>(
-                         std::distance(index_vector_.begin(), it)))
-                   : base::nullopt;
-      }
-    }
-    PERFETTO_FATAL("For GCC");
-  }
-
-  // Performs an ordered insert the row into the current RowMap (precondition:
-  // this RowMap is ordered based on the rows it contains).
-  //
-  // Example:
-  // this = [1, 5, 10, 11, 20]
-  // Insert(10)  // this = [1, 5, 10, 11, 20]
-  // Insert(12)  // this = [1, 5, 10, 11, 12, 20]
-  // Insert(21)  // this = [1, 5, 10, 11, 12, 20, 21]
-  // Insert(2)   // this = [1, 2, 5, 10, 11, 12, 20, 21]
-  //
-  // Speecifically, this means that it is only valid to call Insert on a RowMap
-  // which is sorted by the rows it contains; this is automatically true when
-  // the RowMap is in range or BitVector mode but is a required condition for
-  // IndexVector mode.
-  void Insert(uint32_t row) {
-    switch (mode_) {
-      case Mode::kRange:
-        if (row == end_idx_) {
-          // Fast path: if we're just appending to the end of the range, we can
-          // stay in range mode and just bump the end index.
-          end_idx_++;
-        } else {
-          // Slow path: the insert is somewhere else other than the end. This
-          // means we need to switch to using a BitVector instead.
-          bit_vector_.Resize(start_idx_, false);
-          bit_vector_.Resize(end_idx_, true);
-          *this = RowMap(std::move(bit_vector_));
-
-          InsertIntoBitVector(row);
-        }
-        break;
-      case Mode::kBitVector:
-        InsertIntoBitVector(row);
-        break;
-      case Mode::kIndexVector: {
-        PERFETTO_DCHECK(
-            std::is_sorted(index_vector_.begin(), index_vector_.end()));
-        auto it =
-            std::upper_bound(index_vector_.begin(), index_vector_.end(), row);
-        index_vector_.insert(it, row);
-        break;
-      }
-    }
-  }
-
-  // Updates this RowMap by 'picking' the rows at indicies given by |picker|.
-  // This is easiest to explain with an example; suppose we have the following
-  // RowMaps:
-  // this  : [0, 1, 4, 10, 11]
-  // picker: [0, 3, 4, 4, 2]
-  //
-  // After calling Apply(picker), we now have the following:
-  // this  : [0, 10, 11, 11, 4]
-  //
-  // Conceptually, we are performing the following algorithm:
-  // RowMap rm = Copy()
-  // for (idx : picker)
-  //   rm[i++] = this[idx]
-  // return rm;
-  RowMap SelectRows(const RowMap& selector) const {
-    uint32_t size = selector.size();
-
-    // If the selector is empty, just return an empty RowMap.
-    if (size == 0u)
-      return RowMap();
-
-    // If the selector is just picking a single row, just return that row
-    // without any additional overhead.
-    if (size == 1u)
-      return RowMap::SingleRow(Get(selector.Get(0)));
-
-    // For all other cases, go into the slow-path.
-    return SelectRowsSlow(selector);
-  }
-
-  // Intersects |other| with |this| writing the result into |this|.
-  // By "intersect", we mean to keep only the rows present in both RowMaps. The
-  // order of the preserved rows will be the same as |this|.
-  //
-  // Conceptually, we are performing the following algorithm:
-  // for (idx : this)
-  //   if (!other.Contains(idx))
-  //     Remove(idx)
-  void Intersect(const RowMap& other) {
-    uint32_t size = other.size();
-
-    if (size == 0u) {
-      // If other is empty, then we will also end up being empty.
-      *this = RowMap();
-      return;
-    }
-
-    if (size == 1u) {
-      // If other just has a single row, see if we also have that row. If we
-      // do, then just return that row. Otherwise, make ourselves empty.
-      uint32_t row = other.Get(0);
-      *this = Contains(row) ? RowMap::SingleRow(row) : RowMap();
-      return;
-    }
-
-    // TODO(lalitm): improve efficiency of this if we end up needing it.
-    RemoveIf([&other](uint32_t row) { return !other.Contains(row); });
-  }
-
-  // Filters the current RowMap into the RowMap given by |out| based on the
-  // return value of |p(idx)|.
-  //
-  // Precondition: |out| should be sorted by the rows inside it (this is
-  // required to keep this method efficient). This is automatically true if the
-  // mode is out is Range or BitVector but needs to be enforced if the mode is
-  // IndexVector.
-  //
-  // Specifically, the setup for each of the variables is as follows:
-  //  this: contains the RowMap indices which will be looked up and passed to
-  //        p to filter.
-  //  out : contains indicies into |this| and will be filtered down to only
-  //        contain indicies where p returns true.
-  //  p   : takes an index given by |this| and returns whether the index should
-  //        be retained in |out|.
-  //
-  // Concretely, the algorithm being invoked looks like (but more efficient
-  // based on the mode of |this| and |out|):
-  // for (idx : out)
-  //   this_idx = (*this)[idx]
-  //   if (!p(this_idx))
-  //     out->Remove(idx)
-  template <typename Predicate>
-  void FilterInto(RowMap* out, Predicate p) const {
-    PERFETTO_DCHECK(size() >= out->size());
-
-    switch (mode_) {
-      case Mode::kRange:
-        FilterInto(out, RangeIterator(this), p);
-        break;
-      case Mode::kBitVector:
-        FilterInto(out, bit_vector_.IterateSetBits(), p);
-        break;
-      case Mode::kIndexVector:
-        FilterInto(out, IndexVectorIterator(this), p);
-        break;
-    }
-  }
-
-  // Returns the iterator over the rows in this RowMap.
-  Iterator IterateRows() const { return Iterator(this); }
-
- private:
-  enum class Mode {
-    kRange,
-    kBitVector,
-    kIndexVector,
-  };
-
-  template <typename Iterator, typename Predicate>
-  void FilterInto(RowMap* out, Iterator it, Predicate p) const {
-    switch (out->mode_) {
-      case Mode::kRange: {
-        // TODO(lalitm): investigate whether we can reuse the data inside
-        // out->bit_vector_ at some point.
-        BitVector bv(out->end_idx_, false);
-        for (auto out_it = bv.IterateAllBits(); it; it.Next(), out_it.Next()) {
-          uint32_t ordinal = it.ordinal();
-          if (ordinal < out->start_idx_)
-            continue;
-          if (ordinal >= out->end_idx_)
-            break;
-
-          if (p(it.index())) {
-            out_it.Set();
-          }
-        }
-        *out = RowMap(std::move(bv));
-        break;
-      }
-      case Mode::kBitVector: {
-        auto out_it = out->bit_vector_.IterateAllBits();
-        for (; it; it.Next(), out_it.Next()) {
-          PERFETTO_DCHECK(out_it);
-          if (out_it.IsSet() && !p(it.index()))
-            out_it.Clear();
-        }
-        break;
-      }
-      case Mode::kIndexVector: {
-        PERFETTO_DCHECK(std::is_sorted(out->index_vector_.begin(),
-                                       out->index_vector_.end()));
-        auto fn = [&p, &it](uint32_t i) {
-          while (it.ordinal() < i) {
-            it.Next();
-            PERFETTO_DCHECK(it);
-          }
-          PERFETTO_DCHECK(it.ordinal() == i);
-          return !p(it.index());
-        };
-        auto iv_it = std::remove_if(out->index_vector_.begin(),
-                                    out->index_vector_.end(), fn);
-        out->index_vector_.erase(iv_it, out->index_vector_.end());
-        break;
-      }
-    }
-  }
-
-  void InsertIntoBitVector(uint32_t row) {
-    PERFETTO_DCHECK(mode_ == Mode::kBitVector);
-
-    bit_vector_.Resize(row + 1, false);
-    bit_vector_.Set(row);
-  }
-
-  // Removes any row where |p(row)| returns false from this RowMap.
-  template <typename Predicate>
-  void RemoveIf(Predicate p) {
-    switch (mode_) {
-      case Mode::kRange: {
-        bit_vector_.Resize(start_idx_, false);
-        for (uint32_t i = start_idx_; i < end_idx_; ++i) {
-          if (p(i))
-            bit_vector_.AppendFalse();
-          else
-            bit_vector_.AppendTrue();
-        }
-        *this = RowMap(std::move(bit_vector_));
-        break;
-      }
-      case Mode::kBitVector: {
-        for (auto it = bit_vector_.IterateSetBits(); it; it.Next()) {
-          if (p(it.index()))
-            it.Clear();
-        }
-        break;
-      }
-      case Mode::kIndexVector: {
-        auto it = std::remove_if(index_vector_.begin(), index_vector_.end(), p);
-        index_vector_.erase(it, index_vector_.end());
-        break;
-      }
-    }
-  }
-
-  RowMap SelectRowsSlow(const RowMap& selector) const;
-
-  Mode mode_ = Mode::kRange;
-
-  // Only valid when |mode_| == Mode::kRange.
-  uint32_t start_idx_ = 0;  // This is an inclusive index.
-  uint32_t end_idx_ = 0;    // This is an exclusive index.
-
-  // Only valid when |mode_| == Mode::kBitVector.
-  BitVector bit_vector_;
-
-  // Only valid when |mode_| == Mode::kIndexVector.
-  std::vector<uint32_t> index_vector_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_DB_ROW_MAP_H_
diff --git a/src/trace_processor/db/row_map_benchmark.cc b/src/trace_processor/db/row_map_benchmark.cc
deleted file mode 100644
index 1d6892e..0000000
--- a/src/trace_processor/db/row_map_benchmark.cc
+++ /dev/null
@@ -1,265 +0,0 @@
-// Copyright (C) 2019 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 <random>
-
-#include <benchmark/benchmark.h>
-
-#include "src/trace_processor/db/row_map.h"
-
-using perfetto::trace_processor::BitVector;
-using perfetto::trace_processor::RowMap;
-
-namespace {
-
-static constexpr uint32_t kPoolSize = 100000;
-static constexpr uint32_t kSize = 123456;
-
-RowMap CreateRange(uint32_t end) {
-  static constexpr uint32_t kRandomSeed = 32;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-
-  uint32_t start = rnd_engine() % end;
-  uint32_t size = rnd_engine() % (end - start);
-  return RowMap(start, start + size);
-}
-
-std::vector<uint32_t> CreateIndexVector(uint32_t size, uint32_t mod) {
-  static constexpr uint32_t kRandomSeed = 476;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-  std::vector<uint32_t> rows(size);
-  for (uint32_t i = 0; i < size; ++i) {
-    rows[i] = rnd_engine() % mod;
-  }
-  return rows;
-}
-
-BitVector CreateBitVector(uint32_t size) {
-  static constexpr uint32_t kRandomSeed = 42;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-  BitVector bv;
-  for (uint32_t i = 0; i < size; ++i) {
-    if (rnd_engine() % 2) {
-      bv.AppendTrue();
-    } else {
-      bv.AppendFalse();
-    }
-  }
-  return bv;
-}
-
-void BenchRowMapGet(benchmark::State& state, RowMap rm) {
-  auto pool_vec = CreateIndexVector(kPoolSize, rm.size());
-
-  uint32_t pool_idx = 0;
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(rm.Get(pool_vec[pool_idx]));
-    pool_idx = (pool_idx + 1) % kPoolSize;
-  }
-}
-
-template <typename Factory>
-void BenchRowMapInsertIntoEmpty(benchmark::State& state, Factory factory) {
-  auto pool_vec = CreateIndexVector(kPoolSize, kSize);
-
-  uint32_t pool_idx = 0;
-  for (auto _ : state) {
-    RowMap rm = factory();
-
-    rm.Insert(pool_vec[pool_idx]);
-    pool_idx = (pool_idx + 1) % kPoolSize;
-
-    benchmark::ClobberMemory();
-  }
-}
-
-void BenchRowMapSelect(benchmark::State& state,
-                       RowMap rm,
-                       const RowMap& selector) {
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(rm.SelectRows(selector));
-  }
-}
-
-template <typename Factory>
-void BenchRowMapFilterInto(benchmark::State& state,
-                           RowMap rm,
-                           Factory factory) {
-  auto pool_vec = CreateIndexVector(kPoolSize, kSize);
-
-  uint32_t pool_idx = 0;
-  for (auto _ : state) {
-    state.PauseTiming();
-    RowMap out = factory();
-    state.ResumeTiming();
-
-    auto fn = [&pool_vec, pool_idx](uint32_t row) {
-      return pool_vec[pool_idx] != 0 && (row % pool_vec[pool_idx]) != 0;
-    };
-    rm.FilterInto(&out, fn);
-    pool_idx = (pool_idx + 1) % kPoolSize;
-
-    benchmark::ClobberMemory();
-  }
-}
-
-}  // namespace
-
-static void BM_RowMapRangeGet(benchmark::State& state) {
-  BenchRowMapGet(state, RowMap(CreateRange(kSize)));
-}
-BENCHMARK(BM_RowMapRangeGet);
-
-static void BM_RowMapBvGet(benchmark::State& state) {
-  BenchRowMapGet(state, RowMap(CreateBitVector(kSize)));
-}
-BENCHMARK(BM_RowMapBvGet);
-
-static void BM_RowMapIvGet(benchmark::State& state) {
-  BenchRowMapGet(state, RowMap(CreateIndexVector(kSize, kSize)));
-}
-BENCHMARK(BM_RowMapIvGet);
-
-// TODO(lalitm): add benchmarks for IndexOf after BitVector is made faster.
-// We can't add them right now because they are just too slow to run.
-
-static void BM_RowMapRangeInsertIntoEmpty(benchmark::State& state) {
-  BenchRowMapInsertIntoEmpty(state, []() { return RowMap(0, 0); });
-}
-BENCHMARK(BM_RowMapRangeInsertIntoEmpty);
-
-static void BM_RowMapBvInsertIntoEmpty(benchmark::State& state) {
-  BenchRowMapInsertIntoEmpty(state, []() { return RowMap(BitVector{}); });
-}
-BENCHMARK(BM_RowMapBvInsertIntoEmpty);
-
-static void BM_RowMapIvInsertIntoEmpty(benchmark::State& state) {
-  BenchRowMapInsertIntoEmpty(state,
-                             []() { return RowMap(std::vector<uint32_t>{}); });
-}
-BENCHMARK(BM_RowMapIvInsertIntoEmpty);
-
-static void BM_RowMapSelectRangeWithRange(benchmark::State& state) {
-  RowMap rm(CreateRange(kSize));
-  RowMap selector(CreateRange(rm.size()));
-  BenchRowMapSelect(state, std::move(rm), std::move(selector));
-}
-BENCHMARK(BM_RowMapSelectRangeWithRange);
-
-static void BM_RowMapSelectRangeWithBv(benchmark::State& state) {
-  RowMap rm(CreateRange(kSize));
-  RowMap selector(CreateBitVector(rm.size()));
-  BenchRowMapSelect(state, std::move(rm), std::move(selector));
-}
-BENCHMARK(BM_RowMapSelectRangeWithBv);
-
-static void BM_RowMapSelectRangeWithIv(benchmark::State& state) {
-  RowMap rm(CreateRange(kSize));
-  RowMap selector(CreateIndexVector(rm.size(), rm.size()));
-  BenchRowMapSelect(state, std::move(rm), std::move(selector));
-}
-BENCHMARK(BM_RowMapSelectRangeWithIv);
-
-static void BM_RowMapSelectBvWithRange(benchmark::State& state) {
-  RowMap rm(CreateBitVector(kSize));
-  RowMap selector(CreateRange(rm.size()));
-  BenchRowMapSelect(state, std::move(rm), std::move(selector));
-}
-BENCHMARK(BM_RowMapSelectBvWithRange);
-
-static void BM_RowMapSelectBvWithBv(benchmark::State& state) {
-  RowMap rm(CreateBitVector(kSize));
-  RowMap selector(CreateBitVector(rm.size()));
-  BenchRowMapSelect(state, std::move(rm), std::move(selector));
-}
-BENCHMARK(BM_RowMapSelectBvWithBv);
-
-static void BM_RowMapSelectBvWithIv(benchmark::State& state) {
-  RowMap rm(CreateBitVector(kSize));
-  RowMap selector(CreateIndexVector(rm.size(), rm.size()));
-  BenchRowMapSelect(state, std::move(rm), std::move(selector));
-}
-BENCHMARK(BM_RowMapSelectBvWithIv);
-
-static void BM_RowMapSelectIvWithRange(benchmark::State& state) {
-  RowMap rm(CreateIndexVector(kSize, kSize));
-  RowMap selector(CreateRange(rm.size()));
-  BenchRowMapSelect(state, std::move(rm), std::move(selector));
-}
-BENCHMARK(BM_RowMapSelectIvWithRange);
-
-static void BM_RowMapSelectIvWithBv(benchmark::State& state) {
-  RowMap rm(CreateIndexVector(kSize, kSize));
-  RowMap selector(CreateBitVector(rm.size()));
-  BenchRowMapSelect(state, std::move(rm), std::move(selector));
-}
-BENCHMARK(BM_RowMapSelectIvWithBv);
-
-static void BM_RowMapSelectIvWithIv(benchmark::State& state) {
-  RowMap rm(CreateIndexVector(kSize, kSize));
-  RowMap selector(CreateIndexVector(rm.size(), rm.size()));
-  BenchRowMapSelect(state, std::move(rm), std::move(selector));
-}
-BENCHMARK(BM_RowMapSelectIvWithIv);
-
-static void BM_RowMapFilterIntoRangeWithRange(benchmark::State& state) {
-  RowMap rm(CreateRange(kSize));
-  uint32_t rm_size = rm.size();
-  BenchRowMapFilterInto(state, std::move(rm),
-                        [rm_size]() { return RowMap(CreateRange(rm_size)); });
-}
-BENCHMARK(BM_RowMapFilterIntoRangeWithRange);
-
-static void BM_RowMapFilterIntoRangeWithBv(benchmark::State& state) {
-  RowMap rm(CreateRange(kSize));
-  uint32_t rm_size = rm.size();
-  BenchRowMapFilterInto(state, std::move(rm), [rm_size]() {
-    return RowMap(CreateBitVector(rm_size));
-  });
-}
-BENCHMARK(BM_RowMapFilterIntoRangeWithBv);
-
-static void BM_RowMapFilterIntoBvWithRange(benchmark::State& state) {
-  RowMap rm(CreateBitVector(kSize));
-  uint32_t rm_size = rm.size();
-  BenchRowMapFilterInto(state, std::move(rm),
-                        [rm_size]() { return RowMap(CreateRange(rm_size)); });
-}
-BENCHMARK(BM_RowMapFilterIntoBvWithRange);
-
-static void BM_RowMapFilterIntoBvWithBv(benchmark::State& state) {
-  RowMap rm(CreateBitVector(kSize));
-  uint32_t rm_size = rm.size();
-  BenchRowMapFilterInto(state, std::move(rm), [rm_size]() {
-    return RowMap(CreateBitVector(rm_size));
-  });
-}
-BENCHMARK(BM_RowMapFilterIntoBvWithBv);
-
-static void BM_RowMapFilterIntoIvWithRange(benchmark::State& state) {
-  RowMap rm(CreateIndexVector(kSize, kSize));
-  uint32_t rm_size = rm.size();
-  BenchRowMapFilterInto(state, std::move(rm),
-                        [rm_size]() { return RowMap(CreateRange(rm_size)); });
-}
-BENCHMARK(BM_RowMapFilterIntoIvWithRange);
-
-static void BM_RowMapFilterIntoIvWithBv(benchmark::State& state) {
-  RowMap rm(CreateIndexVector(kSize, kSize));
-  uint32_t rm_size = rm.size();
-  BenchRowMapFilterInto(state, std::move(rm), [rm_size]() {
-    return RowMap(CreateBitVector(rm_size));
-  });
-}
-BENCHMARK(BM_RowMapFilterIntoIvWithBv);
diff --git a/src/trace_processor/db/row_map_unittest.cc b/src/trace_processor/db/row_map_unittest.cc
deleted file mode 100644
index b0929af..0000000
--- a/src/trace_processor/db/row_map_unittest.cc
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/db/row_map.h"
-
-#include <memory>
-
-#include "src/base/test/gtest_test_suite.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-TEST(RowMapUnittest, SmokeRange) {
-  RowMap rm(30, 47);
-
-  ASSERT_EQ(rm.size(), 17u);
-
-  ASSERT_EQ(rm.Get(0), 30u);
-  ASSERT_EQ(rm.Get(1), 31u);
-  ASSERT_EQ(rm.Get(16), 46u);
-
-  ASSERT_EQ(rm.IndexOf(29), base::nullopt);
-  ASSERT_EQ(rm.IndexOf(30), 0u);
-  ASSERT_EQ(rm.IndexOf(37), 7u);
-  ASSERT_EQ(rm.IndexOf(46), 16u);
-  ASSERT_EQ(rm.IndexOf(47), base::nullopt);
-}
-
-TEST(RowMapUnittest, SmokeBitVector) {
-  RowMap rm(BitVector{true, false, false, false, true, true});
-
-  ASSERT_EQ(rm.size(), 3u);
-
-  ASSERT_EQ(rm.Get(0u), 0u);
-  ASSERT_EQ(rm.Get(1u), 4u);
-  ASSERT_EQ(rm.Get(2u), 5u);
-
-  ASSERT_EQ(rm.IndexOf(0u), 0u);
-  ASSERT_EQ(rm.IndexOf(4u), 1u);
-  ASSERT_EQ(rm.IndexOf(5u), 2u);
-
-  ASSERT_EQ(rm.IndexOf(1u), base::nullopt);
-  ASSERT_EQ(rm.IndexOf(100u), base::nullopt);
-}
-
-TEST(RowMapUnittest, SmokeIndexVector) {
-  RowMap rm(std::vector<uint32_t>{32u, 56u, 24u, 0u, 100u, 1u});
-
-  ASSERT_EQ(rm.size(), 6u);
-
-  ASSERT_EQ(rm.Get(0u), 32u);
-  ASSERT_EQ(rm.Get(1u), 56u);
-  ASSERT_EQ(rm.Get(2u), 24u);
-  ASSERT_EQ(rm.Get(3u), 0u);
-  ASSERT_EQ(rm.Get(4u), 100u);
-  ASSERT_EQ(rm.Get(5u), 1u);
-
-  ASSERT_EQ(rm.IndexOf(32u), 0u);
-  ASSERT_EQ(rm.IndexOf(56u), 1u);
-  ASSERT_EQ(rm.IndexOf(24u), 2u);
-  ASSERT_EQ(rm.IndexOf(0u), 3u);
-  ASSERT_EQ(rm.IndexOf(100u), 4u);
-  ASSERT_EQ(rm.IndexOf(1u), 5u);
-}
-
-TEST(RowMapUnittest, InsertToRangeAfter) {
-  RowMap rm(3u, 7u);
-  rm.Insert(10u);
-
-  ASSERT_EQ(rm.size(), 5u);
-  ASSERT_EQ(rm.Get(4u), 10u);
-  ASSERT_EQ(rm.IndexOf(10u), 4u);
-}
-
-TEST(RowMapUnittest, InsertToBitVectorAfter) {
-  RowMap rm(BitVector{true, false, true, true, false, true});
-  rm.Insert(10u);
-
-  ASSERT_EQ(rm.size(), 5u);
-  ASSERT_EQ(rm.Get(4u), 10u);
-  ASSERT_EQ(rm.IndexOf(10u), 4u);
-}
-
-TEST(RowMapUnittest, InsertToIndexVectorAfter) {
-  RowMap rm(std::vector<uint32_t>{0u, 2u, 3u, 5u});
-  rm.Insert(10u);
-
-  ASSERT_EQ(rm.size(), 5u);
-  ASSERT_EQ(rm.Get(4u), 10u);
-  ASSERT_EQ(rm.IndexOf(10u), 4u);
-}
-
-TEST(RowMapUnittest, ContainsRange) {
-  RowMap rm(93, 157);
-
-  ASSERT_TRUE(rm.Contains(93));
-  ASSERT_TRUE(rm.Contains(105));
-  ASSERT_TRUE(rm.Contains(156));
-
-  ASSERT_FALSE(rm.Contains(0));
-  ASSERT_FALSE(rm.Contains(92));
-  ASSERT_FALSE(rm.Contains(157));
-}
-
-TEST(RowMapUnittest, ContainsBitVector) {
-  RowMap rm(BitVector{true, false, true, true, false, true});
-
-  ASSERT_TRUE(rm.Contains(0));
-  ASSERT_TRUE(rm.Contains(2));
-  ASSERT_TRUE(rm.Contains(3));
-
-  ASSERT_FALSE(rm.Contains(1));
-  ASSERT_FALSE(rm.Contains(4));
-  ASSERT_FALSE(rm.Contains(6));
-}
-
-TEST(RowMapUnittest, ContainsIndexVector) {
-  RowMap rm(std::vector<uint32_t>{0u, 2u, 3u, 5u});
-
-  ASSERT_TRUE(rm.Contains(0));
-  ASSERT_TRUE(rm.Contains(2));
-  ASSERT_TRUE(rm.Contains(3));
-
-  ASSERT_FALSE(rm.Contains(1));
-  ASSERT_FALSE(rm.Contains(4));
-  ASSERT_FALSE(rm.Contains(6));
-}
-
-TEST(RowMapUnittest, SelectRangeWithRange) {
-  RowMap rm(93, 157);
-  RowMap picker(4, 7);
-  auto res = rm.SelectRows(picker);
-
-  ASSERT_EQ(res.size(), 3u);
-  ASSERT_EQ(res.Get(0u), 97u);
-  ASSERT_EQ(res.Get(1u), 98u);
-  ASSERT_EQ(res.Get(2u), 99u);
-}
-
-TEST(RowMapUnittest, SelectBitVectorWithRange) {
-  RowMap rm(BitVector{true, false, false, true, false, true, false});
-  RowMap picker(1u, 3u);
-  auto res = rm.SelectRows(picker);
-
-  ASSERT_EQ(res.size(), 2u);
-  ASSERT_EQ(res.Get(0u), 3u);
-  ASSERT_EQ(res.Get(1u), 5u);
-}
-
-TEST(RowMapUnittest, SelectIndexVectorWithRange) {
-  RowMap rm(std::vector<uint32_t>{33, 2u, 45u, 7u, 8u, 9u});
-  RowMap picker(2, 5);
-  auto res = rm.SelectRows(picker);
-
-  ASSERT_EQ(res.size(), 3u);
-  ASSERT_EQ(res.Get(0u), 45u);
-  ASSERT_EQ(res.Get(1u), 7u);
-  ASSERT_EQ(res.Get(2u), 8u);
-}
-
-TEST(RowMapUnittest, SelectRangeWithBitVector) {
-  RowMap rm(27, 31);
-  RowMap picker(BitVector{true, false, false, true});
-  auto res = rm.SelectRows(picker);
-
-  ASSERT_EQ(res.size(), 2u);
-  ASSERT_EQ(res.Get(0u), 27u);
-  ASSERT_EQ(res.Get(1u), 30u);
-}
-
-TEST(RowMapUnittest, SelectBitVectorWithBitVector) {
-  RowMap rm(BitVector{true, false, true, true, false, true});
-  RowMap picker(BitVector{true, false, false, true});
-  auto res = rm.SelectRows(picker);
-
-  ASSERT_EQ(res.size(), 2u);
-  ASSERT_EQ(res.Get(0u), 0u);
-  ASSERT_EQ(res.Get(1u), 5u);
-}
-
-TEST(RowMapUnittest, SelectIndexVectorWithBitVector) {
-  RowMap rm(std::vector<uint32_t>{0u, 2u, 3u, 5u});
-  RowMap picker(BitVector{true, false, false, true});
-  auto res = rm.SelectRows(picker);
-
-  ASSERT_EQ(res.size(), 2u);
-  ASSERT_EQ(res.Get(0u), 0u);
-  ASSERT_EQ(res.Get(1u), 5u);
-}
-
-TEST(RowMapUnittest, SelectRangeWithIndexVector) {
-  RowMap rm(27, 31);
-  RowMap picker(std::vector<uint32_t>{3u, 2u, 0u, 1u, 1u, 3u});
-  auto res = rm.SelectRows(picker);
-
-  ASSERT_EQ(res.size(), 6u);
-  ASSERT_EQ(res.Get(0u), 30u);
-  ASSERT_EQ(res.Get(1u), 29u);
-  ASSERT_EQ(res.Get(2u), 27u);
-  ASSERT_EQ(res.Get(3u), 28u);
-  ASSERT_EQ(res.Get(4u), 28u);
-  ASSERT_EQ(res.Get(5u), 30u);
-}
-
-TEST(RowMapUnittest, SelectBitVectorWithIndexVector) {
-  RowMap rm(BitVector{true, false, true, true, false, true});
-  RowMap picker(std::vector<uint32_t>{3u, 2u, 0u, 1u, 1u, 3u});
-  auto res = rm.SelectRows(picker);
-
-  ASSERT_EQ(res.size(), 6u);
-  ASSERT_EQ(res.Get(0u), 5u);
-  ASSERT_EQ(res.Get(1u), 3u);
-  ASSERT_EQ(res.Get(2u), 0u);
-  ASSERT_EQ(res.Get(3u), 2u);
-  ASSERT_EQ(res.Get(4u), 2u);
-  ASSERT_EQ(res.Get(5u), 5u);
-}
-
-TEST(RowMapUnittest, SelectIndexVectorWithIndexVector) {
-  RowMap rm(std::vector<uint32_t>{33u, 2u, 45u, 7u, 8u, 9u});
-  RowMap picker(std::vector<uint32_t>{3u, 2u, 0u, 1u, 1u, 3u});
-  auto res = rm.SelectRows(picker);
-
-  ASSERT_EQ(res.size(), 6u);
-  ASSERT_EQ(res.Get(0u), 7u);
-  ASSERT_EQ(res.Get(1u), 45u);
-  ASSERT_EQ(res.Get(2u), 33u);
-  ASSERT_EQ(res.Get(3u), 2u);
-  ASSERT_EQ(res.Get(4u), 2u);
-  ASSERT_EQ(res.Get(5u), 7u);
-}
-
-TEST(RowMapUnittest, IntersectNone) {
-  RowMap rm(BitVector{true, false, true, true, false, true});
-  rm.Intersect(RowMap());
-
-  ASSERT_EQ(rm.size(), 0u);
-}
-
-TEST(RowMapUnittest, IntersectSinglePresent) {
-  RowMap rm(BitVector{true, false, true, true, false, true});
-  rm.Intersect(RowMap::SingleRow(2u));
-
-  ASSERT_EQ(rm.size(), 1u);
-  ASSERT_EQ(rm.Get(0u), 2u);
-}
-
-TEST(RowMapUnittest, IntersectSingleAbsent) {
-  RowMap rm(BitVector{true, false, true, true, false, true});
-  rm.Intersect(RowMap::SingleRow(1u));
-
-  ASSERT_EQ(rm.size(), 0u);
-}
-
-TEST(RowMapUnittest, IntersectMany) {
-  RowMap rm(std::vector<uint32_t>{3u, 2u, 0u, 1u, 1u, 3u});
-  rm.Intersect(RowMap(BitVector{false, false, true, true}));
-
-  ASSERT_EQ(rm.size(), 3u);
-  ASSERT_EQ(rm.Get(0u), 3u);
-  ASSERT_EQ(rm.Get(1u), 2u);
-  ASSERT_EQ(rm.Get(2u), 3u);
-}
-
-TEST(RowMapUnittest, FilterIntoRangeWithRange) {
-  RowMap rm(93, 157);
-  RowMap filter(4, 7);
-  rm.FilterInto(&filter, [](uint32_t row) { return row == 97u || row == 98u; });
-
-  ASSERT_EQ(filter.size(), 2u);
-  ASSERT_EQ(filter.Get(0u), 4u);
-  ASSERT_EQ(filter.Get(1u), 5u);
-}
-
-TEST(RowMapUnittest, FilterIntoBitVectorWithRange) {
-  RowMap rm(
-      BitVector{true, false, false, true, false, true, false, true, true});
-  RowMap filter(1u, 5u);
-  rm.FilterInto(&filter, [](uint32_t row) { return row == 3u || row == 7u; });
-
-  ASSERT_EQ(filter.size(), 2u);
-  ASSERT_EQ(filter.Get(0u), 1u);
-  ASSERT_EQ(filter.Get(1u), 3u);
-}
-
-TEST(RowMapUnittest, FilterIntoIndexVectorWithRange) {
-  RowMap rm(std::vector<uint32_t>{33, 2u, 45u, 7u, 8u, 9u});
-  RowMap filter(2, 5);
-  rm.FilterInto(&filter, [](uint32_t row) { return row == 45u || row == 8u; });
-
-  ASSERT_EQ(filter.size(), 2u);
-  ASSERT_EQ(filter.Get(0u), 2u);
-  ASSERT_EQ(filter.Get(1u), 4u);
-}
-
-TEST(RowMapUnittest, FilterIntoRangeWithBitVector) {
-  RowMap rm(27, 31);
-  RowMap filter(BitVector{true, false, true, true});
-  rm.FilterInto(&filter, [](uint32_t row) { return row == 29u || row == 30u; });
-
-  ASSERT_EQ(filter.size(), 2u);
-  ASSERT_EQ(filter.Get(0u), 2u);
-  ASSERT_EQ(filter.Get(1u), 3u);
-}
-
-TEST(RowMapUnittest, FilterIntoBitVectorWithBitVector) {
-  RowMap rm(BitVector{true, false, true, true, false, true});
-  RowMap filter(BitVector{true, true, false, true});
-  rm.FilterInto(&filter, [](uint32_t row) { return row == 2u || row == 5u; });
-
-  ASSERT_EQ(filter.size(), 2u);
-  ASSERT_EQ(filter.Get(0u), 1u);
-  ASSERT_EQ(filter.Get(1u), 3u);
-}
-
-TEST(RowMapUnittest, FilterIntoIndexVectorWithBitVector) {
-  RowMap rm(std::vector<uint32_t>{0u, 2u, 3u, 5u});
-  RowMap filter(BitVector{true, true, false, true});
-  rm.FilterInto(&filter, [](uint32_t row) { return row == 2u || row == 5u; });
-
-  ASSERT_EQ(filter.size(), 2u);
-  ASSERT_EQ(filter.Get(0u), 1u);
-  ASSERT_EQ(filter.Get(1u), 3u);
-}
-
-TEST(RowMapUnittest, FilterIntoRangeWithIndexVector) {
-  RowMap rm(27, 41);
-  RowMap filter(std::vector<uint32_t>{3u, 5u, 9u, 10u, 12u});
-  rm.FilterInto(&filter, [](uint32_t row) { return row == 32u || row == 39u; });
-
-  ASSERT_EQ(filter.size(), 2u);
-  ASSERT_EQ(filter.Get(0u), 5u);
-  ASSERT_EQ(filter.Get(1u), 12u);
-}
-
-TEST(RowMapUnittest, FilterIntoBitVectorWithIndexVector) {
-  RowMap rm(BitVector{false, true, false, true, true, false, true});
-  RowMap filter(std::vector<uint32_t>{1u, 2u, 3u});
-  rm.FilterInto(&filter, [](uint32_t row) { return row == 3u || row == 4u; });
-
-  ASSERT_EQ(filter.size(), 2u);
-  ASSERT_EQ(filter.Get(0u), 1u);
-  ASSERT_EQ(filter.Get(1u), 2u);
-}
-
-TEST(RowMapUnittest, FilterIntoIndexVectorWithIndexVector) {
-  RowMap rm(std::vector<uint32_t>{33u, 2u, 45u, 7u, 8u, 9u});
-  RowMap filter(std::vector<uint32_t>{1u, 2u, 3u});
-  rm.FilterInto(&filter, [](uint32_t row) { return row == 2u || row == 7u; });
-
-  ASSERT_EQ(filter.size(), 2u);
-  ASSERT_EQ(filter.Get(0u), 1u);
-  ASSERT_EQ(filter.Get(1u), 3u);
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/db/sparse_vector.h b/src/trace_processor/db/sparse_vector.h
deleted file mode 100644
index 7fb0d87..0000000
--- a/src/trace_processor/db/sparse_vector.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_DB_SPARSE_VECTOR_H_
-#define SRC_TRACE_PROCESSOR_DB_SPARSE_VECTOR_H_
-
-#include <stdint.h>
-
-#include <deque>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/optional.h"
-#include "src/trace_processor/db/row_map.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// A data structure which compactly stores a list of possibly nullable data.
-//
-// Internally, this class is implemented using a combination of a std::deque
-// with a BitVector used to store whether each index is null or not.
-// For each null value, it only uses a single bit inside the BitVector at
-// a slight cost (searching the BitVector to find the index into the std::deque)
-// when looking up the data.
-template <typename T>
-class SparseVector {
- public:
-  // Creates an empty SparseVector.
-  SparseVector() = default;
-
-  // Returns the optional value at |idx| or base::nullopt if the value is null.
-  base::Optional<T> Get(uint32_t idx) const {
-    auto opt_idx = valid_.IndexOf(idx);
-    return opt_idx ? base::Optional<T>(data_[*opt_idx]) : base::nullopt;
-  }
-
-  // Returns the non-null value at |ordinal| where |ordinal| gives the index
-  // of the entry in-terms of non-null entries only.
-  //
-  // For example:
-  // this = [0, null, 2, null, 4]
-  //
-  // GetNonNull(0) = 0
-  // GetNonNull(1) = 2
-  // GetNoNull(2) = 4
-  // ...
-  T GetNonNull(uint32_t ordinal) const {
-    PERFETTO_DCHECK(ordinal < data_.size());
-    return data_[ordinal];
-  }
-
-  // Adds the given value to the SparseVector.
-  void Append(T val) {
-    data_.emplace_back(val);
-    valid_.Insert(size_++);
-  }
-
-  // Adds a null value to the SparseVector.
-  void AppendNull() { size_++; }
-
-  // Adds the given optional value to the SparseVector.
-  void Append(base::Optional<T> val) {
-    if (val) {
-      Append(*val);
-    } else {
-      AppendNull();
-    }
-  }
-
-  // Sets the value at |idx| to the given |val|.
-  void Set(uint32_t idx, T val) {
-    auto opt_idx = valid_.IndexOf(idx);
-
-    // Generally, we will be setting a null row to non-null so optimize for that
-    // path.
-    if (PERFETTO_UNLIKELY(opt_idx)) {
-      data_[*opt_idx] = val;
-    } else {
-      valid_.Insert(idx);
-
-      opt_idx = valid_.IndexOf(idx);
-      PERFETTO_DCHECK(opt_idx);
-      data_.insert(data_.begin() + static_cast<ptrdiff_t>(*opt_idx), val);
-    }
-  }
-
-  // Returns the size of the SparseVector; this includes any null values.
-  uint32_t size() const { return size_; }
-
- private:
-  explicit SparseVector(const SparseVector&) = delete;
-  SparseVector& operator=(const SparseVector&) = delete;
-
-  SparseVector(SparseVector&&) = delete;
-  SparseVector& operator=(SparseVector&&) noexcept = delete;
-
-  std::deque<T> data_;
-  RowMap valid_;
-  uint32_t size_ = 0;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_DB_SPARSE_VECTOR_H_
diff --git a/src/trace_processor/db/sparse_vector_benchmark.cc b/src/trace_processor/db/sparse_vector_benchmark.cc
deleted file mode 100644
index ed1bed2..0000000
--- a/src/trace_processor/db/sparse_vector_benchmark.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (C) 2019 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 <random>
-
-#include <benchmark/benchmark.h>
-
-#include "src/trace_processor/db/sparse_vector.h"
-
-namespace {
-
-static constexpr uint32_t kPoolSize = 100000;
-static constexpr uint32_t kSize = 123456;
-
-}  // namespace
-
-static void BM_SparseVectorAppendNonNull(benchmark::State& state) {
-  std::vector<uint8_t> data_pool(kPoolSize);
-
-  static constexpr uint32_t kRandomSeed = 42;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-  for (uint32_t i = 0; i < kPoolSize; ++i) {
-    data_pool[i] = rnd_engine() % std::numeric_limits<uint8_t>::max();
-  }
-
-  perfetto::trace_processor::SparseVector<uint8_t> sv;
-  uint32_t pool_idx = 0;
-  for (auto _ : state) {
-    sv.Append(data_pool[pool_idx]);
-    pool_idx = (pool_idx + 1) % kPoolSize;
-    benchmark::ClobberMemory();
-  }
-}
-BENCHMARK(BM_SparseVectorAppendNonNull);
-
-static void BM_SparseVectorGetNonNull(benchmark::State& state) {
-  std::vector<uint32_t> idx_pool(kPoolSize);
-
-  perfetto::trace_processor::SparseVector<uint8_t> sv;
-  static constexpr uint32_t kRandomSeed = 42;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-  for (uint32_t i = 0; i < kSize; ++i) {
-    sv.Append(rnd_engine() % std::numeric_limits<uint8_t>::max());
-  }
-  for (uint32_t i = 0; i < kPoolSize; ++i) {
-    idx_pool[i] = rnd_engine() % kSize;
-  }
-
-  uint32_t pool_idx = 0;
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(sv.Get(idx_pool[pool_idx]));
-    pool_idx = (pool_idx + 1) % kPoolSize;
-  }
-}
-BENCHMARK(BM_SparseVectorGetNonNull);
diff --git a/src/trace_processor/db/sparse_vector_unittest.cc b/src/trace_processor/db/sparse_vector_unittest.cc
deleted file mode 100644
index e6474ea..0000000
--- a/src/trace_processor/db/sparse_vector_unittest.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/db/sparse_vector.h"
-
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-TEST(SparseVector, Append) {
-  SparseVector<int64_t> sv;
-  sv.Append(10);
-  sv.Append(20);
-  sv.AppendNull();
-  sv.Append(40);
-
-  ASSERT_EQ(sv.size(), 4u);
-  ASSERT_EQ(sv.Get(0), base::Optional<int64_t>(10));
-  ASSERT_EQ(sv.Get(1), base::Optional<int64_t>(20));
-  ASSERT_EQ(sv.Get(2), base::nullopt);
-  ASSERT_EQ(sv.Get(3), base::Optional<int64_t>(40));
-}
-
-TEST(SparseVector, Set) {
-  SparseVector<int64_t> sv;
-  sv.Append(10);
-  sv.Append(20);
-  sv.AppendNull();
-  sv.AppendNull();
-  sv.Append(40);
-
-  sv.Set(0, 15);
-  sv.Set(3, 30);
-
-  ASSERT_EQ(sv.Get(0), base::Optional<int64_t>(15));
-  ASSERT_EQ(sv.Get(3), base::Optional<int64_t>(30));
-}
-
-TEST(SparseVector, SetNonNull) {
-  SparseVector<int64_t> sv;
-  sv.Append(1);
-  sv.Append(2);
-  sv.Append(3);
-  sv.Append(4);
-
-  sv.Set(1, 22);
-
-  ASSERT_EQ(sv.Get(0), base::Optional<int64_t>(1));
-  ASSERT_EQ(sv.Get(1), base::Optional<int64_t>(22));
-  ASSERT_EQ(sv.Get(2), base::Optional<int64_t>(3));
-  ASSERT_EQ(sv.Get(3), base::Optional<int64_t>(4));
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/db/table.cc b/src/trace_processor/db/table.cc
deleted file mode 100644
index 289b357..0000000
--- a/src/trace_processor/db/table.cc
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/db/table.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-Table::Table(StringPool* pool, const Table* parent) : string_pool_(pool) {
-  if (!parent)
-    return;
-
-  // If this table has a parent, then copy over all the columns pointing to
-  // empty RowMaps.
-  for (uint32_t i = 0; i < parent->row_maps_.size(); ++i)
-    row_maps_.emplace_back();
-  for (const Column& col : parent->columns_)
-    columns_.emplace_back(col, this, columns_.size(), col.row_map_idx_);
-}
-
-Table& Table::operator=(Table&& other) noexcept {
-  size_ = other.size_;
-  string_pool_ = other.string_pool_;
-
-  row_maps_ = std::move(other.row_maps_);
-  columns_ = std::move(other.columns_);
-  for (Column& col : columns_) {
-    col.table_ = this;
-  }
-  return *this;
-}
-
-Table Table::Copy() const {
-  Table table = CopyExceptRowMaps();
-  for (const RowMap& rm : row_maps_) {
-    table.row_maps_.emplace_back(rm.Copy());
-  }
-  return table;
-}
-
-Table Table::CopyExceptRowMaps() const {
-  Table table(string_pool_, nullptr);
-  table.size_ = size_;
-  for (const Column& col : columns_) {
-    table.columns_.emplace_back(col, &table, col.col_idx_, col.row_map_idx_);
-  }
-  return table;
-}
-
-Table Table::Filter(const std::vector<Constraint>& cs) const {
-  // TODO(lalitm): we can add optimizations here depending on whether this is
-  // an lvalue or rvalue.
-
-  if (cs.empty())
-    return Copy();
-
-  // Create a RowMap indexing all rows and filter this down to the rows which
-  // meet all the constraints.
-  RowMap rm(0, size_);
-  for (const Constraint& c : cs) {
-    columns_[c.col_idx].FilterInto(c.op, c.value, &rm);
-  }
-
-  // Return a copy of this table with the RowMaps using the computed filter
-  // RowMap and with the updated size.
-  Table table = CopyExceptRowMaps();
-  table.size_ = rm.size();
-  for (const RowMap& map : row_maps_) {
-    table.row_maps_.emplace_back(map.SelectRows(rm));
-    PERFETTO_DCHECK(table.row_maps_.back().size() == table.size());
-  }
-  return table;
-}
-
-Table Table::Sort(const std::vector<Order>& od) const {
-  // TODO(lalitm): we can add optimizations here depending on whether this is
-  // an lvalue or rvalue.
-
-  if (od.empty())
-    return Copy();
-
-  // Build an index vector with all the indices for the first |size_| rows.
-  std::vector<uint32_t> idx(size_);
-  std::iota(idx.begin(), idx.end(), 0);
-
-  // Sort the row indices according to the given order by constraints.
-  std::sort(idx.begin(), idx.end(), [this, &od](uint32_t a, uint32_t b) {
-    for (const Order& o : od) {
-      const Column& col = columns_[o.col_idx];
-      int cmp =
-          col.Get(a) < col.Get(b) ? -1 : (col.Get(b) < col.Get(a) ? 1 : 0);
-      if (cmp != 0)
-        return o.desc ? cmp > 0 : cmp < 0;
-    }
-    return false;
-  });
-
-  // Return a copy of this table with the RowMaps using the computed ordered
-  // RowMap.
-  Table table = CopyExceptRowMaps();
-  RowMap rm(std::move(idx));
-  for (const RowMap& map : row_maps_) {
-    table.row_maps_.emplace_back(map.SelectRows(rm));
-    PERFETTO_DCHECK(table.row_maps_.back().size() == table.size());
-  }
-  return table;
-}
-
-Table Table::LookupJoin(JoinKey left, const Table& other, JoinKey right) {
-  // The join table will have the same size and RowMaps as the left (this)
-  // table because the left column is indexing the right table.
-  Table table(string_pool_, nullptr);
-  table.size_ = size_;
-  for (const RowMap& rm : row_maps_) {
-    table.row_maps_.emplace_back(rm.Copy());
-  }
-
-  for (const Column& col : columns_) {
-    // We skip id columns as they are misleading on join tables.
-    if ((col.flags_ & Column::kId) != 0)
-      continue;
-    table.columns_.emplace_back(col, &table, table.columns_.size(),
-                                col.row_map_idx_);
-  }
-
-  const Column& left_col = columns_[left.col_idx];
-  const Column& right_col = other.columns_[right.col_idx];
-
-  // For each index in the left column, retrieve the index of the row inside
-  // the RowMap of the right column. By getting the index of the row rather
-  // than the row number itself, we can call |Apply| on the other RowMaps
-  // in the right table.
-  std::vector<uint32_t> indices(size_);
-  for (uint32_t i = 0; i < size_; ++i) {
-    SqlValue val = left_col.Get(i);
-    PERFETTO_CHECK(val.type != SqlValue::Type::kNull);
-    indices[i] = right_col.IndexOf(val).value();
-  }
-
-  // Apply the computed RowMap to each of the right RowMaps, adding it to the
-  // join table as we go.
-  RowMap rm(std::move(indices));
-  for (const RowMap& ot : other.row_maps_) {
-    table.row_maps_.emplace_back(ot.SelectRows(rm));
-  }
-
-  uint32_t left_row_maps_size = static_cast<uint32_t>(row_maps_.size());
-  for (const Column& col : other.columns_) {
-    // We skip id columns as they are misleading on join tables.
-    if ((col.flags_ & Column::kId) != 0)
-      continue;
-
-    // Ensure that we offset the RowMap index by the number of RowMaps in the
-    // left table.
-    table.columns_.emplace_back(col, &table, table.columns_.size(),
-                                col.row_map_idx_ + left_row_maps_size);
-  }
-  return table;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/db/table.h b/src/trace_processor/db/table.h
deleted file mode 100644
index e9410b4..0000000
--- a/src/trace_processor/db/table.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_DB_TABLE_H_
-#define SRC_TRACE_PROCESSOR_DB_TABLE_H_
-
-#include <stdint.h>
-
-#include <limits>
-#include <numeric>
-#include <vector>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/optional.h"
-#include "src/trace_processor/db/column.h"
-#include "src/trace_processor/string_pool.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Represents a table of data with named, strongly typed columns.
-class Table {
- public:
-  // Iterator over the rows of the table.
-  class Iterator {
-   public:
-    Iterator(const Table* table) : table_(table) {
-      for (const auto& rm : table->row_maps()) {
-        its_.emplace_back(rm.IterateRows());
-      }
-    }
-
-    // Advances the iterator to the next row of the table.
-    void Next() {
-      for (auto& it : its_) {
-        it.Next();
-      }
-    }
-
-    // Returns whether the row the iterator is pointing at is valid.
-    operator bool() const { return its_[0]; }
-
-    // Returns the value at the current row for column |col_idx|.
-    SqlValue Get(uint32_t col_idx) const {
-      const auto& col = table_->columns_[col_idx];
-      return col.GetAtIdx(its_[col.row_map_idx_].row());
-    }
-
-   private:
-    const Table* table_ = nullptr;
-    std::vector<RowMap::Iterator> its_;
-  };
-
-  // We explicitly define the move constructor here because we need to update
-  // the Table pointer in each column in the table.
-  Table(Table&& other) noexcept { *this = std::move(other); }
-  Table& operator=(Table&& other) noexcept;
-
-  // Filters the Table using the specified filter constraints.
-  Table Filter(const std::vector<Constraint>& cs) const;
-
-  // Sorts the Table using the specified order by constraints.
-  Table Sort(const std::vector<Order>& od) const;
-
-  // Joins |this| table with the |other| table using the values of column |left|
-  // of |this| table to lookup the row in |right| column of the |other| table.
-  //
-  // Concretely, for each row in the returned table we lookup the value of
-  // |left| in |right|. The found row is used as the values for |other|'s
-  // columns in the returned table.
-  //
-  // This means we obtain the following invariants:
-  //  1. this->size() == ret->size()
-  //  2. this->Rows()[i].Get(j) == ret->Rows()[i].Get(j)
-  //
-  // It also means there are few restrictions on the data in |left| and |right|:
-  //  * |left| is not allowed to have any nulls.
-  //  * |left|'s values must exist in |right|
-  Table LookupJoin(JoinKey left, const Table& other, JoinKey right);
-
-  // Returns the column at index |idx| in the Table.
-  const Column& GetColumn(uint32_t idx) const { return columns_[idx]; }
-
-  // Retuns the index of the column with the given name, if one exists, or
-  // nullptr otherwise.
-  base::Optional<uint32_t> FindColumnIdxByName(const char* name) const {
-    auto it = std::find_if(
-        columns_.begin(), columns_.end(),
-        [name](const Column& col) { return strcmp(col.name(), name) == 0; });
-    return it == columns_.end() ? base::nullopt
-                                : base::make_optional(static_cast<uint32_t>(
-                                      std::distance(columns_.begin(), it)));
-  }
-
-  // Returns the number of columns in the Table.
-  uint32_t GetColumnCount() const {
-    return static_cast<uint32_t>(columns_.size());
-  }
-
-  // Returns an iterator into the Table.
-  Iterator IterateRows() const { return Iterator(this); }
-
-  uint32_t size() const { return size_; }
-  const std::vector<RowMap>& row_maps() const { return row_maps_; }
-
- protected:
-  Table(StringPool* pool, const Table* parent);
-
-  std::vector<RowMap> row_maps_;
-  std::vector<Column> columns_;
-  uint32_t size_ = 0;
-
-  StringPool* string_pool_ = nullptr;
-
- private:
-  friend class Column;
-
-  Table Copy() const;
-  Table CopyExceptRowMaps() const;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_DB_TABLE_H_
diff --git a/src/trace_processor/db/typed_column.h b/src/trace_processor/db/typed_column.h
deleted file mode 100644
index 52d279c..0000000
--- a/src/trace_processor/db/typed_column.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_DB_TYPED_COLUMN_H_
-#define SRC_TRACE_PROCESSOR_DB_TYPED_COLUMN_H_
-
-#include "src/trace_processor/db/column.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Represents a column containing data with the given type T.
-//
-// This class exists as a memberless subclass of Column (i.e. sizeof(Column) ==
-// sizeof(TypedColumn<T>)); this is because Columns are type erased but we still
-// want low boilerplate methods to get/set rows in columns where we know the
-// type.
-template <typename T>
-struct TypedColumn : public Column {
-  using StoredType = T;
-
-  T operator[](uint32_t row) const {
-    return sparse_vector<T>().GetNonNull(row_map().Get(row));
-  }
-  void Set(uint32_t row, T value) {
-    mutable_sparse_vector<T>()->Set(row_map().Get(row), value);
-  }
-  void Append(T value) { mutable_sparse_vector<T>()->Append(value); }
-
-  static constexpr uint32_t default_flags() { return Flag::kNonNull; }
-};
-
-template <typename T>
-struct TypedColumn<base::Optional<T>> : public Column {
-  using StoredType = T;
-
-  base::Optional<T> operator[](uint32_t row) const {
-    return sparse_vector<T>().Get(row_map().Get(row));
-  }
-  void Set(uint32_t row, T value) {
-    mutable_sparse_vector<T>()->Set(row_map().Get(row), value);
-  }
-
-  void Append(base::Optional<T> value) {
-    mutable_sparse_vector<T>()->Append(value);
-  }
-
-  static constexpr uint32_t default_flags() { return Flag::kNoFlag; }
-};
-
-template <>
-struct TypedColumn<StringPool::Id> : public Column {
-  using StoredType = StringPool::Id;
-
-  StringPool::Id operator[](uint32_t row) const {
-    return sparse_vector<StringPool::Id>().GetNonNull(row_map().Get(row));
-  }
-  NullTermStringView GetString(uint32_t row) const {
-    return GetStringPoolStringAtIdx(row_map().Get(row));
-  }
-  void Set(uint32_t row, StringPool::Id value) {
-    mutable_sparse_vector<StringPool::Id>()->Set(row_map().Get(row), value);
-  }
-  void Append(StringPool::Id value) {
-    mutable_sparse_vector<StringPool::Id>()->Append(value);
-  }
-
-  static constexpr uint32_t default_flags() { return Flag::kNonNull; }
-};
-
-template <>
-struct TypedColumn<base::Optional<StringPool::Id>>
-    : public TypedColumn<StringPool::Id> {
-  void Append(base::Optional<StringPool::Id> value) {
-    // Since StringPool::Id == 0 is always treated as null, rewrite
-    // base::nullopt -> 0 to remove an extra check at filter time for
-    // base::nullopt. Instead, that code can assume that the SparseVector layer
-    // always returns a valid id and can handle the nullability at the
-    // stringpool level.
-    // TODO(lalitm): remove this special casing if we migrate all tables over
-    // to macro tables and find that we can remove support for null stringids
-    // in the stringpool.
-    return TypedColumn<StringPool::Id>::Append(value ? *value
-                                                     : StringPool::Id(0u));
-  }
-
-  static constexpr uint32_t default_flags() { return Flag::kNonNull; }
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_DB_TYPED_COLUMN_H_
diff --git a/src/trace_processor/event_tracker.cc b/src/trace_processor/event_tracker.cc
index 2e9babf..f46225d 100644
--- a/src/trace_processor/event_tracker.cc
+++ b/src/trace_processor/event_tracker.cc
@@ -18,53 +18,153 @@
 
 #include <math.h>
 
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/utils.h"
 #include "src/trace_processor/args_tracker.h"
+#include "src/trace_processor/ftrace_descriptors.h"
+#include "src/trace_processor/ftrace_utils.h"
 #include "src/trace_processor/process_tracker.h"
 #include "src/trace_processor/stats.h"
 #include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/track_tracker.h"
-#include "src/trace_processor/variadic.h"
+
+#include "perfetto/trace/ftrace/ftrace_event.pbzero.h"
+#include "perfetto/trace/ftrace/sched.pbzero.h"
 
 namespace perfetto {
 namespace trace_processor {
 
-EventTracker::EventTracker(TraceProcessorContext* context)
-    : context_(context) {}
+EventTracker::EventTracker(TraceProcessorContext* context) : context_(context) {
+  auto* descriptor = GetMessageDescriptorForId(
+      protos::pbzero::FtraceEvent::kSchedSwitchFieldNumber);
+  PERFETTO_CHECK(descriptor->max_field_id == kSchedSwitchMaxFieldId);
+
+  for (size_t i = 1; i <= kSchedSwitchMaxFieldId; i++) {
+    sched_switch_field_ids_[i] =
+        context->storage->InternString(descriptor->fields[i].name);
+  }
+  sched_switch_id_ = context->storage->InternString(descriptor->name);
+}
 
 EventTracker::~EventTracker() = default;
 
-RowId EventTracker::PushProcessCounterForThread(int64_t timestamp,
-                                                double value,
-                                                StringId name_id,
-                                                UniqueTid utid) {
-  RowId row_id = PushCounter(timestamp, value, kInvalidTrackId);
-  if (row_id != kInvalidRowId) {
-    auto table_and_row = TraceStorage::ParseRowId(row_id);
-    PendingUpidResolutionCounter pending;
-    pending.row = table_and_row.second;
-    pending.utid = utid;
-    pending.name_id = name_id;
-    pending_upid_resolution_counter_.emplace_back(pending);
+void EventTracker::PushSchedSwitch(uint32_t cpu,
+                                   int64_t ts,
+                                   uint32_t prev_pid,
+                                   base::StringView prev_comm,
+                                   int32_t prev_prio,
+                                   int64_t prev_state,
+                                   uint32_t next_pid,
+                                   base::StringView next_comm,
+                                   int32_t next_prio) {
+  // At this stage all events should be globally timestamp ordered.
+  if (ts < prev_timestamp_) {
+    PERFETTO_ELOG("sched_switch event out of order by %.4f ms, skipping",
+                  (prev_timestamp_ - ts) / 1e6);
+    context_->storage->IncrementStats(stats::sched_switch_out_of_order);
+    return;
   }
-  return row_id;
+  prev_timestamp_ = ts;
+  PERFETTO_DCHECK(cpu < base::kMaxCpus);
+
+  auto* slices = context_->storage->mutable_slices();
+
+  StringId next_comm_id = context_->storage->InternString(next_comm);
+  auto next_utid =
+      context_->process_tracker->UpdateThreadName(next_pid, next_comm_id);
+
+  // First use this data to close the previous slice.
+  bool prev_pid_match_prev_next_pid = false;
+  auto* prev_slice = &pending_sched_per_cpu_[cpu];
+  size_t slice_idx = prev_slice->storage_index;
+  if (slice_idx < std::numeric_limits<size_t>::max()) {
+    prev_pid_match_prev_next_pid = prev_pid == prev_slice->next_pid;
+    if (PERFETTO_LIKELY(prev_pid_match_prev_next_pid)) {
+      int64_t duration = ts - slices->start_ns()[slice_idx];
+      slices->set_duration(slice_idx, duration);
+
+      // We store the state as a uint16 as we only consider values up to 2048
+      // when unpacking the information inside; this allows savings of 48 bits
+      // per slice.
+      slices->set_end_state(slice_idx, ftrace_utils::TaskState(
+                                           static_cast<uint16_t>(prev_state)));
+    } else {
+      // If the pids ae not consistent, make a note of this.
+      context_->storage->IncrementStats(stats::mismatched_sched_switch_tids);
+    }
+  }
+
+  // We have to intern prev_comm again because our assumption that
+  // this event's |prev_comm| == previous event's |next_comm| does not hold
+  // if the thread changed its name while scheduled.
+  StringId prev_comm_id = context_->storage->InternString(prev_comm);
+  UniqueTid prev_utid =
+      context_->process_tracker->UpdateThreadName(prev_pid, prev_comm_id);
+
+  // Push the raw event - this is done as the raw ftrace event codepath does
+  // not insert sched_switch.
+  auto rid = context_->storage->mutable_raw_events()->AddRawEvent(
+      ts, sched_switch_id_, cpu, prev_utid);
+
+  // Note: this ordering is important. The events should be pushed in the same
+  // order as the order of fields in the proto; this is used by the raw table to
+  // index these events using the field ids.
+  using Variadic = TraceStorage::Args::Variadic;
+  using SS = protos::pbzero::SchedSwitchFtraceEvent;
+  auto add_raw_arg = [this](RowId row_id, int field_num,
+                            TraceStorage::Args::Variadic var) {
+    StringId key = sched_switch_field_ids_[static_cast<size_t>(field_num)];
+    context_->args_tracker->AddArg(row_id, key, key, var);
+  };
+  add_raw_arg(rid, SS::kPrevCommFieldNumber, Variadic::String(prev_comm_id));
+  add_raw_arg(rid, SS::kPrevPidFieldNumber, Variadic::Integer(prev_pid));
+  add_raw_arg(rid, SS::kPrevPrioFieldNumber, Variadic::Integer(prev_prio));
+  add_raw_arg(rid, SS::kPrevStateFieldNumber, Variadic::Integer(prev_state));
+  add_raw_arg(rid, SS::kNextCommFieldNumber, Variadic::String(next_comm_id));
+  add_raw_arg(rid, SS::kNextPidFieldNumber, Variadic::Integer(next_pid));
+  add_raw_arg(rid, SS::kNextPrioFieldNumber, Variadic::Integer(next_prio));
+
+  // Add the slice for the "next" slice.
+  auto next_idx = slices->AddSlice(cpu, ts, 0 /* duration */, next_utid,
+                                   ftrace_utils::TaskState(), next_prio);
+
+  // Finally, update the info for the next sched switch on this CPU.
+  prev_slice->storage_index = next_idx;
+  prev_slice->next_pid = next_pid;
 }
 
 RowId EventTracker::PushCounter(int64_t timestamp,
                                 double value,
-                                TrackId track_id) {
-  if (timestamp < max_timestamp_) {
+                                StringId name_id,
+                                int64_t ref,
+                                RefType ref_type,
+                                bool resolve_utid_to_upid) {
+  if (timestamp < prev_timestamp_) {
     PERFETTO_DLOG("counter event (ts: %" PRId64
                   ") out of order by %.4f ms, skipping",
-                  timestamp, (max_timestamp_ - timestamp) / 1e6);
+                  timestamp, (prev_timestamp_ - timestamp) / 1e6);
     context_->storage->IncrementStats(stats::counter_events_out_of_order);
     return kInvalidRowId;
   }
-  max_timestamp_ = timestamp;
+  prev_timestamp_ = timestamp;
+
+  PERFETTO_DCHECK(!resolve_utid_to_upid || ref_type == RefType::kRefUtid);
+
+  auto* definitions = context_->storage->mutable_counter_definitions();
+  TraceStorage::CounterDefinitions::Id defn_id;
+  if (resolve_utid_to_upid) {
+    defn_id = TraceStorage::CounterDefinitions::kInvalidId;
+  } else {
+    defn_id = definitions->AddCounterDefinition(name_id, ref, ref_type);
+  }
 
   auto* counter_values = context_->storage->mutable_counter_values();
-  uint32_t idx = counter_values->AddCounterValue(track_id, timestamp, value);
+  uint32_t idx = counter_values->AddCounterValue(defn_id, timestamp, value);
+  if (resolve_utid_to_upid) {
+    PendingUpidResolutionCounter pending;
+    pending.row = idx;
+    pending.utid = static_cast<UniqueTid>(ref);
+    pending.name_id = name_id;
+    pending_upid_resolution_counter_.emplace_back(pending);
+  }
   return TraceStorage::CreateRowId(TableId::kCounterValues,
                                    static_cast<uint32_t>(idx));
 }
@@ -92,14 +192,31 @@
 }
 
 void EventTracker::FlushPendingEvents() {
+  // TODO(lalitm): the day this method is called before end of trace, don't
+  // flush the sched events as they will probably be pushed in the next round
+  // of ftrace events.
+  int64_t end_ts = context_->storage->GetTraceTimestampBoundsNs().second;
+  auto* slices = context_->storage->mutable_slices();
+  for (const auto& pending_sched : pending_sched_per_cpu_) {
+    size_t row = pending_sched.storage_index;
+    if (row == std::numeric_limits<size_t>::max())
+      continue;
+
+    int64_t duration = end_ts - slices->start_ns()[row];
+    slices->set_duration(row, duration);
+    slices->set_end_state(
+        row, ftrace_utils::TaskState(ftrace_utils::TaskState::kRunnable));
+  }
+
   for (const auto& pending_counter : pending_upid_resolution_counter_) {
     const auto& thread = context_->storage->GetThread(pending_counter.utid);
     // TODO(lalitm): having upid == 0 is probably not the correct approach here
     // but it's unclear what may be better.
     UniquePid upid = thread.upid.value_or(0);
-    auto id = context_->track_tracker->InternProcessCounterTrack(
-        pending_counter.name_id, upid);
-    context_->storage->mutable_counter_values()->set_track_id(
+    auto id =
+        context_->storage->mutable_counter_definitions()->AddCounterDefinition(
+            pending_counter.name_id, upid, RefType::kRefUpid);
+    context_->storage->mutable_counter_values()->set_counter_id(
         pending_counter.row, id);
   }
 
@@ -111,6 +228,7 @@
     context_->storage->mutable_instants()->set_ref(pending_instant.row, upid);
   }
 
+  pending_sched_per_cpu_ = {};
   pending_upid_resolution_counter_.clear();
   pending_upid_resolution_instant_.clear();
 }
diff --git a/src/trace_processor/event_tracker.h b/src/trace_processor/event_tracker.h
index 906443a..d8a765a 100644
--- a/src/trace_processor/event_tracker.h
+++ b/src/trace_processor/event_tracker.h
@@ -20,8 +20,8 @@
 #include <array>
 #include <limits>
 
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/string_view.h"
+#include "perfetto/base/utils.h"
 #include "src/trace_processor/trace_storage.h"
 
 namespace perfetto {
@@ -29,7 +29,8 @@
 
 class TraceProcessorContext;
 
-// Tracks sched events, instants, and counters.
+// This class takes sched events from the trace and processes them to store
+// as sched slices.
 class EventTracker {
  public:
   explicit EventTracker(TraceProcessorContext*);
@@ -37,20 +38,24 @@
   EventTracker& operator=(const EventTracker&) = delete;
   virtual ~EventTracker();
 
-  // Adds a counter event to the counters table returning the RowId of the
-  // newly added row.
-  virtual RowId PushCounter(int64_t timestamp, double value, TrackId track_id);
+  // This method is called when a sched switch event is seen in the trace.
+  virtual void PushSchedSwitch(uint32_t cpu,
+                               int64_t timestamp,
+                               uint32_t prev_pid,
+                               base::StringView prev_comm,
+                               int32_t prev_prio,
+                               int64_t prev_state,
+                               uint32_t next_pid,
+                               base::StringView next_comm,
+                               int32_t next_prio);
 
-  // Adds a counter event to the counters table for counter events which
-  // should be associated with a process but only have a thread context
-  // (e.g. rss_stat events).
-  //
-  // This function will resolve the utid to a upid when the events are
-  // flushed (see |FlushPendingEvents()|).
-  virtual RowId PushProcessCounterForThread(int64_t timestamp,
-                                            double value,
-                                            StringId name_id,
-                                            UniqueTid utid);
+  // This method is called when a counter event is seen in the trace.
+  virtual RowId PushCounter(int64_t timestamp,
+                            double value,
+                            StringId name_id,
+                            int64_t ref,
+                            RefType ref_type,
+                            bool resolve_utid_to_upid = false);
 
   // This method is called when a instant event is seen in the trace.
   virtual RowId PushInstant(int64_t timestamp,
@@ -64,13 +69,13 @@
   // storage.
   void FlushPendingEvents();
 
-  // For SchedEventTracker.
-  int64_t max_timestamp() const { return max_timestamp_; }
-  void UpdateMaxTimestamp(int64_t ts) {
-    max_timestamp_ = std::max(ts, max_timestamp_);
-  }
-
  private:
+  // Represents a slice which is currently pending.
+  struct PendingSchedSlice {
+    size_t storage_index = std::numeric_limits<size_t>::max();
+    uint32_t next_pid = 0;
+  };
+
   // Represents a counter event which is currently pending upid resolution.
   struct PendingUpidResolutionCounter {
     uint32_t row = 0;
@@ -84,6 +89,9 @@
     UniqueTid utid = 0;
   };
 
+  // Store pending sched slices for each CPU.
+  std::array<PendingSchedSlice, base::kMaxCpus> pending_sched_per_cpu_{};
+
   // Store the rows in the counters table which need upids resolved.
   std::vector<PendingUpidResolutionCounter> pending_upid_resolution_counter_;
 
@@ -92,7 +100,11 @@
 
   // Timestamp of the previous event. Used to discard events arriving out
   // of order.
-  int64_t max_timestamp_ = 0;
+  int64_t prev_timestamp_ = 0;
+
+  static constexpr uint8_t kSchedSwitchMaxFieldId = 7;
+  std::array<StringId, kSchedSwitchMaxFieldId + 1> sched_switch_field_ids_;
+  StringId sched_switch_id_;
 
   TraceProcessorContext* const context_;
 };
diff --git a/src/trace_processor/event_tracker_unittest.cc b/src/trace_processor/event_tracker_unittest.cc
index 58b905f..aa27a45 100644
--- a/src/trace_processor/event_tracker_unittest.cc
+++ b/src/trace_processor/event_tracker_unittest.cc
@@ -16,12 +16,11 @@
 
 #include "src/trace_processor/event_tracker.h"
 
-#include "perfetto/base/logging.h"
 #include "src/trace_processor/args_tracker.h"
-#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
 #include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/track_tracker.h"
-#include "test/gtest_and_gmock.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -38,17 +37,12 @@
     context.args_tracker.reset(new ArgsTracker(&context));
     context.process_tracker.reset(new ProcessTracker(&context));
     context.event_tracker.reset(new EventTracker(&context));
-    context.track_tracker.reset(new TrackTracker(&context));
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-    context.sched_tracker.reset(new SchedEventTracker(&context));
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
   }
 
  protected:
   TraceProcessorContext context;
 };
 
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
 TEST_F(EventTrackerTest, InsertSecondSched) {
   uint32_t cpu = 3;
   int64_t timestamp = 100;
@@ -60,12 +54,12 @@
   int32_t prio = 1024;
 
   const auto& timestamps = context.storage->slices().start_ns();
-  context.sched_tracker->PushSchedSwitch(cpu, timestamp, pid_1, kCommProc2,
+  context.event_tracker->PushSchedSwitch(cpu, timestamp, pid_1, kCommProc2,
                                          prio, prev_state, pid_2, kCommProc1,
                                          prio);
-  ASSERT_EQ(timestamps.size(), 1u);
+  ASSERT_EQ(timestamps.size(), 1);
 
-  context.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, pid_2, kCommProc1,
+  context.event_tracker->PushSchedSwitch(cpu, timestamp + 1, pid_2, kCommProc1,
                                          prio, prev_state, pid_1, kCommProc2,
                                          prio);
 
@@ -75,7 +69,7 @@
   ASSERT_STREQ(
       context.storage->GetString(context.storage->GetThread(1).name_id).c_str(),
       kCommProc1);
-  ASSERT_EQ(context.storage->slices().utids().front(), 1u);
+  ASSERT_EQ(context.storage->slices().utids().front(), 1);
   ASSERT_EQ(context.storage->slices().durations().front(), 1);
 }
 
@@ -88,18 +82,18 @@
   int32_t prio = 1024;
 
   const auto& timestamps = context.storage->slices().start_ns();
-  context.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/4, kCommProc2,
+  context.event_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/4, kCommProc2,
                                          prio, prev_state,
                                          /*tid=*/2, kCommProc1, prio);
-  ASSERT_EQ(timestamps.size(), 1u);
+  ASSERT_EQ(timestamps.size(), 1);
 
-  context.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/2,
+  context.event_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/2,
                                          kCommProc1, prio, prev_state,
                                          /*tid=*/4, kCommProc2, prio);
-  context.sched_tracker->PushSchedSwitch(cpu, timestamp + 11, /*tid=*/4,
+  context.event_tracker->PushSchedSwitch(cpu, timestamp + 11, /*tid=*/4,
                                          kCommProc2, prio, prev_state,
                                          /*tid=*/2, kCommProc1, prio);
-  context.sched_tracker->PushSchedSwitch(cpu, timestamp + 31, /*tid=*/2,
+  context.event_tracker->PushSchedSwitch(cpu, timestamp + 31, /*tid=*/2,
                                          kCommProc1, prio, prev_state,
                                          /*tid=*/4, kCommProc2, prio);
 
@@ -112,32 +106,33 @@
   ASSERT_EQ(context.storage->slices().utids().at(0),
             context.storage->slices().utids().at(2));
 }
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
 
 TEST_F(EventTrackerTest, CounterDuration) {
   uint32_t cpu = 3;
   int64_t timestamp = 100;
   StringId name_id = 0;
+  context.event_tracker->PushCounter(timestamp, 1000, name_id, cpu,
+                                     RefType::kRefCpuId);
+  context.event_tracker->PushCounter(timestamp + 1, 4000, name_id, cpu,
+                                     RefType::kRefCpuId);
+  context.event_tracker->PushCounter(timestamp + 3, 5000, name_id, cpu,
+                                     RefType::kRefCpuId);
+  context.event_tracker->PushCounter(timestamp + 9, 1000, name_id, cpu,
+                                     RefType::kRefCpuId);
 
-  TrackId track = context.track_tracker->InternCpuCounterTrack(name_id, cpu);
-  context.event_tracker->PushCounter(timestamp, 1000, track);
-  context.event_tracker->PushCounter(timestamp + 1, 4000, track);
-  context.event_tracker->PushCounter(timestamp + 3, 5000, track);
-  context.event_tracker->PushCounter(timestamp + 9, 1000, track);
-
-  ASSERT_EQ(context.storage->counter_track_table().size(), 1ul);
+  ASSERT_EQ(context.storage->counter_definitions().size(), 1ul);
 
   ASSERT_EQ(context.storage->counter_values().size(), 4ul);
   ASSERT_EQ(context.storage->counter_values().timestamps().at(0), timestamp);
-  ASSERT_DOUBLE_EQ(context.storage->counter_values().values().at(0), 1000);
+  ASSERT_EQ(context.storage->counter_values().values().at(0), 1000);
 
   ASSERT_EQ(context.storage->counter_values().timestamps().at(1),
             timestamp + 1);
-  ASSERT_DOUBLE_EQ(context.storage->counter_values().values().at(1), 4000);
+  ASSERT_EQ(context.storage->counter_values().values().at(1), 4000);
 
   ASSERT_EQ(context.storage->counter_values().timestamps().at(2),
             timestamp + 3);
-  ASSERT_DOUBLE_EQ(context.storage->counter_values().values().at(2), 5000);
+  ASSERT_EQ(context.storage->counter_values().values().at(2), 5000);
 }
 
 }  // namespace
diff --git a/src/trace_processor/export_json.cc b/src/trace_processor/export_json.cc
deleted file mode 100644
index 15ad611..0000000
--- a/src/trace_processor/export_json.cc
+++ /dev/null
@@ -1,1068 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-// For bazel build.
-#include "perfetto/base/build_config.h"
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
-
-#include "perfetto/ext/trace_processor/export_json.h"
-#include "src/trace_processor/export_json.h"
-
-#include <inttypes.h>
-#include <json/reader.h>
-#include <json/value.h>
-#include <json/writer.h>
-#include <stdio.h>
-#include <cstring>
-#include <vector>
-
-#include "perfetto/ext/base/string_splitter.h"
-#include "src/trace_processor/metadata.h"
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/trace_processor_storage_impl.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace json {
-
-namespace {
-
-using IndexMap = perfetto::trace_processor::TraceStorage::Stats::IndexMap;
-
-const char kLegacyEventArgsKey[] = "legacy_event";
-const char kLegacyEventOriginalTidKey[] = "original_tid";
-const char kLegacyEventCategoryKey[] = "category";
-const char kLegacyEventNameKey[] = "name";
-const char kLegacyEventPhaseKey[] = "phase";
-const char kLegacyEventDurationNsKey[] = "duration_ns";
-const char kLegacyEventThreadTimestampNsKey[] = "thread_timestamp_ns";
-const char kLegacyEventThreadDurationNsKey[] = "thread_duration_ns";
-const char kLegacyEventThreadInstructionCountKey[] = "thread_instruction_count";
-const char kLegacyEventThreadInstructionDeltaKey[] = "thread_instruction_delta";
-const char kLegacyEventUseAsyncTtsKey[] = "use_async_tts";
-const char kLegacyEventUnscopedIdKey[] = "unscoped_id";
-const char kLegacyEventGlobalIdKey[] = "global_id";
-const char kLegacyEventLocalIdKey[] = "local_id";
-const char kLegacyEventIdScopeKey[] = "id_scope";
-const char kLegacyEventBindIdKey[] = "bind_id";
-const char kLegacyEventBindToEnclosingKey[] = "bind_to_enclosing";
-const char kLegacyEventFlowDirectionKey[] = "flow_direction";
-const char kFlowDirectionValueIn[] = "in";
-const char kFlowDirectionValueOut[] = "out";
-const char kFlowDirectionValueInout[] = "inout";
-const char kStrippedArgument[] = "__stripped__";
-
-const char* GetNonNullString(const TraceStorage* storage, StringId id) {
-  return id == kNullStringId ? "" : storage->GetString(id).c_str();
-}
-
-class FileWriter : public OutputWriter {
- public:
-  FileWriter(FILE* file) : file_(file) {}
-  ~FileWriter() override { fflush(file_); }
-
-  util::Status AppendString(const std::string& s) override {
-    size_t written =
-        fwrite(s.data(), sizeof(std::string::value_type), s.size(), file_);
-    if (written != s.size())
-      return util::ErrStatus("Error writing to file: %d", ferror(file_));
-    return util::OkStatus();
-  }
-
- private:
-  FILE* file_;
-};
-
-class TraceFormatWriter {
- public:
-  TraceFormatWriter(OutputWriter* output,
-                    ArgumentFilterPredicate argument_filter,
-                    MetadataFilterPredicate metadata_filter,
-                    LabelFilterPredicate label_filter)
-      : output_(output),
-        argument_filter_(argument_filter),
-        metadata_filter_(metadata_filter),
-        label_filter_(label_filter),
-        first_event_(true) {
-    WriteHeader();
-  }
-
-  ~TraceFormatWriter() { WriteFooter(); }
-
-  void WriteCommonEvent(const Json::Value& event) {
-    if (label_filter_ && !label_filter_("traceEvents"))
-      return;
-
-    if (!first_event_)
-      output_->AppendString(",\n");
-
-    Json::FastWriter writer;
-    writer.omitEndingLineFeed();
-
-    ArgumentNameFilterPredicate argument_name_filter;
-    bool strip_args =
-        argument_filter_ &&
-        !argument_filter_(event["cat"].asCString(), event["name"].asCString(),
-                          &argument_name_filter);
-    if ((strip_args || argument_name_filter) && event.isMember("args")) {
-      Json::Value event_copy = event;
-      if (strip_args) {
-        event_copy["args"] = kStrippedArgument;
-      } else {
-        auto& args = event_copy["args"];
-        for (const auto& member : event["args"].getMemberNames()) {
-          if (!argument_name_filter(member.c_str()))
-            args[member] = kStrippedArgument;
-        }
-      }
-      output_->AppendString(writer.write(event_copy));
-    } else {
-      output_->AppendString(writer.write(event));
-    }
-    first_event_ = false;
-  }
-
-  void WriteMetadataEvent(const char* metadata_type,
-                          const char* metadata_value,
-                          uint32_t tid,
-                          uint32_t pid) {
-    if (label_filter_ && !label_filter_("traceEvents"))
-      return;
-
-    if (!first_event_)
-      output_->AppendString(",\n");
-
-    Json::FastWriter writer;
-    writer.omitEndingLineFeed();
-    Json::Value value;
-    value["ph"] = "M";
-    value["cat"] = "__metadata";
-    value["ts"] = 0;
-    value["name"] = metadata_type;
-    value["tid"] = static_cast<int32_t>(tid);
-    value["pid"] = static_cast<int32_t>(pid);
-
-    Json::Value args;
-    args["name"] = metadata_value;
-    value["args"] = args;
-
-    output_->AppendString(writer.write(value));
-    first_event_ = false;
-  }
-
-  void MergeMetadata(const Json::Value& value) {
-    for (const auto& member : value.getMemberNames()) {
-      metadata_[member] = value[member];
-    }
-  }
-
-  void AppendTelemetryMetadataString(const char* key, const char* value) {
-    metadata_["telemetry"][key].append(value);
-  }
-
-  void AppendTelemetryMetadataInt(const char* key, int64_t value) {
-    metadata_["telemetry"][key].append(Json::Int64(value));
-  }
-
-  void AppendTelemetryMetadataBool(const char* key, bool value) {
-    metadata_["telemetry"][key].append(value);
-  }
-
-  void SetTelemetryMetadataTimestamp(const char* key, int64_t value) {
-    metadata_["telemetry"][key] = value / 1000.0;
-  }
-
-  void SetPerfettoStats(const char* key, int64_t value) {
-    metadata_["perfetto_trace_stats"][key] = Json::Int64(value);
-  }
-
-  void SetPerfettoBufferStats(const char* key, const IndexMap& indexed_values) {
-    for (const auto& value : indexed_values) {
-      metadata_["perfetto_trace_stats"]["buffer_stats"][value.first][key] =
-          Json::Int64(value.second);
-    }
-  }
-
-  void AddSystemTraceData(const std::string& data) {
-    system_trace_data_ += data;
-  }
-
-  void AddUserTraceData(const std::string& data) {
-    if (user_trace_data_.empty())
-      user_trace_data_ = "[";
-    user_trace_data_ += data;
-  }
-
- private:
-  void WriteHeader() {
-    if (!label_filter_)
-      output_->AppendString("{\"traceEvents\":[\n");
-  }
-
-  void WriteFooter() {
-    // Filter metadata entries.
-    if (metadata_filter_) {
-      for (const auto& member : metadata_.getMemberNames()) {
-        if (!metadata_filter_(member.c_str()))
-          metadata_[member] = kStrippedArgument;
-      }
-    }
-
-    Json::FastWriter writer;
-    writer.omitEndingLineFeed();
-    if ((!label_filter_ || label_filter_("traceEvents")) &&
-        !user_trace_data_.empty()) {
-      user_trace_data_ += "]";
-      Json::Reader reader;
-      Json::Value result;
-      if (reader.parse(user_trace_data_, result)) {
-        for (const auto& event : result) {
-          WriteCommonEvent(event);
-        }
-      } else {
-        PERFETTO_DLOG(
-            "can't parse legacy user json trace export, skipping. data: %s",
-            user_trace_data_.c_str());
-      }
-    }
-    if (!label_filter_)
-      output_->AppendString("]");
-    if ((!label_filter_ || label_filter_("systemTraceEvents")) &&
-        !system_trace_data_.empty()) {
-      output_->AppendString(",\"systemTraceEvents\":\n");
-      output_->AppendString(writer.write(Json::Value(system_trace_data_)));
-    }
-    if ((!label_filter_ || label_filter_("metadata")) && !metadata_.empty()) {
-      output_->AppendString(",\"metadata\":\n");
-      output_->AppendString(writer.write(metadata_));
-    }
-    if (!label_filter_)
-      output_->AppendString("}");
-  }
-
-  OutputWriter* output_;
-  ArgumentFilterPredicate argument_filter_;
-  MetadataFilterPredicate metadata_filter_;
-  LabelFilterPredicate label_filter_;
-
-  bool first_event_;
-  Json::Value metadata_;
-  std::string system_trace_data_;
-  std::string user_trace_data_;
-};
-
-std::string PrintUint64(uint64_t x) {
-  char hex_str[19];
-  sprintf(hex_str, "0x%" PRIx64, x);
-  return hex_str;
-}
-
-class ArgsBuilder {
- public:
-  explicit ArgsBuilder(const TraceStorage* storage)
-      : storage_(storage), empty_value_(Json::objectValue) {
-    const TraceStorage::Args& args = storage->args();
-    if (args.args_count() == 0) {
-      args_sets_.resize(1, empty_value_);
-      return;
-    }
-    args_sets_.resize(args.set_ids().back() + 1, empty_value_);
-    for (size_t i = 0; i < args.args_count(); ++i) {
-      ArgSetId set_id = args.set_ids()[i];
-      const char* key = GetNonNullString(storage_, args.keys()[i]);
-      Variadic value = args.arg_values()[i];
-      AppendArg(set_id, key, VariadicToJson(value));
-    }
-    PostprocessArgs();
-  }
-
-  const Json::Value& GetArgs(ArgSetId set_id) const {
-    // If |set_id| was empty and added to the storage last, it may not be in
-    // args_sets_.
-    if (set_id > args_sets_.size())
-      return empty_value_;
-    return args_sets_[set_id];
-  }
-
- private:
-  Json::Value VariadicToJson(Variadic variadic) {
-    switch (variadic.type) {
-      case Variadic::kInt:
-        return Json::Int64(variadic.int_value);
-      case Variadic::kUint:
-        return Json::UInt64(variadic.uint_value);
-      case Variadic::kString:
-        return GetNonNullString(storage_, variadic.string_value);
-      case Variadic::kReal:
-        return variadic.real_value;
-      case Variadic::kPointer:
-        return PrintUint64(variadic.pointer_value);
-      case Variadic::kBool:
-        return variadic.bool_value;
-      case Variadic::kJson:
-        Json::Reader reader;
-        Json::Value result;
-        reader.parse(GetNonNullString(storage_, variadic.json_value), result);
-        return result;
-    }
-    PERFETTO_FATAL("Not reached");  // For gcc.
-  }
-
-  void AppendArg(ArgSetId set_id,
-                 const std::string& key,
-                 const Json::Value& value) {
-    Json::Value* target = &args_sets_[set_id];
-    for (base::StringSplitter parts(key, '.'); parts.Next();) {
-      std::string key_part = parts.cur_token();
-      size_t bracketpos = key_part.find('[');
-      if (bracketpos == key_part.npos) {  // A single item
-        target = &(*target)[key_part];
-      } else {  // A list item
-        target = &(*target)[key_part.substr(0, bracketpos)];
-        while (bracketpos != key_part.npos) {
-          std::string index = key_part.substr(
-              bracketpos + 1, key_part.find(']', bracketpos) - bracketpos - 1);
-          target = &(*target)[stoi(index)];
-          bracketpos = key_part.find('[', bracketpos + 1);
-        }
-      }
-    }
-    *target = value;
-  }
-
-  void PostprocessArgs() {
-    for (Json::Value& args : args_sets_) {
-      // Move all fields from "debug" key to upper level.
-      if (args.isMember("debug")) {
-        Json::Value debug = args["debug"];
-        args.removeMember("debug");
-        for (const auto& member : debug.getMemberNames()) {
-          args[member] = debug[member];
-        }
-      }
-
-      // Rename source fields.
-      if (args.isMember("task")) {
-        if (args["task"].isMember("posted_from")) {
-          Json::Value posted_from = args["task"]["posted_from"];
-          args["task"].removeMember("posted_from");
-          if (posted_from.isMember("function_name")) {
-            args["src_func"] = posted_from["function_name"];
-            args["src_file"] = posted_from["file_name"];
-          } else if (posted_from.isMember("file_name")) {
-            args["src"] = posted_from["file_name"];
-          }
-        }
-        if (args["task"].empty())
-          args.removeMember("task");
-      }
-    }
-  }
-
-  const TraceStorage* storage_;
-  std::vector<Json::Value> args_sets_;
-  Json::Value empty_value_;
-};
-
-void ConvertLegacyFlowEventArgs(const Json::Value& legacy_args,
-                                Json::Value* event) {
-  if (legacy_args.isMember(kLegacyEventBindIdKey)) {
-    (*event)["bind_id"] =
-        PrintUint64(legacy_args[kLegacyEventBindIdKey].asUInt64());
-  }
-
-  if (legacy_args.isMember(kLegacyEventBindToEnclosingKey))
-    (*event)["bp"] = "e";
-
-  if (legacy_args.isMember(kLegacyEventFlowDirectionKey)) {
-    const char* val = legacy_args[kLegacyEventFlowDirectionKey].asCString();
-    if (strcmp(val, kFlowDirectionValueIn) == 0) {
-      (*event)["flow_in"] = true;
-    } else if (strcmp(val, kFlowDirectionValueOut) == 0) {
-      (*event)["flow_out"] = true;
-    } else {
-      PERFETTO_DCHECK(strcmp(val, kFlowDirectionValueInout) == 0);
-      (*event)["flow_in"] = true;
-      (*event)["flow_out"] = true;
-    }
-  }
-}
-
-util::Status ExportThreadNames(const TraceStorage* storage,
-                               TraceFormatWriter* writer) {
-  for (UniqueTid i = 1; i < storage->thread_count(); ++i) {
-    auto thread = storage->GetThread(i);
-    if (!thread.name_id.is_null()) {
-      const char* thread_name = GetNonNullString(storage, thread.name_id);
-      uint32_t pid = thread.upid ? storage->GetProcess(*thread.upid).pid : 0;
-      writer->WriteMetadataEvent("thread_name", thread_name, thread.tid, pid);
-    }
-  }
-  return util::OkStatus();
-}
-
-util::Status ExportProcessNames(const TraceStorage* storage,
-                                TraceFormatWriter* writer) {
-  for (UniquePid i = 1; i < storage->process_count(); ++i) {
-    auto process = storage->GetProcess(i);
-    if (!process.name_id.is_null()) {
-      const char* process_name = GetNonNullString(storage, process.name_id);
-      writer->WriteMetadataEvent("process_name", process_name, 0, process.pid);
-    }
-  }
-  return util::OkStatus();
-}
-
-util::Status ExportSlices(const TraceStorage* storage,
-                          const ArgsBuilder& args_builder,
-                          TraceFormatWriter* writer) {
-  const auto& slices = storage->nestable_slices();
-  for (uint32_t i = 0; i < slices.slice_count(); ++i) {
-    Json::Value event;
-    event["ts"] = Json::Int64(slices.start_ns()[i] / 1000);
-    event["cat"] = GetNonNullString(storage, slices.categories()[i]);
-    event["name"] = GetNonNullString(storage, slices.names()[i]);
-    event["pid"] = 0;
-    event["tid"] = 0;
-
-    int32_t legacy_tid = 0;
-
-    event["args"] =
-        args_builder.GetArgs(slices.arg_set_ids()[i]);  // Makes a copy.
-    if (event["args"].isMember(kLegacyEventArgsKey)) {
-      ConvertLegacyFlowEventArgs(event["args"][kLegacyEventArgsKey], &event);
-
-      if (event["args"][kLegacyEventArgsKey].isMember(
-              kLegacyEventOriginalTidKey)) {
-        legacy_tid = static_cast<int32_t>(
-            event["args"][kLegacyEventArgsKey][kLegacyEventOriginalTidKey]
-                .asInt());
-      }
-
-      event["args"].removeMember(kLegacyEventArgsKey);
-    }
-
-    // To prevent duplicate export of slices, only export slices on descriptor
-    // or chrome tracks (i.e. TrackEvent slices). Slices on other tracks may
-    // also be present as raw events and handled by trace_to_text. Only add more
-    // track types here if they are not already covered by trace_to_text.
-    auto track_id = slices.track_id()[i];
-    auto track_args_id = storage->track_table().source_arg_set_id()[track_id];
-    if (!track_args_id)
-      continue;
-    const auto& track_args = args_builder.GetArgs(*track_args_id);
-    bool legacy_chrome_track = track_args["source"].asString() == "chrome";
-    if (!track_args.isMember("source") ||
-        (!legacy_chrome_track &&
-         track_args["source"].asString() != "descriptor")) {
-      continue;
-    }
-
-    const auto& thread_track = storage->thread_track_table();
-    const auto& process_track = storage->process_track_table();
-    const auto& thread_slices = storage->thread_slices();
-    const auto& virtual_track_slices = storage->virtual_track_slices();
-
-    int64_t duration_ns = slices.durations()[i];
-    int64_t thread_ts_ns = 0;
-    int64_t thread_duration_ns = 0;
-    int64_t thread_instruction_count = 0;
-    int64_t thread_instruction_delta = 0;
-
-    base::Optional<uint32_t> thread_slice_row =
-        thread_slices.FindRowForSliceId(i);
-    if (thread_slice_row) {
-      thread_ts_ns = thread_slices.thread_timestamp_ns()[*thread_slice_row];
-      thread_duration_ns =
-          thread_slices.thread_duration_ns()[*thread_slice_row];
-      thread_instruction_count =
-          thread_slices.thread_instruction_counts()[*thread_slice_row];
-      thread_instruction_delta =
-          thread_slices.thread_instruction_deltas()[*thread_slice_row];
-    } else {
-      base::Optional<uint32_t> vtrack_slice_row =
-          virtual_track_slices.FindRowForSliceId(i);
-      if (vtrack_slice_row) {
-        thread_ts_ns =
-            virtual_track_slices.thread_timestamp_ns()[*vtrack_slice_row];
-        thread_duration_ns =
-            virtual_track_slices.thread_duration_ns()[*vtrack_slice_row];
-        thread_instruction_count =
-            virtual_track_slices.thread_instruction_counts()[*vtrack_slice_row];
-        thread_instruction_delta =
-            virtual_track_slices.thread_instruction_deltas()[*vtrack_slice_row];
-      }
-    }
-
-    auto opt_thread_track_row =
-        thread_track.id().IndexOf(SqlValue::Long(track_id));
-
-    if (opt_thread_track_row) {
-      // Synchronous (thread) slice or instant event.
-      UniqueTid utid = thread_track.utid()[*opt_thread_track_row];
-      auto thread = storage->GetThread(utid);
-      event["tid"] = static_cast<int32_t>(thread.tid);
-      if (thread.upid) {
-        event["pid"] =
-            static_cast<int32_t>(storage->GetProcess(*thread.upid).pid);
-      }
-
-      if (duration_ns == 0) {
-        // Use "I" instead of "i" phase for backwards-compat with old consumers.
-        event["ph"] = "I";
-        if (thread_ts_ns > 0) {
-          event["tts"] = Json::Int64(thread_ts_ns / 1000);
-        }
-        if (thread_instruction_count > 0) {
-          event["ticount"] = Json::Int64(thread_instruction_count);
-        }
-        event["s"] = "t";
-      } else {
-        if (duration_ns > 0) {
-          event["ph"] = "X";
-          event["dur"] = Json::Int64(duration_ns / 1000);
-        } else {
-          // If the slice didn't finish, the duration may be negative. Only
-          // write a begin event without end event in this case.
-          event["ph"] = "B";
-        }
-        if (thread_ts_ns > 0) {
-          event["tts"] = Json::Int64(thread_ts_ns / 1000);
-          // Only write thread duration for completed events.
-          if (duration_ns > 0)
-            event["tdur"] = Json::Int64(thread_duration_ns / 1000);
-        }
-        if (thread_instruction_count > 0) {
-          event["ticount"] = Json::Int64(thread_instruction_count);
-          // Only write thread instruction delta for completed events.
-          if (duration_ns > 0)
-            event["tidelta"] = Json::Int64(thread_instruction_delta);
-        }
-      }
-      writer->WriteCommonEvent(event);
-    } else if (!legacy_chrome_track ||
-               (legacy_chrome_track && track_args.isMember("source_id"))) {
-      // Async event slice.
-      auto opt_process_row =
-          process_track.id().IndexOf(SqlValue::Long(track_id));
-      if (legacy_chrome_track) {
-        // Legacy async tracks are always process-associated.
-        PERFETTO_DCHECK(opt_process_row);
-        uint32_t upid = process_track.upid()[*opt_process_row];
-        event["pid"] = static_cast<int32_t>(storage->GetProcess(upid).pid);
-        event["tid"] =
-            legacy_tid ? legacy_tid
-                       : static_cast<int32_t>(storage->GetProcess(upid).pid);
-
-        // Preserve original event IDs for legacy tracks. This is so that e.g.
-        // memory dump IDs show up correctly in the JSON trace.
-        PERFETTO_DCHECK(track_args.isMember("source_id"));
-        PERFETTO_DCHECK(track_args.isMember("source_id_is_process_scoped"));
-        PERFETTO_DCHECK(track_args.isMember("source_scope"));
-        uint64_t source_id =
-            static_cast<uint64_t>(track_args["source_id"].asInt64());
-        std::string source_scope = track_args["source_scope"].asString();
-        if (!source_scope.empty())
-          event["scope"] = source_scope;
-        bool source_id_is_process_scoped =
-            track_args["source_id_is_process_scoped"].asBool();
-        if (source_id_is_process_scoped) {
-          event["id2"]["local"] = PrintUint64(source_id);
-        } else {
-          // Some legacy importers don't understand "id2" fields, so we use the
-          // "usually" global "id" field instead. This works as long as the
-          // event phase is not in {'N', 'D', 'O', '(', ')'}, see
-          // "LOCAL_ID_PHASES" in catapult.
-          event["id"] = PrintUint64(source_id);
-        }
-      } else {
-        if (opt_process_row) {
-          uint32_t upid = process_track.upid()[*opt_process_row];
-          event["id2"]["local"] = PrintUint64(track_id);
-          event["pid"] = static_cast<int32_t>(storage->GetProcess(upid).pid);
-          event["tid"] =
-              legacy_tid ? legacy_tid
-                         : static_cast<int32_t>(storage->GetProcess(upid).pid);
-        } else {
-          // Some legacy importers don't understand "id2" fields, so we use the
-          // "usually" global "id" field instead. This works as long as the
-          // event phase is not in {'N', 'D', 'O', '(', ')'}, see
-          // "LOCAL_ID_PHASES" in catapult.
-          event["id"] = PrintUint64(track_id);
-        }
-      }
-
-      if (thread_ts_ns > 0) {
-        event["tts"] = Json::Int64(thread_ts_ns / 1000);
-        event["use_async_tts"] = Json::Int(1);
-      }
-      if (thread_instruction_count > 0) {
-        event["ticount"] = Json::Int64(thread_instruction_count);
-        event["use_async_tts"] = Json::Int(1);
-      }
-
-      if (duration_ns == 0) {  // Instant async event.
-        event["ph"] = "n";
-        writer->WriteCommonEvent(event);
-      } else {  // Async start and end.
-        event["ph"] = "b";
-        writer->WriteCommonEvent(event);
-        // If the slice didn't finish, the duration may be negative. Don't
-        // write the end event in this case.
-        if (duration_ns > 0) {
-          event["ph"] = "e";
-          event["ts"] =
-              Json::Int64((slices.start_ns()[i] + duration_ns) / 1000);
-          if (thread_ts_ns > 0) {
-            event["tts"] =
-                Json::Int64((thread_ts_ns + thread_duration_ns) / 1000);
-          }
-          if (thread_instruction_count > 0) {
-            event["ticount"] = Json::Int64(
-                (thread_instruction_count + thread_instruction_delta));
-          }
-          event["args"].clear();
-          writer->WriteCommonEvent(event);
-        }
-      }
-    } else {
-      // Global or process-scoped instant event.
-      PERFETTO_DCHECK(duration_ns == 0);
-      // Use "I" instead of "i" phase for backwards-compat with old consumers.
-      event["ph"] = "I";
-
-      auto opt_process_row =
-          process_track.id().IndexOf(SqlValue::Long(track_id));
-      if (opt_process_row.has_value()) {
-        uint32_t upid = process_track.upid()[*opt_process_row];
-        event["pid"] = static_cast<int32_t>(storage->GetProcess(upid).pid);
-        event["tid"] =
-            legacy_tid ? legacy_tid
-                       : static_cast<int32_t>(storage->GetProcess(upid).pid);
-        event["s"] = "p";
-      } else {
-        event["s"] = "g";
-      }
-      writer->WriteCommonEvent(event);
-    }
-  }
-  return util::OkStatus();
-}
-
-Json::Value ConvertLegacyRawEventToJson(const TraceStorage* storage,
-                                        const ArgsBuilder& args_builder,
-                                        uint32_t index) {
-  const auto& events = storage->raw_events();
-
-  Json::Value event;
-  event["ts"] = Json::Int64(events.timestamps()[index] / 1000);
-
-  UniqueTid utid = static_cast<UniqueTid>(events.utids()[index]);
-  auto thread = storage->GetThread(utid);
-  event["tid"] = static_cast<int32_t>(thread.tid);
-  event["pid"] = 0;
-  if (thread.upid)
-    event["pid"] = static_cast<int32_t>(storage->GetProcess(*thread.upid).pid);
-
-  // Raw legacy events store all other params in the arg set. Make a copy of
-  // the converted args here, parse, and then remove the legacy params.
-  event["args"] = args_builder.GetArgs(events.arg_set_ids()[index]);
-  const Json::Value& legacy_args = event["args"][kLegacyEventArgsKey];
-
-  PERFETTO_DCHECK(legacy_args.isMember(kLegacyEventCategoryKey));
-  event["cat"] = legacy_args[kLegacyEventCategoryKey];
-
-  PERFETTO_DCHECK(legacy_args.isMember(kLegacyEventNameKey));
-  event["name"] = legacy_args[kLegacyEventNameKey];
-
-  PERFETTO_DCHECK(legacy_args.isMember(kLegacyEventPhaseKey));
-  event["ph"] = legacy_args[kLegacyEventPhaseKey];
-
-  // Object snapshot events are supposed to have a mandatory "snapshot" arg,
-  // which may be removed in trace processor if it is empty.
-  if (legacy_args[kLegacyEventPhaseKey] == "O" &&
-      !event["args"].isMember("snapshot")) {
-    event["args"]["snapshot"] = Json::Value(Json::objectValue);
-  }
-
-  if (legacy_args.isMember(kLegacyEventDurationNsKey))
-    event["dur"] = legacy_args[kLegacyEventDurationNsKey].asInt64() / 1000;
-
-  if (legacy_args.isMember(kLegacyEventThreadTimestampNsKey)) {
-    event["tts"] =
-        legacy_args[kLegacyEventThreadTimestampNsKey].asInt64() / 1000;
-  }
-
-  if (legacy_args.isMember(kLegacyEventThreadDurationNsKey)) {
-    event["tdur"] =
-        legacy_args[kLegacyEventThreadDurationNsKey].asInt64() / 1000;
-  }
-
-  if (legacy_args.isMember(kLegacyEventThreadInstructionCountKey))
-    event["ticount"] = legacy_args[kLegacyEventThreadInstructionCountKey];
-
-  if (legacy_args.isMember(kLegacyEventThreadInstructionDeltaKey))
-    event["tidelta"] = legacy_args[kLegacyEventThreadInstructionDeltaKey];
-
-  if (legacy_args.isMember(kLegacyEventUseAsyncTtsKey))
-    event["use_async_tts"] = legacy_args[kLegacyEventUseAsyncTtsKey];
-
-  if (legacy_args.isMember(kLegacyEventUnscopedIdKey)) {
-    event["id"] =
-        PrintUint64(legacy_args[kLegacyEventUnscopedIdKey].asUInt64());
-  }
-
-  if (legacy_args.isMember(kLegacyEventGlobalIdKey)) {
-    event["id2"]["global"] =
-        PrintUint64(legacy_args[kLegacyEventGlobalIdKey].asUInt64());
-  }
-
-  if (legacy_args.isMember(kLegacyEventLocalIdKey)) {
-    event["id2"]["local"] =
-        PrintUint64(legacy_args[kLegacyEventLocalIdKey].asUInt64());
-  }
-
-  if (legacy_args.isMember(kLegacyEventIdScopeKey))
-    event["scope"] = legacy_args[kLegacyEventIdScopeKey];
-
-  ConvertLegacyFlowEventArgs(legacy_args, &event);
-
-  event["args"].removeMember(kLegacyEventArgsKey);
-
-  return event;
-}
-
-util::Status ExportRawEvents(const TraceStorage* storage,
-                             const ArgsBuilder& args_builder,
-                             TraceFormatWriter* writer) {
-  base::Optional<StringId> raw_legacy_event_key_id =
-      storage->string_pool().GetId("track_event.legacy_event");
-  base::Optional<StringId> raw_legacy_system_trace_event_id =
-      storage->string_pool().GetId("chrome_event.legacy_system_trace");
-  base::Optional<StringId> raw_legacy_user_trace_event_id =
-      storage->string_pool().GetId("chrome_event.legacy_user_trace");
-  base::Optional<StringId> raw_chrome_metadata_event_id =
-      storage->string_pool().GetId("chrome_event.metadata");
-
-  const auto& events = storage->raw_events();
-  for (uint32_t i = 0; i < events.raw_event_count(); ++i) {
-    if (raw_legacy_event_key_id &&
-        events.name_ids()[i] == *raw_legacy_event_key_id) {
-      Json::Value event = ConvertLegacyRawEventToJson(storage, args_builder, i);
-      writer->WriteCommonEvent(event);
-    } else if (raw_legacy_system_trace_event_id &&
-               events.name_ids()[i] == *raw_legacy_system_trace_event_id) {
-      Json::Value args = args_builder.GetArgs(events.arg_set_ids()[i]);
-      PERFETTO_DCHECK(args.isMember("data"));
-      writer->AddSystemTraceData(args["data"].asString());
-    } else if (raw_legacy_user_trace_event_id &&
-               events.name_ids()[i] == *raw_legacy_user_trace_event_id) {
-      Json::Value args = args_builder.GetArgs(events.arg_set_ids()[i]);
-      PERFETTO_DCHECK(args.isMember("data"));
-      writer->AddUserTraceData(args["data"].asString());
-    } else if (raw_chrome_metadata_event_id &&
-               events.name_ids()[i] == *raw_chrome_metadata_event_id) {
-      Json::Value args = args_builder.GetArgs(events.arg_set_ids()[i]);
-      writer->MergeMetadata(args);
-    }
-  }
-  return util::OkStatus();
-}
-
-util::Status ExportCpuProfileSamples(const TraceStorage* storage,
-                                     TraceFormatWriter* writer) {
-  const TraceStorage::CpuProfileStackSamples& samples =
-      storage->cpu_profile_stack_samples();
-  for (uint32_t i = 0; i < samples.size(); ++i) {
-    Json::Value event;
-    event["ts"] = Json::Int64(samples.timestamps()[i] / 1000);
-
-    UniqueTid utid = static_cast<UniqueTid>(samples.utids()[i]);
-    auto thread = storage->GetThread(utid);
-    event["tid"] = static_cast<int32_t>(thread.tid);
-    if (thread.upid) {
-      event["pid"] =
-          static_cast<int32_t>(storage->GetProcess(*thread.upid).pid);
-    }
-
-    // Use "I" instead of "i" phase for backwards-compat with old consumers.
-    event["ph"] = "I";
-    event["cat"] = "disabled_by_default-cpu_profiler";
-    event["name"] = "StackCpuSampling";
-    event["s"] = "t";
-
-    std::vector<std::string> callstack;
-    const auto& callsites = storage->stack_profile_callsite_table();
-    int64_t maybe_callsite_id = samples.callsite_ids()[i];
-    PERFETTO_DCHECK(maybe_callsite_id >= 0 &&
-                    maybe_callsite_id < callsites.size());
-    while (maybe_callsite_id >= 0) {
-      uint32_t callsite_id = static_cast<uint32_t>(maybe_callsite_id);
-
-      const TraceStorage::StackProfileFrames& frames =
-          storage->stack_profile_frames();
-      PERFETTO_DCHECK(callsites.frame_id()[callsite_id] >= 0 &&
-                      callsites.frame_id()[callsite_id] < frames.size());
-      size_t frame_id = static_cast<size_t>(callsites.frame_id()[callsite_id]);
-
-      const TraceStorage::StackProfileMappings& mappings =
-          storage->stack_profile_mappings();
-      PERFETTO_DCHECK(frames.mappings()[frame_id] >= 0 &&
-                      frames.mappings()[frame_id] < mappings.size());
-      size_t mapping_id = static_cast<size_t>(frames.mappings()[frame_id]);
-
-      NullTermStringView symbol_name;
-      uint32_t symbol_set_id = frames.symbol_set_ids()[frame_id];
-      if (symbol_set_id) {
-        symbol_name =
-            storage->GetString(storage->symbol_table().name()[symbol_set_id]);
-      }
-
-      char frame_entry[1024];
-      snprintf(
-          frame_entry, sizeof(frame_entry), "%s - %s [%s]\n",
-          (symbol_name.empty()
-               ? PrintUint64(static_cast<uint64_t>(frames.rel_pcs()[frame_id]))
-                     .c_str()
-               : symbol_name.c_str()),
-          GetNonNullString(storage, mappings.names()[mapping_id]),
-          GetNonNullString(storage, mappings.build_ids()[mapping_id]));
-
-      callstack.emplace_back(frame_entry);
-
-      maybe_callsite_id = callsites.parent_id()[callsite_id];
-    }
-
-    std::string merged_callstack;
-    for (auto entry = callstack.rbegin(); entry != callstack.rend(); ++entry) {
-      merged_callstack += *entry;
-    }
-
-    event["args"]["frames"] = merged_callstack;
-    writer->WriteCommonEvent(event);
-  }
-
-  return util::OkStatus();
-}
-
-util::Status ExportMetadata(const TraceStorage* storage,
-                            TraceFormatWriter* writer) {
-  const auto& trace_metadata = storage->metadata();
-  const auto& keys = trace_metadata.keys();
-  const auto& values = trace_metadata.values();
-  for (size_t pos = 0; pos < keys.size(); pos++) {
-    // Cast away from enum type, as otherwise -Wswitch-enum will demand an
-    // exhaustive list of cases, even if there's a default case.
-    switch (static_cast<size_t>(keys[pos])) {
-      case metadata::benchmark_description:
-        writer->AppendTelemetryMetadataString(
-            "benchmarkDescriptions",
-            GetNonNullString(storage, values[pos].string_value));
-        break;
-
-      case metadata::benchmark_name:
-        writer->AppendTelemetryMetadataString(
-            "benchmarks", GetNonNullString(storage, values[pos].string_value));
-        break;
-
-      case metadata::benchmark_start_time_us:
-
-        writer->SetTelemetryMetadataTimestamp("benchmarkStart",
-                                              values[pos].int_value);
-        break;
-
-      case metadata::benchmark_had_failures:
-        if (pos < values.size())
-          writer->AppendTelemetryMetadataBool("hadFailures",
-                                              values[pos].int_value);
-        break;
-
-      case metadata::benchmark_label:
-        writer->AppendTelemetryMetadataString(
-            "labels", GetNonNullString(storage, values[pos].string_value));
-        break;
-
-      case metadata::benchmark_story_name:
-        writer->AppendTelemetryMetadataString(
-            "stories", GetNonNullString(storage, values[pos].string_value));
-        break;
-
-      case metadata::benchmark_story_run_index:
-        writer->AppendTelemetryMetadataInt("storysetRepeats",
-                                           values[pos].int_value);
-        break;
-
-      case metadata::benchmark_story_run_time_us:
-        writer->SetTelemetryMetadataTimestamp("traceStart",
-                                              values[pos].int_value);
-        break;
-
-      case metadata::benchmark_story_tags:  // repeated
-        writer->AppendTelemetryMetadataString(
-            "storyTags", GetNonNullString(storage, values[pos].string_value));
-        break;
-
-      default:
-        PERFETTO_DLOG("Ignoring metadata key %zu",
-                      static_cast<size_t>(keys[pos]));
-        break;
-    }
-  }
-  return util::OkStatus();
-}
-
-util::Status ExportStats(const TraceStorage* storage,
-                         TraceFormatWriter* writer) {
-  const auto& stats = storage->stats();
-
-  writer->SetPerfettoStats("producers_connected",
-                           stats[stats::traced_producers_connected].value);
-  writer->SetPerfettoStats("producers_seen",
-                           stats[stats::traced_producers_seen].value);
-  writer->SetPerfettoStats("data_sources_registered",
-                           stats[stats::traced_data_sources_registered].value);
-  writer->SetPerfettoStats("data_sources_seen",
-                           stats[stats::traced_data_sources_seen].value);
-  writer->SetPerfettoStats("tracing_sessions",
-                           stats[stats::traced_tracing_sessions].value);
-  writer->SetPerfettoStats("total_buffers",
-                           stats[stats::traced_total_buffers].value);
-  writer->SetPerfettoStats("chunks_discarded",
-                           stats[stats::traced_chunks_discarded].value);
-  writer->SetPerfettoStats("patches_discarded",
-                           stats[stats::traced_patches_discarded].value);
-
-  writer->SetPerfettoBufferStats(
-      "buffer_size", stats[stats::traced_buf_buffer_size].indexed_values);
-  writer->SetPerfettoBufferStats(
-      "bytes_written", stats[stats::traced_buf_bytes_written].indexed_values);
-  writer->SetPerfettoBufferStats(
-      "bytes_overwritten",
-      stats[stats::traced_buf_bytes_overwritten].indexed_values);
-  writer->SetPerfettoBufferStats(
-      "bytes_read", stats[stats::traced_buf_bytes_read].indexed_values);
-  writer->SetPerfettoBufferStats(
-      "padding_bytes_written",
-      stats[stats::traced_buf_padding_bytes_written].indexed_values);
-  writer->SetPerfettoBufferStats(
-      "padding_bytes_cleared",
-      stats[stats::traced_buf_padding_bytes_cleared].indexed_values);
-  writer->SetPerfettoBufferStats(
-      "chunks_written", stats[stats::traced_buf_chunks_written].indexed_values);
-  writer->SetPerfettoBufferStats(
-      "chunks_rewritten",
-      stats[stats::traced_buf_chunks_rewritten].indexed_values);
-  writer->SetPerfettoBufferStats(
-      "chunks_overwritten",
-      stats[stats::traced_buf_chunks_overwritten].indexed_values);
-  writer->SetPerfettoBufferStats(
-      "chunks_discarded",
-      stats[stats::traced_buf_chunks_discarded].indexed_values);
-  writer->SetPerfettoBufferStats(
-      "chunks_read", stats[stats::traced_buf_chunks_read].indexed_values);
-  writer->SetPerfettoBufferStats(
-      "chunks_committed_out_of_order",
-      stats[stats::traced_buf_chunks_committed_out_of_order].indexed_values);
-  writer->SetPerfettoBufferStats(
-      "write_wrap_count",
-      stats[stats::traced_buf_write_wrap_count].indexed_values);
-  writer->SetPerfettoBufferStats(
-      "patches_succeeded",
-      stats[stats::traced_buf_patches_succeeded].indexed_values);
-  writer->SetPerfettoBufferStats(
-      "patches_failed", stats[stats::traced_buf_patches_failed].indexed_values);
-  writer->SetPerfettoBufferStats(
-      "readaheads_succeeded",
-      stats[stats::traced_buf_readaheads_succeeded].indexed_values);
-  writer->SetPerfettoBufferStats(
-      "readaheads_failed",
-      stats[stats::traced_buf_readaheads_failed].indexed_values);
-  writer->SetPerfettoBufferStats(
-      "trace_writer_packet_loss",
-      stats[stats::traced_buf_trace_writer_packet_loss].indexed_values);
-
-  return util::OkStatus();
-}
-
-}  // namespace
-
-OutputWriter::OutputWriter() = default;
-OutputWriter::~OutputWriter() = default;
-
-util::Status ExportJson(const TraceStorage* storage,
-                        OutputWriter* output,
-                        ArgumentFilterPredicate argument_filter,
-                        MetadataFilterPredicate metadata_filter,
-                        LabelFilterPredicate label_filter) {
-  // TODO(eseckler): Implement argument/metadata/label filtering.
-  TraceFormatWriter writer(output, argument_filter, metadata_filter,
-                           label_filter);
-  ArgsBuilder args_builder(storage);
-
-  util::Status status = ExportThreadNames(storage, &writer);
-  if (!status.ok())
-    return status;
-
-  status = ExportProcessNames(storage, &writer);
-  if (!status.ok())
-    return status;
-
-  status = ExportSlices(storage, args_builder, &writer);
-  if (!status.ok())
-    return status;
-
-  status = ExportRawEvents(storage, args_builder, &writer);
-  if (!status.ok())
-    return status;
-
-  status = ExportCpuProfileSamples(storage, &writer);
-  if (!status.ok())
-    return status;
-
-  status = ExportMetadata(storage, &writer);
-  if (!status.ok())
-    return status;
-
-  status = ExportStats(storage, &writer);
-  if (!status.ok())
-    return status;
-
-  return util::OkStatus();
-}
-
-util::Status ExportJson(TraceProcessorStorage* tp,
-                        OutputWriter* output,
-                        ArgumentFilterPredicate argument_filter,
-                        MetadataFilterPredicate metadata_filter,
-                        LabelFilterPredicate label_filter) {
-  const TraceStorage* storage = reinterpret_cast<TraceProcessorStorageImpl*>(tp)
-                                    ->context()
-                                    ->storage.get();
-  return ExportJson(storage, output, argument_filter, metadata_filter,
-                    label_filter);
-}
-
-util::Status ExportJson(const TraceStorage* storage, FILE* output) {
-  FileWriter writer(output);
-  return ExportJson(storage, &writer, nullptr, nullptr, nullptr);
-}
-
-}  // namespace json
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
diff --git a/src/trace_processor/export_json.h b/src/trace_processor/export_json.h
deleted file mode 100644
index 5d2ea54..0000000
--- a/src/trace_processor/export_json.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_EXPORT_JSON_H_
-#define SRC_TRACE_PROCESSOR_EXPORT_JSON_H_
-
-#include <stdio.h>
-
-#include "perfetto/ext/trace_processor/export_json.h"
-#include "perfetto/trace_processor/status.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace json {
-
-// Export trace to a file stream in json format.
-util::Status ExportJson(const TraceStorage*, FILE* output);
-
-// For testing.
-util::Status ExportJson(const TraceStorage* storage,
-                        OutputWriter*,
-                        ArgumentFilterPredicate = nullptr,
-                        MetadataFilterPredicate = nullptr,
-                        LabelFilterPredicate = nullptr);
-
-}  // namespace json
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_EXPORT_JSON_H_
diff --git a/src/trace_processor/export_json_unittest.cc b/src/trace_processor/export_json_unittest.cc
deleted file mode 100644
index c5c949a..0000000
--- a/src/trace_processor/export_json_unittest.cc
+++ /dev/null
@@ -1,1358 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/ext/trace_processor/export_json.h"
-#include "src/trace_processor/export_json.h"
-
-#include <string.h>
-
-#include <limits>
-
-#include <json/reader.h>
-#include <json/value.h>
-
-#include "perfetto/ext/base/temp_file.h"
-#include "src/trace_processor/args_tracker.h"
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/track_tracker.h"
-
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace json {
-namespace {
-
-std::string ReadFile(FILE* input) {
-  fseek(input, 0, SEEK_SET);
-  const int kBufSize = 1000;
-  char buffer[kBufSize];
-  size_t ret = fread(buffer, sizeof(char), kBufSize, input);
-  EXPECT_GT(ret, 0u);
-  return std::string(buffer, ret);
-}
-
-class StringOutputWriter : public OutputWriter {
- public:
-  StringOutputWriter() { str_.reserve(1024); }
-  ~StringOutputWriter() override {}
-
-  util::Status AppendString(const std::string& str) override {
-    str_ += str;
-    return util::OkStatus();
-  }
-
-  std::string TakeStr() { return std::move(str_); }
-
- private:
-  std::string str_;
-};
-
-class ExportJsonTest : public ::testing::Test {
- public:
-  ExportJsonTest() {
-    context_.args_tracker.reset(new ArgsTracker(&context_));
-    context_.storage.reset(new TraceStorage());
-    context_.track_tracker.reset(new TrackTracker(&context_));
-  }
-
-  std::string ToJson(ArgumentFilterPredicate argument_filter = nullptr,
-                     MetadataFilterPredicate metadata_filter = nullptr,
-                     LabelFilterPredicate label_filter = nullptr) {
-    StringOutputWriter writer;
-    util::Status status =
-        ExportJson(context_.storage.get(), &writer, argument_filter,
-                   metadata_filter, label_filter);
-    EXPECT_TRUE(status.ok());
-    return writer.TakeStr();
-  }
-
-  Json::Value ToJsonValue(const std::string& json) {
-    Json::Reader reader;
-    Json::Value result;
-    EXPECT_TRUE(reader.parse(json, result));
-    return result;
-  }
-
- protected:
-  TraceProcessorContext context_;
-};
-
-TEST_F(ExportJsonTest, EmptyStorage) {
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 0u);
-}
-
-TEST_F(ExportJsonTest, StorageWithOneSlice) {
-  const int64_t kTimestamp = 10000000;
-  const int64_t kDuration = 10000;
-  const int64_t kThreadTimestamp = 20000000;
-  const int64_t kThreadDuration = 20000;
-  const int64_t kThreadInstructionCount = 30000000;
-  const int64_t kThreadInstructionDelta = 30000;
-  const int64_t kThreadID = 100;
-  const char* kCategory = "cat";
-  const char* kName = "name";
-
-  UniqueTid utid = context_.storage->AddEmptyThread(kThreadID);
-  TrackId track =
-      context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
-  context_.args_tracker->Flush();  // Flush track args.
-  StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
-  StringId name_id = context_.storage->InternString(base::StringView(kName));
-  context_.storage->mutable_nestable_slices()->AddSlice(
-      kTimestamp, kDuration, track, utid, RefType::kRefUtid, cat_id, name_id, 0,
-      0, 0);
-  context_.storage->mutable_thread_slices()->AddThreadSlice(
-      0, kThreadTimestamp, kThreadDuration, kThreadInstructionCount,
-      kThreadInstructionDelta);
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 1u);
-
-  Json::Value event = result["traceEvents"][0];
-  EXPECT_EQ(event["ph"].asString(), "X");
-  EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
-  EXPECT_EQ(event["dur"].asInt64(), kDuration / 1000);
-  EXPECT_EQ(event["tts"].asInt64(), kThreadTimestamp / 1000);
-  EXPECT_EQ(event["tdur"].asInt64(), kThreadDuration / 1000);
-  EXPECT_EQ(event["ticount"].asInt64(), kThreadInstructionCount);
-  EXPECT_EQ(event["tidelta"].asInt64(), kThreadInstructionDelta);
-  EXPECT_EQ(event["tid"].asUInt(), kThreadID);
-  EXPECT_EQ(event["cat"].asString(), kCategory);
-  EXPECT_EQ(event["name"].asString(), kName);
-  EXPECT_TRUE(event["args"].isObject());
-  EXPECT_EQ(event["args"].size(), 0u);
-}
-
-TEST_F(ExportJsonTest, StorageWithOneUnfinishedSlice) {
-  const int64_t kTimestamp = 10000000;
-  const int64_t kDuration = -1;
-  const int64_t kThreadTimestamp = 20000000;
-  const int64_t kThreadDuration = -1;
-  const int64_t kThreadInstructionCount = 30000000;
-  const int64_t kThreadInstructionDelta = -1;
-  const int64_t kThreadID = 100;
-  const char* kCategory = "cat";
-  const char* kName = "name";
-
-  UniqueTid utid = context_.storage->AddEmptyThread(kThreadID);
-  TrackId track =
-      context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
-  context_.args_tracker->Flush();  // Flush track args.
-  StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
-  StringId name_id = context_.storage->InternString(base::StringView(kName));
-  context_.storage->mutable_nestable_slices()->AddSlice(
-      kTimestamp, kDuration, track, utid, RefType::kRefUtid, cat_id, name_id, 0,
-      0, 0);
-  context_.storage->mutable_thread_slices()->AddThreadSlice(
-      0, kThreadTimestamp, kThreadDuration, kThreadInstructionCount,
-      kThreadInstructionDelta);
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 1u);
-
-  Json::Value event = result["traceEvents"][0];
-  EXPECT_EQ(event["ph"].asString(), "B");
-  EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
-  EXPECT_FALSE(event.isMember("dur"));
-  EXPECT_EQ(event["tts"].asInt64(), kThreadTimestamp / 1000);
-  EXPECT_FALSE(event.isMember("tdur"));
-  EXPECT_EQ(event["ticount"].asInt64(), kThreadInstructionCount);
-  EXPECT_FALSE(event.isMember("tidelta"));
-  EXPECT_EQ(event["tid"].asUInt(), kThreadID);
-  EXPECT_EQ(event["cat"].asString(), kCategory);
-  EXPECT_EQ(event["name"].asString(), kName);
-  EXPECT_TRUE(event["args"].isObject());
-  EXPECT_EQ(event["args"].size(), 0u);
-}
-
-TEST_F(ExportJsonTest, StorageWithThreadName) {
-  const int64_t kThreadID = 100;
-  const char* kName = "thread";
-
-  UniqueTid utid = context_.storage->AddEmptyThread(kThreadID);
-  StringId name_id = context_.storage->InternString(base::StringView(kName));
-  context_.storage->GetMutableThread(utid)->name_id = name_id;
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 1u);
-
-  Json::Value event = result["traceEvents"][0];
-  EXPECT_EQ(event["ph"].asString(), "M");
-  EXPECT_EQ(event["tid"].asUInt(), kThreadID);
-  EXPECT_EQ(event["name"].asString(), "thread_name");
-  EXPECT_EQ(event["args"]["name"].asString(), kName);
-}
-
-TEST_F(ExportJsonTest, WrongTrackTypeIgnored) {
-  constexpr int64_t kCookie = 22;
-  TrackId track = context_.track_tracker->InternAndroidAsyncTrack(
-      /*name=*/0, /*upid=*/0, kCookie);
-  context_.args_tracker->Flush();  // Flush track args.
-
-  StringId cat_id = context_.storage->InternString("cat");
-  StringId name_id = context_.storage->InternString("name");
-  context_.storage->mutable_nestable_slices()->AddSlice(
-      0, 0, track, track, RefType::kRefTrack, cat_id, name_id, 0, 0, 0);
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 0u);
-}
-
-TEST_F(ExportJsonTest, StorageWithMetadata) {
-  const char* kDescription = "description";
-  const char* kBenchmarkName = "benchmark name";
-  const char* kStoryName = "story name";
-  const char* kStoryTag1 = "tag1";
-  const char* kStoryTag2 = "tag2";
-  const int64_t kBenchmarkStart = 1000000;
-  const int64_t kStoryStart = 2000000;
-  const bool kHadFailures = true;
-
-  StringId desc_id =
-      context_.storage->InternString(base::StringView(kDescription));
-  Variadic description = Variadic::String(desc_id);
-  context_.storage->SetMetadata(metadata::benchmark_description, description);
-
-  StringId benchmark_name_id =
-      context_.storage->InternString(base::StringView(kBenchmarkName));
-  Variadic benchmark_name = Variadic::String(benchmark_name_id);
-  context_.storage->SetMetadata(metadata::benchmark_name, benchmark_name);
-
-  StringId story_name_id =
-      context_.storage->InternString(base::StringView(kStoryName));
-  Variadic story_name = Variadic::String(story_name_id);
-  context_.storage->SetMetadata(metadata::benchmark_story_name, story_name);
-
-  StringId tag1_id =
-      context_.storage->InternString(base::StringView(kStoryTag1));
-  StringId tag2_id =
-      context_.storage->InternString(base::StringView(kStoryTag2));
-  Variadic tag1 = Variadic::String(tag1_id);
-  Variadic tag2 = Variadic::String(tag2_id);
-  context_.storage->AppendMetadata(metadata::benchmark_story_tags, tag1);
-  context_.storage->AppendMetadata(metadata::benchmark_story_tags, tag2);
-
-  Variadic benchmark_start = Variadic::Integer(kBenchmarkStart);
-  context_.storage->SetMetadata(metadata::benchmark_start_time_us,
-                                benchmark_start);
-
-  Variadic story_start = Variadic::Integer(kStoryStart);
-  context_.storage->SetMetadata(metadata::benchmark_story_run_time_us,
-                                story_start);
-
-  Variadic had_failures = Variadic::Integer(kHadFailures);
-  context_.storage->SetMetadata(metadata::benchmark_had_failures, had_failures);
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-
-  EXPECT_TRUE(result.isMember("metadata"));
-  EXPECT_TRUE(result["metadata"].isMember("telemetry"));
-  Json::Value telemetry_metadata = result["metadata"]["telemetry"];
-
-  EXPECT_EQ(telemetry_metadata["benchmarkDescriptions"].size(), 1u);
-  EXPECT_EQ(telemetry_metadata["benchmarkDescriptions"][0].asString(),
-            kDescription);
-
-  EXPECT_EQ(telemetry_metadata["benchmarks"].size(), 1u);
-  EXPECT_EQ(telemetry_metadata["benchmarks"][0].asString(), kBenchmarkName);
-
-  EXPECT_EQ(telemetry_metadata["stories"].size(), 1u);
-  EXPECT_EQ(telemetry_metadata["stories"][0].asString(), kStoryName);
-
-  EXPECT_EQ(telemetry_metadata["storyTags"].size(), 2u);
-  EXPECT_EQ(telemetry_metadata["storyTags"][0].asString(), kStoryTag1);
-  EXPECT_EQ(telemetry_metadata["storyTags"][1].asString(), kStoryTag2);
-
-  EXPECT_DOUBLE_EQ(telemetry_metadata["benchmarkStart"].asInt(),
-                   kBenchmarkStart / 1000.0);
-
-  EXPECT_DOUBLE_EQ(telemetry_metadata["traceStart"].asInt(),
-                   kStoryStart / 1000.0);
-
-  EXPECT_EQ(telemetry_metadata["hadFailures"].size(), 1u);
-  EXPECT_EQ(telemetry_metadata["hadFailures"][0].asBool(), kHadFailures);
-}
-
-TEST_F(ExportJsonTest, StorageWithStats) {
-  int64_t kProducers = 10;
-  int64_t kBufferSize0 = 1000;
-  int64_t kBufferSize1 = 2000;
-
-  context_.storage->SetStats(stats::traced_producers_connected, kProducers);
-  context_.storage->SetIndexedStats(stats::traced_buf_buffer_size, 0,
-                                    kBufferSize0);
-  context_.storage->SetIndexedStats(stats::traced_buf_buffer_size, 1,
-                                    kBufferSize1);
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-
-  EXPECT_TRUE(result.isMember("metadata"));
-  EXPECT_TRUE(result["metadata"].isMember("perfetto_trace_stats"));
-  Json::Value stats = result["metadata"]["perfetto_trace_stats"];
-
-  EXPECT_EQ(stats["producers_connected"].asInt(), kProducers);
-  EXPECT_EQ(stats["buffer_stats"].size(), 2u);
-  EXPECT_EQ(stats["buffer_stats"][0]["buffer_size"].asInt(), kBufferSize0);
-  EXPECT_EQ(stats["buffer_stats"][1]["buffer_size"].asInt(), kBufferSize1);
-}
-
-TEST_F(ExportJsonTest, StorageWithChromeMetadata) {
-  const char* kName1 = "name1";
-  const char* kName2 = "name2";
-  const char* kValue1 = "value1";
-  const int kValue2 = 222;
-
-  TraceStorage* storage = context_.storage.get();
-
-  RowId row_id = storage->mutable_raw_events()->AddRawEvent(
-      0, storage->InternString("chrome_event.metadata"), 0, 0);
-
-  StringId name1_id = storage->InternString(base::StringView(kName1));
-  StringId name2_id = storage->InternString(base::StringView(kName2));
-  StringId value1_id = storage->InternString(base::StringView(kValue1));
-  context_.args_tracker->AddArg(row_id, name1_id, name1_id,
-                                Variadic::String(value1_id));
-  context_.args_tracker->AddArg(row_id, name2_id, name2_id,
-                                Variadic::Integer(kValue2));
-  context_.args_tracker->Flush();
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(storage, output);
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-
-  EXPECT_TRUE(result.isMember("metadata"));
-  Json::Value metadata = result["metadata"];
-
-  EXPECT_EQ(metadata[kName1].asString(), kValue1);
-  EXPECT_EQ(metadata[kName2].asInt(), kValue2);
-}
-
-TEST_F(ExportJsonTest, StorageWithArgs) {
-  const char* kCategory = "cat";
-  const char* kName = "name";
-  const char* kSrc = "source_file.cc";
-
-  UniqueTid utid = context_.storage->AddEmptyThread(0);
-  TrackId track =
-      context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
-  context_.args_tracker->Flush();  // Flush track args.
-  StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
-  StringId name_id = context_.storage->InternString(base::StringView(kName));
-  context_.storage->mutable_nestable_slices()->AddSlice(
-      0, 0, track, utid, RefType::kRefUtid, cat_id, name_id, 0, 0, 0);
-
-  StringId arg_key_id = context_.storage->InternString(
-      base::StringView("task.posted_from.file_name"));
-  StringId arg_value_id =
-      context_.storage->InternString(base::StringView(kSrc));
-  TraceStorage::Args::Arg arg;
-  arg.flat_key = arg_key_id;
-  arg.key = arg_key_id;
-  arg.value = Variadic::String(arg_value_id);
-  ArgSetId args = context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
-  context_.storage->mutable_nestable_slices()->set_arg_set_id(0, args);
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 1u);
-
-  Json::Value event = result["traceEvents"][0];
-  EXPECT_EQ(event["cat"].asString(), kCategory);
-  EXPECT_EQ(event["name"].asString(), kName);
-  EXPECT_EQ(event["args"]["src"].asString(), kSrc);
-}
-
-TEST_F(ExportJsonTest, StorageWithSliceAndFlowEventArgs) {
-  const char* kCategory = "cat";
-  const char* kName = "name";
-  const uint64_t kBindId = 0xaa00aa00aa00aa00;
-  const char* kFlowDirection = "inout";
-  const char* kArgName = "arg_name";
-  const int kArgValue = 123;
-
-  TraceStorage* storage = context_.storage.get();
-
-  UniqueTid utid = storage->AddEmptyThread(0);
-  TrackId track =
-      context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
-  context_.args_tracker->Flush();  // Flush track args.
-  StringId cat_id = storage->InternString(base::StringView(kCategory));
-  StringId name_id = storage->InternString(base::StringView(kName));
-  RowId row_id = TraceStorage::CreateRowId(
-      kNestableSlices,
-      storage->mutable_nestable_slices()->AddSlice(
-          0, 0, track, utid, RefType::kRefUtid, cat_id, name_id, 0, 0, 0));
-
-  auto add_arg = [&](const char* key, Variadic value) {
-    StringId key_id = storage->InternString(key);
-    context_.args_tracker->AddArg(row_id, key_id, key_id, value);
-  };
-
-  add_arg("legacy_event.bind_id", Variadic::UnsignedInteger(kBindId));
-  add_arg("legacy_event.bind_to_enclosing", Variadic::Boolean(true));
-  StringId flow_direction_id = storage->InternString(kFlowDirection);
-  add_arg("legacy_event.flow_direction", Variadic::String(flow_direction_id));
-
-  add_arg(kArgName, Variadic::Integer(kArgValue));
-
-  context_.args_tracker->Flush();
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(storage, output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 1u);
-
-  Json::Value event = result["traceEvents"][0];
-  EXPECT_EQ(event["cat"].asString(), kCategory);
-  EXPECT_EQ(event["name"].asString(), kName);
-  EXPECT_EQ(event["bind_id"].asString(), "0xaa00aa00aa00aa00");
-  EXPECT_EQ(event["bp"].asString(), "e");
-  EXPECT_EQ(event["flow_in"].asBool(), true);
-  EXPECT_EQ(event["flow_out"].asBool(), true);
-  EXPECT_EQ(event["args"][kArgName].asInt(), kArgValue);
-  EXPECT_FALSE(event["args"].isMember("legacy_event"));
-}
-
-TEST_F(ExportJsonTest, StorageWithListArgs) {
-  const char* kCategory = "cat";
-  const char* kName = "name";
-  double kValues[] = {1.234, 2.345};
-
-  UniqueTid utid = context_.storage->AddEmptyThread(0);
-  TrackId track =
-      context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
-  context_.args_tracker->Flush();  // Flush track args.
-  StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
-  StringId name_id = context_.storage->InternString(base::StringView(kName));
-  context_.storage->mutable_nestable_slices()->AddSlice(
-      0, 0, track, utid, RefType::kRefUtid, cat_id, name_id, 0, 0, 0);
-
-  StringId arg_flat_key_id = context_.storage->InternString(
-      base::StringView("debug.draw_duration_ms"));
-  StringId arg_key0_id = context_.storage->InternString(
-      base::StringView("debug.draw_duration_ms[0]"));
-  StringId arg_key1_id = context_.storage->InternString(
-      base::StringView("debug.draw_duration_ms[1]"));
-  TraceStorage::Args::Arg arg0;
-  arg0.flat_key = arg_flat_key_id;
-  arg0.key = arg_key0_id;
-  arg0.value = Variadic::Real(kValues[0]);
-  TraceStorage::Args::Arg arg1;
-  arg1.flat_key = arg_flat_key_id;
-  arg1.key = arg_key1_id;
-  arg1.value = Variadic::Real(kValues[1]);
-  ArgSetId args =
-      context_.storage->mutable_args()->AddArgSet({arg0, arg1}, 0, 2);
-  context_.storage->mutable_nestable_slices()->set_arg_set_id(0, args);
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 1u);
-
-  Json::Value event = result["traceEvents"][0];
-  EXPECT_EQ(event["cat"].asString(), kCategory);
-  EXPECT_EQ(event["name"].asString(), kName);
-  EXPECT_EQ(event["args"]["draw_duration_ms"].size(), 2u);
-  EXPECT_DOUBLE_EQ(event["args"]["draw_duration_ms"][0].asDouble(), kValues[0]);
-  EXPECT_DOUBLE_EQ(event["args"]["draw_duration_ms"][1].asDouble(), kValues[1]);
-}
-
-TEST_F(ExportJsonTest, StorageWithMultiplePointerArgs) {
-  const char* kCategory = "cat";
-  const char* kName = "name";
-  uint64_t kValue0 = 1;
-  uint64_t kValue1 = std::numeric_limits<uint64_t>::max();
-
-  UniqueTid utid = context_.storage->AddEmptyThread(0);
-  TrackId track =
-      context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
-  context_.args_tracker->Flush();  // Flush track args.
-  StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
-  StringId name_id = context_.storage->InternString(base::StringView(kName));
-  context_.storage->mutable_nestable_slices()->AddSlice(
-      0, 0, track, utid, RefType::kRefUtid, cat_id, name_id, 0, 0, 0);
-
-  StringId arg_key0_id =
-      context_.storage->InternString(base::StringView("arg0"));
-  StringId arg_key1_id =
-      context_.storage->InternString(base::StringView("arg1"));
-  TraceStorage::Args::Arg arg0;
-  arg0.flat_key = arg_key0_id;
-  arg0.key = arg_key0_id;
-  arg0.value = Variadic::Pointer(kValue0);
-  TraceStorage::Args::Arg arg1;
-  arg1.flat_key = arg_key1_id;
-  arg1.key = arg_key1_id;
-  arg1.value = Variadic::Pointer(kValue1);
-  ArgSetId args =
-      context_.storage->mutable_args()->AddArgSet({arg0, arg1}, 0, 2);
-  context_.storage->mutable_nestable_slices()->set_arg_set_id(0, args);
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 1u);
-
-  Json::Value event = result["traceEvents"][0];
-  EXPECT_EQ(event["cat"].asString(), kCategory);
-  EXPECT_EQ(event["name"].asString(), kName);
-  EXPECT_EQ(event["args"]["arg0"].asString(), "0x1");
-  EXPECT_EQ(event["args"]["arg1"].asString(), "0xffffffffffffffff");
-}
-
-TEST_F(ExportJsonTest, StorageWithObjectListArgs) {
-  const char* kCategory = "cat";
-  const char* kName = "name";
-  int kValues[] = {123, 234};
-
-  UniqueTid utid = context_.storage->AddEmptyThread(0);
-  TrackId track =
-      context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
-  context_.args_tracker->Flush();  // Flush track args.
-  StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
-  StringId name_id = context_.storage->InternString(base::StringView(kName));
-  context_.storage->mutable_nestable_slices()->AddSlice(
-      0, 0, track, utid, RefType::kRefUtid, cat_id, name_id, 0, 0, 0);
-
-  StringId arg_flat_key_id =
-      context_.storage->InternString(base::StringView("a.b"));
-  StringId arg_key0_id =
-      context_.storage->InternString(base::StringView("a[0].b"));
-  StringId arg_key1_id =
-      context_.storage->InternString(base::StringView("a[1].b"));
-  TraceStorage::Args::Arg arg0;
-  arg0.flat_key = arg_flat_key_id;
-  arg0.key = arg_key0_id;
-  arg0.value = Variadic::Integer(kValues[0]);
-  TraceStorage::Args::Arg arg1;
-  arg1.flat_key = arg_flat_key_id;
-  arg1.key = arg_key1_id;
-  arg1.value = Variadic::Integer(kValues[1]);
-  ArgSetId args =
-      context_.storage->mutable_args()->AddArgSet({arg0, arg1}, 0, 2);
-  context_.storage->mutable_nestable_slices()->set_arg_set_id(0, args);
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 1u);
-
-  Json::Value event = result["traceEvents"][0];
-  EXPECT_EQ(event["cat"].asString(), kCategory);
-  EXPECT_EQ(event["name"].asString(), kName);
-  EXPECT_EQ(event["args"]["a"].size(), 2u);
-  EXPECT_EQ(event["args"]["a"][0]["b"].asInt(), kValues[0]);
-  EXPECT_EQ(event["args"]["a"][1]["b"].asInt(), kValues[1]);
-}
-
-TEST_F(ExportJsonTest, StorageWithNestedListArgs) {
-  const char* kCategory = "cat";
-  const char* kName = "name";
-  int kValues[] = {123, 234};
-
-  UniqueTid utid = context_.storage->AddEmptyThread(0);
-  TrackId track =
-      context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
-  context_.args_tracker->Flush();  // Flush track args.
-  StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
-  StringId name_id = context_.storage->InternString(base::StringView(kName));
-  context_.storage->mutable_nestable_slices()->AddSlice(
-      0, 0, track, utid, RefType::kRefUtid, cat_id, name_id, 0, 0, 0);
-
-  StringId arg_flat_key_id =
-      context_.storage->InternString(base::StringView("a"));
-  StringId arg_key0_id =
-      context_.storage->InternString(base::StringView("a[0][0]"));
-  StringId arg_key1_id =
-      context_.storage->InternString(base::StringView("a[0][1]"));
-  TraceStorage::Args::Arg arg0;
-  arg0.flat_key = arg_flat_key_id;
-  arg0.key = arg_key0_id;
-  arg0.value = Variadic::Integer(kValues[0]);
-  TraceStorage::Args::Arg arg1;
-  arg1.flat_key = arg_flat_key_id;
-  arg1.key = arg_key1_id;
-  arg1.value = Variadic::Integer(kValues[1]);
-  ArgSetId args =
-      context_.storage->mutable_args()->AddArgSet({arg0, arg1}, 0, 2);
-  context_.storage->mutable_nestable_slices()->set_arg_set_id(0, args);
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 1u);
-
-  Json::Value event = result["traceEvents"][0];
-  EXPECT_EQ(event["cat"].asString(), kCategory);
-  EXPECT_EQ(event["name"].asString(), kName);
-  EXPECT_EQ(event["args"]["a"].size(), 1u);
-  EXPECT_EQ(event["args"]["a"][0].size(), 2u);
-  EXPECT_EQ(event["args"]["a"][0][0].asInt(), kValues[0]);
-  EXPECT_EQ(event["args"]["a"][0][1].asInt(), kValues[1]);
-}
-
-TEST_F(ExportJsonTest, StorageWithLegacyJsonArgs) {
-  const char* kCategory = "cat";
-  const char* kName = "name";
-
-  UniqueTid utid = context_.storage->AddEmptyThread(0);
-  TrackId track =
-      context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
-  context_.args_tracker->Flush();  // Flush track args.
-  StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
-  StringId name_id = context_.storage->InternString(base::StringView(kName));
-  context_.storage->mutable_nestable_slices()->AddSlice(
-      0, 0, track, utid, RefType::kRefUtid, cat_id, name_id, 0, 0, 0);
-
-  StringId arg_key_id = context_.storage->InternString(base::StringView("a"));
-  StringId arg_value_id =
-      context_.storage->InternString(base::StringView("{\"b\":123}"));
-  TraceStorage::Args::Arg arg;
-  arg.flat_key = arg_key_id;
-  arg.key = arg_key_id;
-  arg.value = Variadic::Json(arg_value_id);
-  ArgSetId args = context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
-  context_.storage->mutable_nestable_slices()->set_arg_set_id(0, args);
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 1u);
-
-  Json::Value event = result["traceEvents"][0];
-  EXPECT_EQ(event["cat"].asString(), kCategory);
-  EXPECT_EQ(event["name"].asString(), kName);
-  EXPECT_EQ(event["args"]["a"]["b"].asInt(), 123);
-}
-
-TEST_F(ExportJsonTest, InstantEvent) {
-  const int64_t kTimestamp = 10000000;
-  const char* kCategory = "cat";
-  const char* kName = "name";
-
-  TrackId track =
-      context_.track_tracker->GetOrCreateLegacyChromeGlobalInstantTrack();
-  context_.args_tracker->Flush();  // Flush track args.
-  StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
-  StringId name_id = context_.storage->InternString(base::StringView(kName));
-  context_.storage->mutable_nestable_slices()->AddSlice(
-      kTimestamp, 0, track, 0, RefType::kRefNoRef, cat_id, name_id, 0, 0, 0);
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 1u);
-
-  Json::Value event = result["traceEvents"][0];
-  EXPECT_EQ(event["ph"].asString(), "I");
-  EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
-  EXPECT_EQ(event["s"].asString(), "g");
-  EXPECT_EQ(event["cat"].asString(), kCategory);
-  EXPECT_EQ(event["name"].asString(), kName);
-}
-
-TEST_F(ExportJsonTest, InstantEventOnThread) {
-  const int64_t kTimestamp = 10000000;
-  const int64_t kThreadID = 100;
-  const char* kCategory = "cat";
-  const char* kName = "name";
-
-  UniqueTid utid = context_.storage->AddEmptyThread(kThreadID);
-  TrackId track =
-      context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
-  context_.args_tracker->Flush();  // Flush track args.
-  StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
-  StringId name_id = context_.storage->InternString(base::StringView(kName));
-  context_.storage->mutable_nestable_slices()->AddSlice(
-      kTimestamp, 0, track, utid, RefType::kRefUtid, cat_id, name_id, 0, 0, 0);
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 1u);
-
-  Json::Value event = result["traceEvents"][0];
-  EXPECT_EQ(event["tid"].asUInt(), kThreadID);
-  EXPECT_EQ(event["ph"].asString(), "I");
-  EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
-  EXPECT_EQ(event["s"].asString(), "t");
-  EXPECT_EQ(event["cat"].asString(), kCategory);
-  EXPECT_EQ(event["name"].asString(), kName);
-}
-
-TEST_F(ExportJsonTest, AsyncEvent) {
-  const int64_t kTimestamp = 10000000;
-  const int64_t kDuration = 100000;
-  const int64_t kProcessID = 100;
-  const char* kCategory = "cat";
-  const char* kName = "name";
-  const char* kArgName = "arg_name";
-  const int kArgValue = 123;
-
-  UniquePid upid = context_.storage->AddEmptyProcess(kProcessID);
-  StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
-  StringId name_id = context_.storage->InternString(base::StringView(kName));
-
-  constexpr int64_t kSourceId = 235;
-  TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
-      name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
-      /*source_scope=*/0);
-  context_.args_tracker->Flush();  // Flush track args.
-
-  context_.storage->mutable_nestable_slices()->AddSlice(
-      kTimestamp, kDuration, track, track, RefType::kRefTrack, cat_id, name_id,
-      0, 0, 0);
-  StringId arg_key_id =
-      context_.storage->InternString(base::StringView(kArgName));
-  TraceStorage::Args::Arg arg;
-  arg.flat_key = arg_key_id;
-  arg.key = arg_key_id;
-  arg.value = Variadic::Integer(kArgValue);
-  ArgSetId args = context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
-  context_.storage->mutable_nestable_slices()->set_arg_set_id(0, args);
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 2u);
-
-  Json::Value begin_event = result["traceEvents"][0];
-  EXPECT_EQ(begin_event["ph"].asString(), "b");
-  EXPECT_EQ(begin_event["ts"].asInt64(), kTimestamp / 1000);
-  EXPECT_EQ(begin_event["pid"].asInt64(), kProcessID);
-  EXPECT_EQ(begin_event["id2"]["local"].asString(), "0xeb");
-  EXPECT_EQ(begin_event["cat"].asString(), kCategory);
-  EXPECT_EQ(begin_event["name"].asString(), kName);
-  EXPECT_EQ(begin_event["args"][kArgName].asInt(), kArgValue);
-  EXPECT_FALSE(begin_event.isMember("tts"));
-  EXPECT_FALSE(begin_event.isMember("use_async_tts"));
-
-  Json::Value end_event = result["traceEvents"][1];
-  EXPECT_EQ(end_event["ph"].asString(), "e");
-  EXPECT_EQ(end_event["ts"].asInt64(), (kTimestamp + kDuration) / 1000);
-  EXPECT_EQ(end_event["pid"].asInt64(), kProcessID);
-  EXPECT_EQ(end_event["id2"]["local"].asString(), "0xeb");
-  EXPECT_EQ(end_event["cat"].asString(), kCategory);
-  EXPECT_EQ(end_event["name"].asString(), kName);
-  EXPECT_TRUE(end_event["args"].isObject());
-  EXPECT_EQ(end_event["args"].size(), 0u);
-  EXPECT_FALSE(end_event.isMember("tts"));
-  EXPECT_FALSE(end_event.isMember("use_async_tts"));
-}
-
-TEST_F(ExportJsonTest, AsyncEventWithThreadTimestamp) {
-  const int64_t kTimestamp = 10000000;
-  const int64_t kDuration = 100000;
-  const int64_t kThreadTimestamp = 10000001;
-  const int64_t kThreadDuration = 99998;
-  const int64_t kProcessID = 100;
-  const char* kCategory = "cat";
-  const char* kName = "name";
-
-  UniquePid upid = context_.storage->AddEmptyProcess(kProcessID);
-  StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
-  StringId name_id = context_.storage->InternString(base::StringView(kName));
-
-  constexpr int64_t kSourceId = 235;
-  TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
-      name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
-      /*source_scope=*/0);
-  context_.args_tracker->Flush();  // Flush track args.
-
-  auto slice_id = context_.storage->mutable_nestable_slices()->AddSlice(
-      kTimestamp, kDuration, track, track, RefType::kRefTrack, cat_id, name_id,
-      0, 0, 0);
-  context_.storage->mutable_virtual_track_slices()->AddVirtualTrackSlice(
-      slice_id, kThreadTimestamp, kThreadDuration, 0, 0);
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 2u);
-
-  Json::Value begin_event = result["traceEvents"][0];
-  EXPECT_EQ(begin_event["ph"].asString(), "b");
-  EXPECT_EQ(begin_event["ts"].asInt64(), kTimestamp / 1000);
-  EXPECT_EQ(begin_event["tts"].asInt64(), kThreadTimestamp / 1000);
-  EXPECT_EQ(begin_event["use_async_tts"].asInt(), 1);
-  EXPECT_EQ(begin_event["pid"].asInt64(), kProcessID);
-  EXPECT_EQ(begin_event["id2"]["local"].asString(), "0xeb");
-  EXPECT_EQ(begin_event["cat"].asString(), kCategory);
-  EXPECT_EQ(begin_event["name"].asString(), kName);
-
-  Json::Value end_event = result["traceEvents"][1];
-  EXPECT_EQ(end_event["ph"].asString(), "e");
-  EXPECT_EQ(end_event["ts"].asInt64(), (kTimestamp + kDuration) / 1000);
-  EXPECT_EQ(end_event["tts"].asInt64(),
-            (kThreadTimestamp + kThreadDuration) / 1000);
-  EXPECT_EQ(end_event["use_async_tts"].asInt(), 1);
-  EXPECT_EQ(end_event["pid"].asInt64(), kProcessID);
-  EXPECT_EQ(end_event["id2"]["local"].asString(), "0xeb");
-  EXPECT_EQ(end_event["cat"].asString(), kCategory);
-  EXPECT_EQ(end_event["name"].asString(), kName);
-}
-
-TEST_F(ExportJsonTest, UnfinishedAsyncEvent) {
-  const int64_t kTimestamp = 10000000;
-  const int64_t kDuration = -1;
-  const int64_t kThreadTimestamp = 10000001;
-  const int64_t kThreadDuration = -1;
-  const int64_t kProcessID = 100;
-  const char* kCategory = "cat";
-  const char* kName = "name";
-
-  UniquePid upid = context_.storage->AddEmptyProcess(kProcessID);
-  StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
-  StringId name_id = context_.storage->InternString(base::StringView(kName));
-
-  constexpr int64_t kSourceId = 235;
-  TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
-      name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
-      /*source_scope=*/0);
-  context_.args_tracker->Flush();  // Flush track args.
-
-  auto slice_id = context_.storage->mutable_nestable_slices()->AddSlice(
-      kTimestamp, kDuration, track, track, RefType::kRefTrack, cat_id, name_id,
-      0, 0, 0);
-  context_.storage->mutable_virtual_track_slices()->AddVirtualTrackSlice(
-      slice_id, kThreadTimestamp, kThreadDuration, 0, 0);
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 1u);
-
-  Json::Value begin_event = result["traceEvents"][0];
-  EXPECT_EQ(begin_event["ph"].asString(), "b");
-  EXPECT_EQ(begin_event["ts"].asInt64(), kTimestamp / 1000);
-  EXPECT_EQ(begin_event["tts"].asInt64(), kThreadTimestamp / 1000);
-  EXPECT_EQ(begin_event["use_async_tts"].asInt(), 1);
-  EXPECT_EQ(begin_event["pid"].asInt64(), kProcessID);
-  EXPECT_EQ(begin_event["id2"]["local"].asString(), "0xeb");
-  EXPECT_EQ(begin_event["cat"].asString(), kCategory);
-  EXPECT_EQ(begin_event["name"].asString(), kName);
-}
-
-TEST_F(ExportJsonTest, AsyncInstantEvent) {
-  const int64_t kTimestamp = 10000000;
-  const int64_t kProcessID = 100;
-  const char* kCategory = "cat";
-  const char* kName = "name";
-  const char* kArgName = "arg_name";
-  const int kArgValue = 123;
-
-  UniquePid upid = context_.storage->AddEmptyProcess(kProcessID);
-  StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
-  StringId name_id = context_.storage->InternString(base::StringView(kName));
-
-  constexpr int64_t kSourceId = 235;
-  TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
-      name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
-      /*source_scope=*/0);
-  context_.args_tracker->Flush();  // Flush track args.
-
-  context_.storage->mutable_nestable_slices()->AddSlice(
-      kTimestamp, 0, track, track, RefType::kRefTrack, cat_id, name_id, 0, 0,
-      0);
-  StringId arg_key_id =
-      context_.storage->InternString(base::StringView("arg_name"));
-  TraceStorage::Args::Arg arg;
-  arg.flat_key = arg_key_id;
-  arg.key = arg_key_id;
-  arg.value = Variadic::Integer(kArgValue);
-  ArgSetId args = context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
-  context_.storage->mutable_nestable_slices()->set_arg_set_id(0, args);
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(context_.storage.get(), output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 1u);
-
-  Json::Value event = result["traceEvents"][0];
-  EXPECT_EQ(event["ph"].asString(), "n");
-  EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
-  EXPECT_EQ(event["pid"].asInt64(), kProcessID);
-  EXPECT_EQ(event["id2"]["local"].asString(), "0xeb");
-  EXPECT_EQ(event["cat"].asString(), kCategory);
-  EXPECT_EQ(event["name"].asString(), kName);
-  EXPECT_EQ(event["args"][kArgName].asInt(), kArgValue);
-}
-
-TEST_F(ExportJsonTest, RawEvent) {
-  const int64_t kTimestamp = 10000000;
-  const int64_t kDuration = 10000;
-  const int64_t kThreadTimestamp = 20000000;
-  const int64_t kThreadDuration = 20000;
-  const int64_t kThreadInstructionCount = 30000000;
-  const int64_t kThreadInstructionDelta = 30000;
-  const int64_t kProcessID = 100;
-  const int64_t kThreadID = 200;
-  const char* kCategory = "cat";
-  const char* kName = "name";
-  const char* kPhase = "?";
-  const uint64_t kGlobalId = 0xaaffaaffaaffaaff;
-  const char* kIdScope = "my_id";
-  const uint64_t kBindId = 0xaa00aa00aa00aa00;
-  const char* kFlowDirection = "inout";
-  const char* kArgName = "arg_name";
-  const int kArgValue = 123;
-
-  TraceStorage* storage = context_.storage.get();
-
-  UniquePid upid = storage->AddEmptyProcess(kProcessID);
-  UniqueTid utid = storage->AddEmptyThread(kThreadID);
-  storage->GetMutableThread(utid)->upid = upid;
-
-  RowId row_id = storage->mutable_raw_events()->AddRawEvent(
-      kTimestamp, storage->InternString("track_event.legacy_event"), /*cpu=*/0,
-      utid);
-
-  auto add_arg = [&](const char* key, Variadic value) {
-    StringId key_id = storage->InternString(key);
-    context_.args_tracker->AddArg(row_id, key_id, key_id, value);
-  };
-
-  StringId cat_id = storage->InternString(base::StringView(kCategory));
-  add_arg("legacy_event.category", Variadic::String(cat_id));
-  StringId name_id = storage->InternString(base::StringView(kName));
-  add_arg("legacy_event.name", Variadic::String(name_id));
-  StringId phase_id = storage->InternString(base::StringView(kPhase));
-  add_arg("legacy_event.phase", Variadic::String(phase_id));
-
-  add_arg("legacy_event.duration_ns", Variadic::Integer(kDuration));
-  add_arg("legacy_event.thread_timestamp_ns",
-          Variadic::Integer(kThreadTimestamp));
-  add_arg("legacy_event.thread_duration_ns",
-          Variadic::Integer(kThreadDuration));
-  add_arg("legacy_event.thread_instruction_count",
-          Variadic::Integer(kThreadInstructionCount));
-  add_arg("legacy_event.thread_instruction_delta",
-          Variadic::Integer(kThreadInstructionDelta));
-  add_arg("legacy_event.use_async_tts", Variadic::Boolean(true));
-  add_arg("legacy_event.global_id", Variadic::UnsignedInteger(kGlobalId));
-  StringId scope_id = storage->InternString(base::StringView(kIdScope));
-  add_arg("legacy_event.id_scope", Variadic::String(scope_id));
-  add_arg("legacy_event.bind_id", Variadic::UnsignedInteger(kBindId));
-  add_arg("legacy_event.bind_to_enclosing", Variadic::Boolean(true));
-  StringId flow_direction_id = storage->InternString(kFlowDirection);
-  add_arg("legacy_event.flow_direction", Variadic::String(flow_direction_id));
-
-  add_arg(kArgName, Variadic::Integer(kArgValue));
-
-  context_.args_tracker->Flush();
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(storage, output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-  EXPECT_EQ(result["traceEvents"].size(), 1u);
-
-  Json::Value event = result["traceEvents"][0];
-  EXPECT_EQ(event["ph"].asString(), kPhase);
-  EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
-  EXPECT_EQ(event["dur"].asInt64(), kDuration / 1000);
-  EXPECT_EQ(event["tts"].asInt64(), kThreadTimestamp / 1000);
-  EXPECT_EQ(event["tdur"].asInt64(), kThreadDuration / 1000);
-  EXPECT_EQ(event["ticount"].asInt64(), kThreadInstructionCount);
-  EXPECT_EQ(event["tidelta"].asInt64(), kThreadInstructionDelta);
-  EXPECT_EQ(event["tid"].asUInt(), kThreadID);
-  EXPECT_EQ(event["cat"].asString(), kCategory);
-  EXPECT_EQ(event["name"].asString(), kName);
-  EXPECT_EQ(event["use_async_tts"].asInt(), 1);
-  EXPECT_EQ(event["id2"]["global"].asString(), "0xaaffaaffaaffaaff");
-  EXPECT_EQ(event["scope"].asString(), kIdScope);
-  EXPECT_EQ(event["bind_id"].asString(), "0xaa00aa00aa00aa00");
-  EXPECT_EQ(event["bp"].asString(), "e");
-  EXPECT_EQ(event["flow_in"].asBool(), true);
-  EXPECT_EQ(event["flow_out"].asBool(), true);
-  EXPECT_EQ(event["args"][kArgName].asInt(), kArgValue);
-}
-
-TEST_F(ExportJsonTest, LegacyRawEvents) {
-  const char* kLegacyFtraceData = "some \"data\"\nsome :data:";
-  const char* kLegacyJsonData1 = "{\"us";
-  const char* kLegacyJsonData2 = "er\": 1},{\"user\": 2}";
-
-  TraceStorage* storage = context_.storage.get();
-
-  RowId row_id = storage->mutable_raw_events()->AddRawEvent(
-      0, storage->InternString("chrome_event.legacy_system_trace"), 0, 0);
-
-  StringId data_id = storage->InternString("data");
-  StringId ftrace_data_id = storage->InternString(kLegacyFtraceData);
-  context_.args_tracker->AddArg(row_id, data_id, data_id,
-                                Variadic::String(ftrace_data_id));
-
-  row_id = storage->mutable_raw_events()->AddRawEvent(
-      0, storage->InternString("chrome_event.legacy_user_trace"), 0, 0);
-  StringId json_data1_id = storage->InternString(kLegacyJsonData1);
-  context_.args_tracker->AddArg(row_id, data_id, data_id,
-                                Variadic::String(json_data1_id));
-
-  row_id = storage->mutable_raw_events()->AddRawEvent(
-      0, storage->InternString("chrome_event.legacy_user_trace"), 0, 0);
-  StringId json_data2_id = storage->InternString(kLegacyJsonData2);
-  context_.args_tracker->AddArg(row_id, data_id, data_id,
-                                Variadic::String(json_data2_id));
-
-  context_.args_tracker->Flush();
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(storage, output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-
-  EXPECT_EQ(result["traceEvents"].size(), 2u);
-  EXPECT_EQ(result["traceEvents"][0]["user"].asInt(), 1);
-  EXPECT_EQ(result["traceEvents"][1]["user"].asInt(), 2);
-  EXPECT_EQ(result["systemTraceEvents"].asString(), kLegacyFtraceData);
-}
-
-TEST_F(ExportJsonTest, CpuProfileEvent) {
-  const int64_t kProcessID = 100;
-  const int64_t kThreadID = 200;
-  const int64_t kTimestamp = 10000000;
-
-  TraceStorage* storage = context_.storage.get();
-
-  UniquePid upid = storage->AddEmptyProcess(kProcessID);
-  UniqueTid utid = storage->AddEmptyThread(kThreadID);
-  storage->GetMutableThread(utid)->upid = upid;
-
-  uint32_t module_row_id_1 = storage->mutable_stack_profile_mappings()->Insert(
-      {storage->InternString("foo_module_id"), 0, 0, 0, 0, 0,
-       storage->InternString("foo_module_name")});
-
-  uint32_t module_row_id_2 = storage->mutable_stack_profile_mappings()->Insert(
-      {storage->InternString("bar_module_id"), 0, 0, 0, 0, 0,
-       storage->InternString("bar_module_name")});
-
-  // TODO(140860736): Once we support null values for
-  // stack_profile_frame.symbol_set_id remove this hack
-  storage->mutable_symbol_table()->Insert({0, 0, 0, 0});
-
-  uint32_t frame_row_id_1 = storage->mutable_stack_profile_frames()->Insert(
-      {/*name_id=*/0, module_row_id_1, 0x42});
-  uint32_t symbol_set_id = storage->symbol_table().size();
-  storage->mutable_symbol_table()->Insert(
-      {symbol_set_id, storage->InternString("foo_func"),
-       storage->InternString("foo_file"), 66});
-  storage->mutable_stack_profile_frames()->SetSymbolSetId(
-      static_cast<size_t>(frame_row_id_1), symbol_set_id);
-
-  uint32_t frame_row_id_2 = storage->mutable_stack_profile_frames()->Insert(
-      {/*name_id=*/0, module_row_id_2, 0x4242});
-  symbol_set_id = storage->symbol_table().size();
-  storage->mutable_symbol_table()->Insert(
-      {symbol_set_id, storage->InternString("bar_func"),
-       storage->InternString("bar_file"), 77});
-  storage->mutable_stack_profile_frames()->SetSymbolSetId(
-      static_cast<size_t>(frame_row_id_2), symbol_set_id);
-
-  uint32_t frame_callsite_id_1 =
-      storage->mutable_stack_profile_callsite_table()->Insert(
-          {0, -1, frame_row_id_1});
-
-  uint32_t frame_callsite_id_2 =
-      storage->mutable_stack_profile_callsite_table()->Insert(
-          {1, frame_callsite_id_1, frame_row_id_2});
-
-  storage->mutable_cpu_profile_stack_samples()->Insert(
-      {kTimestamp, frame_callsite_id_2, utid});
-
-  base::TempFile temp_file = base::TempFile::Create();
-  FILE* output = fopen(temp_file.path().c_str(), "w+");
-  util::Status status = ExportJson(storage, output);
-
-  EXPECT_TRUE(status.ok());
-
-  Json::Value result = ToJsonValue(ReadFile(output));
-
-  EXPECT_EQ(result["traceEvents"].size(), 1u);
-  Json::Value event = result["traceEvents"][0];
-  EXPECT_EQ(event["ph"].asString(), "I");
-  EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
-  EXPECT_EQ(event["tid"].asUInt(), kThreadID);
-  EXPECT_EQ(event["cat"].asString(), "disabled_by_default-cpu_profiler");
-  EXPECT_EQ(event["name"].asString(), "StackCpuSampling");
-  EXPECT_EQ(event["s"].asString(), "t");
-  EXPECT_EQ(event["args"]["frames"].asString(),
-            "foo_func - foo_module_name [foo_module_id]\nbar_func - "
-            "bar_module_name [bar_module_id]\n");
-}
-
-TEST_F(ExportJsonTest, ArgumentFilter) {
-  UniqueTid utid = context_.storage->AddEmptyThread(0);
-  TrackId track =
-      context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
-  context_.args_tracker->Flush();  // Flush track args.
-
-  StringId cat_id = context_.storage->InternString(base::StringView("cat"));
-  std::array<StringId, 3> name_ids{
-      context_.storage->InternString(base::StringView("name1")),
-      context_.storage->InternString(base::StringView("name2")),
-      context_.storage->InternString(base::StringView("name3"))};
-  StringId arg1_id = context_.storage->InternString(base::StringView("arg1"));
-  StringId arg2_id = context_.storage->InternString(base::StringView("arg2"));
-  StringId val_id = context_.storage->InternString(base::StringView("val"));
-
-  std::array<RowId, 3> slice_ids;
-  for (size_t i = 0; i < name_ids.size(); i++) {
-    slice_ids[i] = TraceStorage::CreateRowId(
-        kNestableSlices, context_.storage->mutable_nestable_slices()->AddSlice(
-                             0, 0, track, utid, RefType::kRefUtid, cat_id,
-                             name_ids[i], 0, 0, 0));
-  }
-
-  for (RowId row : slice_ids) {
-    context_.args_tracker->AddArg(row, arg1_id, arg1_id, Variadic::Integer(5));
-    context_.args_tracker->AddArg(row, arg2_id, arg2_id,
-                                  Variadic::String(val_id));
-  }
-  context_.args_tracker->Flush();
-
-  auto arg_filter = [](const char* category_group_name, const char* event_name,
-                       ArgumentNameFilterPredicate* arg_name_filter) {
-    EXPECT_TRUE(strcmp(category_group_name, "cat") == 0);
-    if (strcmp(event_name, "name1") == 0) {
-      // Filter all args for name1.
-      return false;
-    } else if (strcmp(event_name, "name2") == 0) {
-      // Filter only the second arg for name2.
-      *arg_name_filter = [](const char* arg_name) {
-        if (strcmp(arg_name, "arg1") == 0) {
-          return true;
-        }
-        EXPECT_TRUE(strcmp(arg_name, "arg2") == 0);
-        return false;
-      };
-      return true;
-    }
-    // Filter no args for name3.
-    EXPECT_TRUE(strcmp(event_name, "name3") == 0);
-    return true;
-  };
-
-  Json::Value result = ToJsonValue(ToJson(arg_filter));
-
-  EXPECT_EQ(result["traceEvents"].size(), 3u);
-
-  EXPECT_EQ(result["traceEvents"][0]["cat"].asString(), "cat");
-  EXPECT_EQ(result["traceEvents"][0]["name"].asString(), "name1");
-  EXPECT_EQ(result["traceEvents"][0]["args"].asString(), "__stripped__");
-
-  EXPECT_EQ(result["traceEvents"][1]["cat"].asString(), "cat");
-  EXPECT_EQ(result["traceEvents"][1]["name"].asString(), "name2");
-  EXPECT_EQ(result["traceEvents"][1]["args"]["arg1"].asInt(), 5);
-  EXPECT_EQ(result["traceEvents"][1]["args"]["arg2"].asString(),
-            "__stripped__");
-
-  EXPECT_EQ(result["traceEvents"][2]["cat"].asString(), "cat");
-  EXPECT_EQ(result["traceEvents"][2]["name"].asString(), "name3");
-  EXPECT_EQ(result["traceEvents"][2]["args"]["arg1"].asInt(), 5);
-  EXPECT_EQ(result["traceEvents"][2]["args"]["arg2"].asString(), "val");
-}
-
-TEST_F(ExportJsonTest, MetadataFilter) {
-  const char* kName1 = "name1";
-  const char* kName2 = "name2";
-  const char* kValue1 = "value1";
-  const int kValue2 = 222;
-
-  TraceStorage* storage = context_.storage.get();
-
-  RowId row_id = storage->mutable_raw_events()->AddRawEvent(
-      0, storage->InternString("chrome_event.metadata"), 0, 0);
-
-  StringId name1_id = storage->InternString(base::StringView(kName1));
-  StringId name2_id = storage->InternString(base::StringView(kName2));
-  StringId value1_id = storage->InternString(base::StringView(kValue1));
-  context_.args_tracker->AddArg(row_id, name1_id, name1_id,
-                                Variadic::String(value1_id));
-  context_.args_tracker->AddArg(row_id, name2_id, name2_id,
-                                Variadic::Integer(kValue2));
-  context_.args_tracker->Flush();
-
-  auto metadata_filter = [](const char* metadata_name) {
-    // Only allow name1.
-    return strcmp(metadata_name, "name1") == 0;
-  };
-
-  Json::Value result = ToJsonValue(ToJson(nullptr, metadata_filter));
-
-  EXPECT_TRUE(result.isMember("metadata"));
-  Json::Value metadata = result["metadata"];
-
-  EXPECT_EQ(metadata[kName1].asString(), kValue1);
-  EXPECT_EQ(metadata[kName2].asString(), "__stripped__");
-}
-
-TEST_F(ExportJsonTest, LabelFilter) {
-  const int64_t kTimestamp1 = 10000000;
-  const int64_t kTimestamp2 = 20000000;
-  const int64_t kDuration = 10000;
-  const int64_t kThreadID = 100;
-  const char* kCategory = "cat";
-  const char* kName = "name";
-
-  UniqueTid utid = context_.storage->AddEmptyThread(kThreadID);
-  TrackId track =
-      context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
-  context_.args_tracker->Flush();  // Flush track args.
-  StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
-  StringId name_id = context_.storage->InternString(base::StringView(kName));
-
-  context_.storage->mutable_nestable_slices()->AddSlice(
-      kTimestamp1, kDuration, track, utid, RefType::kRefUtid, cat_id, name_id,
-      0, 0, 0);
-  context_.storage->mutable_nestable_slices()->AddSlice(
-      kTimestamp2, kDuration, track, utid, RefType::kRefUtid, cat_id, name_id,
-      0, 0, 0);
-
-  auto label_filter = [](const char* label_name) {
-    return strcmp(label_name, "traceEvents") == 0;
-  };
-
-  Json::Value result =
-      ToJsonValue("[" + ToJson(nullptr, nullptr, label_filter) + "]");
-
-  EXPECT_TRUE(result.isArray());
-  EXPECT_EQ(result.size(), 2u);
-
-  EXPECT_EQ(result[0]["ph"].asString(), "X");
-  EXPECT_EQ(result[0]["ts"].asInt64(), kTimestamp1 / 1000);
-  EXPECT_EQ(result[0]["dur"].asInt64(), kDuration / 1000);
-  EXPECT_EQ(result[0]["tid"].asUInt(), kThreadID);
-  EXPECT_EQ(result[0]["cat"].asString(), kCategory);
-  EXPECT_EQ(result[0]["name"].asString(), kName);
-  EXPECT_EQ(result[1]["ph"].asString(), "X");
-  EXPECT_EQ(result[1]["ts"].asInt64(), kTimestamp2 / 1000);
-  EXPECT_EQ(result[1]["dur"].asInt64(), kDuration / 1000);
-  EXPECT_EQ(result[1]["tid"].asUInt(), kThreadID);
-  EXPECT_EQ(result[1]["cat"].asString(), kCategory);
-  EXPECT_EQ(result[1]["name"].asString(), kName);
-}
-
-}  // namespace
-}  // namespace json
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/filtered_row_index.cc b/src/trace_processor/filtered_row_index.cc
index 48c5d3c..f0dbbdf 100644
--- a/src/trace_processor/filtered_row_index.cc
+++ b/src/trace_processor/filtered_row_index.cc
@@ -16,7 +16,6 @@
 
 #include "src/trace_processor/filtered_row_index.h"
 
-#include <stddef.h>
 #include <numeric>
 
 namespace perfetto {
diff --git a/src/trace_processor/filtered_row_index.h b/src/trace_processor/filtered_row_index.h
index c17fc56..d8dcaeb 100644
--- a/src/trace_processor/filtered_row_index.h
+++ b/src/trace_processor/filtered_row_index.h
@@ -122,14 +122,16 @@
 
   template <typename Predicate>
   void FilterRowVector(Predicate fn) {
-    size_t write_idx = 0;
-    for (size_t read_idx = 0; read_idx < rows_.size(); ++read_idx) {
-      uint32_t row = rows_[read_idx];
-      if (fn(row)) {
-        rows_[write_idx++] = row;
+    size_t rows_size = rows_.size();
+    for (size_t i = 0; i < rows_size;) {
+      if (fn(rows_[i])) {
+        i++;
+      } else {
+        std::swap(rows_[i], rows_[rows_size - 1]);
+        rows_size--;
       }
     }
-    rows_.resize(write_idx);
+    rows_.resize(rows_size);
   }
 
   void ConvertBitVectorToRowVector();
diff --git a/src/trace_processor/filtered_row_index_unittest.cc b/src/trace_processor/filtered_row_index_unittest.cc
index 6810097..2a32a3f 100644
--- a/src/trace_processor/filtered_row_index_unittest.cc
+++ b/src/trace_processor/filtered_row_index_unittest.cc
@@ -16,7 +16,8 @@
 
 #include "src/trace_processor/filtered_row_index.h"
 
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace trace_processor {
diff --git a/src/trace_processor/forwarding_trace_parser.cc b/src/trace_processor/forwarding_trace_parser.cc
deleted file mode 100644
index 81de5d1..0000000
--- a/src/trace_processor/forwarding_trace_parser.cc
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/forwarding_trace_parser.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "src/trace_processor/gzip_trace_parser.h"
-#include "src/trace_processor/importers/proto/proto_trace_parser.h"
-#include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
-#include "src/trace_processor/importers/systrace/systrace_trace_parser.h"
-#include "src/trace_processor/trace_sorter.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FUCHSIA)
-#include "src/trace_processor/importers/fuchsia/fuchsia_trace_parser.h"
-#include "src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h"
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FUCHSIA)
-
-// JSON parsing and exporting is only supported in the standalone and
-// Chromium builds.
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON_IMPORT)
-#include "src/trace_processor/importers/json/json_trace_parser.h"
-#include "src/trace_processor/importers/json/json_trace_tokenizer.h"
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON_IMPORT)
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-std::string RemoveWhitespace(const std::string& input) {
-  std::string str(input);
-  str.erase(std::remove_if(str.begin(), str.end(), ::isspace), str.end());
-  return str;
-}
-
-// Fuchsia traces have a magic number as documented here:
-// https://fuchsia.googlesource.com/fuchsia/+/HEAD/docs/development/tracing/trace-format/README.md#magic-number-record-trace-info-type-0
-constexpr uint64_t kFuchsiaMagicNumber = 0x0016547846040010;
-
-}  // namespace
-
-ForwardingTraceParser::ForwardingTraceParser(TraceProcessorContext* context)
-    : context_(context) {}
-
-ForwardingTraceParser::~ForwardingTraceParser() {}
-
-util::Status ForwardingTraceParser::Parse(std::unique_ptr<uint8_t[]> data,
-                                          size_t size) {
-  // If this is the first Parse() call, guess the trace type and create the
-  // appropriate parser.
-
-  if (!reader_) {
-    TraceType trace_type;
-    {
-      auto scoped_trace = context_->storage->TraceExecutionTimeIntoStats(
-          stats::guess_trace_type_duration_ns);
-      trace_type = GuessTraceType(data.get(), size);
-    }
-    switch (trace_type) {
-      case kJsonTraceType: {
-        PERFETTO_DLOG("JSON trace detected");
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON_IMPORT)
-        reader_.reset(new JsonTraceTokenizer(context_));
-        // JSON traces have no guarantees about the order of events in them.
-        int64_t window_size_ns = std::numeric_limits<int64_t>::max();
-        context_->sorter.reset(new TraceSorter(context_, window_size_ns));
-        context_->parser.reset(new JsonTraceParser(context_));
-#else   // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON_IMPORT)
-        PERFETTO_FATAL("JSON traces not supported.");
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON_IMPORT)
-        break;
-      }
-      case kProtoTraceType: {
-        PERFETTO_DLOG("Proto trace detected");
-        // This will be reduced once we read the trace config and we see flush
-        // period being set.
-        int64_t window_size_ns = std::numeric_limits<int64_t>::max();
-        reader_.reset(new ProtoTraceTokenizer(context_));
-        context_->sorter.reset(new TraceSorter(context_, window_size_ns));
-        context_->parser.reset(new ProtoTraceParser(context_));
-        break;
-      }
-      case kFuchsiaTraceType: {
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FUCHSIA)
-        PERFETTO_DLOG("Fuchsia trace detected");
-        // Fuschia traces can have massively out of order events.
-        int64_t window_size_ns = std::numeric_limits<int64_t>::max();
-        reader_.reset(new FuchsiaTraceTokenizer(context_));
-        context_->sorter.reset(new TraceSorter(context_, window_size_ns));
-        context_->parser.reset(new FuchsiaTraceParser(context_));
-#else   // PERFETTO_BUILDFLAG(PERFETTO_TP_FUCHSIA)
-        PERFETTO_FATAL("Fuchsia traces not supported.");
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FUCHSIA)
-        break;
-      }
-      case kSystraceTraceType:
-        PERFETTO_DLOG("Systrace trace detected");
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-        reader_.reset(new SystraceTraceParser(context_));
-        break;
-#else   // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-        return util::ErrStatus("Systrace support is disabled");
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-      case kGzipTraceType:
-        PERFETTO_DLOG("gzip trace detected");
-        reader_.reset(new GzipTraceParser(context_));
-        break;
-      case kCtraceTraceType:
-        PERFETTO_DLOG("ctrace trace detected");
-        reader_.reset(new GzipTraceParser(context_));
-        break;
-      case kUnknownTraceType:
-        return util::ErrStatus("Unknown trace type provided");
-    }
-  }
-
-  return reader_->Parse(std::move(data), size);
-}
-
-TraceType GuessTraceType(const uint8_t* data, size_t size) {
-  if (size == 0)
-    return kUnknownTraceType;
-  std::string start(reinterpret_cast<const char*>(data),
-                    std::min<size_t>(size, 20));
-  std::string start_minus_white_space = RemoveWhitespace(start);
-  if (base::StartsWith(start_minus_white_space, "{\"traceEvents\":["))
-    return kJsonTraceType;
-  if (base::StartsWith(start_minus_white_space, "[{"))
-    return kJsonTraceType;
-  if (size >= 8) {
-    uint64_t first_word = *reinterpret_cast<const uint64_t*>(data);
-    if (first_word == kFuchsiaMagicNumber)
-      return kFuchsiaTraceType;
-  }
-
-  // Systrace with header but no leading HTML.
-  if (base::StartsWith(start, "# tracer"))
-    return kSystraceTraceType;
-
-  // Systrace with leading HTML.
-  if (base::StartsWith(start, "<!DOCTYPE html>") ||
-      base::StartsWith(start, "<html>"))
-    return kSystraceTraceType;
-
-  // Ctrace is deflate'ed systrace.
-  if (start.find("TRACE:") != std::string::npos)
-    return kCtraceTraceType;
-
-  // Systrace with no header or leading HTML.
-  if (base::StartsWith(start, " "))
-    return kSystraceTraceType;
-
-  // gzip'ed trace containing one of the other formats.
-  if (base::StartsWith(start, "\x1f\x8b"))
-    return kGzipTraceType;
-
-  return kProtoTraceType;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/forwarding_trace_parser.h b/src/trace_processor/forwarding_trace_parser.h
deleted file mode 100644
index f7216b3..0000000
--- a/src/trace_processor/forwarding_trace_parser.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_FORWARDING_TRACE_PARSER_H_
-#define SRC_TRACE_PROCESSOR_FORWARDING_TRACE_PARSER_H_
-
-#include "src/trace_processor/chunked_trace_reader.h"
-
-#include "src/trace_processor/trace_processor_context.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-enum TraceType {
-  kUnknownTraceType,
-  kProtoTraceType,
-  kJsonTraceType,
-  kFuchsiaTraceType,
-  kSystraceTraceType,
-  kGzipTraceType,
-  kCtraceTraceType,
-};
-
-TraceType GuessTraceType(const uint8_t* data, size_t size);
-
-class ForwardingTraceParser : public ChunkedTraceReader {
- public:
-  explicit ForwardingTraceParser(TraceProcessorContext*);
-  ~ForwardingTraceParser() override;
-
-  // ChunkedTraceReader implementation
-  util::Status Parse(std::unique_ptr<uint8_t[]>, size_t) override;
-
- private:
-  TraceProcessorContext* const context_;
-  std::unique_ptr<ChunkedTraceReader> reader_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_FORWARDING_TRACE_PARSER_H_
diff --git a/src/trace_processor/forwarding_trace_parser_unittest.cc b/src/trace_processor/forwarding_trace_parser_unittest.cc
deleted file mode 100644
index 0d6877c..0000000
--- a/src/trace_processor/forwarding_trace_parser_unittest.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.
- */
-
-#include "src/trace_processor/forwarding_trace_parser.h"
-
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-TEST(TraceProcessorImplTest, GuessTraceType_Empty) {
-  const uint8_t prefix[] = "";
-  EXPECT_EQ(kUnknownTraceType, GuessTraceType(prefix, 0));
-}
-
-TEST(TraceProcessorImplTest, GuessTraceType_Json) {
-  const uint8_t prefix[] = "{\"traceEvents\":[";
-  EXPECT_EQ(kJsonTraceType, GuessTraceType(prefix, sizeof(prefix)));
-}
-
-TEST(TraceProcessorImplTest, GuessTraceType_JsonWithSpaces) {
-  const uint8_t prefix[] = "\n{ \"traceEvents\": [";
-  EXPECT_EQ(kJsonTraceType, GuessTraceType(prefix, sizeof(prefix)));
-}
-
-TEST(TraceProcessorImplTest, GuessTraceType_JsonMissingTraceEvents) {
-  const uint8_t prefix[] = "[{";
-  EXPECT_EQ(kJsonTraceType, GuessTraceType(prefix, sizeof(prefix)));
-}
-
-TEST(TraceProcessorImplTest, GuessTraceType_Proto) {
-  const uint8_t prefix[] = {0x0a, 0x00};  // An empty TracePacket.
-  EXPECT_EQ(kProtoTraceType, GuessTraceType(prefix, sizeof(prefix)));
-}
-
-TEST(TraceProcessorImplTest, GuessTraceType_Fuchsia) {
-  const uint8_t prefix[] = {0x10, 0x00, 0x04, 0x46, 0x78, 0x54, 0x16, 0x00};
-  EXPECT_EQ(kFuchsiaTraceType, GuessTraceType(prefix, sizeof(prefix)));
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/ftrace_descriptors.cc b/src/trace_processor/ftrace_descriptors.cc
new file mode 100644
index 0000000..90b9661
--- /dev/null
+++ b/src/trace_processor/ftrace_descriptors.cc
@@ -0,0 +1,3544 @@
+// Autogenerated by:
+// ../../tools/ftrace_proto_gen/ftrace_descriptor_gen.cc
+// Do not edit.
+
+#include "src/trace_processor/ftrace_descriptors.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+std::array<MessageDescriptor, 332> descriptors{{
+    {nullptr, 0, {}},
+    {nullptr, 0, {}},
+    {nullptr, 0, {}},
+    {
+        "print",
+        2,
+        {
+            {},
+            {"ip", ProtoSchemaType::kUint64},
+            {"buf", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "sched_switch",
+        7,
+        {
+            {},
+            {"prev_comm", ProtoSchemaType::kString},
+            {"prev_pid", ProtoSchemaType::kInt32},
+            {"prev_prio", ProtoSchemaType::kInt32},
+            {"prev_state", ProtoSchemaType::kInt64},
+            {"next_comm", ProtoSchemaType::kString},
+            {"next_pid", ProtoSchemaType::kInt32},
+            {"next_prio", ProtoSchemaType::kInt32},
+        },
+    },
+    {nullptr, 0, {}},
+    {nullptr, 0, {}},
+    {nullptr, 0, {}},
+    {nullptr, 0, {}},
+    {nullptr, 0, {}},
+    {nullptr, 0, {}},
+    {
+        "cpu_frequency",
+        2,
+        {
+            {},
+            {"state", ProtoSchemaType::kUint32},
+            {"cpu_id", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "cpu_frequency_limits",
+        3,
+        {
+            {},
+            {"min_freq", ProtoSchemaType::kUint32},
+            {"max_freq", ProtoSchemaType::kUint32},
+            {"cpu_id", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "cpu_idle",
+        2,
+        {
+            {},
+            {"state", ProtoSchemaType::kUint32},
+            {"cpu_id", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "clock_enable",
+        3,
+        {
+            {},
+            {"name", ProtoSchemaType::kString},
+            {"state", ProtoSchemaType::kUint64},
+            {"cpu_id", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "clock_disable",
+        3,
+        {
+            {},
+            {"name", ProtoSchemaType::kString},
+            {"state", ProtoSchemaType::kUint64},
+            {"cpu_id", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "clock_set_rate",
+        3,
+        {
+            {},
+            {"name", ProtoSchemaType::kString},
+            {"state", ProtoSchemaType::kUint64},
+            {"cpu_id", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "sched_wakeup",
+        5,
+        {
+            {},
+            {"comm", ProtoSchemaType::kString},
+            {"pid", ProtoSchemaType::kInt32},
+            {"prio", ProtoSchemaType::kInt32},
+            {"success", ProtoSchemaType::kInt32},
+            {"target_cpu", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "sched_blocked_reason",
+        3,
+        {
+            {},
+            {"pid", ProtoSchemaType::kInt32},
+            {"caller", ProtoSchemaType::kUint64},
+            {"io_wait", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "sched_cpu_hotplug",
+        3,
+        {
+            {},
+            {"affected_cpu", ProtoSchemaType::kInt32},
+            {"error", ProtoSchemaType::kInt32},
+            {"status", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "sched_waking",
+        5,
+        {
+            {},
+            {"comm", ProtoSchemaType::kString},
+            {"pid", ProtoSchemaType::kInt32},
+            {"prio", ProtoSchemaType::kInt32},
+            {"success", ProtoSchemaType::kInt32},
+            {"target_cpu", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ipi_entry",
+        1,
+        {
+            {},
+            {"reason", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "ipi_exit",
+        1,
+        {
+            {},
+            {"reason", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "ipi_raise",
+        2,
+        {
+            {},
+            {"target_cpus", ProtoSchemaType::kUint32},
+            {"reason", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "softirq_entry",
+        1,
+        {
+            {},
+            {"vec", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "softirq_exit",
+        1,
+        {
+            {},
+            {"vec", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "softirq_raise",
+        1,
+        {
+            {},
+            {"vec", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "i2c_read",
+        5,
+        {
+            {},
+            {"adapter_nr", ProtoSchemaType::kInt32},
+            {"msg_nr", ProtoSchemaType::kUint32},
+            {"addr", ProtoSchemaType::kUint32},
+            {"flags", ProtoSchemaType::kUint32},
+            {"len", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "i2c_write",
+        6,
+        {
+            {},
+            {"adapter_nr", ProtoSchemaType::kInt32},
+            {"msg_nr", ProtoSchemaType::kUint32},
+            {"addr", ProtoSchemaType::kUint32},
+            {"flags", ProtoSchemaType::kUint32},
+            {"len", ProtoSchemaType::kUint32},
+            {"buf", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "i2c_result",
+        3,
+        {
+            {},
+            {"adapter_nr", ProtoSchemaType::kInt32},
+            {"nr_msgs", ProtoSchemaType::kUint32},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "i2c_reply",
+        6,
+        {
+            {},
+            {"adapter_nr", ProtoSchemaType::kInt32},
+            {"msg_nr", ProtoSchemaType::kUint32},
+            {"addr", ProtoSchemaType::kUint32},
+            {"flags", ProtoSchemaType::kUint32},
+            {"len", ProtoSchemaType::kUint32},
+            {"buf", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "smbus_read",
+        5,
+        {
+            {},
+            {"adapter_nr", ProtoSchemaType::kInt32},
+            {"flags", ProtoSchemaType::kUint32},
+            {"addr", ProtoSchemaType::kUint32},
+            {"command", ProtoSchemaType::kUint32},
+            {"protocol", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "smbus_write",
+        6,
+        {
+            {},
+            {"adapter_nr", ProtoSchemaType::kInt32},
+            {"addr", ProtoSchemaType::kUint32},
+            {"flags", ProtoSchemaType::kUint32},
+            {"command", ProtoSchemaType::kUint32},
+            {"len", ProtoSchemaType::kUint32},
+            {"protocol", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "smbus_result",
+        7,
+        {
+            {},
+            {"adapter_nr", ProtoSchemaType::kInt32},
+            {"addr", ProtoSchemaType::kUint32},
+            {"flags", ProtoSchemaType::kUint32},
+            {"read_write", ProtoSchemaType::kUint32},
+            {"command", ProtoSchemaType::kUint32},
+            {"res", ProtoSchemaType::kInt32},
+            {"protocol", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "smbus_reply",
+        6,
+        {
+            {},
+            {"adapter_nr", ProtoSchemaType::kInt32},
+            {"addr", ProtoSchemaType::kUint32},
+            {"flags", ProtoSchemaType::kUint32},
+            {"command", ProtoSchemaType::kUint32},
+            {"len", ProtoSchemaType::kUint32},
+            {"protocol", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "lowmemory_kill",
+        5,
+        {
+            {},
+            {"comm", ProtoSchemaType::kString},
+            {"pid", ProtoSchemaType::kInt32},
+            {"pagecache_size", ProtoSchemaType::kInt64},
+            {"pagecache_limit", ProtoSchemaType::kInt64},
+            {"free", ProtoSchemaType::kInt64},
+        },
+    },
+    {
+        "irq_handler_entry",
+        3,
+        {
+            {},
+            {"irq", ProtoSchemaType::kInt32},
+            {"name", ProtoSchemaType::kString},
+            {"handler", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "irq_handler_exit",
+        2,
+        {
+            {},
+            {"irq", ProtoSchemaType::kInt32},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "sync_pt",
+        2,
+        {
+            {},
+            {"timeline", ProtoSchemaType::kString},
+            {"value", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "sync_timeline",
+        2,
+        {
+            {},
+            {"name", ProtoSchemaType::kString},
+            {"value", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "sync_wait",
+        3,
+        {
+            {},
+            {"name", ProtoSchemaType::kString},
+            {"status", ProtoSchemaType::kInt32},
+            {"begin", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_da_write_begin",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pos", ProtoSchemaType::kInt64},
+            {"len", ProtoSchemaType::kUint32},
+            {"flags", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_da_write_end",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pos", ProtoSchemaType::kInt64},
+            {"len", ProtoSchemaType::kUint32},
+            {"copied", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_sync_file_enter",
+        4,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"parent", ProtoSchemaType::kUint64},
+            {"datasync", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_sync_file_exit",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "block_rq_issue",
+        7,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"sector", ProtoSchemaType::kUint64},
+            {"nr_sector", ProtoSchemaType::kUint32},
+            {"bytes", ProtoSchemaType::kUint32},
+            {"rwbs", ProtoSchemaType::kString},
+            {"comm", ProtoSchemaType::kString},
+            {"cmd", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "mm_vmscan_direct_reclaim_begin",
+        3,
+        {
+            {},
+            {"order", ProtoSchemaType::kInt32},
+            {"may_writepage", ProtoSchemaType::kInt32},
+            {"gfp_flags", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "mm_vmscan_direct_reclaim_end",
+        1,
+        {
+            {},
+            {"nr_reclaimed", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "mm_vmscan_kswapd_wake",
+        2,
+        {
+            {},
+            {"nid", ProtoSchemaType::kInt32},
+            {"order", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "mm_vmscan_kswapd_sleep",
+        1,
+        {
+            {},
+            {"nid", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "binder_transaction",
+        7,
+        {
+            {},
+            {"debug_id", ProtoSchemaType::kInt32},
+            {"target_node", ProtoSchemaType::kInt32},
+            {"to_proc", ProtoSchemaType::kInt32},
+            {"to_thread", ProtoSchemaType::kInt32},
+            {"reply", ProtoSchemaType::kInt32},
+            {"code", ProtoSchemaType::kUint32},
+            {"flags", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "binder_transaction_received",
+        1,
+        {
+            {},
+            {"debug_id", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "binder_set_priority",
+        5,
+        {
+            {},
+            {"proc", ProtoSchemaType::kInt32},
+            {"thread", ProtoSchemaType::kInt32},
+            {"old_prio", ProtoSchemaType::kUint32},
+            {"new_prio", ProtoSchemaType::kUint32},
+            {"desired_prio", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "binder_lock",
+        1,
+        {
+            {},
+            {"tag", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "binder_locked",
+        1,
+        {
+            {},
+            {"tag", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "binder_unlock",
+        1,
+        {
+            {},
+            {"tag", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "workqueue_activate_work",
+        1,
+        {
+            {},
+            {"work", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "workqueue_execute_end",
+        1,
+        {
+            {},
+            {"work", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "workqueue_execute_start",
+        2,
+        {
+            {},
+            {"work", ProtoSchemaType::kUint64},
+            {"function", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "workqueue_queue_work",
+        5,
+        {
+            {},
+            {"work", ProtoSchemaType::kUint64},
+            {"function", ProtoSchemaType::kUint64},
+            {"workqueue", ProtoSchemaType::kUint64},
+            {"req_cpu", ProtoSchemaType::kUint32},
+            {"cpu", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "regulator_disable",
+        1,
+        {
+            {},
+            {"name", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "regulator_disable_complete",
+        1,
+        {
+            {},
+            {"name", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "regulator_enable",
+        1,
+        {
+            {},
+            {"name", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "regulator_enable_complete",
+        1,
+        {
+            {},
+            {"name", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "regulator_enable_delay",
+        1,
+        {
+            {},
+            {"name", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "regulator_set_voltage",
+        3,
+        {
+            {},
+            {"name", ProtoSchemaType::kString},
+            {"min", ProtoSchemaType::kInt32},
+            {"max", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "regulator_set_voltage_complete",
+        2,
+        {
+            {},
+            {"name", ProtoSchemaType::kString},
+            {"val", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "cgroup_attach_task",
+        5,
+        {
+            {},
+            {"dst_root", ProtoSchemaType::kInt32},
+            {"dst_id", ProtoSchemaType::kInt32},
+            {"pid", ProtoSchemaType::kInt32},
+            {"comm", ProtoSchemaType::kString},
+            {"cname", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "cgroup_mkdir",
+        3,
+        {
+            {},
+            {"root", ProtoSchemaType::kInt32},
+            {"id", ProtoSchemaType::kInt32},
+            {"cname", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "cgroup_remount",
+        3,
+        {
+            {},
+            {"root", ProtoSchemaType::kInt32},
+            {"ss_mask", ProtoSchemaType::kUint32},
+            {"name", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "cgroup_rmdir",
+        3,
+        {
+            {},
+            {"root", ProtoSchemaType::kInt32},
+            {"id", ProtoSchemaType::kInt32},
+            {"cname", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "cgroup_transfer_tasks",
+        5,
+        {
+            {},
+            {"dst_root", ProtoSchemaType::kInt32},
+            {"dst_id", ProtoSchemaType::kInt32},
+            {"pid", ProtoSchemaType::kInt32},
+            {"comm", ProtoSchemaType::kString},
+            {"cname", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "cgroup_destroy_root",
+        3,
+        {
+            {},
+            {"root", ProtoSchemaType::kInt32},
+            {"ss_mask", ProtoSchemaType::kUint32},
+            {"name", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "cgroup_release",
+        3,
+        {
+            {},
+            {"root", ProtoSchemaType::kInt32},
+            {"id", ProtoSchemaType::kInt32},
+            {"cname", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "cgroup_rename",
+        3,
+        {
+            {},
+            {"root", ProtoSchemaType::kInt32},
+            {"id", ProtoSchemaType::kInt32},
+            {"cname", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "cgroup_setup_root",
+        3,
+        {
+            {},
+            {"root", ProtoSchemaType::kInt32},
+            {"ss_mask", ProtoSchemaType::kUint32},
+            {"name", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "mdp_cmd_kickoff",
+        2,
+        {
+            {},
+            {"ctl_num", ProtoSchemaType::kUint32},
+            {"kickoff_cnt", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "mdp_commit",
+        4,
+        {
+            {},
+            {"num", ProtoSchemaType::kUint32},
+            {"play_cnt", ProtoSchemaType::kUint32},
+            {"clk_rate", ProtoSchemaType::kUint32},
+            {"bandwidth", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "mdp_perf_set_ot",
+        4,
+        {
+            {},
+            {"pnum", ProtoSchemaType::kUint32},
+            {"xin_id", ProtoSchemaType::kUint32},
+            {"rd_lim", ProtoSchemaType::kUint32},
+            {"is_vbif_rt", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "mdp_sspp_change",
+        16,
+        {
+            {},
+            {"num", ProtoSchemaType::kUint32},
+            {"play_cnt", ProtoSchemaType::kUint32},
+            {"mixer", ProtoSchemaType::kUint32},
+            {"stage", ProtoSchemaType::kUint32},
+            {"flags", ProtoSchemaType::kUint32},
+            {"format", ProtoSchemaType::kUint32},
+            {"img_w", ProtoSchemaType::kUint32},
+            {"img_h", ProtoSchemaType::kUint32},
+            {"src_x", ProtoSchemaType::kUint32},
+            {"src_y", ProtoSchemaType::kUint32},
+            {"src_w", ProtoSchemaType::kUint32},
+            {"src_h", ProtoSchemaType::kUint32},
+            {"dst_x", ProtoSchemaType::kUint32},
+            {"dst_y", ProtoSchemaType::kUint32},
+            {"dst_w", ProtoSchemaType::kUint32},
+            {"dst_h", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "tracing_mark_write",
+        3,
+        {
+            {},
+            {"pid", ProtoSchemaType::kInt32},
+            {"trace_name", ProtoSchemaType::kString},
+            {"trace_begin", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "mdp_cmd_pingpong_done",
+        4,
+        {
+            {},
+            {"ctl_num", ProtoSchemaType::kUint32},
+            {"intf_num", ProtoSchemaType::kUint32},
+            {"pp_num", ProtoSchemaType::kUint32},
+            {"koff_cnt", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "mdp_compare_bw",
+        8,
+        {
+            {},
+            {"new_ab", ProtoSchemaType::kUint64},
+            {"new_ib", ProtoSchemaType::kUint64},
+            {"new_wb", ProtoSchemaType::kUint64},
+            {"old_ab", ProtoSchemaType::kUint64},
+            {"old_ib", ProtoSchemaType::kUint64},
+            {"old_wb", ProtoSchemaType::kUint64},
+            {"params_changed", ProtoSchemaType::kUint32},
+            {"update_bw", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "mdp_perf_set_panic_luts",
+        5,
+        {
+            {},
+            {"pnum", ProtoSchemaType::kUint32},
+            {"fmt", ProtoSchemaType::kUint32},
+            {"mode", ProtoSchemaType::kUint32},
+            {"panic_lut", ProtoSchemaType::kUint32},
+            {"robust_lut", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "mdp_sspp_set",
+        16,
+        {
+            {},
+            {"num", ProtoSchemaType::kUint32},
+            {"play_cnt", ProtoSchemaType::kUint32},
+            {"mixer", ProtoSchemaType::kUint32},
+            {"stage", ProtoSchemaType::kUint32},
+            {"flags", ProtoSchemaType::kUint32},
+            {"format", ProtoSchemaType::kUint32},
+            {"img_w", ProtoSchemaType::kUint32},
+            {"img_h", ProtoSchemaType::kUint32},
+            {"src_x", ProtoSchemaType::kUint32},
+            {"src_y", ProtoSchemaType::kUint32},
+            {"src_w", ProtoSchemaType::kUint32},
+            {"src_h", ProtoSchemaType::kUint32},
+            {"dst_x", ProtoSchemaType::kUint32},
+            {"dst_y", ProtoSchemaType::kUint32},
+            {"dst_w", ProtoSchemaType::kUint32},
+            {"dst_h", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "mdp_cmd_readptr_done",
+        2,
+        {
+            {},
+            {"ctl_num", ProtoSchemaType::kUint32},
+            {"koff_cnt", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "mdp_misr_crc",
+        3,
+        {
+            {},
+            {"block_id", ProtoSchemaType::kUint32},
+            {"vsync_cnt", ProtoSchemaType::kUint32},
+            {"crc", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "mdp_perf_set_qos_luts",
+        7,
+        {
+            {},
+            {"pnum", ProtoSchemaType::kUint32},
+            {"fmt", ProtoSchemaType::kUint32},
+            {"intf", ProtoSchemaType::kUint32},
+            {"rot", ProtoSchemaType::kUint32},
+            {"fl", ProtoSchemaType::kUint32},
+            {"lut", ProtoSchemaType::kUint32},
+            {"linear", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "mdp_trace_counter",
+        3,
+        {
+            {},
+            {"pid", ProtoSchemaType::kInt32},
+            {"counter_name", ProtoSchemaType::kString},
+            {"value", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "mdp_cmd_release_bw",
+        1,
+        {
+            {},
+            {"ctl_num", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "mdp_mixer_update",
+        1,
+        {
+            {},
+            {"mixer_num", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "mdp_perf_set_wm_levels",
+        8,
+        {
+            {},
+            {"pnum", ProtoSchemaType::kUint32},
+            {"use_space", ProtoSchemaType::kUint32},
+            {"priority_bytes", ProtoSchemaType::kUint32},
+            {"wm0", ProtoSchemaType::kUint32},
+            {"wm1", ProtoSchemaType::kUint32},
+            {"wm2", ProtoSchemaType::kUint32},
+            {"mb_cnt", ProtoSchemaType::kUint32},
+            {"mb_size", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "mdp_video_underrun_done",
+        2,
+        {
+            {},
+            {"ctl_num", ProtoSchemaType::kUint32},
+            {"underrun_cnt", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "mdp_cmd_wait_pingpong",
+        2,
+        {
+            {},
+            {"ctl_num", ProtoSchemaType::kUint32},
+            {"kickoff_cnt", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "mdp_perf_prefill_calc",
+        10,
+        {
+            {},
+            {"pnum", ProtoSchemaType::kUint32},
+            {"latency_buf", ProtoSchemaType::kUint32},
+            {"ot", ProtoSchemaType::kUint32},
+            {"y_buf", ProtoSchemaType::kUint32},
+            {"y_scaler", ProtoSchemaType::kUint32},
+            {"pp_lines", ProtoSchemaType::kUint32},
+            {"pp_bytes", ProtoSchemaType::kUint32},
+            {"post_sc", ProtoSchemaType::kUint32},
+            {"fbc_bytes", ProtoSchemaType::kUint32},
+            {"prefill_bytes", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "mdp_perf_update_bus",
+        3,
+        {
+            {},
+            {"client", ProtoSchemaType::kInt32},
+            {"ab_quota", ProtoSchemaType::kUint64},
+            {"ib_quota", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "rotator_bw_ao_as_context",
+        1,
+        {
+            {},
+            {"state", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "mm_filemap_add_to_page_cache",
+        5,
+        {
+            {},
+            {"pfn", ProtoSchemaType::kUint64},
+            {"i_ino", ProtoSchemaType::kUint64},
+            {"index", ProtoSchemaType::kUint64},
+            {"s_dev", ProtoSchemaType::kUint64},
+            {"page", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "mm_filemap_delete_from_page_cache",
+        5,
+        {
+            {},
+            {"pfn", ProtoSchemaType::kUint64},
+            {"i_ino", ProtoSchemaType::kUint64},
+            {"index", ProtoSchemaType::kUint64},
+            {"s_dev", ProtoSchemaType::kUint64},
+            {"page", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "mm_compaction_begin",
+        5,
+        {
+            {},
+            {"zone_start", ProtoSchemaType::kUint64},
+            {"migrate_pfn", ProtoSchemaType::kUint64},
+            {"free_pfn", ProtoSchemaType::kUint64},
+            {"zone_end", ProtoSchemaType::kUint64},
+            {"sync", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "mm_compaction_defer_compaction",
+        6,
+        {
+            {},
+            {"nid", ProtoSchemaType::kInt32},
+            {"idx", ProtoSchemaType::kUint32},
+            {"order", ProtoSchemaType::kInt32},
+            {"considered", ProtoSchemaType::kUint32},
+            {"defer_shift", ProtoSchemaType::kUint32},
+            {"order_failed", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "mm_compaction_deferred",
+        6,
+        {
+            {},
+            {"nid", ProtoSchemaType::kInt32},
+            {"idx", ProtoSchemaType::kUint32},
+            {"order", ProtoSchemaType::kInt32},
+            {"considered", ProtoSchemaType::kUint32},
+            {"defer_shift", ProtoSchemaType::kUint32},
+            {"order_failed", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "mm_compaction_defer_reset",
+        6,
+        {
+            {},
+            {"nid", ProtoSchemaType::kInt32},
+            {"idx", ProtoSchemaType::kUint32},
+            {"order", ProtoSchemaType::kInt32},
+            {"considered", ProtoSchemaType::kUint32},
+            {"defer_shift", ProtoSchemaType::kUint32},
+            {"order_failed", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "mm_compaction_end",
+        6,
+        {
+            {},
+            {"zone_start", ProtoSchemaType::kUint64},
+            {"migrate_pfn", ProtoSchemaType::kUint64},
+            {"free_pfn", ProtoSchemaType::kUint64},
+            {"zone_end", ProtoSchemaType::kUint64},
+            {"sync", ProtoSchemaType::kUint32},
+            {"status", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "mm_compaction_finished",
+        4,
+        {
+            {},
+            {"nid", ProtoSchemaType::kInt32},
+            {"idx", ProtoSchemaType::kUint32},
+            {"order", ProtoSchemaType::kInt32},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "mm_compaction_isolate_freepages",
+        4,
+        {
+            {},
+            {"start_pfn", ProtoSchemaType::kUint64},
+            {"end_pfn", ProtoSchemaType::kUint64},
+            {"nr_scanned", ProtoSchemaType::kUint64},
+            {"nr_taken", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "mm_compaction_isolate_migratepages",
+        4,
+        {
+            {},
+            {"start_pfn", ProtoSchemaType::kUint64},
+            {"end_pfn", ProtoSchemaType::kUint64},
+            {"nr_scanned", ProtoSchemaType::kUint64},
+            {"nr_taken", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "mm_compaction_kcompactd_sleep",
+        1,
+        {
+            {},
+            {"nid", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "mm_compaction_kcompactd_wake",
+        3,
+        {
+            {},
+            {"nid", ProtoSchemaType::kInt32},
+            {"order", ProtoSchemaType::kInt32},
+            {"classzone_idx", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "mm_compaction_migratepages",
+        2,
+        {
+            {},
+            {"nr_migrated", ProtoSchemaType::kUint64},
+            {"nr_failed", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "mm_compaction_suitable",
+        4,
+        {
+            {},
+            {"nid", ProtoSchemaType::kInt32},
+            {"idx", ProtoSchemaType::kUint32},
+            {"order", ProtoSchemaType::kInt32},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "mm_compaction_try_to_compact_pages",
+        3,
+        {
+            {},
+            {"order", ProtoSchemaType::kInt32},
+            {"gfp_mask", ProtoSchemaType::kUint32},
+            {"mode", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "mm_compaction_wakeup_kcompactd",
+        3,
+        {
+            {},
+            {"nid", ProtoSchemaType::kInt32},
+            {"order", ProtoSchemaType::kInt32},
+            {"classzone_idx", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "suspend_resume",
+        3,
+        {
+            {},
+            {"action", ProtoSchemaType::kString},
+            {"val", ProtoSchemaType::kInt32},
+            {"start", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "sched_wakeup_new",
+        5,
+        {
+            {},
+            {"comm", ProtoSchemaType::kString},
+            {"pid", ProtoSchemaType::kInt32},
+            {"prio", ProtoSchemaType::kInt32},
+            {"success", ProtoSchemaType::kInt32},
+            {"target_cpu", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "block_bio_backmerge",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"sector", ProtoSchemaType::kUint64},
+            {"nr_sector", ProtoSchemaType::kUint32},
+            {"rwbs", ProtoSchemaType::kString},
+            {"comm", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "block_bio_bounce",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"sector", ProtoSchemaType::kUint64},
+            {"nr_sector", ProtoSchemaType::kUint32},
+            {"rwbs", ProtoSchemaType::kString},
+            {"comm", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "block_bio_complete",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"sector", ProtoSchemaType::kUint64},
+            {"nr_sector", ProtoSchemaType::kUint32},
+            {"error", ProtoSchemaType::kInt32},
+            {"rwbs", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "block_bio_frontmerge",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"sector", ProtoSchemaType::kUint64},
+            {"nr_sector", ProtoSchemaType::kUint32},
+            {"rwbs", ProtoSchemaType::kString},
+            {"comm", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "block_bio_queue",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"sector", ProtoSchemaType::kUint64},
+            {"nr_sector", ProtoSchemaType::kUint32},
+            {"rwbs", ProtoSchemaType::kString},
+            {"comm", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "block_bio_remap",
+        6,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"sector", ProtoSchemaType::kUint64},
+            {"nr_sector", ProtoSchemaType::kUint32},
+            {"old_dev", ProtoSchemaType::kUint64},
+            {"old_sector", ProtoSchemaType::kUint64},
+            {"rwbs", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "block_dirty_buffer",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"sector", ProtoSchemaType::kUint64},
+            {"size", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "block_getrq",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"sector", ProtoSchemaType::kUint64},
+            {"nr_sector", ProtoSchemaType::kUint32},
+            {"rwbs", ProtoSchemaType::kString},
+            {"comm", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "block_plug",
+        1,
+        {
+            {},
+            {"comm", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "block_rq_abort",
+        6,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"sector", ProtoSchemaType::kUint64},
+            {"nr_sector", ProtoSchemaType::kUint32},
+            {"errors", ProtoSchemaType::kInt32},
+            {"rwbs", ProtoSchemaType::kString},
+            {"cmd", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "block_rq_complete",
+        6,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"sector", ProtoSchemaType::kUint64},
+            {"nr_sector", ProtoSchemaType::kUint32},
+            {"errors", ProtoSchemaType::kInt32},
+            {"rwbs", ProtoSchemaType::kString},
+            {"cmd", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "block_rq_insert",
+        7,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"sector", ProtoSchemaType::kUint64},
+            {"nr_sector", ProtoSchemaType::kUint32},
+            {"bytes", ProtoSchemaType::kUint32},
+            {"rwbs", ProtoSchemaType::kString},
+            {"comm", ProtoSchemaType::kString},
+            {"cmd", ProtoSchemaType::kString},
+        },
+    },
+    {nullptr, 0, {}},
+    {
+        "block_rq_remap",
+        7,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"sector", ProtoSchemaType::kUint64},
+            {"nr_sector", ProtoSchemaType::kUint32},
+            {"old_dev", ProtoSchemaType::kUint64},
+            {"old_sector", ProtoSchemaType::kUint64},
+            {"nr_bios", ProtoSchemaType::kUint32},
+            {"rwbs", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "block_rq_requeue",
+        6,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"sector", ProtoSchemaType::kUint64},
+            {"nr_sector", ProtoSchemaType::kUint32},
+            {"errors", ProtoSchemaType::kInt32},
+            {"rwbs", ProtoSchemaType::kString},
+            {"cmd", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "block_sleeprq",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"sector", ProtoSchemaType::kUint64},
+            {"nr_sector", ProtoSchemaType::kUint32},
+            {"rwbs", ProtoSchemaType::kString},
+            {"comm", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "block_split",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"sector", ProtoSchemaType::kUint64},
+            {"new_sector", ProtoSchemaType::kUint64},
+            {"rwbs", ProtoSchemaType::kString},
+            {"comm", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "block_touch_buffer",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"sector", ProtoSchemaType::kUint64},
+            {"size", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "block_unplug",
+        2,
+        {
+            {},
+            {"nr_rq", ProtoSchemaType::kInt32},
+            {"comm", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "ext4_alloc_da_blocks",
+        4,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"data_blocks", ProtoSchemaType::kUint32},
+            {"meta_blocks", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_allocate_blocks",
+        11,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"block", ProtoSchemaType::kUint64},
+            {"len", ProtoSchemaType::kUint32},
+            {"logical", ProtoSchemaType::kUint32},
+            {"lleft", ProtoSchemaType::kUint32},
+            {"lright", ProtoSchemaType::kUint32},
+            {"goal", ProtoSchemaType::kUint64},
+            {"pleft", ProtoSchemaType::kUint64},
+            {"pright", ProtoSchemaType::kUint64},
+            {"flags", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_allocate_inode",
+        4,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"dir", ProtoSchemaType::kUint64},
+            {"mode", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_begin_ordered_truncate",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"new_size", ProtoSchemaType::kInt64},
+        },
+    },
+    {
+        "ext4_collapse_range",
+        4,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"offset", ProtoSchemaType::kInt64},
+            {"len", ProtoSchemaType::kInt64},
+        },
+    },
+    {
+        "ext4_da_release_space",
+        8,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"i_blocks", ProtoSchemaType::kUint64},
+            {"freed_blocks", ProtoSchemaType::kInt32},
+            {"reserved_data_blocks", ProtoSchemaType::kInt32},
+            {"reserved_meta_blocks", ProtoSchemaType::kInt32},
+            {"allocated_meta_blocks", ProtoSchemaType::kInt32},
+            {"mode", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_da_reserve_space",
+        7,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"i_blocks", ProtoSchemaType::kUint64},
+            {"reserved_data_blocks", ProtoSchemaType::kInt32},
+            {"reserved_meta_blocks", ProtoSchemaType::kInt32},
+            {"mode", ProtoSchemaType::kUint32},
+            {"md_needed", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_da_update_reserve_space",
+        9,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"i_blocks", ProtoSchemaType::kUint64},
+            {"used_blocks", ProtoSchemaType::kInt32},
+            {"reserved_data_blocks", ProtoSchemaType::kInt32},
+            {"reserved_meta_blocks", ProtoSchemaType::kInt32},
+            {"allocated_meta_blocks", ProtoSchemaType::kInt32},
+            {"quota_claim", ProtoSchemaType::kInt32},
+            {"mode", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_da_write_pages",
+        10,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"first_page", ProtoSchemaType::kUint64},
+            {"nr_to_write", ProtoSchemaType::kInt64},
+            {"sync_mode", ProtoSchemaType::kInt32},
+            {"b_blocknr", ProtoSchemaType::kUint64},
+            {"b_size", ProtoSchemaType::kUint32},
+            {"b_state", ProtoSchemaType::kUint32},
+            {"io_done", ProtoSchemaType::kInt32},
+            {"pages_written", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_da_write_pages_extent",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"lblk", ProtoSchemaType::kUint64},
+            {"len", ProtoSchemaType::kUint32},
+            {"flags", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_direct_IO_enter",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pos", ProtoSchemaType::kInt64},
+            {"len", ProtoSchemaType::kUint64},
+            {"rw", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_direct_IO_exit",
+        6,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pos", ProtoSchemaType::kInt64},
+            {"len", ProtoSchemaType::kUint64},
+            {"rw", ProtoSchemaType::kInt32},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_discard_blocks",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"blk", ProtoSchemaType::kUint64},
+            {"count", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ext4_discard_preallocations",
+        2,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ext4_drop_inode",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"drop", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_es_cache_extent",
+        6,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"lblk", ProtoSchemaType::kUint32},
+            {"len", ProtoSchemaType::kUint32},
+            {"pblk", ProtoSchemaType::kUint64},
+            {"status", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_es_find_delayed_extent_range_enter",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"lblk", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_es_find_delayed_extent_range_exit",
+        6,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"lblk", ProtoSchemaType::kUint32},
+            {"len", ProtoSchemaType::kUint32},
+            {"pblk", ProtoSchemaType::kUint64},
+            {"status", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ext4_es_insert_extent",
+        6,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"lblk", ProtoSchemaType::kUint32},
+            {"len", ProtoSchemaType::kUint32},
+            {"pblk", ProtoSchemaType::kUint64},
+            {"status", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ext4_es_lookup_extent_enter",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"lblk", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_es_lookup_extent_exit",
+        7,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"lblk", ProtoSchemaType::kUint32},
+            {"len", ProtoSchemaType::kUint32},
+            {"pblk", ProtoSchemaType::kUint64},
+            {"status", ProtoSchemaType::kUint64},
+            {"found", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_es_remove_extent",
+        4,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"lblk", ProtoSchemaType::kInt64},
+            {"len", ProtoSchemaType::kInt64},
+        },
+    },
+    {
+        "ext4_es_shrink",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"nr_shrunk", ProtoSchemaType::kInt32},
+            {"scan_time", ProtoSchemaType::kUint64},
+            {"nr_skipped", ProtoSchemaType::kInt32},
+            {"retried", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_es_shrink_count",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"nr_to_scan", ProtoSchemaType::kInt32},
+            {"cache_cnt", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_es_shrink_scan_enter",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"nr_to_scan", ProtoSchemaType::kInt32},
+            {"cache_cnt", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_es_shrink_scan_exit",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"nr_shrunk", ProtoSchemaType::kInt32},
+            {"cache_cnt", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_evict_inode",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"nlink", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_ext_convert_to_initialized_enter",
+        7,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"m_lblk", ProtoSchemaType::kUint32},
+            {"m_len", ProtoSchemaType::kUint32},
+            {"u_lblk", ProtoSchemaType::kUint32},
+            {"u_len", ProtoSchemaType::kUint32},
+            {"u_pblk", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ext4_ext_convert_to_initialized_fastpath",
+        10,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"m_lblk", ProtoSchemaType::kUint32},
+            {"m_len", ProtoSchemaType::kUint32},
+            {"u_lblk", ProtoSchemaType::kUint32},
+            {"u_len", ProtoSchemaType::kUint32},
+            {"u_pblk", ProtoSchemaType::kUint64},
+            {"i_lblk", ProtoSchemaType::kUint32},
+            {"i_len", ProtoSchemaType::kUint32},
+            {"i_pblk", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ext4_ext_handle_unwritten_extents",
+        8,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"flags", ProtoSchemaType::kInt32},
+            {"lblk", ProtoSchemaType::kUint32},
+            {"pblk", ProtoSchemaType::kUint64},
+            {"len", ProtoSchemaType::kUint32},
+            {"allocated", ProtoSchemaType::kUint32},
+            {"newblk", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ext4_ext_in_cache",
+        4,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"lblk", ProtoSchemaType::kUint32},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_ext_load_extent",
+        4,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pblk", ProtoSchemaType::kUint64},
+            {"lblk", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_ext_map_blocks_enter",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"lblk", ProtoSchemaType::kUint32},
+            {"len", ProtoSchemaType::kUint32},
+            {"flags", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_ext_map_blocks_exit",
+        8,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"flags", ProtoSchemaType::kUint32},
+            {"pblk", ProtoSchemaType::kUint64},
+            {"lblk", ProtoSchemaType::kUint32},
+            {"len", ProtoSchemaType::kUint32},
+            {"mflags", ProtoSchemaType::kUint32},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_ext_put_in_cache",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"lblk", ProtoSchemaType::kUint32},
+            {"len", ProtoSchemaType::kUint32},
+            {"start", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ext4_ext_remove_space",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"start", ProtoSchemaType::kUint32},
+            {"end", ProtoSchemaType::kUint32},
+            {"depth", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_ext_remove_space_done",
+        7,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"start", ProtoSchemaType::kUint32},
+            {"end", ProtoSchemaType::kUint32},
+            {"depth", ProtoSchemaType::kInt32},
+            {"partial", ProtoSchemaType::kInt64},
+            {"eh_entries", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_ext_rm_idx",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pblk", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ext4_ext_rm_leaf",
+        7,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"partial", ProtoSchemaType::kInt64},
+            {"start", ProtoSchemaType::kUint32},
+            {"ee_lblk", ProtoSchemaType::kUint32},
+            {"ee_pblk", ProtoSchemaType::kUint64},
+            {"ee_len", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_ext_show_extent",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pblk", ProtoSchemaType::kUint64},
+            {"lblk", ProtoSchemaType::kUint32},
+            {"len", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_fallocate_enter",
+        6,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"offset", ProtoSchemaType::kInt64},
+            {"len", ProtoSchemaType::kInt64},
+            {"mode", ProtoSchemaType::kInt32},
+            {"pos", ProtoSchemaType::kInt64},
+        },
+    },
+    {
+        "ext4_fallocate_exit",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pos", ProtoSchemaType::kInt64},
+            {"blocks", ProtoSchemaType::kUint32},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_find_delalloc_range",
+        7,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"from", ProtoSchemaType::kUint32},
+            {"to", ProtoSchemaType::kUint32},
+            {"reverse", ProtoSchemaType::kInt32},
+            {"found", ProtoSchemaType::kInt32},
+            {"found_blk", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_forget",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"block", ProtoSchemaType::kUint64},
+            {"is_metadata", ProtoSchemaType::kInt32},
+            {"mode", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_free_blocks",
+        6,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"block", ProtoSchemaType::kUint64},
+            {"count", ProtoSchemaType::kUint64},
+            {"flags", ProtoSchemaType::kInt32},
+            {"mode", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_free_inode",
+        6,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"uid", ProtoSchemaType::kUint32},
+            {"gid", ProtoSchemaType::kUint32},
+            {"blocks", ProtoSchemaType::kUint64},
+            {"mode", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_get_implied_cluster_alloc_exit",
+        6,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"flags", ProtoSchemaType::kUint32},
+            {"lblk", ProtoSchemaType::kUint32},
+            {"pblk", ProtoSchemaType::kUint64},
+            {"len", ProtoSchemaType::kUint32},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_get_reserved_cluster_alloc",
+        4,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"lblk", ProtoSchemaType::kUint32},
+            {"len", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_ind_map_blocks_enter",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"lblk", ProtoSchemaType::kUint32},
+            {"len", ProtoSchemaType::kUint32},
+            {"flags", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_ind_map_blocks_exit",
+        8,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"flags", ProtoSchemaType::kUint32},
+            {"pblk", ProtoSchemaType::kUint64},
+            {"lblk", ProtoSchemaType::kUint32},
+            {"len", ProtoSchemaType::kUint32},
+            {"mflags", ProtoSchemaType::kUint32},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_insert_range",
+        4,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"offset", ProtoSchemaType::kInt64},
+            {"len", ProtoSchemaType::kInt64},
+        },
+    },
+    {
+        "ext4_invalidatepage",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"index", ProtoSchemaType::kUint64},
+            {"offset", ProtoSchemaType::kUint64},
+            {"length", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_journal_start",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ip", ProtoSchemaType::kUint64},
+            {"blocks", ProtoSchemaType::kInt32},
+            {"rsv_blocks", ProtoSchemaType::kInt32},
+            {"nblocks", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_journal_start_reserved",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ip", ProtoSchemaType::kUint64},
+            {"blocks", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_journalled_invalidatepage",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"index", ProtoSchemaType::kUint64},
+            {"offset", ProtoSchemaType::kUint64},
+            {"length", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_journalled_write_end",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pos", ProtoSchemaType::kInt64},
+            {"len", ProtoSchemaType::kUint32},
+            {"copied", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_load_inode",
+        2,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ext4_load_inode_bitmap",
+        2,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"group", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_mark_inode_dirty",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"ip", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ext4_mb_bitmap_load",
+        2,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"group", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_mb_buddy_bitmap_load",
+        2,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"group", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_mb_discard_preallocations",
+        2,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"needed", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_mb_new_group_pa",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pa_pstart", ProtoSchemaType::kUint64},
+            {"pa_lstart", ProtoSchemaType::kUint64},
+            {"pa_len", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_mb_new_inode_pa",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pa_pstart", ProtoSchemaType::kUint64},
+            {"pa_lstart", ProtoSchemaType::kUint64},
+            {"pa_len", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_mb_release_group_pa",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"pa_pstart", ProtoSchemaType::kUint64},
+            {"pa_len", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_mb_release_inode_pa",
+        4,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"block", ProtoSchemaType::kUint64},
+            {"count", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_mballoc_alloc",
+        20,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"orig_logical", ProtoSchemaType::kUint32},
+            {"orig_start", ProtoSchemaType::kInt32},
+            {"orig_group", ProtoSchemaType::kUint32},
+            {"orig_len", ProtoSchemaType::kInt32},
+            {"goal_logical", ProtoSchemaType::kUint32},
+            {"goal_start", ProtoSchemaType::kInt32},
+            {"goal_group", ProtoSchemaType::kUint32},
+            {"goal_len", ProtoSchemaType::kInt32},
+            {"result_logical", ProtoSchemaType::kUint32},
+            {"result_start", ProtoSchemaType::kInt32},
+            {"result_group", ProtoSchemaType::kUint32},
+            {"result_len", ProtoSchemaType::kInt32},
+            {"found", ProtoSchemaType::kUint32},
+            {"groups", ProtoSchemaType::kUint32},
+            {"buddy", ProtoSchemaType::kUint32},
+            {"flags", ProtoSchemaType::kUint32},
+            {"tail", ProtoSchemaType::kUint32},
+            {"cr", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_mballoc_discard",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"result_start", ProtoSchemaType::kInt32},
+            {"result_group", ProtoSchemaType::kUint32},
+            {"result_len", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_mballoc_free",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"result_start", ProtoSchemaType::kInt32},
+            {"result_group", ProtoSchemaType::kUint32},
+            {"result_len", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_mballoc_prealloc",
+        10,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"orig_logical", ProtoSchemaType::kUint32},
+            {"orig_start", ProtoSchemaType::kInt32},
+            {"orig_group", ProtoSchemaType::kUint32},
+            {"orig_len", ProtoSchemaType::kInt32},
+            {"result_logical", ProtoSchemaType::kUint32},
+            {"result_start", ProtoSchemaType::kInt32},
+            {"result_group", ProtoSchemaType::kUint32},
+            {"result_len", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_other_inode_update_time",
+        6,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"orig_ino", ProtoSchemaType::kUint64},
+            {"uid", ProtoSchemaType::kUint32},
+            {"gid", ProtoSchemaType::kUint32},
+            {"mode", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_punch_hole",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"offset", ProtoSchemaType::kInt64},
+            {"len", ProtoSchemaType::kInt64},
+            {"mode", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_read_block_bitmap_load",
+        2,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"group", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_readpage",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"index", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ext4_releasepage",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"index", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ext4_remove_blocks",
+        8,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"from", ProtoSchemaType::kUint32},
+            {"to", ProtoSchemaType::kUint32},
+            {"partial", ProtoSchemaType::kInt64},
+            {"ee_pblk", ProtoSchemaType::kUint64},
+            {"ee_lblk", ProtoSchemaType::kUint32},
+            {"ee_len", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_request_blocks",
+        10,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"len", ProtoSchemaType::kUint32},
+            {"logical", ProtoSchemaType::kUint32},
+            {"lleft", ProtoSchemaType::kUint32},
+            {"lright", ProtoSchemaType::kUint32},
+            {"goal", ProtoSchemaType::kUint64},
+            {"pleft", ProtoSchemaType::kUint64},
+            {"pright", ProtoSchemaType::kUint64},
+            {"flags", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_request_inode",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"dir", ProtoSchemaType::kUint64},
+            {"mode", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_sync_fs",
+        2,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"wait", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_trim_all_free",
+        5,
+        {
+            {},
+            {"dev_major", ProtoSchemaType::kInt32},
+            {"dev_minor", ProtoSchemaType::kInt32},
+            {"group", ProtoSchemaType::kUint32},
+            {"start", ProtoSchemaType::kInt32},
+            {"len", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_trim_extent",
+        5,
+        {
+            {},
+            {"dev_major", ProtoSchemaType::kInt32},
+            {"dev_minor", ProtoSchemaType::kInt32},
+            {"group", ProtoSchemaType::kUint32},
+            {"start", ProtoSchemaType::kInt32},
+            {"len", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_truncate_enter",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"blocks", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ext4_truncate_exit",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"blocks", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ext4_unlink_enter",
+        4,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"parent", ProtoSchemaType::kUint64},
+            {"size", ProtoSchemaType::kInt64},
+        },
+    },
+    {
+        "ext4_unlink_exit",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_write_begin",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pos", ProtoSchemaType::kInt64},
+            {"len", ProtoSchemaType::kUint32},
+            {"flags", ProtoSchemaType::kUint32},
+        },
+    },
+    {nullptr, 0, {}},
+    {nullptr, 0, {}},
+    {nullptr, 0, {}},
+    {nullptr, 0, {}},
+    {nullptr, 0, {}},
+    {nullptr, 0, {}},
+    {nullptr, 0, {}},
+    {nullptr, 0, {}},
+    {nullptr, 0, {}},
+    {nullptr, 0, {}},
+    {
+        "ext4_write_end",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pos", ProtoSchemaType::kInt64},
+            {"len", ProtoSchemaType::kUint32},
+            {"copied", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_writepage",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"index", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ext4_writepages",
+        10,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"nr_to_write", ProtoSchemaType::kInt64},
+            {"pages_skipped", ProtoSchemaType::kInt64},
+            {"range_start", ProtoSchemaType::kInt64},
+            {"range_end", ProtoSchemaType::kInt64},
+            {"writeback_index", ProtoSchemaType::kUint64},
+            {"sync_mode", ProtoSchemaType::kInt32},
+            {"for_kupdate", ProtoSchemaType::kUint32},
+            {"range_cyclic", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ext4_writepages_result",
+        7,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"ret", ProtoSchemaType::kInt32},
+            {"pages_written", ProtoSchemaType::kInt32},
+            {"pages_skipped", ProtoSchemaType::kInt64},
+            {"writeback_index", ProtoSchemaType::kUint64},
+            {"sync_mode", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ext4_zero_range",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"offset", ProtoSchemaType::kInt64},
+            {"len", ProtoSchemaType::kInt64},
+            {"mode", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "task_newtask",
+        4,
+        {
+            {},
+            {"pid", ProtoSchemaType::kInt32},
+            {"comm", ProtoSchemaType::kString},
+            {"clone_flags", ProtoSchemaType::kUint64},
+            {"oom_score_adj", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "task_rename",
+        4,
+        {
+            {},
+            {"pid", ProtoSchemaType::kInt32},
+            {"oldcomm", ProtoSchemaType::kString},
+            {"newcomm", ProtoSchemaType::kString},
+            {"oom_score_adj", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "sched_process_exec",
+        3,
+        {
+            {},
+            {"filename", ProtoSchemaType::kString},
+            {"pid", ProtoSchemaType::kInt32},
+            {"old_pid", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "sched_process_exit",
+        4,
+        {
+            {},
+            {"comm", ProtoSchemaType::kString},
+            {"pid", ProtoSchemaType::kInt32},
+            {"tgid", ProtoSchemaType::kInt32},
+            {"prio", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "sched_process_fork",
+        4,
+        {
+            {},
+            {"parent_comm", ProtoSchemaType::kString},
+            {"parent_pid", ProtoSchemaType::kInt32},
+            {"child_comm", ProtoSchemaType::kString},
+            {"child_pid", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "sched_process_free",
+        3,
+        {
+            {},
+            {"comm", ProtoSchemaType::kString},
+            {"pid", ProtoSchemaType::kInt32},
+            {"prio", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "sched_process_hang",
+        2,
+        {
+            {},
+            {"comm", ProtoSchemaType::kString},
+            {"pid", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "sched_process_wait",
+        3,
+        {
+            {},
+            {"comm", ProtoSchemaType::kString},
+            {"pid", ProtoSchemaType::kInt32},
+            {"prio", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "f2fs_do_submit_bio",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"btype", ProtoSchemaType::kInt32},
+            {"sync", ProtoSchemaType::kUint32},
+            {"sector", ProtoSchemaType::kUint64},
+            {"size", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "f2fs_evict_inode",
+        8,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pino", ProtoSchemaType::kUint64},
+            {"mode", ProtoSchemaType::kUint32},
+            {"size", ProtoSchemaType::kInt64},
+            {"nlink", ProtoSchemaType::kUint32},
+            {"blocks", ProtoSchemaType::kUint64},
+            {"advise", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "f2fs_fallocate",
+        8,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"mode", ProtoSchemaType::kInt32},
+            {"offset", ProtoSchemaType::kInt64},
+            {"len", ProtoSchemaType::kInt64},
+            {"size", ProtoSchemaType::kInt64},
+            {"blocks", ProtoSchemaType::kUint64},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "f2fs_get_data_block",
+        6,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"iblock", ProtoSchemaType::kUint64},
+            {"bh_start", ProtoSchemaType::kUint64},
+            {"bh_size", ProtoSchemaType::kUint64},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "f2fs_get_victim",
+        10,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"type", ProtoSchemaType::kInt32},
+            {"gc_type", ProtoSchemaType::kInt32},
+            {"alloc_mode", ProtoSchemaType::kInt32},
+            {"gc_mode", ProtoSchemaType::kInt32},
+            {"victim", ProtoSchemaType::kUint32},
+            {"ofs_unit", ProtoSchemaType::kUint32},
+            {"pre_victim", ProtoSchemaType::kUint32},
+            {"prefree", ProtoSchemaType::kUint32},
+            {"free", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "f2fs_iget",
+        8,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pino", ProtoSchemaType::kUint64},
+            {"mode", ProtoSchemaType::kUint32},
+            {"size", ProtoSchemaType::kInt64},
+            {"nlink", ProtoSchemaType::kUint32},
+            {"blocks", ProtoSchemaType::kUint64},
+            {"advise", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "f2fs_iget_exit",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "f2fs_new_inode",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "f2fs_readpage",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"index", ProtoSchemaType::kUint64},
+            {"blkaddr", ProtoSchemaType::kUint64},
+            {"type", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "f2fs_reserve_new_block",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"nid", ProtoSchemaType::kUint32},
+            {"ofs_in_node", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "f2fs_set_page_dirty",
+        6,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"type", ProtoSchemaType::kInt32},
+            {"dir", ProtoSchemaType::kInt32},
+            {"index", ProtoSchemaType::kUint64},
+            {"dirty", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "f2fs_submit_write_page",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"type", ProtoSchemaType::kInt32},
+            {"index", ProtoSchemaType::kUint64},
+            {"block", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "f2fs_sync_file_enter",
+        8,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pino", ProtoSchemaType::kUint64},
+            {"mode", ProtoSchemaType::kUint32},
+            {"size", ProtoSchemaType::kInt64},
+            {"nlink", ProtoSchemaType::kUint32},
+            {"blocks", ProtoSchemaType::kUint64},
+            {"advise", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "f2fs_sync_file_exit",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"need_cp", ProtoSchemaType::kUint32},
+            {"datasync", ProtoSchemaType::kInt32},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "f2fs_sync_fs",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"dirty", ProtoSchemaType::kInt32},
+            {"wait", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "f2fs_truncate",
+        8,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pino", ProtoSchemaType::kUint64},
+            {"mode", ProtoSchemaType::kUint32},
+            {"size", ProtoSchemaType::kInt64},
+            {"nlink", ProtoSchemaType::kUint32},
+            {"blocks", ProtoSchemaType::kUint64},
+            {"advise", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "f2fs_truncate_blocks_enter",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"size", ProtoSchemaType::kInt64},
+            {"blocks", ProtoSchemaType::kUint64},
+            {"from", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "f2fs_truncate_blocks_exit",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "f2fs_truncate_data_blocks_range",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"nid", ProtoSchemaType::kUint32},
+            {"ofs", ProtoSchemaType::kUint32},
+            {"free", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "f2fs_truncate_inode_blocks_enter",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"size", ProtoSchemaType::kInt64},
+            {"blocks", ProtoSchemaType::kUint64},
+            {"from", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "f2fs_truncate_inode_blocks_exit",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "f2fs_truncate_node",
+        4,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"nid", ProtoSchemaType::kUint32},
+            {"blk_addr", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "f2fs_truncate_nodes_enter",
+        4,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"nid", ProtoSchemaType::kUint32},
+            {"blk_addr", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "f2fs_truncate_nodes_exit",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "f2fs_truncate_partial_nodes",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"nid", ProtoSchemaType::kUint32},
+            {"depth", ProtoSchemaType::kInt32},
+            {"err", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "f2fs_unlink_enter",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"size", ProtoSchemaType::kInt64},
+            {"blocks", ProtoSchemaType::kUint64},
+            {"name", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "f2fs_unlink_exit",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"ret", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "f2fs_vm_page_mkwrite",
+        6,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"type", ProtoSchemaType::kInt32},
+            {"dir", ProtoSchemaType::kInt32},
+            {"index", ProtoSchemaType::kUint64},
+            {"dirty", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "f2fs_write_begin",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pos", ProtoSchemaType::kInt64},
+            {"len", ProtoSchemaType::kUint32},
+            {"flags", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "f2fs_write_checkpoint",
+        3,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"is_umount", ProtoSchemaType::kUint32},
+            {"msg", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "f2fs_write_end",
+        5,
+        {
+            {},
+            {"dev", ProtoSchemaType::kUint64},
+            {"ino", ProtoSchemaType::kUint64},
+            {"pos", ProtoSchemaType::kInt64},
+            {"len", ProtoSchemaType::kUint32},
+            {"copied", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "alloc_pages_iommu_end",
+        2,
+        {
+            {},
+            {"gfp_flags", ProtoSchemaType::kUint32},
+            {"order", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "alloc_pages_iommu_fail",
+        2,
+        {
+            {},
+            {"gfp_flags", ProtoSchemaType::kUint32},
+            {"order", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "alloc_pages_iommu_start",
+        2,
+        {
+            {},
+            {"gfp_flags", ProtoSchemaType::kUint32},
+            {"order", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "alloc_pages_sys_end",
+        2,
+        {
+            {},
+            {"gfp_flags", ProtoSchemaType::kUint32},
+            {"order", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "alloc_pages_sys_fail",
+        2,
+        {
+            {},
+            {"gfp_flags", ProtoSchemaType::kUint32},
+            {"order", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "alloc_pages_sys_start",
+        2,
+        {
+            {},
+            {"gfp_flags", ProtoSchemaType::kUint32},
+            {"order", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "dma_alloc_contiguous_retry",
+        1,
+        {
+            {},
+            {"tries", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "iommu_map_range",
+        4,
+        {
+            {},
+            {"chunk_size", ProtoSchemaType::kUint64},
+            {"len", ProtoSchemaType::kUint64},
+            {"pa", ProtoSchemaType::kUint64},
+            {"va", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "iommu_sec_ptbl_map_range_end",
+        5,
+        {
+            {},
+            {"len", ProtoSchemaType::kUint64},
+            {"num", ProtoSchemaType::kInt32},
+            {"pa", ProtoSchemaType::kUint32},
+            {"sec_id", ProtoSchemaType::kInt32},
+            {"va", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "iommu_sec_ptbl_map_range_start",
+        5,
+        {
+            {},
+            {"len", ProtoSchemaType::kUint64},
+            {"num", ProtoSchemaType::kInt32},
+            {"pa", ProtoSchemaType::kUint32},
+            {"sec_id", ProtoSchemaType::kInt32},
+            {"va", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ion_alloc_buffer_end",
+        5,
+        {
+            {},
+            {"client_name", ProtoSchemaType::kString},
+            {"flags", ProtoSchemaType::kUint32},
+            {"heap_name", ProtoSchemaType::kString},
+            {"len", ProtoSchemaType::kUint64},
+            {"mask", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ion_alloc_buffer_fail",
+        6,
+        {
+            {},
+            {"client_name", ProtoSchemaType::kString},
+            {"error", ProtoSchemaType::kInt64},
+            {"flags", ProtoSchemaType::kUint32},
+            {"heap_name", ProtoSchemaType::kString},
+            {"len", ProtoSchemaType::kUint64},
+            {"mask", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ion_alloc_buffer_fallback",
+        6,
+        {
+            {},
+            {"client_name", ProtoSchemaType::kString},
+            {"error", ProtoSchemaType::kInt64},
+            {"flags", ProtoSchemaType::kUint32},
+            {"heap_name", ProtoSchemaType::kString},
+            {"len", ProtoSchemaType::kUint64},
+            {"mask", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ion_alloc_buffer_start",
+        5,
+        {
+            {},
+            {"client_name", ProtoSchemaType::kString},
+            {"flags", ProtoSchemaType::kUint32},
+            {"heap_name", ProtoSchemaType::kString},
+            {"len", ProtoSchemaType::kUint64},
+            {"mask", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "ion_cp_alloc_retry",
+        1,
+        {
+            {},
+            {"tries", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ion_cp_secure_buffer_end",
+        4,
+        {
+            {},
+            {"align", ProtoSchemaType::kUint64},
+            {"flags", ProtoSchemaType::kUint64},
+            {"heap_name", ProtoSchemaType::kString},
+            {"len", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ion_cp_secure_buffer_start",
+        4,
+        {
+            {},
+            {"align", ProtoSchemaType::kUint64},
+            {"flags", ProtoSchemaType::kUint64},
+            {"heap_name", ProtoSchemaType::kString},
+            {"len", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ion_prefetching",
+        1,
+        {
+            {},
+            {"len", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ion_secure_cma_add_to_pool_end",
+        3,
+        {
+            {},
+            {"is_prefetch", ProtoSchemaType::kUint32},
+            {"len", ProtoSchemaType::kUint64},
+            {"pool_total", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ion_secure_cma_add_to_pool_start",
+        3,
+        {
+            {},
+            {"is_prefetch", ProtoSchemaType::kUint32},
+            {"len", ProtoSchemaType::kUint64},
+            {"pool_total", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "ion_secure_cma_allocate_end",
+        4,
+        {
+            {},
+            {"align", ProtoSchemaType::kUint64},
+            {"flags", ProtoSchemaType::kUint64},
+            {"heap_name", ProtoSchemaType::kString},
+            {"len", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ion_secure_cma_allocate_start",
+        4,
+        {
+            {},
+            {"align", ProtoSchemaType::kUint64},
+            {"flags", ProtoSchemaType::kUint64},
+            {"heap_name", ProtoSchemaType::kString},
+            {"len", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ion_secure_cma_shrink_pool_end",
+        2,
+        {
+            {},
+            {"drained_size", ProtoSchemaType::kUint64},
+            {"skipped_size", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "ion_secure_cma_shrink_pool_start",
+        2,
+        {
+            {},
+            {"drained_size", ProtoSchemaType::kUint64},
+            {"skipped_size", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "kfree",
+        2,
+        {
+            {},
+            {"call_site", ProtoSchemaType::kUint64},
+            {"ptr", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "kmalloc",
+        5,
+        {
+            {},
+            {"bytes_alloc", ProtoSchemaType::kUint64},
+            {"bytes_req", ProtoSchemaType::kUint64},
+            {"call_site", ProtoSchemaType::kUint64},
+            {"gfp_flags", ProtoSchemaType::kUint32},
+            {"ptr", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "kmalloc_node",
+        6,
+        {
+            {},
+            {"bytes_alloc", ProtoSchemaType::kUint64},
+            {"bytes_req", ProtoSchemaType::kUint64},
+            {"call_site", ProtoSchemaType::kUint64},
+            {"gfp_flags", ProtoSchemaType::kUint32},
+            {"node", ProtoSchemaType::kInt32},
+            {"ptr", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "kmem_cache_alloc",
+        5,
+        {
+            {},
+            {"bytes_alloc", ProtoSchemaType::kUint64},
+            {"bytes_req", ProtoSchemaType::kUint64},
+            {"call_site", ProtoSchemaType::kUint64},
+            {"gfp_flags", ProtoSchemaType::kUint32},
+            {"ptr", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "kmem_cache_alloc_node",
+        6,
+        {
+            {},
+            {"bytes_alloc", ProtoSchemaType::kUint64},
+            {"bytes_req", ProtoSchemaType::kUint64},
+            {"call_site", ProtoSchemaType::kUint64},
+            {"gfp_flags", ProtoSchemaType::kUint32},
+            {"node", ProtoSchemaType::kInt32},
+            {"ptr", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "kmem_cache_free",
+        2,
+        {
+            {},
+            {"call_site", ProtoSchemaType::kUint64},
+            {"ptr", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "migrate_pages_end",
+        1,
+        {
+            {},
+            {"mode", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "migrate_pages_start",
+        1,
+        {
+            {},
+            {"mode", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "migrate_retry",
+        1,
+        {
+            {},
+            {"tries", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "mm_page_alloc",
+        5,
+        {
+            {},
+            {"gfp_flags", ProtoSchemaType::kUint32},
+            {"migratetype", ProtoSchemaType::kInt32},
+            {"order", ProtoSchemaType::kUint32},
+            {"page", ProtoSchemaType::kUint64},
+            {"pfn", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "mm_page_alloc_extfrag",
+        7,
+        {
+            {},
+            {"alloc_migratetype", ProtoSchemaType::kInt32},
+            {"alloc_order", ProtoSchemaType::kInt32},
+            {"fallback_migratetype", ProtoSchemaType::kInt32},
+            {"fallback_order", ProtoSchemaType::kInt32},
+            {"page", ProtoSchemaType::kUint64},
+            {"change_ownership", ProtoSchemaType::kInt32},
+            {"pfn", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "mm_page_alloc_zone_locked",
+        4,
+        {
+            {},
+            {"migratetype", ProtoSchemaType::kInt32},
+            {"order", ProtoSchemaType::kUint32},
+            {"page", ProtoSchemaType::kUint64},
+            {"pfn", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "mm_page_free",
+        3,
+        {
+            {},
+            {"order", ProtoSchemaType::kUint32},
+            {"page", ProtoSchemaType::kUint64},
+            {"pfn", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "mm_page_free_batched",
+        3,
+        {
+            {},
+            {"cold", ProtoSchemaType::kInt32},
+            {"page", ProtoSchemaType::kUint64},
+            {"pfn", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "mm_page_pcpu_drain",
+        4,
+        {
+            {},
+            {"migratetype", ProtoSchemaType::kInt32},
+            {"order", ProtoSchemaType::kUint32},
+            {"page", ProtoSchemaType::kUint64},
+            {"pfn", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "rss_stat",
+        2,
+        {
+            {},
+            {"member", ProtoSchemaType::kInt32},
+            {"size", ProtoSchemaType::kInt64},
+        },
+    },
+    {
+        "ion_heap_shrink",
+        3,
+        {
+            {},
+            {"heap_name", ProtoSchemaType::kString},
+            {"len", ProtoSchemaType::kUint64},
+            {"total_allocated", ProtoSchemaType::kInt64},
+        },
+    },
+    {
+        "ion_heap_grow",
+        3,
+        {
+            {},
+            {"heap_name", ProtoSchemaType::kString},
+            {"len", ProtoSchemaType::kUint64},
+            {"total_allocated", ProtoSchemaType::kInt64},
+        },
+    },
+    {
+        "fence_init",
+        4,
+        {
+            {},
+            {"context", ProtoSchemaType::kUint32},
+            {"driver", ProtoSchemaType::kString},
+            {"seqno", ProtoSchemaType::kUint32},
+            {"timeline", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "fence_destroy",
+        4,
+        {
+            {},
+            {"context", ProtoSchemaType::kUint32},
+            {"driver", ProtoSchemaType::kString},
+            {"seqno", ProtoSchemaType::kUint32},
+            {"timeline", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "fence_enable_signal",
+        4,
+        {
+            {},
+            {"context", ProtoSchemaType::kUint32},
+            {"driver", ProtoSchemaType::kString},
+            {"seqno", ProtoSchemaType::kUint32},
+            {"timeline", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "fence_signaled",
+        4,
+        {
+            {},
+            {"context", ProtoSchemaType::kUint32},
+            {"driver", ProtoSchemaType::kString},
+            {"seqno", ProtoSchemaType::kUint32},
+            {"timeline", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "clk_enable",
+        1,
+        {
+            {},
+            {"name", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "clk_disable",
+        1,
+        {
+            {},
+            {"name", ProtoSchemaType::kString},
+        },
+    },
+    {
+        "clk_set_rate",
+        2,
+        {
+            {},
+            {"name", ProtoSchemaType::kString},
+            {"rate", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "binder_transaction_alloc_buf",
+        3,
+        {
+            {},
+            {"data_size", ProtoSchemaType::kUint64},
+            {"debug_id", ProtoSchemaType::kInt32},
+            {"offsets_size", ProtoSchemaType::kUint64},
+        },
+    },
+    {
+        "signal_deliver",
+        3,
+        {
+            {},
+            {"code", ProtoSchemaType::kInt32},
+            {"sa_flags", ProtoSchemaType::kUint64},
+            {"sig", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "signal_generate",
+        6,
+        {
+            {},
+            {"code", ProtoSchemaType::kInt32},
+            {"comm", ProtoSchemaType::kString},
+            {"group", ProtoSchemaType::kInt32},
+            {"pid", ProtoSchemaType::kInt32},
+            {"result", ProtoSchemaType::kInt32},
+            {"sig", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "oom_score_adj_update",
+        3,
+        {
+            {},
+            {"comm", ProtoSchemaType::kString},
+            {"oom_score_adj", ProtoSchemaType::kInt32},
+            {"pid", ProtoSchemaType::kInt32},
+        },
+    },
+    {
+        "generic",
+        2,
+        {
+            {},
+            {"event_name", ProtoSchemaType::kString},
+            {},
+        },
+    },
+    {
+        "mm_event_record",
+        4,
+        {
+            {},
+            {"avg_lat", ProtoSchemaType::kUint32},
+            {"count", ProtoSchemaType::kUint32},
+            {"max_lat", ProtoSchemaType::kUint32},
+            {"type", ProtoSchemaType::kUint32},
+        },
+    },
+    {
+        "sys_enter",
+        1,
+        {
+            {},
+            {"id", ProtoSchemaType::kInt64},
+        },
+    },
+    {
+        "sys_exit",
+        2,
+        {
+            {},
+            {"id", ProtoSchemaType::kInt64},
+            {"ret", ProtoSchemaType::kInt64},
+        },
+    },
+    {
+        "zero",
+        4,
+        {
+            {},
+            {"flag", ProtoSchemaType::kInt32},
+            {"name", ProtoSchemaType::kString},
+            {"pid", ProtoSchemaType::kInt32},
+            {"value", ProtoSchemaType::kInt64},
+        },
+    },
+}};
+
+}  // namespace
+
+MessageDescriptor* GetMessageDescriptorForId(size_t id) {
+  PERFETTO_CHECK(id < descriptors.size());
+  return &descriptors[id];
+}
+
+size_t GetDescriptorsSize() {
+  return descriptors.size();
+}
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/ftrace_descriptors.h b/src/trace_processor/ftrace_descriptors.h
new file mode 100644
index 0000000..71e58d0
--- /dev/null
+++ b/src/trace_processor/ftrace_descriptors.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_FTRACE_DESCRIPTORS_H_
+#define SRC_TRACE_PROCESSOR_FTRACE_DESCRIPTORS_H_
+
+#include <array>
+#include "perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+using protozero::proto_utils::ProtoSchemaType;
+
+// We assume that no ftrace event (e.g. SchedSwitchFtraceEvent) has a proto
+// field which id is >= this.
+static constexpr size_t kMaxFtraceEventFields = 32;
+
+// This file is the header for the generated descriptors for all ftrace event
+// protos. These descriptors can be used to parse ftrace event protos without
+// needing individual parsing logic for every event. (In proto_trace_parser.cc)
+// By generating these descriptors we avoid having to build the full proto
+// library. These structs deliberately don't have a ctor (nor are initialized)
+// because they are used to define linker-initialized dicts in the .cc file.
+struct FieldDescriptor {
+  const char* name;
+  ProtoSchemaType type;
+};
+
+struct MessageDescriptor {
+  const char* name;
+  size_t max_field_id;
+  FieldDescriptor fields[kMaxFtraceEventFields];
+};
+
+MessageDescriptor* GetMessageDescriptorForId(size_t id);
+size_t GetDescriptorsSize();
+
+}  // namespace trace_processor
+}  // namespace perfetto
+#endif  // SRC_TRACE_PROCESSOR_FTRACE_DESCRIPTORS_H_
diff --git a/src/trace_processor/ftrace_utils.cc b/src/trace_processor/ftrace_utils.cc
index b58fd73..13c67aa 100644
--- a/src/trace_processor/ftrace_utils.cc
+++ b/src/trace_processor/ftrace_utils.cc
@@ -20,7 +20,7 @@
 #include <algorithm>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_writer.h"
+#include "perfetto/base/string_writer.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -36,14 +36,6 @@
 };
 }  // namespace
 
-TaskState::TaskState(uint16_t raw_state) {
-  if (raw_state > kMaxState) {
-    state_ = 0;
-  } else {
-    state_ = raw_state | kValid;
-  }
-}
-
 TaskState::TaskState(const char* state_str) {
   bool invalid_char = false;
   bool is_runnable = false;
@@ -97,8 +89,6 @@
       state_ |= Atom::kParked;
     else if (c == 'N')
       state_ |= Atom::kNoLoad;
-    else if (c == '|')
-      continue;
     else {
       invalid_char = true;
       break;
@@ -106,14 +96,14 @@
   }
 
   bool no_state = !is_runnable && state_ == 0;
-  if (invalid_char || no_state || state_ > kMaxState) {
+  if (invalid_char || no_state) {
     state_ = 0;
   } else {
     state_ |= kValid;
   }
 }
 
-TaskState::TaskStateStr TaskState::ToString(char separator) const {
+TaskState::TaskStateStr TaskState::ToString() const {
   PERFETTO_CHECK(is_valid());
 
   char buffer[32];
@@ -126,56 +116,26 @@
   } else {
     if (state_ & Atom::kInterruptibleSleep)
       buffer[pos++] = 'S';
-    if (state_ & Atom::kUninterruptibleSleep) {
-      if (separator && pos != 0)
-        buffer[pos++] = separator;
+    if (state_ & Atom::kUninterruptibleSleep)
       buffer[pos++] = 'D';  // D for (D)isk sleep
-    }
-    if (state_ & Atom::kStopped) {
-      if (separator && pos != 0)
-        buffer[pos++] = separator;
+    if (state_ & Atom::kStopped)
       buffer[pos++] = 'T';
-    }
-    if (state_ & Atom::kTraced) {
-      if (separator && pos != 0)
-        buffer[pos++] = separator;
+    if (state_ & Atom::kTraced)
       buffer[pos++] = 't';
-    }
-    if (state_ & Atom::kExitDead) {
-      if (separator && pos != 0)
-        buffer[pos++] = separator;
+    if (state_ & Atom::kExitDead)
       buffer[pos++] = 'X';
-    }
-    if (state_ & Atom::kExitZombie) {
-      if (separator && pos != 0)
-        buffer[pos++] = separator;
+    if (state_ & Atom::kExitZombie)
       buffer[pos++] = 'Z';
-    }
-    if (state_ & Atom::kTaskDead) {
-      if (separator && pos != 0)
-        buffer[pos++] = separator;
+    if (state_ & Atom::kTaskDead)
       buffer[pos++] = 'x';
-    }
-    if (state_ & Atom::kWakeKill) {
-      if (separator && pos != 0)
-        buffer[pos++] = separator;
+    if (state_ & Atom::kWakeKill)
       buffer[pos++] = 'K';
-    }
-    if (state_ & Atom::kWaking) {
-      if (separator && pos != 0)
-        buffer[pos++] = separator;
+    if (state_ & Atom::kWaking)
       buffer[pos++] = 'W';
-    }
-    if (state_ & Atom::kParked) {
-      if (separator && pos != 0)
-        buffer[pos++] = separator;
+    if (state_ & Atom::kParked)
       buffer[pos++] = 'P';
-    }
-    if (state_ & Atom::kNoLoad) {
-      if (separator && pos != 0)
-        buffer[pos++] = separator;
+    if (state_ & Atom::kNoLoad)
       buffer[pos++] = 'N';
-    }
   }
 
   if (is_kernel_preempt())
@@ -195,22 +155,13 @@
   FtraceTime ftrace_time(timestamp);
   if (pid == 0) {
     name = "<idle>";
-  } else if (name == "") {
-    name = "<unknown>";
-  } else if (name == "CrRendererMain") {
-    // TODO(taylori): Remove this when crbug.com/978093 is fixed or
-    // when a better solution is found.
-    name = "CrRendererMainThread";
   }
 
   int64_t padding = 16 - static_cast<int64_t>(name.size());
-  if (padding > 0) {
+  if (PERFETTO_LIKELY(padding > 0)) {
     writer->AppendChar(' ', static_cast<size_t>(padding));
   }
-  for (size_t i = 0; i < name.size(); ++i) {
-    char c = name.data()[i];
-    writer->AppendChar(c == '-' ? '_' : c);
-  }
+  writer->AppendString(name);
   writer->AppendChar('-');
 
   size_t pre_pid_pos = writer->pos();
diff --git a/src/trace_processor/ftrace_utils.h b/src/trace_processor/ftrace_utils.h
index fa8d48f..ff92028 100644
--- a/src/trace_processor/ftrace_utils.h
+++ b/src/trace_processor/ftrace_utils.h
@@ -21,8 +21,8 @@
 #include <array>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/ext/base/string_writer.h"
+#include "perfetto/base/string_view.h"
+#include "perfetto/base/string_writer.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -61,17 +61,16 @@
   };
 
   TaskState() = default;
-  explicit TaskState(uint16_t raw_state);
+  explicit TaskState(uint16_t raw_state) : state_(raw_state | kValid) {}
   explicit TaskState(const char* state_str);
 
   // Returns if this TaskState has a valid representation.
   bool is_valid() const { return state_ & kValid; }
 
   // Returns the string representation of this (valid) TaskState. This array
-  // is null terminated. |seperator| specifies if a separator should be printed
-  // between the atoms (default: \0 meaning no separator).
+  // is null terminated.
   // Note: This function CHECKs that |is_valid()| is true.
-  TaskStateStr ToString(char separator = '\0') const;
+  TaskStateStr ToString() const;
 
   // Returns the raw state this class was created from.
   uint16_t raw_state() const {
diff --git a/src/trace_processor/ftrace_utils_unittest.cc b/src/trace_processor/ftrace_utils_unittest.cc
index 3675fb2..5f03a65 100644
--- a/src/trace_processor/ftrace_utils_unittest.cc
+++ b/src/trace_processor/ftrace_utils_unittest.cc
@@ -16,7 +16,8 @@
 
 #include "src/trace_processor/ftrace_utils.h"
 
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -53,9 +54,6 @@
   ASSERT_STREQ(TaskState(4096).ToString().data(), "R+");
   ASSERT_STREQ(TaskState(130).ToString().data(), "DK");
   ASSERT_STREQ(TaskState(258).ToString().data(), "DW");
-
-  ASSERT_EQ(TaskState("D|K").raw_state(), 130);
-  ASSERT_EQ(TaskState("D|W").raw_state(), 258);
 }
 
 }  // namespace
diff --git a/src/trace_processor/fuchsia_provider_view.cc b/src/trace_processor/fuchsia_provider_view.cc
new file mode 100644
index 0000000..c83b789
--- /dev/null
+++ b/src/trace_processor/fuchsia_provider_view.cc
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2019 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 "src/trace_processor/fuchsia_provider_view.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+void FuchsiaProviderView::InsertString(uint32_t index, StringId string_id) {
+  StringTableEntry entry;
+  entry.index = index;
+  entry.string_id = string_id;
+
+  string_entries_.push_back(entry);
+}
+
+StringId FuchsiaProviderView::GetString(uint32_t index) {
+  for (const auto& entry : string_entries_) {
+    if (entry.index == index)
+      return entry.string_id;
+  }
+  return StringId();
+}
+
+void FuchsiaProviderView::InsertThread(uint32_t index,
+                                       fuchsia_trace_utils::ThreadInfo info) {
+  ThreadTableEntry entry;
+  entry.index = index;
+  entry.info = info;
+
+  thread_entries_.push_back(entry);
+}
+
+fuchsia_trace_utils::ThreadInfo FuchsiaProviderView::GetThread(uint32_t index) {
+  for (const auto& entry : thread_entries_) {
+    if (entry.index == index)
+      return entry.info;
+  }
+  return fuchsia_trace_utils::ThreadInfo();
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/fuchsia_provider_view.h b/src/trace_processor/fuchsia_provider_view.h
new file mode 100644
index 0000000..3f7add2
--- /dev/null
+++ b/src/trace_processor/fuchsia_provider_view.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_FUCHSIA_PROVIDER_VIEW_H_
+#define SRC_TRACE_PROCESSOR_FUCHSIA_PROVIDER_VIEW_H_
+
+#include "src/trace_processor/fuchsia_trace_utils.h"
+#include "src/trace_processor/trace_storage.h"
+
+#include <vector>
+
+namespace perfetto {
+namespace trace_processor {
+
+// Data from a trace provider that is necessary for interpreting a binary
+// record. Namely, the entries of the string table and the thread table that are
+// referenced by the record. This enables understanding the binary record after
+// arbitrary reordering.
+class FuchsiaProviderView {
+ public:
+  struct StringTableEntry {
+    uint32_t index;
+    StringId string_id;
+  };
+
+  struct ThreadTableEntry {
+    uint32_t index;
+    fuchsia_trace_utils::ThreadInfo info;
+  };
+
+  void InsertString(uint32_t, StringId);
+  StringId GetString(uint32_t);
+
+  void InsertThread(uint32_t, fuchsia_trace_utils::ThreadInfo);
+  fuchsia_trace_utils::ThreadInfo GetThread(uint32_t);
+
+  void set_ticks_per_second(uint64_t ticks_per_second) {
+    ticks_per_second_ = ticks_per_second;
+  }
+
+  uint64_t get_ticks_per_second() { return ticks_per_second_; }
+
+ private:
+  std::vector<StringTableEntry> string_entries_;
+  std::vector<ThreadTableEntry> thread_entries_;
+
+  uint64_t ticks_per_second_ = 1000000000;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_FUCHSIA_PROVIDER_VIEW_H_
diff --git a/src/trace_processor/fuchsia_trace_parser.cc b/src/trace_processor/fuchsia_trace_parser.cc
new file mode 100644
index 0000000..6599a73
--- /dev/null
+++ b/src/trace_processor/fuchsia_trace_parser.cc
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2019 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 "src/trace_processor/fuchsia_trace_parser.h"
+
+#include "src/trace_processor/process_tracker.h"
+#include "src/trace_processor/slice_tracker.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+namespace {
+// Record Types
+constexpr uint32_t kEvent = 4;
+
+// Event Types
+constexpr uint32_t kDurationBegin = 2;
+constexpr uint32_t kDurationEnd = 3;
+constexpr uint32_t kDurationComplete = 4;
+}  // namespace
+
+FuchsiaTraceParser::FuchsiaTraceParser(TraceProcessorContext* context)
+    : context_(context) {}
+
+FuchsiaTraceParser::~FuchsiaTraceParser() = default;
+
+void FuchsiaTraceParser::ParseFtracePacket(uint32_t,
+                                           int64_t,
+                                           TraceSorter::TimestampedTracePiece) {
+  PERFETTO_FATAL("Fuchsia Trace Parser cannot handle ftrace packets.");
+}
+
+void FuchsiaTraceParser::ParseTracePacket(
+    int64_t,
+    TraceSorter::TimestampedTracePiece ttp) {
+  PERFETTO_DCHECK(ttp.fuchsia_provider_view != nullptr);
+
+  // The timestamp is also present in the record, so we'll ignore the one passed
+  // as an argument.
+  const uint64_t* current =
+      reinterpret_cast<const uint64_t*>(ttp.blob_view.data());
+  FuchsiaProviderView* provider_view = ttp.fuchsia_provider_view.get();
+  ProcessTracker* procs = context_->process_tracker.get();
+  SliceTracker* slices = context_->slice_tracker.get();
+
+  uint64_t header = *current++;
+  uint32_t record_type = fuchsia_trace_utils::ReadField<uint32_t>(header, 0, 3);
+  switch (record_type) {
+    case kEvent: {
+      uint32_t event_type =
+          fuchsia_trace_utils::ReadField<uint32_t>(header, 16, 19);
+      uint32_t n_args =
+          fuchsia_trace_utils::ReadField<uint32_t>(header, 20, 23);
+      uint32_t thread_ref =
+          fuchsia_trace_utils::ReadField<uint32_t>(header, 24, 31);
+      uint32_t cat_ref =
+          fuchsia_trace_utils::ReadField<uint32_t>(header, 32, 47);
+      uint32_t name_ref =
+          fuchsia_trace_utils::ReadField<uint32_t>(header, 48, 63);
+
+      int64_t ts = fuchsia_trace_utils::ReadTimestamp(
+          &current, provider_view->get_ticks_per_second());
+      fuchsia_trace_utils::ThreadInfo tinfo;
+      if (fuchsia_trace_utils::IsInlineThread(thread_ref)) {
+        tinfo = fuchsia_trace_utils::ReadInlineThread(&current);
+      } else {
+        tinfo = provider_view->GetThread(thread_ref);
+      }
+      StringId cat;
+      if (fuchsia_trace_utils::IsInlineString(cat_ref)) {
+        cat = context_->storage->InternString(
+            fuchsia_trace_utils::ReadInlineString(&current, cat_ref));
+      } else {
+        cat = provider_view->GetString(cat_ref);
+      }
+      StringId name;
+      if (fuchsia_trace_utils::IsInlineString(name_ref)) {
+        name = context_->storage->InternString(
+            fuchsia_trace_utils::ReadInlineString(&current, name_ref));
+      } else {
+        name = provider_view->GetString(name_ref);
+      }
+
+      // Skip over all the args, so that the |ReadTimestamp| call for complete
+      // durations has the pointer in the right place.
+      for (uint32_t i = 0; i < n_args; i++) {
+        uint64_t arg_header = *current;
+        uint32_t arg_size_words =
+            fuchsia_trace_utils::ReadField<uint32_t>(arg_header, 4, 15);
+        current += arg_size_words;
+      }
+
+      switch (event_type) {
+        case kDurationBegin: {
+          UniqueTid utid =
+              procs->UpdateThread(static_cast<uint32_t>(tinfo.tid),
+                                  static_cast<uint32_t>(tinfo.pid));
+          slices->Begin(ts, utid, cat, name);
+          break;
+        }
+        case kDurationEnd: {
+          UniqueTid utid =
+              procs->UpdateThread(static_cast<uint32_t>(tinfo.tid),
+                                  static_cast<uint32_t>(tinfo.pid));
+          slices->End(ts, utid, cat, name);
+          break;
+        }
+        case kDurationComplete: {
+          int64_t end_ts = fuchsia_trace_utils::ReadTimestamp(
+              &current, provider_view->get_ticks_per_second());
+          UniqueTid utid =
+              procs->UpdateThread(static_cast<uint32_t>(tinfo.tid),
+                                  static_cast<uint32_t>(tinfo.pid));
+          slices->Scoped(ts, utid, cat, name, end_ts - ts);
+          break;
+        }
+      }
+      break;
+    }
+    default: {
+      PERFETTO_DFATAL("Unknown record type %d in FuchsiaTraceParser",
+                      record_type);
+      break;
+    }
+  }
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/fuchsia_trace_parser.h b/src/trace_processor/fuchsia_trace_parser.h
new file mode 100644
index 0000000..67cc95b
--- /dev/null
+++ b/src/trace_processor/fuchsia_trace_parser.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_FUCHSIA_TRACE_PARSER_H_
+#define SRC_TRACE_PROCESSOR_FUCHSIA_TRACE_PARSER_H_
+
+#include "src/trace_processor/fuchsia_provider_view.h"
+#include "src/trace_processor/trace_parser.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class TraceProcessorContext;
+
+class FuchsiaTraceParser : public TraceParser {
+ public:
+  explicit FuchsiaTraceParser(TraceProcessorContext*);
+  ~FuchsiaTraceParser() override;
+
+  // TraceParser implementation
+  void ParseTracePacket(int64_t timestamp,
+                        TraceSorter::TimestampedTracePiece) override;
+  void ParseFtracePacket(uint32_t,
+                         int64_t,
+                         TraceSorter::TimestampedTracePiece) override;
+
+ private:
+  TraceProcessorContext* const context_;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_FUCHSIA_TRACE_PARSER_H_
diff --git a/src/trace_processor/fuchsia_trace_tokenizer.cc b/src/trace_processor/fuchsia_trace_tokenizer.cc
new file mode 100644
index 0000000..0c4d216
--- /dev/null
+++ b/src/trace_processor/fuchsia_trace_tokenizer.cc
@@ -0,0 +1,477 @@
+/*
+ * Copyright (C) 2019 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 "src/trace_processor/fuchsia_trace_tokenizer.h"
+
+#include <inttypes.h>
+#include <unordered_map>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/base/string_view.h"
+#include "src/trace_processor/ftrace_utils.h"
+#include "src/trace_processor/fuchsia_provider_view.h"
+#include "src/trace_processor/process_tracker.h"
+#include "src/trace_processor/slice_tracker.h"
+#include "src/trace_processor/trace_processor_context.h"
+#include "src/trace_processor/trace_sorter.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+namespace {
+// Record types
+constexpr uint32_t kMetadata = 0;
+constexpr uint32_t kInitialization = 1;
+constexpr uint32_t kString = 2;
+constexpr uint32_t kThread = 3;
+constexpr uint32_t kEvent = 4;
+constexpr uint32_t kKernelObject = 7;
+constexpr uint32_t kContextSwitch = 8;
+
+// Metadata types
+constexpr uint32_t kProviderInfo = 1;
+constexpr uint32_t kProviderSection = 2;
+constexpr uint32_t kProviderEvent = 3;
+
+// Thread states
+constexpr uint32_t kThreadNew = 0;
+constexpr uint32_t kThreadRunning = 1;
+constexpr uint32_t kThreadSuspended = 2;
+constexpr uint32_t kThreadBlocked = 3;
+constexpr uint32_t kThreadDying = 4;
+constexpr uint32_t kThreadDead = 5;
+
+// Zircon object types
+constexpr uint32_t kZxObjTypeProcess = 1;
+constexpr uint32_t kZxObjTypeThread = 2;
+
+// Argument types
+constexpr uint32_t kArgKernelObject = 8;
+}  // namespace
+
+FuchsiaTraceTokenizer::FuchsiaTraceTokenizer(TraceProcessorContext* context)
+    : context_(context) {
+  RegisterProvider(0, "");
+}
+
+FuchsiaTraceTokenizer::~FuchsiaTraceTokenizer() = default;
+
+bool FuchsiaTraceTokenizer::Parse(std::unique_ptr<uint8_t[]> data,
+                                  size_t size) {
+  // The relevant internal state is |leftover_bytes_|. Each call to Parse should
+  // maintain the following properties, unless a fatal error occurs in which
+  // case it should return false and no assumptions should be made about the
+  // resulting internal state:
+  //
+  // 1) Every byte passed to |Parse| has either been passed to |ParseRecord| or
+  // is present in |leftover_bytes_|, but not both.
+  // 2) |leftover_bytes_| does not contain a complete record.
+  //
+  // Parse is responsible for creating the "full" |TraceBlobView|s, which own
+  // the underlying data. Generally, there will be one such view. However, if
+  // there is a record that started in an earlier call, then a new buffer is
+  // created here to make the bytes in that record contiguous.
+  //
+  // Because some of the bytes in |data| might belong to the record starting in
+  // |leftover_bytes_|, we track the offset at which the following record will
+  // start.
+  size_t byte_offset = 0;
+
+  // Look for a record starting with the leftover bytes.
+  if (leftover_bytes_.size() + size < 8) {
+    // Even with the new bytes, we can't even read the header of the next
+    // record, so just add the new bytes to |leftover_bytes_| and return.
+    leftover_bytes_.insert(leftover_bytes_.end(), data.get() + byte_offset,
+                           data.get() + size);
+    return true;
+  }
+  if (leftover_bytes_.size() > 0) {
+    // There is a record starting from leftover bytes.
+    if (leftover_bytes_.size() < 8) {
+      // Header was previously incomplete, but we have enough now.
+      // Copy bytes into |leftover_bytes_| so that the whole header is present,
+      // and update |byte_offset| and |size| accordingly.
+      size_t needed_bytes = 8 - leftover_bytes_.size();
+      leftover_bytes_.insert(leftover_bytes_.end(), data.get() + byte_offset,
+                             data.get() + needed_bytes);
+      byte_offset += needed_bytes;
+      size -= needed_bytes;
+    }
+    // Read the record length from the header.
+    uint64_t header =
+        *reinterpret_cast<const uint64_t*>(leftover_bytes_.data());
+    uint32_t record_len_words =
+        fuchsia_trace_utils::ReadField<uint32_t>(header, 4, 15);
+    uint32_t record_len_bytes = record_len_words * sizeof(uint64_t);
+
+    // From property (2) above, leftover_bytes_ must have had less than a full
+    // record to start with. We padded leftover_bytes_ out to read the header,
+    // so it may now be a full record (in the case that the record consists of
+    // only the header word), but it still cannot have any extra bytes.
+    PERFETTO_DCHECK(leftover_bytes_.size() <= record_len_bytes);
+    size_t missing_bytes = record_len_bytes - leftover_bytes_.size();
+
+    if (missing_bytes <= size) {
+      // We have enough bytes to complete the partial record. Create a new
+      // buffer for that record.
+      std::unique_ptr<uint8_t[]> buf(new uint8_t[record_len_bytes]);
+      memcpy(&buf[0], leftover_bytes_.data(), leftover_bytes_.size());
+      memcpy(&buf[leftover_bytes_.size()], &data[byte_offset], missing_bytes);
+      byte_offset += missing_bytes;
+      size -= missing_bytes;
+      leftover_bytes_.clear();
+
+      TraceBlobView leftover_record(std::move(buf), 0, record_len_bytes);
+      ParseRecord(std::move(leftover_record));
+    } else {
+      // There are not enough bytes for the full record. Add all the bytes we
+      // have to leftover_bytes_ and wait for more.
+      leftover_bytes_.insert(leftover_bytes_.end(), data.get() + byte_offset,
+                             data.get() + byte_offset + size);
+      return true;
+    }
+  }
+
+  TraceBlobView full_view(std::move(data), byte_offset, size);
+
+  // |record_offset| is a number of bytes past |byte_offset| where the record
+  // under consideration starts. As a result, it must always be in the range [0,
+  // size-8]. Any larger offset means we don't have enough bytes for the header.
+  size_t record_offset = 0;
+  while (record_offset + 8 <= size) {
+    uint64_t header =
+        *reinterpret_cast<const uint64_t*>(full_view.data() + record_offset);
+    uint32_t record_len_bytes =
+        fuchsia_trace_utils::ReadField<uint32_t>(header, 4, 15) *
+        sizeof(uint64_t);
+    if (record_len_bytes == 0) {
+      PERFETTO_DLOG("Unexpected record of size 0");
+      return false;
+    }
+
+    if (record_offset + record_len_bytes > size)
+      break;
+
+    TraceBlobView record =
+        full_view.slice(byte_offset + record_offset, record_len_bytes);
+    ParseRecord(std::move(record));
+
+    record_offset += record_len_bytes;
+  }
+
+  leftover_bytes_.insert(leftover_bytes_.end(),
+                         full_view.data() + record_offset,
+                         full_view.data() + size);
+  return true;
+}
+
+// Most record types are read and recorded in |TraceStorage| here directly.
+// Event records are sorted by timestamp before processing, so instead of
+// recording them in |TraceStorage| they are given to |TraceSorter|. In order to
+// facilitate the parsing after sorting, a small view of the provider's string
+// and thread tables is passed alongside the record. See |FuchsiaProviderView|.
+void FuchsiaTraceTokenizer::ParseRecord(TraceBlobView tbv) {
+  TraceStorage* storage = context_->storage.get();
+  ProcessTracker* procs = context_->process_tracker.get();
+  TraceSorter* sorter = context_->sorter.get();
+
+  const uint64_t* record = reinterpret_cast<const uint64_t*>(tbv.data());
+  uint64_t header = *record;
+
+  uint32_t record_type = fuchsia_trace_utils::ReadField<uint32_t>(header, 0, 3);
+  switch (record_type) {
+    case kMetadata: {
+      uint32_t metadata_type =
+          fuchsia_trace_utils::ReadField<uint32_t>(header, 16, 19);
+      switch (metadata_type) {
+        case kProviderInfo: {
+          uint32_t provider_id =
+              fuchsia_trace_utils::ReadField<uint32_t>(header, 20, 51);
+          uint32_t name_len =
+              fuchsia_trace_utils::ReadField<uint32_t>(header, 52, 59);
+          std::string name(reinterpret_cast<const char*>(&record[1]), name_len);
+          RegisterProvider(provider_id, name);
+          break;
+        }
+        case kProviderSection: {
+          uint32_t provider_id =
+              fuchsia_trace_utils::ReadField<uint32_t>(header, 20, 51);
+          current_provider_ = providers_[provider_id].get();
+          break;
+        }
+        case kProviderEvent: {
+          // TODO(bhamrick): Handle buffer fill events
+          PERFETTO_DLOG(
+              "Ignoring provider event. Events may have been dropped");
+          break;
+        }
+      }
+      break;
+    }
+    case kInitialization: {
+      current_provider_->ticks_per_second = record[1];
+      break;
+    }
+    case kString: {
+      uint32_t index = fuchsia_trace_utils::ReadField<uint32_t>(header, 16, 30);
+      if (index != 0) {
+        uint32_t len = fuchsia_trace_utils::ReadField<uint32_t>(header, 32, 46);
+        base::StringView s(reinterpret_cast<const char*>(&record[1]), len);
+        StringId id = storage->InternString(s);
+        current_provider_->string_table[index] = id;
+      }
+      break;
+    }
+    case kThread: {
+      uint32_t index = fuchsia_trace_utils::ReadField<uint32_t>(header, 16, 23);
+      if (index != 0) {
+        fuchsia_trace_utils::ThreadInfo tinfo;
+        tinfo.pid = record[1];
+        tinfo.tid = record[2];
+
+        current_provider_->thread_table[index] = tinfo;
+      }
+      break;
+    }
+    case kEvent: {
+      uint32_t thread_ref =
+          fuchsia_trace_utils::ReadField<uint32_t>(header, 24, 31);
+      uint32_t cat_ref =
+          fuchsia_trace_utils::ReadField<uint32_t>(header, 32, 47);
+      uint32_t name_ref =
+          fuchsia_trace_utils::ReadField<uint32_t>(header, 48, 63);
+
+      // Build the minimal FuchsiaProviderView needed by
+      // the record. This means the thread information if not inline, and any
+      // non-inline strings (name, category for now, arg names and string values
+      // in the future.
+      const uint64_t* current = &record[1];
+      auto provider_view =
+          std::unique_ptr<FuchsiaProviderView>(new FuchsiaProviderView());
+      provider_view->set_ticks_per_second(current_provider_->ticks_per_second);
+
+      uint64_t ticks = *current++;
+      int64_t ts = fuchsia_trace_utils::TicksToNs(
+          ticks, current_provider_->ticks_per_second);
+
+      if (fuchsia_trace_utils::IsInlineThread(thread_ref)) {
+        // Skip over inline thread
+        fuchsia_trace_utils::ReadInlineThread(&current);
+      } else {
+        provider_view->InsertThread(
+            thread_ref, current_provider_->thread_table[thread_ref]);
+      }
+
+      if (fuchsia_trace_utils::IsInlineString(cat_ref)) {
+        // Skip over inline string
+        fuchsia_trace_utils::ReadInlineString(&current, cat_ref);
+      } else {
+        provider_view->InsertString(cat_ref,
+                                    current_provider_->string_table[cat_ref]);
+      }
+
+      if (fuchsia_trace_utils::IsInlineString(name_ref)) {
+        // Skip over inline string
+        fuchsia_trace_utils::ReadInlineString(&current, name_ref);
+      } else {
+        provider_view->InsertString(name_ref,
+                                    current_provider_->string_table[name_ref]);
+      }
+
+      sorter->PushFuchsiaRecord(ts, std::move(tbv), std::move(provider_view));
+
+      break;
+    }
+    case kKernelObject: {
+      uint32_t obj_type =
+          fuchsia_trace_utils::ReadField<uint32_t>(header, 16, 23);
+      uint32_t name_ref =
+          fuchsia_trace_utils::ReadField<uint32_t>(header, 24, 39);
+
+      const uint64_t* current = &record[1];
+      uint64_t obj_id = *current++;
+
+      StringId name = StringId();
+      if (fuchsia_trace_utils::IsInlineString(name_ref)) {
+        name = storage->InternString(
+            fuchsia_trace_utils::ReadInlineString(&current, name_ref));
+      } else {
+        name = current_provider_->string_table[name_ref];
+      }
+
+      switch (obj_type) {
+        case kZxObjTypeProcess: {
+          // Note: Fuchsia pid/tids are 64 bits but Perfetto's tables only
+          // support 32 bits. This is usually not an issue except for
+          // artificial koids which have the 2^63 bit set. This is used for
+          // things such as virtual threads.
+          procs->UpdateProcess(static_cast<uint32_t>(obj_id),
+                               base::Optional<uint32_t>(),
+                               base::StringView(storage->GetString(name)));
+          break;
+        }
+        case kZxObjTypeThread: {
+          uint32_t n_args =
+              fuchsia_trace_utils::ReadField<uint32_t>(header, 40, 43);
+          uint64_t pid = 0;
+
+          // Scan for a Kernel Object argument named "process"
+          for (uint32_t i = 0; i < n_args; i++) {
+            const uint64_t* arg_base = current;
+            uint64_t arg_header = *current++;
+            uint32_t arg_type =
+                fuchsia_trace_utils::ReadField<uint32_t>(arg_header, 0, 3);
+            uint32_t arg_size =
+                fuchsia_trace_utils::ReadField<uint32_t>(arg_header, 4, 15);
+            if (arg_type == kArgKernelObject) {
+              uint32_t arg_name_ref =
+                  fuchsia_trace_utils::ReadField<uint32_t>(arg_header, 16, 31);
+              base::StringView arg_name;
+              if (fuchsia_trace_utils::IsInlineString(arg_name_ref)) {
+                arg_name = fuchsia_trace_utils::ReadInlineString(&current,
+                                                                 arg_name_ref);
+              } else {
+                arg_name = storage->GetString(
+                    current_provider_->string_table[arg_name_ref]);
+              }
+
+              if (arg_name == "process") {
+                pid = *current++;
+              }
+            }
+
+            current = arg_base + arg_size;
+          }
+
+          pid_table_[obj_id] = pid;
+
+          UniqueTid utid = procs->UpdateThread(static_cast<uint32_t>(obj_id),
+                                               static_cast<uint32_t>(pid));
+          storage->GetMutableThread(utid)->name_id = name;
+          break;
+        }
+        default: {
+          PERFETTO_DLOG("Skipping Kernel Object record with type %d", obj_type);
+          break;
+        }
+      }
+      break;
+    }
+    case kContextSwitch: {
+      // Context switch records come in order, so they do not need to go through
+      // TraceSorter.
+      uint32_t cpu = fuchsia_trace_utils::ReadField<uint32_t>(header, 16, 23);
+      uint32_t outgoing_state =
+          fuchsia_trace_utils::ReadField<uint32_t>(header, 24, 27);
+      uint32_t outgoing_thread_ref =
+          fuchsia_trace_utils::ReadField<uint32_t>(header, 28, 35);
+      uint32_t incoming_thread_ref =
+          fuchsia_trace_utils::ReadField<uint32_t>(header, 36, 43);
+      int32_t outgoing_priority =
+          fuchsia_trace_utils::ReadField<int32_t>(header, 44, 51);
+
+      uint64_t ticks = record[1];
+      int64_t ts = fuchsia_trace_utils::TicksToNs(
+          ticks, current_provider_->ticks_per_second);
+
+      const uint64_t* current = &record[2];
+
+      fuchsia_trace_utils::ThreadInfo outgoing_thread;
+      if (fuchsia_trace_utils::IsInlineThread(outgoing_thread_ref)) {
+        outgoing_thread = fuchsia_trace_utils::ReadInlineThread(&current);
+      } else {
+        outgoing_thread = current_provider_->thread_table[outgoing_thread_ref];
+      }
+
+      fuchsia_trace_utils::ThreadInfo incoming_thread;
+      if (fuchsia_trace_utils::IsInlineThread(incoming_thread_ref)) {
+        incoming_thread = fuchsia_trace_utils::ReadInlineThread(&current);
+      } else {
+        incoming_thread = current_provider_->thread_table[incoming_thread_ref];
+      }
+
+      // A thread with priority 0 represents an idle CPU
+      if (cpu_threads_.count(cpu) != 0 && outgoing_priority != 0) {
+        // TODO(bhamrick): Some early events will fail to associate with their
+        // pid because the kernel object info event hasn't been processed yet.
+        if (pid_table_.count(outgoing_thread.tid) > 0) {
+          outgoing_thread.pid = pid_table_[outgoing_thread.tid];
+        }
+
+        UniqueTid utid =
+            procs->UpdateThread(static_cast<uint32_t>(outgoing_thread.tid),
+                                static_cast<uint32_t>(outgoing_thread.pid));
+        RunningThread previous_thread = cpu_threads_[cpu];
+
+        ftrace_utils::TaskState end_state;
+        switch (outgoing_state) {
+          case kThreadNew:
+          case kThreadRunning: {
+            end_state =
+                ftrace_utils::TaskState(ftrace_utils::TaskState::kRunnable);
+            break;
+          }
+          case kThreadBlocked: {
+            end_state = ftrace_utils::TaskState(
+                ftrace_utils::TaskState::kInterruptibleSleep);
+            break;
+          }
+          case kThreadSuspended: {
+            end_state =
+                ftrace_utils::TaskState(ftrace_utils::TaskState::kStopped);
+            break;
+          }
+          case kThreadDying: {
+            end_state =
+                ftrace_utils::TaskState(ftrace_utils::TaskState::kExitZombie);
+            break;
+          }
+          case kThreadDead: {
+            end_state =
+                ftrace_utils::TaskState(ftrace_utils::TaskState::kExitDead);
+            break;
+          }
+          default: { break; }
+        }
+
+        storage->mutable_slices()->AddSlice(cpu, previous_thread.start_ts,
+                                            ts - previous_thread.start_ts, utid,
+                                            end_state, outgoing_priority);
+      }
+
+      RunningThread new_running;
+      new_running.info = incoming_thread;
+      new_running.start_ts = ts;
+      cpu_threads_[cpu] = new_running;
+      break;
+    }
+    default: {
+      PERFETTO_DLOG("Skipping record of unknown type %d", record_type);
+      break;
+    }
+  }
+}
+
+void FuchsiaTraceTokenizer::RegisterProvider(uint32_t provider_id,
+                                             std::string name) {
+  std::unique_ptr<ProviderInfo> provider(new ProviderInfo());
+  provider->name = name;
+  current_provider_ = provider.get();
+  providers_[provider_id] = std::move(provider);
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/fuchsia_trace_tokenizer.h b/src/trace_processor/fuchsia_trace_tokenizer.h
new file mode 100644
index 0000000..9f5bad9
--- /dev/null
+++ b/src/trace_processor/fuchsia_trace_tokenizer.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_FUCHSIA_TRACE_TOKENIZER_H_
+#define SRC_TRACE_PROCESSOR_FUCHSIA_TRACE_TOKENIZER_H_
+
+#include "src/trace_processor/chunked_trace_reader.h"
+#include "src/trace_processor/fuchsia_trace_utils.h"
+#include "src/trace_processor/trace_blob_view.h"
+#include "src/trace_processor/trace_storage.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class TraceProcessorContext;
+
+// The Fuchsia trace format is documented at
+// https://fuchsia.googlesource.com/fuchsia/+/HEAD/docs/development/tracing/trace-format/README.md
+class FuchsiaTraceTokenizer : public ChunkedTraceReader {
+ public:
+  explicit FuchsiaTraceTokenizer(TraceProcessorContext*);
+  ~FuchsiaTraceTokenizer() override;
+
+  // ChunkedTraceReader implementation
+  bool Parse(std::unique_ptr<uint8_t[]>, size_t) override;
+
+ private:
+  struct ProviderInfo {
+    std::string name;
+
+    std::unordered_map<uint64_t, StringId> string_table;
+    std::unordered_map<uint64_t, fuchsia_trace_utils::ThreadInfo> thread_table;
+
+    uint64_t ticks_per_second = 1000000000;
+  };
+
+  struct RunningThread {
+    fuchsia_trace_utils::ThreadInfo info;
+    int64_t start_ts;
+  };
+
+  void ParseRecord(TraceBlobView);
+  void RegisterProvider(uint32_t, std::string);
+
+  TraceProcessorContext* const context_;
+  std::vector<uint8_t> leftover_bytes_;
+
+  // Map from tid to pid. Used because in some places we do not get pid info.
+  // Fuchsia tids are never reused.
+  std::unordered_map<uint64_t, uint64_t> pid_table_;
+  std::unordered_map<uint32_t, std::unique_ptr<ProviderInfo>> providers_;
+  ProviderInfo* current_provider_;
+
+  std::unordered_map<uint32_t, RunningThread> cpu_threads_;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_FUCHSIA_TRACE_TOKENIZER_H_
diff --git a/src/trace_processor/fuchsia_trace_utils.cc b/src/trace_processor/fuchsia_trace_utils.cc
new file mode 100644
index 0000000..7f012f9
--- /dev/null
+++ b/src/trace_processor/fuchsia_trace_utils.cc
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 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 "src/trace_processor/fuchsia_trace_utils.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace fuchsia_trace_utils {
+
+namespace {
+constexpr uint32_t kInlineStringMarker = 0x8000;
+constexpr uint32_t kInlineStringLengthMask = 0x7FFF;
+}  // namespace
+
+bool IsInlineString(uint32_t string_ref) {
+  // Treat a string ref of 0 (the empty string) as inline. The empty string is
+  // not a true entry in the string table.
+  return (string_ref & kInlineStringMarker) || (string_ref == 0);
+}
+
+base::StringView ReadInlineString(const uint64_t** current_ptr,
+                                  uint32_t string_ref) {
+  // Note that this works correctly for the empty string, where string_ref is 0.
+  size_t len = string_ref & kInlineStringLengthMask;
+  size_t len_words = (len + 7) / 8;
+  base::StringView s(reinterpret_cast<const char*>(*current_ptr), len);
+  *current_ptr += len_words;
+  return s;
+}
+
+bool IsInlineThread(uint32_t thread_ref) {
+  return thread_ref == 0;
+}
+
+ThreadInfo ReadInlineThread(const uint64_t** current_ptr) {
+  ThreadInfo ret;
+  ret.pid = **current_ptr;
+  (*current_ptr)++;
+  ret.tid = **current_ptr;
+  (*current_ptr)++;
+  return ret;
+}
+
+int64_t ReadTimestamp(const uint64_t** current_ptr, uint64_t ticks_per_second) {
+  uint64_t ticks = **current_ptr;
+  (*current_ptr)++;
+  return TicksToNs(ticks, ticks_per_second);
+}
+
+int64_t TicksToNs(uint64_t ticks, uint64_t ticks_per_second) {
+  return static_cast<int64_t>(ticks * uint64_t(1000000000) / ticks_per_second);
+}
+
+}  // namespace fuchsia_trace_utils
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/fuchsia_trace_utils.h b/src/trace_processor/fuchsia_trace_utils.h
new file mode 100644
index 0000000..21d3a70
--- /dev/null
+++ b/src/trace_processor/fuchsia_trace_utils.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_FUCHSIA_TRACE_UTILS_H_
+#define SRC_TRACE_PROCESSOR_FUCHSIA_TRACE_UTILS_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <functional>
+
+#include "perfetto/base/string_view.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace fuchsia_trace_utils {
+
+struct ThreadInfo {
+  uint64_t pid;
+  uint64_t tid;
+};
+
+template <class T>
+T ReadField(uint64_t word, size_t begin, size_t end) {
+  return static_cast<T>((word >> begin) &
+                        ((uint64_t(1) << (end - begin + 1)) - 1));
+}
+
+bool IsInlineString(uint32_t);
+base::StringView ReadInlineString(const uint64_t**, uint32_t);
+
+bool IsInlineThread(uint32_t);
+ThreadInfo ReadInlineThread(const uint64_t**);
+
+int64_t ReadTimestamp(const uint64_t**, uint64_t);
+int64_t TicksToNs(uint64_t ticks, uint64_t ticks_per_second);
+
+}  // namespace fuchsia_trace_utils
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_FUCHSIA_TRACE_UTILS_H_
diff --git a/src/trace_processor/gzip_trace_parser.cc b/src/trace_processor/gzip_trace_parser.cc
deleted file mode 100644
index 4dfce0b..0000000
--- a/src/trace_processor/gzip_trace_parser.cc
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/gzip_trace_parser.h"
-
-#include <string>
-
-#include <zlib.h>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/string_view.h"
-#include "src/trace_processor/forwarding_trace_parser.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-GzipTraceParser::GzipTraceParser(TraceProcessorContext* context)
-    : context_(context), z_stream_(new z_stream()) {
-  z_stream_->zalloc = Z_NULL;
-  z_stream_->zfree = Z_NULL;
-  z_stream_->opaque = Z_NULL;
-  inflateInit2(z_stream_.get(), 32 + 15);
-}
-
-GzipTraceParser::~GzipTraceParser() {
-  // Ensure the call to inflateEnd to prevent leaks of internal state.
-  inflateEnd(z_stream_.get());
-}
-
-util::Status GzipTraceParser::Parse(std::unique_ptr<uint8_t[]> data,
-                                    size_t size) {
-  uint8_t* start = data.get();
-  size_t len = size;
-
-  if (!inner_) {
-    inner_.reset(new ForwardingTraceParser(context_));
-
-    // .ctrace files begin with: "TRACE:\n" or "done. TRACE:\n" strip this if
-    // present.
-    base::StringView beginning(reinterpret_cast<char*>(start), size);
-
-    static const char* kSystraceFileHeader = "TRACE:\n";
-    size_t offset = Find(kSystraceFileHeader, beginning);
-    if (offset != std::string::npos) {
-      start += strlen(kSystraceFileHeader) + offset;
-      len -= strlen(kSystraceFileHeader) + offset;
-    }
-  }
-
-  z_stream_->next_in = start;
-  z_stream_->avail_in = static_cast<uInt>(len);
-
-  // Our default uncompressed buffer size is 32MB as it allows for good
-  // throughput.
-  constexpr size_t kUncompressedBufferSize = 32 * 1024 * 1024;
-  int ret = Z_OK;
-  for (; ret != Z_STREAM_END && z_stream_->avail_in != 0;) {
-    std::unique_ptr<uint8_t[]> buffer(new uint8_t[kUncompressedBufferSize]);
-    z_stream_->next_out = buffer.get();
-    z_stream_->avail_out = static_cast<uInt>(kUncompressedBufferSize);
-
-    ret = inflate(z_stream_.get(), Z_NO_FLUSH);
-    switch (ret) {
-      case Z_NEED_DICT:
-      case Z_DATA_ERROR:
-      case Z_MEM_ERROR:
-        // Ignore inflateEnd error as we will error out anyway.
-        inflateEnd(z_stream_.get());
-        return util::ErrStatus("Error decompressing ctrace file");
-    }
-
-    size_t read = kUncompressedBufferSize - z_stream_->avail_out;
-    util::Status status = inner_->Parse(std::move(buffer), read);
-    if (!status.ok())
-      return status;
-  }
-  if (ret == Z_STREAM_END) {
-    ret = inflateEnd(z_stream_.get());
-    if (ret == Z_STREAM_ERROR)
-      return util::ErrStatus("Error finishing decompression");
-  }
-  return util::OkStatus();
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/gzip_trace_parser.h b/src/trace_processor/gzip_trace_parser.h
deleted file mode 100644
index a129c4b..0000000
--- a/src/trace_processor/gzip_trace_parser.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_GZIP_TRACE_PARSER_H_
-#define SRC_TRACE_PROCESSOR_GZIP_TRACE_PARSER_H_
-
-#include "src/trace_processor/chunked_trace_reader.h"
-
-struct z_stream_s;
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-class GzipTraceParser : public ChunkedTraceReader {
- public:
-  explicit GzipTraceParser(TraceProcessorContext*);
-  ~GzipTraceParser() override;
-
-  // ChunkedTraceReader implementation
-  util::Status Parse(std::unique_ptr<uint8_t[]>, size_t) override;
-
- private:
-  TraceProcessorContext* const context_;
-  std::unique_ptr<z_stream_s> z_stream_;
-  std::unique_ptr<ChunkedTraceReader> inner_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_GZIP_TRACE_PARSER_H_
diff --git a/src/trace_processor/heap_profile_allocation_table.cc b/src/trace_processor/heap_profile_allocation_table.cc
deleted file mode 100644
index dcdb825..0000000
--- a/src/trace_processor/heap_profile_allocation_table.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/heap_profile_allocation_table.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-HeapProfileAllocationTable::HeapProfileAllocationTable(
-    sqlite3*,
-    const TraceStorage* storage)
-    : storage_(storage) {}
-
-void HeapProfileAllocationTable::RegisterTable(sqlite3* db,
-                                               const TraceStorage* storage) {
-  SqliteTable::Register<HeapProfileAllocationTable>(db, storage,
-                                                    "heap_profile_allocation");
-}
-
-StorageSchema HeapProfileAllocationTable::CreateStorageSchema() {
-  const auto& allocs = storage_->heap_profile_allocations();
-  return StorageSchema::Builder()
-      .AddGenericNumericColumn("id", RowAccessor())
-      .AddOrderedNumericColumn("ts", &allocs.timestamps())
-      .AddNumericColumn("upid", &allocs.upids())
-      .AddNumericColumn("callsite_id", &allocs.callsite_ids())
-      .AddNumericColumn("count", &allocs.counts())
-      .AddNumericColumn("size", &allocs.sizes())
-      .Build({"id"});
-}
-
-uint32_t HeapProfileAllocationTable::RowCount() {
-  return storage_->heap_profile_allocations().size();
-}
-
-int HeapProfileAllocationTable::BestIndex(const QueryConstraints& qc,
-                                          BestIndexInfo* info) {
-  info->sqlite_omit_order_by = true;
-  info->estimated_cost = HasEqConstraint(qc, "id") ? 1 : RowCount();
-  return SQLITE_OK;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/heap_profile_allocation_table.h b/src/trace_processor/heap_profile_allocation_table.h
deleted file mode 100644
index 9f7fd44..0000000
--- a/src/trace_processor/heap_profile_allocation_table.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_HEAP_PROFILE_ALLOCATION_TABLE_H_
-#define SRC_TRACE_PROCESSOR_HEAP_PROFILE_ALLOCATION_TABLE_H_
-
-#include "src/trace_processor/storage_table.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class HeapProfileAllocationTable : public StorageTable {
- public:
-  static void RegisterTable(sqlite3* db, const TraceStorage* storage);
-
-  HeapProfileAllocationTable(sqlite3*, const TraceStorage*);
-
-  // StorageTable implementation.
-  StorageSchema CreateStorageSchema() override;
-  uint32_t RowCount() override;
-  int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
-
- private:
-  const TraceStorage* const storage_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_HEAP_PROFILE_ALLOCATION_TABLE_H_
diff --git a/src/trace_processor/heap_profile_tracker.cc b/src/trace_processor/heap_profile_tracker.cc
index bcf85af..f1999aa 100644
--- a/src/trace_processor/heap_profile_tracker.cc
+++ b/src/trace_processor/heap_profile_tracker.cc
@@ -16,7 +16,6 @@
 
 #include "src/trace_processor/heap_profile_tracker.h"
 
-#include "src/trace_processor/process_tracker.h"
 #include "src/trace_processor/trace_processor_context.h"
 
 #include "perfetto/base/logging.h"
@@ -29,89 +28,174 @@
 
 HeapProfileTracker::~HeapProfileTracker() = default;
 
-void HeapProfileTracker::SetProfilePacketIndex(uint64_t index) {
-  if (last_profile_packet_index_ != 0 &&
-      last_profile_packet_index_ + 1 != index) {
-    context_->storage->IncrementStats(stats::heapprofd_missing_packet);
-  }
-  last_profile_packet_index_ = index;
+void HeapProfileTracker::AddString(ProfileIndex pidx,
+                                   SourceStringId id,
+                                   StringId str) {
+  string_map_.emplace(std::make_pair(pidx, id), str);
 }
 
-void HeapProfileTracker::AddAllocation(
-    StackProfileTracker* stack_profile_tracker,
-    const SourceAllocation& alloc,
-    const StackProfileTracker::InternLookup* intern_lookup) {
-  auto maybe_callstack_id =
-      stack_profile_tracker->FindCallstack(alloc.callstack_id, intern_lookup);
-  if (!maybe_callstack_id)
+void HeapProfileTracker::AddMapping(ProfileIndex pidx,
+                                    SourceMappingId id,
+                                    const SourceMapping& mapping) {
+  auto opt_name_id = FindString(pidx, mapping.name_id);
+  if (!opt_name_id)
     return;
+  const StringId name_id = opt_name_id.value();
 
-  int64_t callstack_id = *maybe_callstack_id;
+  auto opt_build_id = FindString(pidx, mapping.build_id);
+  if (!opt_build_id)
+    return;
+  const StringId build_id = opt_build_id.value();
 
-  UniquePid upid = context_->process_tracker->GetOrCreateProcess(
-      static_cast<uint32_t>(alloc.pid));
+  TraceStorage::HeapProfileMappings::Row row{
+      build_id,
+      static_cast<int64_t>(mapping.offset),
+      static_cast<int64_t>(mapping.start),
+      static_cast<int64_t>(mapping.end),
+      static_cast<int64_t>(mapping.load_bias),
+      name_id};
+
+  int64_t cur_row;
+  auto it = mapping_idx_.find(row);
+  if (it != mapping_idx_.end()) {
+    cur_row = it->second;
+  } else {
+    cur_row = context_->storage->mutable_heap_profile_mappings()->Insert(row);
+    mapping_idx_.emplace(row, cur_row);
+  }
+  mappings_.emplace(std::make_pair(pidx, id), cur_row);
+}
+
+void HeapProfileTracker::AddFrame(ProfileIndex pidx,
+                                  SourceFrameId id,
+                                  const SourceFrame& frame) {
+  auto opt_str_id = FindString(pidx, frame.name_id);
+  if (!opt_str_id)
+    return;
+  const StringId& str_id = opt_str_id.value();
+
+  auto mapping_it = mappings_.find({pidx, frame.mapping_id});
+  if (mapping_it == mappings_.end()) {
+    context_->storage->IncrementStats(stats::heapprofd_invalid_mapping_id);
+    PERFETTO_DFATAL("Invalid mapping.");
+    return;
+  }
+  int64_t mapping_row = mapping_it->second;
+
+  TraceStorage::HeapProfileFrames::Row row{str_id, mapping_row,
+                                           static_cast<int64_t>(frame.rel_pc)};
+
+  int64_t cur_row;
+  auto it = frame_idx_.find(row);
+  if (it != frame_idx_.end()) {
+    cur_row = it->second;
+  } else {
+    cur_row = context_->storage->mutable_heap_profile_frames()->Insert(row);
+    frame_idx_.emplace(row, cur_row);
+  }
+  frames_.emplace(std::make_pair(pidx, id), cur_row);
+}
+
+void HeapProfileTracker::AddCallstack(ProfileIndex pidx,
+                                      SourceCallstackId id,
+                                      const SourceCallstack& frame_ids) {
+  int64_t parent_id = 0;
+  for (size_t depth = 0; depth < frame_ids.size(); ++depth) {
+    std::vector<uint64_t> frame_subset = frame_ids;
+    frame_subset.resize(depth + 1);
+    auto self_it = callstacks_from_frames_.find({pidx, frame_subset});
+    if (self_it != callstacks_from_frames_.end()) {
+      parent_id = self_it->second;
+      continue;
+    }
+
+    uint64_t frame_id = frame_ids[depth];
+    auto it = frames_.find({pidx, frame_id});
+    if (it == frames_.end()) {
+      context_->storage->IncrementStats(stats::heapprofd_invalid_frame_id);
+      PERFETTO_DFATAL("Unknown frames.");
+      return;
+    }
+    int64_t frame_row = it->second;
+
+    TraceStorage::HeapProfileCallsites::Row row{static_cast<int64_t>(depth),
+                                                parent_id, frame_row};
+
+    int64_t self_id;
+    auto callsite_it = callsite_idx_.find(row);
+    if (callsite_it != callsite_idx_.end()) {
+      self_id = callsite_it->second;
+    } else {
+      self_id =
+          context_->storage->mutable_heap_profile_callsites()->Insert(row);
+      callsite_idx_.emplace(row, self_id);
+    }
+    parent_id = self_id;
+  }
+  callstacks_.emplace(std::make_pair(pidx, id), parent_id);
+}
+
+void HeapProfileTracker::AddAllocation(ProfileIndex pidx,
+                                       const SourceAllocation& alloc) {
+  auto it = callstacks_.find({pidx, alloc.callstack_id});
+  if (it == callstacks_.end()) {
+    context_->storage->IncrementStats(stats::heapprofd_invalid_callstack_id);
+    PERFETTO_DFATAL("Unknown callstack %" PRIu64 " : %zu", alloc.callstack_id,
+                    callstacks_.size());
+    return;
+  }
 
   TraceStorage::HeapProfileAllocations::Row alloc_row{
-      alloc.timestamp, upid, callstack_id,
-      static_cast<int64_t>(alloc.alloc_count),
+      static_cast<int64_t>(alloc.timestamp), static_cast<int64_t>(alloc.pid),
+      static_cast<int64_t>(it->second), static_cast<int64_t>(alloc.alloc_count),
       static_cast<int64_t>(alloc.self_allocated)};
 
   TraceStorage::HeapProfileAllocations::Row free_row{
-      alloc.timestamp, upid, callstack_id,
-      -static_cast<int64_t>(alloc.free_count),
+      static_cast<int64_t>(alloc.timestamp), static_cast<int64_t>(alloc.pid),
+      static_cast<int64_t>(it->second), -static_cast<int64_t>(alloc.free_count),
       -static_cast<int64_t>(alloc.self_freed)};
 
-  TraceStorage::HeapProfileAllocations::Row alloc_delta = alloc_row;
-  TraceStorage::HeapProfileAllocations::Row free_delta = free_row;
-
-  auto prev_alloc_it = prev_alloc_.find({upid, callstack_id});
-  if (prev_alloc_it == prev_alloc_.end()) {
-    std::tie(prev_alloc_it, std::ignore) =
-        prev_alloc_.emplace(std::make_pair(upid, callstack_id),
-                            TraceStorage::HeapProfileAllocations::Row{});
-  }
-
-  TraceStorage::HeapProfileAllocations::Row& prev_alloc = prev_alloc_it->second;
-  alloc_delta.count -= prev_alloc.count;
-  alloc_delta.size -= prev_alloc.size;
-
-  auto prev_free_it = prev_free_.find({upid, callstack_id});
-  if (prev_free_it == prev_free_.end()) {
-    std::tie(prev_free_it, std::ignore) =
-        prev_free_.emplace(std::make_pair(upid, callstack_id),
-                           TraceStorage::HeapProfileAllocations::Row{});
-  }
-
-  TraceStorage::HeapProfileAllocations::Row& prev_free = prev_free_it->second;
-  free_delta.count -= prev_free.count;
-  free_delta.size -= prev_free.size;
-
-  if (alloc_delta.count)
-    context_->storage->mutable_heap_profile_allocations()->Insert(alloc_delta);
-  if (free_delta.count)
-    context_->storage->mutable_heap_profile_allocations()->Insert(free_delta);
-
-  prev_alloc = alloc_row;
-  prev_free = free_row;
+  context_->storage->mutable_heap_profile_allocations()->Insert(alloc_row);
+  context_->storage->mutable_heap_profile_allocations()->Insert(free_row);
 }
 
-void HeapProfileTracker::StoreAllocation(SourceAllocation alloc) {
-  pending_allocs_.emplace_back(std::move(alloc));
+void HeapProfileTracker::StoreAllocation(ProfileIndex pidx,
+                                         SourceAllocation alloc) {
+  pending_allocs_.emplace_back(pidx, std::move(alloc));
 }
 
-void HeapProfileTracker::CommitAllocations(
-    StackProfileTracker* stack_profile_tracker,
-    const StackProfileTracker::InternLookup* intern_lookup) {
+void HeapProfileTracker::ApplyAllAllocations() {
   for (const auto& p : pending_allocs_)
-    AddAllocation(stack_profile_tracker, p, intern_lookup);
-  pending_allocs_.clear();
+    AddAllocation(p.first, p.second);
 }
 
-void HeapProfileTracker::FinalizeProfile(
-    StackProfileTracker* stack_profile_tracker,
-    const StackProfileTracker::InternLookup* intern_lookup) {
-  CommitAllocations(stack_profile_tracker, intern_lookup);
-  stack_profile_tracker->ClearIndices();
+int64_t HeapProfileTracker::GetDatabaseFrameIdForTesting(
+    ProfileIndex pidx,
+    SourceFrameId frame_id) {
+  auto it = frames_.find({pidx, frame_id});
+  if (it == frames_.end()) {
+    PERFETTO_DFATAL("Invalid frame.");
+    return -1;
+  }
+  return it->second;
+}
+
+base::Optional<StringId> HeapProfileTracker::FindString(ProfileIndex pidx,
+                                                        SourceStringId id) {
+  base::Optional<StringId> res;
+  if (id == 0) {
+    res = empty_;
+    return res;
+  }
+
+  auto it = string_map_.find({pidx, id});
+  if (it == string_map_.end()) {
+    context_->storage->IncrementStats(stats::heapprofd_invalid_string_id);
+    PERFETTO_DFATAL("Invalid string.");
+    return res;
+  }
+  res = it->second;
+  return res;
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/heap_profile_tracker.h b/src/trace_processor/heap_profile_tracker.h
index 8b3984f..eb1b40a 100644
--- a/src/trace_processor/heap_profile_tracker.h
+++ b/src/trace_processor/heap_profile_tracker.h
@@ -19,13 +19,35 @@
 
 #include <deque>
 
-#include "perfetto/ext/base/optional.h"
-
-#include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
-#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
-#include "src/trace_processor/stack_profile_tracker.h"
+#include "perfetto/trace/profiling/profile_packet.pbzero.h"
 #include "src/trace_processor/trace_storage.h"
 
+namespace std {
+
+template <>
+struct hash<std::pair<uint64_t, uint64_t>> {
+  using argument_type = std::pair<uint64_t, uint64_t>;
+  using result_type = size_t;
+
+  result_type operator()(const argument_type& p) const {
+    return std::hash<uint64_t>{}(p.first) ^ std::hash<uint64_t>{}(p.second);
+  }
+};
+
+template <>
+struct hash<std::pair<uint64_t, std::vector<uint64_t>>> {
+  using argument_type = std::pair<uint64_t, std::vector<uint64_t>>;
+  using result_type = size_t;
+
+  result_type operator()(const argument_type& p) const {
+    auto h = std::hash<uint64_t>{}(p.first);
+    for (auto v : p.second)
+      h = h ^ std::hash<uint64_t>{}(v);
+    return h;
+  }
+};
+
+}  // namespace std
 namespace perfetto {
 namespace trace_processor {
 
@@ -33,54 +55,81 @@
 
 class HeapProfileTracker {
  public:
+  // Not the same as ProfilePacket.index. This gets only gets incremented when
+  // encountering a ProfilePacket that is not continued.
+  // This namespaces all other Source*Ids.
+  using ProfileIndex = uint64_t;
+
+  using SourceStringId = uint64_t;
+
+  struct SourceMapping {
+    SourceStringId build_id = 0;
+    uint64_t offset = 0;
+    uint64_t start = 0;
+    uint64_t end = 0;
+    uint64_t load_bias = 0;
+    SourceStringId name_id = 0;
+  };
+  using SourceMappingId = uint64_t;
+
+  struct SourceFrame {
+    SourceStringId name_id = 0;
+    SourceMappingId mapping_id = 0;
+    uint64_t rel_pc = 0;
+  };
+  using SourceFrameId = uint64_t;
+
+  using SourceCallstack = std::vector<SourceFrameId>;
+  using SourceCallstackId = uint64_t;
+
   struct SourceAllocation {
     uint64_t pid = 0;
-    // This is int64_t, because we get this from the TraceSorter which also
-    // converts this for us.
-    int64_t timestamp = 0;
-    StackProfileTracker::SourceCallstackId callstack_id = 0;
+    uint64_t timestamp = 0;
+    SourceCallstackId callstack_id = 0;
     uint64_t self_allocated = 0;
     uint64_t self_freed = 0;
     uint64_t alloc_count = 0;
     uint64_t free_count = 0;
   };
 
-  void SetProfilePacketIndex(uint64_t id);
-
   explicit HeapProfileTracker(TraceProcessorContext* context);
 
-  void StoreAllocation(SourceAllocation);
+  void AddString(ProfileIndex, SourceStringId, StringId);
+  void AddMapping(ProfileIndex, SourceMappingId, const SourceMapping&);
+  void AddFrame(ProfileIndex, SourceFrameId, const SourceFrame&);
+  void AddCallstack(ProfileIndex, SourceCallstackId, const SourceCallstack&);
 
-  // Call after the last profile packet of a dump to commit the allocations
-  // that had been stored using StoreAllocation and clear internal indices
-  // for that dump.
-  void FinalizeProfile(StackProfileTracker* stack_profile_tracker,
-                       const StackProfileTracker::InternLookup* lookup);
+  void StoreAllocation(ProfileIndex, SourceAllocation);
+  void ApplyAllAllocations();
 
-  // Only commit the allocations that had been stored using StoreAllocations.
-  // This is only needed in tests, use FinalizeProfile instead.
-  void CommitAllocations(StackProfileTracker* stack_profile_tracker,
-                         const StackProfileTracker::InternLookup* lookup);
+  int64_t GetDatabaseFrameIdForTesting(ProfileIndex, SourceFrameId);
 
   ~HeapProfileTracker();
 
  private:
-  void AddAllocation(
-      StackProfileTracker* stack_profile_tracker,
-      const SourceAllocation&,
-      const StackProfileTracker::InternLookup* intern_lookup = nullptr);
+  void AddAllocation(ProfileIndex, const SourceAllocation&);
 
-  std::vector<SourceAllocation> pending_allocs_;
+  base::Optional<StringId> FindString(ProfileIndex, SourceStringId);
 
-  std::unordered_map<std::pair<UniquePid, int64_t>,
-                     TraceStorage::HeapProfileAllocations::Row>
-      prev_alloc_;
-  std::unordered_map<std::pair<UniquePid, int64_t>,
-                     TraceStorage::HeapProfileAllocations::Row>
-      prev_free_;
+  std::unordered_map<std::pair<ProfileIndex, SourceStringId>, StringId>
+      string_map_;
+  std::unordered_map<std::pair<ProfileIndex, SourceMappingId>, int64_t>
+      mappings_;
+  std::unordered_map<std::pair<ProfileIndex, SourceFrameId>, int64_t> frames_;
+  std::unordered_map<std::pair<ProfileIndex, SourceCallstack>, int64_t>
+      callstacks_from_frames_;
+  std::unordered_map<std::pair<ProfileIndex, SourceCallstackId>, int64_t>
+      callstacks_;
+
+  std::unordered_map<TraceStorage::HeapProfileMappings::Row, int64_t>
+      mapping_idx_;
+  std::unordered_map<TraceStorage::HeapProfileFrames::Row, int64_t> frame_idx_;
+  std::unordered_map<TraceStorage::HeapProfileCallsites::Row, int64_t>
+      callsite_idx_;
+
+  std::vector<std::pair<ProfileIndex, SourceAllocation>> pending_allocs_;
 
   TraceProcessorContext* const context_;
-  uint64_t last_profile_packet_index_ = 0;
   const StringId empty_;
 };
 
diff --git a/src/trace_processor/heap_profile_tracker_unittest.cc b/src/trace_processor/heap_profile_tracker_unittest.cc
index f503096..3e095be 100644
--- a/src/trace_processor/heap_profile_tracker_unittest.cc
+++ b/src/trace_processor/heap_profile_tracker_unittest.cc
@@ -16,38 +16,37 @@
 
 #include "src/trace_processor/heap_profile_tracker.h"
 
-#include "src/trace_processor/stack_profile_tracker.h"
 #include "src/trace_processor/trace_processor_context.h"
-#include "test/gtest_and_gmock.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace trace_processor {
 namespace {
 
-struct Packet {
-  uint32_t mapping_name_id;
-  uint32_t build_id;
-  uint32_t frame_name_id;
-  uint32_t mapping_id;
-  uint32_t frame_id;
-};
+constexpr auto kFirstPacket = 0;
+constexpr auto kFirstPacketMappingNameId = 1;
+constexpr auto kFirstPacketBuildId = 2;
+constexpr auto kFirstPacketFrameNameId = 3;
 
-constexpr Packet kFirstPacket{1, 2, 3, 1, 1};
-constexpr Packet kSecondPacket{3, 2, 1, 2, 2};
+constexpr auto kFirstPacketMappingId = 1;
+constexpr auto kFirstPacketFrameId = 1;
 
-constexpr auto kMappingExactOffset = 123;
-constexpr auto kMappingStartOffset = 1231;
+constexpr auto kSecondPacket = 1;
+constexpr auto kSecondPacketMappingNameId = 3;
+constexpr auto kSecondPacketBuildId = 2;
+constexpr auto kSecondPacketFrameNameId = 1;
+
+constexpr auto kSecondPacketFrameId = 2;
+constexpr auto kSecondPacketMappingId = 2;
+
+constexpr auto kMappingOffset = 123;
 constexpr auto kMappingStart = 234;
 constexpr auto kMappingEnd = 345;
 constexpr auto kMappingLoadBias = 456;
 
-// heapprofd on Android Q has large callstack ideas, explicitly test large
-// values.
-constexpr auto kCallstackId = 1ull << 34;
-
 static constexpr auto kFrameRelPc = 567;
-static constexpr char kBuildIDName[] = "[build id]";
-static constexpr char kBuildIDHexName[] = "5b6275696c642069645d";
 
 using ::testing::ElementsAre;
 
@@ -55,176 +54,149 @@
  public:
   HeapProfileTrackerDupTest() {
     context.storage.reset(new TraceStorage());
-    stack_profile_tracker.reset(new StackProfileTracker(&context));
     context.heap_profile_tracker.reset(new HeapProfileTracker(&context));
 
     mapping_name = context.storage->InternString("[mapping]");
-    fully_qualified_mapping_name = context.storage->InternString("/[mapping]");
-    build = context.storage->InternString(kBuildIDName);
+    build = context.storage->InternString("[build id]");
     frame_name = context.storage->InternString("[frame]");
   }
 
  protected:
-  void InsertMapping(const Packet& packet) {
-    stack_profile_tracker->AddString(packet.mapping_name_id, "[mapping]");
+  void InsertMapping() {
+    context.heap_profile_tracker->AddString(
+        kFirstPacket, kFirstPacketMappingNameId, mapping_name);
+    context.heap_profile_tracker->AddString(
+        kSecondPacket, kSecondPacketMappingNameId, mapping_name);
 
-    stack_profile_tracker->AddString(packet.build_id, kBuildIDName);
+    context.heap_profile_tracker->AddString(kFirstPacket, kFirstPacketBuildId,
+                                            build);
+    context.heap_profile_tracker->AddString(kSecondPacket, kSecondPacketBuildId,
+                                            build);
 
-    StackProfileTracker::SourceMapping first_frame;
-    first_frame.build_id = packet.build_id;
-    first_frame.exact_offset = kMappingExactOffset;
-    first_frame.start_offset = kMappingStartOffset;
+    HeapProfileTracker::SourceMapping first_frame;
+    first_frame.build_id = kFirstPacketBuildId;
+    first_frame.offset = kMappingOffset;
     first_frame.start = kMappingStart;
     first_frame.end = kMappingEnd;
     first_frame.load_bias = kMappingLoadBias;
-    first_frame.name_ids = {packet.mapping_name_id};
+    first_frame.name_id = kFirstPacketMappingNameId;
 
-    stack_profile_tracker->AddMapping(packet.mapping_id, first_frame);
+    HeapProfileTracker::SourceMapping second_frame;
+    second_frame.build_id = kSecondPacketBuildId;
+    second_frame.offset = kMappingOffset;
+    second_frame.start = kMappingStart;
+    second_frame.end = kMappingEnd;
+    second_frame.load_bias = kMappingLoadBias;
+    second_frame.name_id = kSecondPacketMappingNameId;
+
+    context.heap_profile_tracker->AddMapping(
+        kFirstPacket, kFirstPacketMappingId, first_frame);
+    context.heap_profile_tracker->AddMapping(
+        kSecondPacket, kSecondPacketMappingId, second_frame);
   }
 
-  void InsertFrame(const Packet& packet) {
-    InsertMapping(packet);
-    stack_profile_tracker->AddString(packet.frame_name_id, "[frame]");
+  void InsertFrame() {
+    InsertMapping();
+    context.heap_profile_tracker->AddString(
+        kFirstPacket, kFirstPacketFrameNameId, frame_name);
+    context.heap_profile_tracker->AddString(
+        kSecondPacket, kSecondPacketFrameNameId, frame_name);
 
-    StackProfileTracker::SourceFrame first_frame;
-    first_frame.name_id = packet.frame_name_id;
-    first_frame.mapping_id = packet.mapping_id;
+    HeapProfileTracker::SourceFrame first_frame;
+    first_frame.name_id = kFirstPacketFrameNameId;
+    first_frame.mapping_id = kFirstPacketMappingId;
     first_frame.rel_pc = kFrameRelPc;
 
-    stack_profile_tracker->AddFrame(packet.frame_id, first_frame);
+    HeapProfileTracker::SourceFrame second_frame;
+    second_frame.name_id = kSecondPacketFrameNameId;
+    second_frame.mapping_id = kSecondPacketMappingId;
+    second_frame.rel_pc = kFrameRelPc;
+
+    context.heap_profile_tracker->AddFrame(kFirstPacket, kFirstPacketFrameId,
+                                           first_frame);
+    context.heap_profile_tracker->AddFrame(kSecondPacket, kSecondPacketFrameId,
+                                           second_frame);
   }
 
-  void InsertCallsite(const Packet& packet) {
-    InsertFrame(packet);
+  void InsertCallsite() {
+    InsertFrame();
 
-    StackProfileTracker::SourceCallstack first_callsite = {packet.frame_id,
-                                                           packet.frame_id};
-    stack_profile_tracker->AddCallstack(kCallstackId, first_callsite);
+    HeapProfileTracker::SourceCallstack first_callsite = {kFirstPacketFrameId,
+                                                          kFirstPacketFrameId};
+    HeapProfileTracker::SourceCallstack second_callsite = {
+        kSecondPacketFrameId, kSecondPacketFrameId};
+
+    context.heap_profile_tracker->AddCallstack(kFirstPacket, 0, first_callsite);
+    context.heap_profile_tracker->AddCallstack(kSecondPacket, 0,
+                                               second_callsite);
   }
 
   StringId mapping_name;
-  StringId fully_qualified_mapping_name;
   StringId build;
   StringId frame_name;
   TraceProcessorContext context;
-  std::unique_ptr<StackProfileTracker> stack_profile_tracker;
 };
 
 // Insert the same mapping from two different packets, with different strings
 // interned, and assert we only store one.
 TEST_F(HeapProfileTrackerDupTest, Mapping) {
-  InsertMapping(kFirstPacket);
-  context.heap_profile_tracker->FinalizeProfile(stack_profile_tracker.get(),
-                                                nullptr);
-  InsertMapping(kSecondPacket);
-  context.heap_profile_tracker->FinalizeProfile(stack_profile_tracker.get(),
-                                                nullptr);
+  InsertMapping();
 
-  EXPECT_THAT(context.storage->stack_profile_mappings().build_ids(),
-              ElementsAre(context.storage->InternString({kBuildIDHexName})));
-  EXPECT_THAT(context.storage->stack_profile_mappings().exact_offsets(),
-              ElementsAre(kMappingExactOffset));
-  EXPECT_THAT(context.storage->stack_profile_mappings().start_offsets(),
-              ElementsAre(kMappingStartOffset));
-  EXPECT_THAT(context.storage->stack_profile_mappings().starts(),
+  EXPECT_THAT(context.storage->heap_profile_mappings().build_ids(),
+              ElementsAre(build));
+  EXPECT_THAT(context.storage->heap_profile_mappings().offsets(),
+              ElementsAre(kMappingOffset));
+  EXPECT_THAT(context.storage->heap_profile_mappings().starts(),
               ElementsAre(kMappingStart));
-  EXPECT_THAT(context.storage->stack_profile_mappings().ends(),
+  EXPECT_THAT(context.storage->heap_profile_mappings().ends(),
               ElementsAre(kMappingEnd));
-  EXPECT_THAT(context.storage->stack_profile_mappings().load_biases(),
+  EXPECT_THAT(context.storage->heap_profile_mappings().load_biases(),
               ElementsAre(kMappingLoadBias));
-  EXPECT_THAT(context.storage->stack_profile_mappings().names(),
-              ElementsAre(fully_qualified_mapping_name));
+  EXPECT_THAT(context.storage->heap_profile_mappings().names(),
+              ElementsAre(mapping_name));
 }
 
 // Insert the same mapping from two different packets, with different strings
 // interned, and assert we only store one.
 TEST_F(HeapProfileTrackerDupTest, Frame) {
-  InsertFrame(kFirstPacket);
-  context.heap_profile_tracker->FinalizeProfile(stack_profile_tracker.get(),
-                                                nullptr);
-  InsertFrame(kSecondPacket);
-  context.heap_profile_tracker->FinalizeProfile(stack_profile_tracker.get(),
-                                                nullptr);
+  InsertFrame();
 
-  EXPECT_THAT(context.storage->stack_profile_frames().names(),
+  EXPECT_THAT(context.storage->heap_profile_frames().names(),
               ElementsAre(frame_name));
-  EXPECT_THAT(context.storage->stack_profile_frames().mappings(),
+  EXPECT_THAT(context.storage->heap_profile_frames().mappings(),
               ElementsAre(0));
-  EXPECT_THAT(context.storage->stack_profile_frames().rel_pcs(),
+  EXPECT_THAT(context.storage->heap_profile_frames().rel_pcs(),
               ElementsAre(kFrameRelPc));
 }
 
 // Insert the same callstack from two different packets, assert it is only
 // stored once.
 TEST_F(HeapProfileTrackerDupTest, Callstack) {
-  InsertCallsite(kFirstPacket);
-  context.heap_profile_tracker->FinalizeProfile(stack_profile_tracker.get(),
-                                                nullptr);
-  InsertCallsite(kSecondPacket);
-  context.heap_profile_tracker->FinalizeProfile(stack_profile_tracker.get(),
-                                                nullptr);
+  InsertCallsite();
 
-  const auto& callsite_table = context.storage->stack_profile_callsite_table();
-  const auto& depth = callsite_table.depth();
-  const auto& parent_id = callsite_table.parent_id();
-  const auto& frame_id = callsite_table.frame_id();
-
-  EXPECT_EQ(depth[0], 0);
-  EXPECT_EQ(depth[1], 1);
-
-  EXPECT_EQ(parent_id[0], -1);
-  EXPECT_EQ(parent_id[1], 0);
-
-  EXPECT_EQ(frame_id[0], 0);
-  EXPECT_EQ(frame_id[1], 0);
+  EXPECT_THAT(context.storage->heap_profile_callsites().frame_depths(),
+              ElementsAre(0, 1));
+  EXPECT_THAT(context.storage->heap_profile_callsites().parent_callsite_ids(),
+              ElementsAre(0, 0));
+  EXPECT_THAT(context.storage->heap_profile_callsites().frame_ids(),
+              ElementsAre(0, 0));
 }
 
 int64_t FindCallstack(const TraceStorage& storage,
                       int64_t depth,
                       int64_t parent,
                       int64_t frame_id) {
-  const auto& callsites = storage.stack_profile_callsite_table();
-  for (uint32_t i = 0; i < callsites.size(); ++i) {
-    if (callsites.depth()[i] == depth && callsites.parent_id()[i] == parent &&
-        callsites.frame_id()[i] == frame_id) {
+  const auto& callsites = storage.heap_profile_callsites();
+  for (size_t i = 0; i < callsites.frame_depths().size(); ++i) {
+    if (callsites.frame_depths()[i] == depth &&
+        callsites.parent_callsite_ids()[i] == parent &&
+        callsites.frame_ids()[i] == frame_id) {
       return static_cast<int64_t>(i);
     }
   }
   return -1;
 }
 
-TEST(HeapProfileTrackerTest, SourceMappingPath) {
-  TraceProcessorContext context;
-  context.storage.reset(new TraceStorage());
-  context.heap_profile_tracker.reset(new HeapProfileTracker(&context));
-
-  HeapProfileTracker* hpt = context.heap_profile_tracker.get();
-  std::unique_ptr<StackProfileTracker> spt(new StackProfileTracker(&context));
-
-  constexpr auto kBuildId = 1u;
-  constexpr auto kMappingNameId1 = 2u;
-  constexpr auto kMappingNameId2 = 3u;
-
-  spt->AddString(kBuildId, "buildid");
-  spt->AddString(kMappingNameId1, "foo");
-  spt->AddString(kMappingNameId2, "bar");
-
-  StackProfileTracker::SourceMapping mapping;
-  mapping.build_id = kBuildId;
-  mapping.exact_offset = 1;
-  mapping.start_offset = 1;
-  mapping.start = 2;
-  mapping.end = 3;
-  mapping.load_bias = 0;
-  mapping.name_ids = {kMappingNameId1, kMappingNameId2};
-  spt->AddMapping(0, mapping);
-  hpt->CommitAllocations(spt.get(), nullptr);
-  auto foo_bar_id = context.storage->string_pool().GetId("/foo/bar");
-  ASSERT_NE(foo_bar_id, base::nullopt);
-  EXPECT_THAT(context.storage->stack_profile_mappings().names(),
-              ElementsAre(*foo_bar_id));
-}
-
 // Insert multiple mappings, frames and callstacks and check result.
 TEST(HeapProfileTrackerTest, Functional) {
   TraceProcessorContext context;
@@ -232,52 +204,49 @@
   context.heap_profile_tracker.reset(new HeapProfileTracker(&context));
 
   HeapProfileTracker* hpt = context.heap_profile_tracker.get();
-  std::unique_ptr<StackProfileTracker> spt(new StackProfileTracker(&context));
 
-  uint32_t next_string_intern_id = 1;
+  constexpr auto kPacket = 0;
+  uint64_t next_string_intern_id = 1;
 
   const std::string build_ids[] = {"build1", "build2", "build3"};
-  uint32_t build_id_ids[base::ArraySize(build_ids)];
+  uint64_t build_id_ids[base::ArraySize(build_ids)];
   for (size_t i = 0; i < base::ArraySize(build_ids); ++i)
     build_id_ids[i] = next_string_intern_id++;
 
   const std::string mapping_names[] = {"map1", "map2", "map3"};
-  uint32_t mapping_name_ids[base::ArraySize(mapping_names)];
+  uint64_t mapping_name_ids[base::ArraySize(mapping_names)];
   for (size_t i = 0; i < base::ArraySize(mapping_names); ++i)
     mapping_name_ids[i] = next_string_intern_id++;
 
-  StackProfileTracker::SourceMapping mappings[base::ArraySize(mapping_names)] =
+  HeapProfileTracker::SourceMapping mappings[base::ArraySize(mapping_names)] =
       {};
   mappings[0].build_id = build_id_ids[0];
-  mappings[0].exact_offset = 1;
-  mappings[0].start_offset = 1;
+  mappings[0].offset = 1;
   mappings[0].start = 2;
   mappings[0].end = 3;
   mappings[0].load_bias = 0;
-  mappings[0].name_ids = {mapping_name_ids[0], mapping_name_ids[1]};
+  mappings[0].name_id = mapping_name_ids[0];
 
   mappings[1].build_id = build_id_ids[1];
-  mappings[1].exact_offset = 1;
-  mappings[1].start_offset = 1;
+  mappings[1].offset = 1;
   mappings[1].start = 2;
   mappings[1].end = 3;
   mappings[1].load_bias = 1;
-  mappings[1].name_ids = {mapping_name_ids[1]};
+  mappings[1].name_id = mapping_name_ids[1];
 
   mappings[2].build_id = build_id_ids[2];
-  mappings[2].exact_offset = 1;
-  mappings[2].start_offset = 1;
+  mappings[2].offset = 1;
   mappings[2].start = 2;
   mappings[2].end = 3;
   mappings[2].load_bias = 2;
-  mappings[2].name_ids = {mapping_name_ids[2]};
+  mappings[2].name_id = mapping_name_ids[2];
 
   const std::string function_names[] = {"fun1", "fun2", "fun3", "fun4"};
-  uint32_t function_name_ids[base::ArraySize(function_names)];
+  uint64_t function_name_ids[base::ArraySize(function_names)];
   for (size_t i = 0; i < base::ArraySize(function_names); ++i)
     function_name_ids[i] = next_string_intern_id++;
 
-  StackProfileTracker::SourceFrame frames[base::ArraySize(function_names)];
+  HeapProfileTracker::SourceFrame frames[base::ArraySize(function_names)];
   frames[0].name_id = function_name_ids[0];
   frames[0].mapping_id = 0;
   frames[0].rel_pc = 123;
@@ -294,40 +263,40 @@
   frames[3].mapping_id = 2;
   frames[3].rel_pc = 123;
 
-  StackProfileTracker::SourceCallstack callstacks[3];
+  HeapProfileTracker::SourceCallstack callstacks[3];
   callstacks[0] = {2, 1, 0};
   callstacks[1] = {2, 1, 0, 1, 0};
   callstacks[2] = {0, 2, 0, 1, 2};
 
   for (size_t i = 0; i < base::ArraySize(build_ids); ++i) {
-    auto interned = base::StringView(build_ids[i].data(), build_ids[i].size());
-    spt->AddString(build_id_ids[i], interned);
+    auto interned = context.storage->InternString(
+        {build_ids[i].data(), build_ids[i].size()});
+    hpt->AddString(kPacket, build_id_ids[i], interned);
   }
   for (size_t i = 0; i < base::ArraySize(mapping_names); ++i) {
-    auto interned =
-        base::StringView(mapping_names[i].data(), mapping_names[i].size());
-    spt->AddString(mapping_name_ids[i], interned);
+    auto interned = context.storage->InternString(
+        {mapping_names[i].data(), mapping_names[i].size()});
+    hpt->AddString(kPacket, mapping_name_ids[i], interned);
   }
   for (size_t i = 0; i < base::ArraySize(function_names); ++i) {
-    auto interned =
-        base::StringView(function_names[i].data(), function_names[i].size());
-    spt->AddString(function_name_ids[i], interned);
+    auto interned = context.storage->InternString(
+        {function_names[i].data(), function_names[i].size()});
+    hpt->AddString(kPacket, function_name_ids[i], interned);
   }
 
-  for (uint32_t i = 0; i < base::ArraySize(mappings); ++i)
-    spt->AddMapping(i, mappings[i]);
-  for (uint32_t i = 0; i < base::ArraySize(frames); ++i)
-    spt->AddFrame(i, frames[i]);
-  for (uint32_t i = 0; i < base::ArraySize(callstacks); ++i)
-    spt->AddCallstack(i, callstacks[i]);
-
-  hpt->CommitAllocations(spt.get(), nullptr);
+  for (size_t i = 0; i < base::ArraySize(mappings); ++i)
+    hpt->AddMapping(kPacket, i, mappings[i]);
+  for (size_t i = 0; i < base::ArraySize(frames); ++i)
+    hpt->AddFrame(kPacket, i, frames[i]);
+  for (size_t i = 0; i < base::ArraySize(callstacks); ++i)
+    hpt->AddCallstack(kPacket, i, callstacks[i]);
 
   for (size_t i = 0; i < base::ArraySize(callstacks); ++i) {
-    int64_t parent = -1;
-    const StackProfileTracker::SourceCallstack& callstack = callstacks[i];
+    int64_t parent = 0;
+    const HeapProfileTracker::SourceCallstack& callstack = callstacks[i];
     for (size_t depth = 0; depth < callstack.size(); ++depth) {
-      auto frame_id = spt->GetDatabaseFrameIdForTesting(callstack[depth]);
+      auto frame_id =
+          hpt->GetDatabaseFrameIdForTesting(kPacket, callstack[depth]);
       ASSERT_NE(frame_id, -1);
       int64_t self = FindCallstack(
           *context.storage, static_cast<int64_t>(depth), parent, frame_id);
@@ -335,8 +304,6 @@
       parent = self;
     }
   }
-
-  hpt->FinalizeProfile(spt.get(), nullptr);
 }
 
 }  // namespace
diff --git a/src/trace_processor/importers/ftrace/ftrace_descriptors.cc b/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
deleted file mode 100644
index 4c49442..0000000
--- a/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
+++ /dev/null
@@ -1,3553 +0,0 @@
-// Autogenerated by:
-// ../../tools/ftrace_proto_gen/ftrace_descriptor_gen.cc
-// Do not edit.
-
-#include "src/trace_processor/importers/ftrace/ftrace_descriptors.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-std::array<MessageDescriptor, 333> descriptors{{
-    {nullptr, 0, {}},
-    {nullptr, 0, {}},
-    {nullptr, 0, {}},
-    {
-        "print",
-        2,
-        {
-            {},
-            {"ip", ProtoSchemaType::kUint64},
-            {"buf", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "sched_switch",
-        7,
-        {
-            {},
-            {"prev_comm", ProtoSchemaType::kString},
-            {"prev_pid", ProtoSchemaType::kInt32},
-            {"prev_prio", ProtoSchemaType::kInt32},
-            {"prev_state", ProtoSchemaType::kInt64},
-            {"next_comm", ProtoSchemaType::kString},
-            {"next_pid", ProtoSchemaType::kInt32},
-            {"next_prio", ProtoSchemaType::kInt32},
-        },
-    },
-    {nullptr, 0, {}},
-    {nullptr, 0, {}},
-    {nullptr, 0, {}},
-    {nullptr, 0, {}},
-    {nullptr, 0, {}},
-    {nullptr, 0, {}},
-    {
-        "cpu_frequency",
-        2,
-        {
-            {},
-            {"state", ProtoSchemaType::kUint32},
-            {"cpu_id", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "cpu_frequency_limits",
-        3,
-        {
-            {},
-            {"min_freq", ProtoSchemaType::kUint32},
-            {"max_freq", ProtoSchemaType::kUint32},
-            {"cpu_id", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "cpu_idle",
-        2,
-        {
-            {},
-            {"state", ProtoSchemaType::kUint32},
-            {"cpu_id", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "clock_enable",
-        3,
-        {
-            {},
-            {"name", ProtoSchemaType::kString},
-            {"state", ProtoSchemaType::kUint64},
-            {"cpu_id", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "clock_disable",
-        3,
-        {
-            {},
-            {"name", ProtoSchemaType::kString},
-            {"state", ProtoSchemaType::kUint64},
-            {"cpu_id", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "clock_set_rate",
-        3,
-        {
-            {},
-            {"name", ProtoSchemaType::kString},
-            {"state", ProtoSchemaType::kUint64},
-            {"cpu_id", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "sched_wakeup",
-        5,
-        {
-            {},
-            {"comm", ProtoSchemaType::kString},
-            {"pid", ProtoSchemaType::kInt32},
-            {"prio", ProtoSchemaType::kInt32},
-            {"success", ProtoSchemaType::kInt32},
-            {"target_cpu", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "sched_blocked_reason",
-        3,
-        {
-            {},
-            {"pid", ProtoSchemaType::kInt32},
-            {"caller", ProtoSchemaType::kUint64},
-            {"io_wait", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "sched_cpu_hotplug",
-        3,
-        {
-            {},
-            {"affected_cpu", ProtoSchemaType::kInt32},
-            {"error", ProtoSchemaType::kInt32},
-            {"status", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "sched_waking",
-        5,
-        {
-            {},
-            {"comm", ProtoSchemaType::kString},
-            {"pid", ProtoSchemaType::kInt32},
-            {"prio", ProtoSchemaType::kInt32},
-            {"success", ProtoSchemaType::kInt32},
-            {"target_cpu", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ipi_entry",
-        1,
-        {
-            {},
-            {"reason", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "ipi_exit",
-        1,
-        {
-            {},
-            {"reason", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "ipi_raise",
-        2,
-        {
-            {},
-            {"target_cpus", ProtoSchemaType::kUint32},
-            {"reason", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "softirq_entry",
-        1,
-        {
-            {},
-            {"vec", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "softirq_exit",
-        1,
-        {
-            {},
-            {"vec", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "softirq_raise",
-        1,
-        {
-            {},
-            {"vec", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "i2c_read",
-        5,
-        {
-            {},
-            {"adapter_nr", ProtoSchemaType::kInt32},
-            {"msg_nr", ProtoSchemaType::kUint32},
-            {"addr", ProtoSchemaType::kUint32},
-            {"flags", ProtoSchemaType::kUint32},
-            {"len", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "i2c_write",
-        6,
-        {
-            {},
-            {"adapter_nr", ProtoSchemaType::kInt32},
-            {"msg_nr", ProtoSchemaType::kUint32},
-            {"addr", ProtoSchemaType::kUint32},
-            {"flags", ProtoSchemaType::kUint32},
-            {"len", ProtoSchemaType::kUint32},
-            {"buf", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "i2c_result",
-        3,
-        {
-            {},
-            {"adapter_nr", ProtoSchemaType::kInt32},
-            {"nr_msgs", ProtoSchemaType::kUint32},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "i2c_reply",
-        6,
-        {
-            {},
-            {"adapter_nr", ProtoSchemaType::kInt32},
-            {"msg_nr", ProtoSchemaType::kUint32},
-            {"addr", ProtoSchemaType::kUint32},
-            {"flags", ProtoSchemaType::kUint32},
-            {"len", ProtoSchemaType::kUint32},
-            {"buf", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "smbus_read",
-        5,
-        {
-            {},
-            {"adapter_nr", ProtoSchemaType::kInt32},
-            {"flags", ProtoSchemaType::kUint32},
-            {"addr", ProtoSchemaType::kUint32},
-            {"command", ProtoSchemaType::kUint32},
-            {"protocol", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "smbus_write",
-        6,
-        {
-            {},
-            {"adapter_nr", ProtoSchemaType::kInt32},
-            {"addr", ProtoSchemaType::kUint32},
-            {"flags", ProtoSchemaType::kUint32},
-            {"command", ProtoSchemaType::kUint32},
-            {"len", ProtoSchemaType::kUint32},
-            {"protocol", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "smbus_result",
-        7,
-        {
-            {},
-            {"adapter_nr", ProtoSchemaType::kInt32},
-            {"addr", ProtoSchemaType::kUint32},
-            {"flags", ProtoSchemaType::kUint32},
-            {"read_write", ProtoSchemaType::kUint32},
-            {"command", ProtoSchemaType::kUint32},
-            {"res", ProtoSchemaType::kInt32},
-            {"protocol", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "smbus_reply",
-        6,
-        {
-            {},
-            {"adapter_nr", ProtoSchemaType::kInt32},
-            {"addr", ProtoSchemaType::kUint32},
-            {"flags", ProtoSchemaType::kUint32},
-            {"command", ProtoSchemaType::kUint32},
-            {"len", ProtoSchemaType::kUint32},
-            {"protocol", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "lowmemory_kill",
-        5,
-        {
-            {},
-            {"comm", ProtoSchemaType::kString},
-            {"pid", ProtoSchemaType::kInt32},
-            {"pagecache_size", ProtoSchemaType::kInt64},
-            {"pagecache_limit", ProtoSchemaType::kInt64},
-            {"free", ProtoSchemaType::kInt64},
-        },
-    },
-    {
-        "irq_handler_entry",
-        3,
-        {
-            {},
-            {"irq", ProtoSchemaType::kInt32},
-            {"name", ProtoSchemaType::kString},
-            {"handler", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "irq_handler_exit",
-        2,
-        {
-            {},
-            {"irq", ProtoSchemaType::kInt32},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "sync_pt",
-        2,
-        {
-            {},
-            {"timeline", ProtoSchemaType::kString},
-            {"value", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "sync_timeline",
-        2,
-        {
-            {},
-            {"name", ProtoSchemaType::kString},
-            {"value", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "sync_wait",
-        3,
-        {
-            {},
-            {"name", ProtoSchemaType::kString},
-            {"status", ProtoSchemaType::kInt32},
-            {"begin", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_da_write_begin",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pos", ProtoSchemaType::kInt64},
-            {"len", ProtoSchemaType::kUint32},
-            {"flags", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_da_write_end",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pos", ProtoSchemaType::kInt64},
-            {"len", ProtoSchemaType::kUint32},
-            {"copied", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_sync_file_enter",
-        4,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"parent", ProtoSchemaType::kUint64},
-            {"datasync", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_sync_file_exit",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "block_rq_issue",
-        7,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"sector", ProtoSchemaType::kUint64},
-            {"nr_sector", ProtoSchemaType::kUint32},
-            {"bytes", ProtoSchemaType::kUint32},
-            {"rwbs", ProtoSchemaType::kString},
-            {"comm", ProtoSchemaType::kString},
-            {"cmd", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "mm_vmscan_direct_reclaim_begin",
-        3,
-        {
-            {},
-            {"order", ProtoSchemaType::kInt32},
-            {"may_writepage", ProtoSchemaType::kInt32},
-            {"gfp_flags", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "mm_vmscan_direct_reclaim_end",
-        1,
-        {
-            {},
-            {"nr_reclaimed", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "mm_vmscan_kswapd_wake",
-        2,
-        {
-            {},
-            {"nid", ProtoSchemaType::kInt32},
-            {"order", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "mm_vmscan_kswapd_sleep",
-        1,
-        {
-            {},
-            {"nid", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "binder_transaction",
-        7,
-        {
-            {},
-            {"debug_id", ProtoSchemaType::kInt32},
-            {"target_node", ProtoSchemaType::kInt32},
-            {"to_proc", ProtoSchemaType::kInt32},
-            {"to_thread", ProtoSchemaType::kInt32},
-            {"reply", ProtoSchemaType::kInt32},
-            {"code", ProtoSchemaType::kUint32},
-            {"flags", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "binder_transaction_received",
-        1,
-        {
-            {},
-            {"debug_id", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "binder_set_priority",
-        5,
-        {
-            {},
-            {"proc", ProtoSchemaType::kInt32},
-            {"thread", ProtoSchemaType::kInt32},
-            {"old_prio", ProtoSchemaType::kUint32},
-            {"new_prio", ProtoSchemaType::kUint32},
-            {"desired_prio", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "binder_lock",
-        1,
-        {
-            {},
-            {"tag", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "binder_locked",
-        1,
-        {
-            {},
-            {"tag", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "binder_unlock",
-        1,
-        {
-            {},
-            {"tag", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "workqueue_activate_work",
-        1,
-        {
-            {},
-            {"work", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "workqueue_execute_end",
-        1,
-        {
-            {},
-            {"work", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "workqueue_execute_start",
-        2,
-        {
-            {},
-            {"work", ProtoSchemaType::kUint64},
-            {"function", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "workqueue_queue_work",
-        5,
-        {
-            {},
-            {"work", ProtoSchemaType::kUint64},
-            {"function", ProtoSchemaType::kUint64},
-            {"workqueue", ProtoSchemaType::kUint64},
-            {"req_cpu", ProtoSchemaType::kUint32},
-            {"cpu", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "regulator_disable",
-        1,
-        {
-            {},
-            {"name", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "regulator_disable_complete",
-        1,
-        {
-            {},
-            {"name", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "regulator_enable",
-        1,
-        {
-            {},
-            {"name", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "regulator_enable_complete",
-        1,
-        {
-            {},
-            {"name", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "regulator_enable_delay",
-        1,
-        {
-            {},
-            {"name", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "regulator_set_voltage",
-        3,
-        {
-            {},
-            {"name", ProtoSchemaType::kString},
-            {"min", ProtoSchemaType::kInt32},
-            {"max", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "regulator_set_voltage_complete",
-        2,
-        {
-            {},
-            {"name", ProtoSchemaType::kString},
-            {"val", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "cgroup_attach_task",
-        5,
-        {
-            {},
-            {"dst_root", ProtoSchemaType::kInt32},
-            {"dst_id", ProtoSchemaType::kInt32},
-            {"pid", ProtoSchemaType::kInt32},
-            {"comm", ProtoSchemaType::kString},
-            {"cname", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "cgroup_mkdir",
-        3,
-        {
-            {},
-            {"root", ProtoSchemaType::kInt32},
-            {"id", ProtoSchemaType::kInt32},
-            {"cname", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "cgroup_remount",
-        3,
-        {
-            {},
-            {"root", ProtoSchemaType::kInt32},
-            {"ss_mask", ProtoSchemaType::kUint32},
-            {"name", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "cgroup_rmdir",
-        3,
-        {
-            {},
-            {"root", ProtoSchemaType::kInt32},
-            {"id", ProtoSchemaType::kInt32},
-            {"cname", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "cgroup_transfer_tasks",
-        5,
-        {
-            {},
-            {"dst_root", ProtoSchemaType::kInt32},
-            {"dst_id", ProtoSchemaType::kInt32},
-            {"pid", ProtoSchemaType::kInt32},
-            {"comm", ProtoSchemaType::kString},
-            {"cname", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "cgroup_destroy_root",
-        3,
-        {
-            {},
-            {"root", ProtoSchemaType::kInt32},
-            {"ss_mask", ProtoSchemaType::kUint32},
-            {"name", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "cgroup_release",
-        3,
-        {
-            {},
-            {"root", ProtoSchemaType::kInt32},
-            {"id", ProtoSchemaType::kInt32},
-            {"cname", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "cgroup_rename",
-        3,
-        {
-            {},
-            {"root", ProtoSchemaType::kInt32},
-            {"id", ProtoSchemaType::kInt32},
-            {"cname", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "cgroup_setup_root",
-        3,
-        {
-            {},
-            {"root", ProtoSchemaType::kInt32},
-            {"ss_mask", ProtoSchemaType::kUint32},
-            {"name", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "mdp_cmd_kickoff",
-        2,
-        {
-            {},
-            {"ctl_num", ProtoSchemaType::kUint32},
-            {"kickoff_cnt", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "mdp_commit",
-        4,
-        {
-            {},
-            {"num", ProtoSchemaType::kUint32},
-            {"play_cnt", ProtoSchemaType::kUint32},
-            {"clk_rate", ProtoSchemaType::kUint32},
-            {"bandwidth", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "mdp_perf_set_ot",
-        4,
-        {
-            {},
-            {"pnum", ProtoSchemaType::kUint32},
-            {"xin_id", ProtoSchemaType::kUint32},
-            {"rd_lim", ProtoSchemaType::kUint32},
-            {"is_vbif_rt", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "mdp_sspp_change",
-        16,
-        {
-            {},
-            {"num", ProtoSchemaType::kUint32},
-            {"play_cnt", ProtoSchemaType::kUint32},
-            {"mixer", ProtoSchemaType::kUint32},
-            {"stage", ProtoSchemaType::kUint32},
-            {"flags", ProtoSchemaType::kUint32},
-            {"format", ProtoSchemaType::kUint32},
-            {"img_w", ProtoSchemaType::kUint32},
-            {"img_h", ProtoSchemaType::kUint32},
-            {"src_x", ProtoSchemaType::kUint32},
-            {"src_y", ProtoSchemaType::kUint32},
-            {"src_w", ProtoSchemaType::kUint32},
-            {"src_h", ProtoSchemaType::kUint32},
-            {"dst_x", ProtoSchemaType::kUint32},
-            {"dst_y", ProtoSchemaType::kUint32},
-            {"dst_w", ProtoSchemaType::kUint32},
-            {"dst_h", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "tracing_mark_write",
-        3,
-        {
-            {},
-            {"pid", ProtoSchemaType::kInt32},
-            {"trace_name", ProtoSchemaType::kString},
-            {"trace_begin", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "mdp_cmd_pingpong_done",
-        4,
-        {
-            {},
-            {"ctl_num", ProtoSchemaType::kUint32},
-            {"intf_num", ProtoSchemaType::kUint32},
-            {"pp_num", ProtoSchemaType::kUint32},
-            {"koff_cnt", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "mdp_compare_bw",
-        8,
-        {
-            {},
-            {"new_ab", ProtoSchemaType::kUint64},
-            {"new_ib", ProtoSchemaType::kUint64},
-            {"new_wb", ProtoSchemaType::kUint64},
-            {"old_ab", ProtoSchemaType::kUint64},
-            {"old_ib", ProtoSchemaType::kUint64},
-            {"old_wb", ProtoSchemaType::kUint64},
-            {"params_changed", ProtoSchemaType::kUint32},
-            {"update_bw", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "mdp_perf_set_panic_luts",
-        5,
-        {
-            {},
-            {"pnum", ProtoSchemaType::kUint32},
-            {"fmt", ProtoSchemaType::kUint32},
-            {"mode", ProtoSchemaType::kUint32},
-            {"panic_lut", ProtoSchemaType::kUint32},
-            {"robust_lut", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "mdp_sspp_set",
-        16,
-        {
-            {},
-            {"num", ProtoSchemaType::kUint32},
-            {"play_cnt", ProtoSchemaType::kUint32},
-            {"mixer", ProtoSchemaType::kUint32},
-            {"stage", ProtoSchemaType::kUint32},
-            {"flags", ProtoSchemaType::kUint32},
-            {"format", ProtoSchemaType::kUint32},
-            {"img_w", ProtoSchemaType::kUint32},
-            {"img_h", ProtoSchemaType::kUint32},
-            {"src_x", ProtoSchemaType::kUint32},
-            {"src_y", ProtoSchemaType::kUint32},
-            {"src_w", ProtoSchemaType::kUint32},
-            {"src_h", ProtoSchemaType::kUint32},
-            {"dst_x", ProtoSchemaType::kUint32},
-            {"dst_y", ProtoSchemaType::kUint32},
-            {"dst_w", ProtoSchemaType::kUint32},
-            {"dst_h", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "mdp_cmd_readptr_done",
-        2,
-        {
-            {},
-            {"ctl_num", ProtoSchemaType::kUint32},
-            {"koff_cnt", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "mdp_misr_crc",
-        3,
-        {
-            {},
-            {"block_id", ProtoSchemaType::kUint32},
-            {"vsync_cnt", ProtoSchemaType::kUint32},
-            {"crc", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "mdp_perf_set_qos_luts",
-        7,
-        {
-            {},
-            {"pnum", ProtoSchemaType::kUint32},
-            {"fmt", ProtoSchemaType::kUint32},
-            {"intf", ProtoSchemaType::kUint32},
-            {"rot", ProtoSchemaType::kUint32},
-            {"fl", ProtoSchemaType::kUint32},
-            {"lut", ProtoSchemaType::kUint32},
-            {"linear", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "mdp_trace_counter",
-        3,
-        {
-            {},
-            {"pid", ProtoSchemaType::kInt32},
-            {"counter_name", ProtoSchemaType::kString},
-            {"value", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "mdp_cmd_release_bw",
-        1,
-        {
-            {},
-            {"ctl_num", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "mdp_mixer_update",
-        1,
-        {
-            {},
-            {"mixer_num", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "mdp_perf_set_wm_levels",
-        8,
-        {
-            {},
-            {"pnum", ProtoSchemaType::kUint32},
-            {"use_space", ProtoSchemaType::kUint32},
-            {"priority_bytes", ProtoSchemaType::kUint32},
-            {"wm0", ProtoSchemaType::kUint32},
-            {"wm1", ProtoSchemaType::kUint32},
-            {"wm2", ProtoSchemaType::kUint32},
-            {"mb_cnt", ProtoSchemaType::kUint32},
-            {"mb_size", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "mdp_video_underrun_done",
-        2,
-        {
-            {},
-            {"ctl_num", ProtoSchemaType::kUint32},
-            {"underrun_cnt", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "mdp_cmd_wait_pingpong",
-        2,
-        {
-            {},
-            {"ctl_num", ProtoSchemaType::kUint32},
-            {"kickoff_cnt", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "mdp_perf_prefill_calc",
-        10,
-        {
-            {},
-            {"pnum", ProtoSchemaType::kUint32},
-            {"latency_buf", ProtoSchemaType::kUint32},
-            {"ot", ProtoSchemaType::kUint32},
-            {"y_buf", ProtoSchemaType::kUint32},
-            {"y_scaler", ProtoSchemaType::kUint32},
-            {"pp_lines", ProtoSchemaType::kUint32},
-            {"pp_bytes", ProtoSchemaType::kUint32},
-            {"post_sc", ProtoSchemaType::kUint32},
-            {"fbc_bytes", ProtoSchemaType::kUint32},
-            {"prefill_bytes", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "mdp_perf_update_bus",
-        3,
-        {
-            {},
-            {"client", ProtoSchemaType::kInt32},
-            {"ab_quota", ProtoSchemaType::kUint64},
-            {"ib_quota", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "rotator_bw_ao_as_context",
-        1,
-        {
-            {},
-            {"state", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "mm_filemap_add_to_page_cache",
-        5,
-        {
-            {},
-            {"pfn", ProtoSchemaType::kUint64},
-            {"i_ino", ProtoSchemaType::kUint64},
-            {"index", ProtoSchemaType::kUint64},
-            {"s_dev", ProtoSchemaType::kUint64},
-            {"page", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "mm_filemap_delete_from_page_cache",
-        5,
-        {
-            {},
-            {"pfn", ProtoSchemaType::kUint64},
-            {"i_ino", ProtoSchemaType::kUint64},
-            {"index", ProtoSchemaType::kUint64},
-            {"s_dev", ProtoSchemaType::kUint64},
-            {"page", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "mm_compaction_begin",
-        5,
-        {
-            {},
-            {"zone_start", ProtoSchemaType::kUint64},
-            {"migrate_pfn", ProtoSchemaType::kUint64},
-            {"free_pfn", ProtoSchemaType::kUint64},
-            {"zone_end", ProtoSchemaType::kUint64},
-            {"sync", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "mm_compaction_defer_compaction",
-        6,
-        {
-            {},
-            {"nid", ProtoSchemaType::kInt32},
-            {"idx", ProtoSchemaType::kUint32},
-            {"order", ProtoSchemaType::kInt32},
-            {"considered", ProtoSchemaType::kUint32},
-            {"defer_shift", ProtoSchemaType::kUint32},
-            {"order_failed", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "mm_compaction_deferred",
-        6,
-        {
-            {},
-            {"nid", ProtoSchemaType::kInt32},
-            {"idx", ProtoSchemaType::kUint32},
-            {"order", ProtoSchemaType::kInt32},
-            {"considered", ProtoSchemaType::kUint32},
-            {"defer_shift", ProtoSchemaType::kUint32},
-            {"order_failed", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "mm_compaction_defer_reset",
-        6,
-        {
-            {},
-            {"nid", ProtoSchemaType::kInt32},
-            {"idx", ProtoSchemaType::kUint32},
-            {"order", ProtoSchemaType::kInt32},
-            {"considered", ProtoSchemaType::kUint32},
-            {"defer_shift", ProtoSchemaType::kUint32},
-            {"order_failed", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "mm_compaction_end",
-        6,
-        {
-            {},
-            {"zone_start", ProtoSchemaType::kUint64},
-            {"migrate_pfn", ProtoSchemaType::kUint64},
-            {"free_pfn", ProtoSchemaType::kUint64},
-            {"zone_end", ProtoSchemaType::kUint64},
-            {"sync", ProtoSchemaType::kUint32},
-            {"status", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "mm_compaction_finished",
-        4,
-        {
-            {},
-            {"nid", ProtoSchemaType::kInt32},
-            {"idx", ProtoSchemaType::kUint32},
-            {"order", ProtoSchemaType::kInt32},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "mm_compaction_isolate_freepages",
-        4,
-        {
-            {},
-            {"start_pfn", ProtoSchemaType::kUint64},
-            {"end_pfn", ProtoSchemaType::kUint64},
-            {"nr_scanned", ProtoSchemaType::kUint64},
-            {"nr_taken", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "mm_compaction_isolate_migratepages",
-        4,
-        {
-            {},
-            {"start_pfn", ProtoSchemaType::kUint64},
-            {"end_pfn", ProtoSchemaType::kUint64},
-            {"nr_scanned", ProtoSchemaType::kUint64},
-            {"nr_taken", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "mm_compaction_kcompactd_sleep",
-        1,
-        {
-            {},
-            {"nid", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "mm_compaction_kcompactd_wake",
-        3,
-        {
-            {},
-            {"nid", ProtoSchemaType::kInt32},
-            {"order", ProtoSchemaType::kInt32},
-            {"classzone_idx", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "mm_compaction_migratepages",
-        2,
-        {
-            {},
-            {"nr_migrated", ProtoSchemaType::kUint64},
-            {"nr_failed", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "mm_compaction_suitable",
-        4,
-        {
-            {},
-            {"nid", ProtoSchemaType::kInt32},
-            {"idx", ProtoSchemaType::kUint32},
-            {"order", ProtoSchemaType::kInt32},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "mm_compaction_try_to_compact_pages",
-        3,
-        {
-            {},
-            {"order", ProtoSchemaType::kInt32},
-            {"gfp_mask", ProtoSchemaType::kUint32},
-            {"mode", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "mm_compaction_wakeup_kcompactd",
-        3,
-        {
-            {},
-            {"nid", ProtoSchemaType::kInt32},
-            {"order", ProtoSchemaType::kInt32},
-            {"classzone_idx", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "suspend_resume",
-        3,
-        {
-            {},
-            {"action", ProtoSchemaType::kString},
-            {"val", ProtoSchemaType::kInt32},
-            {"start", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "sched_wakeup_new",
-        5,
-        {
-            {},
-            {"comm", ProtoSchemaType::kString},
-            {"pid", ProtoSchemaType::kInt32},
-            {"prio", ProtoSchemaType::kInt32},
-            {"success", ProtoSchemaType::kInt32},
-            {"target_cpu", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "block_bio_backmerge",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"sector", ProtoSchemaType::kUint64},
-            {"nr_sector", ProtoSchemaType::kUint32},
-            {"rwbs", ProtoSchemaType::kString},
-            {"comm", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "block_bio_bounce",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"sector", ProtoSchemaType::kUint64},
-            {"nr_sector", ProtoSchemaType::kUint32},
-            {"rwbs", ProtoSchemaType::kString},
-            {"comm", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "block_bio_complete",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"sector", ProtoSchemaType::kUint64},
-            {"nr_sector", ProtoSchemaType::kUint32},
-            {"error", ProtoSchemaType::kInt32},
-            {"rwbs", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "block_bio_frontmerge",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"sector", ProtoSchemaType::kUint64},
-            {"nr_sector", ProtoSchemaType::kUint32},
-            {"rwbs", ProtoSchemaType::kString},
-            {"comm", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "block_bio_queue",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"sector", ProtoSchemaType::kUint64},
-            {"nr_sector", ProtoSchemaType::kUint32},
-            {"rwbs", ProtoSchemaType::kString},
-            {"comm", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "block_bio_remap",
-        6,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"sector", ProtoSchemaType::kUint64},
-            {"nr_sector", ProtoSchemaType::kUint32},
-            {"old_dev", ProtoSchemaType::kUint64},
-            {"old_sector", ProtoSchemaType::kUint64},
-            {"rwbs", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "block_dirty_buffer",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"sector", ProtoSchemaType::kUint64},
-            {"size", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "block_getrq",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"sector", ProtoSchemaType::kUint64},
-            {"nr_sector", ProtoSchemaType::kUint32},
-            {"rwbs", ProtoSchemaType::kString},
-            {"comm", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "block_plug",
-        1,
-        {
-            {},
-            {"comm", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "block_rq_abort",
-        6,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"sector", ProtoSchemaType::kUint64},
-            {"nr_sector", ProtoSchemaType::kUint32},
-            {"errors", ProtoSchemaType::kInt32},
-            {"rwbs", ProtoSchemaType::kString},
-            {"cmd", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "block_rq_complete",
-        6,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"sector", ProtoSchemaType::kUint64},
-            {"nr_sector", ProtoSchemaType::kUint32},
-            {"errors", ProtoSchemaType::kInt32},
-            {"rwbs", ProtoSchemaType::kString},
-            {"cmd", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "block_rq_insert",
-        7,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"sector", ProtoSchemaType::kUint64},
-            {"nr_sector", ProtoSchemaType::kUint32},
-            {"bytes", ProtoSchemaType::kUint32},
-            {"rwbs", ProtoSchemaType::kString},
-            {"comm", ProtoSchemaType::kString},
-            {"cmd", ProtoSchemaType::kString},
-        },
-    },
-    {nullptr, 0, {}},
-    {
-        "block_rq_remap",
-        7,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"sector", ProtoSchemaType::kUint64},
-            {"nr_sector", ProtoSchemaType::kUint32},
-            {"old_dev", ProtoSchemaType::kUint64},
-            {"old_sector", ProtoSchemaType::kUint64},
-            {"nr_bios", ProtoSchemaType::kUint32},
-            {"rwbs", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "block_rq_requeue",
-        6,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"sector", ProtoSchemaType::kUint64},
-            {"nr_sector", ProtoSchemaType::kUint32},
-            {"errors", ProtoSchemaType::kInt32},
-            {"rwbs", ProtoSchemaType::kString},
-            {"cmd", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "block_sleeprq",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"sector", ProtoSchemaType::kUint64},
-            {"nr_sector", ProtoSchemaType::kUint32},
-            {"rwbs", ProtoSchemaType::kString},
-            {"comm", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "block_split",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"sector", ProtoSchemaType::kUint64},
-            {"new_sector", ProtoSchemaType::kUint64},
-            {"rwbs", ProtoSchemaType::kString},
-            {"comm", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "block_touch_buffer",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"sector", ProtoSchemaType::kUint64},
-            {"size", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "block_unplug",
-        2,
-        {
-            {},
-            {"nr_rq", ProtoSchemaType::kInt32},
-            {"comm", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "ext4_alloc_da_blocks",
-        4,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"data_blocks", ProtoSchemaType::kUint32},
-            {"meta_blocks", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_allocate_blocks",
-        11,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"block", ProtoSchemaType::kUint64},
-            {"len", ProtoSchemaType::kUint32},
-            {"logical", ProtoSchemaType::kUint32},
-            {"lleft", ProtoSchemaType::kUint32},
-            {"lright", ProtoSchemaType::kUint32},
-            {"goal", ProtoSchemaType::kUint64},
-            {"pleft", ProtoSchemaType::kUint64},
-            {"pright", ProtoSchemaType::kUint64},
-            {"flags", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_allocate_inode",
-        4,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"dir", ProtoSchemaType::kUint64},
-            {"mode", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_begin_ordered_truncate",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"new_size", ProtoSchemaType::kInt64},
-        },
-    },
-    {
-        "ext4_collapse_range",
-        4,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"offset", ProtoSchemaType::kInt64},
-            {"len", ProtoSchemaType::kInt64},
-        },
-    },
-    {
-        "ext4_da_release_space",
-        8,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"i_blocks", ProtoSchemaType::kUint64},
-            {"freed_blocks", ProtoSchemaType::kInt32},
-            {"reserved_data_blocks", ProtoSchemaType::kInt32},
-            {"reserved_meta_blocks", ProtoSchemaType::kInt32},
-            {"allocated_meta_blocks", ProtoSchemaType::kInt32},
-            {"mode", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_da_reserve_space",
-        7,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"i_blocks", ProtoSchemaType::kUint64},
-            {"reserved_data_blocks", ProtoSchemaType::kInt32},
-            {"reserved_meta_blocks", ProtoSchemaType::kInt32},
-            {"mode", ProtoSchemaType::kUint32},
-            {"md_needed", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_da_update_reserve_space",
-        9,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"i_blocks", ProtoSchemaType::kUint64},
-            {"used_blocks", ProtoSchemaType::kInt32},
-            {"reserved_data_blocks", ProtoSchemaType::kInt32},
-            {"reserved_meta_blocks", ProtoSchemaType::kInt32},
-            {"allocated_meta_blocks", ProtoSchemaType::kInt32},
-            {"quota_claim", ProtoSchemaType::kInt32},
-            {"mode", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_da_write_pages",
-        10,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"first_page", ProtoSchemaType::kUint64},
-            {"nr_to_write", ProtoSchemaType::kInt64},
-            {"sync_mode", ProtoSchemaType::kInt32},
-            {"b_blocknr", ProtoSchemaType::kUint64},
-            {"b_size", ProtoSchemaType::kUint32},
-            {"b_state", ProtoSchemaType::kUint32},
-            {"io_done", ProtoSchemaType::kInt32},
-            {"pages_written", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_da_write_pages_extent",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"lblk", ProtoSchemaType::kUint64},
-            {"len", ProtoSchemaType::kUint32},
-            {"flags", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_direct_IO_enter",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pos", ProtoSchemaType::kInt64},
-            {"len", ProtoSchemaType::kUint64},
-            {"rw", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_direct_IO_exit",
-        6,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pos", ProtoSchemaType::kInt64},
-            {"len", ProtoSchemaType::kUint64},
-            {"rw", ProtoSchemaType::kInt32},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_discard_blocks",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"blk", ProtoSchemaType::kUint64},
-            {"count", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ext4_discard_preallocations",
-        2,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ext4_drop_inode",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"drop", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_es_cache_extent",
-        6,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"lblk", ProtoSchemaType::kUint32},
-            {"len", ProtoSchemaType::kUint32},
-            {"pblk", ProtoSchemaType::kUint64},
-            {"status", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_es_find_delayed_extent_range_enter",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"lblk", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_es_find_delayed_extent_range_exit",
-        6,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"lblk", ProtoSchemaType::kUint32},
-            {"len", ProtoSchemaType::kUint32},
-            {"pblk", ProtoSchemaType::kUint64},
-            {"status", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ext4_es_insert_extent",
-        6,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"lblk", ProtoSchemaType::kUint32},
-            {"len", ProtoSchemaType::kUint32},
-            {"pblk", ProtoSchemaType::kUint64},
-            {"status", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ext4_es_lookup_extent_enter",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"lblk", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_es_lookup_extent_exit",
-        7,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"lblk", ProtoSchemaType::kUint32},
-            {"len", ProtoSchemaType::kUint32},
-            {"pblk", ProtoSchemaType::kUint64},
-            {"status", ProtoSchemaType::kUint64},
-            {"found", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_es_remove_extent",
-        4,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"lblk", ProtoSchemaType::kInt64},
-            {"len", ProtoSchemaType::kInt64},
-        },
-    },
-    {
-        "ext4_es_shrink",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"nr_shrunk", ProtoSchemaType::kInt32},
-            {"scan_time", ProtoSchemaType::kUint64},
-            {"nr_skipped", ProtoSchemaType::kInt32},
-            {"retried", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_es_shrink_count",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"nr_to_scan", ProtoSchemaType::kInt32},
-            {"cache_cnt", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_es_shrink_scan_enter",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"nr_to_scan", ProtoSchemaType::kInt32},
-            {"cache_cnt", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_es_shrink_scan_exit",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"nr_shrunk", ProtoSchemaType::kInt32},
-            {"cache_cnt", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_evict_inode",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"nlink", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_ext_convert_to_initialized_enter",
-        7,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"m_lblk", ProtoSchemaType::kUint32},
-            {"m_len", ProtoSchemaType::kUint32},
-            {"u_lblk", ProtoSchemaType::kUint32},
-            {"u_len", ProtoSchemaType::kUint32},
-            {"u_pblk", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ext4_ext_convert_to_initialized_fastpath",
-        10,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"m_lblk", ProtoSchemaType::kUint32},
-            {"m_len", ProtoSchemaType::kUint32},
-            {"u_lblk", ProtoSchemaType::kUint32},
-            {"u_len", ProtoSchemaType::kUint32},
-            {"u_pblk", ProtoSchemaType::kUint64},
-            {"i_lblk", ProtoSchemaType::kUint32},
-            {"i_len", ProtoSchemaType::kUint32},
-            {"i_pblk", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ext4_ext_handle_unwritten_extents",
-        8,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"flags", ProtoSchemaType::kInt32},
-            {"lblk", ProtoSchemaType::kUint32},
-            {"pblk", ProtoSchemaType::kUint64},
-            {"len", ProtoSchemaType::kUint32},
-            {"allocated", ProtoSchemaType::kUint32},
-            {"newblk", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ext4_ext_in_cache",
-        4,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"lblk", ProtoSchemaType::kUint32},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_ext_load_extent",
-        4,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pblk", ProtoSchemaType::kUint64},
-            {"lblk", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_ext_map_blocks_enter",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"lblk", ProtoSchemaType::kUint32},
-            {"len", ProtoSchemaType::kUint32},
-            {"flags", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_ext_map_blocks_exit",
-        8,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"flags", ProtoSchemaType::kUint32},
-            {"pblk", ProtoSchemaType::kUint64},
-            {"lblk", ProtoSchemaType::kUint32},
-            {"len", ProtoSchemaType::kUint32},
-            {"mflags", ProtoSchemaType::kUint32},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_ext_put_in_cache",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"lblk", ProtoSchemaType::kUint32},
-            {"len", ProtoSchemaType::kUint32},
-            {"start", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ext4_ext_remove_space",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"start", ProtoSchemaType::kUint32},
-            {"end", ProtoSchemaType::kUint32},
-            {"depth", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_ext_remove_space_done",
-        7,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"start", ProtoSchemaType::kUint32},
-            {"end", ProtoSchemaType::kUint32},
-            {"depth", ProtoSchemaType::kInt32},
-            {"partial", ProtoSchemaType::kInt64},
-            {"eh_entries", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_ext_rm_idx",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pblk", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ext4_ext_rm_leaf",
-        7,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"partial", ProtoSchemaType::kInt64},
-            {"start", ProtoSchemaType::kUint32},
-            {"ee_lblk", ProtoSchemaType::kUint32},
-            {"ee_pblk", ProtoSchemaType::kUint64},
-            {"ee_len", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_ext_show_extent",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pblk", ProtoSchemaType::kUint64},
-            {"lblk", ProtoSchemaType::kUint32},
-            {"len", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_fallocate_enter",
-        6,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"offset", ProtoSchemaType::kInt64},
-            {"len", ProtoSchemaType::kInt64},
-            {"mode", ProtoSchemaType::kInt32},
-            {"pos", ProtoSchemaType::kInt64},
-        },
-    },
-    {
-        "ext4_fallocate_exit",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pos", ProtoSchemaType::kInt64},
-            {"blocks", ProtoSchemaType::kUint32},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_find_delalloc_range",
-        7,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"from", ProtoSchemaType::kUint32},
-            {"to", ProtoSchemaType::kUint32},
-            {"reverse", ProtoSchemaType::kInt32},
-            {"found", ProtoSchemaType::kInt32},
-            {"found_blk", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_forget",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"block", ProtoSchemaType::kUint64},
-            {"is_metadata", ProtoSchemaType::kInt32},
-            {"mode", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_free_blocks",
-        6,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"block", ProtoSchemaType::kUint64},
-            {"count", ProtoSchemaType::kUint64},
-            {"flags", ProtoSchemaType::kInt32},
-            {"mode", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_free_inode",
-        6,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"uid", ProtoSchemaType::kUint32},
-            {"gid", ProtoSchemaType::kUint32},
-            {"blocks", ProtoSchemaType::kUint64},
-            {"mode", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_get_implied_cluster_alloc_exit",
-        6,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"flags", ProtoSchemaType::kUint32},
-            {"lblk", ProtoSchemaType::kUint32},
-            {"pblk", ProtoSchemaType::kUint64},
-            {"len", ProtoSchemaType::kUint32},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_get_reserved_cluster_alloc",
-        4,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"lblk", ProtoSchemaType::kUint32},
-            {"len", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_ind_map_blocks_enter",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"lblk", ProtoSchemaType::kUint32},
-            {"len", ProtoSchemaType::kUint32},
-            {"flags", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_ind_map_blocks_exit",
-        8,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"flags", ProtoSchemaType::kUint32},
-            {"pblk", ProtoSchemaType::kUint64},
-            {"lblk", ProtoSchemaType::kUint32},
-            {"len", ProtoSchemaType::kUint32},
-            {"mflags", ProtoSchemaType::kUint32},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_insert_range",
-        4,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"offset", ProtoSchemaType::kInt64},
-            {"len", ProtoSchemaType::kInt64},
-        },
-    },
-    {
-        "ext4_invalidatepage",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"index", ProtoSchemaType::kUint64},
-            {"offset", ProtoSchemaType::kUint64},
-            {"length", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_journal_start",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ip", ProtoSchemaType::kUint64},
-            {"blocks", ProtoSchemaType::kInt32},
-            {"rsv_blocks", ProtoSchemaType::kInt32},
-            {"nblocks", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_journal_start_reserved",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ip", ProtoSchemaType::kUint64},
-            {"blocks", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_journalled_invalidatepage",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"index", ProtoSchemaType::kUint64},
-            {"offset", ProtoSchemaType::kUint64},
-            {"length", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_journalled_write_end",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pos", ProtoSchemaType::kInt64},
-            {"len", ProtoSchemaType::kUint32},
-            {"copied", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_load_inode",
-        2,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ext4_load_inode_bitmap",
-        2,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"group", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_mark_inode_dirty",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"ip", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ext4_mb_bitmap_load",
-        2,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"group", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_mb_buddy_bitmap_load",
-        2,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"group", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_mb_discard_preallocations",
-        2,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"needed", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_mb_new_group_pa",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pa_pstart", ProtoSchemaType::kUint64},
-            {"pa_lstart", ProtoSchemaType::kUint64},
-            {"pa_len", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_mb_new_inode_pa",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pa_pstart", ProtoSchemaType::kUint64},
-            {"pa_lstart", ProtoSchemaType::kUint64},
-            {"pa_len", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_mb_release_group_pa",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"pa_pstart", ProtoSchemaType::kUint64},
-            {"pa_len", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_mb_release_inode_pa",
-        4,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"block", ProtoSchemaType::kUint64},
-            {"count", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_mballoc_alloc",
-        20,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"orig_logical", ProtoSchemaType::kUint32},
-            {"orig_start", ProtoSchemaType::kInt32},
-            {"orig_group", ProtoSchemaType::kUint32},
-            {"orig_len", ProtoSchemaType::kInt32},
-            {"goal_logical", ProtoSchemaType::kUint32},
-            {"goal_start", ProtoSchemaType::kInt32},
-            {"goal_group", ProtoSchemaType::kUint32},
-            {"goal_len", ProtoSchemaType::kInt32},
-            {"result_logical", ProtoSchemaType::kUint32},
-            {"result_start", ProtoSchemaType::kInt32},
-            {"result_group", ProtoSchemaType::kUint32},
-            {"result_len", ProtoSchemaType::kInt32},
-            {"found", ProtoSchemaType::kUint32},
-            {"groups", ProtoSchemaType::kUint32},
-            {"buddy", ProtoSchemaType::kUint32},
-            {"flags", ProtoSchemaType::kUint32},
-            {"tail", ProtoSchemaType::kUint32},
-            {"cr", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_mballoc_discard",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"result_start", ProtoSchemaType::kInt32},
-            {"result_group", ProtoSchemaType::kUint32},
-            {"result_len", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_mballoc_free",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"result_start", ProtoSchemaType::kInt32},
-            {"result_group", ProtoSchemaType::kUint32},
-            {"result_len", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_mballoc_prealloc",
-        10,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"orig_logical", ProtoSchemaType::kUint32},
-            {"orig_start", ProtoSchemaType::kInt32},
-            {"orig_group", ProtoSchemaType::kUint32},
-            {"orig_len", ProtoSchemaType::kInt32},
-            {"result_logical", ProtoSchemaType::kUint32},
-            {"result_start", ProtoSchemaType::kInt32},
-            {"result_group", ProtoSchemaType::kUint32},
-            {"result_len", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_other_inode_update_time",
-        6,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"orig_ino", ProtoSchemaType::kUint64},
-            {"uid", ProtoSchemaType::kUint32},
-            {"gid", ProtoSchemaType::kUint32},
-            {"mode", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_punch_hole",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"offset", ProtoSchemaType::kInt64},
-            {"len", ProtoSchemaType::kInt64},
-            {"mode", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_read_block_bitmap_load",
-        2,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"group", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_readpage",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"index", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ext4_releasepage",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"index", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ext4_remove_blocks",
-        8,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"from", ProtoSchemaType::kUint32},
-            {"to", ProtoSchemaType::kUint32},
-            {"partial", ProtoSchemaType::kInt64},
-            {"ee_pblk", ProtoSchemaType::kUint64},
-            {"ee_lblk", ProtoSchemaType::kUint32},
-            {"ee_len", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_request_blocks",
-        10,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"len", ProtoSchemaType::kUint32},
-            {"logical", ProtoSchemaType::kUint32},
-            {"lleft", ProtoSchemaType::kUint32},
-            {"lright", ProtoSchemaType::kUint32},
-            {"goal", ProtoSchemaType::kUint64},
-            {"pleft", ProtoSchemaType::kUint64},
-            {"pright", ProtoSchemaType::kUint64},
-            {"flags", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_request_inode",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"dir", ProtoSchemaType::kUint64},
-            {"mode", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_sync_fs",
-        2,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"wait", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_trim_all_free",
-        5,
-        {
-            {},
-            {"dev_major", ProtoSchemaType::kInt32},
-            {"dev_minor", ProtoSchemaType::kInt32},
-            {"group", ProtoSchemaType::kUint32},
-            {"start", ProtoSchemaType::kInt32},
-            {"len", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_trim_extent",
-        5,
-        {
-            {},
-            {"dev_major", ProtoSchemaType::kInt32},
-            {"dev_minor", ProtoSchemaType::kInt32},
-            {"group", ProtoSchemaType::kUint32},
-            {"start", ProtoSchemaType::kInt32},
-            {"len", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_truncate_enter",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"blocks", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ext4_truncate_exit",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"blocks", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ext4_unlink_enter",
-        4,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"parent", ProtoSchemaType::kUint64},
-            {"size", ProtoSchemaType::kInt64},
-        },
-    },
-    {
-        "ext4_unlink_exit",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_write_begin",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pos", ProtoSchemaType::kInt64},
-            {"len", ProtoSchemaType::kUint32},
-            {"flags", ProtoSchemaType::kUint32},
-        },
-    },
-    {nullptr, 0, {}},
-    {nullptr, 0, {}},
-    {nullptr, 0, {}},
-    {nullptr, 0, {}},
-    {nullptr, 0, {}},
-    {nullptr, 0, {}},
-    {nullptr, 0, {}},
-    {nullptr, 0, {}},
-    {nullptr, 0, {}},
-    {nullptr, 0, {}},
-    {
-        "ext4_write_end",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pos", ProtoSchemaType::kInt64},
-            {"len", ProtoSchemaType::kUint32},
-            {"copied", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_writepage",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"index", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ext4_writepages",
-        10,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"nr_to_write", ProtoSchemaType::kInt64},
-            {"pages_skipped", ProtoSchemaType::kInt64},
-            {"range_start", ProtoSchemaType::kInt64},
-            {"range_end", ProtoSchemaType::kInt64},
-            {"writeback_index", ProtoSchemaType::kUint64},
-            {"sync_mode", ProtoSchemaType::kInt32},
-            {"for_kupdate", ProtoSchemaType::kUint32},
-            {"range_cyclic", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ext4_writepages_result",
-        7,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"ret", ProtoSchemaType::kInt32},
-            {"pages_written", ProtoSchemaType::kInt32},
-            {"pages_skipped", ProtoSchemaType::kInt64},
-            {"writeback_index", ProtoSchemaType::kUint64},
-            {"sync_mode", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ext4_zero_range",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"offset", ProtoSchemaType::kInt64},
-            {"len", ProtoSchemaType::kInt64},
-            {"mode", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "task_newtask",
-        4,
-        {
-            {},
-            {"pid", ProtoSchemaType::kInt32},
-            {"comm", ProtoSchemaType::kString},
-            {"clone_flags", ProtoSchemaType::kUint64},
-            {"oom_score_adj", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "task_rename",
-        4,
-        {
-            {},
-            {"pid", ProtoSchemaType::kInt32},
-            {"oldcomm", ProtoSchemaType::kString},
-            {"newcomm", ProtoSchemaType::kString},
-            {"oom_score_adj", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "sched_process_exec",
-        3,
-        {
-            {},
-            {"filename", ProtoSchemaType::kString},
-            {"pid", ProtoSchemaType::kInt32},
-            {"old_pid", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "sched_process_exit",
-        4,
-        {
-            {},
-            {"comm", ProtoSchemaType::kString},
-            {"pid", ProtoSchemaType::kInt32},
-            {"tgid", ProtoSchemaType::kInt32},
-            {"prio", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "sched_process_fork",
-        4,
-        {
-            {},
-            {"parent_comm", ProtoSchemaType::kString},
-            {"parent_pid", ProtoSchemaType::kInt32},
-            {"child_comm", ProtoSchemaType::kString},
-            {"child_pid", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "sched_process_free",
-        3,
-        {
-            {},
-            {"comm", ProtoSchemaType::kString},
-            {"pid", ProtoSchemaType::kInt32},
-            {"prio", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "sched_process_hang",
-        2,
-        {
-            {},
-            {"comm", ProtoSchemaType::kString},
-            {"pid", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "sched_process_wait",
-        3,
-        {
-            {},
-            {"comm", ProtoSchemaType::kString},
-            {"pid", ProtoSchemaType::kInt32},
-            {"prio", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "f2fs_do_submit_bio",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"btype", ProtoSchemaType::kInt32},
-            {"sync", ProtoSchemaType::kUint32},
-            {"sector", ProtoSchemaType::kUint64},
-            {"size", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "f2fs_evict_inode",
-        8,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pino", ProtoSchemaType::kUint64},
-            {"mode", ProtoSchemaType::kUint32},
-            {"size", ProtoSchemaType::kInt64},
-            {"nlink", ProtoSchemaType::kUint32},
-            {"blocks", ProtoSchemaType::kUint64},
-            {"advise", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "f2fs_fallocate",
-        8,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"mode", ProtoSchemaType::kInt32},
-            {"offset", ProtoSchemaType::kInt64},
-            {"len", ProtoSchemaType::kInt64},
-            {"size", ProtoSchemaType::kInt64},
-            {"blocks", ProtoSchemaType::kUint64},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "f2fs_get_data_block",
-        6,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"iblock", ProtoSchemaType::kUint64},
-            {"bh_start", ProtoSchemaType::kUint64},
-            {"bh_size", ProtoSchemaType::kUint64},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "f2fs_get_victim",
-        10,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"type", ProtoSchemaType::kInt32},
-            {"gc_type", ProtoSchemaType::kInt32},
-            {"alloc_mode", ProtoSchemaType::kInt32},
-            {"gc_mode", ProtoSchemaType::kInt32},
-            {"victim", ProtoSchemaType::kUint32},
-            {"ofs_unit", ProtoSchemaType::kUint32},
-            {"pre_victim", ProtoSchemaType::kUint32},
-            {"prefree", ProtoSchemaType::kUint32},
-            {"free", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "f2fs_iget",
-        8,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pino", ProtoSchemaType::kUint64},
-            {"mode", ProtoSchemaType::kUint32},
-            {"size", ProtoSchemaType::kInt64},
-            {"nlink", ProtoSchemaType::kUint32},
-            {"blocks", ProtoSchemaType::kUint64},
-            {"advise", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "f2fs_iget_exit",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "f2fs_new_inode",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "f2fs_readpage",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"index", ProtoSchemaType::kUint64},
-            {"blkaddr", ProtoSchemaType::kUint64},
-            {"type", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "f2fs_reserve_new_block",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"nid", ProtoSchemaType::kUint32},
-            {"ofs_in_node", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "f2fs_set_page_dirty",
-        6,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"type", ProtoSchemaType::kInt32},
-            {"dir", ProtoSchemaType::kInt32},
-            {"index", ProtoSchemaType::kUint64},
-            {"dirty", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "f2fs_submit_write_page",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"type", ProtoSchemaType::kInt32},
-            {"index", ProtoSchemaType::kUint64},
-            {"block", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "f2fs_sync_file_enter",
-        8,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pino", ProtoSchemaType::kUint64},
-            {"mode", ProtoSchemaType::kUint32},
-            {"size", ProtoSchemaType::kInt64},
-            {"nlink", ProtoSchemaType::kUint32},
-            {"blocks", ProtoSchemaType::kUint64},
-            {"advise", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "f2fs_sync_file_exit",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"need_cp", ProtoSchemaType::kUint32},
-            {"datasync", ProtoSchemaType::kInt32},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "f2fs_sync_fs",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"dirty", ProtoSchemaType::kInt32},
-            {"wait", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "f2fs_truncate",
-        8,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pino", ProtoSchemaType::kUint64},
-            {"mode", ProtoSchemaType::kUint32},
-            {"size", ProtoSchemaType::kInt64},
-            {"nlink", ProtoSchemaType::kUint32},
-            {"blocks", ProtoSchemaType::kUint64},
-            {"advise", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "f2fs_truncate_blocks_enter",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"size", ProtoSchemaType::kInt64},
-            {"blocks", ProtoSchemaType::kUint64},
-            {"from", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "f2fs_truncate_blocks_exit",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "f2fs_truncate_data_blocks_range",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"nid", ProtoSchemaType::kUint32},
-            {"ofs", ProtoSchemaType::kUint32},
-            {"free", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "f2fs_truncate_inode_blocks_enter",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"size", ProtoSchemaType::kInt64},
-            {"blocks", ProtoSchemaType::kUint64},
-            {"from", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "f2fs_truncate_inode_blocks_exit",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "f2fs_truncate_node",
-        4,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"nid", ProtoSchemaType::kUint32},
-            {"blk_addr", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "f2fs_truncate_nodes_enter",
-        4,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"nid", ProtoSchemaType::kUint32},
-            {"blk_addr", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "f2fs_truncate_nodes_exit",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "f2fs_truncate_partial_nodes",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"nid", ProtoSchemaType::kUint32},
-            {"depth", ProtoSchemaType::kInt32},
-            {"err", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "f2fs_unlink_enter",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"size", ProtoSchemaType::kInt64},
-            {"blocks", ProtoSchemaType::kUint64},
-            {"name", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "f2fs_unlink_exit",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"ret", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "f2fs_vm_page_mkwrite",
-        6,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"type", ProtoSchemaType::kInt32},
-            {"dir", ProtoSchemaType::kInt32},
-            {"index", ProtoSchemaType::kUint64},
-            {"dirty", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "f2fs_write_begin",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pos", ProtoSchemaType::kInt64},
-            {"len", ProtoSchemaType::kUint32},
-            {"flags", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "f2fs_write_checkpoint",
-        3,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"is_umount", ProtoSchemaType::kUint32},
-            {"msg", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "f2fs_write_end",
-        5,
-        {
-            {},
-            {"dev", ProtoSchemaType::kUint64},
-            {"ino", ProtoSchemaType::kUint64},
-            {"pos", ProtoSchemaType::kInt64},
-            {"len", ProtoSchemaType::kUint32},
-            {"copied", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "alloc_pages_iommu_end",
-        2,
-        {
-            {},
-            {"gfp_flags", ProtoSchemaType::kUint32},
-            {"order", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "alloc_pages_iommu_fail",
-        2,
-        {
-            {},
-            {"gfp_flags", ProtoSchemaType::kUint32},
-            {"order", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "alloc_pages_iommu_start",
-        2,
-        {
-            {},
-            {"gfp_flags", ProtoSchemaType::kUint32},
-            {"order", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "alloc_pages_sys_end",
-        2,
-        {
-            {},
-            {"gfp_flags", ProtoSchemaType::kUint32},
-            {"order", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "alloc_pages_sys_fail",
-        2,
-        {
-            {},
-            {"gfp_flags", ProtoSchemaType::kUint32},
-            {"order", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "alloc_pages_sys_start",
-        2,
-        {
-            {},
-            {"gfp_flags", ProtoSchemaType::kUint32},
-            {"order", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "dma_alloc_contiguous_retry",
-        1,
-        {
-            {},
-            {"tries", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "iommu_map_range",
-        4,
-        {
-            {},
-            {"chunk_size", ProtoSchemaType::kUint64},
-            {"len", ProtoSchemaType::kUint64},
-            {"pa", ProtoSchemaType::kUint64},
-            {"va", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "iommu_sec_ptbl_map_range_end",
-        5,
-        {
-            {},
-            {"len", ProtoSchemaType::kUint64},
-            {"num", ProtoSchemaType::kInt32},
-            {"pa", ProtoSchemaType::kUint32},
-            {"sec_id", ProtoSchemaType::kInt32},
-            {"va", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "iommu_sec_ptbl_map_range_start",
-        5,
-        {
-            {},
-            {"len", ProtoSchemaType::kUint64},
-            {"num", ProtoSchemaType::kInt32},
-            {"pa", ProtoSchemaType::kUint32},
-            {"sec_id", ProtoSchemaType::kInt32},
-            {"va", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ion_alloc_buffer_end",
-        5,
-        {
-            {},
-            {"client_name", ProtoSchemaType::kString},
-            {"flags", ProtoSchemaType::kUint32},
-            {"heap_name", ProtoSchemaType::kString},
-            {"len", ProtoSchemaType::kUint64},
-            {"mask", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ion_alloc_buffer_fail",
-        6,
-        {
-            {},
-            {"client_name", ProtoSchemaType::kString},
-            {"error", ProtoSchemaType::kInt64},
-            {"flags", ProtoSchemaType::kUint32},
-            {"heap_name", ProtoSchemaType::kString},
-            {"len", ProtoSchemaType::kUint64},
-            {"mask", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ion_alloc_buffer_fallback",
-        6,
-        {
-            {},
-            {"client_name", ProtoSchemaType::kString},
-            {"error", ProtoSchemaType::kInt64},
-            {"flags", ProtoSchemaType::kUint32},
-            {"heap_name", ProtoSchemaType::kString},
-            {"len", ProtoSchemaType::kUint64},
-            {"mask", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ion_alloc_buffer_start",
-        5,
-        {
-            {},
-            {"client_name", ProtoSchemaType::kString},
-            {"flags", ProtoSchemaType::kUint32},
-            {"heap_name", ProtoSchemaType::kString},
-            {"len", ProtoSchemaType::kUint64},
-            {"mask", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "ion_cp_alloc_retry",
-        1,
-        {
-            {},
-            {"tries", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ion_cp_secure_buffer_end",
-        4,
-        {
-            {},
-            {"align", ProtoSchemaType::kUint64},
-            {"flags", ProtoSchemaType::kUint64},
-            {"heap_name", ProtoSchemaType::kString},
-            {"len", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ion_cp_secure_buffer_start",
-        4,
-        {
-            {},
-            {"align", ProtoSchemaType::kUint64},
-            {"flags", ProtoSchemaType::kUint64},
-            {"heap_name", ProtoSchemaType::kString},
-            {"len", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ion_prefetching",
-        1,
-        {
-            {},
-            {"len", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ion_secure_cma_add_to_pool_end",
-        3,
-        {
-            {},
-            {"is_prefetch", ProtoSchemaType::kUint32},
-            {"len", ProtoSchemaType::kUint64},
-            {"pool_total", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ion_secure_cma_add_to_pool_start",
-        3,
-        {
-            {},
-            {"is_prefetch", ProtoSchemaType::kUint32},
-            {"len", ProtoSchemaType::kUint64},
-            {"pool_total", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "ion_secure_cma_allocate_end",
-        4,
-        {
-            {},
-            {"align", ProtoSchemaType::kUint64},
-            {"flags", ProtoSchemaType::kUint64},
-            {"heap_name", ProtoSchemaType::kString},
-            {"len", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ion_secure_cma_allocate_start",
-        4,
-        {
-            {},
-            {"align", ProtoSchemaType::kUint64},
-            {"flags", ProtoSchemaType::kUint64},
-            {"heap_name", ProtoSchemaType::kString},
-            {"len", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ion_secure_cma_shrink_pool_end",
-        2,
-        {
-            {},
-            {"drained_size", ProtoSchemaType::kUint64},
-            {"skipped_size", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "ion_secure_cma_shrink_pool_start",
-        2,
-        {
-            {},
-            {"drained_size", ProtoSchemaType::kUint64},
-            {"skipped_size", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "kfree",
-        2,
-        {
-            {},
-            {"call_site", ProtoSchemaType::kUint64},
-            {"ptr", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "kmalloc",
-        5,
-        {
-            {},
-            {"bytes_alloc", ProtoSchemaType::kUint64},
-            {"bytes_req", ProtoSchemaType::kUint64},
-            {"call_site", ProtoSchemaType::kUint64},
-            {"gfp_flags", ProtoSchemaType::kUint32},
-            {"ptr", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "kmalloc_node",
-        6,
-        {
-            {},
-            {"bytes_alloc", ProtoSchemaType::kUint64},
-            {"bytes_req", ProtoSchemaType::kUint64},
-            {"call_site", ProtoSchemaType::kUint64},
-            {"gfp_flags", ProtoSchemaType::kUint32},
-            {"node", ProtoSchemaType::kInt32},
-            {"ptr", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "kmem_cache_alloc",
-        5,
-        {
-            {},
-            {"bytes_alloc", ProtoSchemaType::kUint64},
-            {"bytes_req", ProtoSchemaType::kUint64},
-            {"call_site", ProtoSchemaType::kUint64},
-            {"gfp_flags", ProtoSchemaType::kUint32},
-            {"ptr", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "kmem_cache_alloc_node",
-        6,
-        {
-            {},
-            {"bytes_alloc", ProtoSchemaType::kUint64},
-            {"bytes_req", ProtoSchemaType::kUint64},
-            {"call_site", ProtoSchemaType::kUint64},
-            {"gfp_flags", ProtoSchemaType::kUint32},
-            {"node", ProtoSchemaType::kInt32},
-            {"ptr", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "kmem_cache_free",
-        2,
-        {
-            {},
-            {"call_site", ProtoSchemaType::kUint64},
-            {"ptr", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "migrate_pages_end",
-        1,
-        {
-            {},
-            {"mode", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "migrate_pages_start",
-        1,
-        {
-            {},
-            {"mode", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "migrate_retry",
-        1,
-        {
-            {},
-            {"tries", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "mm_page_alloc",
-        5,
-        {
-            {},
-            {"gfp_flags", ProtoSchemaType::kUint32},
-            {"migratetype", ProtoSchemaType::kInt32},
-            {"order", ProtoSchemaType::kUint32},
-            {"page", ProtoSchemaType::kUint64},
-            {"pfn", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "mm_page_alloc_extfrag",
-        7,
-        {
-            {},
-            {"alloc_migratetype", ProtoSchemaType::kInt32},
-            {"alloc_order", ProtoSchemaType::kInt32},
-            {"fallback_migratetype", ProtoSchemaType::kInt32},
-            {"fallback_order", ProtoSchemaType::kInt32},
-            {"page", ProtoSchemaType::kUint64},
-            {"change_ownership", ProtoSchemaType::kInt32},
-            {"pfn", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "mm_page_alloc_zone_locked",
-        4,
-        {
-            {},
-            {"migratetype", ProtoSchemaType::kInt32},
-            {"order", ProtoSchemaType::kUint32},
-            {"page", ProtoSchemaType::kUint64},
-            {"pfn", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "mm_page_free",
-        3,
-        {
-            {},
-            {"order", ProtoSchemaType::kUint32},
-            {"page", ProtoSchemaType::kUint64},
-            {"pfn", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "mm_page_free_batched",
-        3,
-        {
-            {},
-            {"cold", ProtoSchemaType::kInt32},
-            {"page", ProtoSchemaType::kUint64},
-            {"pfn", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "mm_page_pcpu_drain",
-        4,
-        {
-            {},
-            {"migratetype", ProtoSchemaType::kInt32},
-            {"order", ProtoSchemaType::kUint32},
-            {"page", ProtoSchemaType::kUint64},
-            {"pfn", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "rss_stat",
-        2,
-        {
-            {},
-            {"member", ProtoSchemaType::kInt32},
-            {"size", ProtoSchemaType::kInt64},
-        },
-    },
-    {
-        "ion_heap_shrink",
-        3,
-        {
-            {},
-            {"heap_name", ProtoSchemaType::kString},
-            {"len", ProtoSchemaType::kUint64},
-            {"total_allocated", ProtoSchemaType::kInt64},
-        },
-    },
-    {
-        "ion_heap_grow",
-        3,
-        {
-            {},
-            {"heap_name", ProtoSchemaType::kString},
-            {"len", ProtoSchemaType::kUint64},
-            {"total_allocated", ProtoSchemaType::kInt64},
-        },
-    },
-    {
-        "fence_init",
-        4,
-        {
-            {},
-            {"context", ProtoSchemaType::kUint32},
-            {"driver", ProtoSchemaType::kString},
-            {"seqno", ProtoSchemaType::kUint32},
-            {"timeline", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "fence_destroy",
-        4,
-        {
-            {},
-            {"context", ProtoSchemaType::kUint32},
-            {"driver", ProtoSchemaType::kString},
-            {"seqno", ProtoSchemaType::kUint32},
-            {"timeline", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "fence_enable_signal",
-        4,
-        {
-            {},
-            {"context", ProtoSchemaType::kUint32},
-            {"driver", ProtoSchemaType::kString},
-            {"seqno", ProtoSchemaType::kUint32},
-            {"timeline", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "fence_signaled",
-        4,
-        {
-            {},
-            {"context", ProtoSchemaType::kUint32},
-            {"driver", ProtoSchemaType::kString},
-            {"seqno", ProtoSchemaType::kUint32},
-            {"timeline", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "clk_enable",
-        1,
-        {
-            {},
-            {"name", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "clk_disable",
-        1,
-        {
-            {},
-            {"name", ProtoSchemaType::kString},
-        },
-    },
-    {
-        "clk_set_rate",
-        2,
-        {
-            {},
-            {"name", ProtoSchemaType::kString},
-            {"rate", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "binder_transaction_alloc_buf",
-        3,
-        {
-            {},
-            {"data_size", ProtoSchemaType::kUint64},
-            {"debug_id", ProtoSchemaType::kInt32},
-            {"offsets_size", ProtoSchemaType::kUint64},
-        },
-    },
-    {
-        "signal_deliver",
-        3,
-        {
-            {},
-            {"code", ProtoSchemaType::kInt32},
-            {"sa_flags", ProtoSchemaType::kUint64},
-            {"sig", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "signal_generate",
-        6,
-        {
-            {},
-            {"code", ProtoSchemaType::kInt32},
-            {"comm", ProtoSchemaType::kString},
-            {"group", ProtoSchemaType::kInt32},
-            {"pid", ProtoSchemaType::kInt32},
-            {"result", ProtoSchemaType::kInt32},
-            {"sig", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "oom_score_adj_update",
-        3,
-        {
-            {},
-            {"comm", ProtoSchemaType::kString},
-            {"oom_score_adj", ProtoSchemaType::kInt32},
-            {"pid", ProtoSchemaType::kInt32},
-        },
-    },
-    {
-        "generic",
-        2,
-        {
-            {},
-            {"event_name", ProtoSchemaType::kString},
-            {},
-        },
-    },
-    {
-        "mm_event_record",
-        4,
-        {
-            {},
-            {"avg_lat", ProtoSchemaType::kUint32},
-            {"count", ProtoSchemaType::kUint32},
-            {"max_lat", ProtoSchemaType::kUint32},
-            {"type", ProtoSchemaType::kUint32},
-        },
-    },
-    {
-        "sys_enter",
-        1,
-        {
-            {},
-            {"id", ProtoSchemaType::kInt64},
-        },
-    },
-    {
-        "sys_exit",
-        2,
-        {
-            {},
-            {"id", ProtoSchemaType::kInt64},
-            {"ret", ProtoSchemaType::kInt64},
-        },
-    },
-    {
-        "zero",
-        4,
-        {
-            {},
-            {"flag", ProtoSchemaType::kInt32},
-            {"name", ProtoSchemaType::kString},
-            {"pid", ProtoSchemaType::kInt32},
-            {"value", ProtoSchemaType::kInt64},
-        },
-    },
-    {
-        "gpu_frequency",
-        2,
-        {
-            {},
-            {"gpu_id", ProtoSchemaType::kUint32},
-            {"state", ProtoSchemaType::kUint32},
-        },
-    },
-}};
-
-}  // namespace
-
-MessageDescriptor* GetMessageDescriptorForId(size_t id) {
-  PERFETTO_CHECK(id < descriptors.size());
-  return &descriptors[id];
-}
-
-size_t GetDescriptorsSize() {
-  return descriptors.size();
-}
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/ftrace/ftrace_descriptors.h b/src/trace_processor/importers/ftrace/ftrace_descriptors.h
deleted file mode 100644
index dc167ff..0000000
--- a/src/trace_processor/importers/ftrace/ftrace_descriptors.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_FTRACE_DESCRIPTORS_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_FTRACE_DESCRIPTORS_H_
-
-#include <array>
-#include "perfetto/protozero/proto_utils.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-using protozero::proto_utils::ProtoSchemaType;
-
-// We assume that no ftrace event (e.g. SchedSwitchFtraceEvent) has a proto
-// field which id is >= this.
-static constexpr size_t kMaxFtraceEventFields = 32;
-
-// This file is the header for the generated descriptors for all ftrace event
-// protos. These descriptors can be used to parse ftrace event protos without
-// needing individual parsing logic for every event. (In proto_trace_parser.cc)
-// By generating these descriptors we avoid having to build the full proto
-// library. These structs deliberately don't have a ctor (nor are initialized)
-// because they are used to define linker-initialized dicts in the .cc file.
-struct FieldDescriptor {
-  const char* name;
-  ProtoSchemaType type;
-};
-
-struct MessageDescriptor {
-  const char* name;
-  size_t max_field_id;
-  FieldDescriptor fields[kMaxFtraceEventFields];
-};
-
-MessageDescriptor* GetMessageDescriptorForId(size_t id);
-size_t GetDescriptorsSize();
-
-}  // namespace trace_processor
-}  // namespace perfetto
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_FTRACE_DESCRIPTORS_H_
diff --git a/src/trace_processor/importers/ftrace/ftrace_module.h b/src/trace_processor/importers/ftrace/ftrace_module.h
deleted file mode 100644
index fd1ace0..0000000
--- a/src/trace_processor/importers/ftrace/ftrace_module.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_FTRACE_MODULE_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_FTRACE_MODULE_H_
-
-#include "perfetto/base/build_config.h"
-#include "src/trace_processor/importers/ftrace/ftrace_parser.h"
-#include "src/trace_processor/importers/ftrace/ftrace_tokenizer.h"
-#include "src/trace_processor/importers/proto/proto_importer_module.h"
-#include "src/trace_processor/timestamped_trace_piece.h"
-#include "src/trace_processor/trace_blob_view.h"
-
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class FtraceModule
-    : public ProtoImporterModuleBase<PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)> {
- public:
-  explicit FtraceModule(TraceProcessorContext* context)
-      : ProtoImporterModuleBase(context),
-        tokenizer_(context),
-        parser_(context) {}
-
-  ModuleResult TokenizePacket(
-      const protos::pbzero::TracePacket::Decoder& decoder,
-      TraceBlobView* packet,
-      int64_t /*packet_timestamp*/,
-      PacketSequenceState* /*state*/) {
-    if (decoder.has_ftrace_events()) {
-      auto ftrace_field = decoder.ftrace_events();
-      const size_t fld_off = packet->offset_of(ftrace_field.data);
-      tokenizer_.TokenizeFtraceBundle(
-          packet->slice(fld_off, ftrace_field.size));
-      return ModuleResult::Handled();
-    }
-    return ModuleResult::Ignored();
-  }
-
-  ModuleResult ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
-                           const TimestampedTracePiece&) {
-    // TODO(eseckler): implement.
-    if (decoder.has_ftrace_stats()) {
-      parser_.ParseFtraceStats(decoder.ftrace_stats());
-      return ModuleResult::Handled();
-    }
-
-    return ModuleResult::Ignored();
-  }
-
-  ModuleResult ParseFtracePacket(uint32_t cpu,
-                                 const TimestampedTracePiece& ttp) {
-    return parser_.ParseFtraceEvent(cpu, ttp);
-  }
-
- private:
-  FtraceTokenizer tokenizer_;
-  FtraceParser parser_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_FTRACE_MODULE_H_
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
deleted file mode 100644
index 3ee0cf2..0000000
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ /dev/null
@@ -1,799 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/importers/ftrace/ftrace_parser.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/protozero/proto_decoder.h"
-#include "src/trace_processor/args_tracker.h"
-#include "src/trace_processor/binder_tracker.h"
-#include "src/trace_processor/importers/systrace/systrace_parser.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/stats.h"
-#include "src/trace_processor/syscall_tracker.h"
-#include "src/trace_processor/trace_storage.h"
-
-#include "protos/perfetto/trace/ftrace/binder.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_stats.pbzero.h"
-#include "protos/perfetto/trace/ftrace/generic.pbzero.h"
-#include "protos/perfetto/trace/ftrace/kmem.pbzero.h"
-#include "protos/perfetto/trace/ftrace/lowmemorykiller.pbzero.h"
-#include "protos/perfetto/trace/ftrace/mm_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/oom.pbzero.h"
-#include "protos/perfetto/trace/ftrace/power.pbzero.h"
-#include "protos/perfetto/trace/ftrace/raw_syscalls.pbzero.h"
-#include "protos/perfetto/trace/ftrace/sched.pbzero.h"
-#include "protos/perfetto/trace/ftrace/signal.pbzero.h"
-#include "protos/perfetto/trace/ftrace/systrace.pbzero.h"
-#include "protos/perfetto/trace/ftrace/task.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-
-using protozero::ConstBytes;
-using protozero::ProtoDecoder;
-
-// kthreadd is the parent process for all kernel threads and always has
-// pid == 2 on Linux and Android.
-const uint32_t kKthreaddPid = 2;
-const char kKthreaddName[] = "kthreadd";
-
-}  // namespace
-
-FtraceParser::FtraceParser(TraceProcessorContext* context)
-    : context_(context),
-      sched_wakeup_name_id_(context->storage->InternString("sched_wakeup")),
-      sched_waking_name_id_(context->storage->InternString("sched_waking")),
-      cpu_freq_name_id_(context->storage->InternString("cpufreq")),
-      gpu_freq_name_id_(context->storage->InternString("gpufreq")),
-      cpu_idle_name_id_(context->storage->InternString("cpuidle")),
-      ion_total_unknown_id_(context->storage->InternString("mem.ion.unknown")),
-      ion_change_unknown_id_(
-          context->storage->InternString("mem.ion_change.unknown")),
-      signal_generate_id_(context->storage->InternString("signal_generate")),
-      signal_deliver_id_(context->storage->InternString("signal_deliver")),
-      oom_score_adj_id_(context->storage->InternString("oom_score_adj")),
-      lmk_id_(context->storage->InternString("mem.lmk")),
-      comm_name_id_(context->storage->InternString("comm")) {
-  rss_members_.emplace_back(context->storage->InternString("mem.rss.file"));
-  rss_members_.emplace_back(context->storage->InternString("mem.rss.anon"));
-  rss_members_.emplace_back(context->storage->InternString("mem.swap"));
-  rss_members_.emplace_back(context->storage->InternString("mem.rss.shmem"));
-  rss_members_.emplace_back(
-      context->storage->InternString("mem.rss.unknown"));  // Keep this last.
-
-  // Build the lookup table for the strings inside ftrace events (e.g. the
-  // name of ftrace event fields and the names of their args).
-  for (size_t i = 0; i < GetDescriptorsSize(); i++) {
-    auto* descriptor = GetMessageDescriptorForId(i);
-    if (!descriptor->name) {
-      ftrace_message_strings_.emplace_back();
-      continue;
-    }
-
-    FtraceMessageStrings ftrace_strings;
-    ftrace_strings.message_name_id =
-        context->storage->InternString(descriptor->name);
-
-    for (size_t fid = 0; fid <= descriptor->max_field_id; fid++) {
-      const auto& field = descriptor->fields[fid];
-      if (!field.name)
-        continue;
-      ftrace_strings.field_name_ids[fid] =
-          context->storage->InternString(field.name);
-    }
-    ftrace_message_strings_.emplace_back(ftrace_strings);
-  }
-
-  mm_event_counter_names_ = {
-      {MmEventCounterNames(
-           context->storage->InternString("mem.mm.min_flt.count"),
-           context->storage->InternString("mem.mm.min_flt.max_lat"),
-           context->storage->InternString("mem.mm.min_flt.avg_lat")),
-       MmEventCounterNames(
-           context->storage->InternString("mem.mm.maj_flt.count"),
-           context->storage->InternString("mem.mm.maj_flt.max_lat"),
-           context->storage->InternString("mem.mm.maj_flt.avg_lat")),
-       MmEventCounterNames(
-           context->storage->InternString("mem.mm.read_io.count"),
-           context->storage->InternString("mem.mm.read_io.max_lat"),
-           context->storage->InternString("mem.mm.read_io.avg_lat")),
-       MmEventCounterNames(
-           context->storage->InternString("mem.mm.compaction.count"),
-           context->storage->InternString("mem.mm.compaction.max_lat"),
-           context->storage->InternString("mem.mm.compaction.avg_lat")),
-       MmEventCounterNames(
-           context->storage->InternString("mem.mm.reclaim.count"),
-           context->storage->InternString("mem.mm.reclaim.max_lat"),
-           context->storage->InternString("mem.mm.reclaim.avg_lat")),
-       MmEventCounterNames(
-           context->storage->InternString("mem.mm.swp_flt.count"),
-           context->storage->InternString("mem.mm.swp_flt.max_lat"),
-           context->storage->InternString("mem.mm.swp_flt.avg_lat")),
-       MmEventCounterNames(
-           context->storage->InternString("mem.mm.kern_alloc.count"),
-           context->storage->InternString("mem.mm.kern_alloc.max_lat"),
-           context->storage->InternString("mem.mm.kern_alloc.avg_lat"))}};
-}
-
-void FtraceParser::ParseFtraceStats(ConstBytes blob) {
-  protos::pbzero::FtraceStats::Decoder evt(blob.data, blob.size);
-  size_t phase =
-      evt.phase() == protos::pbzero::FtraceStats_Phase_END_OF_TRACE ? 1 : 0;
-
-  // This code relies on the fact that each ftrace_cpu_XXX_end event is
-  // just after the corresponding ftrace_cpu_XXX_begin event.
-  static_assert(
-      stats::ftrace_cpu_read_events_end - stats::ftrace_cpu_read_events_begin ==
-              1 &&
-          stats::ftrace_cpu_entries_end - stats::ftrace_cpu_entries_begin == 1,
-      "ftrace_cpu_XXX stats definition are messed up");
-
-  auto* storage = context_->storage.get();
-  for (auto it = evt.cpu_stats(); it; ++it) {
-    protos::pbzero::FtraceCpuStats::Decoder cpu_stats(*it);
-    int cpu = static_cast<int>(cpu_stats.cpu());
-    storage->SetIndexedStats(stats::ftrace_cpu_entries_begin + phase, cpu,
-                             static_cast<int64_t>(cpu_stats.entries()));
-    storage->SetIndexedStats(stats::ftrace_cpu_overrun_begin + phase, cpu,
-                             static_cast<int64_t>(cpu_stats.overrun()));
-    storage->SetIndexedStats(stats::ftrace_cpu_commit_overrun_begin + phase,
-                             cpu,
-                             static_cast<int64_t>(cpu_stats.commit_overrun()));
-    storage->SetIndexedStats(stats::ftrace_cpu_bytes_read_begin + phase, cpu,
-                             static_cast<int64_t>(cpu_stats.bytes_read()));
-
-    // oldest_event_ts can often be set to very high values, possibly because
-    // of wrapping. Ensure that we are not overflowing to avoid ubsan
-    // complaining.
-    double oldest_event_ts = cpu_stats.oldest_event_ts() * 1e9;
-    if (oldest_event_ts >= std::numeric_limits<int64_t>::max()) {
-      storage->SetIndexedStats(stats::ftrace_cpu_oldest_event_ts_begin + phase,
-                               cpu, std::numeric_limits<int64_t>::max());
-    } else {
-      storage->SetIndexedStats(stats::ftrace_cpu_oldest_event_ts_begin + phase,
-                               cpu, static_cast<int64_t>(oldest_event_ts));
-    }
-
-    storage->SetIndexedStats(stats::ftrace_cpu_now_ts_begin + phase, cpu,
-                             static_cast<int64_t>(cpu_stats.now_ts() * 1e9));
-    storage->SetIndexedStats(stats::ftrace_cpu_dropped_events_begin + phase,
-                             cpu,
-                             static_cast<int64_t>(cpu_stats.dropped_events()));
-    storage->SetIndexedStats(stats::ftrace_cpu_read_events_begin + phase, cpu,
-                             static_cast<int64_t>(cpu_stats.read_events()));
-  }
-}
-
-PERFETTO_ALWAYS_INLINE
-util::Status FtraceParser::ParseFtraceEvent(uint32_t cpu,
-                                            const TimestampedTracePiece& ttp) {
-  using protos::pbzero::FtraceEvent;
-  int64_t ts = ttp.timestamp;
-
-  // Handle the (optional) alternative encoding format for sched_switch.
-  if (ttp.inline_event.type == InlineEvent::Type::kSchedSwitch) {
-    const auto& event = ttp.inline_event.sched_switch;
-    context_->sched_tracker->PushSchedSwitchCompact(
-        cpu, ts, event.prev_state, static_cast<uint32_t>(event.next_pid),
-        event.next_prio, event.next_comm);
-    return util::OkStatus();
-  }
-
-  // Handle the (optional) alternative encoding format for sched_waking.
-  if (ttp.inline_event.type == InlineEvent::Type::kSchedWaking) {
-    const auto& event = ttp.inline_event.sched_waking;
-    context_->sched_tracker->PushSchedWakingCompact(
-        cpu, ts, static_cast<uint32_t>(event.pid), event.target_cpu, event.prio,
-        event.comm);
-    return util::OkStatus();
-  }
-
-  const TraceBlobView& event = ttp.blob_view;
-  ProtoDecoder decoder(event.data(), event.length());
-  uint64_t raw_pid = 0;
-  if (auto pid_field = decoder.FindField(FtraceEvent::kPidFieldNumber)) {
-    raw_pid = pid_field.as_uint64();
-  } else {
-    return util::ErrStatus("Pid field not found in ftrace packet");
-  }
-  uint32_t pid = static_cast<uint32_t>(raw_pid);
-
-  for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
-    bool is_metadata_field = fld.id() == FtraceEvent::kPidFieldNumber ||
-                             fld.id() == FtraceEvent::kTimestampFieldNumber;
-    if (is_metadata_field)
-      continue;
-
-    ConstBytes data = fld.as_bytes();
-    if (fld.id() == FtraceEvent::kGenericFieldNumber) {
-      ParseGenericFtrace(ts, cpu, pid, data);
-    } else if (fld.id() != FtraceEvent::kSchedSwitchFieldNumber) {
-      // sched_switch parsing populates the raw table by itself
-      ParseTypedFtraceToRaw(fld.id(), ts, cpu, pid, data);
-    }
-
-    switch (fld.id()) {
-      case FtraceEvent::kSchedSwitchFieldNumber: {
-        ParseSchedSwitch(cpu, ts, data);
-        break;
-      }
-      case FtraceEvent::kSchedWakeupFieldNumber: {
-        ParseSchedWakeup(ts, data);
-        break;
-      }
-      case FtraceEvent::kSchedWakingFieldNumber: {
-        ParseSchedWaking(ts, data);
-        break;
-      }
-      case FtraceEvent::kSchedProcessFreeFieldNumber: {
-        ParseSchedProcessFree(ts, data);
-        break;
-      }
-      case FtraceEvent::kCpuFrequencyFieldNumber: {
-        ParseCpuFreq(ts, data);
-        break;
-      }
-      case FtraceEvent::kGpuFrequencyFieldNumber: {
-        ParseGpuFreq(ts, data);
-        break;
-      }
-      case FtraceEvent::kCpuIdleFieldNumber: {
-        ParseCpuIdle(ts, data);
-        break;
-      }
-      case FtraceEvent::kPrintFieldNumber: {
-        ParsePrint(cpu, ts, pid, data);
-        break;
-      }
-      case FtraceEvent::kZeroFieldNumber: {
-        ParseZero(cpu, ts, pid, data);
-        break;
-      }
-      case FtraceEvent::kRssStatFieldNumber: {
-        ParseRssStat(ts, pid, data);
-        break;
-      }
-      case FtraceEvent::kIonHeapGrowFieldNumber: {
-        ParseIonHeapGrowOrShrink(ts, pid, data, true);
-        break;
-      }
-      case FtraceEvent::kIonHeapShrinkFieldNumber: {
-        ParseIonHeapGrowOrShrink(ts, pid, data, false);
-        break;
-      }
-      case FtraceEvent::kSignalGenerateFieldNumber: {
-        ParseSignalGenerate(ts, data);
-        break;
-      }
-      case FtraceEvent::kSignalDeliverFieldNumber: {
-        ParseSignalDeliver(ts, pid, data);
-        break;
-      }
-      case FtraceEvent::kLowmemoryKillFieldNumber: {
-        ParseLowmemoryKill(ts, data);
-        break;
-      }
-      case FtraceEvent::kOomScoreAdjUpdateFieldNumber: {
-        ParseOOMScoreAdjUpdate(ts, data);
-        break;
-      }
-      case FtraceEvent::kMmEventRecordFieldNumber: {
-        ParseMmEventRecord(ts, pid, data);
-        break;
-      }
-      case FtraceEvent::kSysEnterFieldNumber: {
-        ParseSysEvent(ts, pid, true, data);
-        break;
-      }
-      case FtraceEvent::kSysExitFieldNumber: {
-        ParseSysEvent(ts, pid, false, data);
-        break;
-      }
-      case FtraceEvent::kTaskNewtaskFieldNumber: {
-        ParseTaskNewTask(ts, pid, data);
-        break;
-      }
-      case FtraceEvent::kTaskRenameFieldNumber: {
-        ParseTaskRename(data);
-        break;
-      }
-      case FtraceEvent::kBinderTransactionFieldNumber: {
-        ParseBinderTransaction(ts, pid, data);
-        break;
-      }
-      case FtraceEvent::kBinderTransactionReceivedFieldNumber: {
-        ParseBinderTransactionReceived(ts, pid, data);
-        break;
-      }
-      case FtraceEvent::kBinderTransactionAllocBufFieldNumber: {
-        ParseBinderTransactionAllocBuf(ts, pid, data);
-        break;
-      }
-      case FtraceEvent::kBinderLockFieldNumber: {
-        ParseBinderLock(ts, pid, data);
-        break;
-      }
-      case FtraceEvent::kBinderUnlockFieldNumber: {
-        ParseBinderUnlock(ts, pid, data);
-        break;
-      }
-      case FtraceEvent::kBinderLockedFieldNumber: {
-        ParseBinderLocked(ts, pid, data);
-        break;
-      }
-      default:
-        break;
-    }
-  }
-
-  PERFETTO_DCHECK(!decoder.bytes_left());
-  return util::OkStatus();
-}
-
-void FtraceParser::ParseGenericFtrace(int64_t ts,
-                                      uint32_t cpu,
-                                      uint32_t tid,
-                                      ConstBytes blob) {
-  protos::pbzero::GenericFtraceEvent::Decoder evt(blob.data, blob.size);
-  StringId event_id = context_->storage->InternString(evt.event_name());
-  UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
-  RowId row_id = context_->storage->mutable_raw_events()->AddRawEvent(
-      ts, event_id, cpu, utid);
-
-  for (auto it = evt.field(); it; ++it) {
-    protos::pbzero::GenericFtraceEvent::Field::Decoder fld(*it);
-    auto field_name_id = context_->storage->InternString(fld.name());
-    if (fld.has_int_value()) {
-      context_->args_tracker->AddArg(row_id, field_name_id, field_name_id,
-                                     Variadic::Integer(fld.int_value()));
-    } else if (fld.has_uint_value()) {
-      context_->args_tracker->AddArg(
-          row_id, field_name_id, field_name_id,
-          Variadic::Integer(static_cast<int64_t>(fld.uint_value())));
-    } else if (fld.has_str_value()) {
-      StringId str_value = context_->storage->InternString(fld.str_value());
-      context_->args_tracker->AddArg(row_id, field_name_id, field_name_id,
-                                     Variadic::String(str_value));
-    }
-  }
-}
-
-void FtraceParser::ParseTypedFtraceToRaw(uint32_t ftrace_id,
-                                         int64_t ts,
-                                         uint32_t cpu,
-                                         uint32_t tid,
-                                         ConstBytes blob) {
-  ProtoDecoder decoder(blob.data, blob.size);
-  if (ftrace_id >= GetDescriptorsSize()) {
-    PERFETTO_DLOG("Event with id: %d does not exist and cannot be parsed.",
-                  ftrace_id);
-    return;
-  }
-
-  MessageDescriptor* m = GetMessageDescriptorForId(ftrace_id);
-  const auto& message_strings = ftrace_message_strings_[ftrace_id];
-  UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
-  RowId raw_event_id = context_->storage->mutable_raw_events()->AddRawEvent(
-      ts, message_strings.message_name_id, cpu, utid);
-  for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
-    if (PERFETTO_UNLIKELY(fld.id() >= kMaxFtraceEventFields)) {
-      PERFETTO_DLOG(
-          "Skipping ftrace arg - proto field id is too large (%" PRIu16 ")",
-          fld.id());
-      continue;
-    }
-    ProtoSchemaType type = m->fields[fld.id()].type;
-    StringId name_id = message_strings.field_name_ids[fld.id()];
-    switch (type) {
-      case ProtoSchemaType::kInt32:
-      case ProtoSchemaType::kInt64:
-      case ProtoSchemaType::kSfixed32:
-      case ProtoSchemaType::kSfixed64:
-      case ProtoSchemaType::kSint32:
-      case ProtoSchemaType::kSint64:
-      case ProtoSchemaType::kBool:
-      case ProtoSchemaType::kEnum: {
-        context_->args_tracker->AddArg(raw_event_id, name_id, name_id,
-                                       Variadic::Integer(fld.as_int64()));
-        break;
-      }
-      case ProtoSchemaType::kUint32:
-      case ProtoSchemaType::kUint64:
-      case ProtoSchemaType::kFixed32:
-      case ProtoSchemaType::kFixed64: {
-        // Note that SQLite functions will still treat unsigned values
-        // as a signed 64 bit integers (but the translation back to ftrace
-        // refers to this storage directly).
-        context_->args_tracker->AddArg(
-            raw_event_id, name_id, name_id,
-            Variadic::UnsignedInteger(fld.as_uint64()));
-        break;
-      }
-      case ProtoSchemaType::kString:
-      case ProtoSchemaType::kBytes: {
-        StringId value = context_->storage->InternString(fld.as_string());
-        context_->args_tracker->AddArg(raw_event_id, name_id, name_id,
-                                       Variadic::String(value));
-        break;
-      }
-      case ProtoSchemaType::kDouble: {
-        context_->args_tracker->AddArg(raw_event_id, name_id, name_id,
-                                       Variadic::Real(fld.as_double()));
-        break;
-      }
-      case ProtoSchemaType::kFloat: {
-        context_->args_tracker->AddArg(
-            raw_event_id, name_id, name_id,
-            Variadic::Real(static_cast<double>(fld.as_float())));
-        break;
-      }
-      case ProtoSchemaType::kUnknown:
-      case ProtoSchemaType::kGroup:
-      case ProtoSchemaType::kMessage:
-        PERFETTO_DLOG("Could not store %s as a field in args table.",
-                      ProtoSchemaToString(type));
-        break;
-    }
-  }
-}
-
-PERFETTO_ALWAYS_INLINE
-void FtraceParser::ParseSchedSwitch(uint32_t cpu, int64_t ts, ConstBytes blob) {
-  protos::pbzero::SchedSwitchFtraceEvent::Decoder ss(blob.data, blob.size);
-  uint32_t prev_pid = static_cast<uint32_t>(ss.prev_pid());
-  uint32_t next_pid = static_cast<uint32_t>(ss.next_pid());
-  context_->sched_tracker->PushSchedSwitch(
-      cpu, ts, prev_pid, ss.prev_comm(), ss.prev_prio(), ss.prev_state(),
-      next_pid, ss.next_comm(), ss.next_prio());
-}
-
-void FtraceParser::ParseSchedWakeup(int64_t ts, ConstBytes blob) {
-  protos::pbzero::SchedWakeupFtraceEvent::Decoder sw(blob.data, blob.size);
-  uint32_t wakee_pid = static_cast<uint32_t>(sw.pid());
-  StringId name_id = context_->storage->InternString(sw.comm());
-  auto utid = context_->process_tracker->UpdateThreadName(wakee_pid, name_id);
-  context_->event_tracker->PushInstant(ts, sched_wakeup_name_id_, 0 /* value */,
-                                       utid, RefType::kRefUtid);
-}
-
-void FtraceParser::ParseSchedWaking(int64_t ts, ConstBytes blob) {
-  protos::pbzero::SchedWakingFtraceEvent::Decoder sw(blob.data, blob.size);
-  uint32_t wakee_pid = static_cast<uint32_t>(sw.pid());
-  StringId name_id = context_->storage->InternString(sw.comm());
-  auto utid = context_->process_tracker->UpdateThreadName(wakee_pid, name_id);
-  context_->event_tracker->PushInstant(ts, sched_waking_name_id_, 0 /* value */,
-                                       utid, RefType::kRefUtid);
-}
-
-void FtraceParser::ParseSchedProcessFree(int64_t ts, ConstBytes blob) {
-  protos::pbzero::SchedProcessFreeFtraceEvent::Decoder ex(blob.data, blob.size);
-  uint32_t pid = static_cast<uint32_t>(ex.pid());
-  context_->process_tracker->EndThread(ts, pid);
-}
-
-void FtraceParser::ParseCpuFreq(int64_t ts, ConstBytes blob) {
-  protos::pbzero::CpuFrequencyFtraceEvent::Decoder freq(blob.data, blob.size);
-  uint32_t cpu = freq.cpu_id();
-  uint32_t new_freq = freq.state();
-  TrackId track =
-      context_->track_tracker->InternCpuCounterTrack(cpu_freq_name_id_, cpu);
-  context_->event_tracker->PushCounter(ts, new_freq, track);
-}
-
-void FtraceParser::ParseGpuFreq(int64_t ts, ConstBytes blob) {
-  protos::pbzero::GpuFrequencyFtraceEvent::Decoder freq(blob.data, blob.size);
-  uint32_t gpu = freq.gpu_id();
-  uint32_t new_freq = freq.state();
-  TrackId track =
-      context_->track_tracker->InternGpuCounterTrack(gpu_freq_name_id_, gpu);
-  context_->event_tracker->PushCounter(ts, new_freq, track);
-}
-
-void FtraceParser::ParseCpuIdle(int64_t ts, ConstBytes blob) {
-  protos::pbzero::CpuIdleFtraceEvent::Decoder idle(blob.data, blob.size);
-  uint32_t cpu = idle.cpu_id();
-  uint32_t new_state = idle.state();
-  TrackId track =
-      context_->track_tracker->InternCpuCounterTrack(cpu_idle_name_id_, cpu);
-  context_->event_tracker->PushCounter(ts, new_state, track);
-}
-
-void FtraceParser::ParsePrint(uint32_t,
-                              int64_t ts,
-                              uint32_t pid,
-                              ConstBytes blob) {
-  protos::pbzero::PrintFtraceEvent::Decoder evt(blob.data, blob.size);
-  context_->systrace_parser->ParsePrintEvent(ts, pid, evt.buf());
-}
-
-void FtraceParser::ParseZero(uint32_t,
-                             int64_t ts,
-                             uint32_t pid,
-                             ConstBytes blob) {
-  protos::pbzero::ZeroFtraceEvent::Decoder evt(blob.data, blob.size);
-  uint32_t tgid = static_cast<uint32_t>(evt.pid());
-  context_->systrace_parser->ParseZeroEvent(ts, pid, evt.flag(), evt.name(),
-                                            tgid, evt.value());
-}
-
-void FtraceParser::ParseRssStat(int64_t ts, uint32_t pid, ConstBytes blob) {
-  protos::pbzero::RssStatFtraceEvent::Decoder rss(blob.data, blob.size);
-  const auto kRssStatUnknown = static_cast<uint32_t>(rss_members_.size()) - 1;
-  auto member = static_cast<uint32_t>(rss.member());
-  int64_t size = rss.size();
-  if (member >= rss_members_.size()) {
-    context_->storage->IncrementStats(stats::rss_stat_unknown_keys);
-    member = kRssStatUnknown;
-  }
-
-  if (size >= 0) {
-    UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
-    context_->event_tracker->PushProcessCounterForThread(
-        ts, size, rss_members_[member], utid);
-  } else {
-    context_->storage->IncrementStats(stats::rss_stat_negative_size);
-  }
-}
-
-void FtraceParser::ParseIonHeapGrowOrShrink(int64_t ts,
-                                            uint32_t pid,
-                                            ConstBytes blob,
-                                            bool grow) {
-  protos::pbzero::IonHeapGrowFtraceEvent::Decoder ion(blob.data, blob.size);
-  int64_t change_bytes = static_cast<int64_t>(ion.len()) * (grow ? 1 : -1);
-  // The total_allocated ftrace event reports the value before the
-  // atomic_long_add / sub takes place.
-  int64_t total_bytes = ion.total_allocated() + change_bytes;
-  StringId global_name_id = ion_total_unknown_id_;
-  StringId change_name_id = ion_change_unknown_id_;
-
-  if (ion.has_heap_name()) {
-    char counter_name[255];
-    base::StringView heap_name = ion.heap_name();
-    snprintf(counter_name, sizeof(counter_name), "mem.ion.%.*s",
-             int(heap_name.size()), heap_name.data());
-    global_name_id = context_->storage->InternString(counter_name);
-    snprintf(counter_name, sizeof(counter_name), "mem.ion_change.%.*s",
-             int(heap_name.size()), heap_name.data());
-    change_name_id = context_->storage->InternString(counter_name);
-  }
-
-  // Push the global counter.
-  TrackId track =
-      context_->track_tracker->InternGlobalCounterTrack(global_name_id);
-  context_->event_tracker->PushCounter(ts, total_bytes, track);
-
-  // Push the change counter.
-  // TODO(b/121331269): these should really be instant events. For now we
-  // manually reset them to 0 after 1ns.
-  UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
-  track =
-      context_->track_tracker->InternThreadCounterTrack(change_name_id, utid);
-  context_->event_tracker->PushCounter(ts, change_bytes, track);
-  context_->event_tracker->PushCounter(ts + 1, 0, track);
-
-  // We are reusing the same function for ion_heap_grow and ion_heap_shrink.
-  // It is fine as the arguments are the same, but we need to be sure that the
-  // protobuf field id for both are the same.
-  static_assert(
-      static_cast<int>(
-          protos::pbzero::IonHeapGrowFtraceEvent::kTotalAllocatedFieldNumber) ==
-              static_cast<int>(protos::pbzero::IonHeapShrinkFtraceEvent::
-                                   kTotalAllocatedFieldNumber) &&
-          static_cast<int>(
-              protos::pbzero::IonHeapGrowFtraceEvent::kLenFieldNumber) ==
-              static_cast<int>(
-                  protos::pbzero::IonHeapShrinkFtraceEvent::kLenFieldNumber) &&
-          static_cast<int>(
-              protos::pbzero::IonHeapGrowFtraceEvent::kHeapNameFieldNumber) ==
-              static_cast<int>(protos::pbzero::IonHeapShrinkFtraceEvent::
-                                   kHeapNameFieldNumber),
-      "ION field mismatch");
-}
-
-// This event has both the pid of the thread that sent the signal and the
-// destination of the signal. Currently storing the pid of the destination.
-void FtraceParser::ParseSignalGenerate(int64_t ts, ConstBytes blob) {
-  protos::pbzero::SignalGenerateFtraceEvent::Decoder sig(blob.data, blob.size);
-
-  UniqueTid utid = context_->process_tracker->GetOrCreateThread(
-      static_cast<uint32_t>(sig.pid()));
-  context_->event_tracker->PushInstant(ts, signal_generate_id_, sig.sig(), utid,
-                                       RefType::kRefUtid);
-}
-
-void FtraceParser::ParseSignalDeliver(int64_t ts,
-                                      uint32_t pid,
-                                      ConstBytes blob) {
-  protos::pbzero::SignalDeliverFtraceEvent::Decoder sig(blob.data, blob.size);
-  UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
-  context_->event_tracker->PushInstant(ts, signal_deliver_id_, sig.sig(), utid,
-                                       RefType::kRefUtid);
-}
-
-void FtraceParser::ParseLowmemoryKill(int64_t ts, ConstBytes blob) {
-  // TODO(taylori): Store the pagecache_size, pagecache_limit and free fields
-  // in an args table
-  protos::pbzero::LowmemoryKillFtraceEvent::Decoder lmk(blob.data, blob.size);
-
-  // Store the pid of the event that is lmk-ed.
-  auto pid = static_cast<uint32_t>(lmk.pid());
-  auto opt_utid = context_->process_tracker->GetThreadOrNull(pid);
-
-  // Don't add LMK events for threads we've never seen before. This works around
-  // the case where we get an LMK event after a thread has already been killed.
-  if (!opt_utid)
-    return;
-
-  auto row_id = context_->event_tracker->PushInstant(
-      ts, lmk_id_, 0, opt_utid.value(), RefType::kRefUtid, true);
-
-  // Store the comm as an arg.
-  auto comm_id = context_->storage->InternString(
-      lmk.has_comm() ? lmk.comm() : base::StringView());
-  context_->args_tracker->AddArg(row_id, comm_name_id_, comm_name_id_,
-                                 Variadic::String(comm_id));
-}
-
-void FtraceParser::ParseOOMScoreAdjUpdate(int64_t ts, ConstBytes blob) {
-  protos::pbzero::OomScoreAdjUpdateFtraceEvent::Decoder evt(blob.data,
-                                                            blob.size);
-  // The int16_t static cast is because older version of the on-device tracer
-  // had a bug on negative varint encoding (b/120618641).
-  int16_t oom_adj = static_cast<int16_t>(evt.oom_score_adj());
-  uint32_t tid = static_cast<uint32_t>(evt.pid());
-  UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
-  context_->event_tracker->PushProcessCounterForThread(ts, oom_adj,
-                                                       oom_score_adj_id_, utid);
-}
-
-void FtraceParser::ParseMmEventRecord(int64_t ts,
-                                      uint32_t pid,
-                                      ConstBytes blob) {
-  protos::pbzero::MmEventRecordFtraceEvent::Decoder evt(blob.data, blob.size);
-  uint32_t type = evt.type();
-  UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
-
-  if (type >= mm_event_counter_names_.size()) {
-    context_->storage->IncrementStats(stats::mm_unknown_type);
-    return;
-  }
-
-  const auto& counter_names = mm_event_counter_names_[type];
-  context_->event_tracker->PushProcessCounterForThread(
-      ts, evt.count(), counter_names.count, utid);
-  context_->event_tracker->PushProcessCounterForThread(
-      ts, evt.max_lat(), counter_names.max_lat, utid);
-  context_->event_tracker->PushProcessCounterForThread(
-      ts, evt.avg_lat(), counter_names.avg_lat, utid);
-}
-
-void FtraceParser::ParseSysEvent(int64_t ts,
-                                 uint32_t pid,
-                                 bool is_enter,
-                                 ConstBytes blob) {
-  protos::pbzero::SysEnterFtraceEvent::Decoder evt(blob.data, blob.size);
-  uint32_t syscall_num = static_cast<uint32_t>(evt.id());
-  UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
-
-  if (is_enter) {
-    context_->syscall_tracker->Enter(ts, utid, syscall_num);
-  } else {
-    context_->syscall_tracker->Exit(ts, utid, syscall_num);
-  }
-
-  // We are reusing the same function for sys_enter and sys_exit.
-  // It is fine as the arguments are the same, but we need to be sure that the
-  // protobuf field id for both are the same.
-  static_assert(
-      static_cast<int>(protos::pbzero::SysEnterFtraceEvent::kIdFieldNumber) ==
-          static_cast<int>(protos::pbzero::SysExitFtraceEvent::kIdFieldNumber),
-      "field mismatch");
-}
-
-void FtraceParser::ParseTaskNewTask(int64_t ts,
-                                    uint32_t source_tid,
-                                    ConstBytes blob) {
-  protos::pbzero::TaskNewtaskFtraceEvent::Decoder evt(blob.data, blob.size);
-  uint32_t clone_flags = static_cast<uint32_t>(evt.clone_flags());
-  uint32_t new_tid = static_cast<uint32_t>(evt.pid());
-  StringId new_comm = context_->storage->InternString(evt.comm());
-  auto* proc_tracker = context_->process_tracker.get();
-
-  // task_newtask is raised both in the case of a new process creation (fork()
-  // family) and thread creation (clone(CLONE_THREAD, ...)).
-  static const uint32_t kCloneThread = 0x00010000;  // From kernel's sched.h.
-
-  // If the process is a fork, start a new process except if the source tid is
-  // kthreadd in which case just make it a new thread associated with kthreadd.
-  if ((clone_flags & kCloneThread) == 0 && source_tid != kKthreaddPid) {
-    // This is a plain-old fork() or equivalent.
-    proc_tracker->StartNewProcess(ts, source_tid, new_tid, new_comm);
-    return;
-  }
-
-  if (source_tid == kKthreaddPid) {
-    context_->process_tracker->SetProcessMetadata(kKthreaddPid, base::nullopt,
-                                                  kKthreaddName);
-  }
-
-  // This is a pthread_create or similar. Bind the two threads together, so
-  // they get resolved to the same process.
-  auto source_utid = proc_tracker->GetOrCreateThread(source_tid);
-  auto new_utid = proc_tracker->StartNewThread(ts, new_tid, new_comm);
-  proc_tracker->AssociateThreads(source_utid, new_utid);
-}
-
-void FtraceParser::ParseTaskRename(ConstBytes blob) {
-  protos::pbzero::TaskRenameFtraceEvent::Decoder evt(blob.data, blob.size);
-  uint32_t tid = static_cast<uint32_t>(evt.pid());
-  StringId comm = context_->storage->InternString(evt.newcomm());
-  context_->process_tracker->UpdateThreadName(tid, comm);
-  context_->process_tracker->UpdateProcessNameFromThreadName(tid, comm);
-}
-
-void FtraceParser::ParseBinderTransaction(int64_t timestamp,
-                                          uint32_t pid,
-                                          ConstBytes blob) {
-  protos::pbzero::BinderTransactionFtraceEvent::Decoder evt(blob.data,
-                                                            blob.size);
-  context_->binder_tracker->Transaction(timestamp, pid);
-}
-
-void FtraceParser::ParseBinderTransactionReceived(int64_t timestamp,
-                                                  uint32_t pid,
-                                                  ConstBytes blob) {
-  protos::pbzero::BinderTransactionReceivedFtraceEvent::Decoder evt(blob.data,
-                                                                    blob.size);
-  context_->binder_tracker->TransactionReceived(timestamp, pid);
-}
-
-void FtraceParser::ParseBinderTransactionAllocBuf(int64_t timestamp,
-                                                  uint32_t pid,
-                                                  ConstBytes blob) {
-  protos::pbzero::BinderTransactionAllocBufFtraceEvent::Decoder evt(blob.data,
-                                                                    blob.size);
-  context_->binder_tracker->TransactionAllocBuf(timestamp, pid);
-}
-
-void FtraceParser::ParseBinderLocked(int64_t timestamp,
-                                     uint32_t pid,
-                                     ConstBytes blob) {
-  protos::pbzero::BinderLockedFtraceEvent::Decoder evt(blob.data, blob.size);
-  context_->binder_tracker->Locked(timestamp, pid);
-}
-
-void FtraceParser::ParseBinderLock(int64_t timestamp,
-                                   uint32_t pid,
-                                   ConstBytes blob) {
-  protos::pbzero::BinderLockFtraceEvent::Decoder evt(blob.data, blob.size);
-  context_->binder_tracker->Lock(timestamp, pid);
-}
-
-void FtraceParser::ParseBinderUnlock(int64_t timestamp,
-                                     uint32_t pid,
-                                     ConstBytes blob) {
-  protos::pbzero::BinderUnlockFtraceEvent::Decoder evt(blob.data, blob.size);
-  context_->binder_tracker->Unlock(timestamp, pid);
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.h b/src/trace_processor/importers/ftrace/ftrace_parser.h
deleted file mode 100644
index 3d7138b..0000000
--- a/src/trace_processor/importers/ftrace/ftrace_parser.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_FTRACE_PARSER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_FTRACE_PARSER_H_
-
-#include "perfetto/trace_processor/status.h"
-#include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/importers/ftrace/ftrace_descriptors.h"
-#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
-#include "src/trace_processor/timestamped_trace_piece.h"
-#include "src/trace_processor/trace_blob_view.h"
-#include "src/trace_processor/trace_processor_context.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class FtraceParser {
- public:
-  explicit FtraceParser(TraceProcessorContext* context);
-
-  void ParseFtraceStats(protozero::ConstBytes);
-
-  util::Status ParseFtraceEvent(uint32_t cpu, const TimestampedTracePiece& ttp);
-
- private:
-  void ParseGenericFtrace(int64_t timestamp,
-                          uint32_t cpu,
-                          uint32_t pid,
-                          protozero::ConstBytes);
-  void ParseTypedFtraceToRaw(uint32_t ftrace_id,
-                             int64_t timestamp,
-                             uint32_t cpu,
-                             uint32_t pid,
-                             protozero::ConstBytes);
-  void ParseSchedSwitch(uint32_t cpu, int64_t timestamp, protozero::ConstBytes);
-  void ParseSchedWakeup(int64_t timestamp, protozero::ConstBytes);
-  void ParseSchedWaking(int64_t timestamp, protozero::ConstBytes);
-  void ParseSchedProcessFree(int64_t timestamp, protozero::ConstBytes);
-  void ParseCpuFreq(int64_t timestamp, protozero::ConstBytes);
-  void ParseGpuFreq(int64_t timestamp, protozero::ConstBytes);
-  void ParseCpuIdle(int64_t timestamp, protozero::ConstBytes);
-  void ParsePrint(uint32_t cpu,
-                  int64_t timestamp,
-                  uint32_t pid,
-                  protozero::ConstBytes);
-  void ParseZero(uint32_t cpu,
-                 int64_t timestamp,
-                 uint32_t pid,
-                 protozero::ConstBytes);
-  void ParseRssStat(int64_t ts, uint32_t pid, protozero::ConstBytes);
-  void ParseIonHeapGrowOrShrink(int64_t ts,
-                                uint32_t pid,
-                                protozero::ConstBytes,
-                                bool grow);
-  void ParseSignalGenerate(int64_t ts, protozero::ConstBytes);
-  void ParseSignalDeliver(int64_t ts, uint32_t pid, protozero::ConstBytes);
-  void ParseLowmemoryKill(int64_t ts, protozero::ConstBytes);
-  void ParseOOMScoreAdjUpdate(int64_t ts, protozero::ConstBytes);
-  void ParseMmEventRecord(int64_t ts, uint32_t pid, protozero::ConstBytes);
-  void ParseSysEvent(int64_t ts,
-                     uint32_t pid,
-                     bool is_enter,
-                     protozero::ConstBytes);
-  void ParseTaskNewTask(int64_t timestamp,
-                        uint32_t source_tid,
-                        protozero::ConstBytes);
-  void ParseTaskRename(protozero::ConstBytes);
-  void ParseBinderTransaction(int64_t timestamp,
-                              uint32_t pid,
-                              protozero::ConstBytes);
-  void ParseBinderTransactionReceived(int64_t timestamp,
-                                      uint32_t pid,
-                                      protozero::ConstBytes);
-  void ParseBinderTransactionAllocBuf(int64_t timestamp,
-                                      uint32_t pid,
-                                      protozero::ConstBytes);
-  void ParseBinderLocked(int64_t timestamp,
-                         uint32_t pid,
-                         protozero::ConstBytes);
-  void ParseBinderLock(int64_t timestamp, uint32_t pid, protozero::ConstBytes);
-  void ParseBinderUnlock(int64_t timestamp,
-                         uint32_t pid,
-                         protozero::ConstBytes);
-
-  TraceProcessorContext* context_;
-
-  const StringId sched_wakeup_name_id_;
-  const StringId sched_waking_name_id_;
-  const StringId cpu_freq_name_id_;
-  const StringId gpu_freq_name_id_;
-  const StringId cpu_idle_name_id_;
-  const StringId ion_total_unknown_id_;
-  const StringId ion_change_unknown_id_;
-  const StringId signal_generate_id_;
-  const StringId signal_deliver_id_;
-  const StringId oom_score_adj_id_;
-  const StringId lmk_id_;
-  const StringId comm_name_id_;
-
-  std::vector<StringId> rss_members_;
-
-  struct FtraceMessageStrings {
-    // The string id of name of the event field (e.g. sched_switch's id).
-    StringId message_name_id = 0;
-    std::array<StringId, kMaxFtraceEventFields> field_name_ids;
-  };
-  std::vector<FtraceMessageStrings> ftrace_message_strings_;
-
-  struct MmEventCounterNames {
-    MmEventCounterNames() = default;
-    MmEventCounterNames(StringId _count, StringId _max_lat, StringId _avg_lat)
-        : count(_count), max_lat(_max_lat), avg_lat(_avg_lat) {}
-
-    StringId count = 0;
-    StringId max_lat = 0;
-    StringId avg_lat = 0;
-  };
-
-  // Keep kMmEventCounterSize equal to mm_event_type::MM_TYPE_NUM in the kernel.
-  static constexpr size_t kMmEventCounterSize = 7;
-  std::array<MmEventCounterNames, kMmEventCounterSize> mm_event_counter_names_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_FTRACE_PARSER_H_
diff --git a/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc b/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc
deleted file mode 100644
index 4319e2d..0000000
--- a/src/trace_processor/importers/ftrace/ftrace_tokenizer.cc
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/importers/ftrace/ftrace_tokenizer.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/protozero/proto_decoder.h"
-#include "perfetto/protozero/proto_utils.h"
-#include "src/trace_processor/stats.h"
-#include "src/trace_processor/trace_sorter.h"
-#include "src/trace_processor/trace_storage.h"
-
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-using protozero::ProtoDecoder;
-using protozero::proto_utils::MakeTagLengthDelimited;
-using protozero::proto_utils::MakeTagVarInt;
-using protozero::proto_utils::ParseVarInt;
-
-PERFETTO_ALWAYS_INLINE
-void FtraceTokenizer::TokenizeFtraceBundle(TraceBlobView bundle) {
-  protos::pbzero::FtraceEventBundle::Decoder decoder(bundle.data(),
-                                                     bundle.length());
-
-  if (PERFETTO_UNLIKELY(!decoder.has_cpu())) {
-    PERFETTO_ELOG("CPU field not found in FtraceEventBundle");
-    context_->storage->IncrementStats(stats::ftrace_bundle_tokenizer_errors);
-    return;
-  }
-
-  uint32_t cpu = decoder.cpu();
-  if (PERFETTO_UNLIKELY(cpu > base::kMaxCpus)) {
-    PERFETTO_ELOG("CPU larger than kMaxCpus (%u > %zu)", cpu, base::kMaxCpus);
-    return;
-  }
-
-  if (decoder.has_compact_sched()) {
-    TokenizeFtraceCompactSched(cpu, decoder.compact_sched().data,
-                               decoder.compact_sched().size);
-  }
-
-  for (auto it = decoder.event(); it; ++it) {
-    protozero::ConstBytes event = *it;
-    size_t off = bundle.offset_of(event.data);
-    TokenizeFtraceEvent(cpu, bundle.slice(off, event.size));
-  }
-  context_->sorter->FinalizeFtraceEventBatch(cpu);
-}
-
-PERFETTO_ALWAYS_INLINE
-void FtraceTokenizer::TokenizeFtraceEvent(uint32_t cpu, TraceBlobView event) {
-  constexpr auto kTimestampFieldNumber =
-      protos::pbzero::FtraceEvent::kTimestampFieldNumber;
-  const uint8_t* data = event.data();
-  const size_t length = event.length();
-  ProtoDecoder decoder(data, length);
-  uint64_t raw_timestamp = 0;
-  bool timestamp_found = false;
-
-  // Speculate on the fact that the timestamp is often the 1st field of the
-  // event.
-  constexpr auto timestampFieldTag = MakeTagVarInt(kTimestampFieldNumber);
-  if (PERFETTO_LIKELY(length > 10 && data[0] == timestampFieldTag)) {
-    // Fastpath.
-    const uint8_t* next = ParseVarInt(data + 1, data + 11, &raw_timestamp);
-    timestamp_found = next != data + 1;
-    decoder.Reset(next);
-  } else {
-    // Slowpath.
-    if (auto ts_field = decoder.FindField(kTimestampFieldNumber)) {
-      timestamp_found = true;
-      raw_timestamp = ts_field.as_uint64();
-    }
-  }
-
-  if (PERFETTO_UNLIKELY(!timestamp_found)) {
-    PERFETTO_ELOG("Timestamp field not found in FtraceEvent");
-    context_->storage->IncrementStats(stats::ftrace_bundle_tokenizer_errors);
-    return;
-  }
-
-  int64_t timestamp = static_cast<int64_t>(raw_timestamp);
-
-  // We don't need to parse this packet, just push it to be sorted with
-  // the timestamp.
-  context_->sorter->PushFtraceEvent(cpu, timestamp, std::move(event));
-}
-
-PERFETTO_ALWAYS_INLINE
-void FtraceTokenizer::TokenizeFtraceCompactSched(uint32_t cpu,
-                                                 const uint8_t* data,
-                                                 size_t size) {
-  protos::pbzero::FtraceEventBundle::CompactSched::Decoder compact_sched(data,
-                                                                         size);
-  // Build the interning table for comm fields.
-  std::vector<StringId> string_table;
-  string_table.reserve(512);
-  for (auto it = compact_sched.intern_table(); it; it++) {
-    StringId value = context_->storage->InternString(*it);
-    string_table.push_back(value);
-  }
-
-  TokenizeFtraceCompactSchedSwitch(cpu, compact_sched, string_table);
-  TokenizeFtraceCompactSchedWaking(cpu, compact_sched, string_table);
-}
-
-void FtraceTokenizer::TokenizeFtraceCompactSchedSwitch(
-    uint32_t cpu,
-    const protos::pbzero::FtraceEventBundle::CompactSched::Decoder& compact,
-    const std::vector<StringId>& string_table) {
-  // Accumulator for timestamp deltas.
-  int64_t timestamp_acc = 0;
-
-  // The events' fields are stored in a structure-of-arrays style, using packed
-  // repeated fields. Walk each repeated field in step to recover individual
-  // events.
-  bool parse_error = false;
-  auto timestamp_it = compact.switch_timestamp(&parse_error);
-  auto pstate_it = compact.switch_prev_state(&parse_error);
-  auto npid_it = compact.switch_next_pid(&parse_error);
-  auto nprio_it = compact.switch_next_prio(&parse_error);
-  auto comm_it = compact.switch_next_comm_index(&parse_error);
-  for (; timestamp_it && pstate_it && npid_it && nprio_it && comm_it;
-       ++timestamp_it, ++pstate_it, ++npid_it, ++nprio_it, ++comm_it) {
-    InlineSchedSwitch event{};
-
-    // delta-encoded timestamp
-    timestamp_acc += static_cast<int64_t>(*timestamp_it);
-    int64_t event_timestamp = timestamp_acc;
-
-    // index into the interned string table
-    PERFETTO_DCHECK(*comm_it < string_table.size());
-    event.next_comm = string_table[*comm_it];
-
-    event.prev_state = *pstate_it;
-    event.next_pid = *npid_it;
-    event.next_prio = *nprio_it;
-
-    context_->sorter->PushInlineFtraceEvent(cpu, event_timestamp,
-                                            InlineEvent::SchedSwitch(event));
-  }
-
-  // Check that all packed buffers were decoded correctly, and fully.
-  bool sizes_match =
-      !timestamp_it && !pstate_it && !npid_it && !nprio_it && !comm_it;
-  if (parse_error || !sizes_match)
-    context_->storage->IncrementStats(stats::compact_sched_has_parse_errors);
-}
-
-void FtraceTokenizer::TokenizeFtraceCompactSchedWaking(
-    uint32_t cpu,
-    const protos::pbzero::FtraceEventBundle::CompactSched::Decoder& compact,
-    const std::vector<StringId>& string_table) {
-  // Accumulator for timestamp deltas.
-  int64_t timestamp_acc = 0;
-
-  // The events' fields are stored in a structure-of-arrays style, using packed
-  // repeated fields. Walk each repeated field in step to recover individual
-  // events.
-  bool parse_error = false;
-  auto timestamp_it = compact.waking_timestamp(&parse_error);
-  auto pid_it = compact.waking_pid(&parse_error);
-  auto tcpu_it = compact.waking_target_cpu(&parse_error);
-  auto prio_it = compact.waking_prio(&parse_error);
-  auto comm_it = compact.waking_comm_index(&parse_error);
-
-  for (; timestamp_it && pid_it && tcpu_it && prio_it && comm_it;
-       ++timestamp_it, ++pid_it, ++tcpu_it, ++prio_it, ++comm_it) {
-    InlineSchedWaking event{};
-
-    // delta-encoded timestamp
-    timestamp_acc += static_cast<int64_t>(*timestamp_it);
-    int64_t event_timestamp = timestamp_acc;
-
-    // index into the interned string table
-    PERFETTO_DCHECK(*comm_it < string_table.size());
-    event.comm = string_table[*comm_it];
-
-    event.pid = *pid_it;
-    event.target_cpu = *tcpu_it;
-    event.prio = *prio_it;
-
-    context_->sorter->PushInlineFtraceEvent(cpu, event_timestamp,
-                                            InlineEvent::SchedWaking(event));
-  }
-
-  // Check that all packed buffers were decoded correctly, and fully.
-  bool sizes_match =
-      !timestamp_it && !pid_it && !tcpu_it && !prio_it && !comm_it;
-  if (parse_error || !sizes_match)
-    context_->storage->IncrementStats(stats::compact_sched_has_parse_errors);
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/ftrace/ftrace_tokenizer.h b/src/trace_processor/importers/ftrace/ftrace_tokenizer.h
deleted file mode 100644
index 8d1007f..0000000
--- a/src/trace_processor/importers/ftrace/ftrace_tokenizer.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_FTRACE_TOKENIZER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_FTRACE_TOKENIZER_H_
-
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-#include "src/trace_processor/trace_blob_view.h"
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class FtraceTokenizer {
- public:
-  explicit FtraceTokenizer(TraceProcessorContext* context)
-      : context_(context) {}
-
-  void TokenizeFtraceBundle(TraceBlobView bundle);
-
- private:
-  void TokenizeFtraceEvent(uint32_t cpu, TraceBlobView event);
-  void TokenizeFtraceCompactSched(uint32_t cpu,
-                                  const uint8_t* data,
-                                  size_t size);
-  void TokenizeFtraceCompactSchedSwitch(
-      uint32_t cpu,
-      const protos::pbzero::FtraceEventBundle::CompactSched::Decoder& compact,
-      const std::vector<StringId>& string_table);
-  void TokenizeFtraceCompactSchedWaking(
-      uint32_t cpu,
-      const protos::pbzero::FtraceEventBundle::CompactSched::Decoder& compact,
-      const std::vector<StringId>& string_table);
-
-  TraceProcessorContext* context_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_FTRACE_TOKENIZER_H_
diff --git a/src/trace_processor/importers/ftrace/sched_event_tracker.cc b/src/trace_processor/importers/ftrace/sched_event_tracker.cc
deleted file mode 100644
index a4027f6..0000000
--- a/src/trace_processor/importers/ftrace/sched_event_tracker.cc
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/importers/ftrace/sched_event_tracker.h"
-
-#include <math.h>
-
-#include "perfetto/ext/base/utils.h"
-#include "src/trace_processor/args_tracker.h"
-#include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/ftrace_utils.h"
-#include "src/trace_processor/importers/ftrace/ftrace_descriptors.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/stats.h"
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/variadic.h"
-
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/sched.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-SchedEventTracker::SchedEventTracker(TraceProcessorContext* context)
-    : context_(context) {
-  // pre-parse sched_switch
-  auto* switch_descriptor = GetMessageDescriptorForId(
-      protos::pbzero::FtraceEvent::kSchedSwitchFieldNumber);
-  PERFETTO_CHECK(switch_descriptor->max_field_id == kSchedSwitchMaxFieldId);
-
-  for (size_t i = 1; i <= kSchedSwitchMaxFieldId; i++) {
-    sched_switch_field_ids_[i] =
-        context->storage->InternString(switch_descriptor->fields[i].name);
-  }
-  sched_switch_id_ = context->storage->InternString(switch_descriptor->name);
-
-  // pre-parse sched_waking
-  auto* waking_descriptor = GetMessageDescriptorForId(
-      protos::pbzero::FtraceEvent::kSchedWakingFieldNumber);
-  PERFETTO_CHECK(waking_descriptor->max_field_id == kSchedWakingMaxFieldId);
-
-  for (size_t i = 1; i <= kSchedWakingMaxFieldId; i++) {
-    sched_waking_field_ids_[i] =
-        context->storage->InternString(waking_descriptor->fields[i].name);
-  }
-  sched_waking_id_ = context->storage->InternString(waking_descriptor->name);
-}
-
-SchedEventTracker::~SchedEventTracker() = default;
-
-void SchedEventTracker::PushSchedSwitch(uint32_t cpu,
-                                        int64_t ts,
-                                        uint32_t prev_pid,
-                                        base::StringView prev_comm,
-                                        int32_t prev_prio,
-                                        int64_t prev_state,
-                                        uint32_t next_pid,
-                                        base::StringView next_comm,
-                                        int32_t next_prio) {
-  // At this stage all events should be globally timestamp ordered.
-  if (ts < context_->event_tracker->max_timestamp()) {
-    PERFETTO_ELOG("sched_switch event out of order by %.4f ms, skipping",
-                  (context_->event_tracker->max_timestamp() - ts) / 1e6);
-    context_->storage->IncrementStats(stats::sched_switch_out_of_order);
-    return;
-  }
-  context_->event_tracker->UpdateMaxTimestamp(ts);
-  PERFETTO_DCHECK(cpu < base::kMaxCpus);
-
-  StringId next_comm_id = context_->storage->InternString(next_comm);
-  auto next_utid =
-      context_->process_tracker->UpdateThreadName(next_pid, next_comm_id);
-
-  // First use this data to close the previous slice.
-  bool prev_pid_match_prev_next_pid = false;
-  auto* pending_sched = &pending_sched_per_cpu_[cpu];
-  size_t pending_slice_idx = pending_sched->pending_slice_storage_idx;
-  if (pending_slice_idx < std::numeric_limits<size_t>::max()) {
-    prev_pid_match_prev_next_pid = prev_pid == pending_sched->last_pid;
-    if (PERFETTO_LIKELY(prev_pid_match_prev_next_pid)) {
-      ClosePendingSlice(pending_slice_idx, ts, prev_state);
-    } else {
-      // If the pids are not consistent, make a note of this.
-      context_->storage->IncrementStats(stats::mismatched_sched_switch_tids);
-    }
-  }
-
-  // We have to intern prev_comm again because our assumption that
-  // this event's |prev_comm| == previous event's |next_comm| does not hold
-  // if the thread changed its name while scheduled.
-  StringId prev_comm_id = context_->storage->InternString(prev_comm);
-  UniqueTid prev_utid =
-      context_->process_tracker->UpdateThreadName(prev_pid, prev_comm_id);
-
-  auto new_slice_idx = AddRawEventAndStartSlice(
-      cpu, ts, prev_utid, prev_pid, prev_comm_id, prev_prio, prev_state,
-      next_utid, next_pid, next_comm_id, next_prio);
-
-  // Finally, update the info for the next sched switch on this CPU.
-  pending_sched->pending_slice_storage_idx = new_slice_idx;
-  pending_sched->last_pid = next_pid;
-  pending_sched->last_utid = next_utid;
-  pending_sched->last_prio = next_prio;
-}
-
-void SchedEventTracker::PushSchedSwitchCompact(uint32_t cpu,
-                                               int64_t ts,
-                                               int64_t prev_state,
-                                               uint32_t next_pid,
-                                               int32_t next_prio,
-                                               StringId next_comm_id) {
-  // At this stage all events should be globally timestamp ordered.
-  if (ts < context_->event_tracker->max_timestamp()) {
-    PERFETTO_ELOG("sched_switch event out of order by %.4f ms, skipping",
-                  (context_->event_tracker->max_timestamp() - ts) / 1e6);
-    context_->storage->IncrementStats(stats::sched_switch_out_of_order);
-    return;
-  }
-  context_->event_tracker->UpdateMaxTimestamp(ts);
-  PERFETTO_DCHECK(cpu < base::kMaxCpus);
-
-  auto next_utid =
-      context_->process_tracker->UpdateThreadName(next_pid, next_comm_id);
-
-  auto* pending_sched = &pending_sched_per_cpu_[cpu];
-
-  // If we're processing the first compact event for this cpu, don't start a
-  // slice since we're missing the "prev_*" fields. The successive events will
-  // create slices as normal, but the first per-cpu switch is effectively
-  // discarded.
-  if (pending_sched->last_utid == std::numeric_limits<UniqueTid>::max()) {
-    context_->storage->IncrementStats(stats::compact_sched_switch_skipped);
-
-    pending_sched->last_pid = next_pid;
-    pending_sched->last_utid = next_utid;
-    pending_sched->last_prio = next_prio;
-    // Note: no pending slice, so leave |pending_slice_storage_idx| in its
-    // invalid state.
-    return;
-  }
-
-  // Close the pending slice if any (we won't have one when processing the first
-  // two compact events for a given cpu).
-  size_t pending_slice_idx = pending_sched->pending_slice_storage_idx;
-  if (pending_slice_idx < std::numeric_limits<size_t>::max())
-    ClosePendingSlice(pending_slice_idx, ts, prev_state);
-
-  // Use the previous event's values to infer this event's "prev_*" fields.
-  // There are edge cases, but this assumption should still produce sensible
-  // results in the absence of data loss.
-  UniqueTid prev_utid = pending_sched->last_utid;
-  uint32_t prev_pid = pending_sched->last_pid;
-  int32_t prev_prio = pending_sched->last_prio;
-
-  // Do a fresh task name lookup in case it was updated by a task_rename while
-  // scheduled.
-  const auto& prev_thread = context_->storage->GetThread(prev_utid);
-  StringId prev_comm_id = prev_thread.name_id;
-
-  auto new_slice_idx = AddRawEventAndStartSlice(
-      cpu, ts, prev_utid, prev_pid, prev_comm_id, prev_prio, prev_state,
-      next_utid, next_pid, next_comm_id, next_prio);
-
-  // Finally, update the info for the next sched switch on this CPU.
-  pending_sched->pending_slice_storage_idx = new_slice_idx;
-  pending_sched->last_pid = next_pid;
-  pending_sched->last_utid = next_utid;
-  pending_sched->last_prio = next_prio;
-}
-
-PERFETTO_ALWAYS_INLINE
-size_t SchedEventTracker::AddRawEventAndStartSlice(uint32_t cpu,
-                                                   int64_t ts,
-                                                   UniqueTid prev_utid,
-                                                   uint32_t prev_pid,
-                                                   StringId prev_comm_id,
-                                                   int32_t prev_prio,
-                                                   int64_t prev_state,
-                                                   UniqueTid next_utid,
-                                                   uint32_t next_pid,
-                                                   StringId next_comm_id,
-                                                   int32_t next_prio) {
-  // Push the raw event - this is done as the raw ftrace event codepath does
-  // not insert sched_switch.
-  auto rid = context_->storage->mutable_raw_events()->AddRawEvent(
-      ts, sched_switch_id_, cpu, prev_utid);
-
-  // Note: this ordering is important. The events should be pushed in the same
-  // order as the order of fields in the proto; this is used by the raw table to
-  // index these events using the field ids.
-  using SS = protos::pbzero::SchedSwitchFtraceEvent;
-  auto add_raw_arg = [this](RowId row_id, int field_num, Variadic var) {
-    StringId key = sched_switch_field_ids_[static_cast<size_t>(field_num)];
-    context_->args_tracker->AddArg(row_id, key, key, var);
-  };
-  add_raw_arg(rid, SS::kPrevCommFieldNumber, Variadic::String(prev_comm_id));
-  add_raw_arg(rid, SS::kPrevPidFieldNumber, Variadic::Integer(prev_pid));
-  add_raw_arg(rid, SS::kPrevPrioFieldNumber, Variadic::Integer(prev_prio));
-  add_raw_arg(rid, SS::kPrevStateFieldNumber, Variadic::Integer(prev_state));
-  add_raw_arg(rid, SS::kNextCommFieldNumber, Variadic::String(next_comm_id));
-  add_raw_arg(rid, SS::kNextPidFieldNumber, Variadic::Integer(next_pid));
-  add_raw_arg(rid, SS::kNextPrioFieldNumber, Variadic::Integer(next_prio));
-
-  // Open a new scheduling slice, corresponding to the task that was
-  // just switched to.
-  return context_->storage->mutable_slices()->AddSlice(
-      cpu, ts, 0 /* duration */, next_utid, ftrace_utils::TaskState(),
-      next_prio);
-}
-
-PERFETTO_ALWAYS_INLINE
-void SchedEventTracker::ClosePendingSlice(size_t pending_slice_idx,
-                                          int64_t ts,
-                                          int64_t prev_state) {
-  auto* slices = context_->storage->mutable_slices();
-
-  int64_t duration = ts - slices->start_ns()[pending_slice_idx];
-  slices->set_duration(pending_slice_idx, duration);
-
-  // We store the state as a uint16 as we only consider values up to 2048
-  // when unpacking the information inside; this allows savings of 48 bits
-  // per slice.
-  auto task_state = ftrace_utils::TaskState(static_cast<uint16_t>(prev_state));
-  if (!task_state.is_valid()) {
-    context_->storage->IncrementStats(stats::task_state_invalid);
-  }
-  slices->set_end_state(pending_slice_idx, task_state);
-}
-
-// Processes a sched_waking that was decoded from a compact representation,
-// adding to the raw and instants tables.
-void SchedEventTracker::PushSchedWakingCompact(uint32_t cpu,
-                                               int64_t ts,
-                                               uint32_t wakee_pid,
-                                               int32_t target_cpu,
-                                               int32_t prio,
-                                               StringId comm_id) {
-  // At this stage all events should be globally timestamp ordered.
-  if (ts < context_->event_tracker->max_timestamp()) {
-    PERFETTO_ELOG("sched_waking event out of order by %.4f ms, skipping",
-                  (context_->event_tracker->max_timestamp() - ts) / 1e6);
-    context_->storage->IncrementStats(stats::sched_waking_out_of_order);
-    return;
-  }
-  context_->event_tracker->UpdateMaxTimestamp(ts);
-  PERFETTO_DCHECK(cpu < base::kMaxCpus);
-
-  // We infer the task that emitted the event (i.e. common_pid) from the
-  // scheduling slices. Drop the event if we haven't seen any sched_switch
-  // events for this cpu yet.
-  // Note that if sched_switch wasn't enabled, we will have to skip all
-  // compact waking events.
-  auto* pending_sched = &pending_sched_per_cpu_[cpu];
-  if (pending_sched->last_utid == std::numeric_limits<UniqueTid>::max()) {
-    context_->storage->IncrementStats(stats::compact_sched_waking_skipped);
-    return;
-  }
-  auto curr_utid = pending_sched->last_utid;
-
-  // Add an entry to the raw table.
-  auto rid = context_->storage->mutable_raw_events()->AddRawEvent(
-      ts, sched_waking_id_, cpu, curr_utid);
-
-  // "success" is hardcoded as always 1 by the kernel, with a TODO to remove it.
-  static constexpr int32_t kHardcodedSuccess = 1;
-
-  using SW = protos::pbzero::SchedWakingFtraceEvent;
-  auto add_raw_arg = [this](RowId row_id, int field_num, Variadic var) {
-    StringId key = sched_waking_field_ids_[static_cast<size_t>(field_num)];
-    context_->args_tracker->AddArg(row_id, key, key, var);
-  };
-  add_raw_arg(rid, SW::kCommFieldNumber, Variadic::String(comm_id));
-  add_raw_arg(rid, SW::kPidFieldNumber, Variadic::Integer(wakee_pid));
-  add_raw_arg(rid, SW::kPrioFieldNumber, Variadic::Integer(prio));
-  add_raw_arg(rid, SW::kSuccessFieldNumber,
-              Variadic::Integer(kHardcodedSuccess));
-  add_raw_arg(rid, SW::kTargetCpuFieldNumber, Variadic::Integer(target_cpu));
-
-  // Add a waking entry to the instants.
-  auto wakee_utid = context_->process_tracker->GetOrCreateThread(wakee_pid);
-  auto* instants = context_->storage->mutable_instants();
-  instants->AddInstantEvent(ts, sched_waking_id_, /*value=*/0, wakee_utid,
-                            RefType::kRefUtid);
-}
-
-void SchedEventTracker::FlushPendingEvents() {
-  // TODO(lalitm): the day this method is called before end of trace, don't
-  // flush the sched events as they will probably be pushed in the next round
-  // of ftrace events.
-  int64_t end_ts = context_->storage->GetTraceTimestampBoundsNs().second;
-  auto* slices = context_->storage->mutable_slices();
-  for (const auto& pending_sched : pending_sched_per_cpu_) {
-    size_t row = pending_sched.pending_slice_storage_idx;
-    if (row == std::numeric_limits<size_t>::max())
-      continue;
-
-    int64_t duration = end_ts - slices->start_ns()[row];
-    slices->set_duration(row, duration);
-    slices->set_end_state(
-        row, ftrace_utils::TaskState(ftrace_utils::TaskState::kRunnable));
-  }
-
-  pending_sched_per_cpu_ = {};
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/ftrace/sched_event_tracker.h b/src/trace_processor/importers/ftrace/sched_event_tracker.h
deleted file mode 100644
index 3c100b6..0000000
--- a/src/trace_processor/importers/ftrace/sched_event_tracker.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_SCHED_EVENT_TRACKER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_SCHED_EVENT_TRACKER_H_
-
-#include <array>
-#include <limits>
-
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/ext/base/utils.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-class EventTracker;
-
-// Tracks sched events and stores them into the storage as sched slices.
-class SchedEventTracker {
- public:
-  explicit SchedEventTracker(TraceProcessorContext*);
-  SchedEventTracker(const SchedEventTracker&) = delete;
-  SchedEventTracker& operator=(const SchedEventTracker&) = delete;
-  virtual ~SchedEventTracker();
-
-  // This method is called when a sched_switch event is seen in the trace.
-  // Virtual for testing.
-  virtual void PushSchedSwitch(uint32_t cpu,
-                               int64_t timestamp,
-                               uint32_t prev_pid,
-                               base::StringView prev_comm,
-                               int32_t prev_prio,
-                               int64_t prev_state,
-                               uint32_t next_pid,
-                               base::StringView next_comm,
-                               int32_t next_prio);
-
-  // This method is called when parsing a sched_switch encoded in the compact
-  // format.
-  void PushSchedSwitchCompact(uint32_t cpu,
-                              int64_t ts,
-                              int64_t prev_state,
-                              uint32_t next_pid,
-                              int32_t next_prio,
-                              StringId next_comm_id);
-
-  // This method is called when parsing a sched_waking encoded in the compact
-  // format. Note that the default encoding is handled by
-  // |EventTracker::PushInstant|.
-  void PushSchedWakingCompact(uint32_t cpu,
-                              int64_t ts,
-                              uint32_t wakee_pid,
-                              int32_t target_cpu,
-                              int32_t prio,
-                              StringId comm_id);
-
-  // Called at the end of trace to flush any events which are pending to the
-  // storage.
-  void FlushPendingEvents();
-
- private:
-  // Information retained from the preceding sched_switch seen on a given cpu.
-  struct PendingSchedInfo {
-    // The pending scheduling slice that the next event will complete.
-    size_t pending_slice_storage_idx = std::numeric_limits<size_t>::max();
-
-    // pid/utid/prio corresponding to the last sched_switch seen on this cpu
-    // (its "next_*" fields). There is some duplication with respect to the
-    // slices storage, but we don't always have a slice when decoding events in
-    // the compact format.
-    uint32_t last_pid = std::numeric_limits<uint32_t>::max();
-    UniqueTid last_utid = std::numeric_limits<UniqueTid>::max();
-    int32_t last_prio = std::numeric_limits<int32_t>::max();
-  };
-
-  size_t AddRawEventAndStartSlice(uint32_t cpu,
-                                  int64_t ts,
-                                  UniqueTid prev_utid,
-                                  uint32_t prev_pid,
-                                  StringId prev_comm_id,
-                                  int32_t prev_prio,
-                                  int64_t prev_state,
-                                  UniqueTid next_utid,
-                                  uint32_t next_pid,
-                                  StringId next_comm_id,
-                                  int32_t next_prio);
-
-  void ClosePendingSlice(size_t slice_idx, int64_t ts, int64_t prev_state);
-
-  // Infromation retained from the preceding sched_switch seen on a given cpu.
-  std::array<PendingSchedInfo, base::kMaxCpus> pending_sched_per_cpu_{};
-
-  static constexpr uint8_t kSchedSwitchMaxFieldId = 7;
-  std::array<StringId, kSchedSwitchMaxFieldId + 1> sched_switch_field_ids_;
-  StringId sched_switch_id_;
-
-  static constexpr uint8_t kSchedWakingMaxFieldId = 5;
-  std::array<StringId, kSchedWakingMaxFieldId + 1> sched_waking_field_ids_;
-  StringId sched_waking_id_;
-
-  TraceProcessorContext* const context_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_FTRACE_SCHED_EVENT_TRACKER_H_
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_provider_view.cc b/src/trace_processor/importers/fuchsia/fuchsia_provider_view.cc
deleted file mode 100644
index 6c69f6b..0000000
--- a/src/trace_processor/importers/fuchsia/fuchsia_provider_view.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/importers/fuchsia/fuchsia_provider_view.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-void FuchsiaProviderView::InsertString(uint32_t index, StringId string_id) {
-  StringTableEntry entry;
-  entry.index = index;
-  entry.string_id = string_id;
-
-  string_entries_.push_back(entry);
-}
-
-StringId FuchsiaProviderView::GetString(uint32_t index) {
-  for (const auto& entry : string_entries_) {
-    if (entry.index == index)
-      return entry.string_id;
-  }
-  return StringId();
-}
-
-void FuchsiaProviderView::InsertThread(uint32_t index,
-                                       fuchsia_trace_utils::ThreadInfo info) {
-  ThreadTableEntry entry;
-  entry.index = index;
-  entry.info = info;
-
-  thread_entries_.push_back(entry);
-}
-
-fuchsia_trace_utils::ThreadInfo FuchsiaProviderView::GetThread(uint32_t index) {
-  for (const auto& entry : thread_entries_) {
-    if (entry.index == index)
-      return entry.info;
-  }
-  return fuchsia_trace_utils::ThreadInfo();
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_provider_view.h b/src/trace_processor/importers/fuchsia/fuchsia_provider_view.h
deleted file mode 100644
index a334ee4..0000000
--- a/src/trace_processor/importers/fuchsia/fuchsia_provider_view.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_FUCHSIA_FUCHSIA_PROVIDER_VIEW_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_FUCHSIA_FUCHSIA_PROVIDER_VIEW_H_
-
-#include "src/trace_processor/importers/fuchsia/fuchsia_trace_utils.h"
-#include "src/trace_processor/trace_storage.h"
-
-#include <vector>
-
-namespace perfetto {
-namespace trace_processor {
-
-// Data from a trace provider that is necessary for interpreting a binary
-// record. Namely, the entries of the string table and the thread table that are
-// referenced by the record. This enables understanding the binary record after
-// arbitrary reordering.
-class FuchsiaProviderView {
- public:
-  struct StringTableEntry {
-    uint32_t index;
-    StringId string_id;
-  };
-
-  struct ThreadTableEntry {
-    uint32_t index;
-    fuchsia_trace_utils::ThreadInfo info;
-  };
-
-  void InsertString(uint32_t, StringId);
-  StringId GetString(uint32_t);
-
-  void InsertThread(uint32_t, fuchsia_trace_utils::ThreadInfo);
-  fuchsia_trace_utils::ThreadInfo GetThread(uint32_t);
-
-  void set_ticks_per_second(uint64_t ticks_per_second) {
-    ticks_per_second_ = ticks_per_second;
-  }
-
-  uint64_t get_ticks_per_second() { return ticks_per_second_; }
-
- private:
-  std::vector<StringTableEntry> string_entries_;
-  std::vector<ThreadTableEntry> thread_entries_;
-
-  uint64_t ticks_per_second_ = 1000000000;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_FUCHSIA_FUCHSIA_PROVIDER_VIEW_H_
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc b/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc
deleted file mode 100644
index a362d8e..0000000
--- a/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/importers/fuchsia/fuchsia_trace_parser.h"
-
-#include "src/trace_processor/args_tracker.h"
-#include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/slice_tracker.h"
-#include "src/trace_processor/track_tracker.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-// Record Types
-constexpr uint32_t kEvent = 4;
-
-// Event Types
-constexpr uint32_t kInstant = 0;
-constexpr uint32_t kCounter = 1;
-constexpr uint32_t kDurationBegin = 2;
-constexpr uint32_t kDurationEnd = 3;
-constexpr uint32_t kDurationComplete = 4;
-constexpr uint32_t kAsyncBegin = 5;
-constexpr uint32_t kAsyncInstant = 6;
-constexpr uint32_t kAsyncEnd = 7;
-
-// Argument Types
-constexpr uint32_t kNull = 0;
-constexpr uint32_t kInt32 = 1;
-constexpr uint32_t kUint32 = 2;
-constexpr uint32_t kInt64 = 3;
-constexpr uint32_t kUint64 = 4;
-constexpr uint32_t kDouble = 5;
-constexpr uint32_t kString = 6;
-constexpr uint32_t kPointer = 7;
-constexpr uint32_t kKoid = 8;
-
-struct Arg {
-  StringId name;
-  fuchsia_trace_utils::ArgValue value;
-};
-}  // namespace
-
-FuchsiaTraceParser::FuchsiaTraceParser(TraceProcessorContext* context)
-    : context_(context) {}
-
-FuchsiaTraceParser::~FuchsiaTraceParser() = default;
-
-void FuchsiaTraceParser::ParseFtracePacket(uint32_t,
-                                           int64_t,
-                                           TimestampedTracePiece) {
-  PERFETTO_FATAL("Fuchsia Trace Parser cannot handle ftrace packets.");
-}
-
-void FuchsiaTraceParser::ParseTracePacket(int64_t, TimestampedTracePiece ttp) {
-  PERFETTO_DCHECK(ttp.fuchsia_provider_view != nullptr);
-
-  // The timestamp is also present in the record, so we'll ignore the one passed
-  // as an argument.
-  fuchsia_trace_utils::RecordCursor cursor(&ttp.blob_view);
-  FuchsiaProviderView* provider_view = ttp.fuchsia_provider_view.get();
-  ProcessTracker* procs = context_->process_tracker.get();
-  SliceTracker* slices = context_->slice_tracker.get();
-
-  uint64_t header;
-  if (!cursor.ReadUint64(&header)) {
-    context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-    return;
-  }
-  uint32_t record_type = fuchsia_trace_utils::ReadField<uint32_t>(header, 0, 3);
-  switch (record_type) {
-    case kEvent: {
-      uint32_t event_type =
-          fuchsia_trace_utils::ReadField<uint32_t>(header, 16, 19);
-      uint32_t n_args =
-          fuchsia_trace_utils::ReadField<uint32_t>(header, 20, 23);
-      uint32_t thread_ref =
-          fuchsia_trace_utils::ReadField<uint32_t>(header, 24, 31);
-      uint32_t cat_ref =
-          fuchsia_trace_utils::ReadField<uint32_t>(header, 32, 47);
-      uint32_t name_ref =
-          fuchsia_trace_utils::ReadField<uint32_t>(header, 48, 63);
-
-      int64_t ts;
-      if (!cursor.ReadTimestamp(provider_view->get_ticks_per_second(), &ts)) {
-        context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-        return;
-      }
-      fuchsia_trace_utils::ThreadInfo tinfo;
-      if (fuchsia_trace_utils::IsInlineThread(thread_ref)) {
-        if (!cursor.ReadInlineThread(&tinfo)) {
-          context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-          return;
-        }
-      } else {
-        tinfo = provider_view->GetThread(thread_ref);
-      }
-      StringId cat;
-      if (fuchsia_trace_utils::IsInlineString(cat_ref)) {
-        base::StringView cat_string_view;
-        if (!cursor.ReadInlineString(cat_ref, &cat_string_view)) {
-          context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-          return;
-        }
-        cat = context_->storage->InternString(cat_string_view);
-      } else {
-        cat = provider_view->GetString(cat_ref);
-      }
-      StringId name;
-      if (fuchsia_trace_utils::IsInlineString(name_ref)) {
-        base::StringView name_string_view;
-        if (!cursor.ReadInlineString(name_ref, &name_string_view)) {
-          context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-          return;
-        }
-        name = context_->storage->InternString(name_string_view);
-      } else {
-        name = provider_view->GetString(name_ref);
-      }
-
-      // Read arguments
-      std::vector<Arg> args;
-      for (uint32_t i = 0; i < n_args; i++) {
-        size_t arg_base = cursor.WordIndex();
-        uint64_t arg_header;
-        if (!cursor.ReadUint64(&arg_header)) {
-          context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-          return;
-        }
-        uint32_t arg_type =
-            fuchsia_trace_utils::ReadField<uint32_t>(arg_header, 0, 3);
-        uint32_t arg_size_words =
-            fuchsia_trace_utils::ReadField<uint32_t>(arg_header, 4, 15);
-        uint32_t arg_name_ref =
-            fuchsia_trace_utils::ReadField<uint32_t>(arg_header, 16, 31);
-        Arg arg;
-        if (fuchsia_trace_utils::IsInlineString(arg_name_ref)) {
-          base::StringView arg_name_view;
-          if (!cursor.ReadInlineString(arg_name_ref, &arg_name_view)) {
-            context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-            return;
-          }
-          arg.name = context_->storage->InternString(arg_name_view);
-        } else {
-          arg.name = provider_view->GetString(arg_name_ref);
-        }
-
-        switch (arg_type) {
-          case kNull:
-            arg.value = fuchsia_trace_utils::ArgValue::Null();
-            break;
-          case kInt32:
-            arg.value = fuchsia_trace_utils::ArgValue::Int32(
-                fuchsia_trace_utils::ReadField<int32_t>(arg_header, 32, 63));
-            break;
-          case kUint32:
-            arg.value = fuchsia_trace_utils::ArgValue::Uint32(
-                fuchsia_trace_utils::ReadField<uint32_t>(arg_header, 32, 63));
-            break;
-          case kInt64: {
-            int64_t value;
-            if (!cursor.ReadInt64(&value)) {
-              context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-              return;
-            }
-            arg.value = fuchsia_trace_utils::ArgValue::Int64(value);
-            break;
-          }
-          case kUint64: {
-            uint64_t value;
-            if (!cursor.ReadUint64(&value)) {
-              context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-              return;
-            }
-            arg.value = fuchsia_trace_utils::ArgValue::Uint64(value);
-            break;
-          }
-          case kDouble: {
-            double value;
-            if (!cursor.ReadDouble(&value)) {
-              context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-              return;
-            }
-            arg.value = fuchsia_trace_utils::ArgValue::Double(value);
-            break;
-          }
-          case kString: {
-            uint32_t arg_value_ref =
-                fuchsia_trace_utils::ReadField<uint32_t>(arg_header, 32, 47);
-            StringId value;
-            if (fuchsia_trace_utils::IsInlineString(arg_value_ref)) {
-              base::StringView arg_value_view;
-              if (!cursor.ReadInlineString(arg_value_ref, &arg_value_view)) {
-                context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-                return;
-              }
-              value = context_->storage->InternString(arg_value_view);
-            } else {
-              value = provider_view->GetString(arg_value_ref);
-            }
-            arg.value = fuchsia_trace_utils::ArgValue::String(value);
-            break;
-          }
-          case kPointer: {
-            uint64_t value;
-            if (!cursor.ReadUint64(&value)) {
-              context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-              return;
-            }
-            arg.value = fuchsia_trace_utils::ArgValue::Pointer(value);
-            break;
-          }
-          case kKoid: {
-            uint64_t value;
-            if (!cursor.ReadUint64(&value)) {
-              context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-              return;
-            }
-            arg.value = fuchsia_trace_utils::ArgValue::Koid(value);
-            break;
-          }
-          default:
-            arg.value = fuchsia_trace_utils::ArgValue::Unknown();
-            break;
-        }
-
-        args.push_back(arg);
-        cursor.SetWordIndex(arg_base + arg_size_words);
-      }
-
-      switch (event_type) {
-        case kInstant: {
-          UniqueTid utid =
-              procs->UpdateThread(static_cast<uint32_t>(tinfo.tid),
-                                  static_cast<uint32_t>(tinfo.pid));
-          RowId row = context_->event_tracker->PushInstant(ts, name, 0, utid,
-                                                           RefType::kRefUtid);
-          for (const Arg& arg : args) {
-            context_->args_tracker->AddArg(
-                row, arg.name, arg.name,
-                arg.value.ToStorageVariadic(context_->storage.get()));
-          }
-          context_->args_tracker->Flush();
-          break;
-        }
-        case kCounter: {
-          UniqueTid utid =
-              procs->UpdateThread(static_cast<uint32_t>(tinfo.tid),
-                                  static_cast<uint32_t>(tinfo.pid));
-          std::string name_str =
-              context_->storage->GetString(name).ToStdString();
-          // Note: In the Fuchsia trace format, counter values are stored in the
-          // arguments for the record, with the data series defined by both the
-          // record name and the argument name. In Perfetto, counters only have
-          // one name, so we combine both names into one here.
-          for (const Arg& arg : args) {
-            std::string counter_name_str = name_str + ":";
-            counter_name_str +=
-                context_->storage->GetString(arg.name).ToStdString();
-            bool is_valid_value = false;
-            double counter_value = -1;
-            switch (arg.value.Type()) {
-              case fuchsia_trace_utils::ArgValue::kInt32:
-                is_valid_value = true;
-                counter_value = static_cast<double>(arg.value.Int32());
-                break;
-              case fuchsia_trace_utils::ArgValue::kUint32:
-                is_valid_value = true;
-                counter_value = static_cast<double>(arg.value.Uint32());
-                break;
-              case fuchsia_trace_utils::ArgValue::kInt64:
-                is_valid_value = true;
-                counter_value = static_cast<double>(arg.value.Int64());
-                break;
-              case fuchsia_trace_utils::ArgValue::kUint64:
-                is_valid_value = true;
-                counter_value = static_cast<double>(arg.value.Uint64());
-                break;
-              case fuchsia_trace_utils::ArgValue::kDouble:
-                is_valid_value = true;
-                counter_value = arg.value.Double();
-                break;
-              case fuchsia_trace_utils::ArgValue::kNull:
-              case fuchsia_trace_utils::ArgValue::kString:
-              case fuchsia_trace_utils::ArgValue::kPointer:
-              case fuchsia_trace_utils::ArgValue::kKoid:
-              case fuchsia_trace_utils::ArgValue::kUnknown:
-                context_->storage->IncrementStats(
-                    stats::fuchsia_non_numeric_counters);
-                break;
-            }
-            if (is_valid_value) {
-              StringId counter_name_id = context_->storage->InternString(
-                  base::StringView(counter_name_str));
-              TrackId track = context_->track_tracker->InternThreadCounterTrack(
-                  counter_name_id, utid);
-              context_->event_tracker->PushCounter(ts, counter_value, track);
-            }
-          }
-          break;
-        }
-        case kDurationBegin: {
-          UniqueTid utid =
-              procs->UpdateThread(static_cast<uint32_t>(tinfo.tid),
-                                  static_cast<uint32_t>(tinfo.pid));
-          TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-          slices->Begin(ts, track_id, utid, RefType::kRefUtid, cat, name);
-          break;
-        }
-        case kDurationEnd: {
-          UniqueTid utid =
-              procs->UpdateThread(static_cast<uint32_t>(tinfo.tid),
-                                  static_cast<uint32_t>(tinfo.pid));
-          TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-          // TODO(b/131181693): |cat| and |name| are not passed here so that
-          // if two slices end at the same timestep, the slices get closed in
-          // the correct order regardless of which end event is processed first.
-          slices->End(ts, track_id);
-          break;
-        }
-        case kDurationComplete: {
-          int64_t end_ts;
-          if (!cursor.ReadTimestamp(provider_view->get_ticks_per_second(),
-                                    &end_ts)) {
-            context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-            return;
-          }
-          int64_t duration = end_ts - ts;
-          if (duration < 0) {
-            context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-            return;
-          }
-          UniqueTid utid =
-              procs->UpdateThread(static_cast<uint32_t>(tinfo.tid),
-                                  static_cast<uint32_t>(tinfo.pid));
-          TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-          slices->Scoped(ts, track_id, utid, RefType::kRefUtid, cat, name,
-                         duration);
-          break;
-        }
-        case kAsyncBegin: {
-          int64_t correlation_id;
-          if (!cursor.ReadInt64(&correlation_id)) {
-            context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-            return;
-          }
-          TrackId track_id = context_->track_tracker->InternFuchsiaAsyncTrack(
-              name, correlation_id);
-          slices->Begin(ts, track_id, track_id, RefType::kRefTrack, cat, name);
-          break;
-        }
-        case kAsyncInstant: {
-          // TODO(eseckler): Consider storing these instants as 0-duration
-          // slices instead, so that they get nested underneath begin/end
-          // slices.
-          int64_t correlation_id;
-          if (!cursor.ReadInt64(&correlation_id)) {
-            context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-            return;
-          }
-          TrackId track_id = context_->track_tracker->InternFuchsiaAsyncTrack(
-              name, correlation_id);
-          RowId row = context_->event_tracker->PushInstant(
-              ts, name, 0, track_id, RefType::kRefTrack);
-          for (const Arg& arg : args) {
-            context_->args_tracker->AddArg(
-                row, arg.name, arg.name,
-                arg.value.ToStorageVariadic(context_->storage.get()));
-          }
-          context_->args_tracker->Flush();
-          break;
-        }
-        case kAsyncEnd: {
-          int64_t correlation_id;
-          if (!cursor.ReadInt64(&correlation_id)) {
-            context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-            return;
-          }
-          TrackId track_id = context_->track_tracker->InternFuchsiaAsyncTrack(
-              name, correlation_id);
-          slices->End(ts, track_id, cat, name);
-          break;
-        }
-      }
-      break;
-    }
-    default: {
-      PERFETTO_DFATAL("Unknown record type %d in FuchsiaTraceParser",
-                      record_type);
-      break;
-    }
-  }
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.h b/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.h
deleted file mode 100644
index bc54d47..0000000
--- a/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_FUCHSIA_FUCHSIA_TRACE_PARSER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_FUCHSIA_FUCHSIA_TRACE_PARSER_H_
-
-#include "src/trace_processor/importers/fuchsia/fuchsia_provider_view.h"
-#include "src/trace_processor/timestamped_trace_piece.h"
-#include "src/trace_processor/trace_parser.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-class FuchsiaTraceParser : public TraceParser {
- public:
-  explicit FuchsiaTraceParser(TraceProcessorContext*);
-  ~FuchsiaTraceParser() override;
-
-  // TraceParser implementation
-  void ParseTracePacket(int64_t timestamp, TimestampedTracePiece) override;
-  void ParseFtracePacket(uint32_t, int64_t, TimestampedTracePiece) override;
-
- private:
-  TraceProcessorContext* const context_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_FUCHSIA_FUCHSIA_TRACE_PARSER_H_
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc b/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc
deleted file mode 100644
index 9f58cc9..0000000
--- a/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc
+++ /dev/null
@@ -1,575 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h"
-
-#include <inttypes.h>
-#include <unordered_map>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_view.h"
-#include "src/trace_processor/ftrace_utils.h"
-#include "src/trace_processor/importers/fuchsia/fuchsia_provider_view.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/slice_tracker.h"
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/trace_sorter.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-// Record types
-constexpr uint32_t kMetadata = 0;
-constexpr uint32_t kInitialization = 1;
-constexpr uint32_t kString = 2;
-constexpr uint32_t kThread = 3;
-constexpr uint32_t kEvent = 4;
-constexpr uint32_t kKernelObject = 7;
-constexpr uint32_t kContextSwitch = 8;
-
-// Metadata types
-constexpr uint32_t kProviderInfo = 1;
-constexpr uint32_t kProviderSection = 2;
-constexpr uint32_t kProviderEvent = 3;
-
-// Thread states
-constexpr uint32_t kThreadNew = 0;
-constexpr uint32_t kThreadRunning = 1;
-constexpr uint32_t kThreadSuspended = 2;
-constexpr uint32_t kThreadBlocked = 3;
-constexpr uint32_t kThreadDying = 4;
-constexpr uint32_t kThreadDead = 5;
-
-// Zircon object types
-constexpr uint32_t kZxObjTypeProcess = 1;
-constexpr uint32_t kZxObjTypeThread = 2;
-
-// Argument types
-constexpr uint32_t kArgString = 6;
-constexpr uint32_t kArgKernelObject = 8;
-}  // namespace
-
-FuchsiaTraceTokenizer::FuchsiaTraceTokenizer(TraceProcessorContext* context)
-    : context_(context) {
-  RegisterProvider(0, "");
-}
-
-FuchsiaTraceTokenizer::~FuchsiaTraceTokenizer() = default;
-
-util::Status FuchsiaTraceTokenizer::Parse(std::unique_ptr<uint8_t[]> data,
-                                          size_t size) {
-  // The relevant internal state is |leftover_bytes_|. Each call to Parse should
-  // maintain the following properties, unless a fatal error occurs in which
-  // case it should return false and no assumptions should be made about the
-  // resulting internal state:
-  //
-  // 1) Every byte passed to |Parse| has either been passed to |ParseRecord| or
-  // is present in |leftover_bytes_|, but not both.
-  // 2) |leftover_bytes_| does not contain a complete record.
-  //
-  // Parse is responsible for creating the "full" |TraceBlobView|s, which own
-  // the underlying data. Generally, there will be one such view. However, if
-  // there is a record that started in an earlier call, then a new buffer is
-  // created here to make the bytes in that record contiguous.
-  //
-  // Because some of the bytes in |data| might belong to the record starting in
-  // |leftover_bytes_|, we track the offset at which the following record will
-  // start.
-  size_t byte_offset = 0;
-
-  // Look for a record starting with the leftover bytes.
-  if (leftover_bytes_.size() + size < 8) {
-    // Even with the new bytes, we can't even read the header of the next
-    // record, so just add the new bytes to |leftover_bytes_| and return.
-    leftover_bytes_.insert(leftover_bytes_.end(), data.get() + byte_offset,
-                           data.get() + size);
-    return util::OkStatus();
-  }
-  if (leftover_bytes_.size() > 0) {
-    // There is a record starting from leftover bytes.
-    if (leftover_bytes_.size() < 8) {
-      // Header was previously incomplete, but we have enough now.
-      // Copy bytes into |leftover_bytes_| so that the whole header is present,
-      // and update |byte_offset| and |size| accordingly.
-      size_t needed_bytes = 8 - leftover_bytes_.size();
-      leftover_bytes_.insert(leftover_bytes_.end(), data.get() + byte_offset,
-                             data.get() + needed_bytes);
-      byte_offset += needed_bytes;
-      size -= needed_bytes;
-    }
-    // Read the record length from the header.
-    uint64_t header =
-        *reinterpret_cast<const uint64_t*>(leftover_bytes_.data());
-    uint32_t record_len_words =
-        fuchsia_trace_utils::ReadField<uint32_t>(header, 4, 15);
-    uint32_t record_len_bytes = record_len_words * sizeof(uint64_t);
-
-    // From property (2) above, leftover_bytes_ must have had less than a full
-    // record to start with. We padded leftover_bytes_ out to read the header,
-    // so it may now be a full record (in the case that the record consists of
-    // only the header word), but it still cannot have any extra bytes.
-    PERFETTO_DCHECK(leftover_bytes_.size() <= record_len_bytes);
-    size_t missing_bytes = record_len_bytes - leftover_bytes_.size();
-
-    if (missing_bytes <= size) {
-      // We have enough bytes to complete the partial record. Create a new
-      // buffer for that record.
-      std::unique_ptr<uint8_t[]> buf(new uint8_t[record_len_bytes]);
-      memcpy(&buf[0], leftover_bytes_.data(), leftover_bytes_.size());
-      memcpy(&buf[leftover_bytes_.size()], &data[byte_offset], missing_bytes);
-      byte_offset += missing_bytes;
-      size -= missing_bytes;
-      leftover_bytes_.clear();
-
-      TraceBlobView leftover_record(std::move(buf), 0, record_len_bytes);
-      ParseRecord(std::move(leftover_record));
-    } else {
-      // There are not enough bytes for the full record. Add all the bytes we
-      // have to leftover_bytes_ and wait for more.
-      leftover_bytes_.insert(leftover_bytes_.end(), data.get() + byte_offset,
-                             data.get() + byte_offset + size);
-      return util::OkStatus();
-    }
-  }
-
-  TraceBlobView full_view(std::move(data), byte_offset, size);
-
-  // |record_offset| is a number of bytes past |byte_offset| where the record
-  // under consideration starts. As a result, it must always be in the range [0,
-  // size-8]. Any larger offset means we don't have enough bytes for the header.
-  size_t record_offset = 0;
-  while (record_offset + 8 <= size) {
-    uint64_t header =
-        *reinterpret_cast<const uint64_t*>(full_view.data() + record_offset);
-    uint32_t record_len_bytes =
-        fuchsia_trace_utils::ReadField<uint32_t>(header, 4, 15) *
-        sizeof(uint64_t);
-    if (record_len_bytes == 0)
-      return util::ErrStatus("Unexpected record of size 0");
-
-    if (record_offset + record_len_bytes > size)
-      break;
-
-    TraceBlobView record =
-        full_view.slice(byte_offset + record_offset, record_len_bytes);
-    ParseRecord(std::move(record));
-
-    record_offset += record_len_bytes;
-  }
-
-  leftover_bytes_.insert(leftover_bytes_.end(),
-                         full_view.data() + record_offset,
-                         full_view.data() + size);
-  return util::OkStatus();
-}
-
-// Most record types are read and recorded in |TraceStorage| here directly.
-// Event records are sorted by timestamp before processing, so instead of
-// recording them in |TraceStorage| they are given to |TraceSorter|. In order to
-// facilitate the parsing after sorting, a small view of the provider's string
-// and thread tables is passed alongside the record. See |FuchsiaProviderView|.
-void FuchsiaTraceTokenizer::ParseRecord(TraceBlobView tbv) {
-  TraceStorage* storage = context_->storage.get();
-  ProcessTracker* procs = context_->process_tracker.get();
-  TraceSorter* sorter = context_->sorter.get();
-
-  fuchsia_trace_utils::RecordCursor cursor(&tbv);
-  uint64_t header;
-  if (!cursor.ReadUint64(&header)) {
-    context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-    return;
-  }
-
-  uint32_t record_type = fuchsia_trace_utils::ReadField<uint32_t>(header, 0, 3);
-
-  // All non-metadata events require current_provider_ to be set.
-  if (record_type != kMetadata && current_provider_ == nullptr) {
-    context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-    return;
-  }
-
-  switch (record_type) {
-    case kMetadata: {
-      uint32_t metadata_type =
-          fuchsia_trace_utils::ReadField<uint32_t>(header, 16, 19);
-      switch (metadata_type) {
-        case kProviderInfo: {
-          uint32_t provider_id =
-              fuchsia_trace_utils::ReadField<uint32_t>(header, 20, 51);
-          uint32_t name_len =
-              fuchsia_trace_utils::ReadField<uint32_t>(header, 52, 59);
-          base::StringView name_view;
-          if (!cursor.ReadInlineString(name_len, &name_view)) {
-            context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-            return;
-          }
-          RegisterProvider(provider_id, name_view.ToStdString());
-          break;
-        }
-        case kProviderSection: {
-          uint32_t provider_id =
-              fuchsia_trace_utils::ReadField<uint32_t>(header, 20, 51);
-          current_provider_ = providers_[provider_id].get();
-          break;
-        }
-        case kProviderEvent: {
-          // TODO(bhamrick): Handle buffer fill events
-          PERFETTO_DLOG(
-              "Ignoring provider event. Events may have been dropped");
-          break;
-        }
-      }
-      break;
-    }
-    case kInitialization: {
-      if (!cursor.ReadUint64(&current_provider_->ticks_per_second)) {
-        context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-        return;
-      }
-      break;
-    }
-    case kString: {
-      uint32_t index = fuchsia_trace_utils::ReadField<uint32_t>(header, 16, 30);
-      if (index != 0) {
-        uint32_t len = fuchsia_trace_utils::ReadField<uint32_t>(header, 32, 46);
-        base::StringView s;
-        if (!cursor.ReadInlineString(len, &s)) {
-          context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-          return;
-        }
-        StringId id = storage->InternString(s);
-
-        current_provider_->string_table[index] = id;
-      }
-      break;
-    }
-    case kThread: {
-      uint32_t index = fuchsia_trace_utils::ReadField<uint32_t>(header, 16, 23);
-      if (index != 0) {
-        fuchsia_trace_utils::ThreadInfo tinfo;
-        if (!cursor.ReadInlineThread(&tinfo)) {
-          context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-          return;
-        }
-
-        current_provider_->thread_table[index] = tinfo;
-      }
-      break;
-    }
-    case kEvent: {
-      uint32_t thread_ref =
-          fuchsia_trace_utils::ReadField<uint32_t>(header, 24, 31);
-      uint32_t cat_ref =
-          fuchsia_trace_utils::ReadField<uint32_t>(header, 32, 47);
-      uint32_t name_ref =
-          fuchsia_trace_utils::ReadField<uint32_t>(header, 48, 63);
-
-      // Build the minimal FuchsiaProviderView needed by
-      // the record. This means the thread information if not inline, and any
-      // non-inline strings (name, category for now, arg names and string values
-      // in the future.
-      auto provider_view =
-          std::unique_ptr<FuchsiaProviderView>(new FuchsiaProviderView());
-      provider_view->set_ticks_per_second(current_provider_->ticks_per_second);
-
-      uint64_t ticks;
-      if (!cursor.ReadUint64(&ticks)) {
-        context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-        return;
-      }
-      int64_t ts = fuchsia_trace_utils::TicksToNs(
-          ticks, current_provider_->ticks_per_second);
-      if (ts < 0) {
-        storage->IncrementStats(stats::fuchsia_timestamp_overflow);
-        return;
-      }
-
-      if (fuchsia_trace_utils::IsInlineThread(thread_ref)) {
-        // Skip over inline thread
-        cursor.ReadInlineThread(nullptr);
-      } else {
-        provider_view->InsertThread(
-            thread_ref, current_provider_->thread_table[thread_ref]);
-      }
-
-      if (fuchsia_trace_utils::IsInlineString(cat_ref)) {
-        // Skip over inline string
-        cursor.ReadInlineString(cat_ref, nullptr);
-      } else {
-        provider_view->InsertString(cat_ref,
-                                    current_provider_->string_table[cat_ref]);
-      }
-
-      if (fuchsia_trace_utils::IsInlineString(name_ref)) {
-        // Skip over inline string
-        cursor.ReadInlineString(name_ref, nullptr);
-      } else {
-        provider_view->InsertString(name_ref,
-                                    current_provider_->string_table[name_ref]);
-      }
-
-      uint32_t n_args =
-          fuchsia_trace_utils::ReadField<uint32_t>(header, 20, 23);
-      for (uint32_t i = 0; i < n_args; i++) {
-        const size_t arg_base = cursor.WordIndex();
-        uint64_t arg_header;
-        if (!cursor.ReadUint64(&arg_header)) {
-          storage->IncrementStats(stats::fuchsia_invalid_event);
-          return;
-        }
-        uint32_t arg_type =
-            fuchsia_trace_utils::ReadField<uint32_t>(arg_header, 0, 3);
-        uint32_t arg_size_words =
-            fuchsia_trace_utils::ReadField<uint32_t>(arg_header, 4, 15);
-        uint32_t arg_name_ref =
-            fuchsia_trace_utils::ReadField<uint32_t>(arg_header, 16, 31);
-
-        if (fuchsia_trace_utils::IsInlineString(arg_name_ref)) {
-          // Skip over inline string
-          cursor.ReadInlineString(arg_name_ref, nullptr);
-        } else {
-          provider_view->InsertString(
-              arg_name_ref, current_provider_->string_table[arg_name_ref]);
-        }
-
-        if (arg_type == kArgString) {
-          uint32_t arg_value_ref =
-              fuchsia_trace_utils::ReadField<uint32_t>(arg_header, 32, 47);
-          if (fuchsia_trace_utils::IsInlineString(arg_value_ref)) {
-            // Skip over inline string
-            cursor.ReadInlineString(arg_value_ref, nullptr);
-          } else {
-            provider_view->InsertString(
-                arg_value_ref, current_provider_->string_table[arg_value_ref]);
-          }
-        }
-
-        cursor.SetWordIndex(arg_base + arg_size_words);
-      }
-
-      sorter->PushFuchsiaRecord(ts, std::move(tbv), std::move(provider_view));
-
-      break;
-    }
-    case kKernelObject: {
-      uint32_t obj_type =
-          fuchsia_trace_utils::ReadField<uint32_t>(header, 16, 23);
-      uint32_t name_ref =
-          fuchsia_trace_utils::ReadField<uint32_t>(header, 24, 39);
-
-      uint64_t obj_id;
-      if (!cursor.ReadUint64(&obj_id)) {
-        storage->IncrementStats(stats::fuchsia_invalid_event);
-        return;
-      }
-
-      StringId name = StringId();
-      if (fuchsia_trace_utils::IsInlineString(name_ref)) {
-        base::StringView name_view;
-        if (!cursor.ReadInlineString(name_ref, &name_view)) {
-          storage->IncrementStats(stats::fuchsia_invalid_event);
-          return;
-        }
-        name = storage->InternString(name_view);
-      } else {
-        name = current_provider_->string_table[name_ref];
-      }
-
-      switch (obj_type) {
-        case kZxObjTypeProcess: {
-          // Note: Fuchsia pid/tids are 64 bits but Perfetto's tables only
-          // support 32 bits. This is usually not an issue except for
-          // artificial koids which have the 2^63 bit set. This is used for
-          // things such as virtual threads.
-          procs->SetProcessMetadata(static_cast<uint32_t>(obj_id),
-                                    base::Optional<uint32_t>(),
-                                    base::StringView(storage->GetString(name)));
-          break;
-        }
-        case kZxObjTypeThread: {
-          uint32_t n_args =
-              fuchsia_trace_utils::ReadField<uint32_t>(header, 40, 43);
-          uint64_t pid = 0;
-
-          // Scan for a Kernel Object argument named "process"
-          for (uint32_t i = 0; i < n_args; i++) {
-            const size_t arg_base = cursor.WordIndex();
-            uint64_t arg_header;
-            if (!cursor.ReadUint64(&arg_header)) {
-              storage->IncrementStats(stats::fuchsia_invalid_event);
-              return;
-            }
-            uint32_t arg_type =
-                fuchsia_trace_utils::ReadField<uint32_t>(arg_header, 0, 3);
-            uint32_t arg_size =
-                fuchsia_trace_utils::ReadField<uint32_t>(arg_header, 4, 15);
-            if (arg_type == kArgKernelObject) {
-              uint32_t arg_name_ref =
-                  fuchsia_trace_utils::ReadField<uint32_t>(arg_header, 16, 31);
-              base::StringView arg_name;
-              if (fuchsia_trace_utils::IsInlineString(arg_name_ref)) {
-                if (!cursor.ReadInlineString(arg_name_ref, &arg_name)) {
-                  storage->IncrementStats(stats::fuchsia_invalid_event);
-                  return;
-                }
-              } else {
-                arg_name = storage->GetString(
-                    current_provider_->string_table[arg_name_ref]);
-              }
-
-              if (arg_name == "process") {
-                if (!cursor.ReadUint64(&pid)) {
-                  storage->IncrementStats(stats::fuchsia_invalid_event);
-                  return;
-                }
-              }
-            }
-
-            cursor.SetWordIndex(arg_base + arg_size);
-          }
-
-          pid_table_[obj_id] = pid;
-
-          UniqueTid utid = procs->UpdateThread(static_cast<uint32_t>(obj_id),
-                                               static_cast<uint32_t>(pid));
-          storage->GetMutableThread(utid)->name_id = name;
-          break;
-        }
-        default: {
-          PERFETTO_DLOG("Skipping Kernel Object record with type %d", obj_type);
-          break;
-        }
-      }
-      break;
-    }
-    case kContextSwitch: {
-      // Context switch records come in order, so they do not need to go through
-      // TraceSorter.
-      uint32_t cpu = fuchsia_trace_utils::ReadField<uint32_t>(header, 16, 23);
-      uint32_t outgoing_state =
-          fuchsia_trace_utils::ReadField<uint32_t>(header, 24, 27);
-      uint32_t outgoing_thread_ref =
-          fuchsia_trace_utils::ReadField<uint32_t>(header, 28, 35);
-      uint32_t incoming_thread_ref =
-          fuchsia_trace_utils::ReadField<uint32_t>(header, 36, 43);
-      int32_t outgoing_priority =
-          fuchsia_trace_utils::ReadField<int32_t>(header, 44, 51);
-
-      int64_t ts;
-      if (!cursor.ReadTimestamp(current_provider_->ticks_per_second, &ts)) {
-        context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-        return;
-      }
-      if (ts == -1) {
-        context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-        return;
-      }
-
-      fuchsia_trace_utils::ThreadInfo outgoing_thread;
-      if (fuchsia_trace_utils::IsInlineThread(outgoing_thread_ref)) {
-        if (!cursor.ReadInlineThread(&outgoing_thread)) {
-          context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-          return;
-        }
-      } else {
-        outgoing_thread = current_provider_->thread_table[outgoing_thread_ref];
-      }
-
-      fuchsia_trace_utils::ThreadInfo incoming_thread;
-      if (fuchsia_trace_utils::IsInlineThread(incoming_thread_ref)) {
-        if (!cursor.ReadInlineThread(&incoming_thread)) {
-          context_->storage->IncrementStats(stats::fuchsia_invalid_event);
-          return;
-        }
-      } else {
-        incoming_thread = current_provider_->thread_table[incoming_thread_ref];
-      }
-
-      // A thread with priority 0 represents an idle CPU
-      if (cpu_threads_.count(cpu) != 0 && outgoing_priority != 0) {
-        // TODO(bhamrick): Some early events will fail to associate with their
-        // pid because the kernel object info event hasn't been processed yet.
-        if (pid_table_.count(outgoing_thread.tid) > 0) {
-          outgoing_thread.pid = pid_table_[outgoing_thread.tid];
-        }
-
-        UniqueTid utid =
-            procs->UpdateThread(static_cast<uint32_t>(outgoing_thread.tid),
-                                static_cast<uint32_t>(outgoing_thread.pid));
-        RunningThread previous_thread = cpu_threads_[cpu];
-
-        ftrace_utils::TaskState end_state;
-        switch (outgoing_state) {
-          case kThreadNew:
-          case kThreadRunning: {
-            end_state =
-                ftrace_utils::TaskState(ftrace_utils::TaskState::kRunnable);
-            break;
-          }
-          case kThreadBlocked: {
-            end_state = ftrace_utils::TaskState(
-                ftrace_utils::TaskState::kInterruptibleSleep);
-            break;
-          }
-          case kThreadSuspended: {
-            end_state =
-                ftrace_utils::TaskState(ftrace_utils::TaskState::kStopped);
-            break;
-          }
-          case kThreadDying: {
-            end_state =
-                ftrace_utils::TaskState(ftrace_utils::TaskState::kExitZombie);
-            break;
-          }
-          case kThreadDead: {
-            end_state =
-                ftrace_utils::TaskState(ftrace_utils::TaskState::kExitDead);
-            break;
-          }
-          default: {
-            break;
-          }
-        }
-
-        storage->mutable_slices()->AddSlice(cpu, previous_thread.start_ts,
-                                            ts - previous_thread.start_ts, utid,
-                                            end_state, outgoing_priority);
-      }
-
-      RunningThread new_running;
-      new_running.info = incoming_thread;
-      new_running.start_ts = ts;
-      cpu_threads_[cpu] = new_running;
-      break;
-    }
-    default: {
-      PERFETTO_DLOG("Skipping record of unknown type %d", record_type);
-      break;
-    }
-  }
-}
-
-void FuchsiaTraceTokenizer::RegisterProvider(uint32_t provider_id,
-                                             std::string name) {
-  std::unique_ptr<ProviderInfo> provider(new ProviderInfo());
-  provider->name = name;
-  current_provider_ = provider.get();
-  providers_[provider_id] = std::move(provider);
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h b/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h
deleted file mode 100644
index e5dd9af..0000000
--- a/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_FUCHSIA_FUCHSIA_TRACE_TOKENIZER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_FUCHSIA_FUCHSIA_TRACE_TOKENIZER_H_
-
-#include "src/trace_processor/chunked_trace_reader.h"
-#include "src/trace_processor/importers/fuchsia/fuchsia_trace_utils.h"
-#include "src/trace_processor/trace_blob_view.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-// The Fuchsia trace format is documented at
-// https://fuchsia.googlesource.com/fuchsia/+/HEAD/docs/development/tracing/trace-format/README.md
-class FuchsiaTraceTokenizer : public ChunkedTraceReader {
- public:
-  explicit FuchsiaTraceTokenizer(TraceProcessorContext*);
-  ~FuchsiaTraceTokenizer() override;
-
-  // ChunkedTraceReader implementation
-  util::Status Parse(std::unique_ptr<uint8_t[]>, size_t) override;
-
- private:
-  struct ProviderInfo {
-    std::string name;
-
-    std::unordered_map<uint64_t, StringId> string_table;
-    std::unordered_map<uint64_t, fuchsia_trace_utils::ThreadInfo> thread_table;
-
-    uint64_t ticks_per_second = 1000000000;
-  };
-
-  struct RunningThread {
-    fuchsia_trace_utils::ThreadInfo info;
-    int64_t start_ts;
-  };
-
-  void ParseRecord(TraceBlobView);
-  void RegisterProvider(uint32_t, std::string);
-
-  TraceProcessorContext* const context_;
-  std::vector<uint8_t> leftover_bytes_;
-
-  // Map from tid to pid. Used because in some places we do not get pid info.
-  // Fuchsia tids are never reused.
-  std::unordered_map<uint64_t, uint64_t> pid_table_;
-  std::unordered_map<uint32_t, std::unique_ptr<ProviderInfo>> providers_;
-  ProviderInfo* current_provider_;
-
-  std::unordered_map<uint32_t, RunningThread> cpu_threads_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_FUCHSIA_FUCHSIA_TRACE_TOKENIZER_H_
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_trace_utils.cc b/src/trace_processor/importers/fuchsia/fuchsia_trace_utils.cc
deleted file mode 100644
index 1edc8ba..0000000
--- a/src/trace_processor/importers/fuchsia/fuchsia_trace_utils.cc
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/importers/fuchsia/fuchsia_trace_utils.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace fuchsia_trace_utils {
-
-namespace {
-constexpr uint32_t kInlineStringMarker = 0x8000;
-constexpr uint32_t kInlineStringLengthMask = 0x7FFF;
-}  // namespace
-
-bool IsInlineString(uint32_t string_ref) {
-  // Treat a string ref of 0 (the empty string) as inline. The empty string is
-  // not a true entry in the string table.
-  return (string_ref & kInlineStringMarker) || (string_ref == 0);
-}
-
-bool IsInlineThread(uint32_t thread_ref) {
-  return thread_ref == 0;
-}
-
-// Converts a tick count to nanoseconds. Returns -1 if the result would not
-// fit in a nonnegative int64_t. Negative timestamps are not allowed by the
-// Fuchsia trace format. Also returns -1 if ticks_per_second is zero.
-int64_t TicksToNs(uint64_t ticks, uint64_t ticks_per_second) {
-  uint64_t ticks_hi = ticks >> 32;
-  uint64_t ticks_lo = ticks & ((uint64_t(1) << 32) - 1);
-  uint64_t ns_per_sec = 1000000000;
-  if (ticks_per_second == 0) {
-    return -1;
-  }
-  // This multiplication may overflow.
-  uint64_t result_hi = ticks_hi * ((ns_per_sec << 32) / ticks_per_second);
-  if (ticks_hi != 0 &&
-      result_hi / ticks_hi != ((ns_per_sec << 32) / ticks_per_second)) {
-    return -1;
-  }
-  // This computation never overflows, because ticks_lo is less than 2^32, and
-  // ns_per_sec = 10^9 < 2^32.
-  uint64_t result_lo = ticks_lo * ns_per_sec / ticks_per_second;
-  // Performing addition before the cast avoids undefined behavior.
-  int64_t result = static_cast<int64_t>(result_hi + result_lo);
-  // Check for addition overflow.
-  if (result < 0) {
-    return -1;
-  }
-  return result;
-}
-
-Variadic ArgValue::ToStorageVariadic(TraceStorage* storage) const {
-  switch (type_) {
-    case ArgType::kNull:
-      return Variadic::String(storage->InternString("null"));
-    case ArgType::kInt32:
-      return Variadic::Integer(static_cast<int64_t>(int32_));
-    case ArgType::kUint32:
-      return Variadic::Integer(static_cast<int64_t>(uint32_));
-    case ArgType::kInt64:
-      return Variadic::Integer(int64_);
-    case ArgType::kUint64:
-      return Variadic::Integer(static_cast<int64_t>(uint64_));
-    case ArgType::kDouble:
-      return Variadic::Real(double_);
-    case ArgType::kString:
-      return Variadic::String(string_);
-    case ArgType::kPointer:
-      return Variadic::Integer(static_cast<int64_t>(pointer_));
-    case ArgType::kKoid:
-      return Variadic::Integer(static_cast<int64_t>(koid_));
-    case ArgType::kUnknown:
-      return Variadic::String(storage->InternString("unknown"));
-  }
-  PERFETTO_FATAL("Not reached");  // Make GCC happy.
-}
-
-size_t RecordCursor::WordIndex() {
-  return word_index_;
-}
-
-void RecordCursor::SetWordIndex(size_t index) {
-  word_index_ = index;
-}
-
-bool RecordCursor::ReadTimestamp(uint64_t ticks_per_second, int64_t* ts_out) {
-  const uint8_t* ts_data;
-  if (!ReadWords(1, &ts_data)) {
-    return false;
-  }
-  if (ts_out != nullptr) {
-    uint64_t ticks;
-    memcpy(&ticks, ts_data, sizeof(uint64_t));
-    *ts_out = TicksToNs(ticks, ticks_per_second);
-  }
-  return true;
-}
-
-bool RecordCursor::ReadInlineString(uint32_t string_ref_or_len,
-                                    base::StringView* string_out) {
-  // Note that this works correctly for the empty string, where string_ref is 0.
-  size_t len = string_ref_or_len & kInlineStringLengthMask;
-  size_t len_words = (len + 7) / 8;
-  const uint8_t* string_data;
-  if (!ReadWords(len_words, &string_data)) {
-    return false;
-  }
-  if (string_out != nullptr) {
-    *string_out =
-        base::StringView(reinterpret_cast<const char*>(string_data), len);
-  }
-  return true;
-}
-
-bool RecordCursor::ReadInlineThread(ThreadInfo* thread_out) {
-  const uint8_t* thread_data;
-  if (!ReadWords(2, &thread_data)) {
-    return false;
-  }
-  if (thread_out != nullptr) {
-    memcpy(&thread_out->pid, thread_data, sizeof(uint64_t));
-    memcpy(&thread_out->tid, thread_data + sizeof(uint64_t), sizeof(uint64_t));
-  }
-  return true;
-}
-
-bool RecordCursor::ReadInt64(int64_t* out) {
-  const uint8_t* out_data;
-  if (!ReadWords(1, &out_data)) {
-    return false;
-  }
-  if (out != nullptr) {
-    memcpy(out, out_data, sizeof(int64_t));
-  }
-  return true;
-}
-
-bool RecordCursor::ReadUint64(uint64_t* out) {
-  const uint8_t* out_data;
-  if (!ReadWords(1, &out_data)) {
-    return false;
-  }
-  if (out != nullptr) {
-    memcpy(out, out_data, sizeof(uint64_t));
-  }
-  return true;
-}
-
-bool RecordCursor::ReadDouble(double* out) {
-  static_assert(sizeof(double) == sizeof(uint64_t), "double must be 64 bits");
-
-  const uint8_t* out_data;
-  if (!ReadWords(1, &out_data)) {
-    return false;
-  }
-  if (out != nullptr) {
-    memcpy(out, out_data, sizeof(double));
-  }
-  return true;
-}
-
-bool RecordCursor::ReadWords(size_t num_words, const uint8_t** data_out) {
-  const uint8_t* end = tbv_.data() + tbv_.length();
-  const uint8_t* data = tbv_.data() + sizeof(uint64_t) * word_index_;
-  // This addition is unconditional so that callers with data_out == nullptr do
-  // not necessarily have to check the return value, as future calls will fail
-  // due to attempting to read out of bounds.
-  word_index_ += num_words;
-  if (data + sizeof(uint64_t) * num_words <= end) {
-    if (data_out != nullptr) {
-      *data_out = data;
-    }
-    return true;
-  } else {
-    return false;
-  }
-}
-
-}  // namespace fuchsia_trace_utils
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_trace_utils.h b/src/trace_processor/importers/fuchsia/fuchsia_trace_utils.h
deleted file mode 100644
index c67b77f..0000000
--- a/src/trace_processor/importers/fuchsia/fuchsia_trace_utils.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_FUCHSIA_FUCHSIA_TRACE_UTILS_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_FUCHSIA_FUCHSIA_TRACE_UTILS_H_
-
-#include <stddef.h>
-#include <stdint.h>
-#include <functional>
-
-#include "perfetto/ext/base/string_view.h"
-#include "src/trace_processor/trace_blob_view.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace fuchsia_trace_utils {
-
-struct ThreadInfo {
-  uint64_t pid;
-  uint64_t tid;
-};
-
-template <class T>
-T ReadField(uint64_t word, size_t begin, size_t end) {
-  return static_cast<T>((word >> begin) &
-                        ((uint64_t(1) << (end - begin + 1)) - 1));
-}
-
-bool IsInlineString(uint32_t);
-bool IsInlineThread(uint32_t);
-int64_t TicksToNs(uint64_t ticks, uint64_t ticks_per_second);
-
-class ArgValue {
- public:
-  enum ArgType {
-    kNull,
-    kInt32,
-    kUint32,
-    kInt64,
-    kUint64,
-    kDouble,
-    kString,
-    kPointer,
-    kKoid,
-    kUnknown,
-  };
-
-  static ArgValue Null() {
-    ArgValue v;
-    v.type_ = ArgType::kNull;
-    v.int32_ = 0;
-    return v;
-  }
-
-  static ArgValue Int32(int32_t value) {
-    ArgValue v;
-    v.type_ = ArgType::kInt32;
-    v.int32_ = value;
-    return v;
-  }
-
-  static ArgValue Uint32(uint32_t value) {
-    ArgValue v;
-    v.type_ = ArgType::kUint32;
-    v.uint32_ = value;
-    return v;
-  }
-
-  static ArgValue Int64(int64_t value) {
-    ArgValue v;
-    v.type_ = ArgType::kInt64;
-    v.int64_ = value;
-    return v;
-  }
-
-  static ArgValue Uint64(uint64_t value) {
-    ArgValue v;
-    v.type_ = ArgType::kUint64;
-    v.uint64_ = value;
-    return v;
-  }
-
-  static ArgValue Double(double value) {
-    ArgValue v;
-    v.type_ = ArgType::kDouble;
-    v.double_ = value;
-    return v;
-  }
-
-  static ArgValue String(StringId value) {
-    ArgValue v;
-    v.type_ = ArgType::kString;
-    v.string_ = value;
-    return v;
-  }
-
-  static ArgValue Pointer(uint64_t value) {
-    ArgValue v;
-    v.type_ = ArgType::kPointer;
-    v.pointer_ = value;
-    return v;
-  }
-
-  static ArgValue Koid(uint64_t value) {
-    ArgValue v;
-    v.type_ = ArgType::kKoid;
-    v.koid_ = value;
-    return v;
-  }
-
-  static ArgValue Unknown() {
-    ArgValue v;
-    v.type_ = ArgType::kUnknown;
-    v.int32_ = 0;
-    return v;
-  }
-
-  ArgType Type() const { return type_; }
-
-  int32_t Int32() const {
-    PERFETTO_DCHECK(type_ == ArgType::kInt32);
-    return int32_;
-  }
-
-  uint32_t Uint32() const {
-    PERFETTO_DCHECK(type_ == ArgType::kUint32);
-    return uint32_;
-  }
-
-  int64_t Int64() const {
-    PERFETTO_DCHECK(type_ == ArgType::kInt64);
-    return int64_;
-  }
-
-  uint64_t Uint64() const {
-    PERFETTO_DCHECK(type_ == ArgType::kUint64);
-    return uint64_;
-  }
-
-  double Double() const {
-    PERFETTO_DCHECK(type_ == ArgType::kDouble);
-    return double_;
-  }
-
-  StringId String() const {
-    PERFETTO_DCHECK(type_ == ArgType::kString);
-    return string_;
-  }
-
-  uint64_t Pointer() const {
-    PERFETTO_DCHECK(type_ == ArgType::kPointer);
-    return pointer_;
-  }
-
-  uint64_t Koid() const {
-    PERFETTO_DCHECK(type_ == ArgType::kKoid);
-    return koid_;
-  }
-
-  Variadic ToStorageVariadic(TraceStorage*) const;
-
- private:
-  ArgType type_;
-  union {
-    int32_t int32_;
-    uint32_t uint32_;
-    int64_t int64_;
-    uint64_t uint64_;
-    double double_;
-    StringId string_;
-    uint64_t pointer_;
-    uint64_t koid_;
-  };
-};
-
-// This class maintains a location into the record, with helper functions to
-// read various trace data from the current location in a safe manner.
-//
-// In the context of Fuchsia trace records, a "word" is defined as 64 bits
-// regardless of platform. For more information, see
-// https://fuchsia.googlesource.com/fuchsia/+/refs/heads/master/docs/development/tracing/trace-format/
-class RecordCursor {
- public:
-  RecordCursor(const TraceBlobView* tbv) : tbv_(*tbv), word_index_(0) {}
-
-  size_t WordIndex();
-  void SetWordIndex(size_t index);
-
-  bool ReadTimestamp(uint64_t ticks_per_second, int64_t* ts_out);
-  bool ReadInlineString(uint32_t string_ref_or_len,
-                        base::StringView* string_out);
-  bool ReadInlineThread(ThreadInfo* thread_out);
-
-  bool ReadInt64(int64_t* out);
-  bool ReadUint64(uint64_t* out);
-  bool ReadDouble(double* out);
-
- private:
-  bool ReadWords(size_t num_words, const uint8_t** data_out);
-
-  const TraceBlobView& tbv_;
-  size_t word_index_;
-};
-
-}  // namespace fuchsia_trace_utils
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_FUCHSIA_FUCHSIA_TRACE_UTILS_H_
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_trace_utils_unittest.cc b/src/trace_processor/importers/fuchsia/fuchsia_trace_utils_unittest.cc
deleted file mode 100644
index 5b942ab..0000000
--- a/src/trace_processor/importers/fuchsia/fuchsia_trace_utils_unittest.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/importers/fuchsia/fuchsia_trace_utils.h"
-
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace fuchsia_trace_utils {
-namespace {
-
-TEST(FuchsiaTraceUtilsTest, TicksToNs) {
-  ASSERT_EQ(TicksToNs(40, 10), 4000000000);
-
-  // Case where naive computation would overflow
-  ASSERT_EQ(TicksToNs(40000000000, 1000000000), 40000000000);
-
-  // Test detecting overflow
-  ASSERT_EQ(TicksToNs(40000000000, 1), -1);
-}
-
-}  // namespace
-}  // namespace fuchsia_trace_utils
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/json/json_trace_parser.cc b/src/trace_processor/importers/json/json_trace_parser.cc
deleted file mode 100644
index e4a7ea1..0000000
--- a/src/trace_processor/importers/json/json_trace_parser.cc
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * 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.
- */
-
-// For bazel build.
-#include "perfetto/base/build_config.h"
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON_IMPORT)
-
-#include "src/trace_processor/importers/json/json_trace_parser.h"
-
-#include <inttypes.h>
-#include <json/reader.h>
-#include <json/value.h>
-
-#include <limits>
-#include <string>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/ext/base/utils.h"
-#include "src/trace_processor/importers/json/json_trace_utils.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/slice_tracker.h"
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/track_tracker.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-JsonTraceParser::JsonTraceParser(TraceProcessorContext* context)
-    : context_(context) {}
-
-JsonTraceParser::~JsonTraceParser() = default;
-
-void JsonTraceParser::ParseFtracePacket(uint32_t,
-                                        int64_t,
-                                        TimestampedTracePiece) {
-  PERFETTO_FATAL("Json Trace Parser cannot handle ftrace packets.");
-}
-
-void JsonTraceParser::ParseTracePacket(int64_t timestamp,
-                                       TimestampedTracePiece ttp) {
-  PERFETTO_DCHECK(ttp.json_value != nullptr);
-  const Json::Value& value = *(ttp.json_value);
-
-  ProcessTracker* procs = context_->process_tracker.get();
-  TraceStorage* storage = context_->storage.get();
-  SliceTracker* slice_tracker = context_->slice_tracker.get();
-
-  auto& ph = value["ph"];
-  if (!ph.isString())
-    return;
-  char phase = *ph.asCString();
-
-  base::Optional<uint32_t> opt_pid;
-  base::Optional<uint32_t> opt_tid;
-
-  if (value.isMember("pid"))
-    opt_pid = json_trace_utils::CoerceToUint32(value["pid"]);
-  if (value.isMember("tid"))
-    opt_tid = json_trace_utils::CoerceToUint32(value["tid"]);
-
-  uint32_t pid = opt_pid.value_or(0);
-  uint32_t tid = opt_tid.value_or(pid);
-
-  base::StringView cat = value.isMember("cat")
-                             ? base::StringView(value["cat"].asCString())
-                             : base::StringView();
-  base::StringView name = value.isMember("name")
-                              ? base::StringView(value["name"].asCString())
-                              : base::StringView();
-
-  StringId cat_id = storage->InternString(cat);
-  StringId name_id = storage->InternString(name);
-  UniqueTid utid = procs->UpdateThread(tid, pid);
-
-  switch (phase) {
-    case 'B': {  // TRACE_EVENT_BEGIN.
-      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-      slice_tracker->Begin(timestamp, track_id, utid, RefType::kRefUtid, cat_id,
-                           name_id);
-      break;
-    }
-    case 'E': {  // TRACE_EVENT_END.
-      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-      slice_tracker->End(timestamp, track_id, cat_id, name_id);
-      break;
-    }
-    case 'X': {  // TRACE_EVENT (scoped event).
-      base::Optional<int64_t> opt_dur =
-          json_trace_utils::CoerceToNs(value["dur"]);
-      if (!opt_dur.has_value())
-        return;
-      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-      slice_tracker->Scoped(timestamp, track_id, utid, RefType::kRefUtid,
-                            cat_id, name_id, opt_dur.value());
-      break;
-    }
-    case 'M': {  // Metadata events (process and thread names).
-      if (strcmp(value["name"].asCString(), "thread_name") == 0 &&
-          !value["args"]["name"].empty()) {
-        const char* thread_name = value["args"]["name"].asCString();
-        auto thread_name_id = context_->storage->InternString(thread_name);
-        procs->UpdateThreadName(tid, thread_name_id);
-        break;
-      }
-      if (strcmp(value["name"].asCString(), "process_name") == 0 &&
-          !value["args"]["name"].empty()) {
-        const char* proc_name = value["args"]["name"].asCString();
-        procs->SetProcessMetadata(pid, base::nullopt, proc_name);
-        break;
-      }
-    }
-  }
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON_IMPORT)
diff --git a/src/trace_processor/importers/json/json_trace_parser.h b/src/trace_processor/importers/json/json_trace_parser.h
deleted file mode 100644
index 30941bf..0000000
--- a/src/trace_processor/importers/json/json_trace_parser.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_JSON_JSON_TRACE_PARSER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_JSON_JSON_TRACE_PARSER_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <tuple>
-#include <unordered_map>
-
-#include "src/trace_processor/timestamped_trace_piece.h"
-#include "src/trace_processor/trace_parser.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace Json {
-class Value;
-}
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-base::Optional<int64_t> CoerceToInt64(const Json::Value& value);
-base::Optional<uint32_t> CoerceToUint32(const Json::Value& value);
-
-// Parses legacy chrome JSON traces. The support for now is extremely rough
-// and supports only explicit TRACE_EVENT_BEGIN/END events.
-class JsonTraceParser : public TraceParser {
- public:
-  explicit JsonTraceParser(TraceProcessorContext*);
-  ~JsonTraceParser() override;
-
-  // TraceParser implementation.
-  void ParseTracePacket(int64_t timestamp, TimestampedTracePiece) override;
-  void ParseFtracePacket(uint32_t, int64_t, TimestampedTracePiece) override;
-
- private:
-  TraceProcessorContext* const context_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_JSON_JSON_TRACE_PARSER_H_
diff --git a/src/trace_processor/importers/json/json_trace_tokenizer.cc b/src/trace_processor/importers/json/json_trace_tokenizer.cc
deleted file mode 100644
index 0eac6df..0000000
--- a/src/trace_processor/importers/json/json_trace_tokenizer.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-// For bazel build.
-#include "perfetto/base/build_config.h"
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON_IMPORT)
-
-#include "src/trace_processor/importers/json/json_trace_tokenizer.h"
-
-#include <json/reader.h>
-#include <json/value.h>
-
-#include "src/trace_processor/importers/json/json_trace_utils.h"
-#include "src/trace_processor/stats.h"
-#include "src/trace_processor/trace_blob_view.h"
-#include "src/trace_processor/trace_sorter.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Parses at most one JSON dictionary and returns a pointer to the end of it,
-// or nullptr if no dict could be detected.
-// This is to avoid decoding the full trace in memory and reduce heap traffic.
-// E.g.  input:  { a:1 b:{ c:2, d:{ e:3 } } } , { a:4, ... },
-//       output: [   only this is parsed    ] ^return value points here.
-ReadDictRes ReadOneJsonDict(const char* start,
-                            const char* end,
-                            Json::Value* value,
-                            const char** next) {
-  int braces = 0;
-  int square_brackets = 0;
-  const char* dict_begin = nullptr;
-  bool in_string = false;
-  bool is_escaping = false;
-  for (const char* s = start; s < end; s++) {
-    if (isspace(*s) || *s == ',')
-      continue;
-    if (*s == '"' && !is_escaping) {
-      in_string = !in_string;
-      continue;
-    }
-    if (in_string) {
-      // If we're in a string and we see a backslash and the last character was
-      // not a backslash the next character is escaped:
-      is_escaping = *s == '\\' && !is_escaping;
-      // If we're currently parsing a string we should ignore otherwise special
-      // characters:
-      continue;
-    }
-    if (*s == '{') {
-      if (braces == 0)
-        dict_begin = s;
-      braces++;
-      continue;
-    }
-    if (*s == '}') {
-      if (braces <= 0)
-        return kEndOfTrace;
-      if (--braces > 0)
-        continue;
-      Json::Reader reader;
-      if (!reader.parse(dict_begin, s + 1, *value, /*collectComments=*/false)) {
-        PERFETTO_ELOG("JSON error: %s",
-                      reader.getFormattedErrorMessages().c_str());
-        return kFatalError;
-      }
-      *next = s + 1;
-      return kFoundDict;
-    }
-    if (*s == '[') {
-      square_brackets++;
-      continue;
-    }
-    if (*s == ']') {
-      if (square_brackets == 0) {
-        // We've reached the end of [traceEvents] array.
-        // There might be other top level keys in the json (e.g. metadata)
-        // after.
-        // TODO(dproy): Handle trace metadata importing.
-        return kEndOfTrace;
-      }
-      square_brackets--;
-    }
-  }
-  return kNeedsMoreData;
-}
-
-JsonTraceTokenizer::JsonTraceTokenizer(TraceProcessorContext* ctx)
-    : context_(ctx) {}
-JsonTraceTokenizer::~JsonTraceTokenizer() = default;
-
-util::Status JsonTraceTokenizer::Parse(std::unique_ptr<uint8_t[]> data,
-                                       size_t size) {
-  buffer_.insert(buffer_.end(), data.get(), data.get() + size);
-  const char* buf = buffer_.data();
-  const char* next = buf;
-  const char* end = buf + buffer_.size();
-
-  if (offset_ == 0) {
-    // Trace could begin in any of these ways:
-    // {"traceEvents":[{
-    // { "traceEvents": [{
-    // [{
-    // Skip up to the first '['
-    while (next != end && *next != '[') {
-      next++;
-    }
-    if (next == end)
-      return util::ErrStatus("Failed to parse: first chunk missing opening [");
-    next++;
-  }
-
-  auto* trace_sorter = context_->sorter.get();
-
-  while (next < end) {
-    std::unique_ptr<Json::Value> value(new Json::Value());
-    const auto res = ReadOneJsonDict(next, end, value.get(), &next);
-    if (res == kFatalError)
-      return util::ErrStatus("Encountered fatal error while parsing JSON");
-    if (res == kEndOfTrace || res == kNeedsMoreData)
-      break;
-
-    base::Optional<int64_t> opt_ts =
-        json_trace_utils::CoerceToNs((*value)["ts"]);
-    if (!opt_ts.has_value()) {
-      context_->storage->IncrementStats(stats::json_tokenizer_failure);
-      continue;
-    }
-    int64_t ts = opt_ts.value();
-
-    trace_sorter->PushJsonValue(ts, std::move(value));
-  }
-
-  offset_ += static_cast<uint64_t>(next - buf);
-  buffer_.erase(buffer_.begin(), buffer_.begin() + (next - buf));
-  return util::OkStatus();
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON_IMPORT)
diff --git a/src/trace_processor/importers/json/json_trace_tokenizer.h b/src/trace_processor/importers/json/json_trace_tokenizer.h
deleted file mode 100644
index 9eb15b3..0000000
--- a/src/trace_processor/importers/json/json_trace_tokenizer.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_JSON_JSON_TRACE_TOKENIZER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_JSON_JSON_TRACE_TOKENIZER_H_
-
-#include <stdint.h>
-
-#include "src/trace_processor/chunked_trace_reader.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace Json {
-class Value;
-}
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-// Visible for testing.
-enum ReadDictRes { kFoundDict, kNeedsMoreData, kEndOfTrace, kFatalError };
-
-// Visible for testing.
-ReadDictRes ReadOneJsonDict(const char* start,
-                            const char* end,
-                            Json::Value* value,
-                            const char** next);
-
-// Reads a JSON trace in chunks and extracts top level json objects.
-class JsonTraceTokenizer : public ChunkedTraceReader {
- public:
-  explicit JsonTraceTokenizer(TraceProcessorContext*);
-  ~JsonTraceTokenizer() override;
-
-  // ChunkedTraceReader implementation.
-  util::Status Parse(std::unique_ptr<uint8_t[]>, size_t) override;
-
- private:
-  TraceProcessorContext* const context_;
-
-  uint64_t offset_ = 0;
-  // Used to glue together JSON objects that span across two (or more)
-  // Parse boundaries.
-  std::vector<char> buffer_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_JSON_JSON_TRACE_TOKENIZER_H_
diff --git a/src/trace_processor/importers/json/json_trace_tokenizer_unittest.cc b/src/trace_processor/importers/json/json_trace_tokenizer_unittest.cc
deleted file mode 100644
index 4305120..0000000
--- a/src/trace_processor/importers/json/json_trace_tokenizer_unittest.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/importers/json/json_trace_tokenizer.h"
-
-#include <json/value.h>
-
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-TEST(JsonTraceTokenizerTest, Success) {
-  const char* start = R"({ "foo": "bar" })";
-  const char* end = start + strlen(start);
-  const char* next = nullptr;
-  Json::Value value;
-  ReadDictRes result = ReadOneJsonDict(start, end, &value, &next);
-
-  ASSERT_EQ(result, kFoundDict);
-  ASSERT_EQ(next, end);
-  ASSERT_EQ(value["foo"].asString(), "bar");
-}
-
-TEST(JsonTraceTokenizerTest, QuotedBraces) {
-  const char* start = R"({ "foo": "}\"bar{\\" })";
-  const char* end = start + strlen(start);
-  const char* next = nullptr;
-  Json::Value value;
-  ReadDictRes result = ReadOneJsonDict(start, end, &value, &next);
-
-  ASSERT_EQ(result, kFoundDict);
-  ASSERT_EQ(next, end);
-  ASSERT_EQ(value["foo"].asString(), "}\"bar{\\");
-}
-
-TEST(JsonTraceTokenizerTest, TwoDicts) {
-  const char* start = R"({"foo": 1}, {"bar": 2})";
-  const char* middle = start + strlen(R"({"foo": 1})");
-  const char* end = start + strlen(start);
-  const char* next = nullptr;
-  Json::Value value;
-
-  ASSERT_EQ(ReadOneJsonDict(start, end, &value, &next), kFoundDict);
-  ASSERT_EQ(next, middle);
-  ASSERT_EQ(value["foo"].asInt(), 1);
-
-  ASSERT_EQ(ReadOneJsonDict(next, end, &value, &next), kFoundDict);
-  ASSERT_EQ(next, end);
-  ASSERT_EQ(value["bar"].asInt(), 2);
-}
-
-TEST(JsonTraceTokenizerTest, NeedMoreData) {
-  const char* start = R"({"foo": 1)";
-  const char* end = start + strlen(start);
-  const char* next = nullptr;
-  Json::Value value;
-
-  ASSERT_EQ(ReadOneJsonDict(start, end, &value, &next), kNeedsMoreData);
-  ASSERT_EQ(next, nullptr);
-}
-
-TEST(JsonTraceTokenizerTest, FatalError) {
-  const char* start = R"({helloworld})";
-  const char* end = start + strlen(start);
-  const char* next = nullptr;
-  Json::Value value;
-
-  ASSERT_EQ(ReadOneJsonDict(start, end, &value, &next), kFatalError);
-  ASSERT_EQ(next, nullptr);
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/json/json_trace_utils.cc b/src/trace_processor/importers/json/json_trace_utils.cc
deleted file mode 100644
index a4802ff..0000000
--- a/src/trace_processor/importers/json/json_trace_utils.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-// For bazel build.
-#include "perfetto/base/build_config.h"
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON_IMPORT)
-
-#include "src/trace_processor/importers/json/json_trace_utils.h"
-
-#include <json/value.h>
-#include <limits>
-
-namespace perfetto {
-namespace trace_processor {
-namespace json_trace_utils {
-
-// Json trace event timestamps are in us.
-// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit#heading=h.nso4gcezn7n1
-base::Optional<int64_t> CoerceToNs(const Json::Value& value) {
-  switch (static_cast<size_t>(value.type())) {
-    case Json::realValue:
-      return static_cast<int64_t>(value.asDouble() * 1000);
-    case Json::uintValue:
-    case Json::intValue:
-      return value.asInt64() * 1000;
-    case Json::stringValue: {
-      std::string s = value.asString();
-      char* end;
-      int64_t n = strtoll(s.c_str(), &end, 10);
-      if (end != s.data() + s.size())
-        return base::nullopt;
-      return n * 1000;
-    }
-    default:
-      return base::nullopt;
-  }
-}
-
-base::Optional<int64_t> CoerceToInt64(const Json::Value& value) {
-  switch (static_cast<size_t>(value.type())) {
-    case Json::realValue:
-    case Json::uintValue:
-    case Json::intValue:
-      return value.asInt64();
-    case Json::stringValue: {
-      std::string s = value.asString();
-      char* end;
-      int64_t n = strtoll(s.c_str(), &end, 10);
-      if (end != s.data() + s.size())
-        return base::nullopt;
-      return n;
-    }
-    default:
-      return base::nullopt;
-  }
-}
-
-base::Optional<uint32_t> CoerceToUint32(const Json::Value& value) {
-  base::Optional<int64_t> result = CoerceToInt64(value);
-  if (!result.has_value())
-    return base::nullopt;
-  int64_t n = result.value();
-  if (n < 0 || n > std::numeric_limits<uint32_t>::max())
-    return base::nullopt;
-  return static_cast<uint32_t>(n);
-}
-
-}  // namespace json_trace_utils
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON_IMPORT)
diff --git a/src/trace_processor/importers/json/json_trace_utils.h b/src/trace_processor/importers/json/json_trace_utils.h
deleted file mode 100644
index 3a18641..0000000
--- a/src/trace_processor/importers/json/json_trace_utils.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_JSON_JSON_TRACE_UTILS_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_JSON_JSON_TRACE_UTILS_H_
-
-#include <stdint.h>
-
-#include "perfetto/ext/base/optional.h"
-
-namespace Json {
-class Value;
-}
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-namespace json_trace_utils {
-
-base::Optional<int64_t> CoerceToNs(const Json::Value& value);
-base::Optional<int64_t> CoerceToInt64(const Json::Value& value);
-base::Optional<uint32_t> CoerceToUint32(const Json::Value& value);
-
-}  // namespace json_trace_utils
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_JSON_JSON_TRACE_UTILS_H_
diff --git a/src/trace_processor/importers/json/json_trace_utils_unittest.cc b/src/trace_processor/importers/json/json_trace_utils_unittest.cc
deleted file mode 100644
index fcc115d..0000000
--- a/src/trace_processor/importers/json/json_trace_utils_unittest.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.
- */
-
-#include "src/trace_processor/importers/json/json_trace_utils.h"
-
-#include <json/value.h>
-
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace json_trace_utils {
-namespace {
-
-TEST(JsonTraceUtilsTest, CoerceToUint32) {
-  ASSERT_EQ(CoerceToUint32(Json::Value(42)).value_or(0), 42u);
-  ASSERT_EQ(CoerceToUint32(Json::Value("42")).value_or(0), 42u);
-  ASSERT_EQ(CoerceToInt64(Json::Value(42.1)).value_or(-1), 42);
-}
-
-TEST(JsonTraceUtilsTest, CoerceToInt64) {
-  ASSERT_EQ(CoerceToInt64(Json::Value(42)).value_or(-1), 42);
-  ASSERT_EQ(CoerceToInt64(Json::Value("42")).value_or(-1), 42);
-  ASSERT_EQ(CoerceToInt64(Json::Value(42.1)).value_or(-1), 42);
-  ASSERT_FALSE(CoerceToInt64(Json::Value("foo")).has_value());
-  ASSERT_FALSE(CoerceToInt64(Json::Value("1234!")).has_value());
-}
-
-TEST(JsonTraceUtilsTest, CoerceToNs) {
-  ASSERT_EQ(CoerceToNs(Json::Value(42)).value_or(-1), 42000);
-  ASSERT_EQ(CoerceToNs(Json::Value("42")).value_or(-1), 42000);
-  ASSERT_EQ(CoerceToNs(Json::Value(42.1)).value_or(-1), 42100);
-  ASSERT_FALSE(CoerceToNs(Json::Value("foo")).has_value());
-  ASSERT_FALSE(CoerceToNs(Json::Value("1234!")).has_value());
-}
-
-}  // namespace
-}  // namespace json_trace_utils
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/android_probes_module.h b/src/trace_processor/importers/proto/android_probes_module.h
deleted file mode 100644
index 94d90a5..0000000
--- a/src/trace_processor/importers/proto/android_probes_module.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_ANDROID_PROBES_MODULE_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_ANDROID_PROBES_MODULE_H_
-
-#include "perfetto/base/build_config.h"
-#include "src/trace_processor/importers/proto/android_probes_parser.h"
-#include "src/trace_processor/importers/proto/proto_importer_module.h"
-#include "src/trace_processor/timestamped_trace_piece.h"
-
-#include "protos/perfetto/config/trace_config.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class AndroidProbesModule : public ProtoImporterModuleBase<PERFETTO_BUILDFLAG(
-                                PERFETTO_TP_ANDROID_PROBES)> {
- public:
-  explicit AndroidProbesModule(TraceProcessorContext* context)
-      : ProtoImporterModuleBase(context), parser_(context) {}
-
-  ModuleResult ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
-                           const TimestampedTracePiece& ttp) {
-    if (decoder.has_battery()) {
-      parser_.ParseBatteryCounters(ttp.timestamp, decoder.battery());
-      return ModuleResult::Handled();
-    }
-
-    if (decoder.has_power_rails()) {
-      parser_.ParsePowerRails(ttp.timestamp, decoder.power_rails());
-      return ModuleResult::Handled();
-    }
-
-    if (decoder.has_android_log()) {
-      parser_.ParseAndroidLogPacket(decoder.android_log());
-      return ModuleResult::Handled();
-    }
-
-    if (decoder.has_packages_list()) {
-      parser_.ParseAndroidPackagesList(decoder.packages_list());
-      return ModuleResult::Handled();
-    }
-
-    return ModuleResult::Ignored();
-  }
-
-  ModuleResult ParseTraceConfig(
-      const protos::pbzero::TraceConfig::Decoder& decoder) {
-    if (decoder.has_statsd_metadata()) {
-      parser_.ParseStatsdMetadata(decoder.statsd_metadata());
-      return ModuleResult::Handled();
-    }
-    return ModuleResult::Ignored();
-  }
-
- private:
-  AndroidProbesParser parser_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_ANDROID_PROBES_MODULE_H_
diff --git a/src/trace_processor/importers/proto/android_probes_parser.cc b/src/trace_processor/importers/proto/android_probes_parser.cc
deleted file mode 100644
index f193885..0000000
--- a/src/trace_processor/importers/proto/android_probes_parser.cc
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/importers/proto/android_probes_parser.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/traced/sys_stats_counters.h"
-#include "src/trace_processor/args_tracker.h"
-#include "src/trace_processor/clock_tracker.h"
-#include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/syscall_tracker.h"
-#include "src/trace_processor/trace_processor_context.h"
-
-#include "protos/perfetto/common/android_log_constants.pbzero.h"
-#include "protos/perfetto/config/trace_config.pbzero.h"
-#include "protos/perfetto/trace/android/android_log.pbzero.h"
-#include "protos/perfetto/trace/android/packages_list.pbzero.h"
-#include "protos/perfetto/trace/clock_snapshot.pbzero.h"
-#include "protos/perfetto/trace/power/battery_counters.pbzero.h"
-#include "protos/perfetto/trace/power/power_rails.pbzero.h"
-#include "protos/perfetto/trace/ps/process_stats.pbzero.h"
-#include "protos/perfetto/trace/ps/process_tree.pbzero.h"
-#include "protos/perfetto/trace/sys_stats/sys_stats.pbzero.h"
-#include "protos/perfetto/trace/system_info.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-AndroidProbesParser::AndroidProbesParser(TraceProcessorContext* context)
-    : context_(context),
-      batt_charge_id_(context->storage->InternString("batt.charge_uah")),
-      batt_capacity_id_(context->storage->InternString("batt.capacity_pct")),
-      batt_current_id_(context->storage->InternString("batt.current_ua")),
-      batt_current_avg_id_(
-          context->storage->InternString("batt.current.avg_ua")) {}
-
-void AndroidProbesParser::ParseBatteryCounters(int64_t ts, ConstBytes blob) {
-  protos::pbzero::BatteryCounters::Decoder evt(blob.data, blob.size);
-  if (evt.has_charge_counter_uah()) {
-    TrackId track =
-        context_->track_tracker->InternGlobalCounterTrack(batt_charge_id_);
-    context_->event_tracker->PushCounter(ts, evt.charge_counter_uah(), track);
-  }
-  if (evt.has_capacity_percent()) {
-    TrackId track =
-        context_->track_tracker->InternGlobalCounterTrack(batt_capacity_id_);
-    context_->event_tracker->PushCounter(
-        ts, static_cast<double>(evt.capacity_percent()), track);
-  }
-  if (evt.has_current_ua()) {
-    TrackId track =
-        context_->track_tracker->InternGlobalCounterTrack(batt_current_id_);
-    context_->event_tracker->PushCounter(ts, evt.current_ua(), track);
-  }
-  if (evt.has_current_avg_ua()) {
-    TrackId track =
-        context_->track_tracker->InternGlobalCounterTrack(batt_current_avg_id_);
-    context_->event_tracker->PushCounter(ts, evt.current_avg_ua(), track);
-  }
-}
-
-void AndroidProbesParser::ParsePowerRails(int64_t ts, ConstBytes blob) {
-  protos::pbzero::PowerRails::Decoder evt(blob.data, blob.size);
-  if (evt.has_rail_descriptor()) {
-    for (auto it = evt.rail_descriptor(); it; ++it) {
-      protos::pbzero::PowerRails::RailDescriptor::Decoder desc(*it);
-      uint32_t idx = desc.index();
-      if (PERFETTO_UNLIKELY(idx > 256)) {
-        PERFETTO_DLOG("Skipping excessively large power_rail index %" PRIu32,
-                      idx);
-        continue;
-      }
-      if (power_rails_strs_id_.size() <= idx)
-        power_rails_strs_id_.resize(idx + 1);
-      char counter_name[255];
-      snprintf(counter_name, sizeof(counter_name), "power.%.*s_uws",
-               int(desc.rail_name().size), desc.rail_name().data);
-      power_rails_strs_id_[idx] = context_->storage->InternString(counter_name);
-    }
-  }
-
-  if (evt.has_energy_data()) {
-    for (auto it = evt.energy_data(); it; ++it) {
-      protos::pbzero::PowerRails::EnergyData::Decoder desc(*it);
-      if (desc.index() < power_rails_strs_id_.size()) {
-        int64_t actual_ts =
-            desc.has_timestamp_ms()
-                ? static_cast<int64_t>(desc.timestamp_ms()) * 1000000
-                : ts;
-        TrackId track = context_->track_tracker->InternGlobalCounterTrack(
-            power_rails_strs_id_[desc.index()]);
-        context_->event_tracker->PushCounter(actual_ts, desc.energy(), track);
-      } else {
-        context_->storage->IncrementStats(stats::power_rail_unknown_index);
-      }
-    }
-  }
-}
-
-void AndroidProbesParser::ParseAndroidLogPacket(ConstBytes blob) {
-  protos::pbzero::AndroidLogPacket::Decoder packet(blob.data, blob.size);
-  for (auto it = packet.events(); it; ++it)
-    ParseAndroidLogEvent(*it);
-
-  if (packet.has_stats())
-    ParseAndroidLogStats(packet.stats());
-}
-
-void AndroidProbesParser::ParseAndroidLogEvent(ConstBytes blob) {
-  // TODO(primiano): Add events and non-stringified fields to the "raw" table.
-  protos::pbzero::AndroidLogPacket::LogEvent::Decoder evt(blob.data, blob.size);
-  int64_t ts = static_cast<int64_t>(evt.timestamp());
-  uint32_t pid = static_cast<uint32_t>(evt.pid());
-  uint32_t tid = static_cast<uint32_t>(evt.tid());
-  uint8_t prio = static_cast<uint8_t>(evt.prio());
-  StringId tag_id = context_->storage->InternString(
-      evt.has_tag() ? evt.tag() : base::StringView());
-  StringId msg_id = context_->storage->InternString(
-      evt.has_message() ? evt.message() : base::StringView());
-
-  char arg_msg[4096];
-  char* arg_str = &arg_msg[0];
-  *arg_str = '\0';
-  auto arg_avail = [&arg_msg, &arg_str]() {
-    return sizeof(arg_msg) - static_cast<size_t>(arg_str - arg_msg);
-  };
-  for (auto it = evt.args(); it; ++it) {
-    protos::pbzero::AndroidLogPacket::LogEvent::Arg::Decoder arg(*it);
-    if (!arg.has_name())
-      continue;
-    arg_str +=
-        snprintf(arg_str, arg_avail(),
-                 " %.*s=", static_cast<int>(arg.name().size), arg.name().data);
-    if (arg.has_string_value()) {
-      arg_str += snprintf(arg_str, arg_avail(), "\"%.*s\"",
-                          static_cast<int>(arg.string_value().size),
-                          arg.string_value().data);
-    } else if (arg.has_int_value()) {
-      arg_str += snprintf(arg_str, arg_avail(), "%" PRId64, arg.int_value());
-    } else if (arg.has_float_value()) {
-      arg_str += snprintf(arg_str, arg_avail(), "%f",
-                          static_cast<double>(arg.float_value()));
-    }
-  }
-
-  if (prio == 0)
-    prio = protos::pbzero::AndroidLogPriority::PRIO_INFO;
-
-  if (arg_str != &arg_msg[0]) {
-    PERFETTO_DCHECK(msg_id.is_null());
-    // Skip the first space char (" foo=1 bar=2" -> "foo=1 bar=2").
-    msg_id = context_->storage->InternString(&arg_msg[1]);
-  }
-  UniquePid utid = tid ? context_->process_tracker->UpdateThread(tid, pid) : 0;
-  base::Optional<int64_t> opt_trace_time = context_->clock_tracker->ToTraceTime(
-      protos::pbzero::ClockSnapshot::Clock::REALTIME, ts);
-  if (!opt_trace_time)
-    return;
-
-  // Log events are NOT required to be sorted by trace_time. The virtual table
-  // will take care of sorting on-demand.
-  context_->storage->mutable_android_log()->AddLogEvent(
-      opt_trace_time.value(), utid, prio, tag_id, msg_id);
-}
-
-void AndroidProbesParser::ParseAndroidLogStats(ConstBytes blob) {
-  protos::pbzero::AndroidLogPacket::Stats::Decoder evt(blob.data, blob.size);
-  if (evt.has_num_failed()) {
-    context_->storage->SetStats(stats::android_log_num_failed,
-                                static_cast<int64_t>(evt.num_failed()));
-  }
-
-  if (evt.has_num_skipped()) {
-    context_->storage->SetStats(stats::android_log_num_skipped,
-                                static_cast<int64_t>(evt.num_skipped()));
-  }
-
-  if (evt.has_num_total()) {
-    context_->storage->SetStats(stats::android_log_num_total,
-                                static_cast<int64_t>(evt.num_total()));
-  }
-}
-
-void AndroidProbesParser::ParseStatsdMetadata(ConstBytes blob) {
-  protos::pbzero::TraceConfig::StatsdMetadata::Decoder metadata(blob.data,
-                                                                blob.size);
-  if (metadata.has_triggering_subscription_id()) {
-    context_->storage->SetMetadata(
-        metadata::statsd_triggering_subscription_id,
-        Variadic::Integer(metadata.triggering_subscription_id()));
-  }
-}
-
-void AndroidProbesParser::ParseAndroidPackagesList(ConstBytes blob) {
-  protos::pbzero::PackagesList::Decoder pkg_list(blob.data, blob.size);
-  context_->storage->SetStats(stats::packages_list_has_read_errors,
-                              pkg_list.read_error());
-  context_->storage->SetStats(stats::packages_list_has_parse_errors,
-                              pkg_list.parse_error());
-
-  // Insert the package info into arg sets (one set per package), with the arg
-  // set ids collected in the Metadata table, under
-  // metadata::android_packages_list key type.
-  for (auto it = pkg_list.packages(); it; ++it) {
-    // Insert a placeholder metadata entry, which will be overwritten by the
-    // arg_set_id when the arg tracker is flushed.
-    RowId row_id = context_->storage->AppendMetadata(
-        metadata::android_packages_list, Variadic::Integer(0));
-
-    auto add_arg = [this, row_id](base::StringView name, Variadic value) {
-      StringId key_id = context_->storage->InternString(name);
-      context_->args_tracker->AddArg(row_id, key_id, key_id, value);
-    };
-    protos::pbzero::PackagesList_PackageInfo::Decoder pkg(*it);
-    add_arg("name",
-            Variadic::String(context_->storage->InternString(pkg.name())));
-    add_arg("uid", Variadic::UnsignedInteger(pkg.uid()));
-    add_arg("debuggable", Variadic::Boolean(pkg.debuggable()));
-    add_arg("profileable_from_shell",
-            Variadic::Boolean(pkg.profileable_from_shell()));
-    add_arg("version_code", Variadic::Integer(pkg.version_code()));
-  }
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/android_probes_parser.h b/src/trace_processor/importers/proto/android_probes_parser.h
deleted file mode 100644
index 41362ed..0000000
--- a/src/trace_processor/importers/proto/android_probes_parser.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_ANDROID_PROBES_PARSER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_ANDROID_PROBES_PARSER_H_
-
-#include <vector>
-
-#include "perfetto/protozero/field.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-class AndroidProbesParser {
- public:
-  using ConstBytes = protozero::ConstBytes;
-
-  explicit AndroidProbesParser(TraceProcessorContext*);
-
-  void ParseBatteryCounters(int64_t ts, ConstBytes);
-  void ParsePowerRails(int64_t ts, ConstBytes);
-  void ParseAndroidLogPacket(ConstBytes);
-  void ParseAndroidLogEvent(ConstBytes);
-  void ParseAndroidLogStats(ConstBytes);
-  void ParseStatsdMetadata(ConstBytes);
-  void ParseAndroidPackagesList(ConstBytes);
-
- private:
-  TraceProcessorContext* const context_;
-
-  const StringId batt_charge_id_;
-  const StringId batt_capacity_id_;
-  const StringId batt_current_id_;
-  const StringId batt_current_avg_id_;
-  std::vector<StringId> power_rails_strs_id_;
-};
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_ANDROID_PROBES_PARSER_H_
diff --git a/src/trace_processor/importers/proto/graphics_event_module.h b/src/trace_processor/importers/proto/graphics_event_module.h
deleted file mode 100644
index 2b246d2..0000000
--- a/src/trace_processor/importers/proto/graphics_event_module.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_GRAPHICS_EVENT_MODULE_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_GRAPHICS_EVENT_MODULE_H_
-
-#include "perfetto/base/build_config.h"
-#include "src/trace_processor/importers/proto/graphics_event_parser.h"
-#include "src/trace_processor/importers/proto/proto_importer_module.h"
-#include "src/trace_processor/timestamped_trace_piece.h"
-
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class GraphicsEventModule
-    : public ProtoImporterModuleBase<PERFETTO_BUILDFLAG(PERFETTO_TP_GRAPHICS)> {
- public:
-  explicit GraphicsEventModule(TraceProcessorContext* context)
-      : ProtoImporterModuleBase(context), parser_(context) {}
-
-  ModuleResult ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
-                           const TimestampedTracePiece& ttp) {
-    if (decoder.has_gpu_counter_event()) {
-      parser_.ParseGpuCounterEvent(ttp.timestamp, decoder.gpu_counter_event());
-      return ModuleResult::Handled();
-    }
-
-    if (decoder.has_gpu_render_stage_event()) {
-      parser_.ParseGpuRenderStageEvent(ttp.timestamp,
-                                       decoder.gpu_render_stage_event());
-      return ModuleResult::Handled();
-    }
-
-    if (decoder.has_gpu_log()) {
-      parser_.ParseGpuLog(ttp.timestamp, decoder.gpu_log());
-      return ModuleResult::Handled();
-    }
-
-    if (decoder.has_graphics_frame_event()) {
-      parser_.ParseGraphicsFrameEvent(ttp.timestamp,
-                                      decoder.graphics_frame_event());
-      return ModuleResult::Handled();
-    }
-
-    if (decoder.has_vulkan_memory_event()) {
-      parser_.ParseVulkanMemoryEvent(ttp.packet_sequence_state,
-                                     ttp.packet_sequence_state_generation,
-                                     decoder.vulkan_memory_event());
-      return ModuleResult::Handled();
-    }
-
-    return ModuleResult::Ignored();
-  }
-
- private:
-  GraphicsEventParser parser_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_GRAPHICS_EVENT_MODULE_H_
diff --git a/src/trace_processor/importers/proto/graphics_event_parser.cc b/src/trace_processor/importers/proto/graphics_event_parser.cc
deleted file mode 100644
index 9b08198..0000000
--- a/src/trace_processor/importers/proto/graphics_event_parser.cc
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/importers/proto/graphics_event_parser.h"
-
-#include "perfetto/protozero/field.h"
-#include "src/trace_processor/args_tracker.h"
-#include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/slice_tracker.h"
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/track_tracker.h"
-#include "src/trace_processor/vulkan_memory_tracker.h"
-
-#include "protos/perfetto/common/gpu_counter_descriptor.pbzero.h"
-#include "protos/perfetto/trace/android/graphics_frame_event.pbzero.h"
-#include "protos/perfetto/trace/gpu/gpu_counter_event.pbzero.h"
-#include "protos/perfetto/trace/gpu/gpu_log.pbzero.h"
-#include "protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h"
-#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-GraphicsEventParser::GraphicsEventParser(TraceProcessorContext* context)
-    : context_(context),
-      gpu_render_stage_scope_id_(
-          context->storage->InternString("gpu_render_stage")),
-      graphics_event_scope_id_(
-          context->storage->InternString("graphics_frame_event")),
-      unknown_event_name_id_(context->storage->InternString("unknown_event")),
-      no_layer_name_name_id_(context->storage->InternString("no_layer_name")),
-      layer_name_key_id_(context->storage->InternString("layer_name")),
-      event_type_name_ids_{
-          {context->storage->InternString(
-               "unspecified_event") /* UNSPECIFIED */,
-           context->storage->InternString("Dequeue") /* DEQUEUE */,
-           context->storage->InternString("Queue") /* QUEUE */,
-           context->storage->InternString("Post") /* POST */,
-           context->storage->InternString(
-               "AcquireFenceSignaled") /* ACQUIRE_FENCE */,
-           context->storage->InternString("Latch") /* LATCH */,
-           context->storage->InternString(
-               "HWCCompositionQueued") /* HWC_COMPOSITION_QUEUED */,
-           context->storage->InternString(
-               "FallbackComposition") /* FALLBACK_COMPOSITION */,
-           context->storage->InternString(
-               "PresentFenceSignaled") /* PRESENT_FENCE */,
-           context->storage->InternString(
-               "ReleaseFenceSignaled") /* RELEASE_FENCE */,
-           context->storage->InternString("Modify") /* MODIFY */,
-           context->storage->InternString("Detach") /* DETACH */,
-           context->storage->InternString("Attach") /* ATTACH */,
-           context->storage->InternString("Cancel") /* CANCEL */}},
-      vulkan_allocated_host_memory_id_(
-          context->storage->InternString("vulkan.host.memory")),
-      vulkan_allocated_gpu_memory_id_(
-          context->storage->InternString("vulkan.gpu.memory")),
-      vulkan_live_image_objects_id_(
-          context->storage->InternString("vulkan.gpu.images")),
-      vulkan_live_buffer_objects_id_(
-          context->storage->InternString("vulkan.gpu.buffers")),
-      vulkan_bound_image_objects_id_(
-          context->storage->InternString("vulkan.gpu.bound_images")),
-      vulkan_bound_buffer_objects_id_(
-          context->storage->InternString("vulkan.gpu.bound_buffers")),
-      vulkan_allocated_host_memory_(0),
-      vulkan_allocated_gpu_memory_(0),
-      vulkan_live_image_objects_(0),
-      vulkan_live_buffer_objects_(0),
-      vulkan_bound_image_objects_(0),
-      vulkan_bound_buffer_objects_(0),
-      gpu_log_track_name_id_(context_->storage->InternString("GPU Log")),
-      gpu_log_scope_id_(context_->storage->InternString("gpu_log")),
-      tag_id_(context_->storage->InternString("tag")),
-      log_message_id_(context->storage->InternString("message")),
-      log_severity_ids_{{context_->storage->InternString("UNSPECIFIED"),
-                         context_->storage->InternString("VERBOSE"),
-                         context_->storage->InternString("DEBUG"),
-                         context_->storage->InternString("INFO"),
-                         context_->storage->InternString("WARNING"),
-                         context_->storage->InternString("ERROR"),
-                         context_->storage->InternString(
-                             "UNKNOWN_SEVERITY") /* must be last */}} {}
-
-void GraphicsEventParser::ParseGpuCounterEvent(int64_t ts, ConstBytes blob) {
-  protos::pbzero::GpuCounterEvent::Decoder event(blob.data, blob.size);
-
-  protos::pbzero::GpuCounterDescriptor::Decoder descriptor(
-      event.counter_descriptor());
-  // Add counter spec to ID map.
-  for (auto it = descriptor.specs(); it; ++it) {
-    protos::pbzero::GpuCounterDescriptor_GpuCounterSpec::Decoder spec(*it);
-    if (!spec.has_counter_id()) {
-      PERFETTO_ELOG("Counter spec missing counter id");
-      context_->storage->IncrementStats(stats::gpu_counters_invalid_spec);
-      continue;
-    }
-    if (!spec.has_name()) {
-      context_->storage->IncrementStats(stats::gpu_counters_invalid_spec);
-      continue;
-    }
-
-    auto counter_id = spec.counter_id();
-    auto name = spec.name();
-    if (gpu_counter_track_ids_.find(counter_id) ==
-        gpu_counter_track_ids_.end()) {
-      auto desc = spec.description();
-
-      StringId unit_id = 0;
-      if (spec.has_numerator_units() || spec.has_denominator_units()) {
-        char buffer[1024];
-        base::StringWriter unit(buffer, sizeof(buffer));
-        for (auto numer = spec.numerator_units(); numer; ++numer) {
-          if (unit.pos()) {
-            unit.AppendChar(':');
-          }
-          unit.AppendInt(*numer);
-        }
-        char sep = '/';
-        for (auto denom = spec.denominator_units(); denom; ++denom) {
-          unit.AppendChar(sep);
-          unit.AppendInt(*denom);
-          sep = ':';
-        }
-        unit_id = context_->storage->InternString(unit.GetStringView());
-      }
-
-      auto name_id = context_->storage->InternString(name);
-      auto desc_id = context_->storage->InternString(desc);
-      auto track_id = context_->track_tracker->CreateGpuCounterTrack(
-          name_id, 0 /* gpu_id */, desc_id, unit_id);
-      gpu_counter_track_ids_.emplace(counter_id, track_id);
-    } else {
-      // Either counter spec was repeated or it came after counter data.
-      PERFETTO_ELOG("Duplicated counter spec found. (counter_id=%d, name=%s)",
-                    counter_id, name.ToStdString().c_str());
-      context_->storage->IncrementStats(stats::gpu_counters_invalid_spec);
-    }
-  }
-
-  for (auto it = event.counters(); it; ++it) {
-    protos::pbzero::GpuCounterEvent_GpuCounter::Decoder counter(*it);
-    if (counter.has_counter_id() &&
-        (counter.has_int_value() || counter.has_double_value())) {
-      auto counter_id = counter.counter_id();
-      // Check missing counter_id
-      if (gpu_counter_track_ids_.find(counter_id) ==
-          gpu_counter_track_ids_.end()) {
-        char buffer[64];
-        base::StringWriter writer(buffer, sizeof(buffer));
-        writer.AppendString("gpu_counter(");
-        writer.AppendUnsignedInt(counter_id);
-        writer.AppendString(")");
-        auto name_id = context_->storage->InternString(writer.GetStringView());
-
-        TrackId track = context_->track_tracker->CreateGpuCounterTrack(
-            name_id, 0 /* gpu_id */);
-        gpu_counter_track_ids_.emplace(counter_id, track);
-        context_->storage->IncrementStats(stats::gpu_counters_missing_spec);
-      }
-      if (counter.has_int_value()) {
-        context_->event_tracker->PushCounter(
-            ts, counter.int_value(), gpu_counter_track_ids_[counter_id]);
-      } else {
-        context_->event_tracker->PushCounter(
-            ts, counter.double_value(), gpu_counter_track_ids_[counter_id]);
-      }
-    }
-  }
-}
-
-void GraphicsEventParser::ParseGpuRenderStageEvent(int64_t ts,
-                                                   ConstBytes blob) {
-  protos::pbzero::GpuRenderStageEvent::Decoder event(blob.data, blob.size);
-
-  if (event.has_specifications()) {
-    protos::pbzero::GpuRenderStageEvent_Specifications::Decoder spec(
-        event.specifications().data, event.specifications().size);
-    for (auto it = spec.hw_queue(); it; ++it) {
-      protos::pbzero::GpuRenderStageEvent_Specifications_Description::Decoder
-          hw_queue(*it);
-      if (hw_queue.has_name()) {
-        StringId track_name = context_->storage->InternString(hw_queue.name());
-        tables::GpuTrackTable::Row track(track_name.id);
-        track.scope = gpu_render_stage_scope_id_;
-        gpu_hw_queue_ids_.emplace_back(
-            context_->track_tracker->InternGpuTrack(track));
-      }
-    }
-    for (auto it = spec.stage(); it; ++it) {
-      protos::pbzero::GpuRenderStageEvent_Specifications_Description::Decoder
-          stage(*it);
-      if (stage.has_name()) {
-        gpu_render_stage_ids_.emplace_back(
-            context_->storage->InternString(stage.name()));
-      }
-    }
-  }
-
-  auto args_callback = [this, &event](ArgsTracker* args_tracker, RowId row_id) {
-    for (auto it = event.extra_data(); it; ++it) {
-      protos::pbzero::GpuRenderStageEvent_ExtraData_Decoder datum(*it);
-      StringId name_id = context_->storage->InternString(datum.name());
-      StringId value = context_->storage->InternString(
-          datum.has_value() ? datum.value() : base::StringView());
-      args_tracker->AddArg(row_id, name_id, name_id, Variadic::String(value));
-    }
-  };
-
-  if (event.has_event_id()) {
-    size_t stage_id = static_cast<size_t>(event.stage_id());
-    StringId stage_name;
-    if (stage_id < gpu_render_stage_ids_.size()) {
-      stage_name = gpu_render_stage_ids_[stage_id];
-    } else {
-      char buffer[64];
-      snprintf(buffer, 64, "render stage(%zu)", stage_id);
-      stage_name = context_->storage->InternString(buffer);
-    }
-    TrackId track_id =
-        gpu_hw_queue_ids_[static_cast<size_t>(event.hw_queue_id())];
-    const auto slice_id = context_->slice_tracker->Scoped(
-        ts, track_id, track_id, RefType::kRefTrack, 0 /* cat */, stage_name,
-        static_cast<int64_t>(event.duration()), args_callback);
-
-    context_->storage->mutable_gpu_slice_table()->Insert(
-        tables::GpuSliceTable::Row(
-            slice_id.value(), static_cast<int64_t>(event.context()),
-            static_cast<int64_t>(event.render_target_handle()),
-            base::nullopt /*frame_id*/, event.submission_id(),
-            static_cast<uint32_t>(event.hw_queue_id())));
-  }
-}
-
-void GraphicsEventParser::ParseGraphicsFrameEvent(int64_t timestamp,
-                                                  ConstBytes blob) {
-  protos::pbzero::GraphicsFrameEvent_Decoder frame_event(blob.data, blob.size);
-  if (!frame_event.has_buffer_event()) {
-    return;
-  }
-
-  ConstBytes bufferBlob = frame_event.buffer_event();
-  protos::pbzero::GraphicsFrameEvent_BufferEvent_Decoder event(bufferBlob.data,
-                                                               bufferBlob.size);
-
-  if (!event.has_buffer_id()) {
-    context_->storage->IncrementStats(
-        stats::graphics_frame_event_parser_errors);
-    PERFETTO_ELOG("GraphicsFrameEvent with missing buffer id field.");
-    return;
-  }
-
-  StringId event_name_id = unknown_event_name_id_;
-  if (event.has_type()) {
-    const auto type = static_cast<size_t>(event.type());
-    if (type < event_type_name_ids_.size()) {
-      event_name_id = event_type_name_ids_[type];
-    } else {
-      context_->storage->IncrementStats(
-          stats::graphics_frame_event_parser_errors);
-      PERFETTO_ELOG("GraphicsFrameEvent with unknown type %zu.", type);
-    }
-  } else {
-    context_->storage->IncrementStats(
-        stats::graphics_frame_event_parser_errors);
-    PERFETTO_ELOG("GraphicsFrameEvent with missing type field.");
-  }
-
-  const uint32_t buffer_id = event.buffer_id();
-  StringId layer_name_id;
-
-  char buffer[4096];
-  const size_t layerNameMaxLength = 4000;
-  base::StringWriter track_name(buffer, sizeof(buffer));
-  if (event.has_layer_name()) {
-    const base::StringView layer_name(event.layer_name());
-    layer_name_id = context_->storage->InternString(layer_name);
-    track_name.AppendString(layer_name.substr(0, layerNameMaxLength));
-  } else {
-    layer_name_id = no_layer_name_name_id_;
-    track_name.AppendLiteral("unknown_layer");
-  }
-  track_name.AppendLiteral("[buffer:");
-  track_name.AppendUnsignedInt(buffer_id);
-  track_name.AppendChar(']');
-
-  const StringId track_name_id =
-      context_->storage->InternString(track_name.GetStringView());
-  const int64_t duration =
-      event.has_duration_ns() ? static_cast<int64_t>(event.duration_ns()) : 0;
-  const uint32_t frame_number =
-      event.has_frame_number() ? event.frame_number() : 0;
-
-  tables::GpuTrackTable::Row track(track_name_id.id);
-  track.scope = graphics_event_scope_id_;
-  TrackId track_id = context_->track_tracker->InternGpuTrack(track);
-
-  const auto slice_id = context_->slice_tracker->Scoped(
-      timestamp, track_id, track_id, RefType::kRefTrack, 0 /* cat */,
-      event_name_id, duration,
-      [this, layer_name_id](ArgsTracker* args_tracker, RowId row_id) {
-        args_tracker->AddArg(row_id, layer_name_key_id_, layer_name_key_id_,
-                             Variadic::String(layer_name_id));
-      });
-
-  if (slice_id) {
-    tables::GpuSliceTable::Row row;
-    row.slice_id = slice_id.value();
-    row.frame_id = frame_number;
-    context_->storage->mutable_gpu_slice_table()->Insert(row);
-  }
-}
-
-void GraphicsEventParser::UpdateVulkanMemoryAllocationCounters(int64_t ts,
-                                                               UniquePid upid,
-                                                               VulkanMemoryEventSource source,
-                                                               VulkanMemoryEventType type,
-                                                               size_t allocation_size) {
-  using protos::pbzero::VulkanMemoryEvent;
-
-  if (source == VulkanMemoryEvent::HOST) {
-    if (type == VulkanMemoryEvent::CREATE) {
-      vulkan_allocated_host_memory_ += allocation_size;
-    } else if (type == VulkanMemoryEvent::DESTROY) {
-      vulkan_allocated_host_memory_ -= allocation_size;
-    }
-    TrackId track = context_->track_tracker->InternProcessCounterTrack(
-        vulkan_allocated_host_memory_id_, upid);
-    context_->event_tracker->PushCounter(ts, vulkan_allocated_host_memory_,
-                                         track);
-  } else if (source == VulkanMemoryEvent::GPU_DEVICE_MEMORY) {
-    if (type == VulkanMemoryEvent::CREATE) {
-      vulkan_allocated_gpu_memory_ += allocation_size;
-    } else if (type == VulkanMemoryEvent::DESTROY) {
-      vulkan_allocated_gpu_memory_ -= allocation_size;
-    }
-    TrackId track = context_->track_tracker->InternProcessCounterTrack(
-        vulkan_allocated_gpu_memory_id_, upid);
-    context_->event_tracker->PushCounter(ts, vulkan_allocated_gpu_memory_,
-                                         track);
-  } else if (source == VulkanMemoryEvent::GPU_BUFFER) {
-    if (type == VulkanMemoryEvent::CREATE) {
-      vulkan_live_buffer_objects_ += 1;
-      TrackId track = context_->track_tracker->InternProcessCounterTrack(
-          vulkan_live_buffer_objects_id_, upid);
-      context_->event_tracker->PushCounter(ts, vulkan_live_buffer_objects_,
-                                           track);
-    } else if (type == VulkanMemoryEvent::DESTROY) {
-      vulkan_live_buffer_objects_ -= 1;
-      TrackId track = context_->track_tracker->InternProcessCounterTrack(
-          vulkan_live_buffer_objects_id_, upid);
-      context_->event_tracker->PushCounter(ts, vulkan_live_buffer_objects_,
-                                           track);
-    } else if (type == VulkanMemoryEvent::BIND) {
-      vulkan_bound_buffer_objects_ += 1;
-      TrackId track = context_->track_tracker->InternProcessCounterTrack(
-          vulkan_bound_buffer_objects_id_, upid);
-      context_->event_tracker->PushCounter(ts, vulkan_bound_buffer_objects_,
-                                           track);
-    } else if (type == VulkanMemoryEvent::DESTROY_BOUND) {
-      vulkan_bound_buffer_objects_ -= 1;
-      TrackId track = context_->track_tracker->InternProcessCounterTrack(
-          vulkan_bound_buffer_objects_id_, upid);
-      context_->event_tracker->PushCounter(ts, vulkan_bound_buffer_objects_,
-                                           track);
-    }
-  } else if (source == VulkanMemoryEvent::GPU_IMAGE) {
-    if (type == VulkanMemoryEvent::CREATE) {
-      vulkan_live_image_objects_ += 1;
-      TrackId track = context_->track_tracker->InternProcessCounterTrack(
-          vulkan_live_image_objects_id_, upid);
-      context_->event_tracker->PushCounter(ts, vulkan_live_image_objects_,
-                                           track);
-    } else if (type == VulkanMemoryEvent::DESTROY) {
-      vulkan_live_image_objects_ -= 1;
-      TrackId track = context_->track_tracker->InternProcessCounterTrack(
-          vulkan_live_image_objects_id_, upid);
-      context_->event_tracker->PushCounter(ts, vulkan_live_image_objects_,
-                                           track);
-    } else if (type == VulkanMemoryEvent::BIND) {
-      vulkan_bound_image_objects_ += 1;
-      TrackId track = context_->track_tracker->InternProcessCounterTrack(
-          vulkan_bound_image_objects_id_, upid);
-      context_->event_tracker->PushCounter(ts, vulkan_bound_image_objects_,
-                                           track);
-    } else if (type == VulkanMemoryEvent::DESTROY_BOUND) {
-      vulkan_bound_image_objects_ -= 1;
-      TrackId track = context_->track_tracker->InternProcessCounterTrack(
-          vulkan_bound_image_objects_id_, upid);
-      context_->event_tracker->PushCounter(ts, vulkan_bound_image_objects_,
-                                           track);
-    }
-  }
-}
-
-void GraphicsEventParser::ParseVulkanMemoryEvent(
-    PacketSequenceState* sequence_state,
-    size_t sequence_state_generation,
-    ConstBytes blob) {
-  protos::pbzero::VulkanMemoryEvent::Decoder vulkan_memory_event(blob.data,
-                                                                 blob.size);
-  tables::VulkanMemoryAllocationsTable::Row vulkan_memory_event_row;
-  vulkan_memory_event_row.source =
-      context_->vulkan_memory_tracker->FindSourceString(
-          static_cast<uint64_t>(vulkan_memory_event.source()));
-  vulkan_memory_event_row.operation =
-      context_->vulkan_memory_tracker->FindTypeString(
-          static_cast<uint64_t>(vulkan_memory_event.type()));
-  vulkan_memory_event_row.timestamp = vulkan_memory_event.timestamp();
-  vulkan_memory_event_row.upid =
-      context_->process_tracker->GetOrCreateProcess(vulkan_memory_event.pid());
-
-  if (vulkan_memory_event.has_device())
-    vulkan_memory_event_row.device =
-        static_cast<int64_t>(vulkan_memory_event.device());
-  if (vulkan_memory_event.has_device_memory())
-    vulkan_memory_event_row.device_memory =
-        static_cast<int64_t>(vulkan_memory_event.device_memory());
-  if (vulkan_memory_event.has_heap())
-    vulkan_memory_event_row.heap = vulkan_memory_event.heap();
-  if (vulkan_memory_event.has_caller_iid()) {
-    vulkan_memory_event_row.function_name =
-        context_->vulkan_memory_tracker->GetInternedString<
-            protos::pbzero::InternedData::kFunctionNamesFieldNumber>(
-            sequence_state, sequence_state_generation,
-            static_cast<uint64_t>(vulkan_memory_event.caller_iid()));
-  }
-  if (vulkan_memory_event.has_object_handle())
-    vulkan_memory_event_row.object_handle =
-        static_cast<int64_t>(vulkan_memory_event.object_handle());
-  if (vulkan_memory_event.has_memory_address())
-    vulkan_memory_event_row.memory_address =
-        static_cast<int64_t>(vulkan_memory_event.memory_address());
-  if (vulkan_memory_event.has_memory_size())
-    vulkan_memory_event_row.memory_size =
-        static_cast<int64_t>(vulkan_memory_event.memory_size());
-
-  using Source = protos::pbzero::VulkanMemoryEvent::Source;
-  using Type = protos::pbzero::VulkanMemoryEvent::Type;
-  UpdateVulkanMemoryAllocationCounters(
-      vulkan_memory_event.timestamp(), vulkan_memory_event_row.upid.value(),
-      static_cast<Source>(vulkan_memory_event.source()),
-      static_cast<Type>(vulkan_memory_event.type()),
-      static_cast<uint32_t>(vulkan_memory_event.memory_size()));
-
-  auto row_id =
-      context_->storage->mutable_vulkan_memory_allocations_table()->Insert(
-          vulkan_memory_event_row);
-
-  if (vulkan_memory_event.has_annotations()) {
-    auto global_row_id =
-        TraceStorage::CreateRowId(TableId::kVulkanMemoryAllocation, row_id);
-
-    for (auto it = vulkan_memory_event.annotations(); it; ++it) {
-      protos::pbzero::VulkanMemoryEventAnnotation::Decoder annotation(*it);
-
-      auto key_id = context_->vulkan_memory_tracker->GetInternedString<
-          protos::pbzero::InternedData::kVulkanMemoryKeysFieldNumber>(
-          sequence_state, sequence_state_generation,
-          static_cast<uint64_t>(annotation.key_iid()));
-
-      if (annotation.has_int_value()) {
-        context_->args_tracker->AddArg(
-            global_row_id, key_id, key_id,
-            Variadic::Integer(annotation.int_value()));
-      } else if (annotation.has_double_value()) {
-        context_->args_tracker->AddArg(
-            global_row_id, key_id, key_id,
-            Variadic::Real(annotation.double_value()));
-
-      } else if (annotation.has_string_iid()) {
-        auto string_id = context_->vulkan_memory_tracker->GetInternedString<
-            protos::pbzero::InternedData::kVulkanMemoryKeysFieldNumber>(
-            sequence_state, sequence_state_generation,
-            static_cast<uint64_t>(annotation.string_iid()));
-
-        context_->args_tracker->AddArg(global_row_id, key_id, key_id,
-                                       Variadic::String(string_id.id));
-      }
-    }
-  }
-}
-
-void GraphicsEventParser::ParseGpuLog(int64_t ts, ConstBytes blob) {
-  protos::pbzero::GpuLog::Decoder event(blob.data, blob.size);
-
-  tables::GpuTrackTable::Row track(gpu_log_track_name_id_.id);
-  track.scope = gpu_log_scope_id_;
-  TrackId track_id = context_->track_tracker->InternGpuTrack(track);
-
-  auto args_callback = [this, &event](ArgsTracker* args_tracker, RowId row_id) {
-    if (event.has_tag()) {
-      args_tracker->AddArg(
-          row_id, tag_id_, tag_id_,
-          Variadic::String(context_->storage->InternString(event.tag())));
-    }
-    if (event.has_log_message()) {
-      args_tracker->AddArg(row_id, log_message_id_, log_message_id_,
-                           Variadic::String(context_->storage->InternString(
-                               event.log_message())));
-    }
-  };
-
-  auto severity = static_cast<size_t>(event.severity());
-  StringId severity_id =
-      severity < log_severity_ids_.size()
-          ? log_severity_ids_[static_cast<size_t>(event.severity())]
-          : log_severity_ids_[log_severity_ids_.size() - 1];
-  const auto slice_id = context_->slice_tracker->Scoped(
-      ts, track_id, track_id, RefType::kRefTrack, 0 /* cat */, severity_id,
-      0 /* duration */, args_callback);
-
-  tables::GpuSliceTable::Row row;
-  row.slice_id = slice_id.value();
-  context_->storage->mutable_gpu_slice_table()->Insert(row);
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/graphics_event_parser.h b/src/trace_processor/importers/proto/graphics_event_parser.h
deleted file mode 100644
index 35a9c2f..0000000
--- a/src/trace_processor/importers/proto/graphics_event_parser.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_GRAPHICS_EVENT_PARSER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_GRAPHICS_EVENT_PARSER_H_
-
-#include <vector>
-
-#include "perfetto/protozero/field.h"
-#include "src/trace_processor/importers/proto/proto_incremental_state.h"
-#include "src/trace_processor/trace_storage.h"
-
-#include "protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-// Class for parsing graphics related events.
-class GraphicsEventParser {
- public:
-  using ConstBytes = protozero::ConstBytes;
-  using VulkanMemoryEventSource = protos::pbzero::VulkanMemoryEvent::Source;
-  using VulkanMemoryEventType = protos::pbzero::VulkanMemoryEvent::Type;
-  explicit GraphicsEventParser(TraceProcessorContext*);
-
-  void ParseGpuCounterEvent(int64_t ts, ConstBytes);
-  void ParseGpuRenderStageEvent(int64_t ts, ConstBytes);
-  void ParseGraphicsFrameEvent(int64_t timestamp, ConstBytes);
-  void ParseGpuLog(int64_t ts, ConstBytes);
-
-  void ParseVulkanMemoryEvent(PacketSequenceState*,
-                              size_t sequence_state_generation,
-                              ConstBytes);
-  void UpdateVulkanMemoryAllocationCounters(int64_t ts,
-                                            UniquePid,
-                                            VulkanMemoryEventSource,
-                                            VulkanMemoryEventType,
-                                            size_t allocation_size);
-
- private:
-  TraceProcessorContext* const context_;
-  // For GpuCounterEvent
-  std::unordered_map<uint32_t, TrackId> gpu_counter_track_ids_;
-  // For GpuRenderStageEvent
-  const StringId gpu_render_stage_scope_id_;
-  std::vector<TrackId> gpu_hw_queue_ids_;
-  std::vector<StringId> gpu_render_stage_ids_;
-  // For GraphicsFrameEvent
-  const StringId graphics_event_scope_id_;
-  const StringId unknown_event_name_id_;
-  const StringId no_layer_name_name_id_;
-  const StringId layer_name_key_id_;
-  std::array<StringId, 14> event_type_name_ids_;
-  // For VulkanMemoryEvent
-  const StringId vulkan_allocated_host_memory_id_;
-  const StringId vulkan_allocated_gpu_memory_id_;
-  const StringId vulkan_live_image_objects_id_;
-  const StringId vulkan_live_buffer_objects_id_;
-  const StringId vulkan_bound_image_objects_id_;
-  const StringId vulkan_bound_buffer_objects_id_;
-  int64_t vulkan_allocated_host_memory_;
-  int64_t vulkan_allocated_gpu_memory_;
-  int64_t vulkan_live_image_objects_;
-  int64_t vulkan_live_buffer_objects_;
-  int64_t vulkan_bound_image_objects_;
-  int64_t vulkan_bound_buffer_objects_;
-  // For GpuLog
-  const StringId gpu_log_track_name_id_;
-  const StringId gpu_log_scope_id_;
-  const StringId tag_id_;
-  const StringId log_message_id_;
-  std::array<StringId, 7> log_severity_ids_;
-};
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_GRAPHICS_EVENT_PARSER_H_
diff --git a/src/trace_processor/importers/proto/heap_graph_module.cc b/src/trace_processor/importers/proto/heap_graph_module.cc
deleted file mode 100644
index 50bba45..0000000
--- a/src/trace_processor/importers/proto/heap_graph_module.cc
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/importers/proto/heap_graph_module.h"
-
-#include "src/trace_processor/importers/proto/heap_graph_tracker.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/trace_storage.h"
-
-#include "protos/perfetto/trace/profiling/heap_graph.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-
-const char* HeapGraphRootTypeToString(int32_t type) {
-  switch (type) {
-    case protos::pbzero::HeapGraphRoot::ROOT_UNKNOWN:
-      return "ROOT_UNKNOWN";
-    case protos::pbzero::HeapGraphRoot::ROOT_JNI_GLOBAL:
-      return "ROOT_JNI_GLOBAL";
-    case protos::pbzero::HeapGraphRoot::ROOT_JNI_LOCAL:
-      return "ROOT_JNI_LOCAL";
-    case protos::pbzero::HeapGraphRoot::ROOT_JAVA_FRAME:
-      return "ROOT_JAVA_FRAME";
-    case protos::pbzero::HeapGraphRoot::ROOT_NATIVE_STACK:
-      return "ROOT_NATIVE_STACK";
-    case protos::pbzero::HeapGraphRoot::ROOT_STICKY_CLASS:
-      return "ROOT_STICKY_CLASS";
-    case protos::pbzero::HeapGraphRoot::ROOT_THREAD_BLOCK:
-      return "ROOT_THREAD_BLOCK";
-    case protos::pbzero::HeapGraphRoot::ROOT_MONITOR_USED:
-      return "ROOT_MONITOR_USED";
-    case protos::pbzero::HeapGraphRoot::ROOT_THREAD_OBJECT:
-      return "ROOT_THREAD_OBJECT";
-    case protos::pbzero::HeapGraphRoot::ROOT_INTERNED_STRING:
-      return "ROOT_INTERNED_STRING";
-    case protos::pbzero::HeapGraphRoot::ROOT_FINALIZING:
-      return "ROOT_FINALIZING";
-    case protos::pbzero::HeapGraphRoot::ROOT_DEBUGGER:
-      return "ROOT_DEBUGGER";
-    case protos::pbzero::HeapGraphRoot::ROOT_REFERENCE_CLEANUP:
-      return "ROOT_REFERENCE_CLEANUP";
-    case protos::pbzero::HeapGraphRoot::ROOT_VM_INTERNAL:
-      return "ROOT_VM_INTERNAL";
-    case protos::pbzero::HeapGraphRoot::ROOT_JNI_MONITOR:
-      return "ROOT_JNI_MONITOR";
-    default:
-      return "ROOT_UNKNOWN";
-  }
-}
-
-}  // namespace
-
-void HeapGraphModule::ParseHeapGraph(int64_t ts, protozero::ConstBytes blob) {
-  protos::pbzero::HeapGraph::Decoder heap_graph(blob.data, blob.size);
-  UniquePid upid = context_->process_tracker->GetOrCreateProcess(
-      static_cast<uint32_t>(heap_graph.pid()));
-  context_->heap_graph_tracker->SetPacketIndex(heap_graph.index());
-  for (auto it = heap_graph.objects(); it; ++it) {
-    protos::pbzero::HeapGraphObject::Decoder object(*it);
-    HeapGraphTracker::SourceObject obj;
-    obj.object_id = object.id();
-    obj.self_size = object.self_size();
-    obj.type_id = object.type_id();
-    auto ref_field_ids_it = object.reference_field_id();
-    auto ref_object_ids_it = object.reference_object_id();
-    for (; ref_field_ids_it && ref_object_ids_it;
-         ++ref_field_ids_it, ++ref_object_ids_it) {
-      HeapGraphTracker::SourceObject::Reference ref;
-      ref.field_name_id = *ref_field_ids_it;
-      ref.owned_object_id = *ref_object_ids_it;
-      obj.references.emplace_back(std::move(ref));
-    }
-
-    if (ref_field_ids_it || ref_object_ids_it) {
-      context_->storage->IncrementIndexedStats(stats::heap_graph_missing_packet,
-                                               static_cast<int>(upid));
-      continue;
-    }
-    context_->heap_graph_tracker->AddObject(upid, ts, std::move(obj));
-  }
-  for (auto it = heap_graph.type_names(); it; ++it) {
-    protos::pbzero::InternedString::Decoder entry(*it);
-    const char* str = reinterpret_cast<const char*>(entry.str().data);
-    auto str_view = base::StringView(str, entry.str().size);
-
-    context_->heap_graph_tracker->AddInternedTypeName(
-        entry.iid(), context_->storage->InternString(str_view));
-  }
-  for (auto it = heap_graph.field_names(); it; ++it) {
-    protos::pbzero::InternedString::Decoder entry(*it);
-    const char* str = reinterpret_cast<const char*>(entry.str().data);
-    auto str_view = base::StringView(str, entry.str().size);
-
-    context_->heap_graph_tracker->AddInternedFieldName(
-        entry.iid(), context_->storage->InternString(str_view));
-  }
-  for (auto it = heap_graph.roots(); it; ++it) {
-    protos::pbzero::HeapGraphRoot::Decoder entry(*it);
-    const char* str = HeapGraphRootTypeToString(entry.root_type());
-    auto str_view = base::StringView(str);
-
-    HeapGraphTracker::SourceRoot src_root;
-    src_root.root_type = context_->storage->InternString(str_view);
-    for (auto obj_it = entry.object_ids(); obj_it; ++obj_it)
-      src_root.object_ids.emplace_back(*obj_it);
-    context_->heap_graph_tracker->AddRoot(upid, ts, std::move(src_root));
-  }
-  if (!heap_graph.continued()) {
-    context_->heap_graph_tracker->FinalizeProfile();
-  }
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/heap_graph_module.h b/src/trace_processor/importers/proto/heap_graph_module.h
deleted file mode 100644
index 1d80b13..0000000
--- a/src/trace_processor/importers/proto/heap_graph_module.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_MODULE_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_MODULE_H_
-
-#include "perfetto/base/build_config.h"
-#include "src/trace_processor/importers/proto/heap_graph_tracker.h"
-#include "src/trace_processor/importers/proto/proto_importer_module.h"
-#include "src/trace_processor/timestamped_trace_piece.h"
-
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class HeapGraphModule : public ProtoImporterModuleBase<PERFETTO_BUILDFLAG(
-                            PERFETTO_TP_HEAP_GRAPHS)> {
- public:
-  explicit HeapGraphModule(TraceProcessorContext* context)
-      : ProtoImporterModuleBase(context) {
-    context_->heap_graph_tracker.reset(new HeapGraphTracker(context_));
-  }
-
-  ModuleResult ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
-                           const TimestampedTracePiece& ttp) {
-    if (decoder.has_heap_graph()) {
-      ParseHeapGraph(ttp.timestamp, decoder.heap_graph());
-      return ModuleResult::Handled();
-    }
-
-    return ModuleResult::Ignored();
-  }
-
- private:
-  void ParseHeapGraph(int64_t ts, protozero::ConstBytes);
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_MODULE_H_
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker.cc b/src/trace_processor/importers/proto/heap_graph_tracker.cc
deleted file mode 100644
index e2d6aef..0000000
--- a/src/trace_processor/importers/proto/heap_graph_tracker.cc
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/importers/proto/heap_graph_tracker.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-HeapGraphTracker::HeapGraphTracker(TraceProcessorContext* context)
-    : context_(context) {}
-
-bool HeapGraphTracker::SetPidAndTimestamp(UniquePid upid, int64_t ts) {
-  if (current_upid_ != 0 && current_upid_ != upid) {
-    context_->storage->IncrementStats(stats::heap_graph_non_finalized_graph);
-    return false;
-  }
-  if (current_ts_ != 0 && current_ts_ != ts) {
-    context_->storage->IncrementStats(stats::heap_graph_non_finalized_graph);
-    return false;
-  }
-  current_upid_ = upid;
-  current_ts_ = ts;
-  return true;
-}
-
-void HeapGraphTracker::AddObject(UniquePid upid, int64_t ts, SourceObject obj) {
-  if (!SetPidAndTimestamp(upid, ts))
-    return;
-
-  current_objects_.emplace_back(std::move(obj));
-}
-
-void HeapGraphTracker::AddRoot(UniquePid upid, int64_t ts, SourceRoot root) {
-  if (!SetPidAndTimestamp(upid, ts))
-    return;
-
-  current_roots_.emplace_back(std::move(root));
-}
-
-void HeapGraphTracker::AddInternedTypeName(uint64_t intern_id,
-                                           StringPool::Id strid) {
-  interned_type_names_.emplace(intern_id, strid);
-}
-
-void HeapGraphTracker::AddInternedFieldName(uint64_t intern_id,
-                                            StringPool::Id strid) {
-  interned_field_names_.emplace(intern_id, strid);
-}
-
-void HeapGraphTracker::SetPacketIndex(uint64_t index) {
-  if (prev_index_ != 0 && prev_index_ + 1 != index) {
-    PERFETTO_ELOG("Missing packets between %" PRIu64 " and %" PRIu64,
-                  prev_index_, index);
-    context_->storage->IncrementIndexedStats(stats::heap_graph_missing_packet,
-                                             static_cast<int>(current_upid_));
-  }
-  prev_index_ = index;
-}
-
-void HeapGraphTracker::FinalizeProfile() {
-  for (const SourceObject& obj : current_objects_) {
-    auto it = interned_type_names_.find(obj.type_id);
-    if (it == interned_type_names_.end()) {
-      context_->storage->IncrementIndexedStats(
-          stats::heap_graph_invalid_string_id, static_cast<int>(current_upid_));
-      continue;
-    }
-    context_->storage->mutable_heap_graph_object_table()->Insert(
-        {current_upid_, current_ts_, static_cast<int64_t>(obj.object_id),
-         static_cast<int64_t>(obj.self_size), -1, 0, -1, 0, it->second,
-         base::nullopt});
-    int64_t row = context_->storage->heap_graph_object_table().size() - 1;
-    object_id_to_row_.emplace(obj.object_id, row);
-    walker_.AddNode(row, obj.self_size);
-  }
-
-  for (const SourceObject& obj : current_objects_) {
-    auto it = object_id_to_row_.find(obj.object_id);
-    if (it == object_id_to_row_.end())
-      continue;
-    int64_t owner_row = it->second;
-
-    int64_t reference_set_id =
-        context_->storage->heap_graph_reference_table().size();
-    for (const SourceObject::Reference& ref : obj.references) {
-      // This is true for unset reference fields.
-      if (ref.owned_object_id == 0)
-        continue;
-
-      it = object_id_to_row_.find(ref.owned_object_id);
-      // This can only happen for an invalid type string id, which is already
-      // reported as an error. Silently continue here.
-      if (it == object_id_to_row_.end())
-        continue;
-
-      int64_t owned_row = it->second;
-      walker_.AddEdge(owner_row, owned_row);
-
-      auto field_name_it = interned_field_names_.find(ref.field_name_id);
-      if (field_name_it == interned_field_names_.end()) {
-        context_->storage->IncrementIndexedStats(
-            stats::heap_graph_invalid_string_id,
-            static_cast<int>(current_upid_));
-        continue;
-      }
-      StringPool::Id field_name = field_name_it->second;
-      context_->storage->mutable_heap_graph_reference_table()->Insert(
-          {reference_set_id, owner_row, owned_row, field_name});
-    }
-    context_->storage->mutable_heap_graph_object_table()
-        ->mutable_reference_set_id()
-        ->Set(static_cast<uint32_t>(owner_row), reference_set_id);
-  }
-
-  for (const SourceRoot& root : current_roots_) {
-    for (uint64_t obj_id : root.object_ids) {
-      auto it = object_id_to_row_.find(obj_id);
-      // This can only happen for an invalid type string id, which is already
-      // reported as an error. Silently continue here.
-      if (it == object_id_to_row_.end())
-        continue;
-
-      int64_t obj_row = it->second;
-      walker_.MarkRoot(obj_row);
-      context_->storage->mutable_heap_graph_object_table()
-          ->mutable_root_type()
-          ->Set(static_cast<uint32_t>(obj_row), root.root_type);
-    }
-  }
-
-  walker_.CalculateRetained();
-
-  auto context = context_;
-  this->~HeapGraphTracker();
-  new (this) HeapGraphTracker(context);
-}
-
-void HeapGraphTracker::MarkReachable(int64_t row) {
-  context_->storage->mutable_heap_graph_object_table()
-      ->mutable_reachable()
-      ->Set(static_cast<uint32_t>(row), 1);
-}
-
-void HeapGraphTracker::SetRetained(int64_t row,
-                                   int64_t retained,
-                                   int64_t unique_retained) {
-  context_->storage->mutable_heap_graph_object_table()
-      ->mutable_retained_size()
-      ->Set(static_cast<uint32_t>(row), retained);
-  context_->storage->mutable_heap_graph_object_table()
-      ->mutable_unique_retained_size()
-      ->Set(static_cast<uint32_t>(row), unique_retained);
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker.h b/src/trace_processor/importers/proto/heap_graph_tracker.h
deleted file mode 100644
index e022906..0000000
--- a/src/trace_processor/importers/proto/heap_graph_tracker.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_TRACKER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_TRACKER_H_
-
-#include <map>
-#include <vector>
-
-#include "perfetto/ext/base/optional.h"
-
-#include "protos/perfetto/trace/profiling/heap_graph.pbzero.h"
-#include "src/trace_processor/importers/proto/heap_graph_walker.h"
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-class HeapGraphTracker : public HeapGraphWalker::Delegate {
- public:
-  struct SourceObject {
-    // All ids in this are in the trace iid space, not in the trace processor
-    // id space.
-    struct Reference {
-      uint64_t field_name_id = 0;
-      uint64_t owned_object_id = 0;
-    };
-    uint64_t object_id = 0;
-    uint64_t self_size = 0;
-    uint64_t type_id = 0;
-    std::vector<Reference> references;
-  };
-
-  struct SourceRoot {
-    StringPool::Id root_type;
-    std::vector<uint64_t> object_ids;
-  };
-
-  explicit HeapGraphTracker(TraceProcessorContext* context);
-
-  void AddRoot(UniquePid upid, int64_t ts, SourceRoot root);
-  void AddObject(UniquePid upid, int64_t ts, SourceObject obj);
-  void AddInternedTypeName(uint64_t intern_id, StringPool::Id strid);
-  void AddInternedFieldName(uint64_t intern_id, StringPool::Id strid);
-  void FinalizeProfile();
-  void SetPacketIndex(uint64_t index);
-
-  ~HeapGraphTracker() override = default;
-  // HeapGraphTracker::Delegate
-  void MarkReachable(int64_t row) override;
-  void SetRetained(int64_t row,
-                   int64_t retained,
-                   int64_t unique_retained) override;
-
- private:
-  bool SetPidAndTimestamp(UniquePid upid, int64_t ts);
-  TraceProcessorContext* const context_;
-
-  UniquePid current_upid_ = 0;
-  int64_t current_ts_ = 0;
-  std::vector<SourceObject> current_objects_;
-  std::vector<SourceRoot> current_roots_;
-  std::map<uint64_t, StringPool::Id> interned_type_names_;
-  std::map<uint64_t, StringPool::Id> interned_field_names_;
-  std::map<uint64_t, int64_t> object_id_to_row_;
-  uint64_t prev_index_ = 0;
-
-  HeapGraphWalker walker_{this};
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_TRACKER_H_
diff --git a/src/trace_processor/importers/proto/heap_graph_walker.cc b/src/trace_processor/importers/proto/heap_graph_walker.cc
deleted file mode 100644
index 8655d85..0000000
--- a/src/trace_processor/importers/proto/heap_graph_walker.cc
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/importers/proto/heap_graph_walker.h"
-#include "perfetto/base/logging.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-void AddChild(std::map<int64_t, int64_t>* component_to_node,
-              uint64_t count,
-              int64_t child_component_id,
-              int64_t last_node_row) {
-  if (count > 1) {
-    // We have multiple edges from this component to the target component.
-    // This cannot possibly be uniquely retained by one node in this
-    // component.
-    (*component_to_node)[child_component_id] = -1;
-  } else {
-    // Check if the node that owns grand_component via child_component_id
-    // is the same as the node that owns it through all other
-    // child_component_ids.
-    auto it = component_to_node->find(child_component_id);
-    if (it == component_to_node->end())
-      (*component_to_node)[child_component_id] = last_node_row;
-    else if (it->second != last_node_row)
-      it->second = -1;
-  }
-}
-
-bool IsUniqueOwner(const std::map<int64_t, int64_t>& component_to_node,
-                   uint64_t count,
-                   int64_t child_component_id,
-                   int64_t last_node_row) {
-  if (count > 1)
-    return false;
-
-  auto it = component_to_node.find(child_component_id);
-  return it == component_to_node.end() || it->second == last_node_row;
-}
-
-}  // namespace
-
-HeapGraphWalker::Delegate::~Delegate() = default;
-
-void HeapGraphWalker::AddNode(int64_t row, uint64_t size) {
-  if (static_cast<size_t>(row) >= nodes_.size())
-    nodes_.resize(static_cast<size_t>(row) + 1);
-  Node& node = GetNode(row);
-  node.self_size = size;
-  node.row = row;
-}
-
-void HeapGraphWalker::AddEdge(int64_t owner_row, int64_t owned_row) {
-  GetNode(owner_row).children.emplace(&GetNode(owned_row));
-  GetNode(owned_row).parents.emplace(&GetNode(owner_row));
-}
-
-void HeapGraphWalker::MarkRoot(int64_t row) {
-  Node& n = GetNode(row);
-  n.root = true;
-  ReachableNode(&n);
-}
-
-void HeapGraphWalker::CalculateRetained() {
-  for (Node& n : nodes_) {
-    if (n.reachable && n.node_index == 0)
-      FindSCC(&n);
-  }
-
-  // Sanity check that we have processed all edges.
-  for (const auto& c : components_)
-    PERFETTO_CHECK(c.incoming_edges == 0);
-}
-
-void HeapGraphWalker::ReachableNode(Node* node) {
-  if (node->reachable)
-    return;
-  delegate_->MarkReachable(node->row);
-  node->reachable = true;
-  for (Node* child : node->children)
-    ReachableNode(child);
-}
-
-int64_t HeapGraphWalker::RetainedSize(const Component& component) {
-  int64_t retained_size =
-      static_cast<int64_t>(component.unique_retained_size) +
-      static_cast<int64_t>(component.unique_retained_root_size);
-  for (const int64_t child_component_id : component.children_components) {
-    const Component& child_component =
-        components_[static_cast<size_t>(child_component_id)];
-    retained_size += child_component.unique_retained_size;
-  }
-  return retained_size;
-}
-
-void HeapGraphWalker::FoundSCC(Node* node) {
-  // We have discovered a new connected component.
-  int64_t component_id = static_cast<int64_t>(components_.size());
-  components_.emplace_back();
-  Component& component = components_.back();
-  component.lowlink = node->lowlink;
-
-  std::vector<Node*> component_nodes;
-
-  // A struct representing all direct children from this component.
-  struct DirectChild {
-    // Number of edges from current component_id to this component.
-    size_t edges_from_current_component = 0;
-    // If edges_from_current_component == 1, this is the row of the node that
-    // has an outgoing edge to it.
-    int64_t last_node_row = 0;
-  };
-  std::map<int64_t, DirectChild> direct_children_rows;
-
-  Node* stack_elem;
-  do {
-    stack_elem = node_stack_.back();
-    component_nodes.emplace_back(stack_elem);
-    node_stack_.pop_back();
-    for (Node* child : stack_elem->children) {
-      if (!child->on_stack) {
-        // If the node is not on the stack, but is a child of a node on the
-        // stack, it must have already been explored (and assigned a
-        // component).
-        PERFETTO_CHECK(child->component != -1);
-        if (child->component != component_id) {
-          DirectChild& dc = direct_children_rows[child->component];
-          dc.edges_from_current_component++;
-          dc.last_node_row = stack_elem->row;
-        }
-      }
-      // If the node is on the stack, it must be part of this SCC and will be
-      // handled by the loop.
-      // This node being on the stack means there exist a path from it to the
-      // current node. If it also is a child of this node, there is a loop.
-    }
-    stack_elem->on_stack = false;
-    // A node can never be part of two components.
-    PERFETTO_CHECK(stack_elem->component == -1);
-    stack_elem->component = component_id;
-    if (stack_elem->root)
-      component.root = true;
-  } while (stack_elem != node);
-
-  for (Node* elem : component_nodes) {
-    component.unique_retained_size += elem->self_size;
-    for (Node* parent : elem->parents) {
-      // We do not count intra-component edges.
-      if (parent->reachable && parent->component != component_id)
-        component.incoming_edges++;
-    }
-    component.orig_incoming_edges = component.incoming_edges;
-    component.pending_nodes = component.orig_incoming_edges;
-  }
-
-  std::map<int64_t, int64_t> unique_retained_by_node;
-  // Map from child component to node in this component that uniquely owns it,
-  // or -1 if non-unique.
-  std::map<int64_t, int64_t> component_to_node;
-  for (const auto& p : direct_children_rows) {
-    int64_t child_component_id = p.first;
-    const DirectChild& dc = p.second;
-    size_t count = dc.edges_from_current_component;
-    PERFETTO_CHECK(child_component_id != component_id);
-
-    AddChild(&component_to_node, count, child_component_id, dc.last_node_row);
-
-    Component& child_component =
-        components_[static_cast<size_t>(child_component_id)];
-
-    for (int64_t grand_component_id : child_component.children_components) {
-      AddChild(&component_to_node, count, grand_component_id, dc.last_node_row);
-      Component& grand_component =
-          components_[static_cast<size_t>(grand_component_id)];
-      grand_component.pending_nodes -= count;
-      if (grand_component.pending_nodes == 0) {
-        component.unique_retained_root_size +=
-            grand_component.unique_retained_root_size;
-        if (grand_component.root) {
-          component.unique_retained_root_size +=
-              grand_component.unique_retained_size;
-        } else {
-          component.unique_retained_size +=
-              grand_component.unique_retained_size;
-
-          if (IsUniqueOwner(component_to_node, count, grand_component_id,
-                            dc.last_node_row)) {
-            unique_retained_by_node[dc.last_node_row] +=
-                grand_component.unique_retained_size;
-          }
-        }
-        grand_component.children_components.clear();
-        component.children_components.erase(grand_component_id);
-      } else {
-        component.children_components.emplace(grand_component_id);
-      }
-    }
-
-    child_component.incoming_edges -= count;
-    child_component.pending_nodes -= count;
-
-    if (child_component.pending_nodes == 0) {
-      PERFETTO_CHECK(child_component.incoming_edges == 0);
-
-      component.unique_retained_root_size +=
-          child_component.unique_retained_root_size;
-      if (child_component.root) {
-        component.unique_retained_root_size +=
-            child_component.unique_retained_size;
-      } else {
-        component.unique_retained_size += child_component.unique_retained_size;
-
-        if (IsUniqueOwner(component_to_node, count, child_component_id,
-                          dc.last_node_row)) {
-          unique_retained_by_node[dc.last_node_row] +=
-              child_component.unique_retained_size;
-        }
-      }
-      component.children_components.erase(child_component_id);
-    } else {
-      component.children_components.emplace(child_component_id);
-    }
-
-    if (child_component.incoming_edges == 0)
-      child_component.children_components.clear();
-  }
-
-  size_t parents = component.orig_incoming_edges;
-  // If this has no parents, but does not retain a node, we know that no other
-  // node can uniquely retain this node. Add 1 to poison that node.
-  // If this is a root, but it does not retain a node, we also know that no
-  // node can uniquely retain that node.
-  if (parents == 0 || component.root)
-    parents += 1;
-  for (const int64_t child_component_id : component.children_components) {
-    Component& child_component =
-        components_[static_cast<size_t>(child_component_id)];
-    PERFETTO_CHECK(child_component.pending_nodes > 0);
-    child_component.pending_nodes += parents;
-  }
-
-  int64_t retained_size = RetainedSize(component);
-  for (Node* n : component_nodes) {
-    int64_t unique_retained_size = 0;
-    auto it = unique_retained_by_node.find(n->row);
-    if (it != unique_retained_by_node.end())
-      unique_retained_size = it->second;
-
-    delegate_->SetRetained(
-        n->row, static_cast<int64_t>(retained_size),
-        static_cast<int64_t>(n->self_size) + unique_retained_size);
-  }
-}
-
-void HeapGraphWalker::FindSCC(Node* node) {
-  node->node_index = node->lowlink = next_node_index_++;
-  node_stack_.push_back(node);
-  node->on_stack = true;
-  for (Node* child : node->children) {
-    PERFETTO_CHECK(child->reachable);
-    if (child->node_index == 0) {
-      FindSCC(child);
-      if (child->lowlink < node->lowlink)
-        node->lowlink = child->lowlink;
-    } else if (child->on_stack) {
-      if (child->node_index < node->lowlink)
-        node->lowlink = child->node_index;
-    }
-  }
-
-  if (node->lowlink == node->node_index)
-    FoundSCC(node);
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/heap_graph_walker.h b/src/trace_processor/importers/proto/heap_graph_walker.h
deleted file mode 100644
index b23f2a3..0000000
--- a/src/trace_processor/importers/proto/heap_graph_walker.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_WALKER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_WALKER_H_
-
-#include <inttypes.h>
-#include <map>
-#include <set>
-#include <vector>
-
-// Implements two algorithms that walk a HeapGraph.
-// a) Traverse all references from roots and mark the nodes as reachable.
-// b) For each node, calculate two numbers:
-//    1. retained: The number of bytes that are directly and indirectly
-//       referenced by the node.
-//    2. uniquely retained: The number of bytes that are only retained through
-//       this object. If this object were destroyed, this many bytes would be
-//       freed up.
-//
-// The algorithm for b) is a modified Tarjan's algorithm. We use Tarjan's
-// algorithm to find connected components. This is such that we break cycles
-// that can exist in the retention graphs. All nodes within the cycle get
-// assigned the same component. Then, most of the graph algorithm operates on
-// these components.
-//
-// For instance, the below graph, which for simplicity does not contain any
-// loops.
-// Apart from nodes retaining / uniquely retaining themselves:
-// a retains nothing
-// a uniquely retains nothing
-//
-// b retains a
-// b uniquely retains nothing
-//
-// c retains a
-// c uniquely retains nothing
-//
-// d retains a, b, c
-// d uniquely retains a, b, c
-//
-//     a      |
-//    ^^      |
-//   /  \     |
-//   b   c    |
-//   ^   ^    |
-//    \ /     |
-//     d      |
-//
-// The basic idea of the algorithm is to keep track of the number of unvisited
-// nodes that retain the node. Nodes that have multiple parents get double
-// counted; this is so we can always reduce the number of unvisited nodes by
-// the number of edges from a node that retain a node.
-//
-// In the same graph:
-// visiting a: 2 unvisited nodes retain a {b, c}
-// visiting b: 2 unvisited nodes retain a {d, c}
-// visiting c: 2 unvisited nodes retain a {d, d}
-// visiting d: 0 unvisited nodes retain a
-//
-//
-// A more complete example
-//
-//     a       |
-//    ^^       |
-//   /  \      |
-//   b   c     |
-//   ^   ^     |
-//    \ / \    |
-//     d  e    |
-//     ^  ^    |
-//     \  /    |
-//      f      |
-//
-// visiting a: 2 unvisited nodes retain a ({b, c})
-// visiting b: 2 unvisited nodes retain a ({d, c})
-// visiting c: 3 unvisited nodes retain a ({d, d, e})
-// visiting d: 2 unvisited nodes retain a ({f, e})
-// visiting e: 2 unvisited nodes retain a ({f, f})
-// visiting f: 0 unvisited nodes retain a
-
-namespace perfetto {
-namespace trace_processor {
-
-class HeapGraphWalker {
- public:
-  class Delegate {
-   public:
-    virtual ~Delegate();
-    virtual void MarkReachable(int64_t row) = 0;
-    virtual void SetRetained(int64_t row,
-                             int64_t retained,
-                             int64_t unique_retained) = 0;
-  };
-
-  HeapGraphWalker(Delegate* delegate) : delegate_(delegate) {}
-
-  void AddEdge(int64_t owner_row, int64_t owned_row);
-  void AddNode(int64_t row, uint64_t size);
-
-  // Mark a a node as root. This marks all the nodes reachable from it as
-  // reachable.
-  void MarkRoot(int64_t row);
-  // Calculate the retained and unique retained size for each node. This
-  // includes nodes not reachable from roots.
-  void CalculateRetained();
-
- private:
-  struct Node {
-    // These are sets to conveniently get rid of double edges between nodes.
-    // We do not care if an object owns another object via multiple references
-    // or only one.
-    std::set<Node*> children;
-    std::set<Node*> parents;
-    uint64_t self_size = 0;
-    uint64_t retained_size = 0;
-
-    int64_t row = 0;
-    uint64_t node_index = 0;
-    uint64_t lowlink = 0;
-    int64_t component = -1;
-
-    bool reachable = false;
-    bool on_stack = false;
-    bool root = false;
-  };
-
-  struct Component {
-    uint64_t self_size = 0;
-    uint64_t unique_retained_size = 0;
-    uint64_t unique_retained_root_size = 0;
-    size_t incoming_edges = 0;
-    size_t orig_incoming_edges = 0;
-    size_t pending_nodes = 0;
-    std::set<int64_t> children_components;
-    uint64_t lowlink = 0;
-
-    bool root = false;
-  };
-
-  Node& GetNode(int64_t id) { return nodes_[static_cast<size_t>(id)]; }
-
-  void FindSCC(Node*);
-  void FoundSCC(Node*);
-  int64_t RetainedSize(const Component&);
-
-  // Make node and all transitive children as reachable.
-  void ReachableNode(Node*);
-
-  std::vector<Component> components_;
-  std::vector<Node*> node_stack_;
-  uint64_t next_node_index_ = 1;
-  std::vector<Node> nodes_;
-
-  Delegate* delegate_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_HEAP_GRAPH_WALKER_H_
diff --git a/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc b/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
deleted file mode 100644
index 763af52..0000000
--- a/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/importers/proto/heap_graph_walker.h"
-
-#include "perfetto/base/logging.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-using ::testing::UnorderedElementsAre;
-using ::testing::UnorderedElementsAreArray;
-
-class HeapGraphWalkerTestDelegate : public HeapGraphWalker::Delegate {
- public:
-  ~HeapGraphWalkerTestDelegate() override = default;
-
-  void MarkReachable(int64_t row) override { reachable_.emplace(row); }
-
-  void SetRetained(int64_t row,
-                   int64_t retained,
-                   int64_t unique_retained) override {
-    bool inserted;
-    std::tie(std::ignore, inserted) = retained_.emplace(row, retained);
-    PERFETTO_CHECK(inserted);
-    std::tie(std::ignore, inserted) =
-        unique_retained_.emplace(row, unique_retained);
-    PERFETTO_CHECK(inserted);
-  }
-
-  bool Reachable(int64_t row) {
-    return reachable_.find(row) != reachable_.end();
-  }
-
-  int64_t Retained(int64_t row) {
-    auto it = retained_.find(row);
-    PERFETTO_CHECK(it != retained_.end());
-    return it->second;
-  }
-
-  int64_t UniqueRetained(int64_t row) {
-    auto it = unique_retained_.find(row);
-    PERFETTO_CHECK(it != unique_retained_.end());
-    return it->second;
-  }
-
- private:
-  std::map<int64_t, int64_t> retained_;
-  std::map<int64_t, int64_t> unique_retained_;
-  std::set<int64_t> reachable_;
-};
-
-//     1     |
-//    ^^     |
-//   /  \    |
-//   2   3   |
-//   ^   ^   |
-//    \ /    |
-//     4R    |
-TEST(HeapGraphWalkerTest, Diamond) {
-  HeapGraphWalkerTestDelegate delegate;
-  HeapGraphWalker walker(&delegate);
-  walker.AddNode(1, 1);
-  walker.AddNode(2, 2);
-  walker.AddNode(3, 3);
-  walker.AddNode(4, 4);
-
-  walker.AddEdge(2, 1);
-  walker.AddEdge(3, 1);
-  walker.AddEdge(4, 2);
-  walker.AddEdge(4, 3);
-
-  walker.MarkRoot(4);
-  walker.CalculateRetained();
-
-  EXPECT_EQ(delegate.Retained(1), 1);
-  EXPECT_EQ(delegate.Retained(2), 3);
-  EXPECT_EQ(delegate.Retained(3), 4);
-  EXPECT_EQ(delegate.Retained(4), 10);
-
-  EXPECT_EQ(delegate.UniqueRetained(1), 1);
-  EXPECT_EQ(delegate.UniqueRetained(2), 2);
-  EXPECT_EQ(delegate.UniqueRetained(3), 3);
-  EXPECT_EQ(delegate.UniqueRetained(4), 10);
-}
-
-// 1       2  |
-// ^       ^  |
-//  \     /   |
-//  3R<->4    |
-TEST(HeapGraphWalkerTest, Loop) {
-  HeapGraphWalkerTestDelegate delegate;
-  HeapGraphWalker walker(&delegate);
-  walker.AddNode(1, 1);
-  walker.AddNode(2, 2);
-  walker.AddNode(3, 3);
-  walker.AddNode(4, 4);
-
-  walker.AddEdge(3, 1);
-  walker.AddEdge(3, 4);
-  walker.AddEdge(4, 2);
-  walker.AddEdge(4, 3);
-
-  walker.MarkRoot(3);
-  walker.CalculateRetained();
-
-  EXPECT_EQ(delegate.Retained(1), 1);
-  EXPECT_EQ(delegate.Retained(2), 2);
-  EXPECT_EQ(delegate.Retained(3), 10);
-  EXPECT_EQ(delegate.Retained(4), 10);
-
-  EXPECT_EQ(delegate.UniqueRetained(1), 1);
-  EXPECT_EQ(delegate.UniqueRetained(2), 2);
-  EXPECT_EQ(delegate.UniqueRetained(3), 4);
-  EXPECT_EQ(delegate.UniqueRetained(4), 6);
-}
-
-//    1R    |
-//    ^\    |
-//   /  v   |
-//   3<-2   |
-TEST(HeapGraphWalkerTest, Triangle) {
-  HeapGraphWalkerTestDelegate delegate;
-  HeapGraphWalker walker(&delegate);
-  walker.AddNode(1, 1);
-  walker.AddNode(2, 2);
-  walker.AddNode(3, 3);
-
-  walker.AddEdge(1, 2);
-  walker.AddEdge(2, 3);
-  walker.AddEdge(3, 1);
-
-  walker.MarkRoot(1);
-  walker.CalculateRetained();
-
-  EXPECT_EQ(delegate.Retained(1), 6);
-  EXPECT_EQ(delegate.Retained(2), 6);
-  EXPECT_EQ(delegate.Retained(3), 6);
-
-  EXPECT_EQ(delegate.UniqueRetained(1), 1);
-  EXPECT_EQ(delegate.UniqueRetained(2), 2);
-  EXPECT_EQ(delegate.UniqueRetained(3), 3);
-}
-
-// 1      |
-// ^      |
-// |      |
-// 2   4  |
-// ^   ^  |
-// |   |  |
-// 3R  5  |
-TEST(HeapGraphWalkerTest, Disconnected) {
-  HeapGraphWalkerTestDelegate delegate;
-  HeapGraphWalker walker(&delegate);
-  walker.AddNode(1, 1);
-  walker.AddNode(2, 2);
-  walker.AddNode(3, 3);
-  walker.AddNode(4, 4);
-  walker.AddNode(5, 5);
-
-  walker.AddEdge(2, 1);
-  walker.AddEdge(3, 2);
-  walker.AddEdge(5, 4);
-
-  walker.MarkRoot(3);
-  walker.CalculateRetained();
-
-  EXPECT_EQ(delegate.Retained(1), 1);
-  EXPECT_EQ(delegate.Retained(2), 3);
-  EXPECT_EQ(delegate.Retained(3), 6);
-
-  EXPECT_EQ(delegate.UniqueRetained(1), 1);
-  EXPECT_EQ(delegate.UniqueRetained(2), 3);
-  EXPECT_EQ(delegate.UniqueRetained(3), 6);
-
-  EXPECT_TRUE(delegate.Reachable(1));
-  EXPECT_TRUE(delegate.Reachable(2));
-  EXPECT_TRUE(delegate.Reachable(3));
-  EXPECT_FALSE(delegate.Reachable(4));
-  EXPECT_FALSE(delegate.Reachable(5));
-}
-
-//      1      |
-//      ^^     |
-//     / \     |
-//    2   3    |
-//    ^  ^^    |
-//    |/  |    |
-//    4   5    |
-//    ^   ^    |
-//    \  /     |
-//      6R     |
-TEST(HeapGraphWalkerTest, Complex) {
-  HeapGraphWalkerTestDelegate delegate;
-  HeapGraphWalker walker(&delegate);
-  walker.AddNode(1, 1);
-  walker.AddNode(2, 2);
-  walker.AddNode(3, 3);
-  walker.AddNode(4, 4);
-  walker.AddNode(5, 5);
-  walker.AddNode(6, 6);
-
-  walker.AddEdge(2, 1);
-  walker.AddEdge(3, 1);
-  walker.AddEdge(4, 2);
-  walker.AddEdge(4, 3);
-  walker.AddEdge(5, 3);
-  walker.AddEdge(6, 4);
-  walker.AddEdge(6, 5);
-
-  walker.MarkRoot(6);
-  walker.CalculateRetained();
-
-  EXPECT_EQ(delegate.Retained(1), 1);
-  EXPECT_EQ(delegate.Retained(2), 3);
-  EXPECT_EQ(delegate.Retained(3), 4);
-  EXPECT_EQ(delegate.Retained(4), 10);
-  EXPECT_EQ(delegate.Retained(5), 9);
-  EXPECT_EQ(delegate.Retained(6), 21);
-
-  EXPECT_EQ(delegate.UniqueRetained(1), 1);
-  EXPECT_EQ(delegate.UniqueRetained(2), 2);
-  EXPECT_EQ(delegate.UniqueRetained(3), 3);
-  EXPECT_EQ(delegate.UniqueRetained(4), 6);
-  EXPECT_EQ(delegate.UniqueRetained(5), 5);
-  EXPECT_EQ(delegate.UniqueRetained(6), 21);
-}
-
-//    1      |
-//    ^^     |
-//   /  \    |
-//  2<-> 3   |
-//  ^        |
-//  |        |
-//  4R       |
-TEST(HeapGraphWalkerTest, SharedInComponent) {
-  HeapGraphWalkerTestDelegate delegate;
-  HeapGraphWalker walker(&delegate);
-  walker.AddNode(1, 1);
-  walker.AddNode(2, 2);
-  walker.AddNode(3, 3);
-  walker.AddNode(4, 4);
-
-  walker.AddEdge(2, 1);
-  walker.AddEdge(2, 3);
-  walker.AddEdge(3, 1);
-  walker.AddEdge(3, 2);
-  walker.AddEdge(4, 2);
-
-  walker.MarkRoot(4);
-  walker.CalculateRetained();
-
-  EXPECT_EQ(delegate.Retained(1), 1);
-  EXPECT_EQ(delegate.Retained(2), 6);
-  EXPECT_EQ(delegate.Retained(3), 6);
-  EXPECT_EQ(delegate.Retained(4), 10);
-
-  EXPECT_EQ(delegate.UniqueRetained(1), 1);
-  // TODO(fmayer): this should be 6, as it breaks away the component.
-  EXPECT_EQ(delegate.UniqueRetained(2), 2);
-  EXPECT_EQ(delegate.UniqueRetained(3), 3);
-  EXPECT_EQ(delegate.UniqueRetained(4), 10);
-}
-
-// 1 <- 2   |
-// ^    ^   |
-// |    |   |
-// 3<-> 4R  |
-TEST(HeapGraphWalkerTest, TwoPaths) {
-  HeapGraphWalkerTestDelegate delegate;
-  HeapGraphWalker walker(&delegate);
-  walker.AddNode(1, 1);
-  walker.AddNode(2, 2);
-  walker.AddNode(3, 3);
-  walker.AddNode(4, 4);
-
-  walker.AddEdge(2, 1);
-  walker.AddEdge(3, 1);
-  walker.AddEdge(3, 4);
-  walker.AddEdge(4, 2);
-  walker.AddEdge(4, 3);
-
-  walker.MarkRoot(4);
-  walker.CalculateRetained();
-
-  EXPECT_EQ(delegate.Retained(1), 1);
-  EXPECT_EQ(delegate.Retained(2), 3);
-  EXPECT_EQ(delegate.Retained(3), 10);
-  EXPECT_EQ(delegate.Retained(4), 10);
-
-  EXPECT_EQ(delegate.UniqueRetained(1), 1);
-  EXPECT_EQ(delegate.UniqueRetained(2), 2);
-  EXPECT_EQ(delegate.UniqueRetained(3), 3);
-  EXPECT_EQ(delegate.UniqueRetained(4), 6);
-}
-
-//    1     |
-//   ^^     |
-//  /  \    |
-// 2R   3R  |
-TEST(HeapGraphWalkerTest, Diverge) {
-  HeapGraphWalkerTestDelegate delegate;
-  HeapGraphWalker walker(&delegate);
-  walker.AddNode(1, 1);
-  walker.AddNode(2, 2);
-  walker.AddNode(3, 3);
-
-  walker.AddEdge(2, 1);
-  walker.AddEdge(3, 1);
-
-  walker.MarkRoot(2);
-  walker.MarkRoot(3);
-  walker.CalculateRetained();
-
-  EXPECT_EQ(delegate.Retained(1), 1);
-  EXPECT_EQ(delegate.Retained(2), 3);
-  EXPECT_EQ(delegate.Retained(3), 4);
-
-  EXPECT_EQ(delegate.UniqueRetained(1), 1);
-  EXPECT_EQ(delegate.UniqueRetained(2), 2);
-  EXPECT_EQ(delegate.UniqueRetained(3), 3);
-}
-
-//    1            |
-//   ^^            |
-//  /  \           |
-// 2R   3 (dead)   |
-TEST(HeapGraphWalkerTest, Dead) {
-  HeapGraphWalkerTestDelegate delegate;
-  HeapGraphWalker walker(&delegate);
-  walker.AddNode(1, 1);
-  walker.AddNode(2, 2);
-  walker.AddNode(3, 3);
-
-  walker.AddEdge(2, 1);
-  walker.AddEdge(3, 1);
-
-  walker.MarkRoot(2);
-  walker.CalculateRetained();
-
-  EXPECT_EQ(delegate.Retained(1), 1);
-  EXPECT_EQ(delegate.Retained(2), 3);
-
-  EXPECT_EQ(delegate.UniqueRetained(1), 1);
-  EXPECT_EQ(delegate.UniqueRetained(2), 3);
-}
-
-//    2<->3  |
-//    ^      |
-//    |      |
-//    1R     |
-TEST(HeapGraphWalkerTest, Component) {
-  HeapGraphWalkerTestDelegate delegate;
-  HeapGraphWalker walker(&delegate);
-  walker.AddNode(1, 1);
-  walker.AddNode(2, 2);
-  walker.AddNode(3, 3);
-
-  walker.AddEdge(1, 2);
-  walker.AddEdge(2, 3);
-  walker.AddEdge(3, 2);
-
-  walker.MarkRoot(1);
-  walker.CalculateRetained();
-
-  EXPECT_EQ(delegate.Retained(1), 6);
-  EXPECT_EQ(delegate.Retained(2), 5);
-  EXPECT_EQ(delegate.Retained(3), 5);
-
-  EXPECT_EQ(delegate.UniqueRetained(1), 6);
-  // TODO(fmayer): this should be 5, as this breaks away the component.
-  EXPECT_EQ(delegate.UniqueRetained(2), 2);
-  EXPECT_EQ(delegate.UniqueRetained(3), 3);
-}
-
-//    2<->3R |
-//    ^      |
-//    |      |
-//    1R     |
-TEST(HeapGraphWalkerTest, ComponentWithRoot) {
-  HeapGraphWalkerTestDelegate delegate;
-  HeapGraphWalker walker(&delegate);
-  walker.AddNode(1, 1);
-  walker.AddNode(2, 2);
-  walker.AddNode(3, 3);
-
-  walker.AddEdge(1, 2);
-  walker.AddEdge(2, 3);
-  walker.AddEdge(3, 2);
-
-  walker.MarkRoot(1);
-  walker.MarkRoot(3);
-  walker.CalculateRetained();
-
-  EXPECT_EQ(delegate.Retained(1), 6);
-  EXPECT_EQ(delegate.Retained(2), 5);
-  EXPECT_EQ(delegate.Retained(3), 5);
-
-  EXPECT_EQ(delegate.UniqueRetained(1), 1);
-  EXPECT_EQ(delegate.UniqueRetained(2), 2);
-  EXPECT_EQ(delegate.UniqueRetained(3), 3);
-}
-
-// R
-// 2 <-  3   |
-//  ^   ^   |
-//   \ /    |
-//    1R    |
-TEST(HeapGraphWalkerTest, TwoRoots) {
-  HeapGraphWalkerTestDelegate delegate;
-  HeapGraphWalker walker(&delegate);
-  walker.AddNode(1, 1);
-  walker.AddNode(2, 2);
-  walker.AddNode(3, 3);
-
-  walker.AddEdge(1, 2);
-  walker.AddEdge(1, 3);
-  walker.AddEdge(3, 2);
-
-  walker.MarkRoot(1);
-  walker.MarkRoot(2);
-  walker.CalculateRetained();
-
-  EXPECT_EQ(delegate.Retained(1), 6);
-  EXPECT_EQ(delegate.Retained(2), 2);
-  EXPECT_EQ(delegate.Retained(3), 5);
-
-  EXPECT_EQ(delegate.UniqueRetained(1), 4);
-  EXPECT_EQ(delegate.UniqueRetained(2), 2);
-  EXPECT_EQ(delegate.UniqueRetained(3), 3);
-}
-
-// Call a function for every set in the powerset or the cartesian product
-// of v with itself.
-// TODO(fmayer): Find a smarter way to generate all graphs.
-template <typename F>
-void SquarePowerSet(const std::vector<int64_t>& v, F fn) {
-  for (uint64_t subset = 0; subset < pow(2, pow(v.size(), 2)); ++subset) {
-    std::vector<std::pair<int64_t, int64_t>> ps;
-    uint64_t node = 0;
-    for (int64_t n1 : v) {
-      for (int64_t n2 : v) {
-        if ((1 << node++) & subset)
-          ps.emplace_back(n1, n2);
-      }
-    }
-    fn(ps);
-  }
-}
-
-// Call a function for every set in the powerset.
-template <typename F>
-void PowerSet(const std::vector<int64_t>& v, F fn) {
-  for (uint64_t subset = 0; subset < pow(2, v.size()); ++subset) {
-    std::vector<int64_t> ps;
-    uint64_t node = 0;
-    for (int64_t n : v) {
-      if ((1 << node++) & subset)
-        ps.emplace_back(n);
-    }
-    fn(ps);
-  }
-}
-
-TEST(PowerSetTest, Simple) {
-  std::vector<int64_t> s = {0, 1, 2};
-  std::vector<std::vector<int64_t>> ps;
-  PowerSet(s, [&ps](const std::vector<int64_t>& x) { ps.emplace_back(x); });
-  EXPECT_THAT(ps, UnorderedElementsAre(std::vector<int64_t>{},      //
-                                       std::vector<int64_t>{0},     //
-                                       std::vector<int64_t>{1},     //
-                                       std::vector<int64_t>{2},     //
-                                       std::vector<int64_t>{0, 1},  //
-                                       std::vector<int64_t>{0, 2},  //
-                                       std::vector<int64_t>{1, 2},  //
-                                       std::vector<int64_t>{0, 1, 2}));
-}
-
-TEST(SquarePowerSetTest, Simple) {
-  std::vector<int64_t> s = {0, 1};
-  std::vector<std::vector<std::pair<int64_t, int64_t>>> ps;
-  SquarePowerSet(s, [&ps](const std::vector<std::pair<int64_t, int64_t>>& x) {
-    ps.emplace_back(x);
-  });
-
-  std::vector<std::pair<int64_t, int64_t>> expected[] = {
-      {},                        //
-      {{0, 0}},                  //
-      {{0, 1}},                  //
-      {{1, 0}},                  //
-      {{1, 1}},                  //
-      {{0, 0}, {0, 1}},          //
-      {{0, 0}, {1, 0}},          //
-      {{0, 0}, {1, 1}},          //
-      {{0, 1}, {1, 0}},          //
-      {{0, 1}, {1, 1}},          //
-      {{1, 0}, {1, 1}},          //
-      {{0, 0}, {0, 1}, {1, 0}},  //
-      {{0, 0}, {0, 1}, {1, 1}},  //
-      {{0, 0}, {1, 0}, {1, 1}},  //
-      {{0, 1}, {1, 0}, {1, 1}},  //
-      {{0, 0}, {0, 1}, {1, 0}, {1, 1}}};
-  EXPECT_THAT(ps, UnorderedElementsAreArray(expected));
-}
-
-// Generate all graphs with 4 nodes, and assert that deleting one node frees
-// up more memory than that node's unique retained.
-TEST(HeapGraphWalkerTest, AllGraphs) {
-  std::vector<int64_t> nodes{1, 2, 3, 4};
-  std::vector<uint64_t> sizes{0, 1, 2, 3, 4};
-  PowerSet(nodes, [&nodes, &sizes](const std::vector<int64_t>& roots) {
-    SquarePowerSet(
-        nodes, [&nodes, &sizes,
-                &roots](const std::vector<std::pair<int64_t, int64_t>>& edges) {
-          HeapGraphWalkerTestDelegate delegate;
-          HeapGraphWalker walker(&delegate);
-
-          HeapGraphWalkerTestDelegate delegate2;
-          HeapGraphWalker walker2(&delegate2);
-
-          for (int64_t node : nodes) {
-            walker.AddNode(node, sizes[static_cast<size_t>(node)]);
-            // walker2 leaves out node 1.
-            if (node != 1)
-              walker2.AddNode(node, sizes[static_cast<size_t>(node)]);
-          }
-
-          for (const auto& p : edges) {
-            walker.AddEdge(p.first, p.second);
-            // walker2 leaves out node 1.
-            if (p.first != 1 && p.second != 1)
-              walker2.AddEdge(p.first, p.second);
-          }
-
-          for (int64_t r : roots) {
-            walker.MarkRoot(r);
-            // walker2 leaves out node 1.
-            if (r != 1)
-              walker2.MarkRoot(r);
-          }
-
-          walker.CalculateRetained();
-          // We do not need to CalculateRetained on walker2, because we only
-          // get the reachable nodes.
-
-          int64_t reachable = 0;
-          int64_t reachable2 = 0;
-
-          ASSERT_FALSE(delegate2.Reachable(1));
-          for (int64_t n : nodes) {
-            if (delegate.Reachable(n))
-              reachable += sizes[static_cast<size_t>(n)];
-            if (delegate2.Reachable(n))
-              reachable2 += sizes[static_cast<size_t>(n)];
-          }
-          EXPECT_LE(reachable2, reachable);
-          if (delegate.Reachable(1)) {
-            // TODO(fmayer): This should be EXPECT_EQ, but we do currently
-            // undercount the unique retained, because we do not include the
-            // memory that could get freed by the component being broken apart.
-            EXPECT_LE(delegate.UniqueRetained(1), reachable - reachable2)
-                << "roots: " << testing::PrintToString(roots)
-                << ", edges: " << testing::PrintToString(edges);
-          }
-        });
-  });
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/packet_sequence_state.h b/src/trace_processor/importers/proto/packet_sequence_state.h
deleted file mode 100644
index b6bc5a6..0000000
--- a/src/trace_processor/importers/proto/packet_sequence_state.h
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PACKET_SEQUENCE_STATE_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PACKET_SEQUENCE_STATE_H_
-
-#include <stdint.h>
-
-#include <unordered_map>
-#include <vector>
-
-#include "perfetto/base/compiler.h"
-#include "perfetto/protozero/proto_decoder.h"
-#include "src/trace_processor/stack_profile_tracker.h"
-#include "src/trace_processor/trace_blob_view.h"
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-#if PERFETTO_DCHECK_IS_ON()
-// When called from GetOrCreateDecoder(), should include the stringified name of
-// the MessageType.
-#define PERFETTO_TYPE_IDENTIFIER PERFETTO_DEBUG_FUNCTION_IDENTIFIER()
-#else  // PERFETTO_DCHECK_IS_ON()
-#define PERFETTO_TYPE_IDENTIFIER nullptr
-#endif  // PERFETTO_DCHECK_IS_ON()
-
-class PacketSequenceState {
- public:
-  // Entry in an interning index, refers to the interned message.
-  struct InternedMessageView {
-    InternedMessageView(TraceBlobView msg) : message(std::move(msg)) {}
-
-    template <typename MessageType>
-    typename MessageType::Decoder* GetOrCreateDecoder() {
-      if (!decoder) {
-        // Lazy init the decoder and save it away, so that we don't have to
-        // reparse the message every time we access the interning entry.
-        decoder = std::unique_ptr<void, std::function<void(void*)>>(
-            new typename MessageType::Decoder(message.data(), message.length()),
-            [](void* obj) {
-              delete reinterpret_cast<typename MessageType::Decoder*>(obj);
-            });
-        decoder_type = PERFETTO_TYPE_IDENTIFIER;
-      }
-      // Verify that the type of the decoder didn't change.
-      if (PERFETTO_TYPE_IDENTIFIER &&
-          strcmp(decoder_type,
-                 // GCC complains if this arg can be null.
-                 PERFETTO_TYPE_IDENTIFIER ? PERFETTO_TYPE_IDENTIFIER : "") !=
-              0) {
-        PERFETTO_FATAL(
-            "Interning entry accessed under different types! previous type: "
-            "%s. new type: %s.",
-            decoder_type, __PRETTY_FUNCTION__);
-      }
-      return reinterpret_cast<typename MessageType::Decoder*>(decoder.get());
-    }
-
-    TraceBlobView message;
-    std::unique_ptr<void, std::function<void(void*)>> decoder;
-
-   private:
-    const char* decoder_type = nullptr;
-  };
-
-  using InternedMessageMap =
-      std::unordered_map<uint64_t /*iid*/, InternedMessageView>;
-  using InternedFieldMap =
-      std::unordered_map<uint32_t /*field_id*/, InternedMessageMap>;
-  using InternedDataGenerationList = std::vector<InternedFieldMap>;
-
-  PacketSequenceState(TraceProcessorContext* context)
-      : context_(context), stack_profile_tracker_(context) {
-    interned_data_.emplace_back();
-  }
-
-  int64_t IncrementAndGetTrackEventTimeNs(int64_t delta_ns) {
-    PERFETTO_DCHECK(track_event_timestamps_valid());
-    track_event_timestamp_ns_ += delta_ns;
-    return track_event_timestamp_ns_;
-  }
-
-  int64_t IncrementAndGetTrackEventThreadTimeNs(int64_t delta_ns) {
-    PERFETTO_DCHECK(track_event_timestamps_valid());
-    track_event_thread_timestamp_ns_ += delta_ns;
-    return track_event_thread_timestamp_ns_;
-  }
-
-  int64_t IncrementAndGetTrackEventThreadInstructionCount(int64_t delta) {
-    PERFETTO_DCHECK(track_event_timestamps_valid());
-    track_event_thread_instruction_count_ += delta;
-    return track_event_thread_instruction_count_;
-  }
-
-  void OnPacketLoss() {
-    packet_loss_ = true;
-    track_event_timestamps_valid_ = false;
-  }
-
-  void OnIncrementalStateCleared() {
-    packet_loss_ = false;
-    interned_data_.emplace_back();  // Bump generation number
-  }
-
-  void SetThreadDescriptor(int32_t pid,
-                           int32_t tid,
-                           int64_t timestamp_ns,
-                           int64_t thread_timestamp_ns,
-                           int64_t thread_instruction_count) {
-    track_event_timestamps_valid_ = true;
-    pid_and_tid_valid_ = true;
-    pid_ = pid;
-    tid_ = tid;
-    track_event_timestamp_ns_ = timestamp_ns;
-    track_event_thread_timestamp_ns_ = thread_timestamp_ns;
-    track_event_thread_instruction_count_ = thread_instruction_count;
-  }
-
-  bool IsIncrementalStateValid() const { return !packet_loss_; }
-
-  StackProfileTracker& stack_profile_tracker() {
-    return stack_profile_tracker_;
-  }
-
-  // Returns the index of the current generation in the
-  // InternedDataGenerationList.
-  size_t current_generation() const { return interned_data_.size() - 1; }
-
-  bool track_event_timestamps_valid() const {
-    return track_event_timestamps_valid_;
-  }
-
-  bool pid_and_tid_valid() const { return pid_and_tid_valid_; }
-
-  int32_t pid() const { return pid_; }
-  int32_t tid() const { return tid_; }
-
-  void InternMessage(uint32_t field_id, TraceBlobView message) {
-    constexpr auto kIidFieldNumber = 1;
-
-    uint64_t iid = 0;
-    auto message_start = message.data();
-    auto message_size = message.length();
-    protozero::ProtoDecoder decoder(message_start, message_size);
-
-    auto field = decoder.FindField(kIidFieldNumber);
-    if (PERFETTO_UNLIKELY(!field)) {
-      PERFETTO_DLOG("Interned message without interning_id");
-      context_->storage->IncrementStats(stats::interned_data_tokenizer_errors);
-      return;
-    }
-    iid = field.as_uint64();
-
-    auto* map = &interned_data_.back()[field_id];
-    auto res = map->emplace(iid, InternedMessageView(std::move(message)));
-
-    // If a message with this ID is already interned in the same generation,
-    // its data should not have changed (this is forbidden by the InternedData
-    // proto).
-    // TODO(eseckler): This DCHECK assumes that the message is encoded the
-    // same way if it is re-emitted.
-    PERFETTO_DCHECK(res.second ||
-                    (res.first->second.message.length() == message_size &&
-                     memcmp(res.first->second.message.data(), message_start,
-                            message_size) == 0));
-  }
-
-  template <uint32_t FieldId, typename MessageType>
-  typename MessageType::Decoder* LookupInternedMessage(size_t generation,
-                                                       uint64_t iid) {
-    PERFETTO_CHECK(generation <= interned_data_.size());
-    auto* field_map = &interned_data_[generation];
-    auto field_it = field_map->find(FieldId);
-    if (field_it != field_map->end()) {
-      auto* message_map = &field_it->second;
-      auto it = message_map->find(iid);
-      if (it != message_map->end()) {
-        return it->second.GetOrCreateDecoder<MessageType>();
-      }
-    }
-    context_->storage->IncrementStats(stats::interned_data_tokenizer_errors);
-    PERFETTO_DLOG("Could not find interning entry for field ID %" PRIu32
-                  ", generation %zu, and IID %" PRIu64,
-                  FieldId, generation, iid);
-    return nullptr;
-  }
-
- private:
-  TraceProcessorContext* context_;
-
-  // If true, incremental state on the sequence is considered invalid until we
-  // see the next packet with incremental_state_cleared. We assume that we
-  // missed some packets at the beginning of the trace.
-  bool packet_loss_ = true;
-
-  // We can only consider TrackEvent delta timestamps to be correct after we
-  // have observed a thread descriptor (since the last packet loss).
-  bool track_event_timestamps_valid_ = false;
-
-  // |pid_| and |tid_| are only valid after we parsed at least one
-  // ThreadDescriptor packet on the sequence.
-  bool pid_and_tid_valid_ = false;
-
-  // Process/thread ID of the packet sequence set by a ThreadDescriptor
-  // packet. Used as default values for TrackEvents that don't specify a
-  // pid/tid override. Only valid after |pid_and_tid_valid_| is set to true.
-  int32_t pid_ = 0;
-  int32_t tid_ = 0;
-
-  // Current wall/thread timestamps/counters used as reference for the next
-  // TrackEvent delta timestamp.
-  int64_t track_event_timestamp_ns_ = 0;
-  int64_t track_event_thread_timestamp_ns_ = 0;
-  int64_t track_event_thread_instruction_count_ = 0;
-
-  InternedDataGenerationList interned_data_;
-  StackProfileTracker stack_profile_tracker_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PACKET_SEQUENCE_STATE_H_
diff --git a/src/trace_processor/importers/proto/proto_importer_module.h b/src/trace_processor/importers/proto/proto_importer_module.h
deleted file mode 100644
index 77a9256..0000000
--- a/src/trace_processor/importers/proto/proto_importer_module.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_IMPORTER_MODULE_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_IMPORTER_MODULE_H_
-
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/trace_processor/status.h"
-#include "src/trace_processor/trace_blob_view.h"
-
-namespace perfetto {
-
-namespace protos {
-namespace pbzero {
-class TraceConfig_Decoder;
-class TracePacket_Decoder;
-}  // namespace pbzero
-}  // namespace protos
-
-namespace trace_processor {
-
-class PacketSequenceState;
-struct TimestampedTracePiece;
-class TraceProcessorContext;
-
-// This file contains helper and base class templates for
-// ProtoTraceTokenizer/Parser modules. A module implements support for a subset
-// of features of the TracePacket proto format. Modules inherit from
-// ProtoImporterModuleBase, and should be instantiated using the
-// ProtoImporterModule<> wrapper template in trace_processor_context.h.
-//
-// To add and integrate a new module:
-// (1) Add MyModule as a subclass of ProtoImporterModuleBase<IsEnabled>,
-//     defining the TokenizePacket() and/or ParsePacket() methods.
-//     Typically, a build-time macro will inform the value of IsEnabled.
-//     See ftrace_module.h for an example.
-// (2) Add a member of type std::unique_ptr<ProtoImporterModule<MyModule>> to
-//     TraceProcessorContext (trace_processor_context.h) and init it from
-//     TraceProcessorImpl() and appropriate tests.
-// (3) Add an include of my_module.h and calls to your module's TokenizePacket /
-//     ParsePacket methods in ProtoTraceTokenizer and/or ProtoTraceParser
-//     (proxying via the wrapper).
-
-class ModuleResult {
- public:
-  // Allow auto conversion from util::Status to Handled / Error result.
-  ModuleResult(util::Status status)
-      : ignored_(false),
-        error_(status.ok() ? base::nullopt
-                           : base::make_optional(status.message())) {}
-
-  // Constructs a result that indicates the module ignored the packet and is
-  // deferring the handling of the packet to other modules.
-  static ModuleResult Ignored() { return ModuleResult(true); }
-
-  // Constructs a result that indicates the module handled the packet. Other
-  // modules will not be notified about the packet.
-  static ModuleResult Handled() { return ModuleResult(false); }
-
-  // Constructs a result that indicates an error condition while handling the
-  // packet. Other modules will not be notified about the packet.
-  static ModuleResult Error(const std::string& message) {
-    return ModuleResult(message);
-  }
-
-  bool ignored() const { return ignored_; }
-  bool ok() const { return !error_.has_value(); }
-  const std::string& message() const { return *error_; }
-
-  util::Status ToStatus() const {
-    PERFETTO_DCHECK(!ignored_);
-    if (error_)
-      return util::Status(*error_);
-    return util::OkStatus();
-  }
-
- private:
-  explicit ModuleResult(bool ignored) : ignored_(ignored) {}
-  explicit ModuleResult(const std::string& error)
-      : ignored_(false), error_(error) {}
-
-  bool ignored_;
-  base::Optional<std::string> error_;
-};
-
-// Wrapper class for a module. This wrapper allows modules to be disabled
-// disabled at compile time to remove support for its features from the trace
-// processor.
-//
-// The trace processor will instantiate enabled modules for each
-// TraceProcessorContext. The tokenizer and parser notify individual modules
-// about trace data by calling their respective methods via the wrapper class.
-// If the module is enabled, the wrapper will forward the call to the module
-// implementation. This way, we avoid virtual methods, so that calling any of
-// the module's methods is zero overhead - they can be inlined by the compiler
-// at callsites directly.
-template <class ModuleType>
-class ProtoImporterModule {
- public:
-  ProtoImporterModule(TraceProcessorContext* context) {
-    if (ModuleType::kEnabled)
-      impl_.reset(new ModuleType(context));
-  }
-
-  // ModuleType may specify methods with the signatures below.
-  // ProtoImporterModule<ModuleType> acts as a wrapper for these methods.
-  // ModuleType only needs to specify the methods that
-  // ProtoTraceParser/Tokenizer actually calls on the respective module.
-
-  // Wraps ModuleType::TokenizePacket(). If the module is disabled, compiles
-  // into a noop in optimized builds. Called by ProtoTraceTokenizer for each
-  // TracePacket during the tokenization stage, i.e. before sorting. If this
-  // returns a result other than ModuleResult::Ignored(), tokenization of the
-  // packet will be aborted after the module.
-  ModuleResult TokenizePacket(
-      const protos::pbzero::TracePacket_Decoder& decoder,
-      TraceBlobView* packet,
-      int64_t packet_timestamp,
-      PacketSequenceState* state) {
-    if (ModuleType::kEnabled) {
-      return impl_->TokenizePacket(decoder, packet, packet_timestamp, state);
-    }
-    return ModuleResult::Ignored();
-  }
-
-  // Wraps ModuleType::ParsePacket(). If the module is disabled, compiles into a
-  // noop in optimized builds. Called by ProtoTraceParser for each non-ftrace
-  // TracePacket after the sorting stage. If this returns a result other than
-  // ModuleResult::Ignored(), parsing of the packet will be aborted after the
-  // module.
-  ModuleResult ParsePacket(const protos::pbzero::TracePacket_Decoder& decoder,
-                           const TimestampedTracePiece& ttp) {
-    if (ModuleType::kEnabled)
-      return impl_->ParsePacket(decoder, ttp);
-    return ModuleResult::Ignored();
-  }
-
-  // Wraps ModuleType::ParseTraceConfig(). If the module is disabled, compiles
-  // into a noop in optimized builds. Called by ProtoTraceParser for trace
-  // config packets after the sorting stage.
-  ModuleResult ParseTraceConfig(
-      const protos::pbzero::TraceConfig_Decoder& decoder) {
-    if (ModuleType::kEnabled)
-      return impl_->ParseTraceConfig(decoder);
-    return ModuleResult::Ignored();
-  }
-
-  // For FtraceModule only. Wraps ModuleType::ParseFtracePacket(). If the module
-  // is disabled, compiles into a noop in optimized builds. Called by
-  // ProtoTraceParser for each ftrace TracePacket after the sorting stage.
-  // Ftrace packets are handled specially here because they are sorted in
-  // separate queues per CPU. If this returns a result other than
-  // ModuleResult::Ignored(), parsing of the packet will be aborted after the
-  // module.
-  ModuleResult ParseFtracePacket(uint32_t cpu,
-                                 const TimestampedTracePiece& ttp) {
-    if (ModuleType::kEnabled)
-      return impl_->ParseFtracePacket(cpu, ttp);
-    return ModuleResult::Ignored();
-  }
-
- private:
-  // Only initialized if the module is enabled.
-  std::unique_ptr<ModuleType> impl_;
-};
-
-// Base class for a proto trace module that can be disabled at compile time.
-// Typically, a build-time macro will inform the value of IsEnabled.
-template <int IsEnabled>
-class ProtoImporterModuleBase {
- public:
-  static constexpr bool kEnabled = static_cast<bool>(IsEnabled);
-
-  explicit ProtoImporterModuleBase(TraceProcessorContext* context)
-      : context_(context) {}
-  ~ProtoImporterModuleBase() {}
-
-  // See ProtoTraceModule<> for the public methods subclasses may implement.
-
- protected:
-  TraceProcessorContext* context_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_IMPORTER_MODULE_H_
diff --git a/src/trace_processor/importers/proto/proto_incremental_state.h b/src/trace_processor/importers/proto/proto_incremental_state.h
deleted file mode 100644
index aaac42f..0000000
--- a/src/trace_processor/importers/proto/proto_incremental_state.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_INCREMENTAL_STATE_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_INCREMENTAL_STATE_H_
-
-#include <stdint.h>
-
-#include <map>
-
-#include "src/trace_processor/importers/proto/packet_sequence_state.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-// Stores per-packet-sequence incremental state during trace parsing, such as
-// reference timestamps for delta timestamp calculation and interned messages.
-class ProtoIncrementalState {
- public:
-  ProtoIncrementalState(TraceProcessorContext* context) : context_(context) {}
-
-  // Returns the PacketSequenceState for the packet sequence with the given id.
-  // If this is a new sequence which we haven't tracked before, initializes and
-  // inserts a new PacketSequenceState into the state map.
-  PacketSequenceState* GetOrCreateStateForPacketSequence(uint32_t sequence_id) {
-    auto& ptr = packet_sequence_states_[sequence_id];
-    if (!ptr)
-      ptr.reset(new PacketSequenceState(context_));
-    return ptr.get();
-  }
-
- private:
-  // Stores unique_ptrs to ensure that pointers to a PacketSequenceState remain
-  // valid even if the map rehashes.
-  std::map<uint32_t, std::unique_ptr<PacketSequenceState>>
-      packet_sequence_states_;
-
-  TraceProcessorContext* context_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_INCREMENTAL_STATE_H_
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.cc b/src/trace_processor/importers/proto/proto_trace_parser.cc
deleted file mode 100644
index bd19c0e..0000000
--- a/src/trace_processor/importers/proto/proto_trace_parser.cc
+++ /dev/null
@@ -1,664 +0,0 @@
-/*
- * 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.
- */
-
-#include "src/trace_processor/importers/proto/proto_trace_parser.h"
-
-#include <inttypes.h>
-#include <string.h>
-
-#include <string>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/metatrace_events.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/ext/base/string_writer.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/base/uuid.h"
-#include "perfetto/trace_processor/status.h"
-#include "src/trace_processor/args_tracker.h"
-#include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/heap_profile_tracker.h"
-#include "src/trace_processor/importers/ftrace/ftrace_module.h"
-#include "src/trace_processor/importers/proto/android_probes_module.h"
-#include "src/trace_processor/importers/proto/graphics_event_module.h"
-#include "src/trace_processor/importers/proto/heap_graph_module.h"
-#include "src/trace_processor/importers/proto/packet_sequence_state.h"
-#include "src/trace_processor/importers/proto/system_probes_module.h"
-#include "src/trace_processor/importers/proto/track_event_module.h"
-#include "src/trace_processor/metadata.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/slice_tracker.h"
-#include "src/trace_processor/stack_profile_tracker.h"
-#include "src/trace_processor/timestamped_trace_piece.h"
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/track_tracker.h"
-#include "src/trace_processor/variadic.h"
-
-#include "protos/perfetto/common/trace_stats.pbzero.h"
-#include "protos/perfetto/config/trace_config.pbzero.h"
-#include "protos/perfetto/trace/chrome/chrome_benchmark_metadata.pbzero.h"
-#include "protos/perfetto/trace/chrome/chrome_trace_event.pbzero.h"
-#include "protos/perfetto/trace/clock_snapshot.pbzero.h"
-#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
-#include "protos/perfetto/trace/perfetto/perfetto_metatrace.pbzero.h"
-#include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
-#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
-#include "protos/perfetto/trace/trace.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-
-StackProfileTracker::SourceMapping MakeSourceMapping(
-    const protos::pbzero::Mapping::Decoder& entry) {
-  StackProfileTracker::SourceMapping src_mapping{};
-  src_mapping.build_id = entry.build_id();
-  src_mapping.exact_offset = entry.exact_offset();
-  src_mapping.start_offset = entry.start_offset();
-  src_mapping.start = entry.start();
-  src_mapping.end = entry.end();
-  src_mapping.load_bias = entry.load_bias();
-  for (auto path_string_id_it = entry.path_string_ids(); path_string_id_it;
-       ++path_string_id_it)
-    src_mapping.name_ids.emplace_back(*path_string_id_it);
-  return src_mapping;
-}
-
-StackProfileTracker::SourceFrame MakeSourceFrame(
-    const protos::pbzero::Frame::Decoder& entry) {
-  StackProfileTracker::SourceFrame src_frame;
-  src_frame.name_id = entry.function_name_id();
-  src_frame.mapping_id = entry.mapping_id();
-  src_frame.rel_pc = entry.rel_pc();
-  return src_frame;
-}
-
-StackProfileTracker::SourceCallstack MakeSourceCallstack(
-    const protos::pbzero::Callstack::Decoder& entry) {
-  StackProfileTracker::SourceCallstack src_callstack;
-  for (auto frame_it = entry.frame_ids(); frame_it; ++frame_it)
-    src_callstack.emplace_back(*frame_it);
-  return src_callstack;
-}
-
-class ProfilePacketInternLookup : public StackProfileTracker::InternLookup {
- public:
-  ProfilePacketInternLookup(PacketSequenceState* seq_state,
-                            size_t seq_state_generation)
-      : seq_state_(seq_state), seq_state_generation_(seq_state_generation) {}
-
-  base::Optional<base::StringView> GetString(
-      StackProfileTracker::SourceStringId iid,
-      StackProfileTracker::InternedStringType type) const override {
-    protos::pbzero::InternedString::Decoder* decoder = nullptr;
-    switch (type) {
-      case StackProfileTracker::InternedStringType::kBuildId:
-        decoder = seq_state_->LookupInternedMessage<
-            protos::pbzero::InternedData::kBuildIdsFieldNumber,
-            protos::pbzero::InternedString>(seq_state_generation_, iid);
-        break;
-      case StackProfileTracker::InternedStringType::kFunctionName:
-        decoder = seq_state_->LookupInternedMessage<
-            protos::pbzero::InternedData::kFunctionNamesFieldNumber,
-            protos::pbzero::InternedString>(seq_state_generation_, iid);
-        break;
-      case StackProfileTracker::InternedStringType::kMappingPath:
-        decoder = seq_state_->LookupInternedMessage<
-            protos::pbzero::InternedData::kMappingPathsFieldNumber,
-            protos::pbzero::InternedString>(seq_state_generation_, iid);
-        break;
-    }
-    if (!decoder)
-      return base::nullopt;
-    return base::StringView(reinterpret_cast<const char*>(decoder->str().data),
-                            decoder->str().size);
-  }
-
-  base::Optional<StackProfileTracker::SourceMapping> GetMapping(
-      StackProfileTracker::SourceMappingId iid) const override {
-    auto* decoder = seq_state_->LookupInternedMessage<
-        protos::pbzero::InternedData::kMappingsFieldNumber,
-        protos::pbzero::Mapping>(seq_state_generation_, iid);
-    if (!decoder)
-      return base::nullopt;
-    return MakeSourceMapping(*decoder);
-  }
-
-  base::Optional<StackProfileTracker::SourceFrame> GetFrame(
-      StackProfileTracker::SourceFrameId iid) const override {
-    auto* decoder = seq_state_->LookupInternedMessage<
-        protos::pbzero::InternedData::kFramesFieldNumber,
-        protos::pbzero::Frame>(seq_state_generation_, iid);
-    if (!decoder)
-      return base::nullopt;
-    return MakeSourceFrame(*decoder);
-  }
-
-  base::Optional<StackProfileTracker::SourceCallstack> GetCallstack(
-      StackProfileTracker::SourceCallstackId iid) const override {
-    auto* decoder = seq_state_->LookupInternedMessage<
-        protos::pbzero::InternedData::kCallstacksFieldNumber,
-        protos::pbzero::Callstack>(seq_state_generation_, iid);
-    if (!decoder)
-      return base::nullopt;
-    return MakeSourceCallstack(*decoder);
-  }
-
- private:
-  PacketSequenceState* seq_state_;
-  size_t seq_state_generation_;
-};
-
-}  // namespace
-
-ProtoTraceParser::ProtoTraceParser(TraceProcessorContext* context)
-    : context_(context),
-      metatrace_id_(context->storage->InternString("metatrace")),
-      data_name_id_(context->storage->InternString("data")),
-      raw_chrome_metadata_event_id_(
-          context->storage->InternString("chrome_event.metadata")),
-      raw_chrome_legacy_system_trace_event_id_(
-          context->storage->InternString("chrome_event.legacy_system_trace")),
-      raw_chrome_legacy_user_trace_event_id_(
-          context->storage->InternString("chrome_event.legacy_user_trace")) {
-  // TODO(140860736): Once we support null values for
-  // stack_profile_frame.symbol_set_id remove this hack
-  context_->storage->mutable_symbol_table()->Insert({0, 0, 0, 0});
-}
-
-ProtoTraceParser::~ProtoTraceParser() = default;
-
-void ProtoTraceParser::ParseTracePacket(int64_t ts, TimestampedTracePiece ttp) {
-  PERFETTO_DCHECK(ttp.json_value == nullptr);
-
-  const TraceBlobView& blob = ttp.blob_view;
-  protos::pbzero::TracePacket::Decoder packet(blob.data(), blob.length());
-
-  ParseTracePacketImpl(ts, std::move(ttp), packet);
-
-  // TODO(lalitm): maybe move this to the flush method in the trace processor
-  // once we have it. This may reduce performance in the ArgsTracker though so
-  // needs to be handled carefully.
-  context_->args_tracker->Flush();
-  PERFETTO_DCHECK(!packet.bytes_left());
-}
-
-void ProtoTraceParser::ParseTracePacketImpl(
-    int64_t ts,
-    TimestampedTracePiece ttp,
-    const protos::pbzero::TracePacket::Decoder& packet) {
-  // TODO(eseckler): Propagate statuses from modules.
-  if (!context_->ftrace_module->ParsePacket(packet, ttp).ignored())
-    return;
-
-  if (!context_->track_event_module->ParsePacket(packet, ttp).ignored())
-    return;
-
-  if (!context_->system_probes_module->ParsePacket(packet, ttp).ignored())
-    return;
-
-  if (!context_->android_probes_module->ParsePacket(packet, ttp).ignored())
-    return;
-
-  if (!context_->heap_graph_module->ParsePacket(packet, ttp).ignored())
-    return;
-
-  if (!context_->graphics_event_module->ParsePacket(packet, ttp).ignored())
-    return;
-
-  if (packet.has_trace_stats())
-    ParseTraceStats(packet.trace_stats());
-
-  if (packet.has_profile_packet()) {
-    ParseProfilePacket(ts, ttp.packet_sequence_state,
-                       ttp.packet_sequence_state_generation,
-                       packet.profile_packet());
-  }
-
-  if (packet.has_streaming_profile_packet()) {
-    ParseStreamingProfilePacket(ttp.packet_sequence_state,
-                                ttp.packet_sequence_state_generation,
-                                packet.streaming_profile_packet());
-  }
-
-  if (packet.has_chrome_benchmark_metadata()) {
-    ParseChromeBenchmarkMetadata(packet.chrome_benchmark_metadata());
-  }
-
-  if (packet.has_chrome_events()) {
-    ParseChromeEvents(ts, packet.chrome_events());
-  }
-
-  if (packet.has_perfetto_metatrace()) {
-    ParseMetatraceEvent(ts, packet.perfetto_metatrace());
-  }
-
-  if (packet.has_trace_config()) {
-    ParseTraceConfig(packet.trace_config());
-  }
-
-  if (packet.has_module_symbols()) {
-    ParseModuleSymbols(packet.module_symbols());
-  }
-}
-
-void ProtoTraceParser::ParseFtracePacket(uint32_t cpu,
-                                         int64_t /*ts*/,
-                                         TimestampedTracePiece ttp) {
-  PERFETTO_DCHECK(ttp.json_value == nullptr);
-
-  ModuleResult res = context_->ftrace_module->ParseFtracePacket(cpu, ttp);
-  PERFETTO_DCHECK(!res.ignored());
-  // TODO(eseckler): Propagate status.
-  if (!res.ok()) {
-    PERFETTO_ELOG("%s", res.message().c_str());
-  }
-
-  // TODO(lalitm): maybe move this to the flush method in the trace processor
-  // once we have it. This may reduce performance in the ArgsTracker though so
-  // needs to be handled carefully.
-  context_->args_tracker->Flush();
-}
-
-void ProtoTraceParser::ParseTraceStats(ConstBytes blob) {
-  protos::pbzero::TraceStats::Decoder evt(blob.data, blob.size);
-  auto* storage = context_->storage.get();
-  storage->SetStats(stats::traced_producers_connected,
-                    static_cast<int64_t>(evt.producers_connected()));
-  storage->SetStats(stats::traced_data_sources_registered,
-                    static_cast<int64_t>(evt.data_sources_registered()));
-  storage->SetStats(stats::traced_data_sources_seen,
-                    static_cast<int64_t>(evt.data_sources_seen()));
-  storage->SetStats(stats::traced_tracing_sessions,
-                    static_cast<int64_t>(evt.tracing_sessions()));
-  storage->SetStats(stats::traced_total_buffers,
-                    static_cast<int64_t>(evt.total_buffers()));
-  storage->SetStats(stats::traced_chunks_discarded,
-                    static_cast<int64_t>(evt.chunks_discarded()));
-  storage->SetStats(stats::traced_patches_discarded,
-                    static_cast<int64_t>(evt.patches_discarded()));
-
-  int buf_num = 0;
-  for (auto it = evt.buffer_stats(); it; ++it, ++buf_num) {
-    protos::pbzero::TraceStats::BufferStats::Decoder buf(*it);
-    storage->SetIndexedStats(stats::traced_buf_buffer_size, buf_num,
-                             static_cast<int64_t>(buf.buffer_size()));
-    storage->SetIndexedStats(stats::traced_buf_bytes_written, buf_num,
-                             static_cast<int64_t>(buf.bytes_written()));
-    storage->SetIndexedStats(stats::traced_buf_bytes_overwritten, buf_num,
-                             static_cast<int64_t>(buf.bytes_overwritten()));
-    storage->SetIndexedStats(stats::traced_buf_bytes_read, buf_num,
-                             static_cast<int64_t>(buf.bytes_read()));
-    storage->SetIndexedStats(stats::traced_buf_padding_bytes_written, buf_num,
-                             static_cast<int64_t>(buf.padding_bytes_written()));
-    storage->SetIndexedStats(stats::traced_buf_padding_bytes_cleared, buf_num,
-                             static_cast<int64_t>(buf.padding_bytes_cleared()));
-    storage->SetIndexedStats(stats::traced_buf_chunks_written, buf_num,
-                             static_cast<int64_t>(buf.chunks_written()));
-    storage->SetIndexedStats(stats::traced_buf_chunks_rewritten, buf_num,
-                             static_cast<int64_t>(buf.chunks_rewritten()));
-    storage->SetIndexedStats(stats::traced_buf_chunks_overwritten, buf_num,
-                             static_cast<int64_t>(buf.chunks_overwritten()));
-    storage->SetIndexedStats(stats::traced_buf_chunks_discarded, buf_num,
-                             static_cast<int64_t>(buf.chunks_discarded()));
-    storage->SetIndexedStats(stats::traced_buf_chunks_read, buf_num,
-                             static_cast<int64_t>(buf.chunks_read()));
-    storage->SetIndexedStats(
-        stats::traced_buf_chunks_committed_out_of_order, buf_num,
-        static_cast<int64_t>(buf.chunks_committed_out_of_order()));
-    storage->SetIndexedStats(stats::traced_buf_write_wrap_count, buf_num,
-                             static_cast<int64_t>(buf.write_wrap_count()));
-    storage->SetIndexedStats(stats::traced_buf_patches_succeeded, buf_num,
-                             static_cast<int64_t>(buf.patches_succeeded()));
-    storage->SetIndexedStats(stats::traced_buf_patches_failed, buf_num,
-                             static_cast<int64_t>(buf.patches_failed()));
-    storage->SetIndexedStats(stats::traced_buf_readaheads_succeeded, buf_num,
-                             static_cast<int64_t>(buf.readaheads_succeeded()));
-    storage->SetIndexedStats(stats::traced_buf_readaheads_failed, buf_num,
-                             static_cast<int64_t>(buf.readaheads_failed()));
-    storage->SetIndexedStats(
-        stats::traced_buf_trace_writer_packet_loss, buf_num,
-        static_cast<int64_t>(buf.trace_writer_packet_loss()));
-  }
-}
-
-void ProtoTraceParser::ParseProfilePacket(int64_t,
-                                          PacketSequenceState* sequence_state,
-                                          size_t sequence_state_generation,
-                                          ConstBytes blob) {
-  protos::pbzero::ProfilePacket::Decoder packet(blob.data, blob.size);
-  context_->heap_profile_tracker->SetProfilePacketIndex(packet.index());
-
-  for (auto it = packet.strings(); it; ++it) {
-    protos::pbzero::InternedString::Decoder entry(*it);
-
-    const char* str = reinterpret_cast<const char*>(entry.str().data);
-    auto str_view = base::StringView(str, entry.str().size);
-    sequence_state->stack_profile_tracker().AddString(entry.iid(), str_view);
-  }
-
-  for (auto it = packet.mappings(); it; ++it) {
-    protos::pbzero::Mapping::Decoder entry(*it);
-    StackProfileTracker::SourceMapping src_mapping = MakeSourceMapping(entry);
-    sequence_state->stack_profile_tracker().AddMapping(entry.iid(),
-                                                       src_mapping);
-  }
-
-  for (auto it = packet.frames(); it; ++it) {
-    protos::pbzero::Frame::Decoder entry(*it);
-    StackProfileTracker::SourceFrame src_frame = MakeSourceFrame(entry);
-    sequence_state->stack_profile_tracker().AddFrame(entry.iid(), src_frame);
-  }
-
-  for (auto it = packet.callstacks(); it; ++it) {
-    protos::pbzero::Callstack::Decoder entry(*it);
-    StackProfileTracker::SourceCallstack src_callstack =
-        MakeSourceCallstack(entry);
-    sequence_state->stack_profile_tracker().AddCallstack(entry.iid(),
-                                                         src_callstack);
-  }
-
-  for (auto it = packet.process_dumps(); it; ++it) {
-    protos::pbzero::ProfilePacket::ProcessHeapSamples::Decoder entry(*it);
-
-    int pid = static_cast<int>(entry.pid());
-
-    if (entry.buffer_corrupted())
-      context_->storage->IncrementIndexedStats(
-          stats::heapprofd_buffer_corrupted, pid);
-    if (entry.buffer_overran())
-      context_->storage->IncrementIndexedStats(stats::heapprofd_buffer_overran,
-                                               pid);
-    if (entry.rejected_concurrent())
-      context_->storage->IncrementIndexedStats(
-          stats::heapprofd_rejected_concurrent, pid);
-
-    for (auto sample_it = entry.samples(); sample_it; ++sample_it) {
-      protos::pbzero::ProfilePacket::HeapSample::Decoder sample(*sample_it);
-
-      HeapProfileTracker::SourceAllocation src_allocation;
-      src_allocation.pid = entry.pid();
-      src_allocation.timestamp = static_cast<int64_t>(entry.timestamp());
-      src_allocation.callstack_id = sample.callstack_id();
-      src_allocation.self_allocated = sample.self_allocated();
-      src_allocation.self_freed = sample.self_freed();
-      src_allocation.alloc_count = sample.alloc_count();
-      src_allocation.free_count = sample.free_count();
-
-      context_->heap_profile_tracker->StoreAllocation(src_allocation);
-    }
-  }
-  if (!packet.continued()) {
-    PERFETTO_CHECK(sequence_state);
-    ProfilePacketInternLookup intern_lookup(sequence_state,
-                                            sequence_state_generation);
-    context_->heap_profile_tracker->FinalizeProfile(
-        &sequence_state->stack_profile_tracker(), &intern_lookup);
-  }
-}
-
-void ProtoTraceParser::ParseStreamingProfilePacket(
-    PacketSequenceState* sequence_state,
-    size_t sequence_state_generation,
-    ConstBytes blob) {
-  protos::pbzero::StreamingProfilePacket::Decoder packet(blob.data, blob.size);
-
-  ProcessTracker* procs = context_->process_tracker.get();
-  TraceStorage* storage = context_->storage.get();
-  StackProfileTracker& stack_profile_tracker =
-      sequence_state->stack_profile_tracker();
-  ProfilePacketInternLookup intern_lookup(sequence_state,
-                                          sequence_state_generation);
-
-  uint32_t pid = static_cast<uint32_t>(sequence_state->pid());
-  uint32_t tid = static_cast<uint32_t>(sequence_state->tid());
-  UniqueTid utid = procs->UpdateThread(tid, pid);
-
-  auto timestamp_it = packet.timestamp_delta_us();
-  for (auto callstack_it = packet.callstack_iid(); callstack_it;
-       ++callstack_it, ++timestamp_it) {
-    if (!timestamp_it) {
-      context_->storage->IncrementStats(stats::stackprofile_parser_error);
-      PERFETTO_ELOG(
-          "StreamingProfilePacket has less callstack IDs than timestamps!");
-      break;
-    }
-
-    auto maybe_callstack_id =
-        stack_profile_tracker.FindCallstack(*callstack_it, &intern_lookup);
-    if (!maybe_callstack_id) {
-      context_->storage->IncrementStats(stats::stackprofile_parser_error);
-      PERFETTO_ELOG("StreamingProfilePacket referencing invalid callstack!");
-      continue;
-    }
-
-    int64_t callstack_id = *maybe_callstack_id;
-
-    TraceStorage::CpuProfileStackSamples::Row sample_row{
-        sequence_state->IncrementAndGetTrackEventTimeNs(*timestamp_it),
-        callstack_id, utid};
-    storage->mutable_cpu_profile_stack_samples()->Insert(sample_row);
-  }
-}
-
-void ProtoTraceParser::ParseChromeBenchmarkMetadata(ConstBytes blob) {
-  TraceStorage* storage = context_->storage.get();
-  protos::pbzero::ChromeBenchmarkMetadata::Decoder packet(blob.data, blob.size);
-  if (packet.has_benchmark_name()) {
-    auto benchmark_name_id = storage->InternString(packet.benchmark_name());
-    storage->SetMetadata(metadata::benchmark_name,
-                         Variadic::String(benchmark_name_id));
-  }
-  if (packet.has_benchmark_description()) {
-    auto benchmark_description_id =
-        storage->InternString(packet.benchmark_description());
-    storage->SetMetadata(metadata::benchmark_description,
-                         Variadic::String(benchmark_description_id));
-  }
-  if (packet.has_label()) {
-    auto label_id = storage->InternString(packet.label());
-    storage->SetMetadata(metadata::benchmark_label, Variadic::String(label_id));
-  }
-  if (packet.has_story_name()) {
-    auto story_name_id = storage->InternString(packet.story_name());
-    storage->SetMetadata(metadata::benchmark_story_name,
-                         Variadic::String(story_name_id));
-  }
-  for (auto it = packet.story_tags(); it; ++it) {
-    auto story_tag_id = storage->InternString(*it);
-    storage->AppendMetadata(metadata::benchmark_story_tags,
-                            Variadic::String(story_tag_id));
-  }
-  if (packet.has_benchmark_start_time_us()) {
-    storage->SetMetadata(metadata::benchmark_start_time_us,
-                         Variadic::Integer(packet.benchmark_start_time_us()));
-  }
-  if (packet.has_story_run_time_us()) {
-    storage->SetMetadata(metadata::benchmark_story_run_time_us,
-                         Variadic::Integer(packet.story_run_time_us()));
-  }
-  if (packet.has_story_run_index()) {
-    storage->SetMetadata(metadata::benchmark_story_run_index,
-                         Variadic::Integer(packet.story_run_index()));
-  }
-  if (packet.has_had_failures()) {
-    storage->SetMetadata(metadata::benchmark_had_failures,
-                         Variadic::Integer(packet.had_failures()));
-  }
-}
-
-void ProtoTraceParser::ParseChromeEvents(int64_t ts, ConstBytes blob) {
-  TraceStorage* storage = context_->storage.get();
-  protos::pbzero::ChromeEventBundle::Decoder bundle(blob.data, blob.size);
-  ArgsTracker args(context_);
-  if (bundle.has_metadata()) {
-    RowId row_id = storage->mutable_raw_events()->AddRawEvent(
-        ts, raw_chrome_metadata_event_id_, 0, 0);
-
-    // Metadata is proxied via a special event in the raw table to JSON export.
-    for (auto it = bundle.metadata(); it; ++it) {
-      protos::pbzero::ChromeMetadata::Decoder metadata(*it);
-      StringId name_id = storage->InternString(metadata.name());
-      Variadic value;
-      if (metadata.has_string_value()) {
-        value =
-            Variadic::String(storage->InternString(metadata.string_value()));
-      } else if (metadata.has_int_value()) {
-        value = Variadic::Integer(metadata.int_value());
-      } else if (metadata.has_bool_value()) {
-        value = Variadic::Integer(metadata.bool_value());
-      } else if (metadata.has_json_value()) {
-        value = Variadic::Json(storage->InternString(metadata.json_value()));
-      } else {
-        PERFETTO_FATAL("Empty ChromeMetadata message");
-      }
-      args.AddArg(row_id, name_id, name_id, value);
-    }
-  }
-
-  if (bundle.has_legacy_ftrace_output()) {
-    RowId row_id = storage->mutable_raw_events()->AddRawEvent(
-        ts, raw_chrome_legacy_system_trace_event_id_, 0, 0);
-
-    std::string data;
-    for (auto it = bundle.legacy_ftrace_output(); it; ++it) {
-      data += (*it).ToStdString();
-    }
-    Variadic value =
-        Variadic::String(storage->InternString(base::StringView(data)));
-    args.AddArg(row_id, data_name_id_, data_name_id_, value);
-  }
-
-  if (bundle.has_legacy_json_trace()) {
-    for (auto it = bundle.legacy_json_trace(); it; ++it) {
-      protos::pbzero::ChromeLegacyJsonTrace::Decoder legacy_trace(*it);
-      if (legacy_trace.type() !=
-          protos::pbzero::ChromeLegacyJsonTrace::USER_TRACE) {
-        continue;
-      }
-      RowId row_id = storage->mutable_raw_events()->AddRawEvent(
-          ts, raw_chrome_legacy_user_trace_event_id_, 0, 0);
-      Variadic value =
-          Variadic::String(storage->InternString(legacy_trace.data()));
-      args.AddArg(row_id, data_name_id_, data_name_id_, value);
-    }
-  }
-}
-
-void ProtoTraceParser::ParseMetatraceEvent(int64_t ts, ConstBytes blob) {
-  protos::pbzero::PerfettoMetatrace::Decoder event(blob.data, blob.size);
-  auto utid = context_->process_tracker->GetOrCreateThread(event.thread_id());
-
-  StringId cat_id = metatrace_id_;
-  StringId name_id = 0;
-  char fallback[64];
-
-  if (event.has_event_id()) {
-    auto eid = event.event_id();
-    if (eid < metatrace::EVENTS_MAX) {
-      name_id = context_->storage->InternString(metatrace::kEventNames[eid]);
-    } else {
-      sprintf(fallback, "Event %d", eid);
-      name_id = context_->storage->InternString(fallback);
-    }
-    TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-    context_->slice_tracker->Scoped(ts, track_id, utid, RefType::kRefUtid,
-                                    cat_id, name_id, event.event_duration_ns());
-  } else if (event.has_counter_id()) {
-    auto cid = event.counter_id();
-    if (cid < metatrace::COUNTERS_MAX) {
-      name_id = context_->storage->InternString(metatrace::kCounterNames[cid]);
-    } else {
-      sprintf(fallback, "Counter %d", cid);
-      name_id = context_->storage->InternString(fallback);
-    }
-    TrackId track =
-        context_->track_tracker->InternThreadCounterTrack(name_id, utid);
-    context_->event_tracker->PushCounter(ts, event.counter_value(), track);
-  }
-
-  if (event.has_overruns())
-    context_->storage->IncrementStats(stats::metatrace_overruns);
-}
-
-void ProtoTraceParser::ParseTraceConfig(ConstBytes blob) {
-  protos::pbzero::TraceConfig::Decoder trace_config(blob.data, blob.size);
-
-  // TODO(eseckler): Propagate statuses from modules.
-  context_->android_probes_module->ParseTraceConfig(trace_config);
-
-  if (trace_config.trace_uuid().size != 0) {
-    ConstBytes bytes = trace_config.trace_uuid();
-    base::Optional<base::Uuid> uuid = base::BytesToUuid(bytes.data, bytes.size);
-    if (uuid.has_value()) {
-      std::string str = base::UuidToPrettyString(uuid.value());
-      StringId id = context_->storage->InternString(base::StringView(str));
-      context_->storage->SetMetadata(metadata::trace_uuid,
-                                     Variadic::String(id));
-    }
-  }
-}
-
-void ProtoTraceParser::ParseModuleSymbols(ConstBytes blob) {
-  protos::pbzero::ModuleSymbols::Decoder module_symbols(blob.data, blob.size);
-  std::string hex_build_id = base::ToHex(module_symbols.build_id().data,
-                                         module_symbols.build_id().size);
-  auto mapping_rows =
-      context_->storage->stack_profile_mappings().FindMappingRow(
-          context_->storage->InternString(module_symbols.path()),
-          context_->storage->InternString(base::StringView(hex_build_id)));
-  if (mapping_rows.empty()) {
-    context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
-    return;
-  }
-  for (auto addr_it = module_symbols.address_symbols(); addr_it; ++addr_it) {
-    protos::pbzero::AddressSymbols::Decoder address_symbols(*addr_it);
-
-    uint32_t symbol_set_id = context_->storage->symbol_table().size();
-    bool frame_found = false;
-    for (int64_t mapping_row : mapping_rows) {
-      std::vector<int64_t> frame_rows =
-          context_->storage->stack_profile_frames().FindFrameRow(
-              static_cast<size_t>(mapping_row), address_symbols.address());
-
-      for (const int64_t frame_row : frame_rows) {
-        PERFETTO_DCHECK(frame_row >= 0);
-        context_->storage->mutable_stack_profile_frames()->SetSymbolSetId(
-            static_cast<size_t>(frame_row), symbol_set_id);
-        frame_found = true;
-      }
-    }
-
-    if (!frame_found) {
-      context_->storage->IncrementStats(stats::stackprofile_invalid_frame_id);
-      continue;
-    }
-
-    for (auto line_it = address_symbols.lines(); line_it; ++line_it) {
-      protos::pbzero::Line::Decoder line(*line_it);
-      context_->storage->mutable_symbol_table()->Insert(
-          {symbol_set_id, context_->storage->InternString(line.function_name()),
-           context_->storage->InternString(line.source_file_name()),
-           line.line_number()});
-    }
-  }
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.h b/src/trace_processor/importers/proto/proto_trace_parser.h
deleted file mode 100644
index bae7341..0000000
--- a/src/trace_processor/importers/proto/proto_trace_parser.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_TRACE_PARSER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_TRACE_PARSER_H_
-
-#include <stdint.h>
-
-#include <array>
-#include <memory>
-
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/protozero/field.h"
-#include "src/trace_processor/timestamped_trace_piece.h"
-#include "src/trace_processor/trace_blob_view.h"
-#include "src/trace_processor/trace_parser.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-
-namespace protos {
-namespace pbzero {
-class TracePacket_Decoder;
-}  // namespace pbzero
-}  // namespace protos
-
-namespace trace_processor {
-
-class ArgsTracker;
-class PacketSequenceState;
-class TraceProcessorContext;
-
-class ProtoTraceParser : public TraceParser {
- public:
-  using ConstBytes = protozero::ConstBytes;
-  explicit ProtoTraceParser(TraceProcessorContext*);
-  ~ProtoTraceParser() override;
-
-  // TraceParser implementation.
-  void ParseTracePacket(int64_t timestamp, TimestampedTracePiece) override;
-  void ParseFtracePacket(uint32_t cpu,
-                         int64_t timestamp,
-                         TimestampedTracePiece) override;
-
-  void ParseTracePacketImpl(int64_t ts,
-                            TimestampedTracePiece,
-                            const protos::pbzero::TracePacket_Decoder&);
-
-  void ParseTraceStats(ConstBytes);
-  void ParseProfilePacket(int64_t ts,
-                          PacketSequenceState*,
-                          size_t sequence_state_generation,
-                          ConstBytes);
-  void ParseStreamingProfilePacket(PacketSequenceState*,
-                                   size_t sequence_state_generation,
-                                   ConstBytes);
-  void ParseChromeBenchmarkMetadata(ConstBytes);
-  void ParseChromeEvents(int64_t ts, ConstBytes);
-  void ParseMetatraceEvent(int64_t ts, ConstBytes);
-  void ParseTraceConfig(ConstBytes);
-  void ParseModuleSymbols(ConstBytes);
-
- private:
-  TraceProcessorContext* context_;
-
-  const StringId metatrace_id_;
-  const StringId data_name_id_;
-  const StringId raw_chrome_metadata_event_id_;
-  const StringId raw_chrome_legacy_system_trace_event_id_;
-  const StringId raw_chrome_legacy_user_trace_event_id_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_TRACE_PARSER_H_
diff --git a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
deleted file mode 100644
index 0d184a4..0000000
--- a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
+++ /dev/null
@@ -1,2647 +0,0 @@
-/*
- * 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.
- */
-
-#include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "src/trace_processor/args_tracker.h"
-#include "src/trace_processor/clock_tracker.h"
-#include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/importers/ftrace/ftrace_module.h"
-#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
-#include "src/trace_processor/importers/proto/android_probes_module.h"
-#include "src/trace_processor/importers/proto/graphics_event_module.h"
-#include "src/trace_processor/importers/proto/heap_graph_module.h"
-#include "src/trace_processor/importers/proto/proto_importer_module.h"
-#include "src/trace_processor/importers/proto/proto_trace_parser.h"
-#include "src/trace_processor/importers/proto/system_probes_module.h"
-#include "src/trace_processor/importers/proto/track_event_module.h"
-#include "src/trace_processor/importers/systrace/systrace_parser.h"
-#include "src/trace_processor/metadata.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/slice_tracker.h"
-#include "src/trace_processor/stack_profile_tracker.h"
-#include "src/trace_processor/trace_sorter.h"
-#include "src/trace_processor/trace_storage.h"
-#include "src/trace_processor/track_tracker.h"
-#include "src/trace_processor/vulkan_memory_tracker.h"
-#include "test/gtest_and_gmock.h"
-
-#include "protos/perfetto/common/sys_stats_counters.pbzero.h"
-#include "protos/perfetto/trace/android/packages_list.pbzero.h"
-#include "protos/perfetto/trace/chrome/chrome_benchmark_metadata.pbzero.h"
-#include "protos/perfetto/trace/chrome/chrome_trace_event.pbzero.h"
-#include "protos/perfetto/trace/clock_snapshot.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-#include "protos/perfetto/trace/ftrace/generic.pbzero.h"
-#include "protos/perfetto/trace/ftrace/power.pbzero.h"
-#include "protos/perfetto/trace/ftrace/sched.pbzero.h"
-#include "protos/perfetto/trace/ftrace/task.pbzero.h"
-#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
-#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
-#include "protos/perfetto/trace/ps/process_tree.pbzero.h"
-#include "protos/perfetto/trace/sys_stats/sys_stats.pbzero.h"
-#include "protos/perfetto/trace/trace.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-#include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
-#include "protos/perfetto/trace/track_event/log_message.pbzero.h"
-#include "protos/perfetto/trace/track_event/source_location.pbzero.h"
-#include "protos/perfetto/trace/track_event/task_execution.pbzero.h"
-#include "protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
-#include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
-#include "protos/perfetto/trace/track_event/track_event.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-using ::testing::_;
-using ::testing::Args;
-using ::testing::AtLeast;
-using ::testing::ElementsAreArray;
-using ::testing::Eq;
-using ::testing::InSequence;
-using ::testing::Invoke;
-using ::testing::InvokeArgument;
-using ::testing::NiceMock;
-using ::testing::Pointwise;
-using ::testing::Return;
-using ::testing::UnorderedElementsAreArray;
-
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE) || \
-    PERFETTO_BUILDFLAG(PERFETTO_TP_SYSTEM_PROBES)
-namespace {
-MATCHER_P(DoubleEq, exp, "Double matcher that satisfies -Wfloat-equal") {
-  // The IEEE standard says that any comparison operation involving
-  // a NAN must return false.
-  double d_exp = exp;
-  double d_arg = arg;
-  if (isnan(d_exp) || isnan(d_arg))
-    return false;
-  return fabs(d_arg - d_exp) < 1e-128;
-}
-}  // namespace
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE) ||
-        // PERFETTO_BUILDFLAG(PERFETTO_TP_SYSTEM_PROBES)
-
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-class MockSchedEventTracker : public SchedEventTracker {
- public:
-  MockSchedEventTracker(TraceProcessorContext* context)
-      : SchedEventTracker(context) {}
-  virtual ~MockSchedEventTracker() = default;
-
-  MOCK_METHOD9(PushSchedSwitch,
-               void(uint32_t cpu,
-                    int64_t timestamp,
-                    uint32_t prev_pid,
-                    base::StringView prev_comm,
-                    int32_t prev_prio,
-                    int64_t prev_state,
-                    uint32_t next_pid,
-                    base::StringView next_comm,
-                    int32_t next_prio));
-};
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-
-class MockEventTracker : public EventTracker {
- public:
-  MockEventTracker(TraceProcessorContext* context) : EventTracker(context) {}
-  virtual ~MockEventTracker() = default;
-
-  MOCK_METHOD9(PushSchedSwitch,
-               void(uint32_t cpu,
-                    int64_t timestamp,
-                    uint32_t prev_pid,
-                    base::StringView prev_comm,
-                    int32_t prev_prio,
-                    int64_t prev_state,
-                    uint32_t next_pid,
-                    base::StringView next_comm,
-                    int32_t next_prio));
-
-  MOCK_METHOD3(PushCounter,
-               RowId(int64_t timestamp, double value, uint32_t track_id));
-
-  MOCK_METHOD6(PushInstant,
-               RowId(int64_t timestamp,
-                     StringId name_id,
-                     double value,
-                     int64_t ref,
-                     RefType ref_type,
-                     bool resolve_utid_to_upid));
-};
-
-class MockProcessTracker : public ProcessTracker {
- public:
-  MockProcessTracker(TraceProcessorContext* context)
-      : ProcessTracker(context) {}
-
-  MOCK_METHOD3(SetProcessMetadata,
-               UniquePid(uint32_t pid,
-                         base::Optional<uint32_t> ppid,
-                         base::StringView process_name));
-
-  MOCK_METHOD2(UpdateThreadName,
-               UniqueTid(uint32_t tid, StringId thread_name_id));
-  MOCK_METHOD2(SetThreadNameIfUnset,
-               void(UniqueTid utid, StringId thread_name_id));
-  MOCK_METHOD2(UpdateThread, UniqueTid(uint32_t tid, uint32_t tgid));
-
-  MOCK_METHOD1(GetOrCreateProcess, UniquePid(uint32_t pid));
-};
-
-// Mock trace storage that behaves like the real implementation, but allows for
-// the interactions with string interning/lookup to be overridden/inspected.
-class MockTraceStorage : public TraceStorage {
- public:
-  MockTraceStorage() : TraceStorage() {
-    ON_CALL(*this, InternString(_))
-        .WillByDefault(Invoke([this](base::StringView str) {
-          return TraceStorage::InternString(str);
-        }));
-
-    ON_CALL(*this, GetString(_)).WillByDefault(Invoke([this](StringId id) {
-      return TraceStorage::GetString(id);
-    }));
-
-    ON_CALL(*this, GetThread(_))
-        .WillByDefault(Invoke(this, &MockTraceStorage::GetThreadImpl));
-  }
-
-  const Thread& GetThreadImpl(UniqueTid utid) {
-    return TraceStorage::GetThread(utid);
-  }
-
-  MOCK_METHOD1(InternString, StringId(base::StringView));
-  MOCK_CONST_METHOD1(GetString, NullTermStringView(StringId));
-
-  MOCK_CONST_METHOD1(GetThread, const Thread&(UniqueTid));
-};
-
-class MockArgsTracker : public ArgsTracker {
- public:
-  MockArgsTracker(TraceProcessorContext* context) : ArgsTracker(context) {}
-
-  MOCK_METHOD4(AddArg,
-               void(RowId row_id, StringId flat_key, StringId key, Variadic));
-  MOCK_METHOD0(Flush, void());
-};
-
-class MockSliceTracker : public SliceTracker {
- public:
-  MockSliceTracker(TraceProcessorContext* context) : SliceTracker(context) {}
-
-  MOCK_METHOD7(Begin,
-               base::Optional<uint32_t>(int64_t timestamp,
-                                        TrackId track_id,
-                                        int64_t ref,
-                                        RefType ref_type,
-                                        StringId cat,
-                                        StringId name,
-                                        SetArgsCallback args_callback));
-  MOCK_METHOD5(End,
-               base::Optional<uint32_t>(int64_t timestamp,
-                                        TrackId track_id,
-                                        StringId cat,
-                                        StringId name,
-                                        SetArgsCallback args_callback));
-  MOCK_METHOD8(Scoped,
-               base::Optional<uint32_t>(int64_t timestamp,
-                                        TrackId track_id,
-                                        int64_t ref,
-                                        RefType ref_type,
-                                        StringId cat,
-                                        StringId name,
-                                        int64_t duration,
-                                        SetArgsCallback args_callback));
-};
-
-class ProtoTraceParserTest : public ::testing::Test {
- public:
-  ProtoTraceParserTest() {
-    storage_ = new NiceMock<MockTraceStorage>();
-    context_.storage.reset(storage_);
-    context_.track_tracker.reset(new TrackTracker(&context_));
-    context_.args_tracker.reset(new ArgsTracker(&context_));
-    event_ = new MockEventTracker(&context_);
-    context_.event_tracker.reset(event_);
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-    sched_ = new MockSchedEventTracker(&context_);
-    context_.sched_tracker.reset(sched_);
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-    process_ = new MockProcessTracker(&context_);
-    context_.process_tracker.reset(process_);
-    slice_ = new MockSliceTracker(&context_);
-    context_.slice_tracker.reset(slice_);
-    clock_ = new ClockTracker(&context_);
-    context_.clock_tracker.reset(clock_);
-    context_.sorter.reset(new TraceSorter(&context_, 0 /*window size*/));
-    context_.parser.reset(new ProtoTraceParser(&context_));
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-    context_.systrace_parser.reset(new SystraceParser(&context_));
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_GRAPHICS)
-    context_.vulkan_memory_tracker.reset(new VulkanMemoryTracker(&context_));
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_GRAPHICS)
-    context_.ftrace_module.reset(
-        new ProtoImporterModule<FtraceModule>(&context_));
-    context_.track_event_module.reset(
-        new ProtoImporterModule<TrackEventModule>(&context_));
-    context_.system_probes_module.reset(
-        new ProtoImporterModule<SystemProbesModule>(&context_));
-    context_.android_probes_module.reset(
-        new ProtoImporterModule<AndroidProbesModule>(&context_));
-    context_.heap_graph_module.reset(
-        new ProtoImporterModule<HeapGraphModule>(&context_));
-    context_.graphics_event_module.reset(
-        new ProtoImporterModule<GraphicsEventModule>(&context_));
-  }
-
-  void ResetTraceBuffers() {
-    heap_buf_.reset(new protozero::ScatteredHeapBuffer());
-    stream_writer_.reset(new protozero::ScatteredStreamWriter(heap_buf_.get()));
-    heap_buf_->set_writer(stream_writer_.get());
-    trace_.Reset(stream_writer_.get());
-  }
-
-  void SetUp() override { ResetTraceBuffers(); }
-
-  util::Status Tokenize() {
-    trace_.Finalize();
-    std::vector<uint8_t> trace_bytes = heap_buf_->StitchSlices();
-    std::unique_ptr<uint8_t[]> raw_trace(new uint8_t[trace_bytes.size()]);
-    memcpy(raw_trace.get(), trace_bytes.data(), trace_bytes.size());
-    context_.chunk_reader.reset(new ProtoTraceTokenizer(&context_));
-    auto status =
-        context_.chunk_reader->Parse(std::move(raw_trace), trace_bytes.size());
-
-    ResetTraceBuffers();
-    return status;
-  }
-
-  bool HasArg(ArgSetId set_id, StringId key_id, Variadic value) {
-    const auto& args = storage_->args();
-    auto rows =
-        std::equal_range(args.set_ids().begin(), args.set_ids().end(), set_id);
-    for (; rows.first != rows.second; rows.first++) {
-      size_t index = static_cast<size_t>(
-          std::distance(args.set_ids().begin(), rows.first));
-      if (args.keys()[index] == key_id) {
-        EXPECT_EQ(args.flat_keys()[index], key_id);
-        EXPECT_EQ(args.arg_values()[index], value);
-        if (args.flat_keys()[index] == key_id &&
-            args.arg_values()[index] == value) {
-          return true;
-        }
-      }
-    }
-    return false;
-  }
-
- protected:
-  std::unique_ptr<protozero::ScatteredHeapBuffer> heap_buf_;
-  std::unique_ptr<protozero::ScatteredStreamWriter> stream_writer_;
-  protos::pbzero::Trace trace_;
-  TraceProcessorContext context_;
-  MockEventTracker* event_;
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-  MockSchedEventTracker* sched_;
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-  MockProcessTracker* process_;
-  MockSliceTracker* slice_;
-  ClockTracker* clock_;
-  NiceMock<MockTraceStorage>* storage_;
-};
-
-// TODO(eseckler): Refactor these into a new file for ftrace tests.
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-
-TEST_F(ProtoTraceParserTest, LoadSingleEvent) {
-  auto* bundle = trace_.add_packet()->set_ftrace_events();
-  bundle->set_cpu(10);
-
-  auto* event = bundle->add_event();
-  event->set_timestamp(1000);
-  event->set_pid(12);
-
-  static const char kProc1Name[] = "proc1";
-  static const char kProc2Name[] = "proc2";
-  auto* sched_switch = event->set_sched_switch();
-  sched_switch->set_prev_pid(10);
-  sched_switch->set_prev_comm(kProc2Name);
-  sched_switch->set_prev_prio(256);
-  sched_switch->set_prev_state(32);
-  sched_switch->set_next_comm(kProc1Name);
-  sched_switch->set_next_pid(100);
-  sched_switch->set_next_prio(1024);
-
-  EXPECT_CALL(*sched_,
-              PushSchedSwitch(10, 1000, 10, base::StringView(kProc2Name), 256,
-                              32, 100, base::StringView(kProc1Name), 1024));
-  Tokenize();
-}
-
-TEST_F(ProtoTraceParserTest, LoadEventsIntoRaw) {
-  auto* bundle = trace_.add_packet()->set_ftrace_events();
-  bundle->set_cpu(10);
-
-  // This event is unknown and will only appear in
-  // raw events table.
-  auto* event = bundle->add_event();
-  event->set_timestamp(1000);
-  event->set_pid(12);
-  auto* task = event->set_task_newtask();
-  task->set_pid(123);
-  static const char task_newtask[] = "task_newtask";
-  task->set_comm(task_newtask);
-  task->set_clone_flags(12);
-  task->set_oom_score_adj(15);
-
-  // This event has specific parsing logic, but will
-  // also appear in raw events table.
-  event = bundle->add_event();
-  event->set_timestamp(1001);
-  event->set_pid(12);
-  auto* print = event->set_print();
-  print->set_ip(20);
-  static const char buf_value[] = "This is a print event";
-  print->set_buf(buf_value);
-
-  EXPECT_CALL(*storage_, InternString(base::StringView(task_newtask)))
-      .Times(AtLeast(1));
-  EXPECT_CALL(*storage_, InternString(base::StringView(buf_value)));
-  EXPECT_CALL(*process_, UpdateThread(123, 123));
-
-  Tokenize();
-
-  const auto& raw = context_.storage->raw_events();
-  ASSERT_EQ(raw.raw_event_count(), 2u);
-  const auto& args = context_.storage->args();
-  ASSERT_EQ(args.args_count(), 6u);
-  ASSERT_EQ(args.arg_values()[0].int_value, 123);
-  ASSERT_STREQ(
-      context_.storage->GetString(args.arg_values()[1].string_value).c_str(),
-      task_newtask);
-  ASSERT_EQ(args.arg_values()[2].int_value, 12);
-  ASSERT_EQ(args.arg_values()[3].int_value, 15);
-  ASSERT_EQ(args.arg_values()[4].int_value, 20);
-  ASSERT_STREQ(
-      context_.storage->GetString(args.arg_values()[5].string_value).c_str(),
-      buf_value);
-
-  // TODO(taylori): Add test ftrace event with all field types
-  // and test here.
-}
-
-TEST_F(ProtoTraceParserTest, LoadGenericFtrace) {
-  auto* packet = trace_.add_packet();
-  packet->set_timestamp(100);
-
-  auto* bundle = packet->set_ftrace_events();
-  bundle->set_cpu(4);
-
-  auto* ftrace = bundle->add_event();
-  ftrace->set_timestamp(100);
-  ftrace->set_pid(10);
-
-  auto* generic = ftrace->set_generic();
-  generic->set_event_name("Test");
-
-  auto* field = generic->add_field();
-  field->set_name("meta1");
-  field->set_str_value("value1");
-
-  field = generic->add_field();
-  field->set_name("meta2");
-  field->set_int_value(-2);
-
-  field = generic->add_field();
-  field->set_name("meta3");
-  field->set_uint_value(3);
-
-  EXPECT_CALL(*storage_, InternString(base::StringView("Test")));
-  EXPECT_CALL(*storage_, InternString(base::StringView("meta1")));
-  EXPECT_CALL(*storage_, InternString(base::StringView("value1")));
-  EXPECT_CALL(*storage_, InternString(base::StringView("meta2")));
-  EXPECT_CALL(*storage_, InternString(base::StringView("meta3")));
-
-  Tokenize();
-
-  const auto& raw = storage_->raw_events();
-
-  ASSERT_EQ(raw.raw_event_count(), 1u);
-  ASSERT_EQ(raw.timestamps().back(), 100);
-  ASSERT_EQ(storage_->GetThread(raw.utids().back()).tid, 10u);
-
-  auto set_id = raw.arg_set_ids().back();
-
-  const auto& args = storage_->args();
-  auto id_it =
-      std::equal_range(args.set_ids().begin(), args.set_ids().end(), set_id);
-
-  // Ignore string calls as they are handled by checking InternString calls
-  // above.
-
-  auto it = id_it.first;
-  auto row = static_cast<size_t>(std::distance(args.set_ids().begin(), it));
-  ASSERT_EQ(args.arg_values()[++row].int_value, -2);
-  ASSERT_EQ(args.arg_values()[++row].int_value, 3);
-}
-
-TEST_F(ProtoTraceParserTest, LoadMultipleEvents) {
-  auto* bundle = trace_.add_packet()->set_ftrace_events();
-  bundle->set_cpu(10);
-
-  auto* event = bundle->add_event();
-  event->set_timestamp(1000);
-  event->set_pid(12);
-
-  static const char kProcName1[] = "proc1";
-  static const char kProcName2[] = "proc2";
-  auto* sched_switch = event->set_sched_switch();
-  sched_switch->set_prev_pid(10);
-  sched_switch->set_prev_comm(kProcName2);
-  sched_switch->set_prev_prio(256);
-  sched_switch->set_prev_state(32);
-  sched_switch->set_next_comm(kProcName1);
-  sched_switch->set_next_pid(100);
-  sched_switch->set_next_prio(1024);
-
-  event = bundle->add_event();
-  event->set_timestamp(1001);
-  event->set_pid(12);
-
-  sched_switch = event->set_sched_switch();
-  sched_switch->set_prev_pid(100);
-  sched_switch->set_prev_comm(kProcName1);
-  sched_switch->set_prev_prio(256);
-  sched_switch->set_prev_state(32);
-  sched_switch->set_next_comm(kProcName2);
-  sched_switch->set_next_pid(10);
-  sched_switch->set_next_prio(512);
-
-  EXPECT_CALL(*sched_,
-              PushSchedSwitch(10, 1000, 10, base::StringView(kProcName2), 256,
-                              32, 100, base::StringView(kProcName1), 1024));
-
-  EXPECT_CALL(*sched_,
-              PushSchedSwitch(10, 1001, 100, base::StringView(kProcName1), 256,
-                              32, 10, base::StringView(kProcName2), 512));
-
-  Tokenize();
-}
-
-TEST_F(ProtoTraceParserTest, LoadMultiplePackets) {
-  auto* bundle = trace_.add_packet()->set_ftrace_events();
-  bundle->set_cpu(10);
-
-  auto* event = bundle->add_event();
-  event->set_timestamp(1000);
-  event->set_pid(12);
-
-  static const char kProcName1[] = "proc1";
-  static const char kProcName2[] = "proc2";
-  auto* sched_switch = event->set_sched_switch();
-  sched_switch->set_prev_pid(10);
-  sched_switch->set_prev_comm(kProcName2);
-  sched_switch->set_prev_prio(256);
-  sched_switch->set_prev_state(32);
-  sched_switch->set_next_comm(kProcName1);
-  sched_switch->set_next_pid(100);
-  sched_switch->set_next_prio(1024);
-
-  bundle = trace_.add_packet()->set_ftrace_events();
-  bundle->set_cpu(10);
-
-  event = bundle->add_event();
-  event->set_timestamp(1001);
-  event->set_pid(12);
-
-  sched_switch = event->set_sched_switch();
-  sched_switch->set_prev_pid(100);
-  sched_switch->set_prev_comm(kProcName1);
-  sched_switch->set_prev_prio(256);
-  sched_switch->set_prev_state(32);
-  sched_switch->set_next_comm(kProcName2);
-  sched_switch->set_next_pid(10);
-  sched_switch->set_next_prio(512);
-
-  EXPECT_CALL(*sched_,
-              PushSchedSwitch(10, 1000, 10, base::StringView(kProcName2), 256,
-                              32, 100, base::StringView(kProcName1), 1024));
-
-  EXPECT_CALL(*sched_,
-              PushSchedSwitch(10, 1001, 100, base::StringView(kProcName1), 256,
-                              32, 10, base::StringView(kProcName2), 512));
-  Tokenize();
-}
-
-TEST_F(ProtoTraceParserTest, RepeatedLoadSinglePacket) {
-  auto* bundle = trace_.add_packet()->set_ftrace_events();
-  bundle->set_cpu(10);
-  auto* event = bundle->add_event();
-  event->set_timestamp(1000);
-  event->set_pid(12);
-  static const char kProcName1[] = "proc1";
-  static const char kProcName2[] = "proc2";
-  auto* sched_switch = event->set_sched_switch();
-  sched_switch->set_prev_pid(10);
-  sched_switch->set_prev_comm(kProcName2);
-  sched_switch->set_prev_prio(256);
-  sched_switch->set_prev_state(32);
-  sched_switch->set_next_comm(kProcName1);
-  sched_switch->set_next_pid(100);
-  sched_switch->set_next_prio(1024);
-  EXPECT_CALL(*sched_,
-              PushSchedSwitch(10, 1000, 10, base::StringView(kProcName2), 256,
-                              32, 100, base::StringView(kProcName1), 1024));
-  Tokenize();
-
-  bundle = trace_.add_packet()->set_ftrace_events();
-  bundle->set_cpu(10);
-  event = bundle->add_event();
-  event->set_timestamp(1001);
-  event->set_pid(12);
-  sched_switch = event->set_sched_switch();
-  sched_switch->set_prev_pid(100);
-  sched_switch->set_prev_comm(kProcName1);
-  sched_switch->set_prev_prio(256);
-  sched_switch->set_prev_state(32);
-  sched_switch->set_next_comm(kProcName2);
-  sched_switch->set_next_pid(10);
-  sched_switch->set_next_prio(512);
-
-  EXPECT_CALL(*sched_,
-              PushSchedSwitch(10, 1001, 100, base::StringView(kProcName1), 256,
-                              32, 10, base::StringView(kProcName2), 512));
-  Tokenize();
-}
-
-TEST_F(ProtoTraceParserTest, LoadCpuFreq) {
-  auto* bundle = trace_.add_packet()->set_ftrace_events();
-  bundle->set_cpu(12);
-  auto* event = bundle->add_event();
-  event->set_timestamp(1000);
-  event->set_pid(12);
-  auto* cpu_freq = event->set_cpu_frequency();
-  cpu_freq->set_cpu_id(10);
-  cpu_freq->set_state(2000);
-
-  EXPECT_CALL(*event_, PushCounter(1000, DoubleEq(2000), 0));
-  Tokenize();
-
-  EXPECT_EQ(context_.storage->cpu_counter_track_table().cpu()[0], 10u);
-}
-
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_SYSTEM_PROBES)
-
-TEST_F(ProtoTraceParserTest, LoadMemInfo) {
-  auto* packet = trace_.add_packet();
-  uint64_t ts = 1000;
-  packet->set_timestamp(ts);
-  auto* bundle = packet->set_sys_stats();
-  auto* meminfo = bundle->add_meminfo();
-  meminfo->set_key(protos::pbzero::MEMINFO_MEM_TOTAL);
-  uint32_t value = 10;
-  meminfo->set_value(value);
-
-  EXPECT_CALL(*event_, PushCounter(static_cast<int64_t>(ts),
-                                   DoubleEq(value * 1024.0), 0u));
-  Tokenize();
-
-  EXPECT_EQ(context_.storage->track_table().size(), 1u);
-}
-
-TEST_F(ProtoTraceParserTest, LoadVmStats) {
-  auto* packet = trace_.add_packet();
-  uint64_t ts = 1000;
-  packet->set_timestamp(ts);
-  auto* bundle = packet->set_sys_stats();
-  auto* meminfo = bundle->add_vmstat();
-  meminfo->set_key(protos::pbzero::VMSTAT_COMPACT_SUCCESS);
-  uint32_t value = 10;
-  meminfo->set_value(value);
-
-  EXPECT_CALL(*event_,
-              PushCounter(static_cast<int64_t>(ts), DoubleEq(value), 0u));
-  Tokenize();
-
-  EXPECT_EQ(context_.storage->track_table().size(), 1u);
-}
-
-TEST_F(ProtoTraceParserTest, LoadProcessPacket) {
-  auto* tree = trace_.add_packet()->set_process_tree();
-  auto* process = tree->add_processes();
-  static const char kProcName1[] = "proc1";
-
-  process->add_cmdline(kProcName1);
-  process->set_pid(1);
-  process->set_ppid(3);
-
-  EXPECT_CALL(*process_,
-              SetProcessMetadata(1, Eq(3u), base::StringView(kProcName1)));
-  Tokenize();
-}
-
-TEST_F(ProtoTraceParserTest, LoadProcessPacket_FirstCmdline) {
-  auto* tree = trace_.add_packet()->set_process_tree();
-  auto* process = tree->add_processes();
-  static const char kProcName1[] = "proc1";
-  static const char kProcName2[] = "proc2";
-
-  process->add_cmdline(kProcName1);
-  process->add_cmdline(kProcName2);
-  process->set_pid(1);
-  process->set_ppid(3);
-
-  EXPECT_CALL(*process_,
-              SetProcessMetadata(1, Eq(3u), base::StringView(kProcName1)));
-  Tokenize();
-}
-
-TEST_F(ProtoTraceParserTest, LoadThreadPacket) {
-  auto* tree = trace_.add_packet()->set_process_tree();
-  auto* thread = tree->add_threads();
-  thread->set_tid(1);
-  thread->set_tgid(2);
-
-  EXPECT_CALL(*process_, UpdateThread(1, 2));
-  Tokenize();
-}
-
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_SYSTEM_PROBES)
-
-TEST_F(ProtoTraceParserTest, ThreadNameFromThreadDescriptor) {
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_incremental_state_cleared(true);
-    auto* thread_desc = packet->set_thread_descriptor();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(16);
-    thread_desc->set_reference_timestamp_us(1000);
-    thread_desc->set_reference_thread_time_us(2000);
-    thread_desc->set_thread_name("OldThreadName");
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_incremental_state_cleared(true);
-    auto* thread_desc = packet->set_thread_descriptor();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(16);
-    thread_desc->set_reference_timestamp_us(1000);
-    thread_desc->set_reference_thread_time_us(2000);
-    thread_desc->set_thread_name("NewThreadName");
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(2);
-    packet->set_incremental_state_cleared(true);
-    auto* thread_desc = packet->set_thread_descriptor();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(11);
-    thread_desc->set_reference_timestamp_us(1000);
-    thread_desc->set_reference_thread_time_us(2000);
-    thread_desc->set_thread_name("DifferentThreadName");
-  }
-
-  EXPECT_CALL(*process_, UpdateThread(16, 15))
-      .WillRepeatedly(testing::Return(1u));
-  EXPECT_CALL(*process_, UpdateThread(11, 15)).WillOnce(testing::Return(2u));
-
-  EXPECT_CALL(*storage_, InternString(base::StringView("OldThreadName")))
-      .WillOnce(Return(1));
-  EXPECT_CALL(*process_, SetThreadNameIfUnset(1u, StringId(1)));
-  // Packet with same thread, but different name should update the name.
-  EXPECT_CALL(*storage_, InternString(base::StringView("NewThreadName")))
-      .WillOnce(Return(2));
-  EXPECT_CALL(*process_, SetThreadNameIfUnset(1u, StringId(2)));
-  EXPECT_CALL(*storage_, InternString(base::StringView("DifferentThreadName")))
-      .WillOnce(Return(3));
-  EXPECT_CALL(*process_, SetThreadNameIfUnset(2u, StringId(3)));
-
-  Tokenize();
-  context_.sorter->ExtractEventsForced();
-}
-
-TEST_F(ProtoTraceParserTest, TrackEventWithoutInternedData) {
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_incremental_state_cleared(true);
-    auto* thread_desc = packet->set_thread_descriptor();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(16);
-    thread_desc->set_reference_timestamp_us(1000);
-    thread_desc->set_reference_thread_time_us(2000);
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);   // absolute: 1010.
-    event->set_thread_time_delta_us(5);  // absolute: 2005.
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('B');
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);   // absolute: 1020.
-    event->set_thread_time_delta_us(5);  // absolute: 2010.
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('E');
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_absolute_us(1005);
-    event->set_thread_time_absolute_us(2003);
-    event->add_category_iids(2);
-    event->add_category_iids(3);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(2);
-    legacy_event->set_phase('X');
-    legacy_event->set_duration_us(23);         // absolute end: 1028.
-    legacy_event->set_thread_duration_us(12);  // absolute end: 2015.
-  }
-
-  Tokenize();
-
-  EXPECT_CALL(*process_, UpdateThread(16, 15))
-      .Times(3)
-      .WillRepeatedly(Return(1));
-
-  TraceStorage::Thread thread(16);
-  thread.upid = 1u;
-  EXPECT_CALL(*storage_, GetThread(1))
-      .Times(3)
-      .WillRepeatedly(testing::ReturnRef(thread));
-
-  MockArgsTracker args(&context_);
-
-  constexpr TrackId track = 0u;
-  InSequence in_sequence;  // Below slices should be sorted by timestamp.
-  EXPECT_CALL(*slice_, Scoped(1005000, track, 1, RefType::kRefUtid,
-                              kNullStringId, kNullStringId, 23000, _))
-      .WillOnce(DoAll(
-          InvokeArgument<7>(
-              &args, TraceStorage::CreateRowId(TableId::kNestableSlices, 0u)),
-          Return(0u)));
-  EXPECT_CALL(*slice_, Begin(1010000, track, 1, RefType::kRefUtid,
-                             kNullStringId, kNullStringId, _))
-      .WillOnce(DoAll(
-          InvokeArgument<6>(
-              &args, TraceStorage::CreateRowId(TableId::kNestableSlices, 1u)),
-          Return(1u)));
-  EXPECT_CALL(*slice_, End(1020000, track, kNullStringId, kNullStringId, _))
-      .WillOnce(DoAll(
-          InvokeArgument<4>(
-              &args, TraceStorage::CreateRowId(TableId::kNestableSlices, 1u)),
-          Return(1u)));
-
-  context_.sorter->ExtractEventsForced();
-
-  EXPECT_EQ(storage_->thread_slices().slice_count(), 2u);
-  EXPECT_EQ(storage_->thread_slices().slice_ids()[0], 0u);
-  EXPECT_EQ(storage_->thread_slices().thread_timestamp_ns()[0], 2003000);
-  EXPECT_EQ(storage_->thread_slices().thread_duration_ns()[0], 12000);
-  EXPECT_EQ(storage_->thread_slices().slice_ids()[1], 1u);
-  EXPECT_EQ(storage_->thread_slices().thread_timestamp_ns()[1], 2005000);
-  EXPECT_EQ(storage_->thread_slices().thread_duration_ns()[1], 5000);
-}
-
-TEST_F(ProtoTraceParserTest, TrackEventWithoutInternedDataWithTypes) {
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_incremental_state_cleared(true);
-    auto* thread_desc = packet->set_thread_descriptor();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(16);
-    thread_desc->set_reference_timestamp_us(1000);
-    thread_desc->set_reference_thread_time_us(2000);
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);   // absolute: 1010.
-    event->set_thread_time_delta_us(5);  // absolute: 2005.
-    event->add_category_iids(1);
-    event->set_type(protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);   // absolute: 1020.
-    event->set_thread_time_delta_us(5);  // absolute: 2010.
-    event->add_category_iids(1);
-    event->set_type(protos::pbzero::TrackEvent::TYPE_SLICE_END);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_absolute_us(1015);
-    event->set_thread_time_absolute_us(2007);
-    event->add_category_iids(2);
-    event->set_type(protos::pbzero::TrackEvent::TYPE_INSTANT);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(2);
-  }
-
-  Tokenize();
-
-  EXPECT_CALL(*process_, UpdateThread(16, 15))
-      .Times(3)
-      .WillRepeatedly(Return(1));
-
-  TraceStorage::Thread thread(16);
-  thread.upid = 1u;
-  EXPECT_CALL(*storage_, GetThread(1))
-      .Times(3)
-      .WillRepeatedly(testing::ReturnRef(thread));
-
-  MockArgsTracker args(&context_);
-
-  constexpr TrackId track = 0u;
-  InSequence in_sequence;  // Below slices should be sorted by timestamp.
-  EXPECT_CALL(*slice_, Begin(1010000, track, 1, RefType::kRefUtid,
-                             kNullStringId, kNullStringId, _))
-      .WillOnce(DoAll(
-          InvokeArgument<6>(
-              &args, TraceStorage::CreateRowId(TableId::kNestableSlices, 0u)),
-          Return(0u)));
-  EXPECT_CALL(*slice_, Scoped(1015000, track, 1, RefType::kRefUtid,
-                              kNullStringId, kNullStringId, 0, _))
-      .WillOnce(DoAll(
-          InvokeArgument<7>(
-              &args, TraceStorage::CreateRowId(TableId::kNestableSlices, 1u)),
-          Return(1u)));
-  EXPECT_CALL(*slice_, End(1020000, track, kNullStringId, kNullStringId, _))
-      .WillOnce(DoAll(
-          InvokeArgument<4>(
-              &args, TraceStorage::CreateRowId(TableId::kNestableSlices, 0u)),
-          Return(0u)));
-
-  context_.sorter->ExtractEventsForced();
-
-  EXPECT_EQ(storage_->thread_slices().slice_count(), 2u);
-  EXPECT_EQ(storage_->thread_slices().slice_ids()[0], 0u);
-  EXPECT_EQ(storage_->thread_slices().thread_timestamp_ns()[0], 2005000);
-  EXPECT_EQ(storage_->thread_slices().thread_duration_ns()[0], 5000);
-  EXPECT_EQ(storage_->thread_slices().slice_ids()[1], 1u);
-  EXPECT_EQ(storage_->thread_slices().thread_timestamp_ns()[1], 2007000);
-  EXPECT_EQ(storage_->thread_slices().thread_duration_ns()[1], 0);
-}
-
-TEST_F(ProtoTraceParserTest, TrackEventWithInternedData) {
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_incremental_state_cleared(true);
-    auto* thread_desc = packet->set_thread_descriptor();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(16);
-    thread_desc->set_reference_timestamp_us(1000);
-    thread_desc->set_reference_thread_time_us(2000);
-    thread_desc->set_reference_thread_instruction_count(3000);
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);              // absolute: 1010.
-    event->set_thread_time_delta_us(5);             // absolute: 2005.
-    event->set_thread_instruction_count_delta(20);  // absolute: 3020.
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('B');
-
-    auto* interned_data = packet->set_interned_data();
-    auto cat1 = interned_data->add_event_categories();
-    cat1->set_iid(1);
-    cat1->set_name("cat1");
-    auto ev1 = interned_data->add_event_names();
-    ev1->set_iid(1);
-    ev1->set_name("ev1");
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_absolute_us(1040);
-    event->set_thread_time_absolute_us(2030);
-    event->set_thread_instruction_count_absolute(3100);
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('I');
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_absolute_us(1050);
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('i');
-    legacy_event->set_instant_event_scope(
-        protos::pbzero::TrackEvent::LegacyEvent::SCOPE_PROCESS);
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);              // absolute: 1020.
-    event->set_thread_time_delta_us(5);             // absolute: 2010.
-    event->set_thread_instruction_count_delta(20);  // absolute: 3040.
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('E');
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_absolute_us(1005);
-    event->set_thread_time_absolute_us(2003);
-    event->set_thread_instruction_count_absolute(3010);
-    event->add_category_iids(2);
-    event->add_category_iids(3);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(4);
-    legacy_event->set_phase('X');
-    legacy_event->set_duration_us(23);               // absolute end: 1028.
-    legacy_event->set_thread_duration_us(12);        // absolute end: 2015.
-    legacy_event->set_thread_instruction_delta(50);  // absolute end: 3060.
-    legacy_event->set_bind_id(9999);
-    legacy_event->set_bind_to_enclosing(true);
-    legacy_event->set_flow_direction(
-        protos::pbzero::TrackEvent::LegacyEvent::FLOW_INOUT);
-
-    auto* interned_data = packet->set_interned_data();
-    auto cat2 = interned_data->add_event_categories();
-    cat2->set_iid(2);
-    cat2->set_name("cat2");
-    auto cat3 = interned_data->add_event_categories();
-    cat3->set_iid(3);
-    cat3->set_name("cat3");
-    auto ev2 = interned_data->add_event_names();
-    ev2->set_iid(4);
-    ev2->set_name("ev2");
-  }
-
-  Tokenize();
-
-  EXPECT_CALL(*process_, UpdateThread(16, 15))
-      .Times(5)
-      .WillRepeatedly(Return(1));
-
-  TraceStorage::Thread thread(16);
-  thread.upid = 2u;
-  EXPECT_CALL(*storage_, GetThread(1))
-      .WillRepeatedly(testing::ReturnRef(thread));
-
-  MockArgsTracker args(&context_);
-
-  constexpr TrackId thread_1_track = 0u;
-  constexpr TrackId process_2_track = 1u;
-
-  EXPECT_CALL(*storage_, InternString(base::StringView("cat2,cat3")))
-      .WillOnce(Return(1));
-  EXPECT_CALL(*storage_, InternString(base::StringView("ev2")))
-      .WillOnce(Return(2));
-  EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
-      .WillRepeatedly(Return(3));
-  EXPECT_CALL(*storage_, InternString(base::StringView("ev1")))
-      .WillRepeatedly(Return(4));
-
-  InSequence in_sequence;  // Below slices should be sorted by timestamp.
-
-  RowId first_slice_row_id =
-      TraceStorage::CreateRowId(TableId::kNestableSlices, 0u);
-  EXPECT_CALL(*slice_, Scoped(1005000, thread_1_track, 1, RefType::kRefUtid,
-                              StringId(1), StringId(2), 23000, _))
-      .WillOnce(
-          DoAll(InvokeArgument<7>(&args, first_slice_row_id), Return(0u)));
-  EXPECT_CALL(
-      args, AddArg(first_slice_row_id, _, _, Variadic::UnsignedInteger(9999u)));
-  EXPECT_CALL(args, AddArg(first_slice_row_id, _, _, Variadic::Boolean(true)));
-  EXPECT_CALL(args, AddArg(first_slice_row_id, _, _, _));
-
-  EXPECT_CALL(*slice_, Begin(1010000, thread_1_track, 1, RefType::kRefUtid,
-                             StringId(3), StringId(4), _))
-      .WillOnce(DoAll(
-          InvokeArgument<6>(
-              &args, TraceStorage::CreateRowId(TableId::kNestableSlices, 1u)),
-          Return(1u)));
-
-  EXPECT_CALL(*slice_,
-              End(1020000, thread_1_track, StringId(3), StringId(4), _))
-      .WillOnce(DoAll(
-          InvokeArgument<4>(
-              &args, TraceStorage::CreateRowId(TableId::kNestableSlices, 1u)),
-          Return(1u)));
-
-  EXPECT_CALL(*slice_, Scoped(1040000, thread_1_track, 1, RefType::kRefUtid,
-                              StringId(3), StringId(4), 0, _))
-      .WillOnce(DoAll(
-          InvokeArgument<7>(
-              &args, TraceStorage::CreateRowId(TableId::kNestableSlices, 2u)),
-          Return(2u)));
-
-  RowId last_slice_row_id =
-      TraceStorage::CreateRowId(TableId::kNestableSlices, 3u);
-  EXPECT_CALL(*slice_, Scoped(1050000, process_2_track, 2, RefType::kRefUpid,
-                              StringId(3), StringId(4), 0, _))
-      .WillOnce(DoAll(InvokeArgument<7>(&args, last_slice_row_id), Return(3u)));
-  // Second slice should have a legacy_event.original_tid arg.
-  EXPECT_CALL(args, AddArg(last_slice_row_id, _, _, Variadic::Integer(16)));
-
-  context_.sorter->ExtractEventsForced();
-
-  EXPECT_EQ(storage_->thread_slices().slice_count(), 3u);
-  EXPECT_EQ(storage_->thread_slices().slice_ids()[0], 0u);
-  EXPECT_EQ(storage_->thread_slices().thread_timestamp_ns()[0], 2003000);
-  EXPECT_EQ(storage_->thread_slices().thread_duration_ns()[0], 12000);
-  EXPECT_EQ(storage_->thread_slices().thread_instruction_counts()[0], 3010);
-  EXPECT_EQ(storage_->thread_slices().thread_instruction_deltas()[0], 50);
-  EXPECT_EQ(storage_->thread_slices().slice_ids()[1], 1u);
-  EXPECT_EQ(storage_->thread_slices().thread_timestamp_ns()[1], 2005000);
-  EXPECT_EQ(storage_->thread_slices().thread_duration_ns()[1], 5000);
-  EXPECT_EQ(storage_->thread_slices().thread_instruction_counts()[1], 3020);
-  EXPECT_EQ(storage_->thread_slices().thread_instruction_deltas()[1], 20);
-  EXPECT_EQ(storage_->thread_slices().slice_ids()[2], 2u);
-  EXPECT_EQ(storage_->thread_slices().thread_timestamp_ns()[2], 2030000);
-  EXPECT_EQ(storage_->thread_slices().thread_duration_ns()[2], 0);
-  EXPECT_EQ(storage_->thread_slices().thread_instruction_counts()[2], 3100);
-  EXPECT_EQ(storage_->thread_slices().thread_instruction_deltas()[2], 0);
-}
-
-TEST_F(ProtoTraceParserTest, TrackEventAsyncEvents) {
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_incremental_state_cleared(true);
-    auto* thread_desc = packet->set_thread_descriptor();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(16);
-    thread_desc->set_reference_timestamp_us(1000);
-    thread_desc->set_reference_thread_time_us(2000);
-    thread_desc->set_reference_thread_instruction_count(3000);
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);              // absolute: 1010.
-    event->set_thread_time_delta_us(5);             // absolute: 2005.
-    event->set_thread_instruction_count_delta(20);  // absolute: 3020.
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('b');
-    legacy_event->set_global_id(10);
-    legacy_event->set_use_async_tts(true);
-
-    auto* interned_data = packet->set_interned_data();
-    auto cat1 = interned_data->add_event_categories();
-    cat1->set_iid(1);
-    cat1->set_name("cat1");
-    auto ev1 = interned_data->add_event_names();
-    ev1->set_iid(1);
-    ev1->set_name("ev1");
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);              // absolute: 1020.
-    event->set_thread_time_delta_us(5);             // absolute: 2010.
-    event->set_thread_instruction_count_delta(20);  // absolute: 3040.
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('e');
-    legacy_event->set_global_id(10);
-    legacy_event->set_use_async_tts(true);
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_absolute_us(1015);
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(2);
-    legacy_event->set_phase('n');
-    legacy_event->set_global_id(10);
-
-    auto* interned_data = packet->set_interned_data();
-    auto ev2 = interned_data->add_event_names();
-    ev2->set_iid(2);
-    ev2->set_name("ev2");
-  }
-  {
-    // Different category but same global_id -> separate track.
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_absolute_us(1018);
-    event->add_category_iids(2);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(2);
-    legacy_event->set_phase('n');
-    legacy_event->set_global_id(15);
-
-    auto* interned_data = packet->set_interned_data();
-    auto cat2 = interned_data->add_event_categories();
-    cat2->set_iid(2);
-    cat2->set_name("cat2");
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_absolute_us(1030);
-    event->add_category_iids(2);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(2);
-    legacy_event->set_phase('n');
-    legacy_event->set_local_id(15);
-    legacy_event->set_id_scope("scope1");
-  }
-
-  Tokenize();
-
-  EXPECT_CALL(*process_, UpdateThread(16, 15)).WillRepeatedly(Return(1));
-
-  TraceStorage::Thread thread(16);
-  thread.upid = 1u;
-  EXPECT_CALL(*storage_, GetThread(1))
-      .WillRepeatedly(testing::ReturnRef(thread));
-
-  EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
-      .WillRepeatedly(Return(1));
-  EXPECT_CALL(*storage_, InternString(base::StringView("ev1")))
-      .WillRepeatedly(Return(2));
-  EXPECT_CALL(*storage_, InternString(base::StringView("ev2")))
-      .WillRepeatedly(Return(4));
-  EXPECT_CALL(*storage_, InternString(base::StringView("cat2")))
-      .WillRepeatedly(Return(3));
-  EXPECT_CALL(*storage_, InternString(base::StringView("cat2:scope1")))
-      .WillOnce(Return(5));
-  EXPECT_CALL(*storage_, GetString(StringId(1))).WillRepeatedly(Return("cat1"));
-  EXPECT_CALL(*storage_, GetString(StringId(3))).WillRepeatedly(Return("cat2"));
-
-  InSequence in_sequence;  // Below slices should be sorted by timestamp.
-
-  EXPECT_CALL(*slice_, Begin(1010000, 1, 1, RefType::kRefTrack, StringId(1),
-                             StringId(2), _))
-      .WillOnce(Return(0u));
-  EXPECT_CALL(*slice_, Scoped(1015000, 1, 1, RefType::kRefTrack, StringId(1),
-                              StringId(4), 0, _));
-  EXPECT_CALL(*slice_, Scoped(1018000, 2, 2, RefType::kRefTrack, StringId(3),
-                              StringId(4), 0, _));
-  EXPECT_CALL(*slice_, End(1020000, 1, StringId(1), StringId(2), _))
-      .WillOnce(Return(0u));
-  EXPECT_CALL(*slice_, Scoped(1030000, 3, 3, RefType::kRefTrack, StringId(3),
-                              StringId(4), 0, _));
-
-  context_.sorter->ExtractEventsForced();
-
-  // First track is for the thread; others are the async event tracks.
-  EXPECT_EQ(storage_->track_table().size(), 4u);
-  EXPECT_EQ(storage_->track_table().name()[1], 2u);
-  EXPECT_EQ(storage_->track_table().name()[2], 4u);
-  EXPECT_EQ(storage_->track_table().name()[3], 4u);
-
-  EXPECT_EQ(storage_->process_track_table().size(), 3u);
-  EXPECT_EQ(storage_->process_track_table().upid()[0], 1u);
-  EXPECT_EQ(storage_->process_track_table().upid()[1], 1u);
-  EXPECT_EQ(storage_->process_track_table().upid()[2], 1u);
-
-  EXPECT_EQ(storage_->virtual_track_slices().slice_count(), 1u);
-  EXPECT_EQ(storage_->virtual_track_slices().slice_ids()[0], 0u);
-  EXPECT_EQ(storage_->virtual_track_slices().thread_timestamp_ns()[0], 2005000);
-  EXPECT_EQ(storage_->virtual_track_slices().thread_duration_ns()[0], 5000);
-  EXPECT_EQ(storage_->virtual_track_slices().thread_instruction_counts()[0],
-            3020);
-  EXPECT_EQ(storage_->virtual_track_slices().thread_instruction_deltas()[0],
-            20);
-}
-
-// TODO(eseckler): Also test instant events on separate tracks.
-TEST_F(ProtoTraceParserTest, TrackEventWithTrackDescriptors) {
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-
-  // Sequence 1.
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_incremental_state_cleared(true);
-    auto* track_desc = packet->set_track_descriptor();
-    track_desc->set_uuid(1234);
-    track_desc->set_name("Thread track 1");
-    auto* thread_desc = track_desc->set_thread();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(16);
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* track_desc = packet->set_track_descriptor();
-    track_desc->set_uuid(5678);
-    track_desc->set_name("Async track 1");
-  }
-  {
-    // Async event started on "Async track 1".
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_timestamp(1010000);
-    auto* event = packet->set_track_event();
-    event->set_track_uuid(5678);
-    event->set_thread_time_absolute_us(2005);
-    event->set_thread_instruction_count_absolute(3020);
-    event->add_category_iids(1);
-    event->set_name_iid(1);
-    event->set_type(protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_use_async_tts(true);
-
-    auto* interned_data = packet->set_interned_data();
-    auto cat1 = interned_data->add_event_categories();
-    cat1->set_iid(1);
-    cat1->set_name("cat1");
-    auto ev1 = interned_data->add_event_names();
-    ev1->set_iid(1);
-    ev1->set_name("ev1");
-  }
-  {
-    // Instant event on "Thread track 1".
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_timestamp(1015000);
-    auto* event = packet->set_track_event();
-    event->set_track_uuid(1234);
-    event->set_thread_time_absolute_us(2007);
-    event->add_category_iids(2);
-    event->set_name_iid(2);
-    event->set_type(protos::pbzero::TrackEvent::TYPE_INSTANT);
-
-    auto* interned_data = packet->set_interned_data();
-    auto cat1 = interned_data->add_event_categories();
-    cat1->set_iid(2);
-    cat1->set_name("cat2");
-    auto ev1 = interned_data->add_event_names();
-    ev1->set_iid(2);
-    ev1->set_name("ev2");
-  }
-
-  // Sequence 2.
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(2);
-    packet->set_incremental_state_cleared(true);
-    auto* track_desc = packet->set_track_descriptor();
-    track_desc->set_uuid(4321);
-    track_desc->set_name("Thread track 2");
-    auto* thread_desc = track_desc->set_thread();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(17);
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(2);
-    auto* track_desc = packet->set_track_descriptor();
-    track_desc->set_uuid(5678);  // "Async track 1" defined on sequence 1.
-  }
-  {
-    // Async event completed on "Async track 1".
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(2);
-    packet->set_timestamp(1020000);
-    auto* event = packet->set_track_event();
-    event->set_track_uuid(5678);
-    event->set_thread_time_absolute_us(2010);
-    event->set_thread_instruction_count_absolute(3040);
-    event->set_type(protos::pbzero::TrackEvent::TYPE_SLICE_END);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_use_async_tts(true);
-  }
-  {
-    // Instant event on "Thread track 2".
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(2);
-    packet->set_timestamp(1016000);
-    auto* event = packet->set_track_event();
-    event->set_track_uuid(4321);
-    event->set_thread_time_absolute_us(2008);
-    event->add_category_iids(1);
-    event->set_name_iid(1);
-    event->set_type(protos::pbzero::TrackEvent::TYPE_INSTANT);
-
-    auto* interned_data = packet->set_interned_data();
-    auto cat1 = interned_data->add_event_categories();
-    cat1->set_iid(1);
-    cat1->set_name("cat3");
-    auto ev1 = interned_data->add_event_names();
-    ev1->set_iid(1);
-    ev1->set_name("ev3");
-  }
-
-  EXPECT_CALL(*process_, UpdateThread(16, 15)).WillRepeatedly(Return(1));
-  EXPECT_CALL(*process_, UpdateThread(17, 15)).WillRepeatedly(Return(2));
-
-  TraceStorage::Thread thread1(16);
-  thread1.upid = 1u;
-  EXPECT_CALL(*storage_, GetThread(1))
-      .WillRepeatedly(testing::ReturnRef(thread1));
-  TraceStorage::Thread thread2(16);
-  thread2.upid = 2u;
-  EXPECT_CALL(*storage_, GetThread(2))
-      .WillRepeatedly(testing::ReturnRef(thread2));
-
-  EXPECT_CALL(*storage_, InternString(base::StringView("Thread track 1")))
-      .WillOnce(Return(10));
-  EXPECT_CALL(*storage_, InternString(base::StringView("Async track 1")))
-      .WillOnce(Return(11));
-  EXPECT_CALL(*storage_, InternString(base::StringView("Thread track 2")))
-      .WillOnce(Return(12));
-  EXPECT_CALL(*storage_, InternString(base::StringView("")))
-      .WillOnce(Return(0));
-
-  Tokenize();
-
-  // First track is "Thread track 1"; second is "Async track 1", third is
-  // "Thread track 2".
-  EXPECT_EQ(storage_->track_table().size(), 3u);
-  EXPECT_EQ(storage_->track_table().name()[0], 10u);  // "Thread track 1"
-  EXPECT_EQ(storage_->track_table().name()[1], 11u);  // "Async track 1"
-  EXPECT_EQ(storage_->track_table().name()[2], 12u);  // "Thread track 2"
-  EXPECT_EQ(storage_->thread_track_table().size(), 2u);
-  EXPECT_EQ(storage_->thread_track_table().utid()[0], 1u);
-  EXPECT_EQ(storage_->thread_track_table().utid()[1], 2u);
-
-  InSequence in_sequence;  // Below slices should be sorted by timestamp.
-
-  EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
-      .WillOnce(Return(1));
-  EXPECT_CALL(*storage_, InternString(base::StringView("ev1")))
-      .WillOnce(Return(2));
-  EXPECT_CALL(*slice_, Begin(1010000, 1, 1, RefType::kRefTrack, StringId(1),
-                             StringId(2), _))
-      .WillOnce(Return(0u));
-
-  EXPECT_CALL(*storage_, InternString(base::StringView("cat2")))
-      .WillOnce(Return(3));
-  EXPECT_CALL(*storage_, InternString(base::StringView("ev2")))
-      .WillOnce(Return(4));
-  EXPECT_CALL(*slice_, Scoped(1015000, 0, 1, RefType::kRefUtid, StringId(3),
-                              StringId(4), 0, _))
-      .WillOnce(Return(1u));
-
-  EXPECT_CALL(*storage_, InternString(base::StringView("cat3")))
-      .WillOnce(Return(5));
-  EXPECT_CALL(*storage_, InternString(base::StringView("ev3")))
-      .WillOnce(Return(6));
-  EXPECT_CALL(*slice_, Scoped(1016000, 2, 2, RefType::kRefUtid, StringId(5),
-                              StringId(6), 0, _))
-      .WillOnce(Return(2u));
-
-  EXPECT_CALL(*slice_, End(1020000, 1, StringId(0), StringId(0), _))
-      .WillOnce(Return(0u));
-
-  context_.sorter->ExtractEventsForced();
-
-  // Track tables shouldn't have changed.
-  EXPECT_EQ(storage_->track_table().size(), 3u);
-  EXPECT_EQ(storage_->thread_track_table().size(), 2u);
-
-  EXPECT_EQ(storage_->virtual_track_slices().slice_count(), 1u);
-  EXPECT_EQ(storage_->virtual_track_slices().slice_ids()[0], 0u);
-  EXPECT_EQ(storage_->virtual_track_slices().thread_timestamp_ns()[0], 2005000);
-  EXPECT_EQ(storage_->virtual_track_slices().thread_duration_ns()[0], 5000);
-  EXPECT_EQ(storage_->virtual_track_slices().thread_instruction_counts()[0],
-            3020);
-  EXPECT_EQ(storage_->virtual_track_slices().thread_instruction_deltas()[0],
-            20);
-
-  EXPECT_EQ(storage_->thread_slices().slice_count(), 2u);
-  EXPECT_EQ(storage_->thread_slices().slice_ids()[0], 1u);
-  EXPECT_EQ(storage_->thread_slices().thread_timestamp_ns()[0], 2007000);
-  EXPECT_EQ(storage_->thread_slices().thread_duration_ns()[0], 0);
-  EXPECT_EQ(storage_->thread_slices().thread_instruction_counts()[0], 0);
-  EXPECT_EQ(storage_->thread_slices().thread_instruction_deltas()[0], 0);
-  EXPECT_EQ(storage_->thread_slices().slice_ids()[1], 2u);
-  EXPECT_EQ(storage_->thread_slices().thread_timestamp_ns()[1], 2008000);
-  EXPECT_EQ(storage_->thread_slices().thread_duration_ns()[1], 0);
-  EXPECT_EQ(storage_->thread_slices().thread_instruction_counts()[1], 0);
-  EXPECT_EQ(storage_->thread_slices().thread_instruction_deltas()[1], 0);
-}
-
-TEST_F(ProtoTraceParserTest, TrackEventWithoutIncrementalStateReset) {
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* thread_desc = packet->set_thread_descriptor();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(16);
-    thread_desc->set_reference_timestamp_us(1000);
-    thread_desc->set_reference_thread_time_us(2000);
-  }
-  {
-    // Event should be discarded because incremental state was never cleared.
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);   // absolute: 1010.
-    event->set_thread_time_delta_us(5);  // absolute: 2005.
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('B');
-  }
-
-  Tokenize();
-
-  EXPECT_CALL(*slice_, Begin(_, _, _, _, _, _, _)).Times(0);
-  context_.sorter->ExtractEventsForced();
-}
-
-TEST_F(ProtoTraceParserTest, TrackEventWithoutThreadDescriptor) {
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-
-  {
-    // Event should be discarded because no thread descriptor was seen yet.
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_incremental_state_cleared(true);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);
-    event->set_thread_time_delta_us(5);
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('B');
-  }
-
-  Tokenize();
-
-  EXPECT_CALL(*slice_, Begin(_, _, _, _, _, _, _)).Times(0);
-  context_.sorter->ExtractEventsForced();
-}
-
-TEST_F(ProtoTraceParserTest, TrackEventWithDataLoss) {
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_incremental_state_cleared(true);
-    auto* thread_desc = packet->set_thread_descriptor();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(16);
-    thread_desc->set_reference_timestamp_us(1000);
-    thread_desc->set_reference_thread_time_us(2000);
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);   // absolute: 1010.
-    event->set_thread_time_delta_us(5);  // absolute: 2005.
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('B');
-  }
-  {
-    // Event should be dropped because data loss occurred before.
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_previous_packet_dropped(true);  // Data loss occurred.
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);
-    event->set_thread_time_delta_us(5);
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('E');
-  }
-  {
-    // Event should be dropped because incremental state is invalid.
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);
-    event->set_thread_time_delta_us(5);
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('E');
-  }
-  {
-    // Event should be dropped because no new thread descriptor was seen yet.
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_incremental_state_cleared(true);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);
-    event->set_thread_time_delta_us(5);
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('E');
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* thread_desc = packet->set_thread_descriptor();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(16);
-    thread_desc->set_reference_timestamp_us(2000);
-    thread_desc->set_reference_thread_time_us(3000);
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);   // absolute: 2010.
-    event->set_thread_time_delta_us(5);  // absolute: 3005.
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('E');
-  }
-
-  Tokenize();
-
-  EXPECT_CALL(*process_, UpdateThread(16, 15))
-      .Times(2)
-      .WillRepeatedly(Return(1));
-
-  TraceStorage::Thread thread(16);
-  thread.upid = 1u;
-  EXPECT_CALL(*storage_, GetThread(1))
-      .Times(2)
-      .WillRepeatedly(testing::ReturnRef(thread));
-
-  constexpr TrackId track = 0u;
-  InSequence in_sequence;  // Below slices should be sorted by timestamp.
-  EXPECT_CALL(*slice_, Begin(1010000, track, 1, RefType::kRefUtid,
-                             kNullStringId, kNullStringId, _));
-  EXPECT_CALL(*slice_, End(2010000, track, kNullStringId, kNullStringId, _));
-
-  context_.sorter->ExtractEventsForced();
-}
-
-TEST_F(ProtoTraceParserTest, TrackEventMultipleSequences) {
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_incremental_state_cleared(true);
-    auto* thread_desc = packet->set_thread_descriptor();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(16);
-    thread_desc->set_reference_timestamp_us(1000);
-    thread_desc->set_reference_thread_time_us(2000);
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);   // absolute: 1010.
-    event->set_thread_time_delta_us(5);  // absolute: 2005.
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('B');
-
-    auto* interned_data = packet->set_interned_data();
-    auto cat1 = interned_data->add_event_categories();
-    cat1->set_iid(1);
-    cat1->set_name("cat1");
-    auto ev1 = interned_data->add_event_names();
-    ev1->set_iid(1);
-    ev1->set_name("ev1");
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(2);
-    packet->set_incremental_state_cleared(true);
-    auto* thread_desc = packet->set_thread_descriptor();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(17);
-    thread_desc->set_reference_timestamp_us(995);
-    thread_desc->set_reference_thread_time_us(3000);
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(2);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);   // absolute: 1005.
-    event->set_thread_time_delta_us(5);  // absolute: 3005.
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('B');
-
-    auto* interned_data = packet->set_interned_data();
-    auto cat1 = interned_data->add_event_categories();
-    cat1->set_iid(1);
-    cat1->set_name("cat1");
-    auto ev2 = interned_data->add_event_names();
-    ev2->set_iid(1);
-    ev2->set_name("ev2");
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);   // absolute: 1020.
-    event->set_thread_time_delta_us(5);  // absolute: 2010.
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('E');
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(2);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);   // absolute: 1015.
-    event->set_thread_time_delta_us(5);  // absolute: 3015.
-    event->add_category_iids(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('E');
-  }
-
-  Tokenize();
-
-  EXPECT_CALL(*process_, UpdateThread(16, 15))
-      .Times(2)
-      .WillRepeatedly(Return(1));
-  EXPECT_CALL(*process_, UpdateThread(17, 15))
-      .Times(2)
-      .WillRepeatedly(Return(2));
-
-  TraceStorage::Thread thread(16);
-  thread.upid = 1u;
-  EXPECT_CALL(*storage_, GetThread(1))
-      .Times(2)
-      .WillRepeatedly(testing::ReturnRef(thread));
-
-  TraceStorage::Thread thread2(17);
-  thread2.upid = 1u;
-  EXPECT_CALL(*storage_, GetThread(2))
-      .Times(2)
-      .WillRepeatedly(testing::ReturnRef(thread2));
-
-  EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
-      .WillRepeatedly(Return(1));
-  EXPECT_CALL(*storage_, InternString(base::StringView("ev2")))
-      .WillRepeatedly(Return(2));
-  EXPECT_CALL(*storage_, InternString(base::StringView("ev1")))
-      .WillRepeatedly(Return(3));
-
-  constexpr TrackId thread_2_track = 0u;
-  constexpr TrackId thread_1_track = 1u;
-  InSequence in_sequence;  // Below slices should be sorted by timestamp.
-
-  EXPECT_CALL(*slice_, Begin(1005000, thread_2_track, 2, RefType::kRefUtid,
-                             StringId(1), StringId(2), _));
-  EXPECT_CALL(*slice_, Begin(1010000, thread_1_track, 1, RefType::kRefUtid,
-                             StringId(1), StringId(3), _));
-  EXPECT_CALL(*slice_,
-              End(1015000, thread_2_track, StringId(1), StringId(2), _));
-  EXPECT_CALL(*slice_,
-              End(1020000, thread_1_track, StringId(1), StringId(3), _));
-
-  context_.sorter->ExtractEventsForced();
-}
-
-TEST_F(ProtoTraceParserTest, TrackEventWithDebugAnnotations) {
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-  MockArgsTracker args(&context_);
-
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_incremental_state_cleared(true);
-    auto* thread_desc = packet->set_thread_descriptor();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(16);
-    thread_desc->set_reference_timestamp_us(1000);
-    thread_desc->set_reference_thread_time_us(2000);
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);   // absolute: 1010.
-    event->set_thread_time_delta_us(5);  // absolute: 2005.
-    event->add_category_iids(1);
-    auto* annotation1 = event->add_debug_annotations();
-    annotation1->set_name_iid(1);
-    annotation1->set_uint_value(10u);
-    auto* annotation2 = event->add_debug_annotations();
-    annotation2->set_name_iid(2);
-    auto* nested = annotation2->set_nested_value();
-    nested->set_nested_type(protos::pbzero::DebugAnnotation::NestedValue::DICT);
-    nested->add_dict_keys("child1");
-    nested->add_dict_keys("child2");
-    auto* child1 = nested->add_dict_values();
-    child1->set_nested_type(
-        protos::pbzero::DebugAnnotation::NestedValue::UNSPECIFIED);
-    child1->set_bool_value(true);
-    auto* child2 = nested->add_dict_values();
-    child2->set_nested_type(
-        protos::pbzero::DebugAnnotation::NestedValue::ARRAY);
-    auto* child21 = child2->add_array_values();
-    child21->set_nested_type(
-        protos::pbzero::DebugAnnotation::NestedValue::UNSPECIFIED);
-    child21->set_string_value("child21");
-    auto* child22 = child2->add_array_values();
-    child22->set_nested_type(
-        protos::pbzero::DebugAnnotation::NestedValue::UNSPECIFIED);
-    child22->set_double_value(2.2);
-    auto* child23 = child2->add_array_values();
-    child23->set_nested_type(
-        protos::pbzero::DebugAnnotation::NestedValue::UNSPECIFIED);
-    child23->set_int_value(23);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('B');
-
-    auto* interned_data = packet->set_interned_data();
-    auto cat1 = interned_data->add_event_categories();
-    cat1->set_iid(1);
-    cat1->set_name("cat1");
-    auto ev1 = interned_data->add_event_names();
-    ev1->set_iid(1);
-    ev1->set_name("ev1");
-    auto an1 = interned_data->add_debug_annotation_names();
-    an1->set_iid(1);
-    an1->set_name("an1");
-    auto an2 = interned_data->add_debug_annotation_names();
-    an2->set_iid(2);
-    an2->set_name("an2");
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);   // absolute: 1020.
-    event->set_thread_time_delta_us(5);  // absolute: 2010.
-    event->add_category_iids(1);
-    auto* annotation3 = event->add_debug_annotations();
-    annotation3->set_name_iid(3);
-    annotation3->set_int_value(-3);
-    auto* annotation4 = event->add_debug_annotations();
-    annotation4->set_name_iid(4);
-    annotation4->set_bool_value(true);
-    auto* annotation5 = event->add_debug_annotations();
-    annotation5->set_name_iid(5);
-    annotation5->set_double_value(-5.5);
-    auto* annotation6 = event->add_debug_annotations();
-    annotation6->set_name_iid(6);
-    annotation6->set_pointer_value(20u);
-    auto* annotation7 = event->add_debug_annotations();
-    annotation7->set_name_iid(7);
-    annotation7->set_string_value("val7");
-    auto* annotation8 = event->add_debug_annotations();
-    annotation8->set_name_iid(8);
-    annotation8->set_legacy_json_value("val8");
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('E');
-
-    auto* interned_data = packet->set_interned_data();
-    auto an3 = interned_data->add_debug_annotation_names();
-    an3->set_iid(3);
-    an3->set_name("an3");
-    auto an4 = interned_data->add_debug_annotation_names();
-    an4->set_iid(4);
-    an4->set_name("an4");
-    auto an5 = interned_data->add_debug_annotation_names();
-    an5->set_iid(5);
-    an5->set_name("an5");
-    auto an6 = interned_data->add_debug_annotation_names();
-    an6->set_iid(6);
-    an6->set_name("an6");
-    auto an7 = interned_data->add_debug_annotation_names();
-    an7->set_iid(7);
-    an7->set_name("an7");
-    auto an8 = interned_data->add_debug_annotation_names();
-    an8->set_iid(8);
-    an8->set_name("an8");
-  }
-
-  Tokenize();
-
-  EXPECT_CALL(*process_, UpdateThread(16, 15))
-      .Times(2)
-      .WillRepeatedly(Return(1));
-
-  TraceStorage::Thread thread(16);
-  thread.upid = 1u;
-  EXPECT_CALL(*storage_, GetThread(1))
-      .Times(2)
-      .WillRepeatedly(testing::ReturnRef(thread));
-
-  EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
-      .WillRepeatedly(Return(1));
-  EXPECT_CALL(*storage_, InternString(base::StringView("ev1")))
-      .WillRepeatedly(Return(2));
-  EXPECT_CALL(*storage_, InternString(base::StringView("debug.an1")))
-      .WillOnce(Return(3));
-  EXPECT_CALL(*storage_, InternString(base::StringView("debug.an2")))
-      .WillOnce(Return(4));
-  EXPECT_CALL(*storage_, InternString(base::StringView("debug.an2.child1")))
-      .WillRepeatedly(Return(5));
-  EXPECT_CALL(*storage_, InternString(base::StringView("debug.an2.child2")))
-      .WillRepeatedly(Return(6));
-  EXPECT_CALL(*storage_, InternString(base::StringView("debug.an2.child2[0]")))
-      .WillOnce(Return(7));
-  EXPECT_CALL(*storage_, InternString(base::StringView("child21")))
-      .WillOnce(Return(8));
-  EXPECT_CALL(*storage_, InternString(base::StringView("debug.an2.child2[1]")))
-      .WillOnce(Return(9));
-  EXPECT_CALL(*storage_, InternString(base::StringView("debug.an2.child2[2]")))
-      .WillOnce(Return(10));
-  EXPECT_CALL(*storage_, InternString(base::StringView("debug.an3")))
-      .WillOnce(Return(11));
-  EXPECT_CALL(*storage_, InternString(base::StringView("debug.an4")))
-      .WillOnce(Return(12));
-  EXPECT_CALL(*storage_, InternString(base::StringView("debug.an5")))
-      .WillOnce(Return(13));
-  EXPECT_CALL(*storage_, InternString(base::StringView("debug.an6")))
-      .WillOnce(Return(14));
-  EXPECT_CALL(*storage_, InternString(base::StringView("debug.an7")))
-      .WillOnce(Return(15));
-  EXPECT_CALL(*storage_, InternString(base::StringView("val7")))
-      .WillOnce(Return(16));
-  EXPECT_CALL(*storage_, InternString(base::StringView("debug.an8")))
-      .WillOnce(Return(17));
-  EXPECT_CALL(*storage_, InternString(base::StringView("val8")))
-      .WillOnce(Return(18));
-
-  EXPECT_CALL(*storage_, GetString(StringId(4))).WillOnce(Return("debug.an2"));
-
-  constexpr TrackId track = 0u;
-  InSequence in_sequence;  // Below slices should be sorted by timestamp.
-
-  EXPECT_CALL(*slice_, Begin(1010000, track, 1, RefType::kRefUtid, StringId(1),
-                             StringId(2), _))
-      .WillOnce(DoAll(InvokeArgument<6>(&args, 1u), Return(1u)));
-  EXPECT_CALL(args, AddArg(1u, StringId(3), StringId(3),
-                           Variadic::UnsignedInteger(10u)));
-
-  EXPECT_CALL(args,
-              AddArg(1u, StringId(5), StringId(5), Variadic::Boolean(true)));
-
-  EXPECT_CALL(args, AddArg(1u, StringId(6), StringId(7),
-                           Variadic::String(StringId(8))));
-
-  EXPECT_CALL(args, AddArg(1u, StringId(6), StringId(9), Variadic::Real(2.2)));
-
-  EXPECT_CALL(args,
-              AddArg(1u, StringId(6), StringId(10), Variadic::Integer(23)));
-
-  EXPECT_CALL(*slice_, End(1020000, track, StringId(1), StringId(2), _))
-      .WillOnce(DoAll(InvokeArgument<4>(&args, 1u), Return(1u)));
-
-  EXPECT_CALL(args,
-              AddArg(1u, StringId(11), StringId(11), Variadic::Integer(-3)));
-  EXPECT_CALL(args,
-              AddArg(1u, StringId(12), StringId(12), Variadic::Boolean(true)));
-  EXPECT_CALL(args,
-              AddArg(1u, StringId(13), StringId(13), Variadic::Real(-5.5)));
-  EXPECT_CALL(args,
-              AddArg(1u, StringId(14), StringId(14), Variadic::Pointer(20u)));
-  EXPECT_CALL(args,
-              AddArg(1u, StringId(15), StringId(15), Variadic::String(16)));
-  EXPECT_CALL(args, AddArg(1u, StringId(17), StringId(17), Variadic::Json(18)));
-
-  context_.sorter->ExtractEventsForced();
-}
-
-TEST_F(ProtoTraceParserTest, TrackEventWithTaskExecution) {
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-  MockArgsTracker args(&context_);
-
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_incremental_state_cleared(true);
-    auto* thread_desc = packet->set_thread_descriptor();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(16);
-    thread_desc->set_reference_timestamp_us(1000);
-    thread_desc->set_reference_thread_time_us(2000);
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);   // absolute: 1010.
-    event->set_thread_time_delta_us(5);  // absolute: 2005.
-    event->add_category_iids(1);
-    auto* task_execution = event->set_task_execution();
-    task_execution->set_posted_from_iid(1);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('B');
-
-    auto* interned_data = packet->set_interned_data();
-    auto cat1 = interned_data->add_event_categories();
-    cat1->set_iid(1);
-    cat1->set_name("cat1");
-    auto ev1 = interned_data->add_event_names();
-    ev1->set_iid(1);
-    ev1->set_name("ev1");
-    auto loc1 = interned_data->add_source_locations();
-    loc1->set_iid(1);
-    loc1->set_file_name("file1");
-    loc1->set_function_name("func1");
-    loc1->set_line_number(42);
-  }
-
-  Tokenize();
-
-  EXPECT_CALL(*process_, UpdateThread(16, 15)).WillOnce(Return(1));
-
-  TraceStorage::Thread thread(16);
-  thread.upid = 1u;
-  EXPECT_CALL(*storage_, GetThread(1)).WillOnce(testing::ReturnRef(thread));
-
-  constexpr TrackId track = 0u;
-  InSequence in_sequence;  // Below slices should be sorted by timestamp.
-
-  EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
-      .WillOnce(Return(1));
-  EXPECT_CALL(*storage_, InternString(base::StringView("ev1")))
-      .WillOnce(Return(2));
-  EXPECT_CALL(*slice_, Begin(1010000, track, 1, RefType::kRefUtid, StringId(1),
-                             StringId(2), _))
-      .WillOnce(DoAll(InvokeArgument<6>(&args, 1u), Return(1u)));
-  EXPECT_CALL(*storage_, InternString(base::StringView("file1")))
-      .WillOnce(Return(3));
-  EXPECT_CALL(*storage_, InternString(base::StringView("func1")))
-      .WillOnce(Return(4));
-  EXPECT_CALL(args, AddArg(1u, _, _, Variadic::String(3)));
-  EXPECT_CALL(args, AddArg(1u, _, _, Variadic::String(4)));
-  EXPECT_CALL(args, AddArg(1u, _, _, Variadic::UnsignedInteger(42)));
-
-  context_.sorter->ExtractEventsForced();
-}
-
-TEST_F(ProtoTraceParserTest, TrackEventWithLogMessage) {
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-  MockArgsTracker args(&context_);
-
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_incremental_state_cleared(true);
-    auto* thread_desc = packet->set_thread_descriptor();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(16);
-    thread_desc->set_reference_timestamp_us(1000);
-    thread_desc->set_reference_thread_time_us(2000);
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);   // absolute: 1010.
-    event->set_thread_time_delta_us(5);  // absolute: 2005.
-    event->add_category_iids(1);
-
-    auto* log_message = event->set_log_message();
-    log_message->set_body_iid(1);
-    log_message->set_source_location_iid(1);
-
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    legacy_event->set_phase('I');
-
-    auto* interned_data = packet->set_interned_data();
-    auto cat1 = interned_data->add_event_categories();
-    cat1->set_iid(1);
-    cat1->set_name("cat1");
-
-    auto ev1 = interned_data->add_event_names();
-    ev1->set_iid(1);
-    ev1->set_name("ev1");
-
-    auto body = interned_data->add_log_message_body();
-    body->set_iid(1);
-    body->set_body("body1");
-
-    auto loc1 = interned_data->add_source_locations();
-    loc1->set_iid(1);
-    loc1->set_file_name("file1");
-    loc1->set_function_name("func1");
-    loc1->set_line_number(1);
-  }
-
-  Tokenize();
-
-  EXPECT_CALL(*process_, UpdateThread(16, 15)).WillOnce(Return(1));
-
-  TraceStorage::Thread thread(16);
-  thread.upid = 1u;
-  EXPECT_CALL(*storage_, GetThread(1)).WillOnce(testing::ReturnRef(thread));
-
-  constexpr TrackId track = 0;
-  InSequence in_sequence;  // Below slices should be sorted by timestamp.
-
-  EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
-      .WillOnce(Return(1));
-  EXPECT_CALL(*storage_, InternString(base::StringView("ev1")))
-      .WillOnce(Return(2));
-
-  EXPECT_CALL(*slice_, Scoped(1010000, track, 1, RefType::kRefUtid, StringId(1),
-                              StringId(2), 0, _))
-      .WillOnce(DoAll(InvokeArgument<7>(&args, 1u), Return(1u)));
-
-  EXPECT_CALL(*storage_, InternString(base::StringView("body1")))
-      .WillOnce(Return(3));
-
-  // Call with logMessageBody (body1 in this case).
-  EXPECT_CALL(args, AddArg(1u, _, _, Variadic::String(StringId(3))));
-
-  context_.sorter->ExtractEventsForced();
-
-  EXPECT_TRUE(context_.storage->android_logs().size() > 0);
-  EXPECT_EQ(context_.storage->android_logs().timestamps()[0], 1010000);
-  EXPECT_EQ(context_.storage->android_logs().msg_ids()[0], 3u);
-}
-
-TEST_F(ProtoTraceParserTest, TrackEventParseLegacyEventIntoRawTable) {
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_incremental_state_cleared(true);
-    auto* thread_desc = packet->set_thread_descriptor();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(16);
-    thread_desc->set_reference_timestamp_us(1000);
-    thread_desc->set_reference_thread_time_us(2000);
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);   // absolute: 1010.
-    event->set_thread_time_delta_us(5);  // absolute: 2005.
-    event->add_category_iids(1);
-
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-    // Represents a phase that isn't parsed into regular trace processor tables.
-    legacy_event->set_phase('?');
-    legacy_event->set_duration_us(23);
-    legacy_event->set_thread_duration_us(15);
-    legacy_event->set_global_id(99u);
-    legacy_event->set_id_scope("scope1");
-    legacy_event->set_use_async_tts('?');
-    legacy_event->set_bind_id(98);
-    legacy_event->set_bind_to_enclosing(true);
-    legacy_event->set_flow_direction(
-        protos::pbzero::TrackEvent::LegacyEvent::FLOW_INOUT);
-
-    auto* annotation1 = event->add_debug_annotations();
-    annotation1->set_name_iid(1);
-    annotation1->set_uint_value(10u);
-
-    auto* interned_data = packet->set_interned_data();
-    auto cat1 = interned_data->add_event_categories();
-    cat1->set_iid(1);
-    cat1->set_name("cat1");
-    auto ev1 = interned_data->add_event_names();
-    ev1->set_iid(1);
-    ev1->set_name("ev1");
-    auto an1 = interned_data->add_debug_annotation_names();
-    an1->set_iid(1);
-    an1->set_name("an1");
-  }
-
-  Tokenize();
-
-  EXPECT_CALL(*process_, UpdateThread(16, 15)).WillOnce(Return(1));
-
-  TraceStorage::Thread thread(16);
-  thread.upid = 1u;
-  EXPECT_CALL(*storage_, GetThread(1)).WillOnce(testing::ReturnRef(thread));
-
-  EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
-      .WillOnce(Return(1));
-  EXPECT_CALL(*storage_, InternString(base::StringView("ev1")))
-      .WillOnce(Return(2));
-  EXPECT_CALL(*storage_, InternString(base::StringView("scope1")))
-      .Times(1)
-      .WillRepeatedly(Return(3));
-  EXPECT_CALL(*storage_, InternString(base::StringView("?")))
-      .WillOnce(Return(4));
-  EXPECT_CALL(*storage_, InternString(base::StringView("debug.an1")))
-      .WillOnce(Return(5));
-
-  context_.sorter->ExtractEventsForced();
-
-  ::testing::Mock::VerifyAndClearExpectations(storage_);
-
-  // Verify raw_events and args contents.
-  const auto& raw_events = storage_->raw_events();
-  EXPECT_EQ(raw_events.raw_event_count(), 1u);
-  EXPECT_EQ(raw_events.timestamps()[0], 1010000);
-  EXPECT_EQ(raw_events.name_ids()[0],
-            storage_->InternString("track_event.legacy_event"));
-  EXPECT_EQ(raw_events.cpus()[0], 0u);
-  EXPECT_EQ(raw_events.utids()[0], 1u);
-  EXPECT_EQ(raw_events.arg_set_ids()[0], 1u);
-
-  EXPECT_GE(storage_->args().args_count(), 13u);
-
-  EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.category"),
-                     Variadic::String(1u)));
-  EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.name"),
-                     Variadic::String(2u)));
-  EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.phase"),
-                     Variadic::String(4u)));
-  EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.duration_ns"),
-                     Variadic::Integer(23000)));
-  EXPECT_TRUE(HasArg(1u,
-                     storage_->InternString("legacy_event.thread_timestamp_ns"),
-                     Variadic::Integer(2005000)));
-  EXPECT_TRUE(HasArg(1u,
-                     storage_->InternString("legacy_event.thread_duration_ns"),
-                     Variadic::Integer(15000)));
-  EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.use_async_tts"),
-                     Variadic::Boolean(true)));
-  EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.global_id"),
-                     Variadic::UnsignedInteger(99u)));
-  EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.id_scope"),
-                     Variadic::String(3u)));
-  EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.bind_id"),
-                     Variadic::UnsignedInteger(98u)));
-  EXPECT_TRUE(HasArg(1u,
-                     storage_->InternString("legacy_event.bind_to_enclosing"),
-                     Variadic::Boolean(true)));
-  EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.flow_direction"),
-                     Variadic::String(storage_->InternString("inout"))));
-  EXPECT_TRUE(HasArg(1u, 5u, Variadic::UnsignedInteger(10u)));
-}
-
-TEST_F(ProtoTraceParserTest, TrackEventLegacyTimestampsWithClockSnapshot) {
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-
-  std::map<ClockTracker::ClockId, int64_t> clock_map;
-  clock_map[protos::pbzero::ClockSnapshot::Clock::BOOTTIME] = 0u;
-  clock_map[protos::pbzero::ClockSnapshot::Clock::MONOTONIC] = 1000000u;
-  clock_->AddSnapshot(clock_map);
-
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_incremental_state_cleared(true);
-    auto* thread_desc = packet->set_thread_descriptor();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(16);
-    thread_desc->set_reference_timestamp_us(1000);  // MONOTONIC.
-  }
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* event = packet->set_track_event();
-    event->set_timestamp_delta_us(10);  // absolute: 1010 (mon), 10 (boot).
-    event->add_category_iids(1);
-    event->set_type(protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN);
-    auto* legacy_event = event->set_legacy_event();
-    legacy_event->set_name_iid(1);
-  }
-
-  Tokenize();
-
-  EXPECT_CALL(*process_, UpdateThread(16, 15)).WillOnce(Return(1));
-
-  TraceStorage::Thread thread(16);
-  thread.upid = 1u;
-  EXPECT_CALL(*storage_, GetThread(1)).WillOnce(testing::ReturnRef(thread));
-
-  MockArgsTracker args(&context_);
-
-  constexpr TrackId track = 0u;
-  InSequence in_sequence;  // Below slices should be sorted by timestamp.
-
-  // Timestamp should be adjusted to trace time (BOOTTIME).
-  EXPECT_CALL(*slice_, Begin(10000, track, 1, RefType::kRefUtid, kNullStringId,
-                             kNullStringId, _));
-
-  context_.sorter->ExtractEventsForced();
-}
-
-TEST_F(ProtoTraceParserTest, ParseEventWithClockIdButWithoutClockSnapshot) {
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_timestamp(1000);
-    packet->set_timestamp_clock_id(3);
-    packet->set_trusted_packet_sequence_id(1);
-    auto* bundle = packet->set_chrome_events();
-    auto* metadata = bundle->add_metadata();
-    metadata->set_name("test");
-    metadata->set_int_value(23);
-  }
-
-  util::Status status = Tokenize();
-  EXPECT_TRUE(status.ok());
-  context_.sorter->ExtractEventsForced();
-
-  // Metadata should have created a raw event.
-  const auto& raw_events = storage_->raw_events();
-  EXPECT_EQ(raw_events.raw_event_count(), 1u);
-}
-
-TEST_F(ProtoTraceParserTest, ParseChromeMetadataEventIntoRawTable) {
-  static const char kStringName[] = "string_name";
-  static const char kStringValue[] = "string_value";
-  static const char kIntName[] = "int_name";
-  static const int kIntValue = 123;
-
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_timestamp(1000);
-    packet->set_timestamp_clock_id(3);
-    packet->set_trusted_packet_sequence_id(1);
-    auto* bundle = packet->set_chrome_events();
-    auto* metadata = bundle->add_metadata();
-    metadata->set_name(kStringName);
-    metadata->set_string_value(kStringValue);
-    metadata = bundle->add_metadata();
-    metadata->set_name(kIntName);
-    metadata->set_int_value(kIntValue);
-  }
-
-  Tokenize();
-  context_.sorter->ExtractEventsForced();
-
-  // Verify raw_events and args contents.
-  const auto& raw_events = storage_->raw_events();
-  EXPECT_EQ(raw_events.raw_event_count(), 1u);
-  EXPECT_EQ(raw_events.name_ids()[0],
-            storage_->InternString("chrome_event.metadata"));
-  EXPECT_EQ(raw_events.arg_set_ids()[0], 1u);
-
-  EXPECT_EQ(storage_->args().args_count(), 2u);
-  EXPECT_TRUE(HasArg(1u, storage_->InternString(kStringName),
-                     Variadic::String(storage_->InternString(kStringValue))));
-  EXPECT_TRUE(HasArg(1u, storage_->InternString(kIntName),
-                     Variadic::Integer(kIntValue)));
-}
-
-TEST_F(ProtoTraceParserTest, ParseChromeLegacyFtraceIntoRawTable) {
-  static const char kDataPart0[] = "aaa";
-  static const char kDataPart1[] = "bbb";
-  static const char kFullData[] = "aaabbb";
-
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* bundle = packet->set_chrome_events();
-    bundle->add_legacy_ftrace_output(kDataPart0);
-    bundle->add_legacy_ftrace_output(kDataPart1);
-  }
-
-  Tokenize();
-
-  context_.sorter->ExtractEventsForced();
-
-  // Verify raw_events and args contents.
-  const auto& raw_events = storage_->raw_events();
-  EXPECT_EQ(raw_events.raw_event_count(), 1u);
-  EXPECT_EQ(raw_events.name_ids()[0],
-            storage_->InternString("chrome_event.legacy_system_trace"));
-  EXPECT_EQ(raw_events.arg_set_ids()[0], 1u);
-
-  EXPECT_EQ(storage_->args().args_count(), 1u);
-  EXPECT_TRUE(HasArg(1u, storage_->InternString("data"),
-                     Variadic::String(storage_->InternString(kFullData))));
-}
-
-TEST_F(ProtoTraceParserTest, ParseChromeLegacyJsonIntoRawTable) {
-  static const char kUserTraceEvent[] = "{\"user\":1}";
-
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* bundle = packet->set_chrome_events();
-    auto* user_trace = bundle->add_legacy_json_trace();
-    user_trace->set_type(protos::pbzero::ChromeLegacyJsonTrace::USER_TRACE);
-    user_trace->set_data(kUserTraceEvent);
-  }
-
-  Tokenize();
-
-  context_.sorter->ExtractEventsForced();
-
-  // Verify raw_events and args contents.
-  const auto& raw_events = storage_->raw_events();
-  EXPECT_EQ(raw_events.raw_event_count(), 1u);
-  EXPECT_EQ(raw_events.name_ids()[0],
-            storage_->InternString("chrome_event.legacy_user_trace"));
-  EXPECT_EQ(raw_events.arg_set_ids()[0], 1u);
-
-  EXPECT_EQ(storage_->args().args_count(), 1u);
-  EXPECT_TRUE(
-      HasArg(1u, storage_->InternString("data"),
-             Variadic::String(storage_->InternString(kUserTraceEvent))));
-}
-
-TEST_F(ProtoTraceParserTest, LoadChromeBenchmarkMetadata) {
-  static const char kName[] = "name";
-  static const char kTag1[] = "tag1";
-  static const char kTag2[] = "tag2";
-
-  context_.sorter.reset(new TraceSorter(
-      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
-
-  auto* metadata = trace_.add_packet()->set_chrome_benchmark_metadata();
-  metadata->set_benchmark_name(kName);
-  metadata->add_story_tags(kTag1);
-  metadata->add_story_tags(kTag2);
-
-  Tokenize();
-
-  EXPECT_CALL(*storage_, InternString(base::StringView(kName)))
-      .WillOnce(Return(1));
-  EXPECT_CALL(*storage_, InternString(base::StringView(kTag1)))
-      .WillOnce(Return(2));
-  EXPECT_CALL(*storage_, InternString(base::StringView(kTag2)))
-      .WillOnce(Return(3));
-
-  context_.sorter->ExtractEventsForced();
-
-  const auto& meta_keys = storage_->metadata().keys();
-  const auto& meta_values = storage_->metadata().values();
-  EXPECT_EQ(meta_keys.size(), 3u);
-  std::vector<std::pair<metadata::KeyIDs, Variadic>> meta_entries;
-  for (size_t i = 0; i < meta_keys.size(); i++) {
-    meta_entries.emplace_back(std::make_pair(meta_keys[i], meta_values[i]));
-  }
-  EXPECT_THAT(
-      meta_entries,
-      UnorderedElementsAreArray(
-          {std::make_pair(metadata::benchmark_name, Variadic::String(1)),
-           std::make_pair(metadata::benchmark_story_tags, Variadic::String(2)),
-           std::make_pair(metadata::benchmark_story_tags,
-                          Variadic::String(3))}));
-}
-
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_ANDROID_PROBES)
-TEST_F(ProtoTraceParserTest, AndroidPackagesList) {
-  auto* packet = trace_.add_packet();
-  auto* pkg_list = packet->set_packages_list();
-
-  pkg_list->set_read_error(false);
-  pkg_list->set_parse_error(true);
-  {
-    auto* pkg = pkg_list->add_packages();
-    pkg->set_name("com.test.app");
-    pkg->set_uid(1000);
-    pkg->set_debuggable(false);
-    pkg->set_profileable_from_shell(true);
-    pkg->set_version_code(42);
-  }
-  {
-    auto* pkg = pkg_list->add_packages();
-    pkg->set_name("com.test.app2");
-    pkg->set_uid(1001);
-    pkg->set_debuggable(false);
-    pkg->set_profileable_from_shell(false);
-    pkg->set_version_code(43);
-  }
-
-  Tokenize();
-
-  // Packet-level errors reflected in stats storage.
-  const auto& stats = context_.storage->stats();
-  EXPECT_FALSE(stats[stats::packages_list_has_read_errors].value);
-  EXPECT_TRUE(stats[stats::packages_list_has_parse_errors].value);
-
-  // Expect two metadata rows, each with an int_value of a separate arg set id.
-  // The relevant arg sets have the info about the packages. To simplify test
-  // structure, make an assumption that metadata storage is filled in in the
-  // FIFO order of seen packages.
-  const auto& args = context_.storage->args();
-  const auto& metadata = context_.storage->metadata();
-  const auto& meta_keys = metadata.keys();
-  const auto& meta_values = metadata.values();
-
-  ASSERT_TRUE(std::count(meta_keys.cbegin(), meta_keys.cend(),
-                         metadata::android_packages_list) == 2);
-
-  auto first_meta_idx = std::distance(
-      meta_keys.cbegin(), std::find(meta_keys.cbegin(), meta_keys.cend(),
-                                    metadata::android_packages_list));
-  auto second_meta_idx = std::distance(
-      meta_keys.cbegin(),
-      std::find(meta_keys.cbegin() + first_meta_idx + 1, meta_keys.cend(),
-                metadata::android_packages_list));
-
-  uint32_t first_set_id = static_cast<uint32_t>(
-      meta_values[static_cast<size_t>(first_meta_idx)].int_value);
-  uint32_t second_set_id = static_cast<uint32_t>(
-      meta_values[static_cast<size_t>(second_meta_idx)].int_value);
-
-  // helper to look up arg values
-  auto find_arg = [&args, this](ArgSetId set_id, const char* arg_name) {
-    for (size_t i = 0; i < args.set_ids().size(); i++) {
-      if (args.set_ids()[i] == set_id &&
-          args.keys()[i] == storage_->InternString(arg_name))
-        return args.arg_values()[i];
-    }
-    PERFETTO_FATAL("Didn't find expected argument");
-  };
-
-  auto first_name_id = find_arg(first_set_id, "name").string_value;
-  EXPECT_STREQ(storage_->GetString(first_name_id).c_str(), "com.test.app");
-  EXPECT_EQ(find_arg(first_set_id, "uid").uint_value, 1000u);
-  EXPECT_EQ(find_arg(first_set_id, "debuggable").bool_value, false);
-  EXPECT_EQ(find_arg(first_set_id, "profileable_from_shell").bool_value, true);
-  EXPECT_EQ(find_arg(first_set_id, "version_code").int_value, 42);
-
-  auto second_name_id = find_arg(second_set_id, "name").string_value;
-  EXPECT_STREQ(storage_->GetString(second_name_id).c_str(), "com.test.app2");
-  EXPECT_EQ(find_arg(second_set_id, "uid").uint_value, 1001u);
-  EXPECT_EQ(find_arg(second_set_id, "debuggable").bool_value, false);
-  EXPECT_EQ(find_arg(second_set_id, "profileable_from_shell").bool_value,
-            false);
-  EXPECT_EQ(find_arg(second_set_id, "version_code").int_value, 43);
-}
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_ANDROID_PROBES)
-
-TEST_F(ProtoTraceParserTest, ParseCPUProfileSamplesIntoTable) {
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    packet->set_incremental_state_cleared(true);
-
-    auto* thread_desc = packet->set_thread_descriptor();
-    thread_desc->set_pid(15);
-    thread_desc->set_tid(16);
-    thread_desc->set_reference_timestamp_us(1);
-    thread_desc->set_reference_thread_time_us(2);
-
-    auto* interned_data = packet->set_interned_data();
-
-    auto mapping = interned_data->add_mappings();
-    mapping->set_iid(1);
-
-    auto frame = interned_data->add_frames();
-    frame->set_iid(1);
-    frame->set_rel_pc(0x42);
-    frame->set_mapping_id(1);
-
-    auto frame2 = interned_data->add_frames();
-    frame2->set_iid(2);
-    frame2->set_rel_pc(0x4242);
-    frame2->set_mapping_id(1);
-
-    auto callstack = interned_data->add_callstacks();
-    callstack->set_iid(1);
-    callstack->add_frame_ids(1);
-
-    auto callstack2 = interned_data->add_callstacks();
-    callstack2->set_iid(42);
-    callstack2->add_frame_ids(2);
-  }
-
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-
-    auto* samples = packet->set_streaming_profile_packet();
-    samples->add_callstack_iid(42);
-    samples->add_timestamp_delta_us(10);
-
-    samples->add_callstack_iid(1);
-    samples->add_timestamp_delta_us(15);
-  }
-
-  {
-    auto* packet = trace_.add_packet();
-    packet->set_trusted_packet_sequence_id(1);
-    auto* samples = packet->set_streaming_profile_packet();
-
-    samples->add_callstack_iid(42);
-    samples->add_timestamp_delta_us(42);
-  }
-
-  EXPECT_CALL(*process_, UpdateThread(16, 15))
-      .Times(2)
-      .WillRepeatedly(Return(1));
-
-  Tokenize();
-
-  // Verify cpu_profile_samples.
-  const auto& samples = storage_->cpu_profile_stack_samples();
-  EXPECT_EQ(samples.size(), 3u);
-
-  EXPECT_EQ(samples.timestamps()[0], 1010);
-  EXPECT_EQ(samples.callsite_ids()[0], 0);
-  EXPECT_EQ(samples.utids()[0], 1u);
-
-  EXPECT_EQ(samples.timestamps()[1], 1025);
-  EXPECT_EQ(samples.callsite_ids()[1], 1);
-  EXPECT_EQ(samples.utids()[1], 1u);
-
-  EXPECT_EQ(samples.timestamps()[2], 1067);
-  EXPECT_EQ(samples.callsite_ids()[2], 0);
-  EXPECT_EQ(samples.utids()[2], 1u);
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/proto_trace_tokenizer.cc b/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
deleted file mode 100644
index 013bc81..0000000
--- a/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- * 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.
- */
-
-#include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
-
-#include <string>
-
-#include <zlib.h>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/protozero/proto_decoder.h"
-#include "perfetto/protozero/proto_utils.h"
-#include "perfetto/trace_processor/status.h"
-#include "src/trace_processor/clock_tracker.h"
-#include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/importers/ftrace/ftrace_module.h"
-#include "src/trace_processor/importers/proto/packet_sequence_state.h"
-#include "src/trace_processor/importers/proto/proto_incremental_state.h"
-#include "src/trace_processor/importers/proto/track_event_module.h"
-#include "src/trace_processor/stats.h"
-#include "src/trace_processor/trace_sorter.h"
-#include "src/trace_processor/trace_storage.h"
-
-#include "protos/perfetto/config/trace_config.pbzero.h"
-#include "protos/perfetto/trace/clock_snapshot.pbzero.h"
-#include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
-#include "protos/perfetto/trace/trace.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-using protozero::proto_utils::MakeTagLengthDelimited;
-using protozero::proto_utils::ParseVarInt;
-
-namespace {
-
-constexpr uint8_t kTracePacketTag =
-    MakeTagLengthDelimited(protos::pbzero::Trace::kPacketFieldNumber);
-
-TraceBlobView Decompress(TraceBlobView input) {
-  uint8_t out[4096];
-  std::string s;
-
-  z_stream stream{};
-  stream.next_in = const_cast<uint8_t*>(input.data());
-  stream.avail_in = static_cast<unsigned int>(input.length());
-
-  if (inflateInit(&stream) != Z_OK)
-    return TraceBlobView(nullptr, 0, 0);
-
-  int ret;
-  do {
-    stream.next_out = out;
-    stream.avail_out = sizeof(out);
-    ret = inflate(&stream, Z_NO_FLUSH);
-    if (ret != Z_STREAM_END && ret != Z_OK) {
-      inflateEnd(&stream);
-      return TraceBlobView(nullptr, 0, 0);
-    }
-    s.append(reinterpret_cast<char*>(out), sizeof(out) - stream.avail_out);
-  } while (ret != Z_STREAM_END);
-  inflateEnd(&stream);
-
-  std::unique_ptr<uint8_t[]> output(new uint8_t[s.size()]);
-  memcpy(output.get(), s.data(), s.size());
-  return TraceBlobView(std::move(output), 0, s.size());
-}
-
-}  // namespace
-
-ProtoTraceTokenizer::ProtoTraceTokenizer(TraceProcessorContext* ctx)
-    : context_(ctx) {}
-ProtoTraceTokenizer::~ProtoTraceTokenizer() = default;
-
-util::Status ProtoTraceTokenizer::Parse(std::unique_ptr<uint8_t[]> owned_buf,
-                                        size_t size) {
-  uint8_t* data = &owned_buf[0];
-  if (!partial_buf_.empty()) {
-    // It takes ~5 bytes for a proto preamble + the varint size.
-    const size_t kHeaderBytes = 5;
-    if (PERFETTO_UNLIKELY(partial_buf_.size() < kHeaderBytes)) {
-      size_t missing_len = std::min(kHeaderBytes - partial_buf_.size(), size);
-      partial_buf_.insert(partial_buf_.end(), &data[0], &data[missing_len]);
-      if (partial_buf_.size() < kHeaderBytes)
-        return util::OkStatus();
-      data += missing_len;
-      size -= missing_len;
-    }
-
-    // At this point we have enough data in |partial_buf_| to read at least the
-    // field header and know the size of the next TracePacket.
-    const uint8_t* pos = &partial_buf_[0];
-    uint8_t proto_field_tag = *pos;
-    uint64_t field_size = 0;
-    const uint8_t* next = ParseVarInt(++pos, &*partial_buf_.end(), &field_size);
-    bool parse_failed = next == pos;
-    pos = next;
-    if (proto_field_tag != kTracePacketTag || field_size == 0 || parse_failed) {
-      return util::ErrStatus(
-          "Failed parsing a TracePacket from the partial buffer");
-    }
-
-    // At this point we know how big the TracePacket is.
-    size_t hdr_size = static_cast<size_t>(pos - &partial_buf_[0]);
-    size_t size_incl_header = static_cast<size_t>(field_size + hdr_size);
-    PERFETTO_DCHECK(size_incl_header > partial_buf_.size());
-
-    // There is a good chance that between the |partial_buf_| and the new |data|
-    // of the current call we have enough bytes to parse a TracePacket.
-    if (partial_buf_.size() + size >= size_incl_header) {
-      // Create a new buffer for the whole TracePacket and copy into that:
-      // 1) The beginning of the TracePacket (including the proto header) from
-      //    the partial buffer.
-      // 2) The rest of the TracePacket from the current |data| buffer (note
-      //    that we might have consumed already a few bytes form |data| earlier
-      //    in this function, hence we need to keep |off| into account).
-      std::unique_ptr<uint8_t[]> buf(new uint8_t[size_incl_header]);
-      memcpy(&buf[0], partial_buf_.data(), partial_buf_.size());
-      // |size_missing| is the number of bytes for the rest of the TracePacket
-      // in |data|.
-      size_t size_missing = size_incl_header - partial_buf_.size();
-      memcpy(&buf[partial_buf_.size()], &data[0], size_missing);
-      data += size_missing;
-      size -= size_missing;
-      partial_buf_.clear();
-      uint8_t* buf_start = &buf[0];  // Note that buf is std::moved below.
-      util::Status status =
-          ParseInternal(std::move(buf), buf_start, size_incl_header);
-      if (PERFETTO_UNLIKELY(!status.ok()))
-        return status;
-    } else {
-      partial_buf_.insert(partial_buf_.end(), data, &data[size]);
-      return util::OkStatus();
-    }
-  }
-  return ParseInternal(std::move(owned_buf), data, size);
-}
-
-util::Status ProtoTraceTokenizer::ParseInternal(
-    std::unique_ptr<uint8_t[]> owned_buf,
-    uint8_t* data,
-    size_t size) {
-  PERFETTO_DCHECK(data >= &owned_buf[0]);
-  const uint8_t* start = &owned_buf[0];
-  const size_t data_off = static_cast<size_t>(data - start);
-  TraceBlobView whole_buf(std::move(owned_buf), data_off, size);
-
-  protos::pbzero::Trace::Decoder decoder(data, size);
-  for (auto it = decoder.packet(); it; ++it) {
-    protozero::ConstBytes packet = *it;
-    size_t field_offset = whole_buf.offset_of(packet.data);
-    util::Status status =
-        ParsePacket(whole_buf.slice(field_offset, packet.size));
-    if (PERFETTO_UNLIKELY(!status.ok()))
-      return status;
-  }
-
-  const size_t bytes_left = decoder.bytes_left();
-  if (bytes_left > 0) {
-    PERFETTO_DCHECK(partial_buf_.empty());
-    partial_buf_.insert(partial_buf_.end(), &data[decoder.read_offset()],
-                        &data[decoder.read_offset() + bytes_left]);
-  }
-  return util::OkStatus();
-}
-
-util::Status ProtoTraceTokenizer::ParsePacket(TraceBlobView packet) {
-  protos::pbzero::TracePacket::Decoder decoder(packet.data(), packet.length());
-  if (PERFETTO_UNLIKELY(decoder.bytes_left()))
-    return util::ErrStatus(
-        "Failed to parse proto packet fully; the trace is probably corrupt.");
-
-  auto timestamp =
-      decoder.has_timestamp()
-          ? static_cast<int64_t>(decoder.timestamp())
-          : std::max(latest_timestamp_, context_->sorter->max_timestamp());
-
-  const uint32_t seq_id = decoder.trusted_packet_sequence_id();
-
-  if ((decoder.has_chrome_events() || decoder.has_chrome_metadata()) &&
-      (!decoder.timestamp_clock_id() ||
-       decoder.timestamp_clock_id() ==
-           protos::pbzero::ClockSnapshot::Clock::MONOTONIC)) {
-    // Chrome event timestamps are in MONOTONIC domain, but may occur in traces
-    // where (a) no clock snapshots exist or (b) no clock_id is specified for
-    // their timestamps. Adjust to trace time if we have a clock snapshot.
-    // TODO(eseckler): Set timestamp_clock_id and emit ClockSnapshots in chrome
-    // and then remove this.
-    auto trace_ts = context_->clock_tracker->ToTraceTime(
-        protos::pbzero::ClockSnapshot::Clock::MONOTONIC, timestamp);
-    if (trace_ts.has_value())
-      timestamp = trace_ts.value();
-  } else if (decoder.timestamp_clock_id()) {
-    // If the TracePacket specifies a non-zero clock-id, translate the timestamp
-    // into the trace-time clock domain.
-    PERFETTO_DCHECK(decoder.has_timestamp());
-    ClockTracker::ClockId clock_id = decoder.timestamp_clock_id();
-    bool is_seq_scoped = ClockTracker::IsReservedSeqScopedClockId(clock_id);
-    if (is_seq_scoped) {
-      if (!seq_id) {
-        return util::ErrStatus(
-            "TracePacket specified a sequence-local clock id (%" PRIu32
-            ") but the TraceWriter's sequence_id is zero (the service is "
-            "probably too old)",
-            decoder.timestamp_clock_id());
-      }
-      clock_id = ClockTracker::SeqScopedClockIdToGlobal(
-          seq_id, decoder.timestamp_clock_id());
-    }
-    auto trace_ts = context_->clock_tracker->ToTraceTime(clock_id, timestamp);
-    if (!trace_ts.has_value()) {
-      // ToTraceTime() will increase the |clock_sync_failure| stat on failure.
-      static const char seq_extra_err[] =
-          " Because the clock id is sequence-scoped, the ClockSnapshot must be "
-          "emitted on the same TraceWriter sequence of the packet that refers "
-          "to that clock id.";
-      return util::ErrStatus(
-          "Failed to convert TracePacket's timestamp from clock_id=%" PRIu32
-          " seq_id=%" PRIu32
-          ". This is usually due to the lack of a prior ClockSnapshot proto.%s",
-          decoder.timestamp_clock_id(), seq_id,
-          is_seq_scoped ? seq_extra_err : "");
-    }
-    timestamp = trace_ts.value();
-  }
-  latest_timestamp_ = std::max(timestamp, latest_timestamp_);
-
-  auto* state = GetIncrementalStateForPacketSequence(
-      decoder.trusted_packet_sequence_id());
-
-  uint32_t sequence_flags = decoder.sequence_flags();
-
-  if (decoder.incremental_state_cleared() ||
-      sequence_flags &
-          protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED) {
-    HandleIncrementalStateCleared(decoder);
-  } else if (decoder.previous_packet_dropped()) {
-    HandlePreviousPacketDropped(decoder);
-  }
-
-  if (decoder.sequence_flags() &
-      protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE) {
-    if (!seq_id) {
-      return util::ErrStatus(
-          "TracePacket specified SEQ_NEEDS_INCREMENTAL_STATE but the "
-          "TraceWriter's sequence_id is zero (the service is "
-          "probably too old)");
-    }
-
-    if (!state->IsIncrementalStateValid()) {
-      context_->storage->IncrementStats(stats::tokenizer_skipped_packets);
-      return util::OkStatus();
-    }
-  }
-
-  if (decoder.has_clock_snapshot()) {
-    return ParseClockSnapshot(decoder.clock_snapshot(),
-                              decoder.trusted_packet_sequence_id());
-  }
-
-  // TODO(eseckler): Parse TracePacketDefaults.
-
-  if (decoder.has_interned_data()) {
-    auto field = decoder.interned_data();
-    const size_t offset = packet.offset_of(field.data);
-    ParseInternedData(decoder, packet.slice(offset, field.size));
-  }
-
-  ModuleResult res = ModuleResult::Ignored();
-  res = context_->ftrace_module->TokenizePacket(decoder, &packet, timestamp,
-                                                state);
-  if (!res.ignored())
-    return res.ToStatus();
-
-  res = context_->track_event_module->TokenizePacket(decoder, &packet,
-                                                     timestamp, state);
-  if (!res.ignored())
-    return res.ToStatus();
-
-  if (decoder.has_compressed_packets()) {
-    protozero::ConstBytes field = decoder.compressed_packets();
-    const size_t field_off = packet.offset_of(field.data);
-    TraceBlobView compressed_packets = packet.slice(field_off, field.size);
-    TraceBlobView packets = Decompress(std::move(compressed_packets));
-
-    const uint8_t* start = packets.data();
-    const uint8_t* end = packets.data() + packets.length();
-    const uint8_t* ptr = start;
-    while ((end - ptr) > 2) {
-      const uint8_t* packet_start = ptr;
-      if (PERFETTO_UNLIKELY(*ptr != kTracePacketTag))
-        return util::ErrStatus("Expected TracePacket tag");
-      uint64_t packet_size = 0;
-      ptr = ParseVarInt(++ptr, end, &packet_size);
-      size_t packet_offset = static_cast<size_t>(ptr - start);
-      ptr += packet_size;
-      if (PERFETTO_UNLIKELY((ptr - packet_start) < 2 || ptr > end))
-        return util::ErrStatus("Invalid packet size");
-      util::Status status = ParsePacket(
-          packets.slice(packet_offset, static_cast<size_t>(packet_size)));
-      if (PERFETTO_UNLIKELY(!status.ok()))
-        return status;
-    }
-
-    return util::OkStatus();
-  }
-
-  // If we're not forcing a full sort and this is a write_into_file trace, then
-  // use flush_period_ms as an indiciator for how big the sliding window for the
-  // sorter should be.
-  if (!context_->config.force_full_sort && decoder.has_trace_config()) {
-    auto config = decoder.trace_config();
-    protos::pbzero::TraceConfig::Decoder trace_config(config.data, config.size);
-
-    if (trace_config.write_into_file()) {
-      int64_t window_size_ns;
-      if (trace_config.has_flush_period_ms() &&
-          trace_config.flush_period_ms() > 0) {
-        // We use 2x the flush period as a margin of error to allow for any
-        // late flush responses to still be sorted correctly.
-        window_size_ns = static_cast<int64_t>(trace_config.flush_period_ms()) *
-                         2 * 1000 * 1000;
-      } else {
-        constexpr uint64_t kDefaultWindowNs =
-            180 * 1000 * 1000 * 1000ULL;  // 3 minutes.
-        PERFETTO_ELOG(
-            "It is strongly recommended to have flush_period_ms set when "
-            "write_into_file is turned on. You will likely have many dropped "
-            "events because of inability to sort the events correctly.");
-        window_size_ns = static_cast<int64_t>(kDefaultWindowNs);
-      }
-      context_->sorter->SetWindowSizeNs(window_size_ns);
-    }
-  }
-
-  // Use parent data and length because we want to parse this again
-  // later to get the exact type of the packet.
-  context_->sorter->PushTracePacket(timestamp, state, std::move(packet));
-
-  return util::OkStatus();
-}
-
-void ProtoTraceTokenizer::HandleIncrementalStateCleared(
-    const protos::pbzero::TracePacket::Decoder& packet_decoder) {
-  if (PERFETTO_UNLIKELY(!packet_decoder.has_trusted_packet_sequence_id())) {
-    PERFETTO_ELOG(
-        "incremental_state_cleared without trusted_packet_sequence_id");
-    context_->storage->IncrementStats(stats::interned_data_tokenizer_errors);
-    return;
-  }
-  GetIncrementalStateForPacketSequence(
-      packet_decoder.trusted_packet_sequence_id())
-      ->OnIncrementalStateCleared();
-}
-
-void ProtoTraceTokenizer::HandlePreviousPacketDropped(
-    const protos::pbzero::TracePacket::Decoder& packet_decoder) {
-  if (PERFETTO_UNLIKELY(!packet_decoder.has_trusted_packet_sequence_id())) {
-    PERFETTO_ELOG("previous_packet_dropped without trusted_packet_sequence_id");
-    context_->storage->IncrementStats(stats::interned_data_tokenizer_errors);
-    return;
-  }
-  GetIncrementalStateForPacketSequence(
-      packet_decoder.trusted_packet_sequence_id())
-      ->OnPacketLoss();
-}
-
-void ProtoTraceTokenizer::ParseInternedData(
-    const protos::pbzero::TracePacket::Decoder& packet_decoder,
-    TraceBlobView interned_data) {
-  if (PERFETTO_UNLIKELY(!packet_decoder.has_trusted_packet_sequence_id())) {
-    PERFETTO_ELOG("InternedData packet without trusted_packet_sequence_id");
-    context_->storage->IncrementStats(stats::interned_data_tokenizer_errors);
-    return;
-  }
-
-  auto* state = GetIncrementalStateForPacketSequence(
-      packet_decoder.trusted_packet_sequence_id());
-
-  // Don't parse interned data entries until incremental state is valid, because
-  // they could otherwise be associated with the wrong generation in the state.
-  if (!state->IsIncrementalStateValid()) {
-    context_->storage->IncrementStats(stats::tokenizer_skipped_packets);
-    return;
-  }
-
-  // Store references to interned data submessages into the sequence's state.
-  protozero::ProtoDecoder decoder(interned_data.data(), interned_data.length());
-  for (protozero::Field f = decoder.ReadField(); f.valid();
-       f = decoder.ReadField()) {
-    auto bytes = f.as_bytes();
-    auto offset = interned_data.offset_of(bytes.data);
-    state->InternMessage(f.id(), interned_data.slice(offset, bytes.size));
-  }
-}
-
-util::Status ProtoTraceTokenizer::ParseClockSnapshot(ConstBytes blob,
-                                                     uint32_t seq_id) {
-  std::map<ClockTracker::ClockId, int64_t> clock_map;
-  protos::pbzero::ClockSnapshot::Decoder evt(blob.data, blob.size);
-  for (auto it = evt.clocks(); it; ++it) {
-    protos::pbzero::ClockSnapshot::Clock::Decoder clk(*it);
-    ClockTracker::ClockId clock_id = clk.clock_id();
-    if (ClockTracker::IsReservedSeqScopedClockId(clk.clock_id())) {
-      if (!seq_id) {
-        return util::ErrStatus(
-            "ClockSnapshot packet is specifying a sequence-scoped clock id "
-            "(%" PRIu64 ") but the TracePacket sequence_id is zero",
-            clock_id);
-      }
-      clock_id = ClockTracker::SeqScopedClockIdToGlobal(seq_id, clk.clock_id());
-    }
-    clock_map[clock_id] = static_cast<int64_t>(clk.timestamp());
-  }
-  context_->clock_tracker->AddSnapshot(clock_map);
-  return util::OkStatus();
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/proto_trace_tokenizer.h b/src/trace_processor/importers/proto/proto_trace_tokenizer.h
deleted file mode 100644
index bdefa2e..0000000
--- a/src/trace_processor/importers/proto/proto_trace_tokenizer.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_TRACE_TOKENIZER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_TRACE_TOKENIZER_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "src/trace_processor/chunked_trace_reader.h"
-#include "src/trace_processor/importers/proto/proto_incremental_state.h"
-#include "src/trace_processor/trace_blob_view.h"
-
-namespace protozero {
-struct ConstBytes;
-}
-
-namespace perfetto {
-
-namespace protos {
-namespace pbzero {
-class TracePacket_Decoder;
-}  // namespace pbzero
-}  // namespace protos
-
-namespace trace_processor {
-
-class PacketSequenceState;
-class TraceProcessorContext;
-class TraceSorter;
-class TraceStorage;
-
-// Reads a protobuf trace in chunks and extracts boundaries of trace packets
-// (or subfields, for the case of ftrace) with their timestamps.
-class ProtoTraceTokenizer : public ChunkedTraceReader {
- public:
-  // |reader| is the abstract method of getting chunks of size |chunk_size_b|
-  // from a trace file with these chunks parsed into |trace|.
-  explicit ProtoTraceTokenizer(TraceProcessorContext*);
-  ~ProtoTraceTokenizer() override;
-
-  // ChunkedTraceReader implementation.
-  util::Status Parse(std::unique_ptr<uint8_t[]>, size_t size) override;
-
- private:
-  using ConstBytes = protozero::ConstBytes;
-  util::Status ParseInternal(std::unique_ptr<uint8_t[]> owned_buf,
-                             uint8_t* data,
-                             size_t size);
-  util::Status ParsePacket(TraceBlobView);
-  util::Status ParseClockSnapshot(ConstBytes blob, uint32_t seq_id);
-  void HandleIncrementalStateCleared(
-      const protos::pbzero::TracePacket_Decoder&);
-  void HandlePreviousPacketDropped(const protos::pbzero::TracePacket_Decoder&);
-  void ParseInternedData(const protos::pbzero::TracePacket_Decoder&,
-                         TraceBlobView interned_data);
-  PacketSequenceState* GetIncrementalStateForPacketSequence(
-      uint32_t sequence_id) {
-    if (!incremental_state)
-      incremental_state.reset(new ProtoIncrementalState(context_));
-    return incremental_state->GetOrCreateStateForPacketSequence(sequence_id);
-  }
-
-  TraceProcessorContext* context_;
-
-  // Used to glue together trace packets that span across two (or more)
-  // Parse() boundaries.
-  std::vector<uint8_t> partial_buf_;
-
-  // Temporary. Currently trace packets do not have a timestamp, so the
-  // timestamp given is latest_timestamp_.
-  int64_t latest_timestamp_ = 0;
-
-  // Stores incremental state and references to interned data, e.g. for track
-  // event protos.
-  std::unique_ptr<ProtoIncrementalState> incremental_state;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_PROTO_TRACE_TOKENIZER_H_
diff --git a/src/trace_processor/importers/proto/system_probes_module.h b/src/trace_processor/importers/proto/system_probes_module.h
deleted file mode 100644
index 53db890..0000000
--- a/src/trace_processor/importers/proto/system_probes_module.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_SYSTEM_PROBES_MODULE_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_SYSTEM_PROBES_MODULE_H_
-
-#include "perfetto/base/build_config.h"
-#include "src/trace_processor/importers/proto/proto_importer_module.h"
-#include "src/trace_processor/importers/proto/system_probes_parser.h"
-#include "src/trace_processor/timestamped_trace_piece.h"
-
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class SystemProbesModule : public ProtoImporterModuleBase<PERFETTO_BUILDFLAG(
-                               PERFETTO_TP_SYSTEM_PROBES)> {
- public:
-  explicit SystemProbesModule(TraceProcessorContext* context)
-      : ProtoImporterModuleBase(context), parser_(context) {}
-
-  ModuleResult ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
-                           const TimestampedTracePiece& ttp) {
-    if (decoder.has_process_tree()) {
-      parser_.ParseProcessTree(decoder.process_tree());
-      return ModuleResult::Handled();
-    }
-
-    if (decoder.has_process_stats()) {
-      parser_.ParseProcessStats(ttp.timestamp, decoder.process_stats());
-      return ModuleResult::Handled();
-    }
-
-    if (decoder.has_sys_stats()) {
-      parser_.ParseSysStats(ttp.timestamp, decoder.sys_stats());
-      return ModuleResult::Handled();
-    }
-
-    if (decoder.has_system_info()) {
-      parser_.ParseSystemInfo(decoder.system_info());
-      return ModuleResult::Handled();
-    }
-
-    return ModuleResult::Ignored();
-  }
-
- private:
-  SystemProbesParser parser_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_SYSTEM_PROBES_MODULE_H_
diff --git a/src/trace_processor/importers/proto/system_probes_parser.cc b/src/trace_processor/importers/proto/system_probes_parser.cc
deleted file mode 100644
index 14afab1..0000000
--- a/src/trace_processor/importers/proto/system_probes_parser.cc
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/importers/proto/system_probes_parser.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/traced/sys_stats_counters.h"
-#include "perfetto/protozero/proto_decoder.h"
-#include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/syscall_tracker.h"
-#include "src/trace_processor/trace_processor_context.h"
-
-#include "protos/perfetto/trace/ps/process_stats.pbzero.h"
-#include "protos/perfetto/trace/ps/process_tree.pbzero.h"
-#include "protos/perfetto/trace/sys_stats/sys_stats.pbzero.h"
-#include "protos/perfetto/trace/system_info.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-// kthreadd is the parent process for all kernel threads and always has
-// pid == 2 on Linux and Android.
-const uint32_t kKthreaddPid = 2;
-const char kKthreaddName[] = "kthreadd";
-}  // namespace
-
-SystemProbesParser::SystemProbesParser(TraceProcessorContext* context)
-    : context_(context),
-      utid_name_id_(context->storage->InternString("utid")),
-      num_forks_name_id_(context->storage->InternString("num_forks")),
-      num_irq_total_name_id_(context->storage->InternString("num_irq_total")),
-      num_softirq_total_name_id_(
-          context->storage->InternString("num_softirq_total")),
-      num_irq_name_id_(context->storage->InternString("num_irq")),
-      num_softirq_name_id_(context->storage->InternString("num_softirq")),
-      cpu_times_user_ns_id_(
-          context->storage->InternString("cpu.times.user_ns")),
-      cpu_times_user_nice_ns_id_(
-          context->storage->InternString("cpu.times.user_nice_ns")),
-      cpu_times_system_mode_ns_id_(
-          context->storage->InternString("cpu.times.system_mode_ns")),
-      cpu_times_idle_ns_id_(
-          context->storage->InternString("cpu.times.idle_ns")),
-      cpu_times_io_wait_ns_id_(
-          context->storage->InternString("cpu.times.io_wait_ns")),
-      cpu_times_irq_ns_id_(context->storage->InternString("cpu.times.irq_ns")),
-      cpu_times_softirq_ns_id_(
-          context->storage->InternString("cpu.times.softirq_ns")),
-      oom_score_adj_id_(context->storage->InternString("oom_score_adj")) {
-  for (const auto& name : BuildMeminfoCounterNames()) {
-    meminfo_strs_id_.emplace_back(context->storage->InternString(name));
-  }
-  for (const auto& name : BuildVmstatCounterNames()) {
-    vmstat_strs_id_.emplace_back(context->storage->InternString(name));
-  }
-
-  using ProcessStats = protos::pbzero::ProcessStats;
-  proc_stats_process_names_[ProcessStats::Process::kVmSizeKbFieldNumber] =
-      context->storage->InternString("mem.virt");
-  proc_stats_process_names_[ProcessStats::Process::kVmRssKbFieldNumber] =
-      context->storage->InternString("mem.rss");
-  proc_stats_process_names_[ProcessStats::Process::kRssAnonKbFieldNumber] =
-      context->storage->InternString("mem.rss.anon");
-  proc_stats_process_names_[ProcessStats::Process::kRssFileKbFieldNumber] =
-      context->storage->InternString("mem.rss.file");
-  proc_stats_process_names_[ProcessStats::Process::kRssShmemKbFieldNumber] =
-      context->storage->InternString("mem.rss.shmem");
-  proc_stats_process_names_[ProcessStats::Process::kVmSwapKbFieldNumber] =
-      context->storage->InternString("mem.swap");
-  proc_stats_process_names_[ProcessStats::Process::kVmLockedKbFieldNumber] =
-      context->storage->InternString("mem.locked");
-  proc_stats_process_names_[ProcessStats::Process::kVmHwmKbFieldNumber] =
-      context->storage->InternString("mem.rss.watermark");
-  proc_stats_process_names_[ProcessStats::Process::kOomScoreAdjFieldNumber] =
-      oom_score_adj_id_;
-}
-
-void SystemProbesParser::ParseSysStats(int64_t ts, ConstBytes blob) {
-  protos::pbzero::SysStats::Decoder sys_stats(blob.data, blob.size);
-
-  for (auto it = sys_stats.meminfo(); it; ++it) {
-    protos::pbzero::SysStats::MeminfoValue::Decoder mi(*it);
-    auto key = static_cast<size_t>(mi.key());
-    if (PERFETTO_UNLIKELY(key >= meminfo_strs_id_.size())) {
-      PERFETTO_ELOG("MemInfo key %zu is not recognized.", key);
-      context_->storage->IncrementStats(stats::meminfo_unknown_keys);
-      continue;
-    }
-    // /proc/meminfo counters are in kB, convert to bytes
-    TrackId track = context_->track_tracker->InternGlobalCounterTrack(
-        meminfo_strs_id_[key]);
-    context_->event_tracker->PushCounter(ts, mi.value() * 1024L, track);
-  }
-
-  for (auto it = sys_stats.vmstat(); it; ++it) {
-    protos::pbzero::SysStats::VmstatValue::Decoder vm(*it);
-    auto key = static_cast<size_t>(vm.key());
-    if (PERFETTO_UNLIKELY(key >= vmstat_strs_id_.size())) {
-      PERFETTO_ELOG("VmStat key %zu is not recognized.", key);
-      context_->storage->IncrementStats(stats::vmstat_unknown_keys);
-      continue;
-    }
-    TrackId track =
-        context_->track_tracker->InternGlobalCounterTrack(vmstat_strs_id_[key]);
-    context_->event_tracker->PushCounter(ts, vm.value(), track);
-  }
-
-  for (auto it = sys_stats.cpu_stat(); it; ++it) {
-    protos::pbzero::SysStats::CpuTimes::Decoder ct(*it);
-    if (PERFETTO_UNLIKELY(!ct.has_cpu_id())) {
-      PERFETTO_ELOG("CPU field not found in CpuTimes");
-      context_->storage->IncrementStats(stats::invalid_cpu_times);
-      continue;
-    }
-
-    TrackId track = context_->track_tracker->InternCpuCounterTrack(
-        cpu_times_user_ns_id_, ct.cpu_id());
-    context_->event_tracker->PushCounter(ts, ct.user_ns(), track);
-
-    track = context_->track_tracker->InternCpuCounterTrack(
-        cpu_times_user_nice_ns_id_, ct.cpu_id());
-    context_->event_tracker->PushCounter(ts, ct.user_ice_ns(), track);
-
-    track = context_->track_tracker->InternCpuCounterTrack(
-        cpu_times_system_mode_ns_id_, ct.cpu_id());
-    context_->event_tracker->PushCounter(ts, ct.system_mode_ns(), track);
-
-    track = context_->track_tracker->InternCpuCounterTrack(
-        cpu_times_idle_ns_id_, ct.cpu_id());
-    context_->event_tracker->PushCounter(ts, ct.idle_ns(), track);
-
-    track = context_->track_tracker->InternCpuCounterTrack(
-        cpu_times_io_wait_ns_id_, ct.cpu_id());
-    context_->event_tracker->PushCounter(ts, ct.io_wait_ns(), track);
-
-    track = context_->track_tracker->InternCpuCounterTrack(cpu_times_irq_ns_id_,
-                                                           ct.cpu_id());
-    context_->event_tracker->PushCounter(ts, ct.irq_ns(), track);
-
-    track = context_->track_tracker->InternCpuCounterTrack(
-        cpu_times_softirq_ns_id_, ct.cpu_id());
-    context_->event_tracker->PushCounter(ts, ct.softirq_ns(), track);
-  }
-
-  for (auto it = sys_stats.num_irq(); it; ++it) {
-    protos::pbzero::SysStats::InterruptCount::Decoder ic(*it);
-
-    TrackId track = context_->track_tracker->InternIrqCounterTrack(
-        num_irq_name_id_, ic.irq());
-    context_->event_tracker->PushCounter(ts, ic.count(), track);
-  }
-
-  for (auto it = sys_stats.num_softirq(); it; ++it) {
-    protos::pbzero::SysStats::InterruptCount::Decoder ic(*it);
-
-    TrackId track = context_->track_tracker->InternSoftirqCounterTrack(
-        num_softirq_name_id_, ic.irq());
-    context_->event_tracker->PushCounter(ts, ic.count(), track);
-  }
-
-  if (sys_stats.has_num_forks()) {
-    TrackId track =
-        context_->track_tracker->InternGlobalCounterTrack(num_forks_name_id_);
-    context_->event_tracker->PushCounter(ts, sys_stats.num_forks(), track);
-  }
-
-  if (sys_stats.has_num_irq_total()) {
-    TrackId track = context_->track_tracker->InternGlobalCounterTrack(
-        num_irq_total_name_id_);
-    context_->event_tracker->PushCounter(ts, sys_stats.num_irq_total(), track);
-  }
-
-  if (sys_stats.has_num_softirq_total()) {
-    TrackId track = context_->track_tracker->InternGlobalCounterTrack(
-        num_softirq_total_name_id_);
-    context_->event_tracker->PushCounter(ts, sys_stats.num_softirq_total(),
-                                         track);
-  }
-}
-
-void SystemProbesParser::ParseProcessTree(ConstBytes blob) {
-  protos::pbzero::ProcessTree::Decoder ps(blob.data, blob.size);
-
-  for (auto it = ps.processes(); it; ++it) {
-    protos::pbzero::ProcessTree::Process::Decoder proc(*it);
-    if (!proc.has_cmdline())
-      continue;
-    auto pid = static_cast<uint32_t>(proc.pid());
-    auto ppid = static_cast<uint32_t>(proc.ppid());
-
-    // If the parent pid is kthreadd's pid, even though this pid is of a
-    // "process", we want to treat it as being a child thread of kthreadd.
-    if (ppid == kKthreaddPid) {
-      context_->process_tracker->SetProcessMetadata(kKthreaddPid, base::nullopt,
-                                                    kKthreaddName);
-      context_->process_tracker->UpdateThread(pid, kKthreaddPid);
-    } else {
-      auto args = proc.cmdline();
-      base::StringView argv0 = args ? *args : base::StringView();
-      context_->process_tracker->SetProcessMetadata(pid, ppid, argv0);
-    }
-  }
-
-  for (auto it = ps.threads(); it; ++it) {
-    protos::pbzero::ProcessTree::Thread::Decoder thd(*it);
-    auto tid = static_cast<uint32_t>(thd.tid());
-    auto tgid = static_cast<uint32_t>(thd.tgid());
-    context_->process_tracker->UpdateThread(tid, tgid);
-
-    if (thd.has_name()) {
-      StringId threadNameId = context_->storage->InternString(thd.name());
-      context_->process_tracker->UpdateThreadName(tid, threadNameId);
-    }
-  }
-}
-
-void SystemProbesParser::ParseProcessStats(int64_t ts, ConstBytes blob) {
-  protos::pbzero::ProcessStats::Decoder stats(blob.data, blob.size);
-  const auto kOomScoreAdjFieldNumber =
-      protos::pbzero::ProcessStats::Process::kOomScoreAdjFieldNumber;
-  for (auto it = stats.processes(); it; ++it) {
-    // Maps a process counter field it to its value.
-    // E.g., 4 := 1024 -> "mem.rss.anon" := 1024.
-    std::array<int64_t, kProcStatsProcessSize> counter_values{};
-    std::array<bool, kProcStatsProcessSize> has_counter{};
-
-    protozero::ProtoDecoder proc(*it);
-    uint32_t pid = 0;
-    for (auto fld = proc.ReadField(); fld.valid(); fld = proc.ReadField()) {
-      if (fld.id() == protos::pbzero::ProcessStats::Process::kPidFieldNumber) {
-        pid = fld.as_uint32();
-        continue;
-      }
-      bool is_counter_field = fld.id() < proc_stats_process_names_.size() &&
-                              proc_stats_process_names_[fld.id()] != 0;
-      if (is_counter_field) {
-        // Memory counters are in KB, keep values in bytes in the trace
-        // processor.
-        counter_values[fld.id()] = fld.id() == kOomScoreAdjFieldNumber
-                                       ? fld.as_int64()
-                                       : fld.as_int64() * 1024;
-        has_counter[fld.id()] = true;
-      } else {
-        context_->storage->IncrementStats(stats::proc_stat_unknown_counters);
-      }
-    }
-
-    // Skip field_id 0 (invalid) and 1 (pid).
-    for (size_t field_id = 2; field_id < counter_values.size(); field_id++) {
-      if (!has_counter[field_id])
-        continue;
-
-      // Lookup the interned string id from the field name using the
-      // pre-cached |proc_stats_process_names_| map.
-      StringId name = proc_stats_process_names_[field_id];
-      int64_t value = counter_values[field_id];
-      UniquePid upid = context_->process_tracker->GetOrCreateProcess(pid);
-      TrackId track =
-          context_->track_tracker->InternProcessCounterTrack(name, upid);
-      context_->event_tracker->PushCounter(ts, value, track);
-    }
-  }
-}
-
-void SystemProbesParser::ParseSystemInfo(ConstBytes blob) {
-  protos::pbzero::SystemInfo::Decoder packet(blob.data, blob.size);
-  if (packet.has_utsname()) {
-    ConstBytes utsname_blob = packet.utsname();
-    protos::pbzero::Utsname::Decoder utsname(utsname_blob.data,
-                                             utsname_blob.size);
-    base::StringView machine = utsname.machine();
-    if (machine == "aarch64" || machine == "armv8l") {
-      context_->syscall_tracker->SetArchitecture(kAarch64);
-    } else if (machine == "x86_64") {
-      context_->syscall_tracker->SetArchitecture(kX86_64);
-    } else {
-      PERFETTO_ELOG("Unknown architecture %s", machine.ToStdString().c_str());
-    }
-  }
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/system_probes_parser.h b/src/trace_processor/importers/proto/system_probes_parser.h
deleted file mode 100644
index 8dcd810..0000000
--- a/src/trace_processor/importers/proto/system_probes_parser.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_SYSTEM_PROBES_PARSER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_SYSTEM_PROBES_PARSER_H_
-
-#include <vector>
-
-#include "perfetto/protozero/field.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-class SystemProbesParser {
- public:
-  using ConstBytes = protozero::ConstBytes;
-
-  explicit SystemProbesParser(TraceProcessorContext*);
-
-  void ParseProcessTree(ConstBytes);
-  void ParseProcessStats(int64_t timestamp, ConstBytes);
-  void ParseSysStats(int64_t ts, ConstBytes);
-  void ParseSystemInfo(ConstBytes);
-
- private:
-  TraceProcessorContext* const context_;
-
-  const StringId utid_name_id_;
-  const StringId num_forks_name_id_;
-  const StringId num_irq_total_name_id_;
-  const StringId num_softirq_total_name_id_;
-  const StringId num_irq_name_id_;
-  const StringId num_softirq_name_id_;
-  const StringId cpu_times_user_ns_id_;
-  const StringId cpu_times_user_nice_ns_id_;
-  const StringId cpu_times_system_mode_ns_id_;
-  const StringId cpu_times_idle_ns_id_;
-  const StringId cpu_times_io_wait_ns_id_;
-  const StringId cpu_times_irq_ns_id_;
-  const StringId cpu_times_softirq_ns_id_;
-  const StringId oom_score_adj_id_;
-  std::vector<StringId> meminfo_strs_id_;
-  std::vector<StringId> vmstat_strs_id_;
-
-  // Maps a proto field number for memcounters in ProcessStats::Process to
-  // their StringId. Keep kProcStatsProcessSize equal to 1 + max proto field
-  // id of ProcessStats::Process.
-  static constexpr size_t kProcStatsProcessSize = 11;
-  std::array<StringId, kProcStatsProcessSize> proc_stats_process_names_{};
-};
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_SYSTEM_PROBES_PARSER_H_
diff --git a/src/trace_processor/importers/proto/track_event_module.h b/src/trace_processor/importers/proto/track_event_module.h
deleted file mode 100644
index b58b8bc..0000000
--- a/src/trace_processor/importers/proto/track_event_module.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_MODULE_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_MODULE_H_
-
-#include "perfetto/base/build_config.h"
-#include "src/trace_processor/importers/proto/proto_importer_module.h"
-#include "src/trace_processor/importers/proto/track_event_parser.h"
-#include "src/trace_processor/importers/proto/track_event_tokenizer.h"
-#include "src/trace_processor/timestamped_trace_piece.h"
-
-#include "protos/perfetto/config/trace_config.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TrackEventModule : public ProtoImporterModuleBase</*IsEnabled=*/1> {
- public:
-  explicit TrackEventModule(TraceProcessorContext* context)
-      : ProtoImporterModuleBase(context),
-        tokenizer_(context),
-        parser_(context) {}
-
-  ModuleResult TokenizePacket(
-      const protos::pbzero::TracePacket::Decoder& decoder,
-      TraceBlobView* packet,
-      int64_t packet_timestamp,
-      PacketSequenceState* state) {
-    if (decoder.has_track_descriptor()) {
-      tokenizer_.TokenizeTrackDescriptorPacket(decoder);
-      return ModuleResult::Handled();
-    }
-
-    if (decoder.has_track_event()) {
-      tokenizer_.TokenizeTrackEventPacket(state, decoder, packet,
-                                          packet_timestamp);
-      return ModuleResult::Handled();
-    }
-
-    // TODO(eseckler): Remove these once Chrome has switched fully over to
-    // TrackDescriptors.
-    if (decoder.has_thread_descriptor()) {
-      tokenizer_.TokenizeThreadDescriptorPacket(state, decoder);
-      return ModuleResult::Handled();
-    }
-    if (decoder.has_process_descriptor()) {
-      tokenizer_.TokenizeProcessDescriptorPacket(decoder);
-      return ModuleResult::Handled();
-    }
-
-    return ModuleResult::Ignored();
-  }
-
-  ModuleResult ParsePacket(const protos::pbzero::TracePacket::Decoder& decoder,
-                           const TimestampedTracePiece& ttp) {
-    if (decoder.has_track_event()) {
-      parser_.ParseTrackEvent(
-          ttp.timestamp, ttp.thread_timestamp, ttp.thread_instruction_count,
-          ttp.packet_sequence_state, ttp.packet_sequence_state_generation,
-          decoder.track_event());
-      return ModuleResult::Handled();
-    }
-    return ModuleResult::Ignored();
-  }
-
- private:
-  TrackEventTokenizer tokenizer_;
-  TrackEventParser parser_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_MODULE_H_
diff --git a/src/trace_processor/importers/proto/track_event_parser.cc b/src/trace_processor/importers/proto/track_event_parser.cc
deleted file mode 100644
index 721775c..0000000
--- a/src/trace_processor/importers/proto/track_event_parser.cc
+++ /dev/null
@@ -1,916 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/importers/proto/track_event_parser.h"
-
-#include <string>
-
-#include "perfetto/base/logging.h"
-#include "src/trace_processor/args_tracker.h"
-#include "src/trace_processor/importers/proto/packet_sequence_state.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/track_tracker.h"
-
-#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
-#include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
-#include "protos/perfetto/trace/track_event/log_message.pbzero.h"
-#include "protos/perfetto/trace/track_event/source_location.pbzero.h"
-#include "protos/perfetto/trace/track_event/task_execution.pbzero.h"
-#include "protos/perfetto/trace/track_event/track_event.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-using protozero::ConstBytes;
-
-// Slices which have been opened but haven't been closed yet will be marked
-// with these placeholder values.
-constexpr int64_t kPendingThreadDuration = -1;
-constexpr int64_t kPendingThreadInstructionDelta = -1;
-}  // namespace
-
-TrackEventParser::TrackEventParser(TraceProcessorContext* context)
-    : context_(context),
-      task_file_name_args_key_id_(
-          context->storage->InternString("task.posted_from.file_name")),
-      task_function_name_args_key_id_(
-          context->storage->InternString("task.posted_from.function_name")),
-      task_line_number_args_key_id_(
-          context->storage->InternString("task.posted_from.line_number")),
-      log_message_body_key_id_(
-          context->storage->InternString("track_event.log_message")),
-      raw_legacy_event_id_(
-          context->storage->InternString("track_event.legacy_event")),
-      legacy_event_original_tid_id_(
-          context->storage->InternString("legacy_event.original_tid")),
-      legacy_event_category_key_id_(
-          context->storage->InternString("legacy_event.category")),
-      legacy_event_name_key_id_(
-          context->storage->InternString("legacy_event.name")),
-      legacy_event_phase_key_id_(
-          context->storage->InternString("legacy_event.phase")),
-      legacy_event_duration_ns_key_id_(
-          context->storage->InternString("legacy_event.duration_ns")),
-      legacy_event_thread_timestamp_ns_key_id_(
-          context->storage->InternString("legacy_event.thread_timestamp_ns")),
-      legacy_event_thread_duration_ns_key_id_(
-          context->storage->InternString("legacy_event.thread_duration_ns")),
-      legacy_event_thread_instruction_count_key_id_(
-          context->storage->InternString(
-              "legacy_event.thread_instruction_count")),
-      legacy_event_thread_instruction_delta_key_id_(
-          context->storage->InternString(
-              "legacy_event.thread_instruction_delta")),
-      legacy_event_use_async_tts_key_id_(
-          context->storage->InternString("legacy_event.use_async_tts")),
-      legacy_event_unscoped_id_key_id_(
-          context->storage->InternString("legacy_event.unscoped_id")),
-      legacy_event_global_id_key_id_(
-          context->storage->InternString("legacy_event.global_id")),
-      legacy_event_local_id_key_id_(
-          context->storage->InternString("legacy_event.local_id")),
-      legacy_event_id_scope_key_id_(
-          context->storage->InternString("legacy_event.id_scope")),
-      legacy_event_bind_id_key_id_(
-          context->storage->InternString("legacy_event.bind_id")),
-      legacy_event_bind_to_enclosing_key_id_(
-          context->storage->InternString("legacy_event.bind_to_enclosing")),
-      legacy_event_flow_direction_key_id_(
-          context->storage->InternString("legacy_event.flow_direction")),
-      flow_direction_value_in_id_(context->storage->InternString("in")),
-      flow_direction_value_out_id_(context->storage->InternString("out")),
-      flow_direction_value_inout_id_(context->storage->InternString("inout")) {}
-
-void TrackEventParser::ParseTrackEvent(int64_t ts,
-                                       int64_t tts,
-                                       int64_t ticount,
-                                       PacketSequenceState* sequence_state,
-                                       size_t sequence_state_generation,
-                                       ConstBytes blob) {
-  using LegacyEvent = protos::pbzero::TrackEvent::LegacyEvent;
-
-  protos::pbzero::TrackEvent::Decoder event(blob.data, blob.size);
-
-  const auto legacy_event_blob = event.legacy_event();
-  LegacyEvent::Decoder legacy_event(legacy_event_blob.data,
-                                    legacy_event_blob.size);
-
-  // TODO(eseckler): This legacy event field will eventually be replaced by
-  // fields in TrackEvent itself.
-  if (PERFETTO_UNLIKELY(!event.type() && !legacy_event.has_phase())) {
-    context_->storage->IncrementStats(stats::track_event_parser_errors);
-    PERFETTO_DLOG("TrackEvent without type or phase");
-    return;
-  }
-
-  ProcessTracker* procs = context_->process_tracker.get();
-  TraceStorage* storage = context_->storage.get();
-  TrackTracker* track_tracker = context_->track_tracker.get();
-  SliceTracker* slice_tracker = context_->slice_tracker.get();
-
-  std::vector<uint64_t> category_iids;
-  for (auto it = event.category_iids(); it; ++it) {
-    category_iids.push_back(*it);
-  }
-  std::vector<protozero::ConstChars> category_strings;
-  for (auto it = event.categories(); it; ++it) {
-    category_strings.push_back(*it);
-  }
-
-  StringId category_id = 0;
-
-  // If there's a single category, we can avoid building a concatenated
-  // string.
-  if (PERFETTO_LIKELY(category_iids.size() == 1 && category_strings.empty())) {
-    auto* decoder = sequence_state->LookupInternedMessage<
-        protos::pbzero::InternedData::kEventCategoriesFieldNumber,
-        protos::pbzero::EventCategory>(sequence_state_generation,
-                                       category_iids[0]);
-    if (decoder)
-      category_id = storage->InternString(decoder->name());
-  } else if (category_iids.empty() && category_strings.size() == 1) {
-    category_id = storage->InternString(category_strings[0]);
-  } else if (category_iids.size() + category_strings.size() > 1) {
-    // We concatenate the category strings together since we currently only
-    // support a single "cat" column.
-    // TODO(eseckler): Support multi-category events in the table schema.
-    std::string categories;
-    for (uint64_t iid : category_iids) {
-      auto* decoder = sequence_state->LookupInternedMessage<
-          protos::pbzero::InternedData::kEventCategoriesFieldNumber,
-          protos::pbzero::EventCategory>(sequence_state_generation, iid);
-      if (!decoder)
-        continue;
-      base::StringView name = decoder->name();
-      if (!categories.empty())
-        categories.append(",");
-      categories.append(name.data(), name.size());
-    }
-    for (const protozero::ConstChars& cat : category_strings) {
-      if (!categories.empty())
-        categories.append(",");
-      categories.append(cat.data, cat.size);
-    }
-    if (!categories.empty())
-      category_id = storage->InternString(base::StringView(categories));
-  }
-
-  StringId name_id = 0;
-
-  uint64_t name_iid = event.name_iid();
-  if (!name_iid)
-    name_iid = legacy_event.name_iid();
-
-  if (PERFETTO_LIKELY(name_iid)) {
-    auto* decoder = sequence_state->LookupInternedMessage<
-        protos::pbzero::InternedData::kEventNamesFieldNumber,
-        protos::pbzero::EventName>(sequence_state_generation, name_iid);
-    if (decoder)
-      name_id = storage->InternString(decoder->name());
-  } else if (event.has_name()) {
-    name_id = storage->InternString(event.name());
-  }
-
-  // TODO(eseckler): Also consider track_uuid from TrackEventDefaults.
-  // Fall back to the default descriptor track (uuid 0).
-  uint64_t track_uuid = event.has_track_uuid() ? event.track_uuid() : 0u;
-  TrackId track_id;
-  base::Optional<UniqueTid> utid;
-  base::Optional<UniqueTid> upid;
-
-  // Determine track from track_uuid specified in either TrackEvent or
-  // TrackEventDefaults. If none is set, fall back to the track specified by the
-  // sequence's (or event's) pid + tid or a default track.
-  if (track_uuid) {
-    base::Optional<TrackId> opt_track_id =
-        track_tracker->GetDescriptorTrack(track_uuid);
-    if (!opt_track_id) {
-      storage->IncrementStats(stats::track_event_parser_errors);
-      PERFETTO_DLOG("TrackEvent with unknown track_uuid %" PRIu64, track_uuid);
-      return;
-    }
-    track_id = *opt_track_id;
-
-    auto thread_track_row =
-        context_->storage->thread_track_table().id().IndexOf(
-            SqlValue::Long(track_id));
-    if (thread_track_row) {
-      utid = storage->thread_track_table().utid()[*thread_track_row];
-      upid = storage->GetThread(*utid).upid;
-    } else {
-      auto process_track_row =
-          context_->storage->process_track_table().id().IndexOf(
-              SqlValue::Long(track_id));
-      if (process_track_row)
-        upid = storage->process_track_table().upid()[*process_track_row];
-    }
-  } else if (sequence_state->pid_and_tid_valid() ||
-             (legacy_event.has_pid_override() &&
-              legacy_event.has_tid_override())) {
-    uint32_t pid = static_cast<uint32_t>(sequence_state->pid());
-    uint32_t tid = static_cast<uint32_t>(sequence_state->tid());
-    if (legacy_event.has_pid_override())
-      pid = static_cast<uint32_t>(legacy_event.pid_override());
-    if (legacy_event.has_tid_override())
-      tid = static_cast<uint32_t>(legacy_event.tid_override());
-
-    utid = procs->UpdateThread(tid, pid);
-    upid = storage->GetThread(*utid).upid;
-    track_id = track_tracker->GetOrCreateDescriptorTrackForThread(*utid);
-  } else {
-    track_id = track_tracker->GetOrCreateDefaultDescriptorTrack();
-  }
-
-  // All events in legacy JSON require a thread ID, but for some types of events
-  // (e.g. async events or process/global-scoped instants), we don't store it in
-  // the slice/track model. To pass the original tid through to the json export,
-  // we store it in an arg.
-  uint32_t legacy_tid = 0;
-
-  // TODO(eseckler): Replace phase with type and remove handling of
-  // legacy_event.phase() once it is no longer used by producers.
-  int32_t phase = 0;
-  if (legacy_event.has_phase()) {
-    phase = legacy_event.phase();
-
-    switch (phase) {
-      case 'b':
-      case 'e':
-      case 'n': {
-        // Intern tracks for legacy async events based on legacy event ids.
-        int64_t source_id = 0;
-        bool source_id_is_process_scoped = false;
-        if (legacy_event.has_unscoped_id()) {
-          source_id = static_cast<int64_t>(legacy_event.unscoped_id());
-        } else if (legacy_event.has_global_id()) {
-          source_id = static_cast<int64_t>(legacy_event.global_id());
-        } else if (legacy_event.has_local_id()) {
-          if (!upid) {
-            storage->IncrementStats(stats::track_event_parser_errors);
-            PERFETTO_DLOG(
-                "TrackEvent with local_id without process association");
-            return;
-          }
-
-          source_id = static_cast<int64_t>(legacy_event.local_id());
-          source_id_is_process_scoped = true;
-        } else {
-          storage->IncrementStats(stats::track_event_parser_errors);
-          PERFETTO_DLOG("Async LegacyEvent without ID");
-          return;
-        }
-
-        // Catapult treats nestable async events of different categories with
-        // the same ID as separate tracks. We replicate the same behavior here.
-        StringId id_scope = category_id;
-        if (legacy_event.has_id_scope()) {
-          std::string concat = storage->GetString(category_id).ToStdString() +
-                               ":" + legacy_event.id_scope().ToStdString();
-          id_scope = storage->InternString(base::StringView(concat));
-        }
-
-        track_id = context_->track_tracker->InternLegacyChromeAsyncTrack(
-            name_id, upid ? *upid : 0, source_id, source_id_is_process_scoped,
-            id_scope);
-        if (utid)
-          legacy_tid = storage->GetThread(*utid).tid;
-        break;
-      }
-      case 'i':
-      case 'I': {
-        // Intern tracks for global or process-scoped legacy instant events.
-        switch (legacy_event.instant_event_scope()) {
-          case LegacyEvent::SCOPE_UNSPECIFIED:
-          case LegacyEvent::SCOPE_THREAD:
-            // Thread-scoped legacy instant events already have the right track
-            // based on the tid/pid of the sequence.
-            if (!utid) {
-              storage->IncrementStats(stats::track_event_parser_errors);
-              PERFETTO_DLOG(
-                  "Thread-scoped instant event without thread association");
-              return;
-            }
-            break;
-          case LegacyEvent::SCOPE_GLOBAL:
-            track_id = context_->track_tracker
-                           ->GetOrCreateLegacyChromeGlobalInstantTrack();
-            if (utid)
-              legacy_tid = storage->GetThread(*utid).tid;
-            break;
-          case LegacyEvent::SCOPE_PROCESS:
-            if (!upid) {
-              storage->IncrementStats(stats::track_event_parser_errors);
-              PERFETTO_DLOG(
-                  "Process-scoped instant event without process association");
-              return;
-            }
-
-            track_id =
-                context_->track_tracker->InternLegacyChromeProcessInstantTrack(
-                    *upid);
-            if (utid)
-              legacy_tid = storage->GetThread(*utid).tid;
-            break;
-        }
-        break;
-      }
-      default:
-        break;
-    }
-  } else {
-    switch (event.type()) {
-      case protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN:
-        phase = utid ? 'B' : 'b';
-        break;
-      case protos::pbzero::TrackEvent::TYPE_SLICE_END:
-        phase = utid ? 'E' : 'e';
-        break;
-      case protos::pbzero::TrackEvent::TYPE_INSTANT:
-        phase = utid ? 'i' : 'n';
-        break;
-      default:
-        PERFETTO_FATAL("unexpected event type %d", event.type());
-        return;
-    }
-  }
-
-  auto args_callback = [this, &event, &legacy_event, &sequence_state,
-                        sequence_state_generation, ts, utid,
-                        legacy_tid](ArgsTracker* args_tracker, RowId row_id) {
-    for (auto it = event.debug_annotations(); it; ++it) {
-      ParseDebugAnnotationArgs(*it, sequence_state, sequence_state_generation,
-                               args_tracker, row_id);
-    }
-
-    if (event.has_task_execution()) {
-      ParseTaskExecutionArgs(event.task_execution(), sequence_state,
-                             sequence_state_generation, args_tracker, row_id);
-    }
-
-    if (event.has_log_message()) {
-      ParseLogMessage(event.log_message(), sequence_state,
-                      sequence_state_generation, ts, utid, args_tracker,
-                      row_id);
-    }
-
-    if (legacy_tid) {
-      args_tracker->AddArg(row_id, legacy_event_original_tid_id_,
-                           legacy_event_original_tid_id_,
-                           Variadic::Integer(static_cast<int32_t>(legacy_tid)));
-    }
-
-    // TODO(eseckler): Parse legacy flow events into flow events table once we
-    // have a design for it.
-    if (legacy_event.has_bind_id()) {
-      args_tracker->AddArg(row_id, legacy_event_bind_id_key_id_,
-                           legacy_event_bind_id_key_id_,
-                           Variadic::UnsignedInteger(legacy_event.bind_id()));
-    }
-
-    if (legacy_event.bind_to_enclosing()) {
-      args_tracker->AddArg(row_id, legacy_event_bind_to_enclosing_key_id_,
-                           legacy_event_bind_to_enclosing_key_id_,
-                           Variadic::Boolean(true));
-    }
-
-    if (legacy_event.flow_direction()) {
-      StringId value;
-      switch (legacy_event.flow_direction()) {
-        case protos::pbzero::TrackEvent::LegacyEvent::FLOW_IN:
-          value = flow_direction_value_in_id_;
-          break;
-        case protos::pbzero::TrackEvent::LegacyEvent::FLOW_OUT:
-          value = flow_direction_value_out_id_;
-          break;
-        case protos::pbzero::TrackEvent::LegacyEvent::FLOW_INOUT:
-          value = flow_direction_value_inout_id_;
-          break;
-        default:
-          PERFETTO_FATAL("Unknown flow direction: %d",
-                         legacy_event.flow_direction());
-          break;
-      }
-      args_tracker->AddArg(row_id, legacy_event_flow_direction_key_id_,
-                           legacy_event_flow_direction_key_id_,
-                           Variadic::String(value));
-    }
-  };
-
-  switch (static_cast<char>(phase)) {
-    case 'B': {  // TRACE_EVENT_PHASE_BEGIN.
-      if (!utid) {
-        storage->IncrementStats(stats::track_event_parser_errors);
-        PERFETTO_DLOG("TrackEvent with phase B without thread association");
-        return;
-      }
-
-      auto opt_slice_id =
-          slice_tracker->Begin(ts, track_id, *utid, RefType::kRefUtid,
-                               category_id, name_id, args_callback);
-      if (opt_slice_id.has_value()) {
-        auto* thread_slices = storage->mutable_thread_slices();
-        PERFETTO_DCHECK(!thread_slices->slice_count() ||
-                        thread_slices->slice_ids().back() <
-                            opt_slice_id.value());
-        thread_slices->AddThreadSlice(opt_slice_id.value(), tts,
-                                      kPendingThreadDuration, ticount,
-                                      kPendingThreadInstructionDelta);
-      }
-      break;
-    }
-    case 'E': {  // TRACE_EVENT_PHASE_END.
-      if (!utid) {
-        storage->IncrementStats(stats::track_event_parser_errors);
-        PERFETTO_DLOG("TrackEvent with phase E without thread association");
-        return;
-      }
-
-      auto opt_slice_id =
-          slice_tracker->End(ts, track_id, category_id, name_id, args_callback);
-      if (opt_slice_id.has_value()) {
-        auto* thread_slices = storage->mutable_thread_slices();
-        thread_slices->UpdateThreadDeltasForSliceId(opt_slice_id.value(), tts,
-                                                    ticount);
-      }
-      break;
-    }
-    case 'X': {  // TRACE_EVENT_PHASE_COMPLETE.
-      if (!utid) {
-        storage->IncrementStats(stats::track_event_parser_errors);
-        PERFETTO_DLOG("TrackEvent with phase X without thread association");
-        return;
-      }
-
-      auto duration_ns = legacy_event.duration_us() * 1000;
-      if (duration_ns < 0)
-        return;
-      auto opt_slice_id = slice_tracker->Scoped(
-          ts, track_id, *utid, RefType::kRefUtid, category_id, name_id,
-          duration_ns, args_callback);
-      if (opt_slice_id.has_value()) {
-        auto* thread_slices = storage->mutable_thread_slices();
-        PERFETTO_DCHECK(!thread_slices->slice_count() ||
-                        thread_slices->slice_ids().back() <
-                            opt_slice_id.value());
-        auto thread_duration_ns = legacy_event.thread_duration_us() * 1000;
-        thread_slices->AddThreadSlice(opt_slice_id.value(), tts,
-                                      thread_duration_ns, ticount,
-                                      legacy_event.thread_instruction_delta());
-      }
-      break;
-    }
-    case 'i':
-    case 'I': {  // TRACE_EVENT_PHASE_INSTANT.
-      // Handle instant events as slices with zero duration, so that they end
-      // up nested underneath their parent slices.
-      int64_t duration_ns = 0;
-      int64_t tidelta = 0;
-
-      switch (legacy_event.instant_event_scope()) {
-        case LegacyEvent::SCOPE_UNSPECIFIED:
-        case LegacyEvent::SCOPE_THREAD: {
-          // TODO(lalitm): Associate thread slices with track instead.
-          auto opt_slice_id = slice_tracker->Scoped(
-              ts, track_id, *utid, RefType::kRefUtid, category_id, name_id,
-              duration_ns, args_callback);
-          if (opt_slice_id.has_value()) {
-            auto* thread_slices = storage->mutable_thread_slices();
-            PERFETTO_DCHECK(!thread_slices->slice_count() ||
-                            thread_slices->slice_ids().back() <
-                                opt_slice_id.value());
-            thread_slices->AddThreadSlice(opt_slice_id.value(), tts,
-                                          duration_ns, ticount, tidelta);
-          }
-          break;
-        }
-        case LegacyEvent::SCOPE_GLOBAL: {
-          slice_tracker->Scoped(ts, track_id, /*ref=*/0, RefType::kRefNoRef,
-                                category_id, name_id, duration_ns,
-                                args_callback);
-          break;
-        }
-        case LegacyEvent::SCOPE_PROCESS: {
-          slice_tracker->Scoped(ts, track_id, *upid, RefType::kRefUpid,
-                                category_id, name_id, duration_ns,
-                                args_callback);
-          break;
-        }
-        default: {
-          PERFETTO_FATAL("Unknown instant event scope: %u",
-                         legacy_event.instant_event_scope());
-          break;
-        }
-      }
-      break;
-    }
-    case 'b': {  // TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN
-      auto opt_slice_id =
-          slice_tracker->Begin(ts, track_id, track_id, RefType::kRefTrack,
-                               category_id, name_id, args_callback);
-      // For the time beeing, we only create vtrack slice rows if we need to
-      // store thread timestamps/counters.
-      if (legacy_event.use_async_tts() && opt_slice_id.has_value()) {
-        auto* vtrack_slices = storage->mutable_virtual_track_slices();
-        PERFETTO_DCHECK(!vtrack_slices->slice_count() ||
-                        vtrack_slices->slice_ids().back() <
-                            opt_slice_id.value());
-        vtrack_slices->AddVirtualTrackSlice(opt_slice_id.value(), tts,
-                                            kPendingThreadDuration, ticount,
-                                            kPendingThreadInstructionDelta);
-      }
-      break;
-    }
-    case 'e': {  // TRACE_EVENT_PHASE_NESTABLE_ASYNC_END
-      auto opt_slice_id =
-          slice_tracker->End(ts, track_id, category_id, name_id, args_callback);
-      if (legacy_event.use_async_tts() && opt_slice_id.has_value()) {
-        auto* vtrack_slices = storage->mutable_virtual_track_slices();
-        vtrack_slices->UpdateThreadDeltasForSliceId(opt_slice_id.value(), tts,
-                                                    ticount);
-      }
-      break;
-    }
-    case 'n': {  // TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT
-      // Handle instant events as slices with zero duration, so that they end up
-      // nested underneath their parent slices.
-      int64_t duration_ns = 0;
-      int64_t tidelta = 0;
-      auto opt_slice_id = slice_tracker->Scoped(
-          ts, track_id, track_id, RefType::kRefTrack, category_id, name_id,
-          duration_ns, args_callback);
-      if (legacy_event.use_async_tts() && opt_slice_id.has_value()) {
-        auto* vtrack_slices = storage->mutable_virtual_track_slices();
-        PERFETTO_DCHECK(!vtrack_slices->slice_count() ||
-                        vtrack_slices->slice_ids().back() <
-                            opt_slice_id.value());
-        vtrack_slices->AddVirtualTrackSlice(opt_slice_id.value(), tts,
-                                            duration_ns, ticount, tidelta);
-      }
-      break;
-    }
-    case 'M': {  // TRACE_EVENT_PHASE_METADATA (process and thread names).
-      // Parse process and thread names from correspondingly named events.
-      // TODO(eseckler): Also consider names from process/thread descriptors.
-      NullTermStringView event_name = storage->GetString(name_id);
-      PERFETTO_DCHECK(event_name.data());
-      if (strcmp(event_name.c_str(), "thread_name") == 0) {
-        if (!utid) {
-          storage->IncrementStats(stats::track_event_parser_errors);
-          PERFETTO_DLOG(
-              "thread_name metadata event without thread association");
-          return;
-        }
-
-        auto it = event.debug_annotations();
-        if (!it)
-          break;
-        protos::pbzero::DebugAnnotation::Decoder annotation(*it);
-        auto thread_name = annotation.string_value();
-        if (!thread_name.size)
-          break;
-        auto thread_name_id = storage->InternString(thread_name);
-        // Don't override system-provided names.
-        procs->SetThreadNameIfUnset(*utid, thread_name_id);
-        break;
-      }
-      if (strcmp(event_name.c_str(), "process_name") == 0) {
-        if (!upid) {
-          storage->IncrementStats(stats::track_event_parser_errors);
-          PERFETTO_DLOG(
-              "process_name metadata event without process association");
-          return;
-        }
-
-        auto it = event.debug_annotations();
-        if (!it)
-          break;
-        protos::pbzero::DebugAnnotation::Decoder annotation(*it);
-        auto process_name = annotation.string_value();
-        if (!process_name.size)
-          break;
-        auto process_name_id = storage->InternString(process_name);
-        // Don't override system-provided names.
-        procs->SetProcessNameIfUnset(*upid, process_name_id);
-        break;
-      }
-      // Other metadata events are proxied via the raw table for JSON export.
-      ParseLegacyEventAsRawEvent(ts, tts, ticount, utid, category_id, name_id,
-                                 legacy_event, args_callback);
-      break;
-    }
-    default: {
-      // Other events are proxied via the raw table for JSON export.
-      ParseLegacyEventAsRawEvent(ts, tts, ticount, utid, category_id, name_id,
-                                 legacy_event, args_callback);
-    }
-  }
-}
-
-void TrackEventParser::ParseLegacyEventAsRawEvent(
-    int64_t ts,
-    int64_t tts,
-    int64_t ticount,
-    base::Optional<UniqueTid> utid,
-    StringId category_id,
-    StringId name_id,
-    const protos::pbzero::TrackEvent::LegacyEvent::Decoder& legacy_event,
-    SliceTracker::SetArgsCallback args_callback) {
-  if (!utid) {
-    context_->storage->IncrementStats(stats::track_event_parser_errors);
-    PERFETTO_DLOG("raw legacy event without thread association");
-    return;
-  }
-
-  RowId row_id = context_->storage->mutable_raw_events()->AddRawEvent(
-      ts, raw_legacy_event_id_, 0, *utid);
-  ArgsTracker args(context_);
-  args.AddArg(row_id, legacy_event_category_key_id_,
-              legacy_event_category_key_id_, Variadic::String(category_id));
-  args.AddArg(row_id, legacy_event_name_key_id_, legacy_event_name_key_id_,
-              Variadic::String(name_id));
-
-  std::string phase_string(1, static_cast<char>(legacy_event.phase()));
-  StringId phase_id = context_->storage->InternString(phase_string.c_str());
-  args.AddArg(row_id, legacy_event_phase_key_id_, legacy_event_phase_key_id_,
-              Variadic::String(phase_id));
-
-  if (legacy_event.has_duration_us()) {
-    args.AddArg(row_id, legacy_event_duration_ns_key_id_,
-                legacy_event_duration_ns_key_id_,
-                Variadic::Integer(legacy_event.duration_us() * 1000));
-  }
-
-  if (tts) {
-    args.AddArg(row_id, legacy_event_thread_timestamp_ns_key_id_,
-                legacy_event_thread_timestamp_ns_key_id_,
-                Variadic::Integer(tts));
-    if (legacy_event.has_thread_duration_us()) {
-      args.AddArg(row_id, legacy_event_thread_duration_ns_key_id_,
-                  legacy_event_thread_duration_ns_key_id_,
-                  Variadic::Integer(legacy_event.thread_duration_us() * 1000));
-    }
-  }
-
-  if (ticount) {
-    args.AddArg(row_id, legacy_event_thread_instruction_count_key_id_,
-                legacy_event_thread_instruction_count_key_id_,
-                Variadic::Integer(tts));
-    if (legacy_event.has_thread_instruction_delta()) {
-      args.AddArg(row_id, legacy_event_thread_instruction_delta_key_id_,
-                  legacy_event_thread_instruction_delta_key_id_,
-                  Variadic::Integer(legacy_event.thread_instruction_delta()));
-    }
-  }
-
-  if (legacy_event.use_async_tts()) {
-    args.AddArg(row_id, legacy_event_use_async_tts_key_id_,
-                legacy_event_use_async_tts_key_id_, Variadic::Boolean(true));
-  }
-
-  bool has_id = false;
-  if (legacy_event.has_unscoped_id()) {
-    // Unscoped ids are either global or local depending on the phase. Pass them
-    // through as unscoped IDs to JSON export to preserve this behavior.
-    args.AddArg(row_id, legacy_event_unscoped_id_key_id_,
-                legacy_event_unscoped_id_key_id_,
-                Variadic::UnsignedInteger(legacy_event.unscoped_id()));
-    has_id = true;
-  } else if (legacy_event.has_global_id()) {
-    args.AddArg(row_id, legacy_event_global_id_key_id_,
-                legacy_event_global_id_key_id_,
-                Variadic::UnsignedInteger(legacy_event.global_id()));
-    has_id = true;
-  } else if (legacy_event.has_local_id()) {
-    args.AddArg(row_id, legacy_event_local_id_key_id_,
-                legacy_event_local_id_key_id_,
-                Variadic::UnsignedInteger(legacy_event.local_id()));
-    has_id = true;
-  }
-
-  if (has_id && legacy_event.has_id_scope() && legacy_event.id_scope().size) {
-    args.AddArg(row_id, legacy_event_id_scope_key_id_,
-                legacy_event_id_scope_key_id_,
-                Variadic::String(
-                    context_->storage->InternString(legacy_event.id_scope())));
-  }
-
-  // No need to parse legacy_event.instant_event_scope() because we import
-  // instant events into the slice table.
-
-  args_callback(&args, row_id);
-}
-
-void TrackEventParser::ParseDebugAnnotationArgs(
-    ConstBytes debug_annotation,
-    PacketSequenceState* sequence_state,
-    size_t sequence_state_generation,
-    ArgsTracker* args_tracker,
-    RowId row_id) {
-  TraceStorage* storage = context_->storage.get();
-
-  protos::pbzero::DebugAnnotation::Decoder annotation(debug_annotation.data,
-                                                      debug_annotation.size);
-
-  StringId name_id = 0;
-
-  uint64_t name_iid = annotation.name_iid();
-  if (PERFETTO_LIKELY(name_iid)) {
-    auto* decoder = sequence_state->LookupInternedMessage<
-        protos::pbzero::InternedData::kDebugAnnotationNamesFieldNumber,
-        protos::pbzero::DebugAnnotationName>(sequence_state_generation,
-                                             name_iid);
-    if (!decoder)
-      return;
-
-    std::string name_prefixed = "debug." + decoder->name().ToStdString();
-    name_id = storage->InternString(base::StringView(name_prefixed));
-  } else if (annotation.has_name()) {
-    name_id = storage->InternString(annotation.name());
-  } else {
-    context_->storage->IncrementStats(stats::track_event_parser_errors);
-    PERFETTO_DLOG("Debug annotation without name");
-    return;
-  }
-
-  if (annotation.has_bool_value()) {
-    args_tracker->AddArg(row_id, name_id, name_id,
-                         Variadic::Boolean(annotation.bool_value()));
-  } else if (annotation.has_uint_value()) {
-    args_tracker->AddArg(row_id, name_id, name_id,
-                         Variadic::UnsignedInteger(annotation.uint_value()));
-  } else if (annotation.has_int_value()) {
-    args_tracker->AddArg(row_id, name_id, name_id,
-                         Variadic::Integer(annotation.int_value()));
-  } else if (annotation.has_double_value()) {
-    args_tracker->AddArg(row_id, name_id, name_id,
-                         Variadic::Real(annotation.double_value()));
-  } else if (annotation.has_string_value()) {
-    args_tracker->AddArg(
-        row_id, name_id, name_id,
-        Variadic::String(storage->InternString(annotation.string_value())));
-  } else if (annotation.has_pointer_value()) {
-    args_tracker->AddArg(row_id, name_id, name_id,
-                         Variadic::Pointer(annotation.pointer_value()));
-  } else if (annotation.has_legacy_json_value()) {
-    args_tracker->AddArg(
-        row_id, name_id, name_id,
-        Variadic::Json(storage->InternString(annotation.legacy_json_value())));
-  } else if (annotation.has_nested_value()) {
-    auto name = storage->GetString(name_id);
-    ParseNestedValueArgs(annotation.nested_value(), name, name, args_tracker,
-                         row_id);
-  }
-}
-
-void TrackEventParser::ParseNestedValueArgs(ConstBytes nested_value,
-                                            base::StringView flat_key,
-                                            base::StringView key,
-                                            ArgsTracker* args_tracker,
-                                            RowId row_id) {
-  protos::pbzero::DebugAnnotation::NestedValue::Decoder value(
-      nested_value.data, nested_value.size);
-  switch (value.nested_type()) {
-    case protos::pbzero::DebugAnnotation::NestedValue::UNSPECIFIED: {
-      auto flat_key_id = context_->storage->InternString(flat_key);
-      auto key_id = context_->storage->InternString(key);
-      // Leaf value.
-      if (value.has_bool_value()) {
-        args_tracker->AddArg(row_id, flat_key_id, key_id,
-                             Variadic::Boolean(value.bool_value()));
-      } else if (value.has_int_value()) {
-        args_tracker->AddArg(row_id, flat_key_id, key_id,
-                             Variadic::Integer(value.int_value()));
-      } else if (value.has_double_value()) {
-        args_tracker->AddArg(row_id, flat_key_id, key_id,
-                             Variadic::Real(value.double_value()));
-      } else if (value.has_string_value()) {
-        args_tracker->AddArg(row_id, flat_key_id, key_id,
-                             Variadic::String(context_->storage->InternString(
-                                 value.string_value())));
-      }
-      break;
-    }
-    case protos::pbzero::DebugAnnotation::NestedValue::DICT: {
-      auto key_it = value.dict_keys();
-      auto value_it = value.dict_values();
-      for (; key_it && value_it; ++key_it, ++value_it) {
-        std::string child_name = (*key_it).ToStdString();
-        std::string child_flat_key = flat_key.ToStdString() + "." + child_name;
-        std::string child_key = key.ToStdString() + "." + child_name;
-        ParseNestedValueArgs(*value_it, base::StringView(child_flat_key),
-                             base::StringView(child_key), args_tracker, row_id);
-      }
-      break;
-    }
-    case protos::pbzero::DebugAnnotation::NestedValue::ARRAY: {
-      int child_index = 0;
-      std::string child_flat_key = flat_key.ToStdString();
-      for (auto value_it = value.array_values(); value_it;
-           ++value_it, ++child_index) {
-        std::string child_key =
-            key.ToStdString() + "[" + std::to_string(child_index) + "]";
-        ParseNestedValueArgs(*value_it, base::StringView(child_flat_key),
-                             base::StringView(child_key), args_tracker, row_id);
-      }
-      break;
-    }
-  }
-}
-
-void TrackEventParser::ParseTaskExecutionArgs(
-    ConstBytes task_execution,
-    PacketSequenceState* sequence_state,
-    size_t sequence_state_generation,
-    ArgsTracker* args_tracker,
-    RowId row) {
-  protos::pbzero::TaskExecution::Decoder task(task_execution.data,
-                                              task_execution.size);
-  uint64_t iid = task.posted_from_iid();
-  if (!iid)
-    return;
-
-  auto* decoder = sequence_state->LookupInternedMessage<
-      protos::pbzero::InternedData::kSourceLocationsFieldNumber,
-      protos::pbzero::SourceLocation>(sequence_state_generation, iid);
-  if (!decoder)
-    return;
-
-  StringId file_name_id = 0;
-  StringId function_name_id = 0;
-  uint32_t line_number = 0;
-
-  TraceStorage* storage = context_->storage.get();
-  file_name_id = storage->InternString(decoder->file_name());
-  function_name_id = storage->InternString(decoder->function_name());
-  line_number = decoder->line_number();
-
-  args_tracker->AddArg(row, task_file_name_args_key_id_,
-                       task_file_name_args_key_id_,
-                       Variadic::String(file_name_id));
-  args_tracker->AddArg(row, task_function_name_args_key_id_,
-                       task_function_name_args_key_id_,
-                       Variadic::String(function_name_id));
-
-  args_tracker->AddArg(row, task_line_number_args_key_id_,
-                       task_line_number_args_key_id_,
-                       Variadic::UnsignedInteger(line_number));
-}
-
-void TrackEventParser::ParseLogMessage(ConstBytes blob,
-                                       PacketSequenceState* sequence_state,
-                                       size_t sequence_state_generation,
-                                       int64_t ts,
-                                       base::Optional<UniqueTid> utid,
-                                       ArgsTracker* args_tracker,
-                                       RowId row) {
-  if (!utid) {
-    context_->storage->IncrementStats(stats::track_event_parser_errors);
-    PERFETTO_DLOG("LogMessage without thread association");
-    return;
-  }
-
-  protos::pbzero::LogMessage::Decoder message(blob.data, blob.size);
-
-  TraceStorage* storage = context_->storage.get();
-
-  StringId log_message_id = 0;
-
-  auto* decoder = sequence_state->LookupInternedMessage<
-      protos::pbzero::InternedData::kLogMessageBodyFieldNumber,
-      protos::pbzero::LogMessageBody>(sequence_state_generation,
-                                      message.body_iid());
-  if (!decoder)
-    return;
-
-  log_message_id = storage->InternString(decoder->body());
-
-  // TODO(nicomazz): LogMessage also contains the source of the message (file
-  // and line number). Android logs doesn't support this so far.
-  context_->storage->mutable_android_log()->AddLogEvent(
-      ts, *utid,
-      /*priority*/ 0,
-      /*tag_id*/ 0,  // TODO(nicomazz): Abuse tag_id to display
-                     // "file_name:line_number".
-      log_message_id);
-
-  args_tracker->AddArg(row, log_message_body_key_id_, log_message_body_key_id_,
-                       Variadic::String(log_message_id));
-  // TODO(nicomazz): Add the source location as an argument.
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/track_event_parser.h b/src/trace_processor/importers/proto/track_event_parser.h
deleted file mode 100644
index 0aa072d..0000000
--- a/src/trace_processor/importers/proto/track_event_parser.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_PARSER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_PARSER_H_
-
-#include "perfetto/protozero/field.h"
-#include "src/trace_processor/slice_tracker.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-
-namespace protos {
-namespace pbzero {
-class TrackEvent_LegacyEvent_Decoder;
-}  // namespace pbzero
-}  // namespace protos
-
-namespace trace_processor {
-
-class PacketSequenceState;
-class TraceProcessorContext;
-
-class TrackEventParser {
- public:
-  explicit TrackEventParser(TraceProcessorContext* context);
-
-  void ParseTrackEvent(int64_t ts,
-                       int64_t tts,
-                       int64_t ticount,
-                       PacketSequenceState*,
-                       size_t sequence_state_generation,
-                       protozero::ConstBytes);
-  void ParseLegacyEventAsRawEvent(
-      int64_t ts,
-      int64_t tts,
-      int64_t ticount,
-      base::Optional<UniqueTid> utid,
-      StringId category_id,
-      StringId name_id,
-      const protos::pbzero::TrackEvent_LegacyEvent_Decoder& legacy_event,
-      SliceTracker::SetArgsCallback args_callback);
-  void ParseDebugAnnotationArgs(protozero::ConstBytes debug_annotation,
-                                PacketSequenceState*,
-                                size_t sequence_state_generation,
-                                ArgsTracker* args_tracker,
-                                RowId row);
-  void ParseNestedValueArgs(protozero::ConstBytes nested_value,
-                            base::StringView flat_key,
-                            base::StringView key,
-                            ArgsTracker* args_tracker,
-                            RowId row);
-  void ParseTaskExecutionArgs(protozero::ConstBytes task_execution,
-                              PacketSequenceState*,
-                              size_t sequence_state_generation,
-                              ArgsTracker* args_tracker,
-                              RowId row);
-  void ParseLogMessage(protozero::ConstBytes,
-                       PacketSequenceState*,
-                       size_t sequence_state_generation,
-                       int64_t,
-                       base::Optional<UniqueTid>,
-                       ArgsTracker*,
-                       RowId);
-
- private:
-  TraceProcessorContext* context_;
-
-  const StringId task_file_name_args_key_id_;
-  const StringId task_function_name_args_key_id_;
-  const StringId task_line_number_args_key_id_;
-  const StringId log_message_body_key_id_;
-  const StringId raw_legacy_event_id_;
-  const StringId legacy_event_original_tid_id_;
-  const StringId legacy_event_category_key_id_;
-  const StringId legacy_event_name_key_id_;
-  const StringId legacy_event_phase_key_id_;
-  const StringId legacy_event_duration_ns_key_id_;
-  const StringId legacy_event_thread_timestamp_ns_key_id_;
-  const StringId legacy_event_thread_duration_ns_key_id_;
-  const StringId legacy_event_thread_instruction_count_key_id_;
-  const StringId legacy_event_thread_instruction_delta_key_id_;
-  const StringId legacy_event_use_async_tts_key_id_;
-  const StringId legacy_event_unscoped_id_key_id_;
-  const StringId legacy_event_global_id_key_id_;
-  const StringId legacy_event_local_id_key_id_;
-  const StringId legacy_event_id_scope_key_id_;
-  const StringId legacy_event_bind_id_key_id_;
-  const StringId legacy_event_bind_to_enclosing_key_id_;
-  const StringId legacy_event_flow_direction_key_id_;
-  const StringId flow_direction_value_in_id_;
-  const StringId flow_direction_value_out_id_;
-  const StringId flow_direction_value_inout_id_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_PARSER_H_
diff --git a/src/trace_processor/importers/proto/track_event_tokenizer.cc b/src/trace_processor/importers/proto/track_event_tokenizer.cc
deleted file mode 100644
index e4ce716..0000000
--- a/src/trace_processor/importers/proto/track_event_tokenizer.cc
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/importers/proto/track_event_tokenizer.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/protozero/proto_decoder.h"
-#include "src/trace_processor/clock_tracker.h"
-#include "src/trace_processor/importers/proto/packet_sequence_state.h"
-#include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/stats.h"
-#include "src/trace_processor/trace_blob_view.h"
-#include "src/trace_processor/trace_sorter.h"
-#include "src/trace_processor/trace_storage.h"
-#include "src/trace_processor/track_tracker.h"
-
-#include "protos/perfetto/trace/clock_snapshot.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-#include "protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
-#include "protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
-#include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
-#include "protos/perfetto/trace/track_event/track_event.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-TrackEventTokenizer::TrackEventTokenizer(TraceProcessorContext* context)
-    : context_(context),
-      process_name_ids_{{context_->storage->InternString("Unknown"),
-                         context_->storage->InternString("Browser"),
-                         context_->storage->InternString("Renderer"),
-                         context_->storage->InternString("Utility"),
-                         context_->storage->InternString("Zygote"),
-                         context_->storage->InternString("SandboxHelper"),
-                         context_->storage->InternString("Gpu"),
-                         context_->storage->InternString("PpapiPlugin"),
-                         context_->storage->InternString("PpapiBroker")}} {}
-
-void TrackEventTokenizer::TokenizeTrackDescriptorPacket(
-    const protos::pbzero::TracePacket::Decoder& packet_decoder) {
-  auto track_descriptor_field = packet_decoder.track_descriptor();
-  protos::pbzero::TrackDescriptor::Decoder track_descriptor_decoder(
-      track_descriptor_field.data, track_descriptor_field.size);
-
-  if (!track_descriptor_decoder.has_uuid()) {
-    PERFETTO_ELOG("TrackDescriptor packet without trusted_packet_sequence_id");
-    context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
-    return;
-  }
-
-  base::Optional<UniquePid> upid;
-  base::Optional<UniqueTid> utid;
-
-  if (track_descriptor_decoder.has_process()) {
-    auto process_descriptor_field = track_descriptor_decoder.process();
-    protos::pbzero::ProcessDescriptor::Decoder process_descriptor_decoder(
-        process_descriptor_field.data, process_descriptor_field.size);
-
-    // TODO(eseckler): Also parse process name / type here.
-
-    upid = context_->process_tracker->GetOrCreateProcess(
-        static_cast<uint32_t>(process_descriptor_decoder.pid()));
-  }
-
-  if (track_descriptor_decoder.has_thread()) {
-    auto thread_descriptor_field = track_descriptor_decoder.thread();
-    protos::pbzero::ThreadDescriptor::Decoder thread_descriptor_decoder(
-        thread_descriptor_field.data, thread_descriptor_field.size);
-
-    TokenizeThreadDescriptor(thread_descriptor_decoder);
-    utid = context_->process_tracker->UpdateThread(
-        static_cast<uint32_t>(thread_descriptor_decoder.tid()),
-        static_cast<uint32_t>(thread_descriptor_decoder.pid()));
-    upid = *context_->storage->GetThread(*utid).upid;
-  }
-
-  StringId name_id =
-      context_->storage->InternString(track_descriptor_decoder.name());
-
-  context_->track_tracker->UpdateDescriptorTrack(
-      track_descriptor_decoder.uuid(), name_id, upid, utid);
-}
-
-void TrackEventTokenizer::TokenizeProcessDescriptorPacket(
-    const protos::pbzero::TracePacket::Decoder& packet_decoder) {
-  protos::pbzero::ProcessDescriptor::Decoder process_descriptor_decoder(
-      packet_decoder.process_descriptor());
-  if (!process_descriptor_decoder.has_chrome_process_type())
-    return;
-
-  auto process_type = process_descriptor_decoder.chrome_process_type();
-  size_t name_index =
-      static_cast<size_t>(process_type) < process_name_ids_.size()
-          ? static_cast<size_t>(process_type)
-          : 0u;
-  StringId name = process_name_ids_[name_index];
-
-  // Don't override system-provided names.
-  context_->process_tracker->SetProcessNameIfUnset(
-      context_->process_tracker->GetOrCreateProcess(
-          static_cast<uint32_t>(process_descriptor_decoder.pid())),
-      name);
-}
-
-void TrackEventTokenizer::TokenizeThreadDescriptorPacket(
-    PacketSequenceState* state,
-    const protos::pbzero::TracePacket::Decoder& packet_decoder) {
-  if (PERFETTO_UNLIKELY(!packet_decoder.has_trusted_packet_sequence_id())) {
-    PERFETTO_ELOG("ThreadDescriptor packet without trusted_packet_sequence_id");
-    context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
-    return;
-  }
-
-  // TrackEvents will be ignored while incremental state is invalid. As a
-  // consequence, we should also ignore any ThreadDescriptors received in this
-  // state. Otherwise, any delta-encoded timestamps would be calculated
-  // incorrectly once we move out of the packet loss state. Instead, wait until
-  // the first subsequent descriptor after incremental state is cleared.
-  if (!state->IsIncrementalStateValid()) {
-    context_->storage->IncrementStats(stats::tokenizer_skipped_packets);
-    return;
-  }
-
-  auto thread_descriptor_field = packet_decoder.thread_descriptor();
-  protos::pbzero::ThreadDescriptor::Decoder thread_descriptor_decoder(
-      thread_descriptor_field.data, thread_descriptor_field.size);
-
-  state->SetThreadDescriptor(
-      thread_descriptor_decoder.pid(), thread_descriptor_decoder.tid(),
-      thread_descriptor_decoder.reference_timestamp_us() * 1000,
-      thread_descriptor_decoder.reference_thread_time_us() * 1000,
-      thread_descriptor_decoder.reference_thread_instruction_count());
-
-  TokenizeThreadDescriptor(thread_descriptor_decoder);
-}
-
-void TrackEventTokenizer::TokenizeThreadDescriptor(
-    const protos::pbzero::ThreadDescriptor::Decoder&
-        thread_descriptor_decoder) {
-  base::StringView name;
-  if (thread_descriptor_decoder.has_thread_name()) {
-    name = thread_descriptor_decoder.thread_name();
-  } else if (thread_descriptor_decoder.has_chrome_thread_type()) {
-    using protos::pbzero::ThreadDescriptor;
-    switch (thread_descriptor_decoder.chrome_thread_type()) {
-      case ThreadDescriptor::CHROME_THREAD_MAIN:
-        name = "CrProcessMain";
-        break;
-      case ThreadDescriptor::CHROME_THREAD_IO:
-        name = "ChromeIOThread";
-        break;
-      case ThreadDescriptor::CHROME_THREAD_POOL_FG_WORKER:
-        name = "ThreadPoolForegroundWorker&";
-        break;
-      case ThreadDescriptor::CHROME_THREAD_POOL_BG_WORKER:
-        name = "ThreadPoolBackgroundWorker&";
-        break;
-      case ThreadDescriptor::CHROME_THREAD_POOL_FB_BLOCKING:
-        name = "ThreadPoolSingleThreadForegroundBlocking&";
-        break;
-      case ThreadDescriptor::CHROME_THREAD_POOL_BG_BLOCKING:
-        name = "ThreadPoolSingleThreadBackgroundBlocking&";
-        break;
-      case ThreadDescriptor::CHROME_THREAD_POOL_SERVICE:
-        name = "ThreadPoolService";
-        break;
-      case ThreadDescriptor::CHROME_THREAD_COMPOSITOR_WORKER:
-        name = "CompositorTileWorker&";
-        break;
-      case ThreadDescriptor::CHROME_THREAD_COMPOSITOR:
-        name = "Compositor";
-        break;
-      case ThreadDescriptor::CHROME_THREAD_VIZ_COMPOSITOR:
-        name = "VizCompositorThread";
-        break;
-      case ThreadDescriptor::CHROME_THREAD_SERVICE_WORKER:
-        name = "ServiceWorkerThread&";
-        break;
-      case ThreadDescriptor::CHROME_THREAD_MEMORY_INFRA:
-        name = "MemoryInfra";
-        break;
-      case ThreadDescriptor::CHROME_THREAD_SAMPLING_PROFILER:
-        name = "StackSamplingProfiler";
-        break;
-      case ThreadDescriptor::CHROME_THREAD_UNSPECIFIED:
-        name = "ChromeUnspecified";
-        break;
-    }
-  }
-
-  if (!name.empty()) {
-    auto thread_name_id = context_->storage->InternString(name);
-    ProcessTracker* procs = context_->process_tracker.get();
-    // Don't override system-provided names.
-    procs->SetThreadNameIfUnset(
-        procs->UpdateThread(
-            static_cast<uint32_t>(thread_descriptor_decoder.tid()),
-            static_cast<uint32_t>(thread_descriptor_decoder.pid())),
-        thread_name_id);
-  }
-}
-
-void TrackEventTokenizer::TokenizeTrackEventPacket(
-    PacketSequenceState* state,
-    const protos::pbzero::TracePacket::Decoder& packet_decoder,
-    TraceBlobView* packet,
-    int64_t packet_timestamp) {
-  constexpr auto kTimestampDeltaUsFieldNumber =
-      protos::pbzero::TrackEvent::kTimestampDeltaUsFieldNumber;
-  constexpr auto kTimestampAbsoluteUsFieldNumber =
-      protos::pbzero::TrackEvent::kTimestampAbsoluteUsFieldNumber;
-  constexpr auto kThreadTimeDeltaUsFieldNumber =
-      protos::pbzero::TrackEvent::kThreadTimeDeltaUsFieldNumber;
-  constexpr auto kThreadTimeAbsoluteUsFieldNumber =
-      protos::pbzero::TrackEvent::kThreadTimeAbsoluteUsFieldNumber;
-  constexpr auto kThreadInstructionCountDeltaFieldNumber =
-      protos::pbzero::TrackEvent::kThreadInstructionCountDeltaFieldNumber;
-  constexpr auto kThreadInstructionCountAbsoluteFieldNumber =
-      protos::pbzero::TrackEvent::kThreadInstructionCountAbsoluteFieldNumber;
-
-  if (PERFETTO_UNLIKELY(!packet_decoder.has_trusted_packet_sequence_id())) {
-    PERFETTO_ELOG("TrackEvent packet without trusted_packet_sequence_id");
-    context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
-    return;
-  }
-
-  // TODO(eseckler): For now, TrackEvents can only be parsed correctly while
-  // incremental state for their sequence is valid, because chromium doesn't set
-  // SEQ_NEEDS_INCREMENTAL_STATE yet. Remove this once it does.
-  if (!state->IsIncrementalStateValid()) {
-    context_->storage->IncrementStats(stats::tokenizer_skipped_packets);
-    return;
-  }
-
-  auto field = packet_decoder.track_event();
-  protozero::ProtoDecoder event_decoder(field.data, field.size);
-
-  int64_t timestamp;
-  int64_t thread_timestamp = 0;
-  int64_t thread_instructions = 0;
-
-  // TODO(eseckler): Remove handling of timestamps relative to ThreadDescriptors
-  // once all producers have switched to clock-domain timestamps (e.g.
-  // TracePacket's timestamp).
-
-  if (auto ts_delta_field =
-          event_decoder.FindField(kTimestampDeltaUsFieldNumber)) {
-    // Delta timestamps require a valid ThreadDescriptor packet since the last
-    // packet loss.
-    if (!state->track_event_timestamps_valid()) {
-      context_->storage->IncrementStats(stats::tokenizer_skipped_packets);
-      return;
-    }
-    timestamp = state->IncrementAndGetTrackEventTimeNs(
-        ts_delta_field.as_int64() * 1000);
-
-    // Legacy TrackEvent timestamp fields are in MONOTONIC domain. Adjust to
-    // trace time if we have a clock snapshot.
-    auto trace_ts = context_->clock_tracker->ToTraceTime(
-        protos::pbzero::ClockSnapshot::Clock::MONOTONIC, timestamp);
-    if (trace_ts.has_value())
-      timestamp = trace_ts.value();
-  } else if (auto ts_absolute_field =
-                 event_decoder.FindField(kTimestampAbsoluteUsFieldNumber)) {
-    // One-off absolute timestamps don't affect delta computation.
-    timestamp = ts_absolute_field.as_int64() * 1000;
-
-    // Legacy TrackEvent timestamp fields are in MONOTONIC domain. Adjust to
-    // trace time if we have a clock snapshot.
-    auto trace_ts = context_->clock_tracker->ToTraceTime(
-        protos::pbzero::ClockSnapshot::Clock::MONOTONIC, timestamp);
-    if (trace_ts.has_value())
-      timestamp = trace_ts.value();
-  } else if (packet_decoder.has_timestamp()) {
-    timestamp = packet_timestamp;
-  } else {
-    PERFETTO_ELOG("TrackEvent without timestamp");
-    context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
-    return;
-  }
-
-  if (auto tt_delta_field =
-          event_decoder.FindField(kThreadTimeDeltaUsFieldNumber)) {
-    // Delta timestamps require a valid ThreadDescriptor packet since the last
-    // packet loss.
-    if (!state->track_event_timestamps_valid()) {
-      context_->storage->IncrementStats(stats::tokenizer_skipped_packets);
-      return;
-    }
-    thread_timestamp = state->IncrementAndGetTrackEventThreadTimeNs(
-        tt_delta_field.as_int64() * 1000);
-  } else if (auto tt_absolute_field =
-                 event_decoder.FindField(kThreadTimeAbsoluteUsFieldNumber)) {
-    // One-off absolute timestamps don't affect delta computation.
-    thread_timestamp = tt_absolute_field.as_int64() * 1000;
-  }
-
-  if (auto ti_delta_field =
-          event_decoder.FindField(kThreadInstructionCountDeltaFieldNumber)) {
-    // Delta timestamps require a valid ThreadDescriptor packet since the last
-    // packet loss.
-    if (!state->track_event_timestamps_valid()) {
-      context_->storage->IncrementStats(stats::tokenizer_skipped_packets);
-      return;
-    }
-    thread_instructions =
-        state->IncrementAndGetTrackEventThreadInstructionCount(
-            ti_delta_field.as_int64());
-  } else if (auto ti_absolute_field = event_decoder.FindField(
-                 kThreadInstructionCountAbsoluteFieldNumber)) {
-    // One-off absolute timestamps don't affect delta computation.
-    thread_instructions = ti_absolute_field.as_int64();
-  }
-
-  context_->sorter->PushTrackEventPacket(timestamp, thread_timestamp,
-                                         thread_instructions, state,
-                                         std::move(*packet));
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/proto/track_event_tokenizer.h b/src/trace_processor/importers/proto/track_event_tokenizer.h
deleted file mode 100644
index 13a7425..0000000
--- a/src/trace_processor/importers/proto/track_event_tokenizer.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_TOKENIZER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_TOKENIZER_H_
-
-#include <stdint.h>
-
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-
-namespace protos {
-namespace pbzero {
-class ThreadDescriptor_Decoder;
-class TracePacket_Decoder;
-}  // namespace pbzero
-}  // namespace protos
-
-namespace trace_processor {
-
-class PacketSequenceState;
-class TraceProcessorContext;
-class TraceBlobView;
-
-class TrackEventTokenizer {
- public:
-  explicit TrackEventTokenizer(TraceProcessorContext* context);
-
-  void TokenizeTrackDescriptorPacket(
-      const protos::pbzero::TracePacket_Decoder&);
-  void TokenizeProcessDescriptorPacket(
-      const protos::pbzero::TracePacket_Decoder&);
-  void TokenizeThreadDescriptorPacket(
-      PacketSequenceState* state,
-      const protos::pbzero::TracePacket_Decoder&);
-  void TokenizeThreadDescriptor(
-      const protos::pbzero::ThreadDescriptor_Decoder&);
-  void TokenizeTrackEventPacket(PacketSequenceState* state,
-                                const protos::pbzero::TracePacket_Decoder&,
-                                TraceBlobView* packet,
-                                int64_t packet_timestamp);
-
- private:
-  TraceProcessorContext* context_;
-
-  std::array<StringId, 9> process_name_ids_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_PROTO_TRACK_EVENT_TOKENIZER_H_
diff --git a/src/trace_processor/importers/systrace/systrace_parser.cc b/src/trace_processor/importers/systrace/systrace_parser.cc
deleted file mode 100644
index 9e336a6..0000000
--- a/src/trace_processor/importers/systrace/systrace_parser.cc
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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.
- */
-
-#include "src/trace_processor/importers/systrace/systrace_parser.h"
-
-#include "perfetto/ext/base/optional.h"
-#include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/slice_tracker.h"
-#include "src/trace_processor/track_tracker.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-SystraceParser::SystraceParser(TraceProcessorContext* ctx)
-    : context_(ctx), lmk_id_(ctx->storage->InternString("mem.lmk")) {}
-
-void SystraceParser::ParsePrintEvent(int64_t ts,
-                                     uint32_t pid,
-                                     base::StringView event) {
-  systrace_utils::SystraceTracePoint point{};
-  switch (ParseSystraceTracePoint(event, &point)) {
-    case systrace_utils::SystraceParseResult::kSuccess:
-      ParseSystracePoint(ts, pid, point);
-      break;
-    case systrace_utils::SystraceParseResult::kFailure:
-      context_->storage->IncrementStats(stats::systrace_parse_failure);
-      break;
-    case systrace_utils::SystraceParseResult::kUnsupported:
-      // Silently ignore unsupported results.
-      break;
-  }
-}
-
-void SystraceParser::ParseZeroEvent(int64_t ts,
-                                    uint32_t pid,
-                                    int32_t flag,
-                                    base::StringView name,
-                                    uint32_t tgid,
-                                    int64_t value) {
-  systrace_utils::SystraceTracePoint point{};
-  point.name = name;
-  point.tgid = tgid;
-  point.value = value;
-
-  // The value of these constants can be found in the msm-google kernel.
-  constexpr int32_t kSystraceEventBegin = 1 << 0;
-  constexpr int32_t kSystraceEventEnd = 1 << 1;
-  constexpr int32_t kSystraceEventInt64 = 1 << 2;
-
-  if ((flag & kSystraceEventBegin) != 0) {
-    point.phase = 'B';
-  } else if ((flag & kSystraceEventEnd) != 0) {
-    point.phase = 'E';
-  } else if ((flag & kSystraceEventInt64) != 0) {
-    point.phase = 'C';
-  } else {
-    context_->storage->IncrementStats(stats::systrace_parse_failure);
-    return;
-  }
-  context_->systrace_parser->ParseSystracePoint(ts, pid, point);
-}
-
-void SystraceParser::ParseSystracePoint(
-    int64_t ts,
-    uint32_t pid,
-    systrace_utils::SystraceTracePoint point) {
-  switch (point.phase) {
-    case 'B': {
-      StringId name_id = context_->storage->InternString(point.name);
-      context_->slice_tracker->BeginAndroid(ts, pid, point.tgid, 0 /*cat_id*/,
-                                            name_id);
-      break;
-    }
-
-    case 'E': {
-      context_->slice_tracker->EndAndroid(ts, pid, point.tgid);
-      break;
-    }
-
-    case 'S':
-    case 'F': {
-      StringId name_id = context_->storage->InternString(point.name);
-      int64_t cookie = static_cast<int64_t>(point.value);
-      UniquePid upid =
-          context_->process_tracker->GetOrCreateProcess(point.tgid);
-
-      TrackId track_id = context_->track_tracker->InternAndroidAsyncTrack(
-          name_id, upid, cookie);
-      if (point.phase == 'S') {
-        context_->slice_tracker->Begin(ts, track_id, track_id,
-                                       RefType::kRefTrack, 0, name_id);
-      } else {
-        context_->slice_tracker->End(ts, track_id);
-      }
-      break;
-    }
-
-    case 'C': {
-      // LMK events from userspace are hacked as counter events with the "value"
-      // of the counter representing the pid of the killed process which is
-      // reset to 0 once the kill is complete.
-      // Homogenise this with kernel LMK events as an instant event, ignoring
-      // the resets to 0.
-      if (point.name == "kill_one_process") {
-        auto killed_pid = static_cast<uint32_t>(point.value);
-        if (killed_pid != 0) {
-          UniquePid killed_upid =
-              context_->process_tracker->GetOrCreateProcess(killed_pid);
-          context_->event_tracker->PushInstant(ts, lmk_id_, 0, killed_upid,
-                                               RefType::kRefUpid);
-        }
-        // TODO(lalitm): we should not add LMK events to the counters table
-        // once the UI has support for displaying instants.
-      }
-      // This is per upid on purpose. Some counters are pushed from arbitrary
-      // threads but are really per process.
-      UniquePid upid =
-          context_->process_tracker->GetOrCreateProcess(point.tgid);
-      StringId name_id = context_->storage->InternString(point.name);
-      TrackId track =
-          context_->track_tracker->InternProcessCounterTrack(name_id, upid);
-      context_->event_tracker->PushCounter(ts, point.value, track);
-    }
-  }
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/systrace/systrace_parser.h b/src/trace_processor/importers/systrace/systrace_parser.h
deleted file mode 100644
index 569efd0..0000000
--- a/src/trace_processor/importers/systrace/systrace_parser.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_IMPORTERS_SYSTRACE_SYSTRACE_PARSER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_SYSTRACE_SYSTRACE_PARSER_H_
-
-#include <ostream>
-
-#include "src/trace_processor/trace_processor_context.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/string_view.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace systrace_utils {
-
-// Visible for unittesting.
-enum class SystraceParseResult { kFailure = 0, kUnsupported, kSuccess };
-
-// Visible for unittesting.
-struct SystraceTracePoint {
-  SystraceTracePoint() {}
-
-  static SystraceTracePoint B(uint32_t tgid, base::StringView name) {
-    return SystraceTracePoint('B', tgid, std::move(name), 0);
-  }
-
-  static SystraceTracePoint E(uint32_t tgid) {
-    return SystraceTracePoint('E', tgid, {}, 0);
-  }
-
-  static SystraceTracePoint C(uint32_t tgid,
-                              base::StringView name,
-                              double value) {
-    return SystraceTracePoint('C', tgid, std::move(name), value);
-  }
-
-  static SystraceTracePoint S(uint32_t tgid,
-                              base::StringView name,
-                              double value) {
-    return SystraceTracePoint('S', tgid, std::move(name), value);
-  }
-
-  static SystraceTracePoint F(uint32_t tgid,
-                              base::StringView name,
-                              double value) {
-    return SystraceTracePoint('F', tgid, std::move(name), value);
-  }
-
-  SystraceTracePoint(char p, uint32_t tg, base::StringView n, double v)
-      : phase(p), tgid(tg), name(std::move(n)), value(v) {}
-
-  // Phase can be one of B, E, C, S, F.
-  char phase = '\0';
-
-  uint32_t tgid = 0;
-
-  // For phase = 'B' and phase = 'C' only.
-  base::StringView name;
-
-  // For phase = 'C' only.
-  double value = 0;
-
-  // Visible for unittesting.
-  friend std::ostream& operator<<(std::ostream& os,
-                                  const SystraceTracePoint& point) {
-    return os << "SystraceTracePoint{'" << point.phase << "', " << point.tgid
-              << ", \"" << point.name.ToStdString() << "\", " << point.value
-              << "}";
-  }
-};
-
-// We have to handle trace_marker events of a few different types:
-// 1. some random text
-// 2. B|1636|pokeUserActivity
-// 3. E|1636
-// 4. C|1636|wq:monitor|0
-// 5. S|1636|frame_capture|123
-// 6. F|1636|frame_capture|456
-// Visible for unittesting.
-inline SystraceParseResult ParseSystraceTracePoint(base::StringView str,
-                                                   SystraceTracePoint* out) {
-  const char* s = str.data();
-  size_t len = str.size();
-  *out = {};
-
-  constexpr const char* kClockSyncPrefix = "trace_event_clock_sync:";
-  if (len >= strlen(kClockSyncPrefix) &&
-      strncmp(kClockSyncPrefix, s, strlen(kClockSyncPrefix)) == 0)
-    return SystraceParseResult::kUnsupported;
-
-  if (len < 2)
-    return SystraceParseResult::kFailure;
-
-  // If str matches '[BEC]\|[0-9]+[\|\n]?' set tgid_length to the length of
-  // the number. Otherwise return kFailure.
-  if (s[1] != '|' && s[1] != '\n')
-    return SystraceParseResult::kFailure;
-
-  char ph = s[0];
-  if (ph != 'B' && ph != 'E' && ph != 'C' && ph != 'S' && ph != 'F')
-    return SystraceParseResult::kFailure;
-
-  size_t tgid_length = 0;
-  for (size_t i = 2; i < len; i++) {
-    if (s[i] == '|' || s[i] == '\n') {
-      break;
-    }
-    if (s[i] < '0' || s[i] > '9')
-      return SystraceParseResult::kFailure;
-    tgid_length++;
-  }
-
-  std::string tgid_str(s + 2, tgid_length);
-  out->tgid = base::StringToUInt32(tgid_str).value_or(0);
-
-  out->phase = ph;
-  switch (ph) {
-    case 'B': {
-      size_t name_index = 2 + tgid_length + 1;
-      out->name = base::StringView(
-          s + name_index, len - name_index - (s[len - 1] == '\n' ? 1 : 0));
-      if (out->name.size() == 0)
-        return SystraceParseResult::kFailure;
-      return SystraceParseResult::kSuccess;
-    }
-    case 'E': {
-      return SystraceParseResult::kSuccess;
-    }
-    case 'S':
-    case 'F':
-    case 'C': {
-      size_t name_index = 2 + tgid_length + 1;
-      base::Optional<size_t> name_length;
-      for (size_t i = name_index; i < len; i++) {
-        if (s[i] == '|') {
-          name_length = i - name_index;
-          break;
-        }
-      }
-      if (!name_length.has_value())
-        return SystraceParseResult::kFailure;
-      out->name = base::StringView(s + name_index, name_length.value());
-
-      size_t value_index = name_index + name_length.value() + 1;
-      size_t value_len = len - value_index;
-      if (value_len == 0)
-        return SystraceParseResult::kFailure;
-      if (*(s + value_index + value_len - 1) == '\n')
-        value_len--;
-      std::string value_str(s + value_index, value_len);
-      base::Optional<double> maybe_value = base::StringToDouble(value_str);
-      if (!maybe_value.has_value()) {
-        return SystraceParseResult::kFailure;
-      }
-      out->value = maybe_value.value();
-      return SystraceParseResult::kSuccess;
-    }
-    default:
-      return SystraceParseResult::kFailure;
-  }
-}
-
-// Visible for unittesting.
-inline bool operator==(const SystraceTracePoint& x,
-                       const SystraceTracePoint& y) {
-  return std::tie(x.phase, x.tgid, x.name, x.value) ==
-         std::tie(y.phase, y.tgid, y.name, y.value);
-}
-
-}  // namespace systrace_utils
-
-class SystraceParser {
- public:
-  explicit SystraceParser(TraceProcessorContext*);
-
-  void ParsePrintEvent(int64_t ts, uint32_t pid, base::StringView event);
-
-  void ParseZeroEvent(int64_t ts,
-                      uint32_t pid,
-                      int32_t flag,
-                      base::StringView name,
-                      uint32_t tgid,
-                      int64_t value);
-
- private:
-  void ParseSystracePoint(int64_t ts,
-                          uint32_t pid,
-                          systrace_utils::SystraceTracePoint event);
-
-  TraceProcessorContext* const context_;
-  const StringId lmk_id_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_SYSTRACE_SYSTRACE_PARSER_H_
diff --git a/src/trace_processor/importers/systrace/systrace_parser_unittest.cc b/src/trace_processor/importers/systrace/systrace_parser_unittest.cc
deleted file mode 100644
index 55d42cc..0000000
--- a/src/trace_processor/importers/systrace/systrace_parser_unittest.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.
- */
-
-#include "src/trace_processor/importers/systrace/systrace_parser.h"
-
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace systrace_utils {
-namespace {
-
-using Result = SystraceParseResult;
-
-TEST(SystraceParserTest, SystraceEvent) {
-  SystraceTracePoint result{};
-  ASSERT_EQ(ParseSystraceTracePoint("", &result), Result::kFailure);
-  ASSERT_EQ(ParseSystraceTracePoint("abcdef", &result), Result::kFailure);
-  ASSERT_EQ(ParseSystraceTracePoint("  ", &result), Result::kFailure);
-  ASSERT_EQ(ParseSystraceTracePoint("|", &result), Result::kFailure);
-  ASSERT_EQ(ParseSystraceTracePoint("||", &result), Result::kFailure);
-  ASSERT_EQ(ParseSystraceTracePoint("|||", &result), Result::kFailure);
-  ASSERT_EQ(ParseSystraceTracePoint("\n", &result), Result::kFailure);
-  ASSERT_EQ(ParseSystraceTracePoint("|\n", &result), Result::kFailure);
-  ASSERT_EQ(ParseSystraceTracePoint("||\n", &result), Result::kFailure);
-  ASSERT_EQ(ParseSystraceTracePoint("||\n", &result), Result::kFailure);
-  ASSERT_EQ(ParseSystraceTracePoint("E", &result), Result::kFailure);
-  ASSERT_EQ(ParseSystraceTracePoint("B", &result), Result::kFailure);
-  ASSERT_EQ(ParseSystraceTracePoint("C", &result), Result::kFailure);
-  ASSERT_EQ(ParseSystraceTracePoint("S", &result), Result::kFailure);
-  ASSERT_EQ(ParseSystraceTracePoint("F", &result), Result::kFailure);
-  ASSERT_EQ(ParseSystraceTracePoint("B|42|\n", &result), Result::kFailure);
-
-  ASSERT_EQ(ParseSystraceTracePoint("B|1|foo", &result), Result::kSuccess);
-  EXPECT_EQ(result, SystraceTracePoint::B(1, "foo"));
-
-  ASSERT_EQ(ParseSystraceTracePoint("B|42|Bar\n", &result), Result::kSuccess);
-  EXPECT_EQ(result, SystraceTracePoint::B(42, "Bar"));
-
-  ASSERT_EQ(ParseSystraceTracePoint("E|42\n", &result), Result::kSuccess);
-  EXPECT_EQ(result, SystraceTracePoint::E(42));
-
-  ASSERT_EQ(ParseSystraceTracePoint("E|42", &result), Result::kSuccess);
-  EXPECT_EQ(result, SystraceTracePoint::E(42));
-
-  ASSERT_EQ(ParseSystraceTracePoint("C|543|foo|", &result), Result::kFailure);
-  ASSERT_EQ(ParseSystraceTracePoint("C|543|foo|8", &result), Result::kSuccess);
-  EXPECT_EQ(result, SystraceTracePoint::C(543, "foo", 8));
-
-  ASSERT_EQ(ParseSystraceTracePoint("S|", &result), Result::kFailure);
-
-  ASSERT_EQ(ParseSystraceTracePoint("S|123|foo|456", &result),
-            Result::kSuccess);
-  EXPECT_EQ(result, SystraceTracePoint::S(123, "foo", 456));
-
-  ASSERT_EQ(ParseSystraceTracePoint("F|123|foo|456", &result),
-            Result::kSuccess);
-  EXPECT_EQ(result, SystraceTracePoint::F(123, "foo", 456));
-
-  ASSERT_EQ(ParseSystraceTracePoint("trace_event_clock_sync: parent_ts=0.123\n",
-                                    &result),
-            Result::kUnsupported);
-  ASSERT_EQ(ParseSystraceTracePoint("trace_event_clock_sync: realtime_ts=123\n",
-                                    &result),
-            Result::kUnsupported);
-}
-
-}  // namespace
-}  // namespace systrace_utils
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/systrace/systrace_trace_parser.cc b/src/trace_processor/importers/systrace/systrace_trace_parser.cc
deleted file mode 100644
index 33d5cb1..0000000
--- a/src/trace_processor/importers/systrace/systrace_trace_parser.cc
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * 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.
- */
-
-#include "src/trace_processor/importers/systrace/systrace_trace_parser.h"
-
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "src/trace_processor/args_tracker.h"
-#include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
-#include "src/trace_processor/importers/systrace/systrace_parser.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/slice_tracker.h"
-#include "src/trace_processor/track_tracker.h"
-
-#include <inttypes.h>
-#include <string>
-#include <unordered_map>
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-std::string SubstrTrim(const std::string& input) {
-  std::string s = input;
-  s.erase(s.begin(), std::find_if(s.begin(), s.end(),
-                                  [](int ch) { return !std::isspace(ch); }));
-  s.erase(std::find_if(s.rbegin(), s.rend(),
-                       [](int ch) { return !std::isspace(ch); })
-              .base(),
-          s.end());
-  return s;
-}
-}  // namespace
-
-SystraceTraceParser::SystraceTraceParser(TraceProcessorContext* ctx)
-    : context_(ctx),
-      sched_wakeup_name_id_(ctx->storage->InternString("sched_wakeup")),
-      cpu_idle_name_id_(ctx->storage->InternString("cpuidle")),
-      line_matcher_(std::regex(R"(-(\d+)\s+\(?\s*(\d+|-+)?\)?\s?\[(\d+)\]\s*)"
-                               R"([a-zA-Z0-9.]{0,4}\s+(\d+\.\d+):\s+(\S+):)")) {
-}
-SystraceTraceParser::~SystraceTraceParser() = default;
-
-util::Status SystraceTraceParser::Parse(std::unique_ptr<uint8_t[]> owned_buf,
-                                        size_t size) {
-  if (state_ == ParseState::kEndOfSystrace)
-    return util::OkStatus();
-  partial_buf_.insert(partial_buf_.end(), &owned_buf[0], &owned_buf[size]);
-
-  if (state_ == ParseState::kBeforeParse) {
-    state_ = partial_buf_[0] == '<' ? ParseState::kHtmlBeforeSystrace
-                                    : ParseState::kSystrace;
-  }
-
-  // There can be multiple trace data sections in an HTML trace, we want to
-  // ignore any that don't contain systrace data. In the future it would be
-  // good to also parse the process dump section.
-  const char kTraceDataSection[] =
-      R"(<script class="trace-data" type="application/text">)";
-  auto start_it = partial_buf_.begin();
-  for (;;) {
-    auto line_it = std::find(start_it, partial_buf_.end(), '\n');
-    if (line_it == partial_buf_.end())
-      break;
-
-    std::string buffer(start_it, line_it);
-
-    if (state_ == ParseState::kHtmlBeforeSystrace) {
-      if (base::Contains(buffer, kTraceDataSection)) {
-        state_ = ParseState::kTraceDataSection;
-      }
-    } else if (state_ == ParseState::kTraceDataSection) {
-      if (base::StartsWith(buffer, "#")) {
-        state_ = ParseState::kSystrace;
-      } else if (base::Contains(buffer, R"(</script>)")) {
-        state_ = ParseState::kHtmlBeforeSystrace;
-      }
-    } else if (state_ == ParseState::kSystrace) {
-      if (base::Contains(buffer, R"(</script>)")) {
-        state_ = ParseState::kEndOfSystrace;
-        break;
-      } else if (!base::StartsWith(buffer, "#")) {
-        ParseSingleSystraceEvent(buffer);
-      }
-    }
-    start_it = line_it + 1;
-  }
-  if (state_ == ParseState::kEndOfSystrace) {
-    partial_buf_.clear();
-  } else {
-    partial_buf_.erase(partial_buf_.begin(), start_it);
-  }
-  return util::OkStatus();
-}
-
-// TODO(hjd): This should be more robust to being passed random input.
-// This can happen if we mess up detecting a gzip trace for example.
-util::Status SystraceTraceParser::ParseSingleSystraceEvent(
-    const std::string& buffer) {
-  // An example line from buffer looks something like the following:
-  // kworker/u16:1-77    (   77) [004] ....   316.196720: 0:
-  // B|77|__scm_call_armv8_64|0
-  //
-  // However, sometimes the tgid can be missing and buffer looks like this:
-  // <idle>-0     [000] ...2     0.002188: task_newtask: pid=1 ...
-  //
-  // Also the irq fields can be missing (we don't parse these anyway)
-  // <idle>-0     [000]  0.002188: task_newtask: pid=1 ...
-  //
-  // The task name can contain any characters e.g -:[(/ and for this reason
-  // it is much easier to use a regex (even though it is slower than parsing
-  // manually)
-
-  std::smatch matches;
-  bool matched = std::regex_search(buffer, matches, line_matcher_);
-  if (!matched) {
-    return util::Status("Not a known systrace event format");
-  }
-
-  std::string task = SubstrTrim(matches.prefix());
-  std::string pid_str = matches[1].str();
-  std::string tgid_str = matches[2].str();
-  std::string cpu_str = matches[3].str();
-  std::string ts_str = matches[4].str();
-  std::string event_name = matches[5].str();
-  std::string args_str = SubstrTrim(matches.suffix());
-
-  base::Optional<uint32_t> maybe_pid = base::StringToUInt32(pid_str);
-  if (!maybe_pid.has_value()) {
-    return util::Status("Could not convert pid " + pid_str);
-  }
-  uint32_t pid = maybe_pid.value();
-  context_->process_tracker->GetOrCreateThread(pid);
-
-  if (tgid_str != "" && tgid_str != "-----") {
-    base::Optional<uint32_t> tgid = base::StringToUInt32(tgid_str);
-    if (tgid) {
-      context_->process_tracker->UpdateThread(pid, tgid.value());
-    }
-  }
-
-  base::Optional<uint32_t> maybe_cpu = base::StringToUInt32(cpu_str);
-  if (!maybe_cpu.has_value()) {
-    return util::Status("Could not convert cpu " + cpu_str);
-  }
-  uint32_t cpu = maybe_cpu.value();
-
-  base::Optional<double> maybe_ts = base::StringToDouble(ts_str);
-  if (!maybe_ts.has_value()) {
-    return util::Status("Could not convert ts");
-  }
-  int64_t ts = static_cast<int64_t>(maybe_ts.value() * 1e9);
-
-  std::unordered_map<std::string, std::string> args;
-  for (base::StringSplitter ss(args_str.c_str(), ' '); ss.Next();) {
-    std::string key;
-    std::string value;
-    for (base::StringSplitter inner(ss.cur_token(), '='); inner.Next();) {
-      if (key.empty()) {
-        key = inner.cur_token();
-      } else {
-        value = inner.cur_token();
-      }
-    }
-    args.emplace(std::move(key), std::move(value));
-  }
-  if (event_name == "sched_switch") {
-    auto prev_state_str = args["prev_state"];
-    int64_t prev_state =
-        ftrace_utils::TaskState(prev_state_str.c_str()).raw_state();
-
-    auto prev_pid = base::StringToUInt32(args["prev_pid"]);
-    auto prev_comm = base::StringView(args["prev_comm"]);
-    auto prev_prio = base::StringToInt32(args["prev_prio"]);
-    auto next_pid = base::StringToUInt32(args["next_pid"]);
-    auto next_comm = base::StringView(args["next_comm"]);
-    auto next_prio = base::StringToInt32(args["next_prio"]);
-
-    if (!(prev_pid.has_value() && prev_prio.has_value() &&
-          next_pid.has_value() && next_prio.has_value())) {
-      return util::Status("Could not parse sched_switch");
-    }
-
-    context_->sched_tracker->PushSchedSwitch(
-        cpu, ts, prev_pid.value(), prev_comm, prev_prio.value(), prev_state,
-        next_pid.value(), next_comm, next_prio.value());
-  } else if (event_name == "tracing_mark_write" || event_name == "0" ||
-             event_name == "print") {
-    context_->systrace_parser->ParsePrintEvent(ts, pid, args_str.c_str());
-  } else if (event_name == "sched_wakeup") {
-    auto comm = args["comm"];
-    base::Optional<uint32_t> wakee_pid = base::StringToUInt32(args["pid"]);
-    if (!wakee_pid.has_value()) {
-      return util::Status("Could not convert wakee_pid");
-    }
-
-    StringId name_id = context_->storage->InternString(base::StringView(comm));
-    auto wakee_utid =
-        context_->process_tracker->UpdateThreadName(wakee_pid.value(), name_id);
-    context_->event_tracker->PushInstant(ts, sched_wakeup_name_id_,
-                                         0 /* value */, wakee_utid,
-                                         RefType::kRefUtid);
-  } else if (event_name == "cpu_idle") {
-    base::Optional<uint32_t> event_cpu = base::StringToUInt32(args["cpu_id"]);
-    base::Optional<double> new_state = base::StringToDouble(args["state"]);
-    if (!event_cpu.has_value()) {
-      return util::Status("Could not convert event cpu");
-    }
-    if (!event_cpu.has_value()) {
-      return util::Status("Could not convert state");
-    }
-
-    TrackId track = context_->track_tracker->InternCpuCounterTrack(
-        cpu_idle_name_id_, event_cpu.value());
-    context_->event_tracker->PushCounter(ts, new_state.value(), track);
-  }
-
-  return util::OkStatus();
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/importers/systrace/systrace_trace_parser.h b/src/trace_processor/importers/systrace/systrace_trace_parser.h
deleted file mode 100644
index 1b5926b..0000000
--- a/src/trace_processor/importers/systrace/systrace_trace_parser.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_IMPORTERS_SYSTRACE_SYSTRACE_TRACE_PARSER_H_
-#define SRC_TRACE_PROCESSOR_IMPORTERS_SYSTRACE_SYSTRACE_TRACE_PARSER_H_
-
-#include <deque>
-#include <regex>
-
-#include "src/trace_processor/chunked_trace_reader.h"
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class SystraceTraceParser : public ChunkedTraceReader {
- public:
-  explicit SystraceTraceParser(TraceProcessorContext*);
-  ~SystraceTraceParser() override;
-
-  // ChunkedTraceReader implementation.
-  util::Status Parse(std::unique_ptr<uint8_t[]>, size_t size) override;
-
- private:
-  enum ParseState {
-    kBeforeParse,
-    kHtmlBeforeSystrace,
-    kTraceDataSection,
-    kSystrace,
-    kEndOfSystrace,
-  };
-
-  util::Status ParseSingleSystraceEvent(const std::string& buffer);
-
-  TraceProcessorContext* const context_;
-  const StringId sched_wakeup_name_id_ = 0;
-  const StringId cpu_idle_name_id_ = 0;
-  const std::regex line_matcher_;
-
-  ParseState state_ = ParseState::kBeforeParse;
-
-  // Used to glue together trace packets that span across two (or more)
-  // Parse() boundaries.
-  std::deque<uint8_t> partial_buf_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_IMPORTERS_SYSTRACE_SYSTRACE_TRACE_PARSER_H_
diff --git a/src/trace_processor/instants_table.cc b/src/trace_processor/instants_table.cc
index e0a52ad..f5d368f 100644
--- a/src/trace_processor/instants_table.cc
+++ b/src/trace_processor/instants_table.cc
@@ -27,7 +27,7 @@
     : storage_(storage) {}
 
 void InstantsTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
-  SqliteTable::Register<InstantsTable>(db, storage, "instants");
+  Table::Register<InstantsTable>(db, storage, "instants");
 }
 
 StorageSchema InstantsTable::CreateStorageSchema() {
@@ -50,13 +50,13 @@
 int InstantsTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
   info->estimated_cost =
       static_cast<uint32_t>(storage_->instants().instant_count());
-  info->sqlite_omit_order_by = true;
 
   // Only the string columns are handled by SQLite
+  info->order_by_consumed = true;
   size_t name_index = schema().ColumnIndexFromName("name");
   size_t ref_type_index = schema().ColumnIndexFromName("ref_type");
   for (size_t i = 0; i < qc.constraints().size(); i++) {
-    info->constraint_info[i].sqlite_omit =
+    info->omit[i] =
         qc.constraints()[i].iColumn != static_cast<int>(name_index) &&
         qc.constraints()[i].iColumn != static_cast<int>(ref_type_index);
   }
diff --git a/src/trace_processor/json_trace_parser.cc b/src/trace_processor/json_trace_parser.cc
new file mode 100644
index 0000000..75533f7
--- /dev/null
+++ b/src/trace_processor/json_trace_parser.cc
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+#include "src/trace_processor/json_trace_parser.h"
+
+#include <inttypes.h>
+#include <json/reader.h>
+#include <json/value.h>
+
+#include <limits>
+#include <string>
+
+#include "perfetto/base/build_config.h"
+#include "perfetto/base/logging.h"
+#include "perfetto/base/string_view.h"
+#include "perfetto/base/utils.h"
+#include "src/trace_processor/json_trace_utils.h"
+#include "src/trace_processor/process_tracker.h"
+#include "src/trace_processor/slice_tracker.h"
+#include "src/trace_processor/trace_processor_context.h"
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD)
+#error The JSON trace parser is supported only in the standalone build for now.
+#endif
+
+namespace perfetto {
+namespace trace_processor {
+
+JsonTraceParser::JsonTraceParser(TraceProcessorContext* context)
+    : context_(context) {}
+
+JsonTraceParser::~JsonTraceParser() = default;
+
+void JsonTraceParser::ParseFtracePacket(uint32_t,
+                                        int64_t,
+                                        TraceSorter::TimestampedTracePiece) {
+  PERFETTO_FATAL("Json Trace Parser cannot handle ftrace packets.");
+}
+
+void JsonTraceParser::ParseTracePacket(int64_t timestamp,
+                                       TraceSorter::TimestampedTracePiece ttp) {
+  PERFETTO_DCHECK(ttp.json_value != nullptr);
+  const Json::Value& value = *(ttp.json_value);
+
+  ProcessTracker* procs = context_->process_tracker.get();
+  TraceStorage* storage = context_->storage.get();
+  SliceTracker* slice_tracker = context_->slice_tracker.get();
+
+  auto& ph = value["ph"];
+  if (!ph.isString())
+    return;
+  char phase = *ph.asCString();
+
+  base::Optional<uint32_t> opt_pid;
+  base::Optional<uint32_t> opt_tid;
+
+  if (value.isMember("pid"))
+    opt_pid = json_trace_utils::CoerceToUint32(value["pid"]);
+  if (value.isMember("tid"))
+    opt_tid = json_trace_utils::CoerceToUint32(value["tid"]);
+
+  uint32_t pid = opt_pid.value_or(0);
+  uint32_t tid = opt_tid.value_or(pid);
+
+  base::StringView cat = value.isMember("cat")
+                             ? base::StringView(value["cat"].asCString())
+                             : base::StringView();
+  base::StringView name = value.isMember("name")
+                              ? base::StringView(value["name"].asCString())
+                              : base::StringView();
+
+  StringId cat_id = storage->InternString(cat);
+  StringId name_id = storage->InternString(name);
+  UniqueTid utid = procs->UpdateThread(tid, pid);
+
+  switch (phase) {
+    case 'B': {  // TRACE_EVENT_BEGIN.
+      slice_tracker->Begin(timestamp, utid, cat_id, name_id);
+      break;
+    }
+    case 'E': {  // TRACE_EVENT_END.
+      slice_tracker->End(timestamp, utid, cat_id, name_id);
+      break;
+    }
+    case 'X': {  // TRACE_EVENT (scoped event).
+      base::Optional<int64_t> opt_dur =
+          json_trace_utils::CoerceToNs(value["dur"]);
+      if (!opt_dur.has_value())
+        return;
+      slice_tracker->Scoped(timestamp, utid, cat_id, name_id, opt_dur.value());
+      break;
+    }
+    case 'M': {  // Metadata events (process and thread names).
+      if (strcmp(value["name"].asCString(), "thread_name") == 0) {
+        const char* thread_name = value["args"]["name"].asCString();
+        auto thread_name_id = context_->storage->InternString(thread_name);
+        procs->UpdateThreadName(tid, thread_name_id);
+        break;
+      }
+      if (strcmp(value["name"].asCString(), "process_name") == 0) {
+        const char* proc_name = value["args"]["name"].asCString();
+        procs->UpdateProcess(pid, base::nullopt, proc_name);
+        break;
+      }
+    }
+  }
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/json_trace_parser.h b/src/trace_processor/json_trace_parser.h
new file mode 100644
index 0000000..9850924
--- /dev/null
+++ b/src/trace_processor/json_trace_parser.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_JSON_TRACE_PARSER_H_
+#define SRC_TRACE_PROCESSOR_JSON_TRACE_PARSER_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <tuple>
+#include <unordered_map>
+
+#include "src/trace_processor/trace_parser.h"
+#include "src/trace_processor/trace_sorter.h"
+#include "src/trace_processor/trace_storage.h"
+
+namespace Json {
+class Value;
+}
+
+namespace perfetto {
+namespace trace_processor {
+
+class TraceProcessorContext;
+
+base::Optional<int64_t> CoerceToInt64(const Json::Value& value);
+base::Optional<uint32_t> CoerceToUint32(const Json::Value& value);
+
+// Parses legacy chrome JSON traces. The support for now is extremely rough
+// and supports only explicit TRACE_EVENT_BEGIN/END events.
+class JsonTraceParser : public TraceParser {
+ public:
+  explicit JsonTraceParser(TraceProcessorContext*);
+  ~JsonTraceParser() override;
+
+  // TraceParser implementation.
+  void ParseTracePacket(int64_t timestamp,
+                        TraceSorter::TimestampedTracePiece) override;
+  void ParseFtracePacket(uint32_t,
+                         int64_t,
+                         TraceSorter::TimestampedTracePiece) override;
+
+ private:
+  TraceProcessorContext* const context_;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_JSON_TRACE_PARSER_H_
diff --git a/src/trace_processor/json_trace_tokenizer.cc b/src/trace_processor/json_trace_tokenizer.cc
new file mode 100644
index 0000000..f6e3de6
--- /dev/null
+++ b/src/trace_processor/json_trace_tokenizer.cc
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2019 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 "src/trace_processor/json_trace_tokenizer.h"
+
+#include <json/reader.h>
+#include <json/value.h>
+
+#include "src/trace_processor/json_trace_utils.h"
+#include "src/trace_processor/stats.h"
+#include "src/trace_processor/trace_blob_view.h"
+#include "src/trace_processor/trace_sorter.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+// Parses at most one JSON dictionary and returns a pointer to the end of it,
+// or nullptr if no dict could be detected.
+// This is to avoid decoding the full trace in memory and reduce heap traffic.
+// E.g.  input:  { a:1 b:{ c:2, d:{ e:3 } } } , { a:4, ... },
+//       output: [   only this is parsed    ] ^return value points here.
+ReadDictRes ReadOneJsonDict(const char* start,
+                            const char* end,
+                            Json::Value* value,
+                            const char** next) {
+  int braces = 0;
+  int square_brackets = 0;
+  const char* dict_begin = nullptr;
+  bool in_string = false;
+  bool is_escaping = false;
+  for (const char* s = start; s < end; s++) {
+    if (isspace(*s) || *s == ',')
+      continue;
+    if (*s == '"' && !is_escaping) {
+      in_string = !in_string;
+      continue;
+    }
+    if (in_string) {
+      // If we're in a string and we see a backslash and the last character was
+      // not a backslash the next character is escaped:
+      is_escaping = *s == '\\' && !is_escaping;
+      // If we're currently parsing a string we should ignore otherwise special
+      // characters:
+      continue;
+    }
+    if (*s == '{') {
+      if (braces == 0)
+        dict_begin = s;
+      braces++;
+      continue;
+    }
+    if (*s == '}') {
+      if (braces <= 0)
+        return kEndOfTrace;
+      if (--braces > 0)
+        continue;
+      Json::Reader reader;
+      if (!reader.parse(dict_begin, s + 1, *value, /*collectComments=*/false)) {
+        PERFETTO_ELOG("JSON error: %s",
+                      reader.getFormattedErrorMessages().c_str());
+        return kFatalError;
+      }
+      *next = s + 1;
+      return kFoundDict;
+    }
+    if (*s == '[') {
+      square_brackets++;
+      continue;
+    }
+    if (*s == ']') {
+      if (square_brackets == 0) {
+        // We've reached the end of [traceEvents] array.
+        // There might be other top level keys in the json (e.g. metadata)
+        // after.
+        // TODO(dproy): Handle trace metadata importing.
+        return kEndOfTrace;
+      }
+      square_brackets--;
+    }
+  }
+  return kNeedsMoreData;
+}
+
+JsonTraceTokenizer::JsonTraceTokenizer(TraceProcessorContext* ctx)
+    : context_(ctx) {}
+JsonTraceTokenizer::~JsonTraceTokenizer() = default;
+
+bool JsonTraceTokenizer::Parse(std::unique_ptr<uint8_t[]> data, size_t size) {
+  buffer_.insert(buffer_.end(), data.get(), data.get() + size);
+  const char* buf = buffer_.data();
+  const char* next = buf;
+  const char* end = buf + buffer_.size();
+
+  if (offset_ == 0) {
+    // Trace could begin in any of these ways:
+    // {"traceEvents":[{
+    // { "traceEvents": [{
+    // [{
+    // Skip up to the first '['
+    while (next != end && *next != '[') {
+      next++;
+    }
+    if (next == end) {
+      PERFETTO_ELOG("Failed to parse: first chunk missing opening [");
+      return false;
+    }
+    next++;
+  }
+
+  auto* trace_sorter = context_->sorter.get();
+
+  while (next < end) {
+    std::unique_ptr<Json::Value> value(new Json::Value());
+    const auto res = ReadOneJsonDict(next, end, value.get(), &next);
+    if (res == kFatalError)
+      return false;
+    if (res == kEndOfTrace || res == kNeedsMoreData)
+      break;
+
+    base::Optional<int64_t> opt_ts =
+        json_trace_utils::CoerceToNs((*value)["ts"]);
+    if (!opt_ts.has_value()) {
+      context_->storage->IncrementStats(stats::json_tokenizer_failure);
+      continue;
+    }
+    int64_t ts = opt_ts.value();
+
+    trace_sorter->PushJsonValue(ts, std::move(value));
+  }
+
+  offset_ += static_cast<uint64_t>(next - buf);
+  buffer_.erase(buffer_.begin(), buffer_.begin() + (next - buf));
+  return true;
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/json_trace_tokenizer.h b/src/trace_processor/json_trace_tokenizer.h
new file mode 100644
index 0000000..c2c4ab5
--- /dev/null
+++ b/src/trace_processor/json_trace_tokenizer.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_JSON_TRACE_TOKENIZER_H_
+#define SRC_TRACE_PROCESSOR_JSON_TRACE_TOKENIZER_H_
+
+#include <stdint.h>
+
+#include "src/trace_processor/chunked_trace_reader.h"
+#include "src/trace_processor/trace_sorter.h"
+#include "src/trace_processor/trace_storage.h"
+
+namespace Json {
+class Value;
+}
+
+namespace perfetto {
+namespace trace_processor {
+
+class TraceProcessorContext;
+
+// Visible for testing.
+enum ReadDictRes { kFoundDict, kNeedsMoreData, kEndOfTrace, kFatalError };
+
+// Visible for testing.
+ReadDictRes ReadOneJsonDict(const char* start,
+                            const char* end,
+                            Json::Value* value,
+                            const char** next);
+
+// Reads a JSON trace in chunks and extracts top level json objects.
+class JsonTraceTokenizer : public ChunkedTraceReader {
+ public:
+  explicit JsonTraceTokenizer(TraceProcessorContext*);
+  ~JsonTraceTokenizer() override;
+
+  // ChunkedTraceReader implementation.
+  bool Parse(std::unique_ptr<uint8_t[]>, size_t) override;
+
+ private:
+  TraceProcessorContext* const context_;
+
+  uint64_t offset_ = 0;
+  // Used to glue together JSON objects that span across two (or more)
+  // Parse boundaries.
+  std::vector<char> buffer_;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_JSON_TRACE_TOKENIZER_H_
diff --git a/src/trace_processor/json_trace_tokenizer_unittest.cc b/src/trace_processor/json_trace_tokenizer_unittest.cc
new file mode 100644
index 0000000..9bfb87e
--- /dev/null
+++ b/src/trace_processor/json_trace_tokenizer_unittest.cc
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2019 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 "src/trace_processor/json_trace_tokenizer.h"
+
+#include <json/value.h>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+TEST(JsonTraceTokenizerTest, Success) {
+  const char* start = R"({ "foo": "bar" })";
+  const char* end = start + strlen(start);
+  const char* next = nullptr;
+  Json::Value value;
+  ReadDictRes result = ReadOneJsonDict(start, end, &value, &next);
+
+  ASSERT_EQ(result, kFoundDict);
+  ASSERT_EQ(next, end);
+  ASSERT_EQ(value["foo"].asString(), "bar");
+}
+
+TEST(JsonTraceTokenizerTest, QuotedBraces) {
+  const char* start = R"({ "foo": "}\"bar{\\" })";
+  const char* end = start + strlen(start);
+  const char* next = nullptr;
+  Json::Value value;
+  ReadDictRes result = ReadOneJsonDict(start, end, &value, &next);
+
+  ASSERT_EQ(result, kFoundDict);
+  ASSERT_EQ(next, end);
+  ASSERT_EQ(value["foo"].asString(), "}\"bar{\\");
+}
+
+TEST(JsonTraceTokenizerTest, TwoDicts) {
+  const char* start = R"({"foo": 1}, {"bar": 2})";
+  const char* middle = start + strlen(R"({"foo": 1})");
+  const char* end = start + strlen(start);
+  const char* next = nullptr;
+  Json::Value value;
+
+  ASSERT_EQ(ReadOneJsonDict(start, end, &value, &next), kFoundDict);
+  ASSERT_EQ(next, middle);
+  ASSERT_EQ(value["foo"].asInt(), 1);
+
+  ASSERT_EQ(ReadOneJsonDict(next, end, &value, &next), kFoundDict);
+  ASSERT_EQ(next, end);
+  ASSERT_EQ(value["bar"].asInt(), 2);
+}
+
+TEST(JsonTraceTokenizerTest, NeedMoreData) {
+  const char* start = R"({"foo": 1)";
+  const char* end = start + strlen(start);
+  const char* next = nullptr;
+  Json::Value value;
+
+  ASSERT_EQ(ReadOneJsonDict(start, end, &value, &next), kNeedsMoreData);
+  ASSERT_EQ(next, nullptr);
+}
+
+TEST(JsonTraceTokenizerTest, FatalError) {
+  const char* start = R"({helloworld})";
+  const char* end = start + strlen(start);
+  const char* next = nullptr;
+  Json::Value value;
+
+  ASSERT_EQ(ReadOneJsonDict(start, end, &value, &next), kFatalError);
+  ASSERT_EQ(next, nullptr);
+}
+
+}  // namespace
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/json_trace_utils.cc b/src/trace_processor/json_trace_utils.cc
new file mode 100644
index 0000000..7394e4e
--- /dev/null
+++ b/src/trace_processor/json_trace_utils.cc
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 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 "src/trace_processor/json_trace_utils.h"
+
+#include <json/value.h>
+#include <limits>
+
+#if !PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD)
+#error The JSON trace parser is supported only in the standalone build for now.
+#endif
+
+namespace perfetto {
+namespace trace_processor {
+namespace json_trace_utils {
+
+// Json trace event timestamps are in us.
+// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit#heading=h.nso4gcezn7n1
+base::Optional<int64_t> CoerceToNs(const Json::Value& value) {
+  switch (static_cast<size_t>(value.type())) {
+    case Json::realValue:
+      return static_cast<int64_t>(value.asDouble() * 1000);
+    case Json::uintValue:
+    case Json::intValue:
+      return value.asInt64() * 1000;
+    case Json::stringValue: {
+      std::string s = value.asString();
+      char* end;
+      int64_t n = strtoll(s.c_str(), &end, 10);
+      if (end != s.data() + s.size())
+        return base::nullopt;
+      return n * 1000;
+    }
+    default:
+      return base::nullopt;
+  }
+}
+
+base::Optional<int64_t> CoerceToInt64(const Json::Value& value) {
+  switch (static_cast<size_t>(value.type())) {
+    case Json::realValue:
+    case Json::uintValue:
+    case Json::intValue:
+      return value.asInt64();
+    case Json::stringValue: {
+      std::string s = value.asString();
+      char* end;
+      int64_t n = strtoll(s.c_str(), &end, 10);
+      if (end != s.data() + s.size())
+        return base::nullopt;
+      return n;
+    }
+    default:
+      return base::nullopt;
+  }
+}
+
+base::Optional<uint32_t> CoerceToUint32(const Json::Value& value) {
+  base::Optional<int64_t> result = CoerceToInt64(value);
+  if (!result.has_value())
+    return base::nullopt;
+  int64_t n = result.value();
+  if (n < 0 || n > std::numeric_limits<uint32_t>::max())
+    return base::nullopt;
+  return static_cast<uint32_t>(n);
+}
+
+}  // namespace json_trace_utils
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/json_trace_utils.h b/src/trace_processor/json_trace_utils.h
new file mode 100644
index 0000000..eef12f4
--- /dev/null
+++ b/src/trace_processor/json_trace_utils.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_JSON_TRACE_UTILS_H_
+#define SRC_TRACE_PROCESSOR_JSON_TRACE_UTILS_H_
+
+#include <stdint.h>
+
+#include "perfetto/base/optional.h"
+
+namespace Json {
+class Value;
+}
+
+namespace perfetto {
+namespace trace_processor {
+
+class TraceProcessorContext;
+
+namespace json_trace_utils {
+
+base::Optional<int64_t> CoerceToNs(const Json::Value& value);
+base::Optional<int64_t> CoerceToInt64(const Json::Value& value);
+base::Optional<uint32_t> CoerceToUint32(const Json::Value& value);
+
+}  // namespace json_trace_utils
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_JSON_TRACE_UTILS_H_
diff --git a/src/trace_processor/json_trace_utils_unittest.cc b/src/trace_processor/json_trace_utils_unittest.cc
new file mode 100644
index 0000000..531d397
--- /dev/null
+++ b/src/trace_processor/json_trace_utils_unittest.cc
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#include "src/trace_processor/json_trace_utils.h"
+
+#include <json/value.h>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace json_trace_utils {
+namespace {
+
+TEST(JsonTraceUtilsTest, CoerceToUint32) {
+  ASSERT_EQ(CoerceToUint32(Json::Value(42)).value_or(0), 42);
+  ASSERT_EQ(CoerceToUint32(Json::Value("42")).value_or(0), 42);
+  ASSERT_EQ(CoerceToInt64(Json::Value(42.1)).value_or(-1), 42);
+}
+
+TEST(JsonTraceUtilsTest, CoerceToInt64) {
+  ASSERT_EQ(CoerceToInt64(Json::Value(42)).value_or(-1), 42);
+  ASSERT_EQ(CoerceToInt64(Json::Value("42")).value_or(-1), 42);
+  ASSERT_EQ(CoerceToInt64(Json::Value(42.1)).value_or(-1), 42);
+  ASSERT_FALSE(CoerceToInt64(Json::Value("foo")).has_value());
+  ASSERT_FALSE(CoerceToInt64(Json::Value("1234!")).has_value());
+}
+
+TEST(JsonTraceUtilsTest, CoerceToNs) {
+  ASSERT_EQ(CoerceToNs(Json::Value(42)).value_or(-1), 42000);
+  ASSERT_EQ(CoerceToNs(Json::Value("42")).value_or(-1), 42000);
+  ASSERT_EQ(CoerceToNs(Json::Value(42.1)).value_or(-1), 42100);
+  ASSERT_FALSE(CoerceToNs(Json::Value("foo")).has_value());
+  ASSERT_FALSE(CoerceToNs(Json::Value("1234!")).has_value());
+}
+
+}  // namespace
+}  // namespace json_trace_utils
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/metadata.h b/src/trace_processor/metadata.h
deleted file mode 100644
index b5bef83..0000000
--- a/src/trace_processor/metadata.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_METADATA_H_
-#define SRC_TRACE_PROCESSOR_METADATA_H_
-
-#include <stddef.h>
-
-#include "src/trace_processor/string_pool.h"
-#include "src/trace_processor/variadic.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace metadata {
-
-// Compile time list of metadata items.
-// clang-format off
-#define PERFETTO_TP_METADATA(F)                                        \
-  F(benchmark_description,               kSingle,  Variadic::kString), \
-  F(benchmark_name,                      kSingle,  Variadic::kString), \
-  F(benchmark_start_time_us,             kSingle,  Variadic::kInt),    \
-  F(benchmark_had_failures,              kSingle,  Variadic::kInt),    \
-  F(benchmark_label,                     kSingle,  Variadic::kString), \
-  F(benchmark_story_name,                kSingle,  Variadic::kString), \
-  F(benchmark_story_run_index,           kSingle,  Variadic::kInt),    \
-  F(benchmark_story_run_time_us,         kSingle,  Variadic::kInt),    \
-  F(benchmark_story_tags,                kMulti,   Variadic::kString), \
-  F(android_packages_list,               kMulti,   Variadic::kInt),    \
-  F(statsd_triggering_subscription_id,   kSingle,  Variadic::kInt),    \
-  F(trace_uuid,                          kSingle,   Variadic::kString)
-// clang-format on
-
-enum KeyType {
-  kSingle,  // One value per key.
-  kMulti    // Multiple values per key.
-};
-
-// Declares an enum of literals (one for each item). The enum values of each
-// literal corresponds to the string index in the arrays below.
-#define PERFETTO_TP_META_ENUM(name, ...) name
-enum KeyIDs : size_t { PERFETTO_TP_METADATA(PERFETTO_TP_META_ENUM), kNumKeys };
-
-// The code below declares an array for each property:
-// name, key type, value type.
-
-#define PERFETTO_TP_META_NAME(name, ...) #name
-constexpr char const* kNames[] = {PERFETTO_TP_METADATA(PERFETTO_TP_META_NAME)};
-
-#define PERFETTO_TP_META_KEYTYPE(_, type, ...) type
-constexpr KeyType kKeyTypes[] = {
-    PERFETTO_TP_METADATA(PERFETTO_TP_META_KEYTYPE)};
-
-#define PERFETTO_TP_META_VALUETYPE(_, __, type, ...) type
-constexpr Variadic::Type kValueTypes[] = {
-    PERFETTO_TP_METADATA(PERFETTO_TP_META_VALUETYPE)};
-
-}  // namespace metadata
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_METADATA_H_
diff --git a/src/trace_processor/metadata_table.cc b/src/trace_processor/metadata_table.cc
deleted file mode 100644
index a31a7c0..0000000
--- a/src/trace_processor/metadata_table.cc
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/metadata_table.h"
-#include "src/trace_processor/sqlite/sqlite_utils.h"
-#include "src/trace_processor/storage_columns.h"
-#include "src/trace_processor/storage_schema.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-MetadataTable::MetadataTable(sqlite3*, const TraceStorage* storage)
-    : storage_(storage) {}
-
-void MetadataTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
-  SqliteTable::Register<MetadataTable>(db, storage, "metadata");
-}
-
-StorageSchema MetadataTable::CreateStorageSchema() {
-  return StorageSchema::Builder()
-      .AddColumn<StringColumn<MetadataKeyNameAccessor>>(
-          "name", &storage_->metadata().keys())
-      .AddColumn<StringColumn<MetadataKeyTypeAccessor>>(
-          "key_type", &storage_->metadata().keys())
-      .AddColumn<ValueColumn>("int_value", Variadic::Type::kInt, storage_)
-      .AddColumn<ValueColumn>("str_value", Variadic::Type::kString, storage_)
-      .Build({"name"});
-}
-
-uint32_t MetadataTable::RowCount() {
-  return static_cast<uint32_t>(storage_->metadata().keys().size());
-}
-
-int MetadataTable::BestIndex(const QueryConstraints&, BestIndexInfo*) {
-  return SQLITE_OK;
-}
-
-MetadataTable::MetadataKeyNameAccessor::MetadataKeyNameAccessor(
-    const std::deque<metadata::KeyIDs>* keys)
-    : keys_(keys) {}
-
-MetadataTable::MetadataKeyNameAccessor::~MetadataKeyNameAccessor() = default;
-
-MetadataTable::MetadataKeyTypeAccessor::MetadataKeyTypeAccessor(
-    const std::deque<metadata::KeyIDs>* keys)
-    : keys_(keys) {}
-
-MetadataTable::MetadataKeyTypeAccessor::~MetadataKeyTypeAccessor() = default;
-
-MetadataTable::ValueColumn::ValueColumn(std::string col_name,
-                                        Variadic::Type type,
-                                        const TraceStorage* storage)
-    : StorageColumn(col_name, false /* hidden */),
-      type_(type),
-      storage_(storage) {
-  PERFETTO_CHECK(type == Variadic::Type::kInt ||
-                 type == Variadic::Type::kString);
-}
-
-void MetadataTable::ValueColumn::ReportResult(sqlite3_context* ctx,
-                                              uint32_t row) const {
-  const auto& metadata = storage_->metadata();
-  auto value_type = metadata::kValueTypes[metadata.keys()[row]];
-  if (value_type != type_) {
-    sqlite3_result_null(ctx);
-    return;
-  }
-
-  if (value_type == Variadic::Type::kInt) {
-    sqlite_utils::ReportSqliteResult(ctx, metadata.values()[row].int_value);
-    return;
-  }
-  if (value_type == Variadic::Type::kString) {
-    const char* str =
-        storage_->GetString(metadata.values()[row].string_value).c_str();
-    sqlite3_result_text(ctx, str, -1, sqlite_utils::kSqliteStatic);
-    return;
-  }
-  PERFETTO_FATAL("Unimplemented metadata value type.");
-}
-
-MetadataTable::ValueColumn::Bounds MetadataTable::ValueColumn::BoundFilter(
-    int,
-    sqlite3_value*) const {
-  return Bounds{};
-}
-
-void MetadataTable::ValueColumn::Filter(int op,
-                                        sqlite3_value* value,
-                                        FilteredRowIndex* index) const {
-  if (type_ == Variadic::Type::kInt) {
-    bool op_is_null = sqlite_utils::IsOpIsNull(op);
-    auto predicate = sqlite_utils::CreateNumericPredicate<int64_t>(op, value);
-    index->FilterRows(
-        [this, predicate, op_is_null](uint32_t row) PERFETTO_ALWAYS_INLINE {
-          const auto& arg = storage_->metadata().values()[row];
-          return arg.type == type_ ? predicate(arg.int_value) : op_is_null;
-        });
-    return;
-  }
-  if (type_ == Variadic::Type::kString) {
-    auto predicate = sqlite_utils::CreateStringPredicate(op, value);
-    index->FilterRows([this, &predicate](uint32_t row) PERFETTO_ALWAYS_INLINE {
-      const auto& arg = storage_->metadata().values()[row];
-      return arg.type == type_
-                 ? predicate(storage_->GetString(arg.string_value).c_str())
-                 : predicate(nullptr);
-    });
-    return;
-  }
-  PERFETTO_FATAL("Unimplemented metadata value type.");
-}
-
-MetadataTable::ValueColumn::Comparator MetadataTable::ValueColumn::Sort(
-    const QueryConstraints::OrderBy& ob) const {
-  if (ob.desc) {
-    return [this](uint32_t f, uint32_t s) { return -CompareRefsAsc(f, s); };
-  }
-  return [this](uint32_t f, uint32_t s) { return CompareRefsAsc(f, s); };
-}
-
-int MetadataTable::ValueColumn::CompareRefsAsc(uint32_t f, uint32_t s) const {
-  const auto& arg_f = storage_->metadata().values()[f];
-  const auto& arg_s = storage_->metadata().values()[s];
-
-  if (arg_f.type == type_ && arg_s.type == type_) {
-    if (type_ == Variadic::Type::kInt) {
-      return sqlite_utils::CompareValuesAsc(arg_f.int_value, arg_s.int_value);
-    }
-    if (type_ == Variadic::Type::kString) {
-      const auto& f_str = storage_->GetString(arg_f.string_value);
-      const auto& s_str = storage_->GetString(arg_s.string_value);
-      return sqlite_utils::CompareValuesAsc(f_str, s_str);
-    }
-    PERFETTO_FATAL("Unimplemented metadata value type.");
-  } else if (arg_s.type == type_) {
-    return -1;
-  } else if (arg_f.type == type_) {
-    return 1;
-  }
-  return 0;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/metadata_table.h b/src/trace_processor/metadata_table.h
deleted file mode 100644
index c7b0dfe..0000000
--- a/src/trace_processor/metadata_table.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_METADATA_TABLE_H_
-#define SRC_TRACE_PROCESSOR_METADATA_TABLE_H_
-
-#include "src/trace_processor/metadata.h"
-#include "src/trace_processor/storage_table.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class MetadataTable : public StorageTable {
- public:
-  MetadataTable(sqlite3*, const TraceStorage*);
-
-  static void RegisterTable(sqlite3* db, const TraceStorage* storage);
-
-  // StorageTable implementation.
-  StorageSchema CreateStorageSchema() override;
-  uint32_t RowCount() override;
-  int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
-
- private:
-  // Returns the stringified key enum name from metadata::kNames.
-  class MetadataKeyNameAccessor : public Accessor<NullTermStringView> {
-   public:
-    MetadataKeyNameAccessor(const std::deque<metadata::KeyIDs>* keys);
-    ~MetadataKeyNameAccessor() override;
-
-    uint32_t Size() const override {
-      return static_cast<uint32_t>(keys_->size());
-    }
-
-    NullTermStringView Get(uint32_t idx) const override {
-      return NullTermStringView(metadata::kNames[(*keys_)[idx]]);
-    }
-
-   private:
-    const std::deque<metadata::KeyIDs>* keys_;
-  };
-
-  // Returns the stringified metadata type, "single" for scalar, "multi" for
-  // repeated.
-  class MetadataKeyTypeAccessor : public Accessor<NullTermStringView> {
-   public:
-    MetadataKeyTypeAccessor(const std::deque<metadata::KeyIDs>* keys);
-    ~MetadataKeyTypeAccessor() override;
-
-    uint32_t Size() const override {
-      return static_cast<uint32_t>(keys_->size());
-    }
-
-    NullTermStringView Get(uint32_t idx) const override {
-      switch (metadata::kKeyTypes[(*keys_)[idx]]) {
-        case metadata::KeyType::kSingle:
-          return NullTermStringView("single");
-          break;
-        case metadata::KeyType::kMulti:
-          return NullTermStringView("multi");
-          break;
-      }
-      PERFETTO_FATAL("unsupported metadata type");  // for gcc
-    }
-
-   private:
-    const std::deque<metadata::KeyIDs>* keys_;
-  };
-
-  // Returns values from Variadic storage. Only supports columns of
-  // type Variadic::Type::kInt or Variadic::Type::kString.
-  //
-  // Based on ArgsTable::ValueColumn.
-  class ValueColumn final : public StorageColumn {
-   public:
-    ValueColumn(std::string col_name,
-                Variadic::Type type,
-                const TraceStorage* storage);
-
-    void ReportResult(sqlite3_context* ctx, uint32_t row) const override;
-    Bounds BoundFilter(int op, sqlite3_value* sqlite_val) const override;
-    void Filter(int op, sqlite3_value* value, FilteredRowIndex*) const override;
-    Comparator Sort(const QueryConstraints::OrderBy& ob) const override;
-
-    bool HasOrdering() const override { return false; }
-
-    SqlValue::Type GetType() const override {
-      if (type_ == Variadic::Type::kInt)
-        return SqlValue::Type::kLong;
-      if (type_ == Variadic::Type::kString)
-        return SqlValue::Type::kString;
-      PERFETTO_FATAL("Unimplemented metadata value type.");
-    }
-
-   private:
-    int CompareRefsAsc(uint32_t f, uint32_t s) const;
-
-    Variadic::Type type_;
-    const TraceStorage* storage_ = nullptr;
-  };
-
-  const TraceStorage* const storage_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_METADATA_TABLE_H_
diff --git a/src/trace_processor/metadata_table_unittest.cc b/src/trace_processor/metadata_table_unittest.cc
deleted file mode 100644
index 9f8309c..0000000
--- a/src/trace_processor/metadata_table_unittest.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/metadata_table.h"
-#include "src/trace_processor/sqlite/scoped_db.h"
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/trace_storage.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-class MetadataTableUnittest : public ::testing::Test {
- public:
-  MetadataTableUnittest() {
-    sqlite3* db = nullptr;
-    PERFETTO_CHECK(sqlite3_initialize() == SQLITE_OK);
-    PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
-    db_.reset(db);
-
-    context_.storage.reset(new TraceStorage());
-    MetadataTable::RegisterTable(db_.get(), context_.storage.get());
-  }
-
-  void PrepareValidStatement(const std::string& sql) {
-    int size = static_cast<int>(sql.size());
-    sqlite3_stmt* stmt;
-    ASSERT_EQ(sqlite3_prepare_v2(*db_, sql.c_str(), size, &stmt, nullptr),
-              SQLITE_OK);
-    stmt_.reset(stmt);
-  }
-
-  const char* GetColumnAsText(int colId) {
-    return reinterpret_cast<const char*>(sqlite3_column_text(*stmt_, colId));
-  }
-
- protected:
-  TraceProcessorContext context_;
-  ScopedDb db_;
-  ScopedStmt stmt_;
-};
-
-TEST_F(MetadataTableUnittest, NoEntries) {
-  PrepareValidStatement("SELECT * FROM metadata");
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(MetadataTableUnittest, SingleStringValue) {
-  static const char kName[] = "benchmark";
-  Variadic value = Variadic::String(context_.storage->InternString(kName));
-  context_.storage->SetMetadata(metadata::benchmark_name, value);
-
-  PrepareValidStatement("SELECT * FROM metadata");
-
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  ASSERT_STREQ(GetColumnAsText(0), "benchmark_name");      // name
-  ASSERT_STREQ(GetColumnAsText(1), "single");              // key_type
-  ASSERT_EQ(sqlite3_column_type(*stmt_, 2), SQLITE_NULL);  // int_value
-  ASSERT_STREQ(GetColumnAsText(3), kName);                 // str_value
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(MetadataTableUnittest, SingleIntegerValue) {
-  static const int64_t kTimestamp = 1234567890;
-  Variadic value = Variadic::Integer(kTimestamp);
-  context_.storage->SetMetadata(metadata::benchmark_story_run_time_us, value);
-
-  PrepareValidStatement("SELECT * FROM metadata");
-
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  ASSERT_STREQ(GetColumnAsText(0), "benchmark_story_run_time_us");  // name
-  ASSERT_STREQ(GetColumnAsText(1), "single");                       // key_type
-  ASSERT_EQ(sqlite3_column_int64(*stmt_, 2), kTimestamp);           // int_value
-  ASSERT_EQ(sqlite3_column_type(*stmt_, 3), SQLITE_NULL);           // str_value
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(MetadataTableUnittest, MultipleStringValues) {
-  static const char kTag1[] = "foo";
-  static const char kTag2[] = "bar";
-  Variadic tag1 = Variadic::String(context_.storage->InternString(kTag1));
-  Variadic tag2 = Variadic::String(context_.storage->InternString(kTag2));
-  context_.storage->AppendMetadata(metadata::benchmark_story_tags, tag1);
-  context_.storage->AppendMetadata(metadata::benchmark_story_tags, tag2);
-
-  PrepareValidStatement("SELECT * FROM metadata");
-
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  ASSERT_STREQ(GetColumnAsText(0), "benchmark_story_tags");  // name
-  ASSERT_STREQ(GetColumnAsText(1), "multi");                 // key_type
-  ASSERT_EQ(sqlite3_column_type(*stmt_, 2), SQLITE_NULL);    // int_value
-  ASSERT_STREQ(GetColumnAsText(3), kTag1);                   // str_value
-
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
-  ASSERT_STREQ(GetColumnAsText(0), "benchmark_story_tags");  // name
-  ASSERT_STREQ(GetColumnAsText(1), "multi");                 // key_type
-  ASSERT_EQ(sqlite3_column_type(*stmt_, 2), SQLITE_NULL);    // int_value
-  ASSERT_STREQ(GetColumnAsText(3), kTag2);                   // str_value
-
-  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/metrics/BUILD.gn b/src/trace_processor/metrics/BUILD.gn
index 28d6f01..1f0fdbf 100644
--- a/src/trace_processor/metrics/BUILD.gn
+++ b/src/trace_processor/metrics/BUILD.gn
@@ -13,32 +13,10 @@
 # limitations under the License.
 
 import("../../../gn/perfetto.gni")
-import("../../../gn/test.gni")
 
 sql_files = [
-  "trace_metadata.sql",
-  "android/android_batt.sql",
-  "android/android_cpu.sql",
-  "android/android_cpu_agg.sql",
   "android/android_mem.sql",
-  "android/android_mem_unagg.sql",
-  "android/android_process_growth.sql",
-  "android/android_ion.sql",
-  "android/android_lmk.sql",
-  "android/android_powrails.sql",
-  "android/android_startup_launches.sql",
-  "android/android_task_state.sql",
-  "android/android_startup.sql",
-  "android/android_startup_cpu.sql",
-  "android/android_package_list.sql",
-  "android/heap_profile_callsites.sql",
-  "android/java_heap_stats.sql",
-  "android/process_unagg_mem_view.sql",
-  "android/process_mem.sql",
-  "android/mem_stats_priority_breakdown.sql",
-  "android/span_view_stats.sql",
-  "android/upid_span_view.sql",
-  "android/unsymbolized_frames.sql",
+  "android/android_mem_lmk.sql",
 ]
 
 config("gen_config") {
@@ -59,43 +37,18 @@
   public_configs = [ ":gen_config" ]
 }
 
-if (enable_perfetto_trace_processor_metrics) {
-  source_set("lib") {
-    sources = [
-      "descriptors.cc",
-      "descriptors.h",
-      "metrics.cc",
-      "metrics.descriptor.h",
-      "metrics.h",
-    ]
-    deps = [
-      "../../../gn:default_deps",
-      "../../../gn:sqlite",
-      "../../../include/perfetto/trace_processor",
-      "../../../protos/perfetto/common:zero",
-      "../../../protos/perfetto/metrics:zero",
-      "../../../protos/perfetto/metrics/android:zero",
-      "../../../protos/perfetto/trace_processor:metrics_impl_zero",
-      "../../base",
-      "../../protozero:protozero",
-      "../sqlite",
-    ]
-    public_deps = [
-      ":gen_merged_sql_metrics",
-    ]
-  }
-
-  perfetto_unittest_source_set("unittests") {
-    testonly = true
-    sources = [
-      "metrics_unittest.cc",
-    ]
-    deps = [
-      ":lib",
-      "../../../gn:default_deps",
-      "../../../gn:gtest_and_gmock",
-      "../../../gn:sqlite",
-      "../../../protos/perfetto/common:zero",
-    ]
-  }
+source_set("lib") {
+  sources = [
+    "metrics.cc",
+    "metrics.h",
+  ]
+  deps = [
+    ":gen_merged_sql_metrics",
+    "../../../buildtools:sqlite",
+    "../../../gn:default_deps",
+    "../../../include/perfetto/trace_processor",
+    "../../../protos/perfetto/metrics:zero",
+    "../../../protos/perfetto/metrics/android:zero",
+    "../../protozero:protozero",
+  ]
 }
diff --git a/src/trace_processor/metrics/android/android_batt.sql b/src/trace_processor/metrics/android/android_batt.sql
deleted file mode 100644
index 79205a4..0000000
--- a/src/trace_processor/metrics/android/android_batt.sql
+++ /dev/null
@@ -1,64 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-CREATE VIEW battery_view AS
-SELECT
-  all_ts.ts as ts,
-  current_avg_ua,
-  capacity_percent,
-  charge_uah,
-  current_ua
-FROM (
-  SELECT distinct(ts) AS ts
-  FROM counters
-  WHERE name LIKE 'batt.%'
-) AS all_ts
-LEFT JOIN (
-  SELECT ts, value AS current_avg_ua
-  FROM counters
-  WHERE name='batt.current.avg_ua'
-) USING(ts)
-LEFT JOIN (
-  SELECT ts, value AS capacity_percent
-  FROM counters
-  WHERE name='batt.capacity_pct'
-) USING(ts)
-LEFT JOIN (
-  SELECT ts, value AS charge_uah
-  FROM counters
-  WHERE name='batt.charge_uah'
-) USING(ts)
-LEFT JOIN (
-  SELECT ts, value AS current_ua
-  FROM counters
-  WHERE name='batt.current_ua'
-) USING(ts)
-ORDER BY ts;
-
-CREATE VIEW android_batt_output AS
-SELECT AndroidBatteryMetric(
-  'battery_counters', (
-    SELECT RepeatedField(
-      AndroidBatteryMetric_BatteryCounters(
-        'timestamp_ns', ts,
-        'charge_counter_uah', charge_uah,
-        'capacity_percent', capacity_percent,
-        'current_ua', current_ua,
-        'current_avg_ua', current_avg_ua
-      )
-    )
-    FROM battery_view
-  )
-);
diff --git a/src/trace_processor/metrics/android/android_cpu.sql b/src/trace_processor/metrics/android/android_cpu.sql
deleted file mode 100644
index ef6dc82..0000000
--- a/src/trace_processor/metrics/android/android_cpu.sql
+++ /dev/null
@@ -1,82 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
--- Create all the views used to generate the Android Cpu metrics proto.
-SELECT RUN_METRIC('android/android_cpu_agg.sql');
-
-CREATE VIEW cpu_breakdown_per_utid AS
-SELECT
-  utid,
-  CAST(SUM(dur * freq / 1000000) AS INT) AS normalized_cpu_cycles,
-  AndroidCpuMetric_CpuFrequencyData(
-    'id', cpu,
-    'avg_freq_khz', CAST((SUM(dur * freq) / SUM(dur)) AS INT),
-    'duration_ns', CAST(SUM(dur) AS INT),
-    'min_freq_khz', CAST(MIN(freq) AS INT),
-    'max_freq_khz', CAST(MAX(freq) AS INT)
-  ) as cpu_freq_proto
-FROM cpu_freq_sched_per_thread
-GROUP BY utid, cpu;
-
--- CPU info aggregated per thread, with repeated containing separate data for
--- each CPU.
-CREATE VIEW agg_by_thread AS
-SELECT
-  utid,
-  upid,
-  thread.name AS thread_name,
-  process.name AS process_name,
-  CAST(SUM(normalized_cpu_cycles) AS INT) AS normalized_cpu_cycles,
-  RepeatedField(cpu_freq_proto) AS thread_proto_cpu
-FROM thread
-JOIN process USING (upid)
-LEFT JOIN cpu_breakdown_per_utid USING (utid)
-GROUP BY utid;
-
--- CPU info aggregated per process, with repeated containing separate data for
--- thread.
-CREATE TABLE agg_by_process AS
-SELECT
-  upid,
-  process_name,
-  CAST(SUM(normalized_cpu_cycles) AS INT) AS normalized_cpu_cycles,
-  RepeatedField(
-    AndroidCpuMetric_Thread(
-      'name', CAST(thread_name as TEXT),
-      'cpu', thread_proto_cpu,
-      'normalized_cpu_cycles', CAST(normalized_cpu_cycles as INT)
-    )
-  ) AS thread_proto
-FROM agg_by_thread
-GROUP BY upid;
-
--- Generate Process proto.
-CREATE VIEW thread_cpu_view AS
-SELECT
-  AndroidCpuMetric_Process(
-    'name', process_name,
-    'threads', thread_proto,
-    'normalized_cpu_cycles', CAST(normalized_cpu_cycles AS INT)
-  ) AS cpu_info_process
-FROM agg_by_process
-GROUP BY upid;
-
-CREATE VIEW android_cpu_output AS
-SELECT AndroidCpuMetric(
-  'process_info', (
-    SELECT RepeatedField(cpu_info_process) FROM thread_cpu_view
-  )
-);
diff --git a/src/trace_processor/metrics/android/android_cpu_agg.sql b/src/trace_processor/metrics/android/android_cpu_agg.sql
deleted file mode 100644
index 9105966..0000000
--- a/src/trace_processor/metrics/android/android_cpu_agg.sql
+++ /dev/null
@@ -1,33 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
--- Create all the views used to aggregate CPU data.
--- View with start and end ts for each cpu frequency, per cpu.
-CREATE VIEW cpu_freq_view AS
-SELECT
-  ref as cpu,
-  ts,
-  LEAD(ts, 1, (SELECT end_ts from trace_bounds))
-    OVER (PARTITION by ref ORDER BY ts) AS end_ts,
-  LEAD(ts, 1, (SELECT end_ts from trace_bounds))
-    OVER (PARTITION by ref ORDER BY ts) - ts AS dur,
-  value as freq
-FROM counters
-WHERE name = 'cpufreq';
-
--- View that joins the cpufreq table with the slice table.
-CREATE VIRTUAL TABLE cpu_freq_sched_per_thread
-USING SPAN_LEFT_JOIN(sched PARTITIONED cpu, cpu_freq_view PARTITIONED cpu);
diff --git a/src/trace_processor/metrics/android/android_ion.sql b/src/trace_processor/metrics/android/android_ion.sql
deleted file mode 100644
index 6d4174a..0000000
--- a/src/trace_processor/metrics/android/android_ion.sql
+++ /dev/null
@@ -1,46 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
-CREATE VIEW ion_timeline AS
-SELECT
-  ts,
-  LEAD(ts, 1, (SELECT end_ts FROM trace_bounds))
-    OVER(PARTITION BY counter_id ORDER BY ts) - ts AS dur,
-  SUBSTR(name, 9) AS heap_name,
-  value
-FROM counter_definitions JOIN counter_values USING(counter_id)
-WHERE name LIKE 'mem.ion.%' AND ref_type IS NULL;
-
-CREATE VIEW ion_buffers AS
-SELECT
-  heap_name,
-  SUM(value * dur) / SUM(dur) AS avg_size,
-  MIN(value) AS min_size,
-  MAX(value) AS max_size
-FROM ion_timeline
-GROUP BY 1;
-
-CREATE VIEW android_ion_output AS
-SELECT AndroidIonMetric(
-  'buffer', RepeatedField(
-    AndroidIonMetric_Buffer(
-      'name', heap_name,
-      'avg_size_bytes', avg_size,
-      'min_size_bytes', min_size,
-      'max_size_bytes', max_size
-    )
-  ))
-FROM ion_buffers;
diff --git a/src/trace_processor/metrics/android/android_lmk.sql b/src/trace_processor/metrics/android/android_lmk.sql
deleted file mode 100644
index 253a7cf..0000000
--- a/src/trace_processor/metrics/android/android_lmk.sql
+++ /dev/null
@@ -1,60 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
--- Create all the views used to for LMK related stuff.
-CREATE TABLE lmk_events AS
-SELECT ref AS upid, MIN(ts) AS ts
-FROM instants
-WHERE name = 'mem.lmk' AND ref_type = 'upid'
-GROUP BY 1;
-
-CREATE VIEW oom_scores AS
-SELECT
-  ts,
-  LEAD(ts, 1, (SELECT end_ts + 1 FROM trace_bounds))
-    OVER(PARTITION BY counter_id ORDER BY ts) AS ts_end,
-  ref AS upid,
-  value AS score
-FROM counter_definitions JOIN counter_values USING(counter_id)
-WHERE name = 'oom_score_adj' AND ref IS NOT NULL AND ref_type = 'upid';
-
-CREATE VIEW lmk_by_score AS
-SELECT lmk_events.upid, CAST(oom_scores.score AS INT) AS score
-FROM lmk_events
-LEFT JOIN oom_scores
-  ON (lmk_events.upid = oom_scores.upid AND
-      lmk_events.ts >= oom_scores.ts AND
-      lmk_events.ts < oom_scores.ts_end)
-ORDER BY lmk_events.upid;
-
-CREATE VIEW lmk_counts AS
-SELECT score, COUNT(1) AS count
-FROM lmk_by_score
-GROUP BY score;
-
-CREATE VIEW android_lmk_output AS
-SELECT AndroidLmkMetric(
-  'total_count', (SELECT COUNT(1) FROM lmk_events),
-  'by_oom_score', (
-    SELECT
-      RepeatedField(AndroidLmkMetric_ByOomScore(
-        'oom_score_adj', score,
-        'count', count
-      ))
-    FROM lmk_counts
-    WHERE score IS NOT NULL
-  )
-);
diff --git a/src/trace_processor/metrics/android/android_mem.sql b/src/trace_processor/metrics/android/android_mem.sql
index 919e26d..7646381 100644
--- a/src/trace_processor/metrics/android/android_mem.sql
+++ b/src/trace_processor/metrics/android/android_mem.sql
@@ -14,107 +14,5 @@
 -- limitations under the License.
 --
 
-SELECT RUN_METRIC('android/process_mem.sql');
-
-SELECT RUN_METRIC('android/span_view_stats.sql', 'table_name', 'anon_rss');
-
-SELECT RUN_METRIC('android/span_view_stats.sql', 'table_name', 'file_rss');
-
-SELECT RUN_METRIC('android/span_view_stats.sql', 'table_name', 'swap');
-
-SELECT RUN_METRIC('android/span_view_stats.sql', 'table_name', 'anon_and_swap');
-
-SELECT RUN_METRIC('android/span_view_stats.sql', 'table_name', 'java_heap');
-
-SELECT RUN_METRIC('android/mem_stats_priority_breakdown.sql', 'table_name', 'anon_rss');
-
-SELECT RUN_METRIC('android/mem_stats_priority_breakdown.sql', 'table_name', 'file_rss');
-
-SELECT RUN_METRIC('android/mem_stats_priority_breakdown.sql', 'table_name', 'swap');
-
-SELECT RUN_METRIC('android/mem_stats_priority_breakdown.sql', 'table_name', 'anon_and_swap');
-
-SELECT RUN_METRIC('android/mem_stats_priority_breakdown.sql', 'table_name', 'java_heap');
-
--- Find out all process + priority pairs with data to drive the joins (no outer join in sqlite).
-CREATE VIEW mem_all_processes AS
-SELECT DISTINCT process_name
-FROM
-(
-  SELECT process_name FROM anon_rss_stats_proto
-  UNION
-  SELECT process_name FROM file_rss_stats_proto
-  UNION
-  SELECT process_name FROM swap_stats_proto
-  UNION
-  SELECT process_name FROM anon_and_swap_stats_proto
-  UNION
-  SELECT process_name FROM java_heap_stats_proto
-);
-
-CREATE VIEW mem_all_process_priorities AS
-SELECT DISTINCT process_name, priority
-FROM
-(
-  SELECT process_name, priority FROM anon_rss_by_priority_stats_proto
-  UNION
-  SELECT process_name, priority FROM file_rss_by_priority_stats_proto
-  UNION
-  SELECT process_name, priority FROM swap_by_priority_stats_proto
-  UNION
-  SELECT process_name, priority FROM anon_and_swap_by_priority_stats_proto
-  UNION
-  SELECT process_name, priority FROM java_heap_by_priority_stats_proto
-);
-
-CREATE VIEW process_priority_view AS
-SELECT
-  process_name,
-  AndroidMemoryMetric_PriorityBreakdown(
-    'priority', priority,
-    'counters', AndroidMemoryMetric_ProcessMemoryCounters(
-      'anon_rss', anon_rss_by_priority_stats_proto.proto,
-      'file_rss', file_rss_by_priority_stats_proto.proto,
-      'swap', swap_by_priority_stats_proto.proto,
-      'anon_and_swap', anon_and_swap_by_priority_stats_proto.proto,
-      'java_heap', java_heap_by_priority_stats_proto.proto
-    )
-  ) AS priority_breakdown_proto
-FROM mem_all_process_priorities
-LEFT JOIN anon_rss_by_priority_stats_proto USING (process_name, priority)
-LEFT JOIN file_rss_by_priority_stats_proto USING (process_name, priority)
-LEFT JOIN swap_by_priority_stats_proto USING (process_name, priority)
-LEFT JOIN anon_and_swap_by_priority_stats_proto USING (process_name, priority)
-LEFT JOIN java_heap_by_priority_stats_proto USING (process_name, priority);
-
-CREATE VIEW process_metrics_view AS
-SELECT
-  AndroidMemoryMetric_ProcessMetrics(
-    'process_name', process_name,
-    'total_counters', AndroidMemoryMetric_ProcessMemoryCounters(
-      'anon_rss', anon_rss_stats_proto.proto,
-      'file_rss', file_rss_stats_proto.proto,
-      'swap', swap_stats_proto.proto,
-      'anon_and_swap', anon_and_swap_stats_proto.proto,
-      'java_heap', java_heap_stats_proto.proto
-    ),
-    'priority_breakdown', (
-      SELECT RepeatedField(priority_breakdown_proto)
-      FROM process_priority_view AS ppv
-      WHERE mem_all_processes.process_name = ppv.process_name
-    )
-  ) AS metric
-FROM
-  mem_all_processes
-  LEFT JOIN anon_rss_stats_proto USING (process_name)
-  LEFT JOIN file_rss_stats_proto USING (process_name)
-  LEFT JOIN swap_stats_proto USING (process_name)
-  LEFT JOIN anon_and_swap_stats_proto USING (process_name)
-  LEFT JOIN java_heap_stats_proto USING (process_name);
-
-CREATE VIEW android_mem_output AS
-SELECT
-  AndroidMemoryMetric(
-    'process_metrics',
-    (SELECT RepeatedField(metric) FROM process_metrics_view)
-  );
+-- Create all the views used to generate the Android Memory metrics proto.
+SELECT RUN_METRIC('android_mem_lmk.sql');
diff --git a/src/trace_processor/metrics/android/android_mem_lmk.sql b/src/trace_processor/metrics/android/android_mem_lmk.sql
new file mode 100644
index 0000000..e24f736
--- /dev/null
+++ b/src/trace_processor/metrics/android/android_mem_lmk.sql
@@ -0,0 +1,42 @@
+--
+-- Copyright 2019 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
+--
+--     https://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.
+--
+
+-- Create all the views used to for LMK related stuff.
+CREATE TABLE last_oom_adj(upid BIG INT PRIMARY KEY, ts BIG INT, score INT);
+
+INSERT INTO last_oom_adj
+SELECT upid, ts, score
+FROM (
+  SELECT ref AS upid,
+         ts,
+         CAST(value AS INT) AS score,
+         row_number() OVER (PARTITION BY counter_id ORDER BY ts DESC) AS rank
+  FROM counter_definitions JOIN counter_values USING(counter_id)
+  WHERE name = 'oom_score_adj'
+  AND ref_type = 'upid')
+WHERE rank = 1;
+
+CREATE VIEW lmk_events AS
+SELECT ref AS upid
+FROM instants
+WHERE name = 'mem.lmk' AND ref_type = 'upid';
+
+CREATE VIEW lmk_by_score AS
+SELECT process.name, last_oom_adj.score
+FROM lmk_events
+LEFT JOIN process ON lmk_events.upid = process.upid
+LEFT JOIN last_oom_adj ON lmk_events.upid = last_oom_adj.upid
+ORDER BY lmk_events.upid;
diff --git a/src/trace_processor/metrics/android/android_mem_unagg.sql b/src/trace_processor/metrics/android/android_mem_unagg.sql
deleted file mode 100644
index 5d147d0..0000000
--- a/src/trace_processor/metrics/android/android_mem_unagg.sql
+++ /dev/null
@@ -1,60 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
-SELECT RUN_METRIC('android/process_mem.sql');
-
-SELECT RUN_METRIC('android/process_unagg_mem_view.sql',
-  'table_name', 'anon_rss');
-
-SELECT RUN_METRIC('android/process_unagg_mem_view.sql',
-  'table_name', 'swap');
-
-SELECT RUN_METRIC('android/process_unagg_mem_view.sql',
-  'table_name', 'file_rss');
-
-SELECT RUN_METRIC('android/process_unagg_mem_view.sql',
-  'table_name', 'anon_and_swap');
-
-CREATE VIEW process_unagg_metrics_view AS
-SELECT
-  AndroidMemoryUnaggregatedMetric_ProcessValues(
-    'process_name', process.name,
-    'mem_values', AndroidMemoryUnaggregatedMetric_ProcessMemoryValues(
-      'anon_rss', anon_rss_unagg_values.metric,
-      'swap', swap_unagg_values.metric,
-      'file_rss', file_rss_unagg_values.metric,
-      'anon_and_swap', anon_and_swap_unagg_values.metric
-    )
-  ) AS metric
-FROM
-  process
-LEFT JOIN
-  anon_rss_unagg_values USING(upid)
-LEFT JOIN
-  swap_unagg_values USING(upid)
-LEFT JOIN
-  file_rss_unagg_values USING(upid)
-LEFT JOIN
-  anon_and_swap_unagg_values USING(upid)
-WHERE
-  process.name IS NOT NULL;
-
-CREATE VIEW android_mem_unagg_output AS
-SELECT
-  AndroidMemoryUnaggregatedMetric(
-    'process_values',
-    (SELECT RepeatedField(metric) FROM process_unagg_metrics_view)
-  );
diff --git a/src/trace_processor/metrics/android/android_package_list.sql b/src/trace_processor/metrics/android/android_package_list.sql
deleted file mode 100644
index ff9bbfe..0000000
--- a/src/trace_processor/metrics/android/android_package_list.sql
+++ /dev/null
@@ -1,52 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
--- Get distinct packages list
-CREATE VIEW package_arg_ids AS
-SELECT int_value AS arg_set_id
-FROM metadata WHERE name = 'android_packages_list';
-
--- Generate a table mapping package names to their attributes
-CREATE VIEW package_args AS
-SELECT arg_set_id, key, string_value, int_value
-FROM package_arg_ids JOIN args USING(arg_set_id);
-
-CREATE TABLE package_list(
-  package_name TEXT PRIMARY KEY,
-  uid INT,
-  version_code INT
-);
-
-INSERT OR REPLACE INTO package_list
-SELECT names.name, uids.uid, versions.version
-FROM
-  (SELECT arg_set_id, string_value name FROM package_args WHERE key = 'name')
-    AS names
-  JOIN (SELECT arg_set_id, int_value uid FROM package_args WHERE key = 'uid')
-    AS uids USING (arg_set_id)
-  JOIN (SELECT arg_set_id, int_value version FROM package_args WHERE key = 'version_code')
-    AS versions USING (arg_set_id);
-
-CREATE VIEW android_package_list_output AS
-SELECT AndroidPackageList(
-  'packages', (
-    SELECT RepeatedField(AndroidPackageList_Package(
-      'package_name', package_name,
-      'uid', uid,
-      'version_code', version_code
-    )) FROM package_list
-  )
-);
diff --git a/src/trace_processor/metrics/android/android_powrails.sql b/src/trace_processor/metrics/android/android_powrails.sql
deleted file mode 100644
index 5825d3c..0000000
--- a/src/trace_processor/metrics/android/android_powrails.sql
+++ /dev/null
@@ -1,45 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
--- View of Power Rail counters with ts converted from ns to ms.
-CREATE VIEW power_rails_counters AS
-SELECT value, ts/1000000 AS ts, name FROM counters WHERE name LIKE 'power.%';
-
-CREATE VIEW power_rails_view AS
-WITH RECURSIVE name AS (SELECT DISTINCT name FROM power_rails_counters)
-SELECT
-  name,
-  ts,
-  AndroidPowerRails_PowerRails(
-    'name', name,
-    'energy_data', RepeatedField(
-      AndroidPowerRails_EnergyData(
-        'timestamp_ms', ts,
-        'energy_uws', value
-      )
-    )
-  ) AS power_rails_proto
-FROM power_rails_counters
-GROUP BY name
-ORDER BY ts ASC;
-
-CREATE VIEW android_powrails_output AS
-SELECT AndroidPowerRails(
-  'power_rails', (
-    SELECT RepeatedField(power_rails_proto)
-    FROM power_rails_view
-  )
-);
diff --git a/src/trace_processor/metrics/android/android_process_growth.sql b/src/trace_processor/metrics/android/android_process_growth.sql
deleted file mode 100644
index 956ce92..0000000
--- a/src/trace_processor/metrics/android/android_process_growth.sql
+++ /dev/null
@@ -1,69 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
-SELECT RUN_METRIC('android/process_mem.sql');
-
-CREATE VIEW malloc_memory_delta AS
-SELECT upid, SUM(size) AS delta
-FROM heap_profile_allocation
-GROUP BY 1;
-
-CREATE VIEW malloc_memory_allocated AS
-SELECT upid, SUM(size) AS total
-FROM heap_profile_allocation
-WHERE size > 0
-GROUP BY 1;
-
-CREATE VIEW anon_and_swap_delta AS
-SELECT DISTINCT
-  upid,
-  FIRST_VALUE(anon_and_swap_val) OVER upid_window AS start_val,
-  LAST_VALUE(anon_and_swap_val) OVER upid_window AS end_val
-FROM anon_and_swap_span
-WINDOW upid_window AS (
-  PARTITION BY upid
-  ORDER BY ts
-  ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
-);
-
-CREATE VIEW process_growth AS
-SELECT
-  process.pid AS pid,
-  process.name AS process_name,
-  CAST(asd.start_val AS BIG INT) AS anon_and_swap_start_value,
-  CAST(asd.end_val - asd.start_val AS BIG INT) AS anon_and_swap_change,
-  malloc_memory_delta.delta AS malloc_memory_delta,
-  malloc_memory_allocated.total AS malloc_memory_total
-FROM anon_and_swap_delta AS asd
-JOIN process USING (upid)
-LEFT JOIN malloc_memory_delta USING (upid)
-LEFT JOIN malloc_memory_allocated USING (upid);
-
-CREATE VIEW instance_metrics_proto AS
-SELECT AndroidProcessGrowth_InstanceMetrics(
-  'pid', pid,
-  'process_name', process_name,
-  'anon_and_swap_start_value', anon_and_swap_start_value,
-  'anon_and_swap_change_bytes', anon_and_swap_change,
-  'malloc_memory_change_bytes', malloc_memory_delta,
-  'malloc_memory_total_allocated_bytes', malloc_memory_total
-) AS instance_metric
-FROM process_growth;
-
-CREATE VIEW android_process_growth_output AS
-SELECT AndroidProcessGrowth(
-  'instance_metrics', (SELECT RepeatedField(instance_metric) FROM instance_metrics_proto)
-);
diff --git a/src/trace_processor/metrics/android/android_startup.sql b/src/trace_processor/metrics/android/android_startup.sql
deleted file mode 100644
index f1484e4..0000000
--- a/src/trace_processor/metrics/android/android_startup.sql
+++ /dev/null
@@ -1,178 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
--- Create the base tables and views containing the launch spans.
-SELECT RUN_METRIC('android/android_startup_launches.sql');
-SELECT RUN_METRIC('android/android_task_state.sql');
-SELECT RUN_METRIC('android/android_startup_cpu.sql');
-
--- Slices for forked processes. Never present in hot starts.
--- Prefer this over process start_ts, since the process might have
--- been preforked.
-CREATE VIEW zygote_fork_slices AS
-SELECT slices.ts, slices.dur, STR_SPLIT(slices.name, ": ", 1) AS process_name
-FROM slices WHERE name LIKE 'Start proc: %';
-
-CREATE TABLE zygote_forks_by_id AS
-SELECT
-  launches.id,
-  zygote_fork_slices.ts,
-  zygote_fork_slices.dur
-FROM zygote_fork_slices
-JOIN launches
-ON (launches.ts < zygote_fork_slices.ts
-    AND zygote_fork_slices.ts + zygote_fork_slices.dur < launches.ts_end
-    AND zygote_fork_slices.process_name = launches.package
-);
-
-CREATE VIEW launch_main_threads AS
-SELECT
-  launches.ts AS ts,
-  launches.dur AS dur,
-  launches.id AS launch_id,
-  thread.utid AS utid
-FROM launches
-JOIN launch_processes ON launches.id = launch_processes.launch_id
-JOIN process USING(upid)
-JOIN thread ON (process.upid = thread.upid AND process.pid = thread.tid)
-ORDER BY ts;
-
-CREATE VIRTUAL TABLE main_thread_state
-USING SPAN_JOIN(
-  launch_main_threads PARTITIONED utid,
-  task_state PARTITIONED utid);
-
-CREATE VIEW launch_by_thread_state AS
-SELECT launch_id, state, SUM(dur) AS dur
-FROM main_thread_state
-GROUP BY 1, 2;
-
--- Tracks all slices for the main process threads
-CREATE TABLE main_process_slices AS
-SELECT
-  launches.id AS launch_id,
-  slices.name AS name,
-  AndroidStartupMetric_Slice('dur_ns', SUM(slices.dur)) AS slice_proto
-FROM launches
-JOIN launch_processes ON (launches.id = launch_processes.launch_id)
-JOIN thread ON (launch_processes.upid = thread.upid)
-JOIN slices ON (
-  slices.utid = thread.utid
-  AND slices.ts BETWEEN launches.ts AND launches.ts + launches.dur)
-WHERE slices.name IN (
-  'ActivityThreadMain',
-  'bindApplication',
-  'activityStart',
-  'activityResume',
-  'Choreographer#doFrame',
-  'inflate')
-GROUP BY 1, 2;
-
-CREATE VIEW startup_view AS
-SELECT
-  AndroidStartupMetric_Startup(
-    'startup_id', launches.id,
-    'package_name', launches.package,
-    'process_name', (
-      SELECT name FROM process
-      WHERE upid IN (
-        SELECT upid FROM launch_processes
-        WHERE launch_id = launches.id
-        LIMIT 1
-      )
-    ),
-    'zygote_new_process', EXISTS(SELECT TRUE FROM zygote_forks_by_id WHERE id = launches.id),
-    'activity_hosting_process_count', (
-      SELECT COUNT(1) FROM launch_processes WHERE launch_id = launches.id
-    ),
-    'to_first_frame', AndroidStartupMetric_ToFirstFrame(
-      'dur_ns', launches.dur,
-      'main_thread_by_task_state', AndroidStartupMetric_TaskStateBreakdown(
-        'running_dur_ns', IFNULL(
-            (
-            SELECT dur FROM launch_by_thread_state
-            WHERE launch_id = launches.id AND state = 'running'
-            ), 0),
-        'runnable_dur_ns', IFNULL(
-            (
-            SELECT dur FROM launch_by_thread_state
-            WHERE launch_id = launches.id AND state = 'runnable'
-            ), 0),
-        'uninterruptible_sleep_dur_ns', IFNULL(
-            (
-            SELECT dur FROM launch_by_thread_state
-            WHERE launch_id = launches.id AND state = 'uninterruptible'
-            ), 0),
-        'interruptible_sleep_dur_ns', IFNULL(
-            (
-            SELECT dur FROM launch_by_thread_state
-            WHERE launch_id = launches.id AND state = 'interruptible'
-            ), 0)
-      ),
-      'other_processes_spawned_count', (
-        SELECT COUNT(1) FROM process
-        WHERE (process.name IS NULL OR process.name != launches.package)
-        AND process.start_ts BETWEEN launches.ts AND launches.ts + launches.dur
-      ),
-      'time_activity_manager', AndroidStartupMetric_Slice(
-        'dur_ns', (
-          SELECT launching_events.ts - launches.ts FROM launching_events
-          WHERE launching_events.type = 'S'
-          AND launching_events.ts BETWEEN launches.ts AND launches.ts + launches.dur
-        )
-      ),
-      'time_activity_thread_main', (
-        SELECT slice_proto FROM main_process_slices
-        WHERE launch_id = launches.id AND name = 'ActivityThreadMain'
-      ),
-      'time_bind_application', (
-        SELECT slice_proto FROM main_process_slices
-        WHERE launch_id = launches.id AND name = 'bindApplication'
-      ),
-      'time_activity_start', (
-        SELECT slice_proto FROM main_process_slices
-        WHERE launch_id = launches.id AND name = 'activityStart'
-      ),
-      'time_activity_resume', (
-        SELECT slice_proto FROM main_process_slices
-        WHERE launch_id = launches.id AND name = 'activityResume'
-      ),
-      'time_choreographer', (
-        SELECT slice_proto FROM main_process_slices
-        WHERE launch_id = launches.id AND name = 'Choreographer#doFrame'
-      ),
-      'time_before_start_process', (
-        SELECT AndroidStartupMetric_Slice('dur_ns', ts - launches.ts)
-        FROM zygote_forks_by_id WHERE id = launches.id
-      ),
-      'time_during_start_process', (
-        SELECT AndroidStartupMetric_Slice('dur_ns', dur)
-        FROM zygote_forks_by_id WHERE id = launches.id
-      ),
-      'other_process_to_activity_cpu_ratio', (
-        SELECT cpu_ratio FROM launch_cpu WHERE launch_id = launches.id
-      )
-    )
-  ) as startup
-FROM launches;
-
-CREATE VIEW android_startup_output AS
-SELECT
-  AndroidStartupMetric(
-    'startup', (
-      SELECT RepeatedField(startup) FROM startup_view
-    )
-  );
diff --git a/src/trace_processor/metrics/android/android_startup_cpu.sql b/src/trace_processor/metrics/android/android_startup_cpu.sql
deleted file mode 100644
index f71282e..0000000
--- a/src/trace_processor/metrics/android/android_startup_cpu.sql
+++ /dev/null
@@ -1,51 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
--- Sched view per process
-CREATE VIEW per_process_cpu AS
-SELECT process.upid AS upid, ts, dur
-FROM sched
-JOIN thread USING(utid)
-JOIN process USING(upid);
-
--- CPU usage during the activity launch.
-CREATE TABLE launch_cpu_per_process_type AS
-SELECT
-  id AS launch_id,
-  per_process_cpu.upid IN (
-    SELECT upid FROM launch_processes AS lp WHERE lp.launch_id = launches.id
-  ) AS is_launch_process,
-  SUM(per_process_cpu.dur) AS dur
-FROM launches
-JOIN per_process_cpu ON (
-  per_process_cpu.ts BETWEEN launches.ts AND launches.ts + launches.dur)
-GROUP BY 1, 2;
-
-CREATE VIEW launch_cpu AS
-SELECT
-  launch_id,
-  other_process.dur AS other_process_dur,
-  launch_process.dur AS launch_process_dur,
-  1.0 * IFNULL(other_process.dur, 0) / launch_process.dur AS cpu_ratio
-FROM (
-  SELECT * FROM launch_cpu_per_process_type
-  WHERE is_launch_process = 1
-) AS launch_process
-LEFT JOIN (
-  SELECT * FROM launch_cpu_per_process_type
-  WHERE is_launch_process = 0
-) AS other_process
-USING (launch_id);
diff --git a/src/trace_processor/metrics/android/android_startup_launches.sql b/src/trace_processor/metrics/android/android_startup_launches.sql
deleted file mode 100644
index e714d4c..0000000
--- a/src/trace_processor/metrics/android/android_startup_launches.sql
+++ /dev/null
@@ -1,120 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
--- Helper to optimize the query for launching events
--- TODO(b/132771327): remove when fixed
-CREATE TABLE launching_events_helper AS
-SELECT
-  arg_set_id,
-  STR_SPLIT(STR_SPLIT(args.string_value, "|", 2), ": ", 1) package_name,
-  STR_SPLIT(args.string_value, "|", 0) type
-FROM args
-WHERE string_value LIKE '%|launching: %';
-
--- TODO: Replace with proper async slices once available
--- The start of the launching event corresponds to the end of the AM handling
--- the startActivity intent, whereas the end corresponds to the first frame drawn.
--- Only successful app launches have a launching event.
-CREATE TABLE launching_events AS
-SELECT
-  ts,
-  package_name,
-  type
-FROM raw
-CROSS JOIN launching_events_helper
-JOIN thread USING(utid)
-JOIN process USING(upid)
-WHERE raw.arg_set_id = launching_events_helper.arg_set_id
-AND raw.name = 'print'
-AND process.name = 'system_server';
-
--- Marks the beginning of the trace and is equivalent to when the statsd launch
--- logging begins.
-CREATE VIEW activity_intent_received AS
-SELECT ts FROM slices
-WHERE name = 'MetricsLogger:launchObserverNotifyIntentStarted';
-
--- Successful activity launch. The end of the 'launching' event is not related
--- to whether it actually succeeded or not.
-CREATE VIEW activity_intent_launch_successful AS
-SELECT ts FROM slices
-WHERE name = 'MetricsLogger:launchObserverNotifyActivityLaunchFinished';
-
--- We partition the trace into spans based on posted activity intents.
--- We will refine these progressively in the next steps to only encompass
--- activity starts.
-CREATE TABLE activity_intent_recv_spans(id INT, ts BIG INT, dur BIG INT);
-
-INSERT INTO activity_intent_recv_spans
-SELECT
-  ROW_NUMBER()
-    OVER(ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS id,
-  ts,
-  LEAD(ts, 1, (SELECT end_ts FROM trace_bounds)) OVER(ORDER BY ts) - ts AS dur
-FROM activity_intent_received
-ORDER BY ts;
-
--- Filter activity_intent_recv_spans, keeping only the ones that triggered
--- a launch.
-CREATE VIEW launch_partitions AS
-SELECT * FROM activity_intent_recv_spans AS spans
-WHERE 1 = (
-  SELECT COUNT(1)
-  FROM launching_events
-  WHERE TRUE
-    AND type = 'S'
-    AND ts BETWEEN spans.ts AND spans.ts + spans.dur);
-
--- All activity launches in the trace, keyed by ID.
-CREATE TABLE launches(
-  ts BIG INT,
-  ts_end BIG INT,
-  dur BIG INT,
-  id INT,
-  package STRING);
-
--- Use the starting event package name. The finish event package name
--- is not reliable in the case of failed launches.
-INSERT INTO launches
-SELECT
-  lpart.ts AS ts,
-  finish_event.ts AS ts_end,
-  finish_event.ts - lpart.ts AS dur,
-  lpart.id AS id,
-  start_event.package_name AS package
-FROM launch_partitions AS lpart
-JOIN (SELECT * FROM launching_events WHERE type = 'S') AS start_event
-  ON start_event.ts BETWEEN lpart.ts AND lpart.ts + lpart.dur
-JOIN (SELECT * FROM launching_events WHERE type = 'F') AS finish_event
-  ON finish_event.ts BETWEEN lpart.ts AND lpart.ts + lpart.dur
-JOIN activity_intent_launch_successful AS successful
-  ON successful.ts BETWEEN lpart.ts AND lpart.ts + lpart.dur;
-
--- Maps a launch to the corresponding set of processes that handled the
--- activity start. The vast majority of cases should be a single process.
--- However it is possible that the process dies during the activity launch
--- and is respawned.
-CREATE TABLE launch_processes(launch_id INT, upid BIG INT);
-
--- We make the (not always correct) simplification that process == package
-INSERT INTO launch_processes
-SELECT launches.id, process.upid
-FROM launches
-  JOIN process ON launches.package = process.name
-  JOIN thread ON (process.upid = thread.upid AND process.pid = thread.tid)
-WHERE (process.start_ts IS NULL OR process.start_ts < launches.ts_end)
-AND (thread.end_ts IS NULL OR thread.end_ts > launches.ts_end)
-ORDER BY process.start_ts DESC;
diff --git a/src/trace_processor/metrics/android/android_task_state.sql b/src/trace_processor/metrics/android/android_task_state.sql
deleted file mode 100644
index e296390..0000000
--- a/src/trace_processor/metrics/android/android_task_state.sql
+++ /dev/null
@@ -1,37 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
--- Spans for each thread not in a running state.
-CREATE TABLE unsched_state (ts BIG INT, dur BIG INT, utid BIG INT, state STRING);
-
-INSERT INTO unsched_state
-SELECT
-  ts_end AS ts,
-  LEAD(ts, 1, null) OVER(PARTITION BY utid ORDER BY ts) - ts_end AS dur,
-  utid,
-  CASE
-    WHEN INSTR(end_state, 'R') > 0 THEN 'runnable'
-    WHEN INSTR(end_state, 'D') > 0 THEN 'uninterruptible'
-    WHEN INSTR(end_state, 'S') > 0 THEN 'interruptible'
-  END AS state
-FROM sched;
-
--- Create a single view for the task states.
-CREATE VIEW task_state AS
-SELECT utid, state, ts, dur FROM unsched_state
-UNION
-SELECT utid, 'running', ts, dur FROM sched
-ORDER BY ts;
diff --git a/src/trace_processor/metrics/android/heap_profile_callsites.sql b/src/trace_processor/metrics/android/heap_profile_callsites.sql
deleted file mode 100644
index ce2aeb4..0000000
--- a/src/trace_processor/metrics/android/heap_profile_callsites.sql
+++ /dev/null
@@ -1,232 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
-CREATE VIEW memory_delta AS
-SELECT upid, SUM(size) AS delta
-FROM heap_profile_allocation
-GROUP BY 1;
-
-CREATE VIEW memory_total AS
-SELECT upid, SUM(size) AS total
-FROM heap_profile_allocation
-WHERE size > 0
-GROUP BY 1;
-
--- Join frames with symbols and mappings to get a textual representation.
-CREATE TABLE symbolized_frame AS
-SELECT
-  frame_id,
-  symbol_name,
-  mapping_name,
-  HASH(symbol_name, mapping_name) frame_hash,
-  HeapProfileCallsites_Frame(
-    'name', symbol_name,
-    'mapping_name', mapping_name
-  ) AS frame_proto
-FROM (
-  SELECT
-    spf.id AS frame_id,
-    IFNULL(
-      (SELECT name FROM stack_profile_symbol symbol
-        WHERE symbol.symbol_set_id = spf.symbol_set_id
-        LIMIT 1),
-      spf.name
-    ) AS symbol_name,
-    spm.name AS mapping_name
-  FROM stack_profile_frame spf
-  JOIN stack_profile_mapping spm
-  ON spf.mapping = spm.id
-);
-
--- Required to join with callsites
-CREATE UNIQUE INDEX symbolized_frame_idx ON symbolized_frame(frame_id);
-
--- View that joins callsites with frames. Allocation-agnostic, only used to
--- generated the hashed callsites.
-CREATE TABLE callsites AS
-SELECT cs.id, cs.parent_id, cs.depth, sf.frame_hash
-FROM stack_profile_callsite cs
-JOIN symbolized_frame sf USING(frame_id);
-
-DROP INDEX symbolized_frame_idx;
-
--- heapprofd-based callsite ids are based on frame addresses, whereas we want
--- to group by symbol names.
--- Create a unique ID for each subtree by traversing from the root.
--- 1 self_hash can correspond to N callsite_ids (which can then be used to join
--- with allocs).
-CREATE TABLE hashed_callsites AS
-WITH RECURSIVE callsite_hasher(id, self_hash, parent_hash, frame_hash) AS (
-  SELECT
-    cs.id,
-    cs.frame_hash,
-    -1,
-    cs.frame_hash
-  FROM callsites cs
-  WHERE cs.depth = 0
-  UNION ALL
-  SELECT
-    child.id,
-    HASH(child.frame_hash, parent.self_hash),
-    parent.self_hash,
-    child.frame_hash
-  FROM callsite_hasher parent
-  JOIN callsites child
-  ON parent.id = child.parent_id
-)
-SELECT
-  self_hash,
-  parent_hash,
-  frame_hash,
-  id callsite_id
-FROM callsite_hasher;
-
-DROP TABLE callsites;
-
-CREATE VIEW hashed_callsite_tree AS
-SELECT DISTINCT self_hash, parent_hash, frame_hash
-FROM hashed_callsites;
-
--- Required to join with allocs
-CREATE INDEX hashed_callsites_id_idx ON hashed_callsites(callsite_id);
-
--- Computes the allocations for each hash-based callsite.
-CREATE TABLE self_allocs AS
-SELECT
-  hc.self_hash,
-  alloc.upid,
-  SUM(alloc.count) AS delta_count,
-  SUM(CASE WHEN alloc.count > 0 THEN alloc.count ELSE 0 END) AS total_count,
-  SUM(alloc.size) AS delta_bytes,
-  SUM(CASE WHEN alloc.size > 0 THEN alloc.size ELSE 0 END) AS total_bytes
-FROM hashed_callsites hc
-JOIN heap_profile_allocation alloc USING (callsite_id)
-GROUP BY 1, 2;
-
-DROP INDEX hashed_callsites_id_idx;
-
--- For each allocation (each self_alloc), emit a row for each ancestor and
--- aggregate them by self_hash.
-CREATE TABLE child_allocs AS
-WITH RECURSIVE parent_traversal(
-  self_hash, parent_hash, upid,
-  delta_count, total_count, delta_bytes, total_bytes) AS (
-  SELECT
-    sa.self_hash,
-    hc.parent_hash,
-    sa.upid,
-    sa.delta_count,
-    sa.total_count,
-    sa.delta_bytes,
-    sa.total_bytes
-  FROM self_allocs sa
-  JOIN hashed_callsite_tree hc ON sa.self_hash = hc.self_hash
-  UNION ALL
-  SELECT
-    parent.self_hash,
-    parent.parent_hash,
-    child.upid,
-    child.delta_count,
-    child.total_count,
-    child.delta_bytes,
-    child.total_bytes
-  FROM parent_traversal child
-  JOIN hashed_callsite_tree parent
-  ON child.parent_hash = parent.self_hash
-)
-SELECT
-  self_hash,
-  upid,
-  SUM(delta_count) AS delta_count,
-  SUM(total_count) AS total_count,
-  SUM(delta_bytes) AS delta_bytes,
-  SUM(total_bytes) AS total_bytes
-FROM parent_traversal
-GROUP BY 1, 2;
-
-CREATE VIEW self_allocs_proto AS
-SELECT
-  self_hash,
-  upid,
-  HeapProfileCallsites_Counters(
-    'delta_count', delta_count, 'total_count', total_count,
-    'delta_bytes', delta_bytes, 'total_bytes', total_bytes
-  ) AS allocs_proto
-FROM self_allocs;
-
-CREATE VIEW child_allocs_proto AS
-SELECT
-  self_hash,
-  upid,
-  HeapProfileCallsites_Counters(
-    'delta_count', delta_count, 'total_count', total_count,
-    'delta_bytes', delta_bytes, 'total_bytes', total_bytes
-  ) AS allocs_proto
-FROM child_allocs;
-
--- Required to map back to the symbol.
-CREATE INDEX symbolized_frame_hash_idx ON symbolized_frame(frame_hash);
-
-CREATE TABLE process_callsite AS
-SELECT
-  ca.upid,
-  ca.self_hash,
-  tree.parent_hash,
-  frame.frame_proto,
-  sa.allocs_proto AS self_allocs_proto,
-  ca.allocs_proto AS child_allocs_proto
-FROM hashed_callsite_tree tree
-JOIN (SELECT DISTINCT frame_hash, frame_proto FROM symbolized_frame) frame
-  USING (frame_hash)
-JOIN child_allocs_proto ca
-  USING (self_hash)
-LEFT JOIN self_allocs_proto sa
-  USING (self_hash, upid)
-ORDER BY 1, 2;
-
-DROP INDEX symbolized_frame_hash_idx;
-
-CREATE VIEW process_callsite_proto AS
-SELECT
-  upid,
-  RepeatedField(HeapProfileCallsites_Callsite(
-    'hash', self_hash,
-    'parent_hash', parent_hash,
-    'frame', frame_proto,
-    'self_allocs', self_allocs_proto,
-    'child_allocs', child_allocs_proto
-  )) AS repeated_callsite_proto
-FROM process_callsite
-GROUP BY 1;
-
-CREATE VIEW instance_stats_view AS
-SELECT HeapProfileCallsites_InstanceStats(
-    'pid', process.pid,
-    'process_name', process.name,
-    'callsites', repeated_callsite_proto,
-    'profile_delta_bytes', memory_delta.delta,
-    'profile_total_bytes', memory_total.total
-) AS instance_stats_proto
-FROM process_callsite_proto
-JOIN memory_total USING (upid)
-JOIN memory_delta USING (upid)
-JOIN process USING (upid);
-
-CREATE VIEW heap_profile_callsites_output AS
-SELECT HeapProfileCallsites(
-  'instance_stats',
-  (SELECT RepeatedField(instance_stats_proto) FROM instance_stats_view)
-);
diff --git a/src/trace_processor/metrics/android/java_heap_stats.sql b/src/trace_processor/metrics/android/java_heap_stats.sql
deleted file mode 100644
index d8f2f34..0000000
--- a/src/trace_processor/metrics/android/java_heap_stats.sql
+++ /dev/null
@@ -1,58 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
-CREATE VIEW total_size_samples AS
-SELECT upid, graph_sample_ts, SUM(self_size) AS total_size
-FROM heap_graph_object
-GROUP BY 1, 2;
-
-CREATE VIEW total_reachable_size_samples AS
-SELECT upid, graph_sample_ts, SUM(self_size) AS total_reachable_size
-FROM heap_graph_object
-WHERE reachable = TRUE
-GROUP BY 1, 2;
-
-CREATE TABLE heap_graph_samples AS
-SELECT upid, graph_sample_ts, total_size, total_reachable_size
-FROM total_size_samples JOIN total_reachable_size_samples
-USING (upid, graph_sample_ts);
-
-CREATE VIEW heap_graph_sample_protos AS
-SELECT
-  upid,
-  JavaHeapStats_Sample(
-    'ts', graph_sample_ts,
-    'heap_size', total_size,
-    'reachable_heap_size', total_reachable_size
-  ) sample_proto
-FROM heap_graph_samples;
-
-CREATE TABLE heap_graph_instance_stats AS
-SELECT
-  upid,
-  process.name process_name,
-  RepeatedField(sample_proto) AS sample_protos
-FROM heap_graph_sample_protos JOIN process USING (upid)
-GROUP BY 1, 2;
-
-CREATE VIEW java_heap_stats_output AS
-SELECT JavaHeapStats(
-  'instance_stats', RepeatedField(JavaHeapStats_InstanceStats(
-    'upid', upid,
-    'process_name', process_name,
-    'samples', sample_protos
-  )))
-FROM heap_graph_instance_stats;
diff --git a/src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql b/src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql
deleted file mode 100644
index f7ef71b..0000000
--- a/src/trace_processor/metrics/android/mem_stats_priority_breakdown.sql
+++ /dev/null
@@ -1,66 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
-DROP TABLE IF EXISTS {{table_name}}_by_priority_stats;
-
-CREATE TABLE {{table_name}}_by_priority_stats (
-  process_name TEXT,
-  priority TEXT,
-  min_value REAL,
-  max_value REAL,
-  avg_value REAL,
-  PRIMARY KEY (process_name, priority)
-);
-
-INSERT INTO {{table_name}}_by_priority_stats
-SELECT
-  process.name AS process_name,
-  CASE
-    WHEN oom_score_val < -900 THEN 'native'
-    WHEN oom_score_val < -800 THEN 'system'
-    WHEN oom_score_val < -700 THEN 'persistent'
-    WHEN oom_score_val <  0   THEN 'persistent_service'
-    WHEN oom_score_val <  100 THEN 'foreground'
-    WHEN oom_score_val <  200 THEN 'visible'
-    WHEN oom_score_val <  300 THEN 'perceptible'
-    WHEN oom_score_val <  400 THEN 'backup'
-    WHEN oom_score_val <  500 THEN 'heavy_weight'
-    WHEN oom_score_val <  600 THEN 'service_a'
-    WHEN oom_score_val <  700 THEN 'home'
-    WHEN oom_score_val <  800 THEN 'prev'
-    WHEN oom_score_val <  900 THEN 'service_b'
-    ELSE 'cached'
-  END AS priority,
-  MIN(span.{{table_name}}_val) AS min_value,
-  MAX(span.{{table_name}}_val) AS max_value,
-  SUM(span.{{table_name}}_val * span.dur) / SUM(span.dur) AS avg_value
-FROM {{table_name}}_by_oom_span AS span JOIN process USING(upid)
-WHERE process.name IS NOT NULL
-GROUP BY 1, 2
-ORDER BY 1, 2;
-
-DROP VIEW IF EXISTS {{table_name}}_by_priority_stats_proto;
-
-CREATE VIEW {{table_name}}_by_priority_stats_proto AS
-SELECT
-  process_name,
-  priority,
-  AndroidMemoryMetric_Counter(
-    'min', min_value,
-    'max', max_value,
-    'avg', avg_value
-  ) AS proto
-FROM {{table_name}}_by_priority_stats;
diff --git a/src/trace_processor/metrics/android/process_mem.sql b/src/trace_processor/metrics/android/process_mem.sql
deleted file mode 100644
index 131e942..0000000
--- a/src/trace_processor/metrics/android/process_mem.sql
+++ /dev/null
@@ -1,94 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
--- Create all the views used to generate the Android Memory metrics proto.
--- Anon RSS
-SELECT RUN_METRIC('android/upid_span_view.sql',
-  'table_name', 'anon_rss',
-  'counter_name', 'mem.rss.anon');
-
--- File RSS
-SELECT RUN_METRIC('android/upid_span_view.sql',
-  'table_name', 'file_rss',
-  'counter_name', 'mem.rss.file');
-
--- Swap
-SELECT RUN_METRIC('android/upid_span_view.sql',
-  'table_name', 'swap',
-  'counter_name', 'mem.swap');
-
--- Anon RSS + Swap
-DROP TABLE IF EXISTS anon_and_swap_join;
-
-CREATE VIRTUAL TABLE anon_and_swap_join
-USING SPAN_OUTER_JOIN(anon_rss_span PARTITIONED upid, swap_span PARTITIONED upid);
-
-DROP VIEW IF EXISTS anon_and_swap_span;
-
-CREATE VIEW anon_and_swap_span AS
-SELECT
-  ts, dur, upid,
-  IFNULL(anon_rss_val, 0) + IFNULL(swap_val, 0) AS anon_and_swap_val
-FROM anon_and_swap_join;
-
--- If we have dalvik events enabled (for ART trace points) we can construct the java heap timeline.
-SELECT RUN_METRIC('android/upid_span_view.sql',
-  'table_name', 'java_heap_kb',
-  'counter_name', 'Heap size (KB)');
-
-DROP VIEW IF EXISTS java_heap_span;
-
-CREATE VIEW java_heap_span AS
-SELECT ts, dur, upid, java_heap_kb_val * 1024 AS java_heap_val
-FROM java_heap_kb_span;
-
--- Create a track for process OOM scores.
-DROP VIEW IF EXISTS oom_score_span;
-
-CREATE VIEW oom_score_span AS
-SELECT
-  ts,
-  LEAD(ts, 1, (SELECT end_ts + 1 FROM trace_bounds))
-    OVER(PARTITION BY counter_id ORDER BY ts) - ts AS dur,
-  ref AS upid,
-  CAST(value AS INT) AS oom_score_val
-FROM counters
-WHERE name = 'oom_score_adj' AND ref IS NOT NULL;
-
-DROP TABLE IF EXISTS anon_rss_by_oom_span;
-
-CREATE VIRTUAL TABLE anon_rss_by_oom_span
-USING SPAN_JOIN(anon_rss_span PARTITIONED upid, oom_score_span PARTITIONED upid);
-
-DROP TABLE IF EXISTS file_rss_by_oom_span;
-
-CREATE VIRTUAL TABLE file_rss_by_oom_span
-USING SPAN_JOIN(file_rss_span PARTITIONED upid, oom_score_span PARTITIONED upid);
-
-DROP TABLE IF EXISTS swap_by_oom_span;
-
-CREATE VIRTUAL TABLE swap_by_oom_span
-USING SPAN_JOIN(swap_span PARTITIONED upid, oom_score_span PARTITIONED upid);
-
-DROP TABLE IF EXISTS anon_and_swap_by_oom_span;
-
-CREATE VIRTUAL TABLE anon_and_swap_by_oom_span
-USING SPAN_JOIN(anon_and_swap_span PARTITIONED upid, oom_score_span PARTITIONED upid);
-
-DROP TABLE IF EXISTS java_heap_by_oom_span;
-
-CREATE VIRTUAL TABLE java_heap_by_oom_span
-USING SPAN_JOIN(java_heap_span PARTITIONED upid, oom_score_span PARTITIONED upid);
diff --git a/src/trace_processor/metrics/android/process_unagg_mem_view.sql b/src/trace_processor/metrics/android/process_unagg_mem_view.sql
deleted file mode 100644
index d19c4e2..0000000
--- a/src/trace_processor/metrics/android/process_unagg_mem_view.sql
+++ /dev/null
@@ -1,30 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
-DROP TABLE IF EXISTS {{table_name}}_unagg_values;
-
-CREATE TABLE {{table_name}}_unagg_values AS
-SELECT
-  upid,
-  RepeatedField(
-    AndroidMemoryUnaggregatedMetric_Value(
-      'ts', ts,
-      'oom_score', oom_score_val,
-      'value', {{table_name}}_val
-    )
-  ) as metric
-FROM {{table_name}}_by_oom_span
-GROUP BY upid;
diff --git a/src/trace_processor/metrics/android/span_view_stats.sql b/src/trace_processor/metrics/android/span_view_stats.sql
deleted file mode 100644
index ff85408..0000000
--- a/src/trace_processor/metrics/android/span_view_stats.sql
+++ /dev/null
@@ -1,47 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
-DROP TABLE IF EXISTS {{table_name}}_stats;
-
-CREATE TABLE {{table_name}}_stats (
-  process_name TEXT PRIMARY KEY,
-  min_value REAL,
-  max_value REAL,
-  avg_value REAL
-);
-
-INSERT INTO {{table_name}}_stats
-SELECT
-  process.name AS process_name,
-  MIN(span.{{table_name}}_val) AS min_value,
-  MAX(span.{{table_name}}_val) AS max_value,
-  SUM(span.{{table_name}}_val * span.dur) / SUM(span.dur) AS avg_value
-FROM {{table_name}}_span AS span JOIN process USING(upid)
-WHERE process.name IS NOT NULL
-GROUP BY 1
-ORDER BY 1;
-
-DROP VIEW IF EXISTS {{table_name}}_stats_proto;
-
-CREATE VIEW {{table_name}}_stats_proto AS
-SELECT
-  process_name,
-  AndroidMemoryMetric_Counter(
-    'min', min_value,
-    'max', max_value,
-    'avg', avg_value
-  ) AS proto
-FROM {{table_name}}_stats;
diff --git a/src/trace_processor/metrics/android/unsymbolized_frames.sql b/src/trace_processor/metrics/android/unsymbolized_frames.sql
deleted file mode 100644
index 426beb7..0000000
--- a/src/trace_processor/metrics/android/unsymbolized_frames.sql
+++ /dev/null
@@ -1,33 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
-CREATE VIEW unsymbolized_frames_view AS
-SELECT UnsymbolizedFrames_Frame(
-    'module', spm.name,
-    'build_id', spm.build_id,
-    'address', spf.rel_pc
-) AS frame_proto
-FROM stack_profile_frame spf
-JOIN stack_profile_mapping spm
-ON spf.mapping = spm.id
-WHERE spm.build_id != ''
-AND (spf.symbol_set_id == 0 OR spf.symbol_set_id IS NULL);
-
-CREATE VIEW unsymbolized_frames_output AS
-SELECT UnsymbolizedFrames(
-  'frames',
-  (SELECT RepeatedField(frame_proto) FROM unsymbolized_frames_view)
-);
diff --git a/src/trace_processor/metrics/android/upid_span_view.sql b/src/trace_processor/metrics/android/upid_span_view.sql
deleted file mode 100644
index 748bc4d..0000000
--- a/src/trace_processor/metrics/android/upid_span_view.sql
+++ /dev/null
@@ -1,32 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
-DROP VIEW IF EXISTS {{table_name}}_span;
-
-CREATE VIEW {{table_name}}_span AS
-SELECT
-  ts,
-  LEAD(ts, 1, (
-    SELECT IFNULL(
-      end_ts,
-      (SELECT end_ts FROM trace_bounds)
-    )
-    FROM process WHERE upid = ref) + 1
-  ) OVER(PARTITION BY counter_id ORDER BY ts) - ts AS dur,
-  ref AS upid,
-  value AS {{table_name}}_val
-FROM counters
-WHERE name = '{{counter_name}}' AND ref IS NOT NULL AND ref_type = 'upid';
diff --git a/src/trace_processor/metrics/descriptors.cc b/src/trace_processor/metrics/descriptors.cc
deleted file mode 100644
index 6e563e2..0000000
--- a/src/trace_processor/metrics/descriptors.cc
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/metrics/descriptors.h"
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/protozero/field.h"
-
-#include "protos/perfetto/common/descriptor.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace metrics {
-
-namespace {
-
-FieldDescriptor CreateFieldFromDecoder(
-    const protos::pbzero::FieldDescriptorProto::Decoder& f_decoder) {
-  using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
-  std::string type_name =
-      f_decoder.has_type_name()
-          ? base::StringView(f_decoder.type_name()).ToStdString()
-          : "";
-  // TODO(lalitm): add support for enums here.
-  uint32_t type =
-      f_decoder.has_type()
-          ? static_cast<uint32_t>(f_decoder.type())
-          : static_cast<uint32_t>(FieldDescriptorProto::TYPE_MESSAGE);
-  return FieldDescriptor(
-      base::StringView(f_decoder.name()).ToStdString(),
-      static_cast<uint32_t>(f_decoder.number()), type, std::move(type_name),
-      f_decoder.label() == FieldDescriptorProto::LABEL_REPEATED);
-}
-
-}  // namespace
-
-base::Optional<uint32_t> DescriptorPool::ResolveShortType(
-    const std::string& parent_path,
-    const std::string& short_type) {
-  PERFETTO_DCHECK(!short_type.empty());
-
-  std::string search_path = short_type[0] == '.'
-                                ? parent_path + short_type
-                                : parent_path + '.' + short_type;
-  auto opt_idx = FindDescriptorIdx(search_path);
-  if (opt_idx)
-    return opt_idx;
-
-  if (parent_path.empty())
-    return base::nullopt;
-
-  auto parent_dot_idx = parent_path.rfind('.');
-  auto parent_substr = parent_dot_idx == std::string::npos
-                           ? ""
-                           : parent_path.substr(0, parent_dot_idx);
-  return ResolveShortType(parent_substr, short_type);
-}
-
-util::Status DescriptorPool::AddExtensionField(
-    const std::string& package_name,
-    protozero::ConstBytes field_desc_proto) {
-  using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
-  FieldDescriptorProto::Decoder f_decoder(field_desc_proto);
-  auto field = CreateFieldFromDecoder(f_decoder);
-
-  auto extendee_name =
-      package_name + "." + base::StringView(f_decoder.extendee()).ToStdString();
-  auto extendee = FindDescriptorIdx(extendee_name);
-  if (!extendee.has_value()) {
-    return util::ErrStatus("Extendee does not exist %s", extendee_name.c_str());
-  }
-  descriptors_[extendee.value()].AddField(field);
-  return util::OkStatus();
-}
-
-void DescriptorPool::AddNestedProtoDescriptors(
-    const std::string& package_name,
-    base::Optional<uint32_t> parent_idx,
-    protozero::ConstBytes descriptor_proto) {
-  protos::pbzero::DescriptorProto::Decoder decoder(descriptor_proto);
-
-  auto parent_name =
-      parent_idx ? descriptors_[*parent_idx].full_name() : package_name;
-  auto full_name =
-      parent_name + "." + base::StringView(decoder.name()).ToStdString();
-
-  using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
-  ProtoDescriptor proto_descriptor(package_name, full_name, parent_idx);
-  for (auto it = decoder.field(); it; ++it) {
-    FieldDescriptorProto::Decoder f_decoder(*it);
-    proto_descriptor.AddField(CreateFieldFromDecoder(f_decoder));
-  }
-  descriptors_.emplace_back(std::move(proto_descriptor));
-
-  auto idx = static_cast<uint32_t>(descriptors_.size()) - 1;
-  for (auto it = decoder.nested_type(); it; ++it) {
-    AddNestedProtoDescriptors(package_name, idx, *it);
-  }
-}
-
-util::Status DescriptorPool::AddFromFileDescriptorSet(
-    const uint8_t* file_descriptor_set_proto,
-    size_t size) {
-  // First pass: extract all the message descriptors from the file and add them
-  // to the pool.
-  protos::pbzero::FileDescriptorSet::Decoder proto(file_descriptor_set_proto,
-                                                   size);
-  for (auto it = proto.file(); it; ++it) {
-    protos::pbzero::FileDescriptorProto::Decoder file(*it);
-    std::string package = "." + base::StringView(file.package()).ToStdString();
-    for (auto message_it = file.message_type(); message_it; ++message_it) {
-      AddNestedProtoDescriptors(package, base::nullopt, *message_it);
-    }
-  }
-
-  // Second pass: extract all the extension protos and add them to the real
-  // protos.
-  for (auto it = proto.file(); it; ++it) {
-    protos::pbzero::FileDescriptorProto::Decoder file(*it);
-
-    std::string package = "." + base::StringView(file.package()).ToStdString();
-    for (auto ext_it = file.extension(); ext_it; ++ext_it) {
-      auto status = AddExtensionField(package, *ext_it);
-      if (!status.ok())
-        return status;
-    }
-
-    // TODO(lalitm): we don't currently support nested extensions as they are
-    // relatively niche and probably shouldn't be used in metrics because they
-    // are confusing. Add the code for it here if we find a use for them in
-    // the future.
-  }
-
-  // Third pass: resolve the types of all the fields to the correct indiices.
-  using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
-  for (auto& descriptor : descriptors_) {
-    for (auto& field : *descriptor.mutable_fields()) {
-      if (!field.resolved_type_name().empty())
-        continue;
-
-      if (field.type() == FieldDescriptorProto::TYPE_MESSAGE ||
-          field.type() == FieldDescriptorProto::TYPE_ENUM) {
-        auto opt_desc =
-            ResolveShortType(descriptor.full_name(), field.raw_type_name());
-        if (!opt_desc.has_value()) {
-          return util::ErrStatus(
-              "Unable to find short type %s in field inside message %s",
-              field.raw_type_name().c_str(), descriptor.full_name().c_str());
-        }
-        field.set_resolved_type_name(
-            descriptors_[opt_desc.value()].full_name());
-      }
-    }
-  }
-  return util::OkStatus();
-}
-
-base::Optional<uint32_t> DescriptorPool::FindDescriptorIdx(
-    const std::string& full_name) const {
-  auto it = std::find_if(descriptors_.begin(), descriptors_.end(),
-                         [full_name](const ProtoDescriptor& desc) {
-                           return desc.full_name() == full_name;
-                         });
-  auto idx = static_cast<uint32_t>(std::distance(descriptors_.begin(), it));
-  return idx < descriptors_.size() ? base::Optional<uint32_t>(idx)
-                                   : base::nullopt;
-}
-
-ProtoDescriptor::ProtoDescriptor(std::string package_name,
-                                 std::string full_name,
-                                 base::Optional<uint32_t> parent_id)
-    : package_name_(std::move(package_name)),
-      full_name_(std::move(full_name)),
-      parent_id_(parent_id) {}
-
-FieldDescriptor::FieldDescriptor(std::string name,
-                                 uint32_t number,
-                                 uint32_t type,
-                                 std::string raw_type_name,
-                                 bool is_repeated)
-    : name_(std::move(name)),
-      number_(number),
-      type_(type),
-      raw_type_name_(std::move(raw_type_name)),
-      is_repeated_(is_repeated) {}
-
-}  // namespace metrics
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/metrics/descriptors.h b/src/trace_processor/metrics/descriptors.h
deleted file mode 100644
index e8151bf..0000000
--- a/src/trace_processor/metrics/descriptors.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_METRICS_DESCRIPTORS_H_
-#define SRC_TRACE_PROCESSOR_METRICS_DESCRIPTORS_H_
-
-#include <algorithm>
-#include <string>
-#include <vector>
-
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/trace_processor/basic_types.h"
-#include "perfetto/trace_processor/status.h"
-
-namespace protozero {
-struct ConstBytes;
-}
-
-namespace perfetto {
-namespace trace_processor {
-namespace metrics {
-
-class FieldDescriptor {
- public:
-  FieldDescriptor(std::string name,
-                  uint32_t number,
-                  uint32_t type,
-                  std::string raw_type_name,
-                  bool is_repeated);
-
-  const std::string& name() const { return name_; }
-  uint32_t number() const { return number_; }
-  uint32_t type() const { return type_; }
-  const std::string& raw_type_name() const { return raw_type_name_; }
-  const std::string& resolved_type_name() const { return resolved_type_name_; }
-  bool is_repeated() const { return is_repeated_; }
-
-  void set_resolved_type_name(const std::string& resolved_type_name) {
-    resolved_type_name_ = resolved_type_name;
-  }
-
- private:
-  std::string name_;
-  uint32_t number_;
-  uint32_t type_;
-  std::string raw_type_name_;
-  std::string resolved_type_name_;
-  bool is_repeated_;
-};
-
-class ProtoDescriptor {
- public:
-  ProtoDescriptor(std::string package_name,
-                  std::string full_name,
-                  base::Optional<uint32_t> parent_id);
-
-  void AddField(FieldDescriptor descriptor) {
-    fields_.emplace_back(std::move(descriptor));
-  }
-
-  base::Optional<uint32_t> FindFieldIdx(const std::string& name) const {
-    auto it = std::find_if(
-        fields_.begin(), fields_.end(),
-        [name](const FieldDescriptor& desc) { return desc.name() == name; });
-    auto idx = static_cast<uint32_t>(std::distance(fields_.begin(), it));
-    return idx < fields_.size() ? base::Optional<uint32_t>(idx) : base::nullopt;
-  }
-
-  const std::string& package_name() const { return package_name_; }
-
-  const std::string& full_name() const { return full_name_; }
-
-  const std::vector<FieldDescriptor>& fields() const { return fields_; }
-  std::vector<FieldDescriptor>* mutable_fields() { return &fields_; }
-
- private:
-  std::string package_name_;
-  std::string full_name_;
-  base::Optional<uint32_t> parent_id_;
-  std::vector<FieldDescriptor> fields_;
-};
-
-class DescriptorPool {
- public:
-  util::Status AddFromFileDescriptorSet(
-      const uint8_t* file_descriptor_set_proto,
-      size_t size);
-
-  base::Optional<uint32_t> FindDescriptorIdx(
-      const std::string& full_name) const;
-
-  const std::vector<ProtoDescriptor>& descriptors() const {
-    return descriptors_;
-  }
-
- private:
-  void AddNestedProtoDescriptors(const std::string& package_name,
-                                 base::Optional<uint32_t> parent_idx,
-                                 protozero::ConstBytes descriptor_proto);
-
-  util::Status AddExtensionField(const std::string& package_name,
-                                 protozero::ConstBytes field_desc_proto);
-
-  // Recursively searches for the given short type in all parent messages
-  // and packages.
-  base::Optional<uint32_t> ResolveShortType(const std::string& parent_path,
-                                            const std::string& short_type);
-
-  std::vector<ProtoDescriptor> descriptors_;
-};
-
-}  // namespace metrics
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_METRICS_DESCRIPTORS_H_
diff --git a/src/trace_processor/metrics/metrics.cc b/src/trace_processor/metrics/metrics.cc
index 048ef7f..48a6f19 100644
--- a/src/trace_processor/metrics/metrics.cc
+++ b/src/trace_processor/metrics/metrics.cc
@@ -16,632 +16,96 @@
 
 #include "src/trace_processor/metrics/metrics.h"
 
-#include <regex>
-#include <unordered_map>
-#include <vector>
-
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/string_utils.h"
+#include "perfetto/metrics/android/mem_metric.pbzero.h"
+#include "perfetto/metrics/metrics.pbzero.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
 #include "src/trace_processor/metrics/sql_metrics.h"
 
-#include "protos/perfetto/common/descriptor.pbzero.h"
-#include "protos/perfetto/trace_processor/metrics_impl.pbzero.h"
-
 namespace perfetto {
 namespace trace_processor {
 namespace metrics {
 
-namespace {
-
-// TODO(lalitm): delete this and use sqlite_utils when that is cleaned up of
-// trace processor dependencies.
-const char* ExtractSqliteValue(sqlite3_value* value) {
-  auto type = sqlite3_value_type(value);
-  PERFETTO_DCHECK(type == SQLITE_TEXT);
-  return reinterpret_cast<const char*>(sqlite3_value_text(value));
-}
-
-SqlValue SqlValueFromSqliteValue(sqlite3_value* value) {
-  SqlValue sql_value;
-  switch (sqlite3_value_type(value)) {
-    case SQLITE_INTEGER:
-      sql_value.type = SqlValue::Type::kLong;
-      sql_value.long_value = sqlite3_value_int64(value);
-      break;
-    case SQLITE_FLOAT:
-      sql_value.type = SqlValue::Type::kDouble;
-      sql_value.double_value = sqlite3_value_double(value);
-      break;
-    case SQLITE_TEXT:
-      sql_value.type = SqlValue::Type::kString;
-      sql_value.string_value =
-          reinterpret_cast<const char*>(sqlite3_value_text(value));
-      break;
-    case SQLITE_BLOB:
-      sql_value.type = SqlValue::Type::kBytes;
-      sql_value.bytes_value = sqlite3_value_blob(value);
-      sql_value.bytes_count = static_cast<size_t>(sqlite3_value_bytes(value));
-      break;
-  }
-  return sql_value;
-}
-
-}  // namespace
-
-ProtoBuilder::ProtoBuilder(const ProtoDescriptor* descriptor)
-    : descriptor_(descriptor) {}
-
-util::Status ProtoBuilder::AppendSqlValue(const std::string& field_name,
-                                          const SqlValue& value) {
-  switch (value.type) {
-    case SqlValue::kLong:
-      return AppendLong(field_name, value.long_value);
-    case SqlValue::kDouble:
-      return AppendDouble(field_name, value.double_value);
-    case SqlValue::kString:
-      return AppendString(field_name, value.string_value);
-    case SqlValue::kBytes:
-      return AppendBytes(field_name,
-                         static_cast<const uint8_t*>(value.bytes_value),
-                         value.bytes_count);
-    case SqlValue::kNull:
-      // If the value is null, it's treated as the field being absent so we
-      // don't append anything.
-      return util::OkStatus();
-  }
-  PERFETTO_FATAL("For GCC");
-}
-
-util::Status ProtoBuilder::AppendLong(const std::string& field_name,
-                                      int64_t value,
-                                      bool is_inside_repeated) {
-  auto field_idx = descriptor_->FindFieldIdx(field_name);
-  if (!field_idx.has_value()) {
-    return util::ErrStatus("Field with name %s not found in proto type %s",
-                           field_name.c_str(),
-                           descriptor_->full_name().c_str());
-  }
-
-  using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
-  const auto& field = descriptor_->fields()[field_idx.value()];
-  if (field.is_repeated() && !is_inside_repeated) {
-    return util::ErrStatus(
-        "Unexpected long value for repeated field %s in proto type %s",
-        field_name.c_str(), descriptor_->full_name().c_str());
-  }
-
-  switch (field.type()) {
-    case FieldDescriptorProto::TYPE_INT32:
-    case FieldDescriptorProto::TYPE_INT64:
-    case FieldDescriptorProto::TYPE_UINT32:
-    case FieldDescriptorProto::TYPE_BOOL:
-      message_->AppendVarInt(field.number(), value);
-      break;
-    case FieldDescriptorProto::TYPE_SINT32:
-    case FieldDescriptorProto::TYPE_SINT64:
-      message_->AppendSignedVarInt(field.number(), value);
-      break;
-    case FieldDescriptorProto::TYPE_FIXED32:
-    case FieldDescriptorProto::TYPE_SFIXED32:
-    case FieldDescriptorProto::TYPE_FIXED64:
-    case FieldDescriptorProto::TYPE_SFIXED64:
-      message_->AppendFixed(field.number(), value);
-      break;
-    default: {
-      return util::ErrStatus(
-          "Tried to write value of type long into field %s (in proto type %s) "
-          "which has type %d",
-          field.name().c_str(), descriptor_->full_name().c_str(), field.type());
-    }
-  }
-  return util::OkStatus();
-}
-
-util::Status ProtoBuilder::AppendDouble(const std::string& field_name,
-                                        double value,
-                                        bool is_inside_repeated) {
-  auto field_idx = descriptor_->FindFieldIdx(field_name);
-  if (!field_idx.has_value()) {
-    return util::ErrStatus("Field with name %s not found in proto type %s",
-                           field_name.c_str(),
-                           descriptor_->full_name().c_str());
-  }
-
-  using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
-  const auto& field = descriptor_->fields()[field_idx.value()];
-  if (field.is_repeated() && !is_inside_repeated) {
-    return util::ErrStatus(
-        "Unexpected double value for repeated field %s in proto type %s",
-        field_name.c_str(), descriptor_->full_name().c_str());
-  }
-
-  switch (field.type()) {
-    case FieldDescriptorProto::TYPE_FLOAT:
-    case FieldDescriptorProto::TYPE_DOUBLE: {
-      if (field.type() == FieldDescriptorProto::TYPE_FLOAT) {
-        message_->AppendFixed(field.number(), static_cast<float>(value));
-      } else {
-        message_->AppendFixed(field.number(), value);
-      }
-      break;
-    }
-    default: {
-      return util::ErrStatus(
-          "Tried to write value of type double into field %s (in proto type "
-          "%s) which has type %d",
-          field.name().c_str(), descriptor_->full_name().c_str(), field.type());
-    }
-  }
-  return util::OkStatus();
-}
-
-util::Status ProtoBuilder::AppendString(const std::string& field_name,
-                                        base::StringView data,
-                                        bool is_inside_repeated) {
-  auto field_idx = descriptor_->FindFieldIdx(field_name);
-  if (!field_idx.has_value()) {
-    return util::ErrStatus("Field with name %s not found in proto type %s",
-                           field_name.c_str(),
-                           descriptor_->full_name().c_str());
-  }
-
-  using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
-  const auto& field = descriptor_->fields()[field_idx.value()];
-  if (field.is_repeated() && !is_inside_repeated) {
-    return util::ErrStatus(
-        "Unexpected string value for repeated field %s in proto type %s",
-        field_name.c_str(), descriptor_->full_name().c_str());
-  }
-
-  switch (field.type()) {
-    case FieldDescriptorProto::TYPE_STRING: {
-      message_->AppendBytes(field.number(), data.data(), data.size());
-      break;
-    }
-    default: {
-      return util::ErrStatus(
-          "Tried to write value of type string into field %s (in proto type "
-          "%s) which has type %d",
-          field.name().c_str(), descriptor_->full_name().c_str(), field.type());
-    }
-  }
-  return util::OkStatus();
-}
-
-util::Status ProtoBuilder::AppendBytes(const std::string& field_name,
-                                       const uint8_t* ptr,
-                                       size_t size,
-                                       bool is_inside_repeated) {
-  auto field_idx = descriptor_->FindFieldIdx(field_name);
-  if (!field_idx.has_value()) {
-    return util::ErrStatus("Field with name %s not found in proto type %s",
-                           field_name.c_str(),
-                           descriptor_->full_name().c_str());
-  }
-
-  using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
-  const auto& field = descriptor_->fields()[field_idx.value()];
-  if (field.is_repeated() && !is_inside_repeated)
-    return AppendRepeated(field, ptr, size);
-
-  // If we're inside a repeated field and we get a 0 sized message, this must
-  // be a silent null which we ignore.
-  if (size == 0)
-    return util::OkStatus();
-
-  switch (field.type()) {
-    case FieldDescriptorProto::TYPE_MESSAGE:
-      return AppendSingleMessage(field, ptr, size);
-    default: {
-      return util::ErrStatus(
-          "Tried to write value of type bytes into field %s (in proto type %s) "
-          "which has type %d",
-          field.name().c_str(), descriptor_->full_name().c_str(), field.type());
-    }
-  }
-  PERFETTO_FATAL("For GCC");
-}
-
-util::Status ProtoBuilder::AppendSingleMessage(const FieldDescriptor& field,
-                                               const uint8_t* ptr,
-                                               size_t size) {
-  protos::pbzero::ProtoBuilderResult::Decoder decoder(ptr, size);
-  if (decoder.is_repeated()) {
-    return util::ErrStatus("Cannot handle nested repeated messages in field %s",
-                           field.name().c_str());
-  }
-
-  const auto& single_field = decoder.single();
-  protos::pbzero::SingleBuilderResult::Decoder single(single_field.data,
-                                                      single_field.size);
-
-  if (single.type() != field.type()) {
-    return util::ErrStatus("Field %s has wrong type (expected %u, was %u)",
-                           field.name().c_str(), field.type(), single.type());
-  }
-
-  auto actual_type_name = single.type_name().ToStdString();
-  if (actual_type_name != field.resolved_type_name()) {
-    return util::ErrStatus("Field %s has wrong type (expected %s, was %s)",
-                           field.name().c_str(), actual_type_name.c_str(),
-                           field.resolved_type_name().c_str());
-  }
-
-  if (!single.has_protobuf()) {
-    return util::ErrStatus("Field %s has no proto bytes", field.name().c_str());
-  }
-
-  // We disallow 0 size fields here as they should have been reported as null
-  // one layer down.
-  auto bytes = single.protobuf();
-  if (bytes.size == 0) {
-    return util::ErrStatus("Unexpected to see field %s with zero size",
-                           field.name().c_str());
-  }
-
-  message_->AppendBytes(field.number(), bytes.data, bytes.size);
-  return util::OkStatus();
-}
-
-util::Status ProtoBuilder::AppendRepeated(const FieldDescriptor& field,
-                                          const uint8_t* ptr,
-                                          size_t size) {
-  protos::pbzero::ProtoBuilderResult::Decoder decoder(ptr, size);
-  if (!decoder.is_repeated()) {
-    return util::ErrStatus(
-        "Unexpected message value for repeated field %s in proto type %s",
-        field.name().c_str(), descriptor_->full_name().c_str());
-  }
-
-  const auto& rep = decoder.repeated();
-  protos::pbzero::RepeatedBuilderResult::Decoder repeated(rep.data, rep.size);
-  for (auto it = repeated.value(); it; ++it) {
-    protos::pbzero::RepeatedBuilderResult::Value::Decoder value(*it);
-    util::Status status;
-    if (value.has_int_value()) {
-      status = AppendLong(field.name(), value.int_value(), true);
-    } else if (value.has_double_value()) {
-      status = AppendDouble(field.name(), value.double_value(), true);
-    } else if (value.has_string_value()) {
-      status = AppendString(field.name(),
-                            base::StringView(value.string_value()), true);
-    } else if (value.has_bytes_value()) {
-      const auto& bytes = value.bytes_value();
-      status = AppendBytes(field.name(), bytes.data, bytes.size, true);
-    } else {
-      status = util::ErrStatus("Unknown type in repeated field");
-    }
-
-    if (!status.ok())
-      return status;
-  }
-  return util::OkStatus();
-}
-
-std::vector<uint8_t> ProtoBuilder::SerializeToProtoBuilderResult() {
-  std::vector<uint8_t> serialized = SerializeRaw();
-  if (serialized.empty())
-    return serialized;
-
-  const auto& type_name = descriptor_->full_name();
-
-  protozero::HeapBuffered<protos::pbzero::ProtoBuilderResult> result;
-  result->set_is_repeated(false);
-
-  auto* single = result->set_single();
-  single->set_type(protos::pbzero::FieldDescriptorProto_Type_TYPE_MESSAGE);
-  single->set_type_name(type_name.c_str(), type_name.size());
-  single->set_protobuf(serialized.data(), serialized.size());
-  return result.SerializeAsArray();
-}
-
-std::vector<uint8_t> ProtoBuilder::SerializeRaw() {
-  return message_.SerializeAsArray();
-}
-
-RepeatedFieldBuilder::RepeatedFieldBuilder() {
-  repeated_ = message_->set_repeated();
-}
-
-util::Status RepeatedFieldBuilder::AddSqlValue(SqlValue value) {
-  switch (value.type) {
-    case SqlValue::kLong:
-      AddLong(value.long_value);
-      break;
-    case SqlValue::kDouble:
-      AddDouble(value.double_value);
-      break;
-    case SqlValue::kString:
-      AddString(value.string_value);
-      break;
-    case SqlValue::kBytes:
-      AddBytes(static_cast<const uint8_t*>(value.bytes_value),
-               value.bytes_count);
-      break;
-    case SqlValue::kNull:
-      AddBytes(nullptr, 0);
-      break;
-  }
-  return util::OkStatus();
-}
-
-void RepeatedFieldBuilder::AddLong(int64_t value) {
-  has_data_ = true;
-  repeated_->add_value()->set_int_value(value);
-}
-
-void RepeatedFieldBuilder::AddDouble(double value) {
-  has_data_ = true;
-  repeated_->add_value()->set_double_value(value);
-}
-
-void RepeatedFieldBuilder::AddString(base::StringView value) {
-  has_data_ = true;
-  repeated_->add_value()->set_string_value(value.data(), value.size());
-}
-
-void RepeatedFieldBuilder::AddBytes(const uint8_t* data, size_t size) {
-  has_data_ = true;
-  repeated_->add_value()->set_bytes_value(data, size);
-}
-
-std::vector<uint8_t> RepeatedFieldBuilder::SerializeToProtoBuilderResult() {
-  repeated_ = nullptr;
-  if (!has_data_)
-    return std::vector<uint8_t>();
-
-  message_->set_is_repeated(true);
-  return message_.SerializeAsArray();
-}
-
-int TemplateReplace(
-    const std::string& raw_text,
-    const std::unordered_map<std::string, std::string>& substitutions,
-    std::string* out) {
-  std::regex re(R"(\{\{\s*(\w*)\s*\}\})", std::regex_constants::ECMAScript);
-
-  auto it = std::sregex_iterator(raw_text.begin(), raw_text.end(), re);
-  auto regex_end = std::sregex_iterator();
-  auto start = raw_text.begin();
-  for (; it != regex_end; ++it) {
-    out->insert(out->end(), start, raw_text.begin() + it->position(0));
-
-    auto value_it = substitutions.find(it->str(1));
-    if (value_it == substitutions.end())
-      return 1;
-
-    const auto& value = value_it->second;
-    std::copy(value.begin(), value.end(), std::back_inserter(*out));
-    start = raw_text.begin() + it->position(0) + it->length(0);
-  }
-  out->insert(out->end(), start, raw_text.end());
-  return 0;
-}
-
-void RepeatedFieldStep(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
-  if (argc != 1) {
-    sqlite3_result_error(ctx, "RepeatedField: only expected one arg", -1);
-    return;
-  }
-
-  // We use a double indirection here so we can use new and delete without
-  // needing to do dangerous dances with placement new and checking
-  // initalization.
-  auto** builder_ptr_ptr = static_cast<RepeatedFieldBuilder**>(
-      sqlite3_aggregate_context(ctx, sizeof(RepeatedFieldBuilder*)));
-
-  // The memory returned from sqlite3_aggregate_context is zeroed on its first
-  // invocation so *builder_ptr_ptr will be nullptr on the first invocation of
-  // RepeatedFieldStep.
-  bool needs_init = *builder_ptr_ptr == nullptr;
-  if (needs_init) {
-    *builder_ptr_ptr = new RepeatedFieldBuilder();
-  }
-
-  auto value = SqlValueFromSqliteValue(argv[0]);
-  RepeatedFieldBuilder* builder = *builder_ptr_ptr;
-  auto status = builder->AddSqlValue(value);
-  if (!status.ok()) {
-    sqlite3_result_error(ctx, status.c_message(), -1);
-  }
-}
-
-void RepeatedFieldFinal(sqlite3_context* ctx) {
-  // Note: we choose the size intentionally to be zero because we don't want to
-  // allocate if the Step has never been called.
-  auto** builder_ptr_ptr =
-      static_cast<RepeatedFieldBuilder**>(sqlite3_aggregate_context(ctx, 0));
-
-  // If Step has never been called, |builder_ptr_ptr| will be null.
-  if (builder_ptr_ptr == nullptr) {
-    sqlite3_result_null(ctx);
-    return;
-  }
-
-  // Capture the context pointer so that it will be freed at the end of this
-  // function.
-  std::unique_ptr<RepeatedFieldBuilder> builder(*builder_ptr_ptr);
-  std::vector<uint8_t> raw = builder->SerializeToProtoBuilderResult();
-  if (raw.empty()) {
-    sqlite3_result_null(ctx);
-    return;
-  }
-
-  std::unique_ptr<uint8_t[], base::FreeDeleter> data(
-      static_cast<uint8_t*>(malloc(raw.size())));
-  memcpy(data.get(), raw.data(), raw.size());
-  sqlite3_result_blob(ctx, data.release(), static_cast<int>(raw.size()), free);
-}
-
-// SQLite function implementation used to build a proto directly in SQL. The
-// proto to be built is given by the descriptor which is given as a context
-// parameter to this function and chosen when this function is first registed
-// with SQLite. The args of this function are key value pairs specifying the
-// name of the field and its value. Nested messages are expected to be passed
-// as byte blobs (as they were built recursively using this function).
-// The return value is the built proto or an error about why the proto could
-// not be built.
-void BuildProto(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
-  const auto* fn_ctx =
-      static_cast<const BuildProtoContext*>(sqlite3_user_data(ctx));
-  if (argc % 2 != 0) {
-    util::Status error =
-        util::ErrStatus("Invalid number of args to %s BuildProto (got %d)",
-                        fn_ctx->desc->full_name().c_str(), argc);
-    sqlite3_result_error(ctx, error.c_message(), -1);
-    return;
-  }
-
-  ProtoBuilder builder(fn_ctx->desc);
-  for (int i = 0; i < argc; i += 2) {
-    if (sqlite3_value_type(argv[i]) != SQLITE_TEXT) {
-      sqlite3_result_error(ctx, "BuildProto: Invalid args", -1);
-      return;
-    }
-
-    auto* key = reinterpret_cast<const char*>(sqlite3_value_text(argv[i]));
-    auto value = SqlValueFromSqliteValue(argv[i + 1]);
-    auto status = builder.AppendSqlValue(key, value);
-    if (!status.ok()) {
-      sqlite3_result_error(ctx, status.c_message(), -1);
-      return;
-    }
-  }
-
-  std::vector<uint8_t> raw = builder.SerializeToProtoBuilderResult();
-  if (raw.empty()) {
-    sqlite3_result_null(ctx);
-    return;
-  }
-
-  std::unique_ptr<uint8_t[], base::FreeDeleter> data(
-      static_cast<uint8_t*>(malloc(raw.size())));
-  memcpy(data.get(), raw.data(), raw.size());
-  sqlite3_result_blob(ctx, data.release(), static_cast<int>(raw.size()), free);
-}
-
 void RunMetric(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
-  auto* fn_ctx = static_cast<RunMetricContext*>(sqlite3_user_data(ctx));
+  auto* tp = static_cast<TraceProcessor*>(sqlite3_user_data(ctx));
   if (argc == 0 || sqlite3_value_type(argv[0]) != SQLITE_TEXT) {
-    sqlite3_result_error(ctx, "RUN_METRIC: Invalid arguments", -1);
+    sqlite3_result_error(ctx, "Invalid call to RUN_METRIC", -1);
     return;
   }
 
-  const char* path = reinterpret_cast<const char*>(sqlite3_value_text(argv[0]));
-  auto metric_it = std::find_if(
-      fn_ctx->metrics->begin(), fn_ctx->metrics->end(),
-      [path](const SqlMetricFile& metric) { return metric.path == path; });
-  if (metric_it == fn_ctx->metrics->end()) {
-    sqlite3_result_error(ctx, "RUN_METRIC: Unknown filename provided", -1);
+  const char* filename =
+      reinterpret_cast<const char*>(sqlite3_value_text(argv[0]));
+  const char* sql = sql_metrics::GetBundledMetric(filename);
+  if (!sql) {
+    sqlite3_result_error(ctx, "Unknown filename provided to RUN_METRIC", -1);
     return;
   }
-  const auto& sql = metric_it->sql;
 
-  std::unordered_map<std::string, std::string> substitutions;
-  for (int i = 1; i < argc; i += 2) {
-    if (sqlite3_value_type(argv[i]) != SQLITE_TEXT) {
-      sqlite3_result_error(ctx, "RUN_METRIC: Invalid args", -1);
+  for (const auto& query : base::SplitString(sql, ";\n\n")) {
+    PERFETTO_DLOG("Executing query in RUN_METRIC: %s", query.c_str());
+
+    auto it = tp->ExecuteQuery(query);
+    if (auto opt_error = it.GetLastError()) {
+      sqlite3_result_error(ctx, "Error when running RUN_METRIC file", -1);
       return;
-    }
-
-    auto* key_str = ExtractSqliteValue(argv[i]);
-    auto* value_str = ExtractSqliteValue(argv[i + 1]);
-    substitutions[key_str] = value_str;
-  }
-
-  for (const auto& query : base::SplitString(sql, ";\n")) {
-    std::string buffer;
-    int ret = TemplateReplace(query, substitutions, &buffer);
-    if (ret) {
+    } else if (it.Next()) {
       sqlite3_result_error(
-          ctx, "RUN_METRIC: Error when performing substitution", -1);
-      return;
-    }
-
-    PERFETTO_DLOG("RUN_METRIC: Executing query: %s", buffer.c_str());
-    auto it = fn_ctx->tp->ExecuteQuery(buffer);
-    it.Next();
-
-    util::Status status = it.Status();
-    if (!status.ok()) {
-      char* error =
-          sqlite3_mprintf("RUN_METRIC: Error when running file %s: %s", path,
-                          status.c_message());
-      sqlite3_result_error(ctx, error, -1);
-      sqlite3_free(error);
+          ctx, "RUN_METRIC functions should not produce any output", -1);
       return;
     }
   }
 }
 
-util::Status ComputeMetrics(TraceProcessor* tp,
-                            const std::vector<std::string> metrics_to_compute,
-                            const std::vector<SqlMetricFile>& sql_metrics,
-                            const ProtoDescriptor& root_descriptor,
-                            std::vector<uint8_t>* metrics_proto) {
-  ProtoBuilder metric_builder(&root_descriptor);
-  for (const auto& name : metrics_to_compute) {
-    auto metric_it =
-        std::find_if(sql_metrics.begin(), sql_metrics.end(),
-                     [&name](const SqlMetricFile& metric) {
-                       return metric.proto_field_name.has_value() &&
-                              name == metric.proto_field_name.value();
-                     });
-    if (metric_it == sql_metrics.end())
-      return util::ErrStatus("Unknown metric %s", name.c_str());
-
-    const auto& sql_metric = *metric_it;
-    auto queries = base::SplitString(sql_metric.sql, ";\n");
-    for (const auto& query : queries) {
-      PERFETTO_DLOG("Executing query: %s", query.c_str());
-      auto prep_it = tp->ExecuteQuery(query);
-      prep_it.Next();
-
-      util::Status status = prep_it.Status();
-      if (!status.ok())
-        return status;
-    }
-
-    auto output_query =
-        "SELECT * FROM " + sql_metric.output_table_name.value() + ";";
-    PERFETTO_DLOG("Executing output query: %s", output_query.c_str());
-
-    auto it = tp->ExecuteQuery(output_query.c_str());
-    auto has_next = it.Next();
-    util::Status status = it.Status();
-    if (!status.ok()) {
-      return status;
-    } else if (!has_next) {
-      return util::ErrStatus("Output table %s should have at least one row",
-                             sql_metric.output_table_name.value().c_str());
-    } else if (it.ColumnCount() != 1) {
-      return util::ErrStatus("Output table %s should have exactly one column",
-                             sql_metric.output_table_name.value().c_str());
-    }
-
-    if (it.Get(0).type == SqlValue::kBytes) {
-      const auto& field_name = sql_metric.proto_field_name.value();
-      const auto& col = it.Get(0);
-      status = metric_builder.AppendSqlValue(field_name, col);
-      if (!status.ok())
-        return status;
-    } else if (it.Get(0).type != SqlValue::kNull) {
-      return util::ErrStatus("Output table %s column has invalid type",
-                             sql_metric.output_table_name.value().c_str());
-    }
-
-    has_next = it.Next();
-    if (has_next)
-      return util::ErrStatus("Output table %s should only have one row",
-                             sql_metric.output_table_name.value().c_str());
-
-    status = it.Status();
-    if (!status.ok())
-      return status;
+int ComputeMetrics(TraceProcessor* tp,
+                   const std::vector<std::string>& metric_names,
+                   std::vector<uint8_t>* metrics_proto) {
+  // TODO(lalitm): stop hardcoding android.mem metric and read the proto
+  // descriptor for this logic instead.
+  if (metric_names.size() != 1 || metric_names[0] != "android.mem") {
+    PERFETTO_ELOG("Only android.mem metric is currently supported");
+    return 1;
   }
-  *metrics_proto = metric_builder.SerializeRaw();
-  return util::OkStatus();
+
+  auto queries = base::SplitString(sql_metrics::kAndroidMem, ";\n\n");
+  for (const auto& query : queries) {
+    PERFETTO_DLOG("Executing query: %s", query.c_str());
+    auto prep_it = tp->ExecuteQuery(query);
+    auto prep_has_next = prep_it.Next();
+    if (auto opt_error = prep_it.GetLastError()) {
+      PERFETTO_ELOG("SQLite error: %s", opt_error->c_str());
+      return 1;
+    }
+    PERFETTO_DCHECK(!prep_has_next);
+  }
+
+  protozero::ScatteredHeapBuffer delegate;
+  protozero::ScatteredStreamWriter writer(&delegate);
+  delegate.set_writer(&writer);
+
+  protos::pbzero::TraceMetrics metrics;
+  metrics.Reset(&writer);
+
+  // TODO(lalitm): all the below is temporary hardcoded queries and proto
+  // filling to ensure that the code above works.
+  auto it = tp->ExecuteQuery("SELECT COUNT(*) from lmk_by_score;");
+  auto has_next = it.Next();
+  if (auto opt_error = it.GetLastError()) {
+    PERFETTO_ELOG("SQLite error: %s", opt_error->c_str());
+    return 1;
+  }
+  PERFETTO_CHECK(has_next);
+  PERFETTO_CHECK(it.Get(0).type == SqlValue::Type::kLong);
+
+  auto* memory = metrics.set_android_mem();
+  memory->set_system_metrics()->set_lmks()->set_total_count(
+      static_cast<int32_t>(it.Get(0).long_value));
+  metrics.Finalize();
+
+  *metrics_proto = delegate.StitchSlices();
+
+  has_next = it.Next();
+  PERFETTO_DCHECK(!has_next);
+  return 0;
 }
 
 }  // namespace metrics
diff --git a/src/trace_processor/metrics/metrics.descriptor.h b/src/trace_processor/metrics/metrics.descriptor.h
deleted file mode 100644
index df7696c..0000000
--- a/src/trace_processor/metrics/metrics.descriptor.h
+++ /dev/null
@@ -1,886 +0,0 @@
-
-#ifndef SRC_TRACE_PROCESSOR_METRICS_METRICS_DESCRIPTOR_H_
-#define SRC_TRACE_PROCESSOR_METRICS_METRICS_DESCRIPTOR_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <array>
-
-// This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
-
-// SHA1(tools/gen_binary_descriptors)
-// 192b582ae52bb07b3d3ba66a94bcfd3127a5f42f
-// SHA1(protos/perfetto/metrics/metrics.proto)
-// 4279eeace6a7d9647e484e65b8265ea211a02b6c
-
-// This is the proto Metrics encoded as a ProtoFileDescriptor to allow
-// for reflection without libprotobuf full/non-lite protos.
-
-namespace perfetto {
-
-constexpr std::array<uint8_t, 10312> kMetricsDescriptor{
-    {0x0a, 0x98, 0x03, 0x0a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
-     0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x2f, 0x62, 0x61, 0x74, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22,
-     0xcd, 0x02, 0x0a, 0x14, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x42,
-     0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x12, 0x60, 0x0a, 0x10, 0x62, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x5f,
-     0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03,
-     0x28, 0x0b, 0x32, 0x35, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x4d,
-     0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72,
-     0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0f, 0x62,
-     0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65,
-     0x72, 0x73, 0x1a, 0xd2, 0x01, 0x0a, 0x0f, 0x42, 0x61, 0x74, 0x74, 0x65,
-     0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x21,
-     0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f,
-     0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x69,
-     0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4e, 0x73, 0x12, 0x2c, 0x0a,
-     0x12, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
-     0x74, 0x65, 0x72, 0x5f, 0x75, 0x61, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28,
-     0x01, 0x52, 0x10, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x43, 0x6f, 0x75,
-     0x6e, 0x74, 0x65, 0x72, 0x55, 0x61, 0x68, 0x12, 0x29, 0x0a, 0x10, 0x63,
-     0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x5f, 0x70, 0x65, 0x72, 0x63,
-     0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0f, 0x63,
-     0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x50, 0x65, 0x72, 0x63, 0x65,
-     0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
-     0x74, 0x5f, 0x75, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09,
-     0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x55, 0x61, 0x12, 0x24, 0x0a,
-     0x0e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x76, 0x67,
-     0x5f, 0x75, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x63,
-     0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x41, 0x76, 0x67, 0x55, 0x61, 0x42,
-     0x02, 0x48, 0x03, 0x0a, 0x87, 0x05, 0x0a, 0x30, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
-     0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x2f, 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x22, 0xbd, 0x04, 0x0a, 0x10, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x4c,
-     0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x6e,
-     0x66, 0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70,
-     0x75, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63,
-     0x65, 0x73, 0x73, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
-     0x49, 0x6e, 0x66, 0x6f, 0x1a, 0xa9, 0x01, 0x0a, 0x10, 0x43, 0x70, 0x75,
-     0x46, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x61, 0x74,
-     0x61, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
-     0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x20, 0x0a, 0x0c, 0x6d, 0x69, 0x6e,
-     0x5f, 0x66, 0x72, 0x65, 0x71, 0x5f, 0x6b, 0x68, 0x7a, 0x18, 0x02, 0x20,
-     0x01, 0x28, 0x03, 0x52, 0x0a, 0x6d, 0x69, 0x6e, 0x46, 0x72, 0x65, 0x71,
-     0x4b, 0x68, 0x7a, 0x12, 0x20, 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x5f, 0x66,
-     0x72, 0x65, 0x71, 0x5f, 0x6b, 0x68, 0x7a, 0x18, 0x03, 0x20, 0x01, 0x28,
-     0x03, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x46, 0x72, 0x65, 0x71, 0x4b, 0x68,
-     0x7a, 0x12, 0x20, 0x0a, 0x0c, 0x61, 0x76, 0x67, 0x5f, 0x66, 0x72, 0x65,
-     0x71, 0x5f, 0x6b, 0x68, 0x7a, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52,
-     0x0a, 0x61, 0x76, 0x67, 0x46, 0x72, 0x65, 0x71, 0x4b, 0x68, 0x7a, 0x12,
-     0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
-     0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x75,
-     0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x73, 0x1a, 0x96, 0x01, 0x0a,
-     0x06, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e,
-     0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
-     0x61, 0x6d, 0x65, 0x12, 0x44, 0x0a, 0x03, 0x63, 0x70, 0x75, 0x18, 0x02,
-     0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74,
-     0x72, 0x69, 0x63, 0x2e, 0x43, 0x70, 0x75, 0x46, 0x72, 0x65, 0x71, 0x75,
-     0x65, 0x6e, 0x63, 0x79, 0x44, 0x61, 0x74, 0x61, 0x52, 0x03, 0x63, 0x70,
-     0x75, 0x12, 0x32, 0x0a, 0x15, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69,
-     0x7a, 0x65, 0x64, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x63, 0x79, 0x63, 0x6c,
-     0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x6e, 0x6f,
-     0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x43, 0x70, 0x75, 0x43,
-     0x79, 0x63, 0x6c, 0x65, 0x73, 0x1a, 0x95, 0x01, 0x0a, 0x07, 0x50, 0x72,
-     0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
-     0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
-     0x65, 0x12, 0x42, 0x0a, 0x07, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73,
-     0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d,
-     0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64,
-     0x52, 0x07, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x12, 0x32, 0x0a,
-     0x15, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f,
-     0x63, 0x70, 0x75, 0x5f, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x18, 0x03,
-     0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c,
-     0x69, 0x7a, 0x65, 0x64, 0x43, 0x70, 0x75, 0x43, 0x79, 0x63, 0x6c, 0x65,
-     0x73, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x93, 0x08, 0x0a, 0x30, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x65,
-     0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x22, 0xc9, 0x07, 0x0a, 0x13, 0x41, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74,
-     0x72, 0x69, 0x63, 0x12, 0x5c, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x63, 0x65,
-     0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x01,
-     0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
-     0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65,
-     0x73, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x0e, 0x70,
-     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x73, 0x1a, 0xfd, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
-     0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x21, 0x0a, 0x0c,
-     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
-     0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63,
-     0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x61, 0x0a, 0x0e, 0x74,
-     0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
-     0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d,
-     0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72,
-     0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x43,
-     0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0d, 0x74, 0x6f, 0x74,
-     0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x65,
-     0x0a, 0x12, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x62,
-     0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x03, 0x20, 0x03,
-     0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65,
-     0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74,
-     0x79, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x11,
-     0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x42, 0x72, 0x65, 0x61,
-     0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x1a, 0x87, 0x01, 0x0a, 0x11, 0x50, 0x72,
-     0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64,
-     0x6f, 0x77, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72,
-     0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70,
-     0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x56, 0x0a, 0x08, 0x63,
-     0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
-     0x0b, 0x32, 0x3a, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74,
-     0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d,
-     0x65, 0x6d, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
-     0x73, 0x52, 0x08, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x1a,
-     0x88, 0x03, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d,
-     0x65, 0x6d, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
-     0x73, 0x12, 0x47, 0x0a, 0x08, 0x61, 0x6e, 0x6f, 0x6e, 0x5f, 0x72, 0x73,
-     0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d,
-     0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43, 0x6f,
-     0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x07, 0x61, 0x6e, 0x6f, 0x6e, 0x52,
-     0x73, 0x73, 0x12, 0x47, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x72,
-     0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65,
-     0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43,
-     0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x65,
-     0x52, 0x73, 0x73, 0x12, 0x40, 0x0a, 0x04, 0x73, 0x77, 0x61, 0x70, 0x18,
-     0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
-     0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72,
-     0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43, 0x6f, 0x75, 0x6e,
-     0x74, 0x65, 0x72, 0x52, 0x04, 0x73, 0x77, 0x61, 0x70, 0x12, 0x50, 0x0a,
-     0x0d, 0x61, 0x6e, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x77,
-     0x61, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65,
-     0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43,
-     0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x0b, 0x61, 0x6e, 0x6f, 0x6e,
-     0x41, 0x6e, 0x64, 0x53, 0x77, 0x61, 0x70, 0x12, 0x49, 0x0a, 0x09, 0x6a,
-     0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x18, 0x05, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65,
-     0x74, 0x72, 0x69, 0x63, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
-     0x52, 0x08, 0x6a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x1a, 0x3f,
-     0x0a, 0x07, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x10, 0x0a,
-     0x03, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03,
-     0x6d, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x78, 0x18, 0x02,
-     0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x6d, 0x61, 0x78, 0x12, 0x10, 0x0a,
-     0x03, 0x61, 0x76, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03,
-     0x61, 0x76, 0x67, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xa4, 0x06, 0x0a, 0x36,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
-     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f,
-     0x75, 0x6e, 0x61, 0x67, 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22,
-     0xd4, 0x05, 0x0a, 0x1f, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d,
-     0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65,
-     0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12,
-     0x65, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x76,
-     0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
-     0x3e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67,
-     0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69,
-     0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x56, 0x61, 0x6c,
-     0x75, 0x65, 0x73, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
-     0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x1a, 0x97, 0x01, 0x0a, 0x0d, 0x50,
-     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73,
-     0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f,
-     0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
-     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12,
-     0x63, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
-     0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x44, 0x2e, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d,
-     0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61,
-     0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72,
-     0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x56,
-     0x61, 0x6c, 0x75, 0x65, 0x73, 0x52, 0x09, 0x6d, 0x65, 0x6d, 0x56, 0x61,
-     0x6c, 0x75, 0x65, 0x73, 0x1a, 0xe3, 0x02, 0x0a, 0x13, 0x50, 0x72, 0x6f,
-     0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x56, 0x61,
-     0x6c, 0x75, 0x65, 0x73, 0x12, 0x51, 0x0a, 0x08, 0x61, 0x6e, 0x6f, 0x6e,
-     0x5f, 0x72, 0x73, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36,
-     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72,
-     0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x61, 0x6e, 0x6f, 0x6e,
-     0x52, 0x73, 0x73, 0x12, 0x51, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x5f,
-     0x72, 0x73, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d,
-     0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65,
-     0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
-     0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x65, 0x52,
-     0x73, 0x73, 0x12, 0x4a, 0x0a, 0x04, 0x73, 0x77, 0x61, 0x70, 0x18, 0x03,
-     0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
-     0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64,
-     0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65,
-     0x52, 0x04, 0x73, 0x77, 0x61, 0x70, 0x12, 0x5a, 0x0a, 0x0d, 0x61, 0x6e,
-     0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x18,
-     0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
-     0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72,
-     0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65,
-     0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x56, 0x61, 0x6c, 0x75,
-     0x65, 0x52, 0x0b, 0x61, 0x6e, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x53, 0x77,
-     0x61, 0x70, 0x1a, 0x4a, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
-     0x0e, 0x0a, 0x02, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
-     0x02, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6f, 0x6f, 0x6d, 0x5f, 0x73,
-     0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08,
-     0x6f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05,
-     0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52,
-     0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x90,
-     0x04, 0x0a, 0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
-     0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70,
-     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x77, 0x74,
-     0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x22, 0xc2, 0x03, 0x0a, 0x14, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74,
-     0x68, 0x12, 0x60, 0x0a, 0x10, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
-     0x65, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x01, 0x20,
-     0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
-     0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61,
-     0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x0f,
-     0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x73, 0x1a, 0xc7, 0x02, 0x0a, 0x0f, 0x49, 0x6e, 0x73, 0x74,
-     0x61, 0x6e, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12,
-     0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
-     0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f,
-     0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
-     0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
-     0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x19, 0x61, 0x6e, 0x6f, 0x6e,
-     0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x73, 0x74,
-     0x61, 0x72, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20,
-     0x01, 0x28, 0x03, 0x52, 0x15, 0x61, 0x6e, 0x6f, 0x6e, 0x41, 0x6e, 0x64,
-     0x53, 0x77, 0x61, 0x70, 0x53, 0x74, 0x61, 0x72, 0x74, 0x56, 0x61, 0x6c,
-     0x75, 0x65, 0x12, 0x3a, 0x0a, 0x1a, 0x61, 0x6e, 0x6f, 0x6e, 0x5f, 0x61,
-     0x6e, 0x64, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x63, 0x68, 0x61, 0x6e,
-     0x67, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x16, 0x61, 0x6e, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x53,
-     0x77, 0x61, 0x70, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x79, 0x74,
-     0x65, 0x73, 0x12, 0x3b, 0x0a, 0x1a, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63,
-     0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x63, 0x68, 0x61, 0x6e,
-     0x67, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x17, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x4d, 0x65,
-     0x6d, 0x6f, 0x72, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x79,
-     0x74, 0x65, 0x73, 0x12, 0x4c, 0x0a, 0x23, 0x6d, 0x61, 0x6c, 0x6c, 0x6f,
-     0x63, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x74, 0x6f, 0x74,
-     0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64,
-     0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03,
-     0x52, 0x1f, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x4d, 0x65, 0x6d, 0x6f,
-     0x72, 0x79, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63,
-     0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x02, 0x48,
-     0x03, 0x0a, 0xaf, 0x02, 0x0a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
-     0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x2f, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22,
-     0xe5, 0x01, 0x0a, 0x10, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49,
-     0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x40, 0x0a, 0x06,
-     0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
-     0x32, 0x28, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x49, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
-     0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x52, 0x06, 0x62, 0x75, 0x66, 0x66,
-     0x65, 0x72, 0x1a, 0x8e, 0x01, 0x0a, 0x06, 0x42, 0x75, 0x66, 0x66, 0x65,
-     0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
-     0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a,
-     0x0e, 0x61, 0x76, 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79,
-     0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x61,
-     0x76, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12,
-     0x24, 0x0a, 0x0e, 0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f,
-     0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52,
-     0x0c, 0x6d, 0x69, 0x6e, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65,
-     0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x69, 0x7a,
-     0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
-     0x01, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79,
-     0x74, 0x65, 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x95, 0x02, 0x0a, 0x30,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
-     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d, 0x6b, 0x5f,
-     0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xcb, 0x01, 0x0a, 0x10, 0x41, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f,
-     0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
-     0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12,
-     0x4e, 0x0a, 0x0c, 0x62, 0x79, 0x5f, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63,
-     0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c,
-     0x6d, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x42, 0x79, 0x4f,
-     0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x52, 0x0a, 0x62, 0x79, 0x4f,
-     0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x0a, 0x42,
-     0x79, 0x4f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x22, 0x0a,
-     0x0d, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x61,
-     0x64, 0x6a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6f, 0x6f,
-     0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x41, 0x64, 0x6a, 0x12, 0x14, 0x0a,
-     0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05,
-     0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x02, 0x48, 0x03, 0x0a,
-     0xf4, 0x02, 0x0a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
-     0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x5f, 0x6d, 0x65, 0x74,
-     0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x22, 0xa5, 0x02, 0x0a, 0x11, 0x41, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73,
-     0x12, 0x4e, 0x0a, 0x0b, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x72, 0x61,
-     0x69, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50,
-     0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x50, 0x6f,
-     0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0a, 0x70, 0x6f,
-     0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x1a, 0x4e, 0x0a, 0x0a,
-     0x45, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x44, 0x61, 0x74, 0x61, 0x12, 0x21,
-     0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f,
-     0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x69,
-     0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4d, 0x73, 0x12, 0x1d, 0x0a,
-     0x0a, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x5f, 0x75, 0x77, 0x73, 0x18,
-     0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x65, 0x6e, 0x65, 0x72, 0x67,
-     0x79, 0x55, 0x77, 0x73, 0x1a, 0x70, 0x0a, 0x0a, 0x50, 0x6f, 0x77, 0x65,
-     0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
-     0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
-     0x6d, 0x65, 0x12, 0x4e, 0x0a, 0x0b, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79,
-     0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
-     0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x2e,
-     0x45, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0a,
-     0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x44, 0x61, 0x74, 0x61, 0x42, 0x02,
-     0x48, 0x03, 0x0a, 0xac, 0x0e, 0x0a, 0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d,
-     0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x2f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x6d,
-     0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
-     0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x22, 0xde, 0x0d, 0x0a, 0x14, 0x41, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d,
-     0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x47, 0x0a, 0x07, 0x73, 0x74, 0x61,
-     0x72, 0x74, 0x75, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d,
-     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69,
-     0x63, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x52, 0x07, 0x73,
-     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x1a, 0xe0, 0x01, 0x0a, 0x12, 0x54,
-     0x61, 0x73, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x72, 0x65, 0x61,
-     0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x75, 0x6e,
-     0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18,
-     0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x72, 0x75, 0x6e, 0x6e, 0x69,
-     0x6e, 0x67, 0x44, 0x75, 0x72, 0x4e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x72,
-     0x75, 0x6e, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x5f,
-     0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x72, 0x75,
-     0x6e, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x4e, 0x73, 0x12,
-     0x3f, 0x0a, 0x1c, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75,
-     0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x6c, 0x65, 0x65, 0x70,
-     0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
-     0x03, 0x52, 0x19, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75,
-     0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x53, 0x6c, 0x65, 0x65, 0x70, 0x44,
-     0x75, 0x72, 0x4e, 0x73, 0x12, 0x3b, 0x0a, 0x1a, 0x69, 0x6e, 0x74, 0x65,
-     0x72, 0x72, 0x75, 0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x6c,
-     0x65, 0x65, 0x70, 0x5f, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73, 0x18, 0x04,
-     0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x72,
-     0x75, 0x70, 0x74, 0x69, 0x62, 0x6c, 0x65, 0x53, 0x6c, 0x65, 0x65, 0x70,
-     0x44, 0x75, 0x72, 0x4e, 0x73, 0x1a, 0x1e, 0x0a, 0x05, 0x53, 0x6c, 0x69,
-     0x63, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x75, 0x72, 0x5f, 0x6e, 0x73,
-     0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x75, 0x72, 0x4e,
-     0x73, 0x1a, 0xbb, 0x08, 0x0a, 0x0c, 0x54, 0x6f, 0x46, 0x69, 0x72, 0x73,
-     0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x64, 0x75,
-     0x72, 0x5f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05,
-     0x64, 0x75, 0x72, 0x4e, 0x73, 0x12, 0x72, 0x0a, 0x19, 0x6d, 0x61, 0x69,
-     0x6e, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x62, 0x79, 0x5f,
-     0x74, 0x61, 0x73, 0x6b, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02,
-     0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75,
-     0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x54, 0x61, 0x73, 0x6b,
-     0x53, 0x74, 0x61, 0x74, 0x65, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f,
-     0x77, 0x6e, 0x52, 0x15, 0x6d, 0x61, 0x69, 0x6e, 0x54, 0x68, 0x72, 0x65,
-     0x61, 0x64, 0x42, 0x79, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, 0x61, 0x74,
-     0x65, 0x12, 0x41, 0x0a, 0x1d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x70,
-     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x73, 0x70, 0x61,
-     0x77, 0x6e, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03,
-     0x20, 0x01, 0x28, 0x0d, 0x52, 0x1a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x50,
-     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x53, 0x70, 0x61, 0x77,
-     0x6e, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x5f, 0x0a, 0x15,
-     0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74,
-     0x79, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x18, 0x04, 0x20,
-     0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70,
-     0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65,
-     0x52, 0x13, 0x74, 0x69, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69,
-     0x74, 0x79, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x12, 0x66, 0x0a,
-     0x19, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69,
-     0x74, 0x79, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6d, 0x61,
-     0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74,
-     0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
-     0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65, 0x41,
-     0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x54, 0x68, 0x72, 0x65, 0x61,
-     0x64, 0x4d, 0x61, 0x69, 0x6e, 0x12, 0x5f, 0x0a, 0x15, 0x74, 0x69, 0x6d,
-     0x65, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x70, 0x70, 0x6c, 0x69,
-     0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b,
-     0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74,
-     0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x13, 0x74,
-     0x69, 0x6d, 0x65, 0x42, 0x69, 0x6e, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69,
-     0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x13, 0x74, 0x69,
-     0x6d, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f,
-     0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32,
-     0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x11, 0x74, 0x69,
-     0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x53, 0x74,
-     0x61, 0x72, 0x74, 0x12, 0x5d, 0x0a, 0x14, 0x74, 0x69, 0x6d, 0x65, 0x5f,
-     0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x65, 0x73,
-     0x75, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53,
-     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x12, 0x74, 0x69, 0x6d, 0x65,
-     0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x75,
-     0x6d, 0x65, 0x12, 0x5a, 0x0a, 0x12, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x63,
-     0x68, 0x6f, 0x72, 0x65, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x65, 0x72,
-     0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72,
-     0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c,
-     0x69, 0x63, 0x65, 0x52, 0x11, 0x74, 0x69, 0x6d, 0x65, 0x43, 0x68, 0x6f,
-     0x72, 0x65, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x65, 0x72, 0x12, 0x66,
-     0x0a, 0x19, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72,
-     0x65, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x63,
-     0x65, 0x73, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53,
-     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x2e, 0x53, 0x6c, 0x69, 0x63, 0x65, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65,
-     0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50,
-     0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x66, 0x0a, 0x19, 0x74, 0x69,
-     0x6d, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74,
-     0x61, 0x72, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18,
-     0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
-     0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74,
-     0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x53, 0x6c, 0x69,
-     0x63, 0x65, 0x52, 0x16, 0x74, 0x69, 0x6d, 0x65, 0x44, 0x75, 0x72, 0x69,
-     0x6e, 0x67, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65,
-     0x73, 0x73, 0x12, 0x4b, 0x0a, 0x23, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f,
-     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x61,
-     0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x63, 0x70, 0x75, 0x5f,
-     0x72, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x01, 0x52,
-     0x1e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
-     0x73, 0x54, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x43,
-     0x70, 0x75, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x1a, 0xbb, 0x02, 0x0a, 0x07,
-     0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x73,
-     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
-     0x01, 0x28, 0x0d, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70,
-     0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67,
-     0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
-     0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d,
-     0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
-     0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
-     0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65,
-     0x12, 0x2c, 0x0a, 0x12, 0x7a, 0x79, 0x67, 0x6f, 0x74, 0x65, 0x5f, 0x6e,
-     0x65, 0x77, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18, 0x04,
-     0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x7a, 0x79, 0x67, 0x6f, 0x74, 0x65,
-     0x4e, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x43,
-     0x0a, 0x1e, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x5f, 0x68,
-     0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65,
-     0x73, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01,
-     0x28, 0x0d, 0x52, 0x1b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79,
-     0x48, 0x6f, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x63, 0x65,
-     0x73, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x58, 0x0a, 0x0e, 0x74,
-     0x6f, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d,
-     0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61,
-     0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x54,
-     0x6f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52,
-     0x0c, 0x74, 0x6f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d,
-     0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xb7, 0x07, 0x0a, 0x3c, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x70,
-     0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73,
-     0x69, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x22, 0xe1, 0x06, 0x0a, 0x14, 0x48, 0x65, 0x61, 0x70,
-     0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73,
-     0x69, 0x74, 0x65, 0x73, 0x12, 0x5a, 0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74,
-     0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01,
-     0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48,
-     0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61,
-     0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x73, 0x74,
-     0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x69,
-     0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73,
-     0x1a, 0x3e, 0x0a, 0x05, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a,
-     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
-     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x70,
-     0x70, 0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
-     0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67,
-     0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x8e, 0x01, 0x0a, 0x08, 0x43, 0x6f, 0x75,
-     0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74,
-     0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75,
-     0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f,
-     0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52,
-     0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12,
-     0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x63, 0x6f, 0x75,
-     0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65,
-     0x6c, 0x74, 0x61, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b,
-     0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18,
-     0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65, 0x6c, 0x74, 0x61,
-     0x42, 0x79, 0x74, 0x65, 0x73, 0x1a, 0xa6, 0x02, 0x0a, 0x08, 0x43, 0x61,
-     0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61,
-     0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x68, 0x61,
-     0x73, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
-     0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52,
-     0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12,
-     0x41, 0x0a, 0x05, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61,
-     0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c,
-     0x73, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52,
-     0x05, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x4f, 0x0a, 0x0b, 0x73, 0x65,
-     0x6c, 0x66, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x18, 0x04, 0x20,
-     0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65,
-     0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c,
-     0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74,
-     0x65, 0x72, 0x73, 0x52, 0x0a, 0x73, 0x65, 0x6c, 0x66, 0x41, 0x6c, 0x6c,
-     0x6f, 0x63, 0x73, 0x12, 0x51, 0x0a, 0x0c, 0x63, 0x68, 0x69, 0x6c, 0x64,
-     0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28,
-     0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70,
-     0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73,
-     0x69, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
-     0x73, 0x52, 0x0b, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x41, 0x6c, 0x6c, 0x6f,
-     0x63, 0x73, 0x1a, 0xf2, 0x01, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61,
-     0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03,
-     0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x70,
-     0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
-     0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
-     0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d,
-     0x65, 0x12, 0x4c, 0x0a, 0x09, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74,
-     0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69,
-     0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e,
-     0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x52, 0x09, 0x63, 0x61,
-     0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x70,
-     0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61,
-     0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
-     0x52, 0x11, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x6c,
-     0x74, 0x61, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x70,
-     0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c,
-     0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03,
-     0x52, 0x11, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x6f, 0x74,
-     0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a,
-     0x8c, 0x02, 0x0a, 0x32, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
-     0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22,
-     0xc0, 0x01, 0x0a, 0x12, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50,
-     0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x47,
-     0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01,
-     0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67,
-     0x65, 0x4c, 0x69, 0x73, 0x74, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67,
-     0x65, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x1a,
-     0x61, 0x0a, 0x07, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x21,
-     0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61,
-     0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61,
-     0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a,
-     0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03,
-     0x75, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69,
-     0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
-     0x03, 0x52, 0x0b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f,
-     0x64, 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x80, 0x02, 0x0a, 0x39, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61,
-     0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x75, 0x6e, 0x73, 0x79, 0x6d,
-     0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x61, 0x6d,
-     0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65,
-     0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x22, 0xad, 0x01, 0x0a, 0x12, 0x55, 0x6e, 0x73, 0x79, 0x6d, 0x62,
-     0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
-     0x12, 0x41, 0x0a, 0x06, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01,
-     0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x55,
-     0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x46,
-     0x72, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52,
-     0x06, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x54, 0x0a, 0x05, 0x46,
-     0x72, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x75,
-     0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f,
-     0x64, 0x75, 0x6c, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x75, 0x69, 0x6c,
-     0x64, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
-     0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61,
-     0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
-     0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x02, 0x48,
-     0x03, 0x0a, 0xa4, 0x03, 0x0a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
-     0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f,
-     0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
-     0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x22, 0xd5, 0x02, 0x0a, 0x0d, 0x4a, 0x61, 0x76,
-     0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x53,
-     0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73,
-     0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c,
-     0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61,
-     0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61,
-     0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x69, 0x6e,
-     0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x1a,
-     0x65, 0x0a, 0x06, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x0e, 0x0a,
-     0x02, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x74,
-     0x73, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69,
-     0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x68, 0x65,
-     0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65,
-     0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x70,
-     0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52,
-     0x11, 0x72, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x48, 0x65,
-     0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0x87, 0x01, 0x0a, 0x0d, 0x49,
-     0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73,
-     0x12, 0x12, 0x0a, 0x04, 0x75, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
-     0x28, 0x0d, 0x52, 0x04, 0x75, 0x70, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c,
-     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
-     0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63,
-     0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x07, 0x73,
-     0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
-     0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61, 0x76, 0x61, 0x48,
-     0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x53, 0x61, 0x6d,
-     0x70, 0x6c, 0x65, 0x52, 0x07, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73,
-     0x42, 0x02, 0x48, 0x03, 0x0a, 0xed, 0x10, 0x0a, 0x25, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74,
-     0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x1a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
-     0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x2f, 0x62, 0x61, 0x74, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
-     0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x2f, 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72,
-     0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x65,
-     0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x36,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
-     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f,
-     0x75, 0x6e, 0x61, 0x67, 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x34, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
-     0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f,
-     0x67, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x69, 0x6f,
-     0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
-     0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
-     0x6c, 0x6d, 0x6b, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70,
-     0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
-     0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x2f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x5f, 0x6d,
-     0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
-     0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
-     0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x74, 0x61,
-     0x72, 0x74, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3c, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-     0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d,
-     0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x2f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x66,
-     0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65,
-     0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x32, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
-     0x5f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
-     0x39, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
-     0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x75, 0x6e, 0x73,
-     0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72,
-     0x61, 0x6d, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x35,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
-     0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
-     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6a, 0x61, 0x76, 0x61,
-     0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf1, 0x01, 0x0a, 0x0d, 0x54, 0x72,
-     0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12,
-     0x50, 0x0a, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61,
-     0x74, 0x73, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03,
-     0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61,
-     0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x45,
-     0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x53,
-     0x74, 0x61, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x2a, 0x0a,
-     0x11, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74,
-     0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03,
-     0x52, 0x0f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74,
-     0x69, 0x6f, 0x6e, 0x4e, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x72, 0x61,
-     0x63, 0x65, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
-     0x09, 0x52, 0x09, 0x74, 0x72, 0x61, 0x63, 0x65, 0x55, 0x75, 0x69, 0x64,
-     0x1a, 0x43, 0x0a, 0x05, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a,
-     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
-     0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x78,
-     0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x69, 0x64, 0x78, 0x12,
-     0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01,
-     0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x80, 0x09,
-     0x0a, 0x0c, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69,
-     0x63, 0x73, 0x12, 0x48, 0x0a, 0x0c, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x5f, 0x62, 0x61, 0x74, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
-     0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x4d, 0x65, 0x74,
-     0x72, 0x69, 0x63, 0x52, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x42, 0x61, 0x74, 0x74, 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x5f, 0x63, 0x70, 0x75, 0x18, 0x06, 0x20, 0x01, 0x28,
-     0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
-     0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75,
-     0x12, 0x45, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f,
-     0x6d, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d,
-     0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52,
-     0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x12,
-     0x5c, 0x0a, 0x11, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6d,
-     0x65, 0x6d, 0x5f, 0x75, 0x6e, 0x61, 0x67, 0x67, 0x18, 0x0b, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e,
-     0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65,
-     0x74, 0x72, 0x69, 0x63, 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x4d, 0x65, 0x6d, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x12, 0x55, 0x0a,
-     0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x70, 0x61, 0x63,
-     0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0c, 0x20,
-     0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
-     0x4c, 0x69, 0x73, 0x74, 0x52, 0x12, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
-     0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74,
-     0x12, 0x5b, 0x0a, 0x16, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f,
-     0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x6f, 0x77,
-     0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70,
-     0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-     0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72,
-     0x6f, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x52,
-     0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63,
-     0x65, 0x73, 0x73, 0x47, 0x72, 0x6f, 0x77, 0x74, 0x68, 0x12, 0x42, 0x0a,
-     0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x69, 0x6f, 0x6e,
-     0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72,
-     0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
-     0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x4d,
-     0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f,
-     0x69, 0x64, 0x49, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6c, 0x6d, 0x6b, 0x18, 0x08, 0x20, 0x01,
-     0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
-     0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
-     0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69,
-     0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d,
-     0x6b, 0x12, 0x4d, 0x0a, 0x10, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x5f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x07, 0x20,
-     0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
-     0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61,
-     0x69, 0x6c, 0x73, 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
-     0x50, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x4e, 0x0a, 0x0f,
-     0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x72,
-     0x74, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e,
-     0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
-     0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53,
-     0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
-     0x52, 0x0e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61,
-     0x72, 0x74, 0x75, 0x70, 0x12, 0x5b, 0x0a, 0x16, 0x68, 0x65, 0x61, 0x70,
-     0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c,
-     0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b,
-     0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
-     0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50,
-     0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69,
-     0x74, 0x65, 0x73, 0x52, 0x14, 0x68, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f,
-     0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65,
-     0x73, 0x12, 0x45, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x6d,
-     0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28,
-     0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
-     0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63,
-     0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x74,
-     0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
-     0x12, 0x54, 0x0a, 0x13, 0x75, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c,
-     0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18,
-     0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66,
-     0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
-     0x55, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64,
-     0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x12, 0x75, 0x6e, 0x73, 0x79,
-     0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x46, 0x72, 0x61, 0x6d,
-     0x65, 0x73, 0x12, 0x46, 0x0a, 0x0f, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68,
-     0x65, 0x61, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x11, 0x20,
-     0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
-     0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61,
-     0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52,
-     0x0d, 0x6a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61,
-     0x74, 0x73, 0x2a, 0x06, 0x08, 0xc2, 0x03, 0x10, 0xf4, 0x03, 0x2a, 0x06,
-     0x08, 0xf4, 0x03, 0x10, 0xe9, 0x07, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05,
-     0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x4a, 0x04, 0x08, 0x0e, 0x10, 0x0f,
-     0x42, 0x02, 0x48, 0x03}};
-
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_METRICS_METRICS_DESCRIPTOR_H_
diff --git a/src/trace_processor/metrics/metrics.h b/src/trace_processor/metrics/metrics.h
index 31d0e78..324d436 100644
--- a/src/trace_processor/metrics/metrics.h
+++ b/src/trace_processor/metrics/metrics.h
@@ -18,163 +18,20 @@
 #define SRC_TRACE_PROCESSOR_METRICS_METRICS_H_
 
 #include <sqlite3.h>
-
-#include <unordered_map>
 #include <vector>
 
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/protozero/field.h"
-#include "perfetto/protozero/message.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
 #include "perfetto/trace_processor/trace_processor.h"
-#include "src/trace_processor/metrics/descriptors.h"
-
-#include "protos/perfetto/trace_processor/metrics_impl.pbzero.h"
 
 namespace perfetto {
 namespace trace_processor {
 namespace metrics {
 
-// A description of a SQL metric in C++.
-struct SqlMetricFile {
-  // The path of this file with the root at the metrics root.
-  std::string path;
-
-  // The field in the output proto which will be filled by the result of
-  // querying the table specified by |output_table_name|.
-  // Optional because not all protos need to have a field associated with them
-  // in the root proto; most files will be just be run using RUN_METRIC by
-  // other files.
-  base::Optional<std::string> proto_field_name;
-
-  // The table name which will be created by the SQL below to read the proto
-  // bytes from.
-  // Should only be set when |proto_field_name| is set.
-  base::Optional<std::string> output_table_name;
-
-  // The SQL run by this metric.
-  std::string sql;
-};
-
-// Helper class to build a nested (metric) proto checking the schema against
-// a descriptor.
-// Visible for testing.
-class ProtoBuilder {
- public:
-  ProtoBuilder(const ProtoDescriptor*);
-
-  util::Status AppendSqlValue(const std::string& field_name,
-                              const SqlValue& value);
-
-  // Note: all external callers to these functions should not
-  // |is_inside_repeated| to this function and instead rely on the default
-  // value.
-  util::Status AppendLong(const std::string& field_name,
-                          int64_t value,
-                          bool is_inside_repeated = false);
-  util::Status AppendDouble(const std::string& field_name,
-                            double value,
-                            bool is_inside_repeated = false);
-  util::Status AppendString(const std::string& field_name,
-                            base::StringView value,
-                            bool is_inside_repeated = false);
-  util::Status AppendBytes(const std::string& field_name,
-                           const uint8_t* data,
-                           size_t size,
-                           bool is_inside_repeated = false);
-
-  // Returns the serialized |protos::ProtoBuilderResult| with the built proto
-  // as the nested |protobuf| message.
-  // Note: no other functions should be called on this class after this method
-  // is called.
-  std::vector<uint8_t> SerializeToProtoBuilderResult();
-
-  // Returns the serialized version of the raw message being built.
-  // This function should only be used at the top level where type checking is
-  // no longer important because the proto will be returned as is. In all other
-  // instances, prefer |SerializeToProtoBuilderResult()| instead.
-  // Note: no other functions should be called on this class after this method
-  // is called.
-  std::vector<uint8_t> SerializeRaw();
-
- private:
-  util::Status AppendSingleMessage(const FieldDescriptor& field,
-                                   const uint8_t* ptr,
-                                   size_t size);
-
-  util::Status AppendRepeated(const FieldDescriptor& field,
-                              const uint8_t* ptr,
-                              size_t size);
-
-  const ProtoDescriptor* descriptor_ = nullptr;
-  protozero::HeapBuffered<protozero::Message> message_;
-};
-
-// Helper class to combine a set of repeated fields into a single proto blob
-// to return to SQLite.
-// Visible for testing.
-class RepeatedFieldBuilder {
- public:
-  RepeatedFieldBuilder();
-
-  util::Status AddSqlValue(SqlValue value);
-
-  void AddLong(int64_t value);
-  void AddDouble(double value);
-  void AddString(base::StringView value);
-  void AddBytes(const uint8_t* data, size_t size);
-
-  // Returns the serialized |protos::ProtoBuilderResult| with the set of
-  // repeated fields as |repeated_values| in the proto.
-  // Note: no other functions should be called on this class after this method
-  // is called.
-  std::vector<uint8_t> SerializeToProtoBuilderResult();
-
- private:
-  bool has_data_ = false;
-
-  protozero::HeapBuffered<protos::pbzero::ProtoBuilderResult> message_;
-  protos::pbzero::RepeatedBuilderResult* repeated_ = nullptr;
-};
-
-// Replaces templated variables inside |raw_text| using the substitution given
-// by |substitutions| writing the result to |out|.
-// The syntax followed is a cut-down variant of Jinja. This means variables that
-// are to be replaced use {{variable-name}} in the raw text with subsitutions
-// containing a mapping from (variable-name -> replacement).
-int TemplateReplace(
-    const std::string& raw_text,
-    const std::unordered_map<std::string, std::string>& substitutions,
-    std::string* out);
-
-// These functions implement the RepeatedField SQL aggregate functions.
-void RepeatedFieldStep(sqlite3_context* ctx, int argc, sqlite3_value** argv);
-void RepeatedFieldFinal(sqlite3_context* ctx);
-
-// Context struct for the below function.
-struct BuildProtoContext {
-  TraceProcessor* tp;
-  const DescriptorPool* pool;
-  const ProtoDescriptor* desc;
-};
-
-// This function implements all the proto creation functions.
-void BuildProto(sqlite3_context* ctx, int argc, sqlite3_value** argv);
-
-// Context struct for the below function.
-struct RunMetricContext {
-  TraceProcessor* tp;
-  std::vector<SqlMetricFile>* metrics;
-};
-
 // This function implements the RUN_METRIC SQL function.
 void RunMetric(sqlite3_context* ctx, int argc, sqlite3_value** argv);
 
-util::Status ComputeMetrics(TraceProcessor* impl,
-                            const std::vector<std::string> metrics_to_compute,
-                            const std::vector<SqlMetricFile>& metrics,
-                            const ProtoDescriptor& root_descriptor,
-                            std::vector<uint8_t>* metrics_proto);
+int ComputeMetrics(TraceProcessor* impl,
+                   const std::vector<std::string>& metric_names,
+                   std::vector<uint8_t>* metrics_proto);
 
 }  // namespace metrics
 }  // namespace trace_processor
diff --git a/src/trace_processor/metrics/metrics_unittest.cc b/src/trace_processor/metrics/metrics_unittest.cc
deleted file mode 100644
index 534b181..0000000
--- a/src/trace_processor/metrics/metrics_unittest.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/metrics/metrics.h"
-
-#include <vector>
-
-#include "protos/perfetto/common/descriptor.pbzero.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace metrics {
-
-namespace {
-
-std::string RunTemplateReplace(
-    const std::string& str,
-    std::unordered_map<std::string, std::string> subs) {
-  std::string out;
-  EXPECT_EQ(TemplateReplace(str, subs, &out), 0);
-  return out;
-}
-
-TEST(MetricsTest, TemplateReplace) {
-  auto res = RunTemplateReplace("no templates here", {});
-  ASSERT_EQ(res, "no templates here");
-
-  res = RunTemplateReplace("{{justtemplate}}", {{"justtemplate", "result"}});
-  ASSERT_EQ(res, "result");
-
-  res = RunTemplateReplace("{{temp1}} {{temp2}}!",
-                           {{"temp1", "hello"}, {"temp2", "world"}});
-  ASSERT_EQ(res, "hello world!");
-
-  std::string unused;
-  ASSERT_NE(TemplateReplace("{{missing}}", {{}}, &unused), 0);
-}
-
-class ProtoBuilderTest : public ::testing::Test {
- protected:
-  template <bool repeated>
-  protozero::TypedProtoDecoder<1, repeated> DecodeSingleFieldProto(
-      const std::vector<uint8_t>& result_ser) {
-    protos::pbzero::ProtoBuilderResult::Decoder result(result_ser.data(),
-                                                       result_ser.size());
-    protozero::ConstBytes single_ser = result.single();
-    protos::pbzero::SingleBuilderResult::Decoder single(single_ser.data,
-                                                        single_ser.size);
-
-    protozero::ConstBytes proto_ser = single.protobuf();
-    return protozero::TypedProtoDecoder<1, repeated>(proto_ser.data,
-                                                     proto_ser.size);
-  }
-};
-
-TEST_F(ProtoBuilderTest, AppendLong) {
-  using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
-
-  // Create the descriptor version of the following message:
-  // message TestProto {
-  //   optional int64 int_value = 1;
-  // }
-  ProtoDescriptor descriptor(".perfetto.protos", ".perfetto.protos.TestProto",
-                             base::nullopt);
-  descriptor.AddField(FieldDescriptor(
-      "int_value", 1, FieldDescriptorProto::TYPE_INT64, "", false));
-
-  ProtoBuilder builder(&descriptor);
-  ASSERT_TRUE(builder.AppendLong("int_value", 12345).ok());
-
-  auto result_ser = builder.SerializeToProtoBuilderResult();
-  auto proto = DecodeSingleFieldProto<false>(result_ser);
-  const protozero::Field& int_field = proto.Get(1);
-  ASSERT_EQ(int_field.as_int64(), 12345);
-}
-
-TEST_F(ProtoBuilderTest, AppendDouble) {
-  using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
-
-  // Create the descriptor version of the following message:
-  // message TestProto {
-  //   optional double double_value = 1;
-  // }
-  ProtoDescriptor descriptor(".perfetto.protos", ".perfetto.protos.TestProto",
-                             base::nullopt);
-  descriptor.AddField(FieldDescriptor(
-      "double_value", 1, FieldDescriptorProto::TYPE_DOUBLE, "", false));
-
-  ProtoBuilder builder(&descriptor);
-  ASSERT_TRUE(builder.AppendDouble("double_value", 1.2345).ok());
-
-  auto result_ser = builder.SerializeToProtoBuilderResult();
-  auto proto = DecodeSingleFieldProto<false>(result_ser);
-  const protozero::Field& db_field = proto.Get(1);
-  ASSERT_DOUBLE_EQ(db_field.as_double(), 1.2345);
-}
-
-TEST_F(ProtoBuilderTest, AppendString) {
-  using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
-
-  // Create the descriptor version of the following message:
-  // message TestProto {
-  //   optional string string_value = 1;
-  // }
-  ProtoDescriptor descriptor(".perfetto.protos", ".perfetto.protos.TestProto",
-                             base::nullopt);
-  descriptor.AddField(FieldDescriptor(
-      "string_value", 1, FieldDescriptorProto::TYPE_STRING, "", false));
-
-  ProtoBuilder builder(&descriptor);
-  ASSERT_TRUE(builder.AppendString("string_value", "hello world!").ok());
-
-  auto result_ser = builder.SerializeToProtoBuilderResult();
-  auto proto = DecodeSingleFieldProto<false>(result_ser);
-  const protozero::Field& str_field = proto.Get(1);
-  ASSERT_EQ(str_field.as_std_string(), "hello world!");
-}
-
-TEST_F(ProtoBuilderTest, AppendNested) {
-  using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
-
-  // Create the descriptor version of the following message:
-  // message TestProto {
-  //   message NestedProto {
-  //     optional int64 nested_int_value = 1;
-  //   }
-  //   optional NestedProto nested_value = 1;
-  // }
-  ProtoDescriptor nested(".perfetto.protos",
-                         ".perfetto.protos.TestProto.NestedProto",
-                         base::nullopt);
-  nested.AddField(FieldDescriptor("nested_int_value", 1,
-                                  FieldDescriptorProto::TYPE_INT64, "", false));
-
-  ProtoDescriptor descriptor(".perfetto.protos", ".perfetto.protos.TestProto",
-                             base::nullopt);
-  auto field =
-      FieldDescriptor("nested_value", 1, FieldDescriptorProto::TYPE_MESSAGE,
-                      ".perfetto.protos.TestProto.NestedProto", false);
-  field.set_resolved_type_name(".perfetto.protos.TestProto.NestedProto");
-  descriptor.AddField(field);
-
-  ProtoBuilder nest_builder(&nested);
-  ASSERT_TRUE(nest_builder.AppendLong("nested_int_value", 789).ok());
-
-  auto nest_ser = nest_builder.SerializeToProtoBuilderResult();
-
-  ProtoBuilder builder(&descriptor);
-  ASSERT_TRUE(
-      builder.AppendBytes("nested_value", nest_ser.data(), nest_ser.size())
-          .ok());
-
-  auto result_ser = builder.SerializeToProtoBuilderResult();
-  auto proto = DecodeSingleFieldProto<false>(result_ser);
-  const protozero::Field& nest_field = proto.Get(1);
-  ASSERT_EQ(nest_field.type(),
-            protozero::proto_utils::ProtoWireType::kLengthDelimited);
-
-  protozero::ConstBytes nest_bytes = nest_field.as_bytes();
-  protozero::TypedProtoDecoder<1, false> nest(nest_bytes.data, nest_bytes.size);
-
-  const protozero::Field& nest_int_field = nest.Get(1);
-  ASSERT_EQ(nest_int_field.type(),
-            protozero::proto_utils::ProtoWireType::kVarInt);
-  ASSERT_EQ(nest_int_field.as_int64(), 789);
-}
-
-TEST_F(ProtoBuilderTest, AppendRepeatedPrimitive) {
-  using FieldDescriptorProto = protos::pbzero::FieldDescriptorProto;
-
-  // Create the descriptor version of the following message:
-  // message TestProto {
-  //   repeated int64 int_value = 1;
-  // }
-  ProtoDescriptor descriptor(".perfetto.protos", ".perfetto.protos.TestProto",
-                             base::nullopt);
-  descriptor.AddField(FieldDescriptor(
-      "rep_int_value", 1, FieldDescriptorProto::TYPE_INT64, "", true));
-
-  RepeatedFieldBuilder rep_builder;
-  rep_builder.AddLong(1234);
-  rep_builder.AddLong(5678);
-
-  std::vector<uint8_t> rep_ser = rep_builder.SerializeToProtoBuilderResult();
-
-  ProtoBuilder builder(&descriptor);
-  ASSERT_TRUE(
-      builder.AppendBytes("rep_int_value", rep_ser.data(), rep_ser.size())
-          .ok());
-
-  auto result_ser = builder.SerializeToProtoBuilderResult();
-  auto proto = DecodeSingleFieldProto<true>(result_ser);
-  auto it = proto.GetRepeated<int64_t>(1);
-  ASSERT_EQ(*it, 1234);
-  ASSERT_EQ(*++it, 5678);
-  ASSERT_FALSE(++it);
-}
-
-}  // namespace
-
-}  // namespace metrics
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/metrics/trace_metadata.sql b/src/trace_processor/metrics/trace_metadata.sql
deleted file mode 100644
index 11524ac..0000000
--- a/src/trace_processor/metrics/trace_metadata.sql
+++ /dev/null
@@ -1,31 +0,0 @@
---
--- Copyright 2019 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
---
---     https://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.
---
-
-CREATE VIEW error_stats_view AS
-SELECT TraceMetadata_Entry(
-  'name', name,
-  'idx', idx,
-  'value', value) as entry
-FROM stats
-WHERE severity IN ('data_loss', 'error')
-AND value > 0;
-
-CREATE VIEW trace_metadata_output AS
-SELECT TraceMetadata(
-  'error_stats_entry', (SELECT RepeatedField(entry) FROM error_stats_view),
-  'trace_duration_ns', (SELECT end_ts - start_ts FROM trace_bounds),
-  'trace_uuid', (SELECT str_value FROM metadata WHERE name = 'trace_uuid')
-);
diff --git a/src/trace_processor/null_term_string_view.h b/src/trace_processor/null_term_string_view.h
index f576006..60a27f9 100644
--- a/src/trace_processor/null_term_string_view.h
+++ b/src/trace_processor/null_term_string_view.h
@@ -17,7 +17,7 @@
 #ifndef SRC_TRACE_PROCESSOR_NULL_TERM_STRING_VIEW_H_
 #define SRC_TRACE_PROCESSOR_NULL_TERM_STRING_VIEW_H_
 
-#include "perfetto/ext/base/string_view.h"
+#include "perfetto/base/string_view.h"
 
 namespace perfetto {
 namespace trace_processor {
diff --git a/src/trace_processor/null_term_string_view_unittest.cc b/src/trace_processor/null_term_string_view_unittest.cc
index c8cc29e..75977b09 100644
--- a/src/trace_processor/null_term_string_view_unittest.cc
+++ b/src/trace_processor/null_term_string_view_unittest.cc
@@ -16,7 +16,8 @@
 
 #include "src/trace_processor/null_term_string_view.h"
 
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace trace_processor {
diff --git a/src/trace_processor/process_table.cc b/src/trace_processor/process_table.cc
index c85177a..3d72aa4 100644
--- a/src/trace_processor/process_table.cc
+++ b/src/trace_processor/process_table.cc
@@ -17,8 +17,8 @@
 #include "src/trace_processor/process_table.h"
 
 #include "perfetto/base/logging.h"
-#include "src/trace_processor/sqlite/query_constraints.h"
-#include "src/trace_processor/sqlite/sqlite_utils.h"
+#include "src/trace_processor/query_constraints.h"
+#include "src/trace_processor/sqlite_utils.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -33,97 +33,92 @@
     : storage_(storage) {}
 
 void ProcessTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
-  SqliteTable::Register<ProcessTable>(db, storage, "process");
+  Table::Register<ProcessTable>(db, storage, "process");
 }
 
-util::Status ProcessTable::Init(int, const char* const*, Schema* schema) {
-  *schema = Schema(
+base::Optional<Table::Schema> ProcessTable::Init(int, const char* const*) {
+  return Schema(
       {
-          SqliteTable::Column(Column::kUpid, "upid", SqlValue::Type::kLong),
-          SqliteTable::Column(Column::kName, "name", SqlValue::Type::kString),
-          SqliteTable::Column(Column::kPid, "pid", SqlValue::Type::kLong),
-          SqliteTable::Column(Column::kStartTs, "start_ts",
-                              SqlValue::Type::kLong),
-          SqliteTable::Column(Column::kEndTs, "end_ts", SqlValue::Type::kLong),
-          SqliteTable::Column(Column::kParentUpid, "parent_upid",
-                              SqlValue::Type::kLong),
+          Table::Column(Column::kUpid, "upid", ColumnType::kInt),
+          Table::Column(Column::kName, "name", ColumnType::kString),
+          Table::Column(Column::kPid, "pid", ColumnType::kUint),
+          Table::Column(Column::kStartTs, "start_ts", ColumnType::kLong),
       },
       {Column::kUpid});
-  return util::OkStatus();
 }
 
-std::unique_ptr<SqliteTable::Cursor> ProcessTable::CreateCursor() {
-  return std::unique_ptr<SqliteTable::Cursor>(new Cursor(this));
+std::unique_ptr<Table::Cursor> ProcessTable::CreateCursor() {
+  return std::unique_ptr<Table::Cursor>(new Cursor(this));
 }
 
 int ProcessTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
+  info->estimated_cost = static_cast<uint32_t>(storage_->process_count());
+
   // If the query has a constraint on the |upid| field, return a reduced cost
   // because we can do that filter efficiently.
-  const auto& cs = qc.constraints();
-  auto fn = [](const QueryConstraints::Constraint& c) {
-    return c.iColumn == Column::kUpid && sqlite_utils::IsOpEq(c.op);
-  };
-  info->estimated_cost = std::find_if(cs.begin(), cs.end(), fn) != cs.end()
-                             ? 1
-                             : static_cast<uint32_t>(storage_->process_count());
+  const auto& constraints = qc.constraints();
+  if (constraints.size() == 1 && constraints.front().iColumn == Column::kUpid) {
+    info->estimated_cost = IsOpEq(constraints.front().op) ? 1 : 10;
+  }
+
   return SQLITE_OK;
 }
 
 ProcessTable::Cursor::Cursor(ProcessTable* table)
-    : SqliteTable::Cursor(table), storage_(table->storage_) {}
+    : Table::Cursor(table), storage_(table->storage_) {}
 
 int ProcessTable::Cursor::Filter(const QueryConstraints& qc,
                                  sqlite3_value** argv) {
-  min_ = 0;
-  max_ = static_cast<uint32_t>(storage_->process_count());
-  desc_ = false;
+  min = 0;
+  max = static_cast<uint32_t>(storage_->process_count()) - 1;
+  desc = false;
+  current = min;
 
   for (size_t j = 0; j < qc.constraints().size(); j++) {
     const auto& cs = qc.constraints()[j];
     if (cs.iColumn == Column::kUpid) {
       auto constraint_upid = static_cast<UniquePid>(sqlite3_value_int(argv[j]));
       // Set the range of upids that we are interested in, based on the
-      // constraints in the query. Everything between min and max (exclusive)
+      // constraints in the query. Everything between min and max (inclusive)
       // will be returned.
       if (IsOpEq(cs.op)) {
-        min_ = constraint_upid;
-        max_ = constraint_upid + 1;
+        min = constraint_upid;
+        max = constraint_upid;
       } else if (IsOpGe(cs.op) || IsOpGt(cs.op)) {
-        min_ = IsOpGt(cs.op) ? constraint_upid + 1 : constraint_upid;
+        min = IsOpGt(cs.op) ? constraint_upid + 1 : constraint_upid;
       } else if (IsOpLe(cs.op) || IsOpLt(cs.op)) {
-        max_ = IsOpLt(cs.op) ? constraint_upid : constraint_upid + 1;
+        max = IsOpLt(cs.op) ? constraint_upid - 1 : constraint_upid;
       }
     }
   }
-
   for (const auto& ob : qc.order_by()) {
     if (ob.iColumn == Column::kUpid) {
-      desc_ = ob.desc;
+      desc = ob.desc;
+      current = desc ? max : min;
     }
   }
-  index_ = 0;
-
   return SQLITE_OK;
 }
 
 int ProcessTable::Cursor::Column(sqlite3_context* context, int N) {
-  uint32_t current = desc_ ? max_ - index_ - 1 : min_ + index_;
-  const auto& process = storage_->GetProcess(current);
   switch (N) {
     case Column::kUpid: {
       sqlite3_result_int64(context, current);
       break;
     }
     case Column::kName: {
+      const auto& process = storage_->GetProcess(current);
       const auto& name = storage_->GetString(process.name_id);
       sqlite3_result_text(context, name.c_str(), -1, kSqliteStatic);
       break;
     }
     case Column::kPid: {
+      const auto& process = storage_->GetProcess(current);
       sqlite3_result_int64(context, process.pid);
       break;
     }
     case Column::kStartTs: {
+      const auto& process = storage_->GetProcess(current);
       if (process.start_ns != 0) {
         sqlite3_result_int64(context, process.start_ns);
       } else {
@@ -131,22 +126,6 @@
       }
       break;
     }
-    case Column::kEndTs: {
-      if (process.end_ns != 0) {
-        sqlite3_result_int64(context, process.end_ns);
-      } else {
-        sqlite3_result_null(context);
-      }
-      break;
-    }
-    case Column::kParentUpid: {
-      if (process.parent_upid.has_value()) {
-        sqlite3_result_int64(context, process.parent_upid.value());
-      } else {
-        sqlite3_result_null(context);
-      }
-      break;
-    }
     default:
       PERFETTO_FATAL("Unknown column %d", N);
       break;
@@ -155,12 +134,16 @@
 }
 
 int ProcessTable::Cursor::Next() {
-  ++index_;
+  if (desc) {
+    --current;
+  } else {
+    ++current;
+  }
   return SQLITE_OK;
 }
 
 int ProcessTable::Cursor::Eof() {
-  return index_ >= (max_ - min_);
+  return desc ? current < min : current > max;
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/process_table.h b/src/trace_processor/process_table.h
index c4c1ed5..1fc0f0f 100644
--- a/src/trace_processor/process_table.h
+++ b/src/trace_processor/process_table.h
@@ -20,25 +20,18 @@
 #include <limits>
 #include <memory>
 
-#include "src/trace_processor/sqlite/sqlite_table.h"
+#include "src/trace_processor/table.h"
 #include "src/trace_processor/trace_storage.h"
 
 namespace perfetto {
 namespace trace_processor {
 
 // The implementation of the SQLite table containing each unique process with
-// their details.
-class ProcessTable : public SqliteTable {
+// their details (only name at the moment).
+class ProcessTable : public Table {
  public:
-  enum Column {
-    kUpid = 0,
-    kName = 1,
-    kPid = 2,
-    kStartTs = 3,
-    kEndTs = 4,
-    kParentUpid = 5
-  };
-  class Cursor : public SqliteTable::Cursor {
+  enum Column { kUpid = 0, kName = 1, kPid = 2, kStartTs = 3 };
+  class Cursor : public Table::Cursor {
    public:
     Cursor(ProcessTable*);
 
@@ -50,10 +43,10 @@
 
    private:
     const TraceStorage* const storage_;
-    UniquePid min_ = 0;
-    UniquePid max_ = 0;
-    uint32_t index_ = 0;
-    bool desc_ = false;
+    UniquePid min;
+    UniquePid max;
+    UniquePid current;
+    bool desc;
   };
 
   static void RegisterTable(sqlite3* db, const TraceStorage* storage);
@@ -61,8 +54,8 @@
   ProcessTable(sqlite3*, const TraceStorage*);
 
   // Table implementation.
-  util::Status Init(int, const char* const*, SqliteTable::Schema*) override;
-  std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
+  base::Optional<Table::Schema> Init(int, const char* const*) override;
+  std::unique_ptr<Table::Cursor> CreateCursor() override;
   int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
 
  private:
diff --git a/src/trace_processor/process_table_unittest.cc b/src/trace_processor/process_table_unittest.cc
index 84de696..745bbd5 100644
--- a/src/trace_processor/process_table_unittest.cc
+++ b/src/trace_processor/process_table_unittest.cc
@@ -17,10 +17,11 @@
 #include "src/trace_processor/process_table.h"
 #include "src/trace_processor/event_tracker.h"
 #include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/sqlite/scoped_db.h"
+#include "src/trace_processor/scoped_db.h"
 #include "src/trace_processor/trace_processor_context.h"
 
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -30,7 +31,6 @@
  public:
   ProcessTableUnittest() {
     sqlite3* db = nullptr;
-    PERFETTO_CHECK(sqlite3_initialize() == SQLITE_OK);
     PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
     db_.reset(db);
 
@@ -52,6 +52,8 @@
     return reinterpret_cast<const char*>(sqlite3_column_text(*stmt_, colId));
   }
 
+  ~ProcessTableUnittest() override { context_.storage->ResetStorage(); }
+
  protected:
   TraceProcessorContext context_;
   ScopedDb db_;
@@ -61,8 +63,8 @@
 TEST_F(ProcessTableUnittest, SelectUpidAndName) {
   static const char kCommProc1[] = "process1";
   static const char kCommProc2[] = "process2";
-  context_.process_tracker->SetProcessMetadata(1, base::nullopt, kCommProc1);
-  context_.process_tracker->SetProcessMetadata(2, base::nullopt, kCommProc2);
+  context_.process_tracker->UpdateProcess(1, base::nullopt, kCommProc1);
+  context_.process_tracker->UpdateProcess(2, base::nullopt, kCommProc2);
 
   PrepareValidStatement("SELECT upid, name FROM process");
 
@@ -83,8 +85,8 @@
 TEST_F(ProcessTableUnittest, SelectUpidAndNameWithFilter) {
   static const char kCommProc1[] = "process1";
   static const char kCommProc2[] = "process2";
-  context_.process_tracker->SetProcessMetadata(1, base::nullopt, kCommProc1);
-  context_.process_tracker->SetProcessMetadata(2, base::nullopt, kCommProc2);
+  context_.process_tracker->UpdateProcess(1, base::nullopt, kCommProc1);
+  context_.process_tracker->UpdateProcess(2, base::nullopt, kCommProc2);
 
   PrepareValidStatement("SELECT upid, name FROM process where upid = 2");
 
@@ -98,8 +100,8 @@
 TEST_F(ProcessTableUnittest, SelectUpidAndNameWithOrder) {
   static const char kCommProc1[] = "process1";
   static const char kCommProc2[] = "process2";
-  context_.process_tracker->SetProcessMetadata(1, base::nullopt, kCommProc1);
-  context_.process_tracker->SetProcessMetadata(2, base::nullopt, kCommProc2);
+  context_.process_tracker->UpdateProcess(1, base::nullopt, kCommProc1);
+  context_.process_tracker->UpdateProcess(2, base::nullopt, kCommProc2);
 
   PrepareValidStatement("SELECT upid, name FROM process ORDER BY upid desc");
 
@@ -120,8 +122,8 @@
 TEST_F(ProcessTableUnittest, SelectUpidAndNameFilterGt) {
   static const char kCommProc1[] = "process1";
   static const char kCommProc2[] = "process2";
-  context_.process_tracker->SetProcessMetadata(1, base::nullopt, kCommProc1);
-  context_.process_tracker->SetProcessMetadata(2, base::nullopt, kCommProc2);
+  context_.process_tracker->UpdateProcess(1, base::nullopt, kCommProc1);
+  context_.process_tracker->UpdateProcess(2, base::nullopt, kCommProc2);
 
   PrepareValidStatement("SELECT upid, name FROM process where upid > 1");
 
@@ -135,8 +137,8 @@
 TEST_F(ProcessTableUnittest, SelectUpidAndNameFilterName) {
   static const char kCommProc1[] = "process1";
   static const char kCommProc2[] = "process2";
-  context_.process_tracker->SetProcessMetadata(1, base::nullopt, kCommProc1);
-  context_.process_tracker->SetProcessMetadata(2, base::nullopt, kCommProc2);
+  context_.process_tracker->UpdateProcess(1, base::nullopt, kCommProc1);
+  context_.process_tracker->UpdateProcess(2, base::nullopt, kCommProc2);
 
   PrepareValidStatement(
       "SELECT upid, name FROM process where name = \"process2\"");
@@ -151,8 +153,8 @@
 TEST_F(ProcessTableUnittest, SelectUpidAndNameFilterDifferentOr) {
   static const char kCommProc1[] = "process1";
   static const char kCommProc2[] = "process2";
-  context_.process_tracker->SetProcessMetadata(1, base::nullopt, kCommProc1);
-  context_.process_tracker->SetProcessMetadata(2, base::nullopt, kCommProc2);
+  context_.process_tracker->UpdateProcess(1, base::nullopt, kCommProc1);
+  context_.process_tracker->UpdateProcess(2, base::nullopt, kCommProc2);
 
   PrepareValidStatement(
       "SELECT upid, name FROM process where upid = 2 or name = \"process2\"");
@@ -167,8 +169,8 @@
 TEST_F(ProcessTableUnittest, SelectUpidAndNameFilterSameOr) {
   static const char kCommProc1[] = "process1";
   static const char kCommProc2[] = "process2";
-  context_.process_tracker->SetProcessMetadata(1, base::nullopt, kCommProc1);
-  context_.process_tracker->SetProcessMetadata(2, base::nullopt, kCommProc2);
+  context_.process_tracker->UpdateProcess(1, base::nullopt, kCommProc1);
+  context_.process_tracker->UpdateProcess(2, base::nullopt, kCommProc2);
 
   PrepareValidStatement(
       "SELECT upid, name FROM process where upid = 1 or upid = 2");
diff --git a/src/trace_processor/process_tracker.cc b/src/trace_processor/process_tracker.cc
index e9c0335..6ad36d1 100644
--- a/src/trace_processor/process_tracker.cc
+++ b/src/trace_processor/process_tracker.cc
@@ -44,56 +44,30 @@
   return new_utid;
 }
 
-void ProcessTracker::EndThread(int64_t timestamp, uint32_t tid) {
-  UniqueTid utid = GetOrCreateThread(tid);
-  TraceStorage::Thread* thread = context_->storage->GetMutableThread(utid);
-  thread->end_ns = timestamp;
-  if (thread->upid.has_value()) {
-    TraceStorage::Process* process =
-        context_->storage->GetMutableProcess(thread->upid.value());
-
-    // If the process pid and thread tid are equal, then this is the main thread
-    // of the process.
-    if (process->pid == thread->tid) {
-      process->end_ns = timestamp;
-    }
-  }
-}
-
-base::Optional<UniqueTid> ProcessTracker::GetThreadOrNull(uint32_t tid) {
+UniqueTid ProcessTracker::GetOrCreateThread(uint32_t tid) {
   auto pair_it = tids_.equal_range(tid);
   if (pair_it.first != pair_it.second) {
-    auto prev_utid = std::prev(pair_it.second)->second;
-    TraceStorage::Thread* thread =
-        context_->storage->GetMutableThread(prev_utid);
-
-    // Only return alive threads.
-    if (thread->end_ns == 0)
-      return prev_utid;
+    return std::prev(pair_it.second)->second;
   }
-  return base::nullopt;
-}
-
-UniqueTid ProcessTracker::GetOrCreateThread(uint32_t tid) {
-  auto utid = GetThreadOrNull(tid);
-  return utid ? utid.value() : StartNewThread(0, tid, 0);
+  return StartNewThread(0, tid, 0);
 }
 
 UniqueTid ProcessTracker::UpdateThreadName(uint32_t tid,
                                            StringId thread_name_id) {
-  auto utid = GetOrCreateThread(tid);
-  if (!thread_name_id.is_null()) {
-    TraceStorage::Thread* thread = context_->storage->GetMutableThread(utid);
-    thread->name_id = thread_name_id;
-  }
-  return utid;
-}
+  auto pair_it = tids_.equal_range(tid);
 
-void ProcessTracker::SetThreadNameIfUnset(UniqueTid utid,
-                                          StringId thread_name_id) {
-  TraceStorage::Thread* thread = context_->storage->GetMutableThread(utid);
-  if (thread->name_id == kNullStringId)
-    thread->name_id = thread_name_id;
+  // If a utid exists for the tid, find it and update the name.
+  if (pair_it.first != pair_it.second) {
+    auto prev_utid = std::prev(pair_it.second)->second;
+    TraceStorage::Thread* thread =
+        context_->storage->GetMutableThread(prev_utid);
+    if (thread_name_id)
+      thread->name_id = thread_name_id;
+    return prev_utid;
+  }
+
+  // If none exist, assign a new utid and store it.
+  return StartNewThread(0, tid, thread_name_id);
 }
 
 UniqueTid ProcessTracker::UpdateThread(uint32_t tid, uint32_t pid) {
@@ -105,11 +79,6 @@
   for (auto it = tids_pair.first; it != tids_pair.second; it++) {
     UniqueTid iter_utid = it->second;
     auto* iter_thread = context_->storage->GetMutableThread(iter_utid);
-    if (iter_thread->end_ns != 0) {
-      // If the thread is already dead, don't bother choosing it as the
-      // thread for this process.
-      continue;
-    }
     if (!iter_thread->upid.has_value()) {
       // We haven't discovered the parent process for the thread. Assign it
       // now and use this thread.
@@ -119,11 +88,6 @@
     }
     const auto& iter_process =
         context_->storage->GetProcess(iter_thread->upid.value());
-    if (iter_process.end_ns != 0) {
-      // If the process is already dead, don't bother choosing the associated
-      // thread.
-      continue;
-    }
     if (iter_process.pid == pid) {
       // We found a thread that matches both the tid and its parent pid.
       thread = iter_thread;
@@ -149,37 +113,22 @@
   return utid;
 }
 
-UniquePid ProcessTracker::StartNewProcess(int64_t timestamp,
-                                          uint32_t parent_tid,
-                                          uint32_t pid,
-                                          StringId main_thread_name) {
+UniquePid ProcessTracker::StartNewProcess(int64_t timestamp, uint32_t pid) {
   pids_.erase(pid);
 
   // Create a new UTID for the main thread, so we don't end up reusing an old
   // entry in case of TID recycling.
   StartNewThread(timestamp, /*tid=*/pid, 0);
 
-  // Note that we erased the pid above so this should always return a new
-  // process.
   std::pair<UniquePid, TraceStorage::Process*> process =
       GetOrCreateProcessPtr(pid);
-  PERFETTO_DCHECK(process.second->name_id == 0);
   process.second->start_ns = timestamp;
-  process.second->name_id = main_thread_name;
-
-  UniqueTid parent_utid = GetOrCreateThread(parent_tid);
-  auto* parent_thread = context_->storage->GetMutableThread(parent_utid);
-  if (parent_thread->upid.has_value()) {
-    process.second->parent_upid = parent_thread->upid.value();
-  } else {
-    pending_parent_assocs_.emplace_back(parent_utid, process.first);
-  }
   return process.first;
 }
 
-UniquePid ProcessTracker::SetProcessMetadata(uint32_t pid,
-                                             base::Optional<uint32_t> ppid,
-                                             base::StringView name) {
+UniquePid ProcessTracker::UpdateProcess(uint32_t pid,
+                                        base::Optional<uint32_t> ppid,
+                                        base::StringView name) {
   auto proc_name_id = context_->storage->InternString(name);
 
   base::Optional<UniquePid> pupid;
@@ -190,29 +139,10 @@
   TraceStorage::Process* process;
   std::tie(upid, process) = GetOrCreateProcessPtr(pid);
   process->name_id = proc_name_id;
-  process->parent_upid = pupid;
+  process->pupid = pupid;
   return upid;
 }
 
-void ProcessTracker::SetProcessNameIfUnset(UniquePid upid,
-                                           StringId process_name_id) {
-  TraceStorage::Process* process = context_->storage->GetMutableProcess(upid);
-  if (process->name_id == kNullStringId)
-    process->name_id = process_name_id;
-}
-
-void ProcessTracker::UpdateProcessNameFromThreadName(uint32_t tid,
-                                                     StringId thread_name) {
-  auto utid = GetOrCreateThread(tid);
-  TraceStorage::Thread* thread = context_->storage->GetMutableThread(utid);
-  if (thread->upid.has_value()) {
-    auto* process = context_->storage->GetMutableProcess(thread->upid.value());
-    if (process->pid == tid) {
-      process->name_id = thread_name;
-    }
-  }
-}
-
 UniquePid ProcessTracker::GetOrCreateProcess(uint32_t pid) {
   return GetOrCreateProcessPtr(pid).first;
 }
@@ -276,29 +206,6 @@
   while (!resolved_utids.empty()) {
     UniqueTid utid = resolved_utids.back();
     resolved_utids.pop_back();
-    for (auto it = pending_parent_assocs_.begin();
-         it != pending_parent_assocs_.end();) {
-      UniqueTid parent_utid = it->first;
-      UniquePid child_upid = it->second;
-
-      if (parent_utid != utid) {
-        ++it;
-        continue;
-      }
-      PERFETTO_DCHECK(child_upid != upid);
-
-      // Set the parent pid of the other process
-      auto* child_proc = context_->storage->GetMutableProcess(child_upid);
-      PERFETTO_DCHECK(!child_proc->parent_upid ||
-                      child_proc->parent_upid == upid);
-      child_proc->parent_upid = upid;
-
-      // Erase the pair. The |pending_parent_assocs_| vector is not sorted and
-      // swapping a std::pair<uint32_t, uint32_t> is cheap.
-      std::swap(*it, pending_parent_assocs_.back());
-      pending_parent_assocs_.pop_back();
-    }
-
     for (auto it = pending_assocs_.begin(); it != pending_assocs_.end();) {
       UniqueTid other_utid;
       if (it->first == utid) {
diff --git a/src/trace_processor/process_tracker.h b/src/trace_processor/process_tracker.h
index 7c7ea55..ee064c9 100644
--- a/src/trace_processor/process_tracker.h
+++ b/src/trace_processor/process_tracker.h
@@ -19,7 +19,7 @@
 
 #include <tuple>
 
-#include "perfetto/ext/base/string_view.h"
+#include "perfetto/base/string_view.h"
 #include "src/trace_processor/trace_processor_context.h"
 #include "src/trace_processor/trace_storage.h"
 
@@ -53,24 +53,13 @@
                            uint32_t tid,
                            StringId thread_name_id);
 
-  // Called when sched_process_exit is observed. This forces the tracker to
-  // end the thread lifetime for the utid associated with the given tid.
-  void EndThread(int64_t timestamp, uint32_t tid);
-
-  // Returns the thread utid or base::nullopt if it doesn't exist.
-  base::Optional<UniqueTid> GetThreadOrNull(uint32_t tid);
-
   // Returns the thread utid (or creates a new entry if not present)
   UniqueTid GetOrCreateThread(uint32_t tid);
 
   // Called when a sched switch event is seen in the trace. Retrieves the
   // UniqueTid that matches the tid or assigns a new UniqueTid and stores
   // the thread_name_id.
-  virtual UniqueTid UpdateThreadName(uint32_t tid, StringId thread_name_id);
-
-  // Assigns the given name to the thread identified |utid| if it does not have
-  // a name yet.
-  virtual void SetThreadNameIfUnset(UniqueTid utid, StringId thread_name_id);
+  UniqueTid UpdateThreadName(uint32_t tid, StringId thread_name_id);
 
   // Called when a thread is seen the process tree. Retrieves the matching utid
   // for the tid and the matching upid for the tgid and stores both.
@@ -79,25 +68,14 @@
 
   // Called when a task_newtask without the CLONE_THREAD flag is observed.
   // This force the tracker to start both a new UTID and a new UPID.
-  UniquePid StartNewProcess(int64_t timestamp,
-                            uint32_t parent_tid,
-                            uint32_t pid,
-                            StringId main_thread_name);
+  UniquePid StartNewProcess(int64_t timestamp, uint32_t pid);
 
   // Called when a process is seen in a process tree. Retrieves the UniquePid
   // for that pid or assigns a new one.
   // Virtual for testing.
-  virtual UniquePid SetProcessMetadata(uint32_t pid,
-                                       base::Optional<uint32_t> ppid,
-                                       base::StringView name);
-
-  // Assigns the given name to the process identified by |upid| if it does not
-  // have a name yet.
-  void SetProcessNameIfUnset(UniquePid upid, StringId process_name_id);
-
-  // Called on a task rename event to set the process name if the tid provided
-  // is the main thread of the process.
-  void UpdateProcessNameFromThreadName(uint32_t tid, StringId thread_name);
+  virtual UniquePid UpdateProcess(uint32_t pid,
+                                  base::Optional<uint32_t> ppid,
+                                  base::StringView name);
 
   // Called when a process is seen in a process tree. Retrieves the UniquePid
   // for that pid or assigns a new one.
@@ -146,11 +124,6 @@
   // don't know yet which process. A and A are idempotent, as in, pair<A,B> is
   // equivalent to pair<B,A>.
   std::vector<std::pair<UniqueTid, UniqueTid>> pending_assocs_;
-
-  // Pending parent process associations. The meaning of pair<ThreadA, ProcessB>
-  // in this vector is: we know that A created process B but we don't know the
-  // process of A. That is, we don't know the parent *process* of B.
-  std::vector<std::pair<UniqueTid, UniquePid>> pending_parent_assocs_;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/process_tracker_unittest.cc b/src/trace_processor/process_tracker_unittest.cc
index 492c049..0402b21 100644
--- a/src/trace_processor/process_tracker_unittest.cc
+++ b/src/trace_processor/process_tracker_unittest.cc
@@ -16,11 +16,11 @@
 
 #include "src/trace_processor/process_tracker.h"
 
-#include "perfetto/base/logging.h"
 #include "src/trace_processor/args_tracker.h"
 #include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
-#include "test/gtest_and_gmock.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -37,9 +37,6 @@
     context.args_tracker.reset(new ArgsTracker(&context));
     context.process_tracker.reset(new ProcessTracker(&context));
     context.event_tracker.reset(new EventTracker(&context));
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-    context.sched_tracker.reset(new SchedEventTracker(&context));
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
   }
 
  protected:
@@ -48,9 +45,9 @@
 
 TEST_F(ProcessTrackerTest, PushProcess) {
   TraceStorage storage;
-  context.process_tracker->SetProcessMetadata(1, base::nullopt, "test");
+  context.process_tracker->UpdateProcess(1, base::nullopt, "test");
   auto pair_it = context.process_tracker->UpidsForPid(1);
-  ASSERT_EQ(pair_it.first->second, 1u);
+  ASSERT_EQ(pair_it.first->second, 1);
 }
 
 TEST_F(ProcessTrackerTest, GetOrCreateNewProcess) {
@@ -61,35 +58,34 @@
 
 TEST_F(ProcessTrackerTest, StartNewProcess) {
   TraceStorage storage;
-  auto upid = context.process_tracker->StartNewProcess(1000, 0, 123, 0);
+  auto upid = context.process_tracker->StartNewProcess(1000, 123);
   ASSERT_EQ(context.process_tracker->GetOrCreateProcess(123), upid);
   ASSERT_EQ(context.storage->GetProcess(upid).start_ns, 1000);
 }
 
 TEST_F(ProcessTrackerTest, PushTwoProcessEntries_SamePidAndName) {
-  context.process_tracker->SetProcessMetadata(1, base::nullopt, "test");
-  context.process_tracker->SetProcessMetadata(1, base::nullopt, "test");
+  context.process_tracker->UpdateProcess(1, base::nullopt, "test");
+  context.process_tracker->UpdateProcess(1, base::nullopt, "test");
   auto pair_it = context.process_tracker->UpidsForPid(1);
-  ASSERT_EQ(pair_it.first->second, 1u);
+  ASSERT_EQ(pair_it.first->second, 1);
   ASSERT_EQ(++pair_it.first, pair_it.second);
 }
 
 TEST_F(ProcessTrackerTest, PushTwoProcessEntries_DifferentPid) {
-  context.process_tracker->SetProcessMetadata(1, base::nullopt, "test");
-  context.process_tracker->SetProcessMetadata(3, base::nullopt, "test");
+  context.process_tracker->UpdateProcess(1, base::nullopt, "test");
+  context.process_tracker->UpdateProcess(3, base::nullopt, "test");
   auto pair_it = context.process_tracker->UpidsForPid(1);
-  ASSERT_EQ(pair_it.first->second, 1u);
+  ASSERT_EQ(pair_it.first->second, 1);
   auto second_pair_it = context.process_tracker->UpidsForPid(3);
-  ASSERT_EQ(second_pair_it.first->second, 2u);
+  ASSERT_EQ(second_pair_it.first->second, 2);
 }
 
 TEST_F(ProcessTrackerTest, AddProcessEntry_CorrectName) {
-  context.process_tracker->SetProcessMetadata(1, base::nullopt, "test");
+  context.process_tracker->UpdateProcess(1, base::nullopt, "test");
   ASSERT_EQ(context.storage->GetString(context.storage->GetProcess(1).name_id),
             "test");
 }
 
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
 TEST_F(ProcessTrackerTest, UpdateThreadMatch) {
   uint32_t cpu = 3;
   int64_t timestamp = 100;
@@ -98,25 +94,24 @@
   static const char kCommProc2[] = "process2";
   int32_t prio = 1024;
 
-  context.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1, kCommProc2,
+  context.event_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1, kCommProc2,
                                          prio, prev_state,
                                          /*tid=*/4, kCommProc1, prio);
-  context.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
+  context.event_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
                                          kCommProc1, prio, prev_state,
                                          /*tid=*/1, kCommProc2, prio);
 
-  context.process_tracker->SetProcessMetadata(2, base::nullopt, "test");
+  context.process_tracker->UpdateProcess(2, base::nullopt, "test");
   context.process_tracker->UpdateThread(4, 2);
 
   TraceStorage::Thread thread = context.storage->GetThread(/*utid=*/1);
   TraceStorage::Process process = context.storage->GetProcess(/*utid=*/1);
 
-  ASSERT_EQ(thread.tid, 4u);
-  ASSERT_EQ(thread.upid.value(), 1u);
-  ASSERT_EQ(process.pid, 2u);
+  ASSERT_EQ(thread.tid, 4);
+  ASSERT_EQ(thread.upid.value(), 1);
+  ASSERT_EQ(process.pid, 2);
   ASSERT_EQ(process.start_ns, 0);
 }
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
 
 TEST_F(ProcessTrackerTest, UpdateThreadCreate) {
   context.process_tracker->UpdateThread(12, 2);
@@ -124,14 +119,14 @@
   TraceStorage::Thread thread = context.storage->GetThread(1);
 
   // We expect 3 threads: Invalid thread, main thread for pid, tid 12.
-  ASSERT_EQ(context.storage->thread_count(), 3u);
+  ASSERT_EQ(context.storage->thread_count(), 3);
 
   auto tid_it = context.process_tracker->UtidsForTid(12);
   ASSERT_NE(tid_it.first, tid_it.second);
-  ASSERT_EQ(thread.upid.value(), 1u);
+  ASSERT_EQ(thread.upid.value(), 1);
   auto pid_it = context.process_tracker->UpidsForPid(2);
   ASSERT_NE(pid_it.first, pid_it.second);
-  ASSERT_EQ(context.storage->process_count(), 2u);
+  ASSERT_EQ(context.storage->process_count(), 2);
 }
 
 }  // namespace
diff --git a/src/trace_processor/proto_incremental_state.h b/src/trace_processor/proto_incremental_state.h
new file mode 100644
index 0000000..e407985
--- /dev/null
+++ b/src/trace_processor/proto_incremental_state.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_PROTO_INCREMENTAL_STATE_H_
+#define SRC_TRACE_PROCESSOR_PROTO_INCREMENTAL_STATE_H_
+
+#include <stdint.h>
+
+#include <map>
+#include <unordered_map>
+
+#include "perfetto/base/optional.h"
+#include "perfetto/protozero/proto_decoder.h"
+#include "src/trace_processor/trace_blob_view.h"
+#include "src/trace_processor/trace_storage.h"
+
+#include "perfetto/trace/track_event/debug_annotation.pbzero.h"
+#include "perfetto/trace/track_event/task_execution.pbzero.h"
+#include "perfetto/trace/track_event/track_event.pbzero.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+// Specialization of member types is forbidden inside their parent class, so
+// define the StorageReferences class outside in an internal namespace.
+namespace proto_incremental_state_internal {
+
+template <typename MessageType>
+struct StorageReferences;
+
+template <>
+struct StorageReferences<protos::pbzero::EventCategory> {
+  StringId name_id;
+};
+
+template <>
+struct StorageReferences<protos::pbzero::LegacyEventName> {
+  StringId name_id;
+};
+
+template <>
+struct StorageReferences<protos::pbzero::DebugAnnotationName> {
+  StringId name_id;
+};
+
+template <>
+struct StorageReferences<protos::pbzero::SourceLocation> {
+  StringId file_name_id;
+  StringId function_name_id;
+};
+
+}  // namespace proto_incremental_state_internal
+
+// Stores per-packet-sequence incremental state during trace parsing, such as
+// reference timestamps for delta timestamp calculation and interned messages.
+class ProtoIncrementalState {
+ public:
+  template <typename MessageType>
+  using StorageReferences =
+      proto_incremental_state_internal::StorageReferences<MessageType>;
+
+  // Entry in an interning index, refers to the interned message.
+  template <typename MessageType>
+  struct InternedDataView {
+    InternedDataView(TraceBlobView msg) : message(std::move(msg)) {}
+
+    typename MessageType::Decoder CreateDecoder() {
+      return typename MessageType::Decoder(message.data(), message.length());
+    }
+
+    TraceBlobView message;
+
+    // If the data in this entry was already stored into the trace storage, this
+    // field contains message-type-specific references into the storage which
+    // can be used to look up the entry's data (e.g. indexes of interned
+    // strings).
+    base::Optional<StorageReferences<MessageType>> storage_refs;
+  };
+
+  template <typename MessageType>
+  using InternedDataMap =
+      std::unordered_map<uint32_t, InternedDataView<MessageType>>;
+
+  class PacketSequenceState {
+   public:
+    int64_t IncrementAndGetTrackEventTimeNs(int64_t delta_ns) {
+      PERFETTO_DCHECK(IsTrackEventStateValid());
+      track_event_timestamp_ns_ += delta_ns;
+      return track_event_timestamp_ns_;
+    }
+
+    int64_t IncrementAndGetTrackEventThreadTimeNs(int64_t delta_ns) {
+      PERFETTO_DCHECK(IsTrackEventStateValid());
+      track_event_thread_timestamp_ns_ += delta_ns;
+      return track_event_thread_timestamp_ns_;
+    }
+
+    void OnPacketLoss() {
+      packet_loss_ = true;
+      thread_descriptor_seen_ = false;
+    }
+
+    void OnIncrementalStateCleared() { packet_loss_ = false; }
+
+    void SetThreadDescriptor(int32_t pid,
+                             int32_t tid,
+                             int64_t timestamp_ns,
+                             int64_t thread_timestamp_ns) {
+      thread_descriptor_seen_ = true;
+      pid_ = pid;
+      tid_ = tid;
+      track_event_timestamp_ns_ = timestamp_ns;
+      track_event_thread_timestamp_ns_ = thread_timestamp_ns;
+    }
+
+    bool IsIncrementalStateValid() const { return !packet_loss_; }
+
+    bool IsTrackEventStateValid() const {
+      return IsIncrementalStateValid() && thread_descriptor_seen_;
+    }
+
+    int32_t pid() const { return pid_; }
+    int32_t tid() const { return tid_; }
+
+    template <typename MessageType>
+    InternedDataMap<MessageType>* GetInternedDataMap();
+
+   private:
+    // If true, incremental state on the sequence is considered invalid until we
+    // see the next packet with incremental_state_cleared. We assume that we
+    // missed some packets at the beginning of the trace.
+    bool packet_loss_ = true;
+
+    // We can only consider TrackEvent delta timestamps to be correct after we
+    // have observed a thread descriptor (since the last packet loss).
+    bool thread_descriptor_seen_ = false;
+
+    // Process/thread ID of the packet sequence. Used as default values for
+    // TrackEvents that don't specify a pid/tid override. Only valid while
+    // |seen_thread_descriptor_| is true.
+    int32_t pid_ = 0;
+    int32_t tid_ = 0;
+
+    // Current wall/thread timestamps used as reference for the next TrackEvent
+    // delta timestamp.
+    int64_t track_event_timestamp_ns_ = 0;
+    int64_t track_event_thread_timestamp_ns_ = 0;
+
+    InternedDataMap<protos::pbzero::EventCategory> event_categories_;
+    InternedDataMap<protos::pbzero::LegacyEventName> legacy_event_names_;
+    InternedDataMap<protos::pbzero::DebugAnnotationName>
+        debug_annotation_names_;
+    InternedDataMap<protos::pbzero::SourceLocation> source_locations_;
+  };
+
+  // Returns the PacketSequenceState for the packet sequence with the given id.
+  // If this is a new sequence which we haven't tracked before, initializes and
+  // inserts a new PacketSequenceState into the state map.
+  PacketSequenceState* GetOrCreateStateForPacketSequence(uint32_t sequence_id) {
+    auto& ptr = packet_sequence_states_[sequence_id];
+    if (!ptr)
+      ptr.reset(new PacketSequenceState());
+    return ptr.get();
+  }
+
+ private:
+  // Stores unique_ptrs to ensure that pointers to a PacketSequenceState remain
+  // valid even if the map rehashes.
+  std::map<uint32_t, std::unique_ptr<PacketSequenceState>>
+      packet_sequence_states_;
+};
+
+template <>
+inline ProtoIncrementalState::InternedDataMap<protos::pbzero::EventCategory>*
+ProtoIncrementalState::PacketSequenceState::GetInternedDataMap<
+    protos::pbzero::EventCategory>() {
+  return &event_categories_;
+}
+
+template <>
+inline ProtoIncrementalState::InternedDataMap<protos::pbzero::LegacyEventName>*
+ProtoIncrementalState::PacketSequenceState::GetInternedDataMap<
+    protos::pbzero::LegacyEventName>() {
+  return &legacy_event_names_;
+}
+
+template <>
+inline ProtoIncrementalState::InternedDataMap<
+    protos::pbzero::DebugAnnotationName>*
+ProtoIncrementalState::PacketSequenceState::GetInternedDataMap<
+    protos::pbzero::DebugAnnotationName>() {
+  return &debug_annotation_names_;
+}
+
+template <>
+inline ProtoIncrementalState::InternedDataMap<protos::pbzero::SourceLocation>*
+ProtoIncrementalState::PacketSequenceState::GetInternedDataMap<
+    protos::pbzero::SourceLocation>() {
+  return &source_locations_;
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_PROTO_INCREMENTAL_STATE_H_
diff --git a/src/trace_processor/proto_to_json.cc b/src/trace_processor/proto_to_json.cc
deleted file mode 100644
index 5b07889..0000000
--- a/src/trace_processor/proto_to_json.cc
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * 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.
- */
-
-#include <google/protobuf/message.h>
-
-#include "perfetto/base/logging.h"
-#include "src/trace_processor/proto_to_json.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace proto_to_json {
-
-namespace {
-
-std::string EscapeJsonString(const std::string& raw) {
-  std::string ret;
-  for (auto it = raw.cbegin(); it != raw.cend(); it++) {
-    switch (*it) {
-      case '\\':
-        ret += "\\\\";
-        break;
-      case '"':
-        ret += "\\\"";
-        break;
-      case '/':
-        ret += "\\/";
-        break;
-      case '\b':
-        ret += "\\b";
-        break;
-      case '\f':
-        ret += "\\f";
-        break;
-      case '\n':
-        ret += "\\n";
-        break;
-      case '\r':
-        ret += "\\r";
-        break;
-      case '\t':
-        ret += "\\t";
-        break;
-      default:
-        ret += *it;
-        break;
-    }
-  }
-  return '"' + ret + '"';
-}
-
-std::string FieldToJson(const google::protobuf::Message& message,
-                        const google::protobuf::FieldDescriptor* field_desc,
-                        int idx,
-                        uint32_t indent) {
-  using google::protobuf::FieldDescriptor;
-
-  const google::protobuf::Reflection* ref = message.GetReflection();
-  bool is_repeated = field_desc->is_repeated();
-  switch (field_desc->cpp_type()) {
-    case FieldDescriptor::CppType::CPPTYPE_BOOL:
-      return std::to_string(is_repeated
-                                ? ref->GetRepeatedBool(message, field_desc, idx)
-                                : ref->GetBool(message, field_desc));
-    case FieldDescriptor::CppType::CPPTYPE_ENUM:
-      return EscapeJsonString(
-          is_repeated ? ref->GetRepeatedEnum(message, field_desc, idx)->name()
-                      : ref->GetEnum(message, field_desc)->name());
-    case FieldDescriptor::CppType::CPPTYPE_FLOAT:
-      return std::to_string(
-          is_repeated
-              ? static_cast<double>(
-                    ref->GetRepeatedFloat(message, field_desc, idx))
-              : static_cast<double>(ref->GetFloat(message, field_desc)));
-    case FieldDescriptor::CppType::CPPTYPE_INT32:
-      return std::to_string(
-          is_repeated ? ref->GetRepeatedInt32(message, field_desc, idx)
-                      : ref->GetInt32(message, field_desc));
-    case FieldDescriptor::CppType::CPPTYPE_INT64:
-      return std::to_string(
-          is_repeated ? ref->GetRepeatedInt64(message, field_desc, idx)
-                      : ref->GetInt64(message, field_desc));
-    case FieldDescriptor::CppType::CPPTYPE_DOUBLE:
-      return std::to_string(
-          is_repeated ? ref->GetRepeatedDouble(message, field_desc, idx)
-                      : ref->GetDouble(message, field_desc));
-    case FieldDescriptor::CppType::CPPTYPE_STRING:
-      return EscapeJsonString(
-          is_repeated ? ref->GetRepeatedString(message, field_desc, idx)
-                      : ref->GetString(message, field_desc));
-    case FieldDescriptor::CppType::CPPTYPE_UINT32:
-      return std::to_string(
-          is_repeated ? ref->GetRepeatedUInt32(message, field_desc, idx)
-                      : ref->GetUInt32(message, field_desc));
-    case FieldDescriptor::CppType::CPPTYPE_UINT64:
-      return std::to_string(
-          is_repeated ? ref->GetRepeatedInt64(message, field_desc, idx)
-                      : ref->GetInt64(message, field_desc));
-    case FieldDescriptor::CppType::CPPTYPE_MESSAGE:
-      return MessageToJson(
-          is_repeated ? ref->GetRepeatedMessage(message, field_desc, idx)
-                      : ref->GetMessage(message, field_desc),
-          indent);
-  }
-  PERFETTO_FATAL("For GCC");
-}
-
-std::string RepeatedFieldValuesToJson(
-    const google::protobuf::Message& message,
-    const google::protobuf::FieldDescriptor* field_desc,
-    uint32_t indent) {
-  const google::protobuf::Reflection* ref = message.GetReflection();
-  std::string ret;
-  for (int i = 0; i < ref->FieldSize(message, field_desc); ++i) {
-    if (i != 0) {
-      ret += ",";
-    }
-    ret += "\n" + std::string(indent, ' ') +
-           FieldToJson(message, field_desc, i, indent);
-  }
-  return ret;
-}
-
-std::string MessageFieldsToJson(const google::protobuf::Message& message,
-                                uint32_t indent) {
-  const google::protobuf::Reflection* ref = message.GetReflection();
-  std::vector<const google::protobuf::FieldDescriptor*> field_descs;
-  ref->ListFields(message, &field_descs);
-
-  std::string ret;
-  uint32_t next_field_idx = 0;
-  for (const google::protobuf::FieldDescriptor* field_desc : field_descs) {
-    if (next_field_idx++ != 0) {
-      ret += ",";
-    }
-    std::string value;
-    if (field_desc->is_repeated()) {
-      value = "[" + RepeatedFieldValuesToJson(message, field_desc, indent + 2) +
-              "\n" + std::string(indent, ' ') + "]";
-    } else {
-      value = FieldToJson(message, field_desc, 0, indent);
-    }
-    const std::string& name = field_desc->is_extension()
-                                  ? field_desc->full_name()
-                                  : field_desc->name();
-    ret += "\n" + std::string(indent, ' ') + "\"" + name + "\": " + value;
-  }
-  return ret;
-}
-
-}  // namespace
-
-std::string MessageToJson(const google::protobuf::Message& message,
-                          uint32_t indent) {
-  return "{" + MessageFieldsToJson(message, indent + 2) + "\n" +
-         std::string(indent, ' ') + "}";
-}
-
-}  // namespace proto_to_json
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/proto_to_json.h b/src/trace_processor/proto_to_json.h
deleted file mode 100644
index f46f4c1..0000000
--- a/src/trace_processor/proto_to_json.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_PROTO_TO_JSON_H_
-#define SRC_TRACE_PROCESSOR_PROTO_TO_JSON_H_
-
-#include <google/protobuf/message.h>
-
-namespace perfetto {
-namespace trace_processor {
-namespace proto_to_json {
-
-std::string MessageToJson(const google::protobuf::Message& message,
-                          uint32_t indent = 0);
-
-}  // namespace proto_to_json
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_PROTO_TO_JSON_H_
diff --git a/src/trace_processor/proto_trace_parser.cc b/src/trace_processor/proto_trace_parser.cc
new file mode 100644
index 0000000..fed87e6
--- /dev/null
+++ b/src/trace_processor/proto_trace_parser.cc
@@ -0,0 +1,1559 @@
+/*
+ * 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.
+ */
+
+#include "src/trace_processor/proto_trace_parser.h"
+
+#include <inttypes.h>
+#include <string.h>
+
+#include <string>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/base/optional.h"
+#include "perfetto/base/string_view.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/protozero/proto_decoder.h"
+#include "perfetto/traced/sys_stats_counters.h"
+#include "src/trace_processor/args_tracker.h"
+#include "src/trace_processor/clock_tracker.h"
+#include "src/trace_processor/event_tracker.h"
+#include "src/trace_processor/ftrace_descriptors.h"
+#include "src/trace_processor/heap_profile_tracker.h"
+#include "src/trace_processor/process_tracker.h"
+#include "src/trace_processor/slice_tracker.h"
+#include "src/trace_processor/syscall_tracker.h"
+#include "src/trace_processor/trace_processor_context.h"
+
+#include "perfetto/common/android_log_constants.pbzero.h"
+#include "perfetto/common/trace_stats.pbzero.h"
+#include "perfetto/trace/android/android_log.pbzero.h"
+#include "perfetto/trace/clock_snapshot.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace_event.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace_stats.pbzero.h"
+#include "perfetto/trace/ftrace/generic.pbzero.h"
+#include "perfetto/trace/ftrace/kmem.pbzero.h"
+#include "perfetto/trace/ftrace/lowmemorykiller.pbzero.h"
+#include "perfetto/trace/ftrace/mm_event.pbzero.h"
+#include "perfetto/trace/ftrace/oom.pbzero.h"
+#include "perfetto/trace/ftrace/power.pbzero.h"
+#include "perfetto/trace/ftrace/raw_syscalls.pbzero.h"
+#include "perfetto/trace/ftrace/sched.pbzero.h"
+#include "perfetto/trace/ftrace/signal.pbzero.h"
+#include "perfetto/trace/ftrace/task.pbzero.h"
+#include "perfetto/trace/interned_data/interned_data.pbzero.h"
+#include "perfetto/trace/power/battery_counters.pbzero.h"
+#include "perfetto/trace/power/power_rails.pbzero.h"
+#include "perfetto/trace/profiling/profile_packet.pbzero.h"
+#include "perfetto/trace/ps/process_stats.pbzero.h"
+#include "perfetto/trace/ps/process_tree.pbzero.h"
+#include "perfetto/trace/sys_stats/sys_stats.pbzero.h"
+#include "perfetto/trace/system_info.pbzero.h"
+#include "perfetto/trace/trace.pbzero.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/track_event/debug_annotation.pbzero.h"
+#include "perfetto/trace/track_event/task_execution.pbzero.h"
+#include "perfetto/trace/track_event/track_event.pbzero.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+namespace {
+
+using protozero::ProtoDecoder;
+using Variadic = TraceStorage::Args::Variadic;
+
+}  // namespace
+
+// We have to handle trace_marker events of a few different types:
+// 1. some random text
+// 2. B|1636|pokeUserActivity
+// 3. E|1636
+// 4. C|1636|wq:monitor|0
+SystraceParseResult ParseSystraceTracePoint(base::StringView str,
+                                            SystraceTracePoint* out) {
+  // THIS char* IS NOT NULL TERMINATED.
+  const char* s = str.data();
+  size_t len = str.size();
+
+  if (len < 2)
+    return SystraceParseResult::kFailure;
+
+  // If str matches '[BEC]\|[0-9]+[\|\n]' set tgid_length to the length of
+  // the number. Otherwise return kFailure.
+  if (s[1] != '|' && s[1] != '\n')
+    return SystraceParseResult::kFailure;
+  if (s[0] != 'B' && s[0] != 'E' && s[0] != 'C') {
+    // TODO: support android async slices
+    return s[0] == 'S' || s[0] == 'F' ? SystraceParseResult::kUnsupported
+                                      : SystraceParseResult::kFailure;
+  }
+  size_t tgid_length = 0;
+  for (size_t i = 2; i < len; i++) {
+    if (s[i] == '|' || s[i] == '\n') {
+      tgid_length = i - 2;
+      break;
+    }
+    if (s[i] < '0' || s[i] > '9')
+      return SystraceParseResult::kFailure;
+  }
+
+  if (tgid_length == 0) {
+    out->tgid = 0;
+  } else {
+    std::string tgid_str(s + 2, tgid_length);
+    out->tgid = static_cast<uint32_t>(std::stoi(tgid_str.c_str()));
+  }
+
+  out->phase = s[0];
+  switch (s[0]) {
+    case 'B': {
+      size_t name_index = 2 + tgid_length + 1;
+      out->name = base::StringView(
+          s + name_index, len - name_index - (s[len - 1] == '\n' ? 1 : 0));
+      return SystraceParseResult::kSuccess;
+    }
+    case 'E': {
+      return SystraceParseResult::kSuccess;
+    }
+    case 'C': {
+      size_t name_index = 2 + tgid_length + 1;
+      size_t name_length = 0;
+      for (size_t i = name_index; i < len; i++) {
+        if (s[i] == '|' || s[i] == '\n') {
+          name_length = i - name_index;
+          break;
+        }
+      }
+      out->name = base::StringView(s + name_index, name_length);
+
+      size_t value_index = name_index + name_length + 1;
+      size_t value_len = len - value_index;
+      char value_str[32];
+      if (value_len >= sizeof(value_str)) {
+        return SystraceParseResult::kFailure;
+      }
+      memcpy(value_str, s + value_index, value_len);
+      value_str[value_len] = 0;
+      out->value = std::stod(value_str);
+      return SystraceParseResult::kSuccess;
+    }
+    default:
+      return SystraceParseResult::kFailure;
+  }
+}
+
+ProtoTraceParser::ProtoTraceParser(TraceProcessorContext* context)
+    : context_(context),
+      utid_name_id_(context->storage->InternString("utid")),
+      sched_wakeup_name_id_(context->storage->InternString("sched_wakeup")),
+      cpu_freq_name_id_(context->storage->InternString("cpufreq")),
+      cpu_idle_name_id_(context->storage->InternString("cpuidle")),
+      comm_name_id_(context->storage->InternString("comm")),
+      num_forks_name_id_(context->storage->InternString("num_forks")),
+      num_irq_total_name_id_(context->storage->InternString("num_irq_total")),
+      num_softirq_total_name_id_(
+          context->storage->InternString("num_softirq_total")),
+      num_irq_name_id_(context->storage->InternString("num_irq")),
+      num_softirq_name_id_(context->storage->InternString("num_softirq")),
+      cpu_times_user_ns_id_(
+          context->storage->InternString("cpu.times.user_ns")),
+      cpu_times_user_nice_ns_id_(
+          context->storage->InternString("cpu.times.user_nice_ns")),
+      cpu_times_system_mode_ns_id_(
+          context->storage->InternString("cpu.times.system_mode_ns")),
+      cpu_times_idle_ns_id_(
+          context->storage->InternString("cpu.times.idle_ns")),
+      cpu_times_io_wait_ns_id_(
+          context->storage->InternString("cpu.times.io_wait_ns")),
+      cpu_times_irq_ns_id_(context->storage->InternString("cpu.times.irq_ns")),
+      cpu_times_softirq_ns_id_(
+          context->storage->InternString("cpu.times.softirq_ns")),
+      signal_deliver_id_(context->storage->InternString("signal_deliver")),
+      signal_generate_id_(context->storage->InternString("signal_generate")),
+      batt_charge_id_(context->storage->InternString("batt.charge_uah")),
+      batt_capacity_id_(context->storage->InternString("batt.capacity_pct")),
+      batt_current_id_(context->storage->InternString("batt.current_ua")),
+      batt_current_avg_id_(
+          context->storage->InternString("batt.current.avg_ua")),
+      lmk_id_(context->storage->InternString("mem.lmk")),
+      oom_score_adj_id_(context->storage->InternString("oom_score_adj")),
+      ion_total_unknown_id_(context->storage->InternString("mem.ion.unknown")),
+      ion_change_unknown_id_(
+          context->storage->InternString("mem.ion_change.unknown")) {
+  for (const auto& name : BuildMeminfoCounterNames()) {
+    meminfo_strs_id_.emplace_back(context->storage->InternString(name));
+  }
+  for (const auto& name : BuildVmstatCounterNames()) {
+    vmstat_strs_id_.emplace_back(context->storage->InternString(name));
+  }
+  rss_members_.emplace_back(context->storage->InternString("mem.rss.file"));
+  rss_members_.emplace_back(context->storage->InternString("mem.rss.anon"));
+  rss_members_.emplace_back(context->storage->InternString("mem.swap"));
+  rss_members_.emplace_back(context->storage->InternString("mem.rss.shmem"));
+  rss_members_.emplace_back(
+      context->storage->InternString("mem.rss.unknown"));  // Keep this last.
+
+  using ProcessStats = protos::pbzero::ProcessStats;
+  proc_stats_process_names_[ProcessStats::Process::kVmSizeKbFieldNumber] =
+      context->storage->InternString("mem.virt");
+  proc_stats_process_names_[ProcessStats::Process::kVmRssKbFieldNumber] =
+      context->storage->InternString("mem.rss");
+  proc_stats_process_names_[ProcessStats::Process::kRssAnonKbFieldNumber] =
+      context->storage->InternString("mem.rss.anon");
+  proc_stats_process_names_[ProcessStats::Process::kRssFileKbFieldNumber] =
+      context->storage->InternString("mem.rss.file");
+  proc_stats_process_names_[ProcessStats::Process::kRssShmemKbFieldNumber] =
+      context->storage->InternString("mem.rss.shmem");
+  proc_stats_process_names_[ProcessStats::Process::kVmSwapKbFieldNumber] =
+      context->storage->InternString("mem.swap");
+  proc_stats_process_names_[ProcessStats::Process::kVmLockedKbFieldNumber] =
+      context->storage->InternString("mem.locked");
+  proc_stats_process_names_[ProcessStats::Process::kVmHwmKbFieldNumber] =
+      context->storage->InternString("mem.rss.watermark");
+  proc_stats_process_names_[ProcessStats::Process::kOomScoreAdjFieldNumber] =
+      oom_score_adj_id_;
+
+  mm_event_counter_names_ = {
+      {MmEventCounterNames(
+           context->storage->InternString("mem.mm.min_flt.count"),
+           context->storage->InternString("mem.mm.min_flt.max_lat"),
+           context->storage->InternString("mem.mm.min_flt.avg_lat")),
+       MmEventCounterNames(
+           context->storage->InternString("mem.mm.maj_flt.count"),
+           context->storage->InternString("mem.mm.maj_flt.max_lat"),
+           context->storage->InternString("mem.mm.maj_flt.avg_lat")),
+       MmEventCounterNames(
+           context->storage->InternString("mem.mm.read_io.count"),
+           context->storage->InternString("mem.mm.read_io.max_lat"),
+           context->storage->InternString("mem.mm.read_io.avg_lat")),
+       MmEventCounterNames(
+           context->storage->InternString("mem.mm.compaction.count"),
+           context->storage->InternString("mem.mm.compaction.max_lat"),
+           context->storage->InternString("mem.mm.compaction.avg_lat")),
+       MmEventCounterNames(
+           context->storage->InternString("mem.mm.reclaim.count"),
+           context->storage->InternString("mem.mm.reclaim.max_lat"),
+           context->storage->InternString("mem.mm.reclaim.avg_lat")),
+       MmEventCounterNames(
+           context->storage->InternString("mem.mm.swp_flt.count"),
+           context->storage->InternString("mem.mm.swp_flt.max_lat"),
+           context->storage->InternString("mem.mm.swp_flt.avg_lat")),
+       MmEventCounterNames(
+           context->storage->InternString("mem.mm.kern_alloc.count"),
+           context->storage->InternString("mem.mm.kern_alloc.max_lat"),
+           context->storage->InternString("mem.mm.kern_alloc.avg_lat"))}};
+
+  // Build the lookup table for the strings inside ftrace events (e.g. the
+  // name of ftrace event fields and the names of their args).
+  for (size_t i = 0; i < GetDescriptorsSize(); i++) {
+    auto* descriptor = GetMessageDescriptorForId(i);
+    if (!descriptor->name) {
+      ftrace_message_strings_.emplace_back();
+      continue;
+    }
+
+    FtraceMessageStrings ftrace_strings;
+    ftrace_strings.message_name_id =
+        context->storage->InternString(descriptor->name);
+
+    for (size_t fid = 0; fid <= descriptor->max_field_id; fid++) {
+      const auto& field = descriptor->fields[fid];
+      if (!field.name)
+        continue;
+      ftrace_strings.field_name_ids[fid] =
+          context->storage->InternString(field.name);
+    }
+    ftrace_message_strings_.emplace_back(ftrace_strings);
+  }
+}
+
+ProtoTraceParser::~ProtoTraceParser() = default;
+
+void ProtoTraceParser::ParseTracePacket(
+    int64_t ts,
+    TraceSorter::TimestampedTracePiece ttp) {
+  PERFETTO_DCHECK(ttp.json_value == nullptr);
+  const TraceBlobView& blob = ttp.blob_view;
+
+  protos::pbzero::TracePacket::Decoder packet(blob.data(), blob.length());
+
+  if (packet.has_process_tree())
+    ParseProcessTree(packet.process_tree());
+
+  if (packet.has_process_stats())
+    ParseProcessStats(ts, packet.process_stats());
+
+  if (packet.has_sys_stats())
+    ParseSysStats(ts, packet.sys_stats());
+
+  if (packet.has_battery())
+    ParseBatteryCounters(ts, packet.battery());
+
+  if (packet.has_power_rails())
+    ParsePowerRails(packet.power_rails());
+
+  if (packet.has_trace_stats())
+    ParseTraceStats(packet.trace_stats());
+
+  if (packet.has_ftrace_stats())
+    ParseFtraceStats(packet.ftrace_stats());
+
+  if (packet.has_clock_snapshot())
+    ParseClockSnapshot(packet.clock_snapshot());
+
+  if (packet.has_android_log())
+    ParseAndroidLogPacket(packet.android_log());
+
+  if (packet.has_profile_packet())
+    ParseProfilePacket(packet.profile_packet());
+
+  if (packet.has_system_info())
+    ParseSystemInfo(packet.system_info());
+
+  if (packet.has_track_event()) {
+    ParseTrackEvent(ts, ttp.thread_timestamp, ttp.packet_sequence_state,
+                    packet.track_event());
+  }
+
+  // TODO(lalitm): maybe move this to the flush method in the trace processor
+  // once we have it. This may reduce performance in the ArgsTracker though so
+  // needs to be handled carefully.
+  context_->args_tracker->Flush();
+  PERFETTO_DCHECK(!packet.bytes_left());
+}
+
+void ProtoTraceParser::ParseSysStats(int64_t ts, ConstBytes blob) {
+  protos::pbzero::SysStats::Decoder sys_stats(blob.data, blob.size);
+
+  for (auto it = sys_stats.meminfo(); it; ++it) {
+    protos::pbzero::SysStats::MeminfoValue::Decoder mi(it->data(), it->size());
+    auto key = static_cast<size_t>(mi.key());
+    if (PERFETTO_UNLIKELY(key >= meminfo_strs_id_.size())) {
+      PERFETTO_ELOG("MemInfo key %zu is not recognized.", key);
+      context_->storage->IncrementStats(stats::meminfo_unknown_keys);
+      continue;
+    }
+    // /proc/meminfo counters are in kB, convert to bytes
+    context_->event_tracker->PushCounter(
+        ts, mi.value() * 1024L, meminfo_strs_id_[key], 0, RefType::kRefNoRef);
+  }
+
+  for (auto it = sys_stats.vmstat(); it; ++it) {
+    protos::pbzero::SysStats::VmstatValue::Decoder vm(it->data(), it->size());
+    auto key = static_cast<size_t>(vm.key());
+    if (PERFETTO_UNLIKELY(key >= vmstat_strs_id_.size())) {
+      PERFETTO_ELOG("VmStat key %zu is not recognized.", key);
+      context_->storage->IncrementStats(stats::vmstat_unknown_keys);
+      continue;
+    }
+    context_->event_tracker->PushCounter(ts, vm.value(), vmstat_strs_id_[key],
+                                         0, RefType::kRefNoRef);
+  }
+
+  for (auto it = sys_stats.cpu_stat(); it; ++it) {
+    protos::pbzero::SysStats::CpuTimes::Decoder ct(it->data(), it->size());
+    if (PERFETTO_UNLIKELY(!ct.has_cpu_id())) {
+      PERFETTO_ELOG("CPU field not found in CpuTimes");
+      context_->storage->IncrementStats(stats::invalid_cpu_times);
+      continue;
+    }
+    context_->event_tracker->PushCounter(ts, ct.user_ns(),
+                                         cpu_times_user_ns_id_, ct.cpu_id(),
+                                         RefType::kRefCpuId);
+    context_->event_tracker->PushCounter(ts, ct.user_ice_ns(),
+                                         cpu_times_user_nice_ns_id_,
+                                         ct.cpu_id(), RefType::kRefCpuId);
+    context_->event_tracker->PushCounter(ts, ct.system_mode_ns(),
+                                         cpu_times_system_mode_ns_id_,
+                                         ct.cpu_id(), RefType::kRefCpuId);
+    context_->event_tracker->PushCounter(ts, ct.idle_ns(),
+                                         cpu_times_idle_ns_id_, ct.cpu_id(),
+                                         RefType::kRefCpuId);
+    context_->event_tracker->PushCounter(ts, ct.io_wait_ns(),
+                                         cpu_times_io_wait_ns_id_, ct.cpu_id(),
+                                         RefType::kRefCpuId);
+    context_->event_tracker->PushCounter(ts, ct.irq_ns(), cpu_times_irq_ns_id_,
+                                         ct.cpu_id(), RefType::kRefCpuId);
+    context_->event_tracker->PushCounter(ts, ct.softirq_ns(),
+                                         cpu_times_softirq_ns_id_, ct.cpu_id(),
+                                         RefType::kRefCpuId);
+  }
+
+  for (auto it = sys_stats.num_irq(); it; ++it) {
+    protos::pbzero::SysStats::InterruptCount::Decoder ic(it->data(),
+                                                         it->size());
+    context_->event_tracker->PushCounter(ts, ic.count(), num_irq_name_id_,
+                                         ic.irq(), RefType::kRefIrq);
+  }
+
+  for (auto it = sys_stats.num_softirq(); it; ++it) {
+    protos::pbzero::SysStats::InterruptCount::Decoder ic(it->data(),
+                                                         it->size());
+    context_->event_tracker->PushCounter(ts, ic.count(), num_softirq_name_id_,
+                                         ic.irq(), RefType::kRefSoftIrq);
+  }
+
+  if (sys_stats.has_num_forks()) {
+    context_->event_tracker->PushCounter(
+        ts, sys_stats.num_forks(), num_forks_name_id_, 0, RefType::kRefNoRef);
+  }
+
+  if (sys_stats.has_num_irq_total()) {
+    context_->event_tracker->PushCounter(ts, sys_stats.num_irq_total(),
+                                         num_irq_total_name_id_, 0,
+                                         RefType::kRefNoRef);
+  }
+
+  if (sys_stats.has_num_softirq_total()) {
+    context_->event_tracker->PushCounter(ts, sys_stats.num_softirq_total(),
+                                         num_softirq_total_name_id_, 0,
+                                         RefType::kRefNoRef);
+  }
+}
+
+void ProtoTraceParser::ParseProcessTree(ConstBytes blob) {
+  protos::pbzero::ProcessTree::Decoder ps(blob.data, blob.size);
+
+  for (auto it = ps.processes(); it; ++it) {
+    protos::pbzero::ProcessTree::Process::Decoder proc(it->data(), it->size());
+    if (!proc.has_cmdline())
+      continue;
+    auto pid = static_cast<uint32_t>(proc.pid());
+    auto ppid = static_cast<uint32_t>(proc.ppid());
+
+    context_->process_tracker->UpdateProcess(pid, ppid,
+                                             proc.cmdline()->as_string());
+  }
+
+  for (auto it = ps.threads(); it; ++it) {
+    protos::pbzero::ProcessTree::Thread::Decoder thd(it->data(), it->size());
+    auto tid = static_cast<uint32_t>(thd.tid());
+    auto tgid = static_cast<uint32_t>(thd.tgid());
+    context_->process_tracker->UpdateThread(tid, tgid);
+  }
+}
+
+void ProtoTraceParser::ParseProcessStats(int64_t ts, ConstBytes blob) {
+  protos::pbzero::ProcessStats::Decoder stats(blob.data, blob.size);
+  const auto kOomScoreAdjFieldNumber =
+      protos::pbzero::ProcessStats::Process::kOomScoreAdjFieldNumber;
+  for (auto it = stats.processes(); it; ++it) {
+    // Maps a process counter field it to its value.
+    // E.g., 4 := 1024 -> "mem.rss.anon" := 1024.
+    std::array<int64_t, kProcStatsProcessSize> counter_values{};
+    std::array<bool, kProcStatsProcessSize> has_counter{};
+
+    ProtoDecoder proc(it->data(), it->size());
+    uint32_t pid = 0;
+    for (auto fld = proc.ReadField(); fld.valid(); fld = proc.ReadField()) {
+      if (fld.id() == protos::pbzero::ProcessStats::Process::kPidFieldNumber) {
+        pid = fld.as_uint32();
+        continue;
+      }
+      bool is_counter_field = fld.id() < proc_stats_process_names_.size() &&
+                              proc_stats_process_names_[fld.id()] != 0;
+      if (is_counter_field) {
+        // Memory counters are in KB, keep values in bytes in the trace
+        // processor.
+        counter_values[fld.id()] = fld.id() == kOomScoreAdjFieldNumber
+                                       ? fld.as_int64()
+                                       : fld.as_int64() * 1024;
+        has_counter[fld.id()] = true;
+      } else {
+        context_->storage->IncrementStats(stats::proc_stat_unknown_counters);
+      }
+    }
+
+    // Skip field_id 0 (invalid) and 1 (pid).
+    for (size_t field_id = 2; field_id < counter_values.size(); field_id++) {
+      if (!has_counter[field_id])
+        continue;
+
+      // Lookup the interned string id from the field name using the
+      // pre-cached |proc_stats_process_names_| map.
+      StringId name = proc_stats_process_names_[field_id];
+      int64_t value = counter_values[field_id];
+      UniquePid upid = context_->process_tracker->GetOrCreateProcess(pid);
+      context_->event_tracker->PushCounter(ts, value, name, upid,
+                                           RefType::kRefUpid);
+    }
+  }
+}
+
+void ProtoTraceParser::ParseFtracePacket(
+    uint32_t cpu,
+    int64_t ts,
+    TraceSorter::TimestampedTracePiece ttp) {
+  PERFETTO_DCHECK(ttp.json_value == nullptr);
+  const TraceBlobView& ftrace = ttp.blob_view;
+
+  ProtoDecoder decoder(ftrace.data(), ftrace.length());
+  uint64_t raw_pid = 0;
+  if (auto pid_field =
+          decoder.FindField(protos::pbzero::FtraceEvent::kPidFieldNumber)) {
+    raw_pid = pid_field.as_uint64();
+  } else {
+    PERFETTO_ELOG("Pid field not found in ftrace packet");
+    return;
+  }
+  uint32_t pid = static_cast<uint32_t>(raw_pid);
+
+  for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
+    bool is_metadata_field =
+        fld.id() == protos::pbzero::FtraceEvent::kPidFieldNumber ||
+        fld.id() == protos::pbzero::FtraceEvent::kTimestampFieldNumber;
+    if (is_metadata_field)
+      continue;
+
+    ConstBytes data = fld.as_bytes();
+    if (fld.id() == protos::pbzero::FtraceEvent::kGenericFieldNumber) {
+      ParseGenericFtrace(ts, cpu, pid, data);
+    } else if (fld.id() !=
+               protos::pbzero::FtraceEvent::kSchedSwitchFieldNumber) {
+      ParseTypedFtraceToRaw(fld.id(), ts, cpu, pid, data);
+    }
+
+    switch (fld.id()) {
+      case protos::pbzero::FtraceEvent::kSchedSwitchFieldNumber: {
+        ParseSchedSwitch(cpu, ts, data);
+        break;
+      }
+      case protos::pbzero::FtraceEvent::kSchedWakeupFieldNumber: {
+        ParseSchedWakeup(ts, data);
+        break;
+      }
+      case protos::pbzero::FtraceEvent::kCpuFrequencyFieldNumber: {
+        ParseCpuFreq(ts, data);
+        break;
+      }
+      case protos::pbzero::FtraceEvent::kCpuIdleFieldNumber: {
+        ParseCpuIdle(ts, data);
+        break;
+      }
+      case protos::pbzero::FtraceEvent::kPrintFieldNumber: {
+        ParsePrint(cpu, ts, pid, data);
+        break;
+      }
+      case protos::pbzero::FtraceEvent::kRssStatFieldNumber: {
+        ParseRssStat(ts, pid, data);
+        break;
+      }
+      case protos::pbzero::FtraceEvent::kIonHeapGrowFieldNumber: {
+        ParseIonHeapGrowOrShrink(ts, pid, data, true);
+        break;
+      }
+      case protos::pbzero::FtraceEvent::kIonHeapShrinkFieldNumber: {
+        ParseIonHeapGrowOrShrink(ts, pid, data, false);
+        break;
+      }
+      case protos::pbzero::FtraceEvent::kSignalGenerateFieldNumber: {
+        ParseSignalGenerate(ts, data);
+        break;
+      }
+      case protos::pbzero::FtraceEvent::kSignalDeliverFieldNumber: {
+        ParseSignalDeliver(ts, pid, data);
+        break;
+      }
+      case protos::pbzero::FtraceEvent::kLowmemoryKillFieldNumber: {
+        ParseLowmemoryKill(ts, data);
+        break;
+      }
+      case protos::pbzero::FtraceEvent::kOomScoreAdjUpdateFieldNumber: {
+        ParseOOMScoreAdjUpdate(ts, data);
+        break;
+      }
+      case protos::pbzero::FtraceEvent::kMmEventRecordFieldNumber: {
+        ParseMmEventRecord(ts, pid, data);
+        break;
+      }
+      case protos::pbzero::FtraceEvent::kSysEnterFieldNumber: {
+        ParseSysEvent(ts, pid, true, data);
+        break;
+      }
+      case protos::pbzero::FtraceEvent::kSysExitFieldNumber: {
+        ParseSysEvent(ts, pid, false, data);
+        break;
+      }
+      case protos::pbzero::FtraceEvent::kTaskNewtaskFieldNumber: {
+        ParseTaskNewTask(ts, pid, data);
+        break;
+      }
+      case protos::pbzero::FtraceEvent::kTaskRenameFieldNumber: {
+        ParseTaskRename(data);
+        break;
+      }
+      default:
+        break;
+    }
+  }
+  // TODO(lalitm): maybe move this to the flush method in the trace processor
+  // once we have it. This may reduce performance in the ArgsTracker though so
+  // needs to be handled carefully.
+  context_->args_tracker->Flush();
+
+  PERFETTO_DCHECK(!decoder.bytes_left());
+}
+
+void ProtoTraceParser::ParseSignalDeliver(int64_t ts,
+                                          uint32_t pid,
+                                          ConstBytes blob) {
+  protos::pbzero::SignalDeliverFtraceEvent::Decoder sig(blob.data, blob.size);
+  UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
+  context_->event_tracker->PushInstant(ts, signal_deliver_id_, sig.sig(), utid,
+                                       RefType::kRefUtid);
+}
+
+// This event has both the pid of the thread that sent the signal and the
+// destination of the signal. Currently storing the pid of the destination.
+void ProtoTraceParser::ParseSignalGenerate(int64_t ts, ConstBytes blob) {
+  protos::pbzero::SignalGenerateFtraceEvent::Decoder sig(blob.data, blob.size);
+
+  UniqueTid utid = context_->process_tracker->GetOrCreateThread(
+      static_cast<uint32_t>(sig.pid()));
+  context_->event_tracker->PushInstant(ts, signal_generate_id_, sig.sig(), utid,
+                                       RefType::kRefUtid);
+}
+
+void ProtoTraceParser::ParseLowmemoryKill(int64_t ts, ConstBytes blob) {
+  // TODO(taylori): Store the pagecache_size, pagecache_limit and free fields
+  // in an args table
+  protos::pbzero::LowmemoryKillFtraceEvent::Decoder lmk(blob.data, blob.size);
+
+  // Store the pid of the event that is lmk-ed.
+  auto pid = static_cast<uint32_t>(lmk.pid());
+  UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
+  auto row_id = context_->event_tracker->PushInstant(ts, lmk_id_, 0, utid,
+                                                     RefType::kRefUtid, true);
+
+  // Store the comm as an arg.
+  auto comm_id = context_->storage->InternString(
+      lmk.has_comm() ? lmk.comm() : base::StringView());
+  context_->args_tracker->AddArg(row_id, comm_name_id_, comm_name_id_,
+                                 Variadic::String(comm_id));
+}
+
+void ProtoTraceParser::ParseRssStat(int64_t ts, uint32_t pid, ConstBytes blob) {
+  protos::pbzero::RssStatFtraceEvent::Decoder rss(blob.data, blob.size);
+  const auto kRssStatUnknown = static_cast<uint32_t>(rss_members_.size()) - 1;
+  auto member = static_cast<uint32_t>(rss.member());
+  int64_t size = rss.size();
+  if (member >= rss_members_.size()) {
+    context_->storage->IncrementStats(stats::rss_stat_unknown_keys);
+    member = kRssStatUnknown;
+  }
+
+  if (size >= 0) {
+    UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
+    context_->event_tracker->PushCounter(ts, size, rss_members_[member], utid,
+                                         RefType::kRefUtid, true);
+  } else {
+    context_->storage->IncrementStats(stats::rss_stat_negative_size);
+  }
+}
+
+void ProtoTraceParser::ParseIonHeapGrowOrShrink(int64_t ts,
+                                                uint32_t pid,
+                                                ConstBytes blob,
+                                                bool grow) {
+  protos::pbzero::IonHeapGrowFtraceEvent::Decoder ion(blob.data, blob.size);
+  int64_t total_bytes = ion.total_allocated();
+  int64_t change_bytes = static_cast<int64_t>(ion.len()) * (grow ? 1 : -1);
+  StringId global_name_id = ion_total_unknown_id_;
+  StringId change_name_id = ion_change_unknown_id_;
+
+  if (ion.has_heap_name()) {
+    char counter_name[255];
+    base::StringView heap_name = ion.heap_name();
+    snprintf(counter_name, sizeof(counter_name), "mem.ion.%.*s",
+             int(heap_name.size()), heap_name.data());
+    global_name_id = context_->storage->InternString(counter_name);
+    snprintf(counter_name, sizeof(counter_name), "mem.ion_change.%.*s",
+             int(heap_name.size()), heap_name.data());
+    change_name_id = context_->storage->InternString(counter_name);
+  }
+
+  // Push the global counter.
+  context_->event_tracker->PushCounter(ts, total_bytes, global_name_id, 0,
+                                       RefType::kRefNoRef);
+
+  // Push the change counter.
+  // TODO(b/121331269): these should really be instant events. For now we
+  // manually reset them to 0 after 1ns.
+  UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
+  context_->event_tracker->PushCounter(ts, change_bytes, change_name_id, utid,
+                                       RefType::kRefUtid);
+  context_->event_tracker->PushCounter(ts + 1, 0, change_name_id, utid,
+                                       RefType::kRefUtid);
+
+  // We are reusing the same function for ion_heap_grow and ion_heap_shrink.
+  // It is fine as the arguments are the same, but we need to be sure that the
+  // protobuf field id for both are the same.
+  static_assert(
+      static_cast<int>(
+          protos::pbzero::IonHeapGrowFtraceEvent::kTotalAllocatedFieldNumber) ==
+              static_cast<int>(protos::pbzero::IonHeapShrinkFtraceEvent::
+                                   kTotalAllocatedFieldNumber) &&
+          static_cast<int>(
+              protos::pbzero::IonHeapGrowFtraceEvent::kLenFieldNumber) ==
+              static_cast<int>(
+                  protos::pbzero::IonHeapShrinkFtraceEvent::kLenFieldNumber) &&
+          static_cast<int>(
+              protos::pbzero::IonHeapGrowFtraceEvent::kHeapNameFieldNumber) ==
+              static_cast<int>(protos::pbzero::IonHeapShrinkFtraceEvent::
+                                   kHeapNameFieldNumber),
+      "ION field mismatch");
+}
+
+void ProtoTraceParser::ParseCpuFreq(int64_t ts, ConstBytes blob) {
+  protos::pbzero::CpuFrequencyFtraceEvent::Decoder freq(blob.data, blob.size);
+  uint32_t cpu = freq.cpu_id();
+  uint32_t new_freq = freq.state();
+  context_->event_tracker->PushCounter(ts, new_freq, cpu_freq_name_id_, cpu,
+                                       RefType::kRefCpuId);
+}
+
+void ProtoTraceParser::ParseCpuIdle(int64_t ts, ConstBytes blob) {
+  protos::pbzero::CpuIdleFtraceEvent::Decoder idle(blob.data, blob.size);
+  uint32_t cpu = idle.cpu_id();
+  uint32_t new_state = idle.state();
+  context_->event_tracker->PushCounter(ts, new_state, cpu_idle_name_id_, cpu,
+                                       RefType::kRefCpuId);
+}
+
+PERFETTO_ALWAYS_INLINE
+void ProtoTraceParser::ParseSchedSwitch(uint32_t cpu,
+                                        int64_t ts,
+                                        ConstBytes blob) {
+  protos::pbzero::SchedSwitchFtraceEvent::Decoder ss(blob.data, blob.size);
+  uint32_t prev_pid = static_cast<uint32_t>(ss.prev_pid());
+  uint32_t next_pid = static_cast<uint32_t>(ss.next_pid());
+  context_->event_tracker->PushSchedSwitch(
+      cpu, ts, prev_pid, ss.prev_comm(), ss.prev_prio(), ss.prev_state(),
+      next_pid, ss.next_comm(), ss.next_prio());
+}
+
+void ProtoTraceParser::ParseSchedWakeup(int64_t ts, ConstBytes blob) {
+  protos::pbzero::SchedWakeupFtraceEvent::Decoder sw(blob.data, blob.size);
+  uint32_t wakee_pid = static_cast<uint32_t>(sw.pid());
+  StringId name_id = context_->storage->InternString(sw.comm());
+  auto utid = context_->process_tracker->UpdateThreadName(wakee_pid, name_id);
+  context_->event_tracker->PushInstant(ts, sched_wakeup_name_id_, 0 /* value */,
+                                       utid, RefType::kRefUtid);
+}
+
+void ProtoTraceParser::ParseTaskNewTask(int64_t ts,
+                                        uint32_t source_tid,
+                                        ConstBytes blob) {
+  protos::pbzero::TaskNewtaskFtraceEvent::Decoder evt(blob.data, blob.size);
+  uint32_t clone_flags = static_cast<uint32_t>(evt.clone_flags());
+  uint32_t new_tid = static_cast<uint32_t>(evt.pid());
+  StringId new_comm = context_->storage->InternString(evt.comm());
+  auto* proc_tracker = context_->process_tracker.get();
+
+  // task_newtask is raised both in the case of a new process creation (fork()
+  // family) and thread creation (clone(CLONE_THREAD, ...)).
+  static const uint32_t kCloneThread = 0x00010000;  // From kernel's sched.h.
+  if ((clone_flags & kCloneThread) == 0) {
+    // This is a plain-old fork() or equivalent.
+    proc_tracker->StartNewProcess(ts, new_tid);
+    return;
+  }
+
+  // This is a pthread_create or similar. Bind the two threads together, so
+  // they get resolved to the same process.
+  auto source_utid = proc_tracker->GetOrCreateThread(source_tid);
+  auto new_utid = proc_tracker->StartNewThread(ts, new_tid, new_comm);
+  proc_tracker->AssociateThreads(source_utid, new_utid);
+}
+
+void ProtoTraceParser::ParseTaskRename(ConstBytes blob) {
+  protos::pbzero::TaskRenameFtraceEvent::Decoder evt(blob.data, blob.size);
+  uint32_t tid = static_cast<uint32_t>(evt.pid());
+  StringId comm = context_->storage->InternString(evt.newcomm());
+  context_->process_tracker->UpdateThreadName(tid, comm);
+}
+
+void ProtoTraceParser::ParsePrint(uint32_t,
+                                  int64_t ts,
+                                  uint32_t pid,
+                                  ConstBytes blob) {
+  protos::pbzero::PrintFtraceEvent::Decoder evt(blob.data, blob.size);
+  SystraceTracePoint point{};
+  auto r = ParseSystraceTracePoint(evt.buf(), &point);
+  if (r != SystraceParseResult::kSuccess) {
+    if (r == SystraceParseResult::kFailure) {
+      context_->storage->IncrementStats(stats::systrace_parse_failure);
+    }
+    return;
+  }
+
+  switch (point.phase) {
+    case 'B': {
+      StringId name_id = context_->storage->InternString(point.name);
+      context_->slice_tracker->BeginAndroid(ts, pid, point.tgid, 0 /*cat_id*/,
+                                            name_id);
+      break;
+    }
+
+    case 'E': {
+      context_->slice_tracker->EndAndroid(ts, pid, point.tgid);
+      break;
+    }
+
+    case 'C': {
+      // LMK events from userspace are hacked as counter events with the "value"
+      // of the counter representing the pid of the killed process which is
+      // reset to 0 once the kill is complete.
+      // Homogenise this with kernel LMK events as an instant event, ignoring
+      // the resets to 0.
+      if (point.name == "kill_one_process") {
+        auto killed_pid = static_cast<uint32_t>(point.value);
+        if (killed_pid != 0) {
+          UniquePid killed_upid =
+              context_->process_tracker->GetOrCreateProcess(killed_pid);
+          context_->event_tracker->PushInstant(ts, lmk_id_, 0, killed_upid,
+                                               RefType::kRefUpid);
+        }
+        // TODO(lalitm): we should not add LMK events to the counters table
+        // once the UI has support for displaying instants.
+      }
+      // This is per upid on purpose. Some counters are pushed from arbitrary
+      // threads but are really per process.
+      UniquePid upid =
+          context_->process_tracker->GetOrCreateProcess(point.tgid);
+      StringId name_id = context_->storage->InternString(point.name);
+      context_->event_tracker->PushCounter(ts, point.value, name_id, upid,
+                                           RefType::kRefUpid);
+    }
+  }
+}
+
+void ProtoTraceParser::ParseBatteryCounters(int64_t ts, ConstBytes blob) {
+  protos::pbzero::BatteryCounters::Decoder evt(blob.data, blob.size);
+  if (evt.has_charge_counter_uah()) {
+    context_->event_tracker->PushCounter(
+        ts, evt.charge_counter_uah(), batt_charge_id_, 0, RefType::kRefNoRef);
+  }
+  if (evt.has_capacity_percent()) {
+    context_->event_tracker->PushCounter(
+        ts, static_cast<double>(evt.capacity_percent()), batt_capacity_id_, 0,
+        RefType::kRefNoRef);
+  }
+  if (evt.has_current_ua()) {
+    context_->event_tracker->PushCounter(ts, evt.current_ua(), batt_current_id_,
+                                         0, RefType::kRefNoRef);
+  }
+  if (evt.has_current_avg_ua()) {
+    context_->event_tracker->PushCounter(
+        ts, evt.current_avg_ua(), batt_current_avg_id_, 0, RefType::kRefNoRef);
+  }
+}
+
+void ProtoTraceParser::ParsePowerRails(ConstBytes blob) {
+  protos::pbzero::PowerRails::Decoder evt(blob.data, blob.size);
+  if (evt.has_rail_descriptor()) {
+    for (auto it = evt.rail_descriptor(); it; ++it) {
+      protos::pbzero::PowerRails::RailDescriptor::Decoder desc(it->data(),
+                                                               it->size());
+      uint32_t idx = desc.index();
+      if (PERFETTO_UNLIKELY(idx > 256)) {
+        PERFETTO_DLOG("Skipping excessively large power_rail index %" PRIu32,
+                      idx);
+        continue;
+      }
+      if (power_rails_strs_id_.size() <= idx)
+        power_rails_strs_id_.resize(idx + 1);
+      char counter_name[255];
+      snprintf(counter_name, sizeof(counter_name), "power.%.*s_uws",
+               int(desc.rail_name().size), desc.rail_name().data);
+      power_rails_strs_id_[idx] = context_->storage->InternString(counter_name);
+    }
+  }
+
+  if (evt.has_energy_data()) {
+    for (auto it = evt.energy_data(); it; ++it) {
+      protos::pbzero::PowerRails::EnergyData::Decoder desc(it->data(),
+                                                           it->size());
+      if (desc.index() < power_rails_strs_id_.size()) {
+        int64_t ts = static_cast<int64_t>(desc.timestamp_ms()) * 1000000;
+        context_->event_tracker->PushCounter(ts, desc.energy(),
+                                             power_rails_strs_id_[desc.index()],
+                                             0, RefType::kRefNoRef);
+      } else {
+        context_->storage->IncrementStats(stats::power_rail_unknown_index);
+      }
+    }
+  }
+}
+
+void ProtoTraceParser::ParseOOMScoreAdjUpdate(int64_t ts, ConstBytes blob) {
+  protos::pbzero::OomScoreAdjUpdateFtraceEvent::Decoder evt(blob.data,
+                                                            blob.size);
+  // The int16_t static cast is because older version of the on-device tracer
+  // had a bug on negative varint encoding (b/120618641).
+  int16_t oom_adj = static_cast<int16_t>(evt.oom_score_adj());
+  uint32_t pid = static_cast<uint32_t>(evt.pid());
+  UniquePid upid = context_->process_tracker->GetOrCreateProcess(pid);
+  context_->event_tracker->PushCounter(ts, oom_adj, oom_score_adj_id_, upid,
+                                       RefType::kRefUpid);
+}
+
+void ProtoTraceParser::ParseMmEventRecord(int64_t ts,
+                                          uint32_t pid,
+                                          ConstBytes blob) {
+  protos::pbzero::MmEventRecordFtraceEvent::Decoder evt(blob.data, blob.size);
+  uint32_t type = evt.type();
+  UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
+
+  if (type >= mm_event_counter_names_.size()) {
+    context_->storage->IncrementStats(stats::mm_unknown_type);
+    return;
+  }
+
+  const auto& counter_names = mm_event_counter_names_[type];
+  context_->event_tracker->PushCounter(ts, evt.count(), counter_names.count,
+                                       utid, RefType::kRefUtid, true);
+  context_->event_tracker->PushCounter(ts, evt.max_lat(), counter_names.max_lat,
+                                       utid, RefType::kRefUtid, true);
+  context_->event_tracker->PushCounter(ts, evt.avg_lat(), counter_names.avg_lat,
+                                       utid, RefType::kRefUtid, true);
+}
+
+void ProtoTraceParser::ParseSysEvent(int64_t ts,
+                                     uint32_t pid,
+                                     bool is_enter,
+                                     ConstBytes blob) {
+  protos::pbzero::SysEnterFtraceEvent::Decoder evt(blob.data, blob.size);
+  uint32_t syscall_num = static_cast<uint32_t>(evt.id());
+  UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
+
+  if (is_enter) {
+    context_->syscall_tracker->Enter(ts, utid, syscall_num);
+  } else {
+    context_->syscall_tracker->Exit(ts, utid, syscall_num);
+  }
+
+  // We are reusing the same function for sys_enter and sys_exit.
+  // It is fine as the arguments are the same, but we need to be sure that the
+  // protobuf field id for both are the same.
+  static_assert(
+      static_cast<int>(protos::pbzero::SysEnterFtraceEvent::kIdFieldNumber) ==
+          static_cast<int>(protos::pbzero::SysExitFtraceEvent::kIdFieldNumber),
+      "field mismatch");
+}
+
+void ProtoTraceParser::ParseGenericFtrace(int64_t ts,
+                                          uint32_t cpu,
+                                          uint32_t tid,
+                                          ConstBytes blob) {
+  protos::pbzero::GenericFtraceEvent::Decoder evt(blob.data, blob.size);
+  StringId event_id = context_->storage->InternString(evt.event_name());
+  UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
+  RowId row_id = context_->storage->mutable_raw_events()->AddRawEvent(
+      ts, event_id, cpu, utid);
+
+  for (auto it = evt.field(); it; ++it) {
+    protos::pbzero::GenericFtraceEvent::Field::Decoder fld(it->data(),
+                                                           it->size());
+    auto field_name_id = context_->storage->InternString(fld.name());
+    if (fld.has_int_value()) {
+      context_->args_tracker->AddArg(row_id, field_name_id, field_name_id,
+                                     Variadic::Integer(fld.int_value()));
+    } else if (fld.has_uint_value()) {
+      context_->args_tracker->AddArg(
+          row_id, field_name_id, field_name_id,
+          Variadic::Integer(static_cast<int64_t>(fld.uint_value())));
+    } else if (fld.has_str_value()) {
+      StringId str_value = context_->storage->InternString(fld.str_value());
+      context_->args_tracker->AddArg(row_id, field_name_id, field_name_id,
+                                     Variadic::String(str_value));
+    }
+  }
+}
+
+void ProtoTraceParser::ParseTypedFtraceToRaw(uint32_t ftrace_id,
+                                             int64_t ts,
+                                             uint32_t cpu,
+                                             uint32_t tid,
+                                             ConstBytes blob) {
+  ProtoDecoder decoder(blob.data, blob.size);
+  if (ftrace_id >= GetDescriptorsSize()) {
+    PERFETTO_DLOG("Event with id: %d does not exist and cannot be parsed.",
+                  ftrace_id);
+    return;
+  }
+
+  MessageDescriptor* m = GetMessageDescriptorForId(ftrace_id);
+  const auto& message_strings = ftrace_message_strings_[ftrace_id];
+  UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
+  RowId raw_event_id = context_->storage->mutable_raw_events()->AddRawEvent(
+      ts, message_strings.message_name_id, cpu, utid);
+  for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
+    if (PERFETTO_UNLIKELY(fld.id() >= kMaxFtraceEventFields)) {
+      PERFETTO_DLOG(
+          "Skipping ftrace arg - proto field id is too large (%" PRIu16 ")",
+          fld.id());
+      continue;
+    }
+    ProtoSchemaType type = m->fields[fld.id()].type;
+    StringId name_id = message_strings.field_name_ids[fld.id()];
+    switch (type) {
+      case ProtoSchemaType::kUint32:
+      case ProtoSchemaType::kInt32:
+      case ProtoSchemaType::kUint64:
+      case ProtoSchemaType::kInt64:
+      case ProtoSchemaType::kFixed64:
+      case ProtoSchemaType::kFixed32:
+      case ProtoSchemaType::kSfixed32:
+      case ProtoSchemaType::kSfixed64:
+      case ProtoSchemaType::kSint32:
+      case ProtoSchemaType::kSint64:
+      case ProtoSchemaType::kBool:
+      case ProtoSchemaType::kEnum: {
+        context_->args_tracker->AddArg(raw_event_id, name_id, name_id,
+                                       Variadic::Integer(fld.as_int64()));
+        break;
+      }
+      case ProtoSchemaType::kString:
+      case ProtoSchemaType::kBytes: {
+        StringId value = context_->storage->InternString(fld.as_string());
+        context_->args_tracker->AddArg(raw_event_id, name_id, name_id,
+                                       Variadic::String(value));
+        break;
+      }
+      case ProtoSchemaType::kDouble: {
+        context_->args_tracker->AddArg(raw_event_id, name_id, name_id,
+                                       Variadic::Real(fld.as_double()));
+        break;
+      }
+      case ProtoSchemaType::kFloat: {
+        context_->args_tracker->AddArg(
+            raw_event_id, name_id, name_id,
+            Variadic::Real(static_cast<double>(fld.as_float())));
+        break;
+      }
+      case ProtoSchemaType::kUnknown:
+      case ProtoSchemaType::kGroup:
+      case ProtoSchemaType::kMessage:
+        PERFETTO_DLOG("Could not store %s as a field in args table.",
+                      ProtoSchemaToString(type));
+        break;
+    }
+  }
+}
+
+void ProtoTraceParser::ParseClockSnapshot(ConstBytes blob) {
+  protos::pbzero::ClockSnapshot::Decoder evt(blob.data, blob.size);
+  int64_t clock_boottime = 0;
+  int64_t clock_monotonic = 0;
+  int64_t clock_realtime = 0;
+  for (auto it = evt.clocks(); it; ++it) {
+    protos::pbzero::ClockSnapshot::Clock::Decoder clk(it->data(), it->size());
+    if (clk.type() == protos::pbzero::ClockSnapshot::Clock::BOOTTIME) {
+      clock_boottime = static_cast<int64_t>(clk.timestamp());
+    } else if (clk.type() == protos::pbzero::ClockSnapshot::Clock::REALTIME) {
+      clock_realtime = static_cast<int64_t>(clk.timestamp());
+    } else if (clk.type() == protos::pbzero::ClockSnapshot::Clock::MONOTONIC) {
+      clock_monotonic = static_cast<int64_t>(clk.timestamp());
+    }
+  }
+
+  // Usually these snapshots come all together.
+  PERFETTO_DCHECK(clock_boottime > 0 && clock_monotonic > 0 &&
+                  clock_realtime > 0);
+
+  if (clock_boottime <= 0) {
+    PERFETTO_ELOG("ClockSnapshot has an invalid BOOTTIME (%" PRId64 ")",
+                  clock_boottime);
+    context_->storage->IncrementStats(stats::invalid_clock_snapshots);
+    return;
+  }
+
+  auto* ct = context_->clock_tracker.get();
+
+  // |clock_boottime| is used as the reference trace time.
+  ct->SyncClocks(ClockDomain::kBootTime, clock_boottime, clock_boottime);
+
+  if (clock_monotonic > 0)
+    ct->SyncClocks(ClockDomain::kMonotonic, clock_monotonic, clock_boottime);
+
+  if (clock_realtime > 0)
+    ct->SyncClocks(ClockDomain::kRealTime, clock_realtime, clock_boottime);
+}
+
+void ProtoTraceParser::ParseAndroidLogPacket(ConstBytes blob) {
+  protos::pbzero::AndroidLogPacket::Decoder packet(blob.data, blob.size);
+  for (auto it = packet.events(); it; ++it)
+    ParseAndroidLogEvent(it->as_bytes());
+
+  if (packet.has_stats())
+    ParseAndroidLogStats(packet.stats());
+}
+
+void ProtoTraceParser::ParseAndroidLogEvent(ConstBytes blob) {
+  // TODO(primiano): Add events and non-stringified fields to the "raw" table.
+  protos::pbzero::AndroidLogPacket::LogEvent::Decoder evt(blob.data, blob.size);
+  int64_t ts = static_cast<int64_t>(evt.timestamp());
+  uint32_t pid = static_cast<uint32_t>(evt.pid());
+  uint32_t tid = static_cast<uint32_t>(evt.tid());
+  uint8_t prio = static_cast<uint8_t>(evt.prio());
+  StringId tag_id = context_->storage->InternString(
+      evt.has_tag() ? evt.tag() : base::StringView());
+  StringId msg_id = context_->storage->InternString(
+      evt.has_message() ? evt.message() : base::StringView());
+
+  char arg_msg[4096];
+  char* arg_str = &arg_msg[0];
+  *arg_str = '\0';
+  auto arg_avail = [&arg_msg, &arg_str]() {
+    return sizeof(arg_msg) - static_cast<size_t>(arg_str - arg_msg);
+  };
+  for (auto it = evt.args(); it; ++it) {
+    protos::pbzero::AndroidLogPacket::LogEvent::Arg::Decoder arg(it->data(),
+                                                                 it->size());
+    if (!arg.has_name())
+      continue;
+    arg_str +=
+        snprintf(arg_str, arg_avail(),
+                 " %.*s=", static_cast<int>(arg.name().size), arg.name().data);
+    if (arg.has_string_value()) {
+      arg_str += snprintf(arg_str, arg_avail(), "\"%.*s\"",
+                          static_cast<int>(arg.string_value().size),
+                          arg.string_value().data);
+    } else if (arg.has_int_value()) {
+      arg_str += snprintf(arg_str, arg_avail(), "%" PRId64, arg.int_value());
+    } else if (arg.has_float_value()) {
+      arg_str += snprintf(arg_str, arg_avail(), "%f",
+                          static_cast<double>(arg.float_value()));
+    }
+  }
+
+  if (prio == 0)
+    prio = protos::pbzero::AndroidLogPriority::PRIO_INFO;
+
+  if (arg_str != &arg_msg[0]) {
+    PERFETTO_DCHECK(!msg_id);
+    // Skip the first space char (" foo=1 bar=2" -> "foo=1 bar=2").
+    msg_id = context_->storage->InternString(&arg_msg[1]);
+  }
+  UniquePid utid = tid ? context_->process_tracker->UpdateThread(tid, pid) : 0;
+  base::Optional<int64_t> opt_trace_time =
+      context_->clock_tracker->ToTraceTime(ClockDomain::kRealTime, ts);
+  if (!opt_trace_time)
+    return;
+
+  // Log events are NOT required to be sorted by trace_time. The virtual table
+  // will take care of sorting on-demand.
+  context_->storage->mutable_android_log()->AddLogEvent(
+      opt_trace_time.value(), utid, prio, tag_id, msg_id);
+}
+
+void ProtoTraceParser::ParseAndroidLogStats(ConstBytes blob) {
+  protos::pbzero::AndroidLogPacket::Stats::Decoder evt(blob.data, blob.size);
+  if (evt.has_num_failed()) {
+    context_->storage->SetStats(stats::android_log_num_failed,
+                                static_cast<int64_t>(evt.num_failed()));
+  }
+
+  if (evt.has_num_skipped()) {
+    context_->storage->SetStats(stats::android_log_num_skipped,
+                                static_cast<int64_t>(evt.num_skipped()));
+  }
+
+  if (evt.has_num_total()) {
+    context_->storage->SetStats(stats::android_log_num_total,
+                                static_cast<int64_t>(evt.num_total()));
+  }
+}
+
+void ProtoTraceParser::ParseTraceStats(ConstBytes blob) {
+  protos::pbzero::TraceStats::Decoder evt(blob.data, blob.size);
+  auto* storage = context_->storage.get();
+  storage->SetStats(stats::traced_producers_connected,
+                    static_cast<int64_t>(evt.producers_connected()));
+  storage->SetStats(stats::traced_data_sources_registered,
+                    static_cast<int64_t>(evt.data_sources_registered()));
+  storage->SetStats(stats::traced_data_sources_seen,
+                    static_cast<int64_t>(evt.data_sources_seen()));
+  storage->SetStats(stats::traced_tracing_sessions,
+                    static_cast<int64_t>(evt.tracing_sessions()));
+  storage->SetStats(stats::traced_total_buffers,
+                    static_cast<int64_t>(evt.total_buffers()));
+  storage->SetStats(stats::traced_chunks_discarded,
+                    static_cast<int64_t>(evt.chunks_discarded()));
+  storage->SetStats(stats::traced_patches_discarded,
+                    static_cast<int64_t>(evt.patches_discarded()));
+
+  int buf_num = 0;
+  for (auto it = evt.buffer_stats(); it; ++it, ++buf_num) {
+    protos::pbzero::TraceStats::BufferStats::Decoder buf(it->data(),
+                                                         it->size());
+    storage->SetIndexedStats(stats::traced_buf_buffer_size, buf_num,
+                             static_cast<int64_t>(buf.buffer_size()));
+    storage->SetIndexedStats(stats::traced_buf_bytes_written, buf_num,
+                             static_cast<int64_t>(buf.bytes_written()));
+    storage->SetIndexedStats(stats::traced_buf_bytes_overwritten, buf_num,
+                             static_cast<int64_t>(buf.bytes_overwritten()));
+    storage->SetIndexedStats(stats::traced_buf_bytes_read, buf_num,
+                             static_cast<int64_t>(buf.bytes_read()));
+    storage->SetIndexedStats(stats::traced_buf_padding_bytes_written, buf_num,
+                             static_cast<int64_t>(buf.padding_bytes_written()));
+    storage->SetIndexedStats(stats::traced_buf_padding_bytes_cleared, buf_num,
+                             static_cast<int64_t>(buf.padding_bytes_cleared()));
+    storage->SetIndexedStats(stats::traced_buf_chunks_written, buf_num,
+                             static_cast<int64_t>(buf.chunks_written()));
+    storage->SetIndexedStats(stats::traced_buf_chunks_rewritten, buf_num,
+                             static_cast<int64_t>(buf.chunks_rewritten()));
+    storage->SetIndexedStats(stats::traced_buf_chunks_overwritten, buf_num,
+                             static_cast<int64_t>(buf.chunks_overwritten()));
+    storage->SetIndexedStats(stats::traced_buf_chunks_discarded, buf_num,
+                             static_cast<int64_t>(buf.chunks_discarded()));
+    storage->SetIndexedStats(stats::traced_buf_chunks_read, buf_num,
+                             static_cast<int64_t>(buf.chunks_read()));
+    storage->SetIndexedStats(
+        stats::traced_buf_chunks_committed_out_of_order, buf_num,
+        static_cast<int64_t>(buf.chunks_committed_out_of_order()));
+    storage->SetIndexedStats(stats::traced_buf_write_wrap_count, buf_num,
+                             static_cast<int64_t>(buf.write_wrap_count()));
+    storage->SetIndexedStats(stats::traced_buf_patches_succeeded, buf_num,
+                             static_cast<int64_t>(buf.patches_succeeded()));
+    storage->SetIndexedStats(stats::traced_buf_patches_failed, buf_num,
+                             static_cast<int64_t>(buf.patches_failed()));
+    storage->SetIndexedStats(stats::traced_buf_readaheads_succeeded, buf_num,
+                             static_cast<int64_t>(buf.readaheads_succeeded()));
+    storage->SetIndexedStats(stats::traced_buf_readaheads_failed, buf_num,
+                             static_cast<int64_t>(buf.readaheads_failed()));
+  }
+}
+
+void ProtoTraceParser::ParseFtraceStats(ConstBytes blob) {
+  protos::pbzero::FtraceStats::Decoder evt(blob.data, blob.size);
+  size_t phase =
+      evt.phase() == protos::pbzero::FtraceStats_Phase_END_OF_TRACE ? 1 : 0;
+
+  // This code relies on the fact that each ftrace_cpu_XXX_end event is
+  // just after the corresponding ftrace_cpu_XXX_begin event.
+  static_assert(
+      stats::ftrace_cpu_read_events_end - stats::ftrace_cpu_read_events_begin ==
+              1 &&
+          stats::ftrace_cpu_entries_end - stats::ftrace_cpu_entries_begin == 1,
+      "ftrace_cpu_XXX stats definition are messed up");
+
+  auto* storage = context_->storage.get();
+  for (auto it = evt.cpu_stats(); it; ++it) {
+    protos::pbzero::FtraceCpuStats::Decoder cpu_stats(it->data(), it->size());
+    int cpu = static_cast<int>(cpu_stats.cpu());
+    storage->SetIndexedStats(stats::ftrace_cpu_entries_begin + phase, cpu,
+                             static_cast<int64_t>(cpu_stats.entries()));
+    storage->SetIndexedStats(stats::ftrace_cpu_overrun_begin + phase, cpu,
+                             static_cast<int64_t>(cpu_stats.overrun()));
+    storage->SetIndexedStats(stats::ftrace_cpu_commit_overrun_begin + phase,
+                             cpu,
+                             static_cast<int64_t>(cpu_stats.commit_overrun()));
+    storage->SetIndexedStats(stats::ftrace_cpu_bytes_read_begin + phase, cpu,
+                             static_cast<int64_t>(cpu_stats.bytes_read()));
+
+    // oldest_event_ts can often be set to very high values, possibly because
+    // of wrapping. Ensure that we are not overflowing to avoid ubsan
+    // complaining.
+    double oldest_event_ts = cpu_stats.oldest_event_ts() * 1e9;
+    if (oldest_event_ts >= std::numeric_limits<int64_t>::max()) {
+      storage->SetIndexedStats(stats::ftrace_cpu_oldest_event_ts_begin + phase,
+                               cpu, std::numeric_limits<int64_t>::max());
+    } else {
+      storage->SetIndexedStats(stats::ftrace_cpu_oldest_event_ts_begin + phase,
+                               cpu, static_cast<int64_t>(oldest_event_ts));
+    }
+
+    storage->SetIndexedStats(stats::ftrace_cpu_now_ts_begin + phase, cpu,
+                             static_cast<int64_t>(cpu_stats.now_ts() * 1e9));
+    storage->SetIndexedStats(stats::ftrace_cpu_dropped_events_begin + phase,
+                             cpu,
+                             static_cast<int64_t>(cpu_stats.dropped_events()));
+    storage->SetIndexedStats(stats::ftrace_cpu_read_events_begin + phase, cpu,
+                             static_cast<int64_t>(cpu_stats.read_events()));
+  }
+}
+
+void ProtoTraceParser::ParseProfilePacket(ConstBytes blob) {
+  uint64_t index = 0;
+  protos::pbzero::ProfilePacket::Decoder packet(blob.data, blob.size);
+
+  for (auto it = packet.strings(); it; ++it) {
+    protos::pbzero::ProfilePacket::InternedString::Decoder entry(it->data(),
+                                                                 it->size());
+
+    const char* str = reinterpret_cast<const char*>(entry.str().data);
+    auto str_id = context_->storage->InternString(
+        base::StringView(str, entry.str().size));
+    context_->heap_profile_tracker->AddString(index, entry.id(), str_id);
+  }
+
+  for (auto it = packet.mappings(); it; ++it) {
+    protos::pbzero::ProfilePacket::Mapping::Decoder entry(it->data(),
+                                                          it->size());
+    HeapProfileTracker::SourceMapping src_mapping;
+    src_mapping.build_id = entry.build_id();
+    src_mapping.offset = entry.offset();
+    src_mapping.start = entry.start();
+    src_mapping.end = entry.end();
+    src_mapping.load_bias = entry.load_bias();
+    src_mapping.name_id = 0;
+    for (auto path_string_id_it = entry.path_string_ids(); path_string_id_it;
+         ++path_string_id_it)
+      src_mapping.name_id = path_string_id_it->as_uint64();
+    context_->heap_profile_tracker->AddMapping(index, entry.id(), src_mapping);
+  }
+
+  for (auto it = packet.frames(); it; ++it) {
+    protos::pbzero::ProfilePacket::Frame::Decoder entry(it->data(), it->size());
+    HeapProfileTracker::SourceFrame src_frame;
+    src_frame.name_id = entry.function_name_id();
+    src_frame.mapping_id = entry.mapping_id();
+    src_frame.rel_pc = entry.rel_pc();
+
+    context_->heap_profile_tracker->AddFrame(index, entry.id(), src_frame);
+  }
+
+  for (auto it = packet.callstacks(); it; ++it) {
+    protos::pbzero::ProfilePacket::Callstack::Decoder entry(it->data(),
+                                                            it->size());
+    HeapProfileTracker::SourceCallstack src_callstack;
+    for (auto frame_it = entry.frame_ids(); frame_it; ++frame_it)
+      src_callstack.emplace_back(frame_it->as_uint64());
+
+    context_->heap_profile_tracker->AddCallstack(index, entry.id(),
+                                                 src_callstack);
+  }
+
+  for (auto it = packet.process_dumps(); it; ++it) {
+    protos::pbzero::ProfilePacket::ProcessHeapSamples::Decoder entry(
+        it->data(), it->size());
+
+    int pid = static_cast<int>(entry.pid());
+
+    if (entry.buffer_corrupted())
+      context_->storage->IncrementIndexedStats(
+          stats::heapprofd_buffer_corrupted, pid);
+    if (entry.buffer_overran())
+      context_->storage->IncrementIndexedStats(stats::heapprofd_buffer_overran,
+                                               pid);
+    if (entry.rejected_concurrent())
+      context_->storage->IncrementIndexedStats(
+          stats::heapprofd_rejected_concurrent, pid);
+
+    for (auto sample_it = entry.samples(); sample_it; ++sample_it) {
+      protos::pbzero::ProfilePacket::HeapSample::Decoder sample(
+          sample_it->data(), sample_it->size());
+
+      HeapProfileTracker::SourceAllocation src_allocation;
+      src_allocation.pid = entry.pid();
+      src_allocation.timestamp = sample.timestamp();
+      src_allocation.callstack_id = sample.callstack_id();
+      src_allocation.self_allocated = sample.self_allocated();
+      src_allocation.self_freed = sample.self_freed();
+      src_allocation.alloc_count = sample.alloc_count();
+      src_allocation.free_count = sample.free_count();
+
+      context_->heap_profile_tracker->StoreAllocation(index, src_allocation);
+    }
+  }
+  if (!packet.continued()) {
+    context_->heap_profile_tracker->ApplyAllAllocations();
+    index++;
+  }
+}
+
+void ProtoTraceParser::ParseSystemInfo(ConstBytes blob) {
+  protos::pbzero::SystemInfo::Decoder packet(blob.data, blob.size);
+  if (packet.has_utsname()) {
+    ConstBytes utsname_blob = packet.utsname();
+    protos::pbzero::Utsname::Decoder utsname(utsname_blob.data,
+                                             utsname_blob.size);
+    base::StringView machine = utsname.machine();
+    if (machine == "aarch64" || machine == "armv8l") {
+      context_->syscall_tracker->SetArchitecture(kAarch64);
+    } else if (machine == "x86_64") {
+      context_->syscall_tracker->SetArchitecture(kX86_64);
+    } else {
+      PERFETTO_ELOG("Unknown architecture %s", machine.ToStdString().c_str());
+    }
+  }
+}
+
+void ProtoTraceParser::ParseTrackEvent(
+    int64_t ts,
+    int64_t /*tts*/,
+    ProtoIncrementalState::PacketSequenceState* sequence_state,
+    ConstBytes blob) {
+  protos::pbzero::TrackEvent::Decoder event(blob.data, blob.size);
+
+  const auto legacy_event_blob = event.legacy_event();
+  protos::pbzero::TrackEvent::LegacyEvent::Decoder legacy_event(
+      legacy_event_blob.data, legacy_event_blob.size);
+
+  // TODO(eseckler): This legacy event field will eventually be replaced by
+  // fields in TrackEvent itself.
+  if (PERFETTO_UNLIKELY(!legacy_event.has_phase())) {
+    PERFETTO_ELOG("TrackEvent without phase");
+    return;
+  }
+
+  ProcessTracker* procs = context_->process_tracker.get();
+  TraceStorage* storage = context_->storage.get();
+  SliceTracker* slice_tracker = context_->slice_tracker.get();
+
+  uint32_t pid = static_cast<uint32_t>(sequence_state->pid());
+  uint32_t tid = static_cast<uint32_t>(sequence_state->tid());
+  if (legacy_event.has_pid_override())
+    pid = static_cast<uint32_t>(legacy_event.pid_override());
+  if (legacy_event.has_tid_override())
+    tid = static_cast<uint32_t>(legacy_event.tid_override());
+  UniqueTid utid = procs->UpdateThread(tid, pid);
+
+  std::vector<uint32_t> category_iids;
+  for (auto it = event.category_iids(); it; ++it) {
+    category_iids.push_back(it->as_uint32());
+  }
+
+  StringId category_id = 0;
+
+  // If there's a single category, we can avoid building a concatenated string.
+  if (PERFETTO_LIKELY(category_iids.size() == 1)) {
+    auto* map =
+        sequence_state->GetInternedDataMap<protos::pbzero::EventCategory>();
+    auto cat_view_it = map->find(category_iids[0]);
+    if (cat_view_it == map->end()) {
+      PERFETTO_ELOG("Could not find category interning entry for ID %u",
+                    category_iids[0]);
+    } else {
+      // If the name is already in the pool, no need to decode it again.
+      if (cat_view_it->second.storage_refs) {
+        category_id = cat_view_it->second.storage_refs->name_id;
+      } else {
+        auto cat = cat_view_it->second.CreateDecoder();
+        category_id = storage->InternString(cat.name());
+        // Avoid having to decode & look up the name again in the future.
+        cat_view_it->second.storage_refs =
+            ProtoIncrementalState::StorageReferences<
+                protos::pbzero::EventCategory>{category_id};
+      }
+    }
+  } else if (category_iids.size() > 1) {
+    auto* map =
+        sequence_state->GetInternedDataMap<protos::pbzero::EventCategory>();
+    // We concatenate the category strings together since we currently only
+    // support a single "cat" column.
+    // TODO(eseckler): Support multi-category events in the table schema.
+    std::string categories;
+    for (uint32_t iid : category_iids) {
+      auto cat_view_it = map->find(iid);
+      if (cat_view_it == map->end()) {
+        PERFETTO_ELOG("Could not find category interning entry for ID %u", iid);
+        continue;
+      }
+      auto cat = cat_view_it->second.CreateDecoder();
+      base::StringView name = cat.name();
+      if (!categories.empty())
+        categories.append(",");
+      categories.append(name.data(), name.size());
+    }
+    if (!categories.empty())
+      category_id = storage->InternString(base::StringView(categories));
+  } else {
+    PERFETTO_ELOG("TrackEvent without category");
+  }
+
+  StringId name_id = 0;
+
+  if (PERFETTO_LIKELY(legacy_event.name_iid())) {
+    auto* map =
+        sequence_state->GetInternedDataMap<protos::pbzero::LegacyEventName>();
+    auto name_view_it = map->find(legacy_event.name_iid());
+    if (name_view_it == map->end()) {
+      PERFETTO_ELOG("Could not find event name interning entry for ID %u",
+                    legacy_event.name_iid());
+    } else {
+      // If the name is already in the pool, no need to decode it again.
+      if (name_view_it->second.storage_refs) {
+        name_id = name_view_it->second.storage_refs->name_id;
+      } else {
+        auto event_name = name_view_it->second.CreateDecoder();
+        name_id = storage->InternString(event_name.name());
+        // Avoid having to decode & look up the name again in the future.
+        name_view_it->second.storage_refs =
+            ProtoIncrementalState::StorageReferences<
+                protos::pbzero::LegacyEventName>{name_id};
+      }
+    }
+  }
+
+  // TODO(eseckler): Handle thread timestamp/duration, debug annotations, task
+  // souce locations, legacy event attributes, ...
+
+  int32_t phase = legacy_event.phase();
+  switch (static_cast<char>(phase)) {
+    case 'B': {  // TRACE_EVENT_PHASE_BEGIN.
+      slice_tracker->Begin(ts, utid, category_id, name_id);
+      break;
+    }
+    case 'E': {  // TRACE_EVENT_PHASE_END.
+      slice_tracker->End(ts, utid, category_id, name_id);
+      break;
+    }
+    case 'X': {  // TRACE_EVENT_PHASE_COMPLETE.
+      auto duration_ns = legacy_event.duration_us() * 1000;
+      if (duration_ns < 0)
+        return;
+      slice_tracker->Scoped(ts, utid, category_id, name_id, duration_ns);
+      break;
+    }
+    case 'M': {  // TRACE_EVENT_PHASE_METADATA (process and thread names).
+      // For now, we just compare the event name and assume there's a single
+      // argument in these events with the name of the process/thread.
+      // TODO(eseckler): Use names from process/thread descriptors instead.
+      NullTermStringView event_name = storage->GetString(name_id);
+      PERFETTO_DCHECK(event_name.data());
+      if (strcmp(event_name.c_str(), "thread_name") == 0) {
+        auto it = event.debug_annotations();
+        if (!it)
+          break;
+        protos::pbzero::DebugAnnotation::Decoder annotation(it->data(),
+                                                            it->size());
+        auto thread_name = annotation.string_value();
+        if (!thread_name.size)
+          break;
+        auto thread_name_id = context_->storage->InternString(thread_name);
+        procs->UpdateThreadName(tid, thread_name_id);
+      } else if (strcmp(event_name.c_str(), "process_name") == 0) {
+        auto it = event.debug_annotations();
+        if (!it)
+          break;
+        protos::pbzero::DebugAnnotation::Decoder annotation(it->data(),
+                                                            it->size());
+        auto process_name = annotation.string_value();
+        if (!process_name.size)
+          break;
+        procs->UpdateProcess(pid, base::nullopt, process_name);
+      }
+      break;
+    }
+  }
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/proto_trace_parser.h b/src/trace_processor/proto_trace_parser.h
new file mode 100644
index 0000000..75adf37
--- /dev/null
+++ b/src/trace_processor/proto_trace_parser.h
@@ -0,0 +1,184 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_PROTO_TRACE_PARSER_H_
+#define SRC_TRACE_PROCESSOR_PROTO_TRACE_PARSER_H_
+
+#include <stdint.h>
+
+#include <array>
+#include <memory>
+
+#include "perfetto/base/string_view.h"
+#include "perfetto/protozero/field.h"
+#include "src/trace_processor/ftrace_descriptors.h"
+#include "src/trace_processor/proto_incremental_state.h"
+#include "src/trace_processor/trace_blob_view.h"
+#include "src/trace_processor/trace_parser.h"
+#include "src/trace_processor/trace_storage.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class TraceProcessorContext;
+
+struct SystraceTracePoint {
+  char phase;
+  uint32_t tgid;
+
+  // For phase = 'B' and phase = 'C' only.
+  base::StringView name;
+
+  // For phase = 'C' only.
+  double value;
+};
+
+inline bool operator==(const SystraceTracePoint& x,
+                       const SystraceTracePoint& y) {
+  return std::tie(x.phase, x.tgid, x.name, x.value) ==
+         std::tie(y.phase, y.tgid, y.name, y.value);
+}
+
+enum class SystraceParseResult { kFailure = 0, kUnsupported, kSuccess };
+
+SystraceParseResult ParseSystraceTracePoint(base::StringView,
+                                            SystraceTracePoint* out);
+
+class ProtoTraceParser : public TraceParser {
+ public:
+  using ConstBytes = protozero::ConstBytes;
+  explicit ProtoTraceParser(TraceProcessorContext*);
+  ~ProtoTraceParser() override;
+
+  // TraceParser implementation.
+  void ParseTracePacket(int64_t timestamp,
+                        TraceSorter::TimestampedTracePiece) override;
+  void ParseFtracePacket(uint32_t cpu,
+                         int64_t timestamp,
+                         TraceSorter::TimestampedTracePiece) override;
+
+  void ParseProcessTree(ConstBytes);
+  void ParseProcessStats(int64_t timestamp, ConstBytes);
+  void ParseSchedSwitch(uint32_t cpu, int64_t timestamp, ConstBytes);
+  void ParseSchedWakeup(int64_t timestamp, ConstBytes);
+  void ParseTaskNewTask(int64_t timestamp, uint32_t source_tid, ConstBytes);
+  void ParseTaskRename(ConstBytes);
+  void ParseCpuFreq(int64_t timestamp, ConstBytes);
+  void ParseCpuIdle(int64_t timestamp, ConstBytes);
+  void ParsePrint(uint32_t cpu, int64_t timestamp, uint32_t pid, ConstBytes);
+  void ParseSysStats(int64_t ts, ConstBytes);
+  void ParseRssStat(int64_t ts, uint32_t pid, ConstBytes);
+  void ParseIonHeapGrowOrShrink(int64_t ts,
+                                uint32_t pid,
+                                ConstBytes,
+                                bool grow);
+  void ParseSignalDeliver(int64_t ts, uint32_t pid, ConstBytes);
+  void ParseSignalGenerate(int64_t ts, ConstBytes);
+  void ParseLowmemoryKill(int64_t ts, ConstBytes);
+  void ParseBatteryCounters(int64_t ts, ConstBytes);
+  void ParsePowerRails(ConstBytes);
+  void ParseOOMScoreAdjUpdate(int64_t ts, ConstBytes);
+  void ParseMmEventRecord(int64_t ts, uint32_t pid, ConstBytes);
+  void ParseSysEvent(int64_t ts, uint32_t pid, bool is_enter, ConstBytes);
+  void ParseClockSnapshot(ConstBytes);
+  void ParseAndroidLogPacket(ConstBytes);
+  void ParseAndroidLogEvent(ConstBytes);
+  void ParseAndroidLogStats(ConstBytes);
+  void ParseGenericFtrace(int64_t timestamp,
+                          uint32_t cpu,
+                          uint32_t pid,
+                          ConstBytes view);
+  void ParseTypedFtraceToRaw(uint32_t ftrace_id,
+                             int64_t timestamp,
+                             uint32_t cpu,
+                             uint32_t pid,
+                             ConstBytes view);
+  void ParseTraceStats(ConstBytes);
+  void ParseFtraceStats(ConstBytes);
+  void ParseProfilePacket(ConstBytes);
+  void ParseSystemInfo(ConstBytes);
+  void ParseTrackEvent(int64_t ts,
+                       int64_t tts,
+                       ProtoIncrementalState::PacketSequenceState*,
+                       ConstBytes);
+
+ private:
+  TraceProcessorContext* context_;
+  const StringId utid_name_id_;
+  const StringId sched_wakeup_name_id_;
+  const StringId cpu_freq_name_id_;
+  const StringId cpu_idle_name_id_;
+  const StringId comm_name_id_;
+  const StringId num_forks_name_id_;
+  const StringId num_irq_total_name_id_;
+  const StringId num_softirq_total_name_id_;
+  const StringId num_irq_name_id_;
+  const StringId num_softirq_name_id_;
+  const StringId cpu_times_user_ns_id_;
+  const StringId cpu_times_user_nice_ns_id_;
+  const StringId cpu_times_system_mode_ns_id_;
+  const StringId cpu_times_idle_ns_id_;
+  const StringId cpu_times_io_wait_ns_id_;
+  const StringId cpu_times_irq_ns_id_;
+  const StringId cpu_times_softirq_ns_id_;
+  const StringId signal_deliver_id_;
+  const StringId signal_generate_id_;
+  const StringId batt_charge_id_;
+  const StringId batt_capacity_id_;
+  const StringId batt_current_id_;
+  const StringId batt_current_avg_id_;
+  const StringId lmk_id_;
+  const StringId oom_score_adj_id_;
+  const StringId ion_total_unknown_id_;
+  const StringId ion_change_unknown_id_;
+  std::vector<StringId> meminfo_strs_id_;
+  std::vector<StringId> vmstat_strs_id_;
+  std::vector<StringId> rss_members_;
+  std::vector<StringId> power_rails_strs_id_;
+
+  struct FtraceMessageStrings {
+    // The string id of name of the event field (e.g. sched_switch's id).
+    StringId message_name_id = 0;
+    std::array<StringId, kMaxFtraceEventFields> field_name_ids;
+  };
+  std::vector<FtraceMessageStrings> ftrace_message_strings_;
+
+  // Maps a proto field number for memcounters in ProcessStats::Process to
+  // their StringId. Keep kProcStatsProcessSize equal to 1 + max proto field
+  // id of ProcessStats::Process.
+  static constexpr size_t kProcStatsProcessSize = 11;
+  std::array<StringId, kProcStatsProcessSize> proc_stats_process_names_{};
+
+  struct MmEventCounterNames {
+    MmEventCounterNames() = default;
+    MmEventCounterNames(StringId _count, StringId _max_lat, StringId _avg_lat)
+        : count(_count), max_lat(_max_lat), avg_lat(_avg_lat) {}
+
+    StringId count = 0;
+    StringId max_lat = 0;
+    StringId avg_lat = 0;
+  };
+
+  // Keep kMmEventCounterSize equal to mm_event_type::MM_TYPE_NUM in the kernel.
+  static constexpr size_t kMmEventCounterSize = 7;
+  std::array<MmEventCounterNames, kMmEventCounterSize> mm_event_counter_names_;
+
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_PROTO_TRACE_PARSER_H_
diff --git a/src/trace_processor/proto_trace_parser_unittest.cc b/src/trace_processor/proto_trace_parser_unittest.cc
new file mode 100644
index 0000000..c7f4ad6
--- /dev/null
+++ b/src/trace_processor/proto_trace_parser_unittest.cc
@@ -0,0 +1,992 @@
+/*
+ * 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.
+ */
+
+#include "src/trace_processor/proto_trace_tokenizer.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/string_view.h"
+#include "perfetto/protozero/scattered_heap_buffer.h"
+#include "src/trace_processor/args_tracker.h"
+#include "src/trace_processor/event_tracker.h"
+#include "src/trace_processor/process_tracker.h"
+#include "src/trace_processor/proto_trace_parser.h"
+#include "src/trace_processor/slice_tracker.h"
+#include "src/trace_processor/trace_sorter.h"
+
+#include "perfetto/common/sys_stats_counters.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace_event.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
+#include "perfetto/trace/ftrace/generic.pbzero.h"
+#include "perfetto/trace/ftrace/power.pbzero.h"
+#include "perfetto/trace/ftrace/sched.pbzero.h"
+#include "perfetto/trace/ftrace/task.pbzero.h"
+#include "perfetto/trace/interned_data/interned_data.pbzero.h"
+#include "perfetto/trace/ps/process_tree.pbzero.h"
+#include "perfetto/trace/sys_stats/sys_stats.pbzero.h"
+#include "perfetto/trace/trace.pbzero.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/track_event/debug_annotation.pbzero.h"
+#include "perfetto/trace/track_event/task_execution.pbzero.h"
+#include "perfetto/trace/track_event/thread_descriptor.pbzero.h"
+#include "perfetto/trace/track_event/track_event.pbzero.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+using ::testing::_;
+using ::testing::Args;
+using ::testing::AtLeast;
+using ::testing::ElementsAreArray;
+using ::testing::Eq;
+using ::testing::InSequence;
+using ::testing::NiceMock;
+using ::testing::Pointwise;
+using ::testing::Return;
+
+class MockEventTracker : public EventTracker {
+ public:
+  MockEventTracker(TraceProcessorContext* context) : EventTracker(context) {}
+  virtual ~MockEventTracker() = default;
+
+  MOCK_METHOD9(PushSchedSwitch,
+               void(uint32_t cpu,
+                    int64_t timestamp,
+                    uint32_t prev_pid,
+                    base::StringView prev_comm,
+                    int32_t prev_prio,
+                    int64_t prev_state,
+                    uint32_t next_pid,
+                    base::StringView next_comm,
+                    int32_t next_prio));
+
+  MOCK_METHOD6(PushCounter,
+               RowId(int64_t timestamp,
+                     double value,
+                     StringId name_id,
+                     int64_t ref,
+                     RefType ref_type,
+                     bool resolve_utid_to_upid));
+};
+
+class MockProcessTracker : public ProcessTracker {
+ public:
+  MockProcessTracker(TraceProcessorContext* context)
+      : ProcessTracker(context) {}
+
+  MOCK_METHOD3(UpdateProcess,
+               UniquePid(uint32_t pid,
+                         base::Optional<uint32_t> ppid,
+                         base::StringView process_name));
+
+  MOCK_METHOD2(UpdateThread, UniqueTid(uint32_t tid, uint32_t tgid));
+};
+
+class MockTraceStorage : public TraceStorage {
+ public:
+  MockTraceStorage() : TraceStorage() {}
+
+  MOCK_METHOD1(InternString, StringId(base::StringView));
+};
+
+class MockArgsTracker : public ArgsTracker {
+ public:
+  MockArgsTracker(TraceProcessorContext* context) : ArgsTracker(context) {}
+
+  MOCK_METHOD4(AddArg,
+               void(RowId row_id, StringId flat_key, StringId key, Variadic));
+  MOCK_METHOD0(Flush, void());
+};
+
+class MockSliceTracker : public SliceTracker {
+ public:
+  MockSliceTracker(TraceProcessorContext* context) : SliceTracker(context) {}
+
+  MOCK_METHOD4(
+      Begin,
+      void(int64_t timestamp, UniqueTid utid, StringId cat, StringId name));
+  MOCK_METHOD4(
+      End,
+      void(int64_t timestamp, UniqueTid utid, StringId cat, StringId name));
+  MOCK_METHOD5(Scoped,
+               void(int64_t timestamp,
+                    UniqueTid utid,
+                    StringId cat,
+                    StringId name,
+                    int64_t duration));
+};
+
+class ProtoTraceParserTest : public ::testing::Test {
+ public:
+  ProtoTraceParserTest() {
+    nice_storage_ = new NiceMock<MockTraceStorage>();
+    context_.storage.reset(nice_storage_);
+    args_ = new MockArgsTracker(&context_);
+    context_.args_tracker.reset(args_);
+    event_ = new MockEventTracker(&context_);
+    context_.event_tracker.reset(event_);
+    process_ = new MockProcessTracker(&context_);
+    context_.process_tracker.reset(process_);
+    slice_ = new MockSliceTracker(&context_);
+    context_.slice_tracker.reset(slice_);
+    context_.sorter.reset(new TraceSorter(&context_, 0 /*window size*/));
+    context_.parser.reset(new ProtoTraceParser(&context_));
+  }
+
+  void ResetTraceBuffers() {
+    heap_buf_.reset(new protozero::ScatteredHeapBuffer());
+    stream_writer_.reset(new protozero::ScatteredStreamWriter(heap_buf_.get()));
+    heap_buf_->set_writer(stream_writer_.get());
+    trace_.Reset(stream_writer_.get());
+  }
+
+  void SetUp() override { ResetTraceBuffers(); }
+
+  void InitStorage() {
+    storage_ = new MockTraceStorage();
+    context_.storage.reset(storage_);
+  }
+
+  void Tokenize() {
+    trace_.Finalize();
+    std::vector<uint8_t> trace_bytes = heap_buf_->StitchSlices();
+    std::unique_ptr<uint8_t[]> raw_trace(new uint8_t[trace_bytes.size()]);
+    memcpy(raw_trace.get(), trace_bytes.data(), trace_bytes.size());
+    context_.chunk_reader.reset(new ProtoTraceTokenizer(&context_));
+    context_.chunk_reader->Parse(std::move(raw_trace), trace_bytes.size());
+
+    ResetTraceBuffers();
+  }
+
+ protected:
+  std::unique_ptr<protozero::ScatteredHeapBuffer> heap_buf_;
+  std::unique_ptr<protozero::ScatteredStreamWriter> stream_writer_;
+  protos::pbzero::Trace trace_;
+  TraceProcessorContext context_;
+  MockArgsTracker* args_;
+  MockEventTracker* event_;
+  MockProcessTracker* process_;
+  MockSliceTracker* slice_;
+  NiceMock<MockTraceStorage>* nice_storage_;
+  MockTraceStorage* storage_;
+};
+
+TEST_F(ProtoTraceParserTest, LoadSingleEvent) {
+  auto* bundle = trace_.add_packet()->set_ftrace_events();
+  bundle->set_cpu(10);
+
+  auto* event = bundle->add_event();
+  event->set_timestamp(1000);
+  event->set_pid(12);
+
+  static const char kProc1Name[] = "proc1";
+  static const char kProc2Name[] = "proc2";
+  auto* sched_switch = event->set_sched_switch();
+  sched_switch->set_prev_pid(10);
+  sched_switch->set_prev_comm(kProc2Name);
+  sched_switch->set_prev_prio(256);
+  sched_switch->set_prev_state(32);
+  sched_switch->set_next_comm(kProc1Name);
+  sched_switch->set_next_pid(100);
+  sched_switch->set_next_prio(1024);
+
+  EXPECT_CALL(*event_,
+              PushSchedSwitch(10, 1000, 10, base::StringView(kProc2Name), 256,
+                              32, 100, base::StringView(kProc1Name), 1024));
+  Tokenize();
+}
+
+TEST_F(ProtoTraceParserTest, LoadEventsIntoRaw) {
+  InitStorage();
+
+  auto* bundle = trace_.add_packet()->set_ftrace_events();
+  bundle->set_cpu(10);
+
+  // This event is unknown and will only appear in
+  // raw events table.
+  auto* event = bundle->add_event();
+  event->set_timestamp(1000);
+  event->set_pid(12);
+  auto* task = event->set_task_newtask();
+  task->set_pid(123);
+  static const char task_newtask[] = "task_newtask";
+  task->set_comm(task_newtask);
+  task->set_clone_flags(12);
+  task->set_oom_score_adj(15);
+
+  // This event has specific parsing logic, but will
+  // also appear in raw events table.
+  event = bundle->add_event();
+  event->set_timestamp(1001);
+  event->set_pid(12);
+  auto* print = event->set_print();
+  print->set_ip(20);
+  static const char buf_value[] = "This is a print event";
+  print->set_buf(buf_value);
+
+  EXPECT_CALL(*storage_, InternString(base::StringView(task_newtask)))
+      .Times(AtLeast(1));
+  EXPECT_CALL(*storage_, InternString(base::StringView(buf_value)));
+  EXPECT_CALL(*process_, UpdateThread(123, 123));
+
+  Tokenize();
+  const auto& raw = context_.storage->raw_events();
+  ASSERT_EQ(raw.raw_event_count(), 2);
+  const auto& args = context_.storage->args();
+  ASSERT_EQ(args.args_count(), 6);
+  ASSERT_EQ(args.arg_values()[0].int_value, 123);
+  ASSERT_EQ(args.arg_values()[1].string_value, 0);
+  ASSERT_EQ(args.arg_values()[2].int_value, 12);
+  ASSERT_EQ(args.arg_values()[3].int_value, 15);
+  ASSERT_EQ(args.arg_values()[4].int_value, 20);
+  ASSERT_EQ(args.arg_values()[5].string_value, 0);
+
+  // TODO(taylori): Add test ftrace event with all field types
+  // and test here.
+}
+
+TEST_F(ProtoTraceParserTest, LoadGenericFtrace) {
+  InitStorage();
+  auto* packet = trace_.add_packet();
+  packet->set_timestamp(100);
+
+  auto* bundle = packet->set_ftrace_events();
+  bundle->set_cpu(4);
+
+  auto* ftrace = bundle->add_event();
+  ftrace->set_timestamp(100);
+  ftrace->set_pid(10);
+
+  auto* generic = ftrace->set_generic();
+  generic->set_event_name("Test");
+
+  auto* field = generic->add_field();
+  field->set_name("meta1");
+  field->set_str_value("value1");
+
+  field = generic->add_field();
+  field->set_name("meta2");
+  field->set_int_value(-2);
+
+  field = generic->add_field();
+  field->set_name("meta3");
+  field->set_uint_value(3);
+
+  EXPECT_CALL(*storage_, InternString(base::StringView("Test")));
+  EXPECT_CALL(*storage_, InternString(base::StringView("meta1")));
+  EXPECT_CALL(*storage_, InternString(base::StringView("value1")));
+  EXPECT_CALL(*storage_, InternString(base::StringView("meta2")));
+  EXPECT_CALL(*storage_, InternString(base::StringView("meta3")));
+
+  Tokenize();
+
+  const auto& raw = storage_->raw_events();
+
+  ASSERT_EQ(raw.raw_event_count(), 1);
+  ASSERT_EQ(raw.timestamps().back(), 100);
+  ASSERT_EQ(storage_->GetThread(raw.utids().back()).tid, 10);
+
+  auto set_id = raw.arg_set_ids().back();
+
+  const auto& args = storage_->args();
+  auto id_it =
+      std::equal_range(args.set_ids().begin(), args.set_ids().end(), set_id);
+
+  // Ignore string calls as they are handled by checking InternString calls
+  // above.
+
+  auto it = id_it.first;
+  auto row = static_cast<size_t>(std::distance(args.set_ids().begin(), it));
+  ASSERT_EQ(args.arg_values()[++row].int_value, -2);
+  ASSERT_EQ(args.arg_values()[++row].int_value, 3);
+}
+
+TEST_F(ProtoTraceParserTest, LoadMultipleEvents) {
+  auto* bundle = trace_.add_packet()->set_ftrace_events();
+  bundle->set_cpu(10);
+
+  auto* event = bundle->add_event();
+  event->set_timestamp(1000);
+  event->set_pid(12);
+
+  static const char kProcName1[] = "proc1";
+  static const char kProcName2[] = "proc2";
+  auto* sched_switch = event->set_sched_switch();
+  sched_switch->set_prev_pid(10);
+  sched_switch->set_prev_comm(kProcName2);
+  sched_switch->set_prev_prio(256);
+  sched_switch->set_prev_state(32);
+  sched_switch->set_next_comm(kProcName1);
+  sched_switch->set_next_pid(100);
+  sched_switch->set_next_prio(1024);
+
+  event = bundle->add_event();
+  event->set_timestamp(1001);
+  event->set_pid(12);
+
+  sched_switch = event->set_sched_switch();
+  sched_switch->set_prev_pid(100);
+  sched_switch->set_prev_comm(kProcName1);
+  sched_switch->set_prev_prio(256);
+  sched_switch->set_prev_state(32);
+  sched_switch->set_next_comm(kProcName2);
+  sched_switch->set_next_pid(10);
+  sched_switch->set_next_prio(512);
+
+  EXPECT_CALL(*event_,
+              PushSchedSwitch(10, 1000, 10, base::StringView(kProcName2), 256,
+                              32, 100, base::StringView(kProcName1), 1024));
+
+  EXPECT_CALL(*event_,
+              PushSchedSwitch(10, 1001, 100, base::StringView(kProcName1), 256,
+                              32, 10, base::StringView(kProcName2), 512));
+
+  Tokenize();
+}
+
+TEST_F(ProtoTraceParserTest, LoadMultiplePackets) {
+  auto* bundle = trace_.add_packet()->set_ftrace_events();
+  bundle->set_cpu(10);
+
+  auto* event = bundle->add_event();
+  event->set_timestamp(1000);
+  event->set_pid(12);
+
+  static const char kProcName1[] = "proc1";
+  static const char kProcName2[] = "proc2";
+  auto* sched_switch = event->set_sched_switch();
+  sched_switch->set_prev_pid(10);
+  sched_switch->set_prev_comm(kProcName2);
+  sched_switch->set_prev_prio(256);
+  sched_switch->set_prev_state(32);
+  sched_switch->set_next_comm(kProcName1);
+  sched_switch->set_next_pid(100);
+  sched_switch->set_next_prio(1024);
+
+  bundle = trace_.add_packet()->set_ftrace_events();
+  bundle->set_cpu(10);
+
+  event = bundle->add_event();
+  event->set_timestamp(1001);
+  event->set_pid(12);
+
+  sched_switch = event->set_sched_switch();
+  sched_switch->set_prev_pid(100);
+  sched_switch->set_prev_comm(kProcName1);
+  sched_switch->set_prev_prio(256);
+  sched_switch->set_prev_state(32);
+  sched_switch->set_next_comm(kProcName2);
+  sched_switch->set_next_pid(10);
+  sched_switch->set_next_prio(512);
+
+  EXPECT_CALL(*event_,
+              PushSchedSwitch(10, 1000, 10, base::StringView(kProcName2), 256,
+                              32, 100, base::StringView(kProcName1), 1024));
+
+  EXPECT_CALL(*event_,
+              PushSchedSwitch(10, 1001, 100, base::StringView(kProcName1), 256,
+                              32, 10, base::StringView(kProcName2), 512));
+  Tokenize();
+}
+
+TEST_F(ProtoTraceParserTest, RepeatedLoadSinglePacket) {
+  auto* bundle = trace_.add_packet()->set_ftrace_events();
+  bundle->set_cpu(10);
+  auto* event = bundle->add_event();
+  event->set_timestamp(1000);
+  event->set_pid(12);
+  static const char kProcName1[] = "proc1";
+  static const char kProcName2[] = "proc2";
+  auto* sched_switch = event->set_sched_switch();
+  sched_switch->set_prev_pid(10);
+  sched_switch->set_prev_comm(kProcName2);
+  sched_switch->set_prev_prio(256);
+  sched_switch->set_prev_state(32);
+  sched_switch->set_next_comm(kProcName1);
+  sched_switch->set_next_pid(100);
+  sched_switch->set_next_prio(1024);
+  EXPECT_CALL(*event_,
+              PushSchedSwitch(10, 1000, 10, base::StringView(kProcName2), 256,
+                              32, 100, base::StringView(kProcName1), 1024));
+  Tokenize();
+
+  bundle = trace_.add_packet()->set_ftrace_events();
+  bundle->set_cpu(10);
+  event = bundle->add_event();
+  event->set_timestamp(1001);
+  event->set_pid(12);
+  sched_switch = event->set_sched_switch();
+  sched_switch->set_prev_pid(100);
+  sched_switch->set_prev_comm(kProcName1);
+  sched_switch->set_prev_prio(256);
+  sched_switch->set_prev_state(32);
+  sched_switch->set_next_comm(kProcName2);
+  sched_switch->set_next_pid(10);
+  sched_switch->set_next_prio(512);
+
+
+  EXPECT_CALL(*event_,
+              PushSchedSwitch(10, 1001, 100, base::StringView(kProcName1), 256,
+                              32, 10, base::StringView(kProcName2), 512));
+  Tokenize();
+}
+
+TEST_F(ProtoTraceParserTest, LoadMemInfo) {
+  auto* packet = trace_.add_packet();
+  uint64_t ts = 1000;
+  packet->set_timestamp(ts);
+  auto* bundle = packet->set_sys_stats();
+  auto* meminfo = bundle->add_meminfo();
+  meminfo->set_key(protos::pbzero::MEMINFO_MEM_TOTAL);
+  uint32_t value = 10;
+  meminfo->set_value(value);
+
+  EXPECT_CALL(*event_, PushCounter(static_cast<int64_t>(ts), value * 1024, 0, 0,
+                                   RefType::kRefNoRef, false));
+  Tokenize();
+}
+
+TEST_F(ProtoTraceParserTest, LoadVmStats) {
+  auto* packet = trace_.add_packet();
+  uint64_t ts = 1000;
+  packet->set_timestamp(ts);
+  auto* bundle = packet->set_sys_stats();
+  auto* meminfo = bundle->add_vmstat();
+  meminfo->set_key(protos::pbzero::VMSTAT_COMPACT_SUCCESS);
+  uint32_t value = 10;
+  meminfo->set_value(value);
+
+  EXPECT_CALL(*event_, PushCounter(static_cast<int64_t>(ts), value, 0, 0,
+                                   RefType::kRefNoRef, false));
+  Tokenize();
+}
+
+TEST_F(ProtoTraceParserTest, LoadCpuFreq) {
+  auto* bundle = trace_.add_packet()->set_ftrace_events();
+  bundle->set_cpu(12);
+  auto* event = bundle->add_event();
+  event->set_timestamp(1000);
+  event->set_pid(12);
+  auto* cpu_freq = event->set_cpu_frequency();
+  cpu_freq->set_cpu_id(10);
+  cpu_freq->set_state(2000);
+
+  EXPECT_CALL(*event_,
+              PushCounter(1000, 2000, 0, 10, RefType::kRefCpuId, false));
+  Tokenize();
+}
+
+TEST_F(ProtoTraceParserTest, LoadProcessPacket) {
+  auto* tree = trace_.add_packet()->set_process_tree();
+  auto* process = tree->add_processes();
+  static const char kProcName1[] = "proc1";
+
+  process->add_cmdline(kProcName1);
+  process->set_pid(1);
+  process->set_ppid(2);
+
+  EXPECT_CALL(*process_,
+              UpdateProcess(1, Eq(2u), base::StringView(kProcName1)));
+  Tokenize();
+}
+
+TEST_F(ProtoTraceParserTest, LoadProcessPacket_FirstCmdline) {
+  auto* tree = trace_.add_packet()->set_process_tree();
+  auto* process = tree->add_processes();
+  static const char kProcName1[] = "proc1";
+  static const char kProcName2[] = "proc2";
+
+  process->add_cmdline(kProcName1);
+  process->add_cmdline(kProcName2);
+  process->set_pid(1);
+  process->set_ppid(2);
+
+  EXPECT_CALL(*process_,
+              UpdateProcess(1, Eq(2u), base::StringView(kProcName1)));
+  Tokenize();
+}
+
+TEST_F(ProtoTraceParserTest, LoadThreadPacket) {
+  auto* tree = trace_.add_packet()->set_process_tree();
+  auto* thread = tree->add_threads();
+  thread->set_tid(1);
+  thread->set_tgid(2);
+
+  EXPECT_CALL(*process_, UpdateThread(1, 2));
+  Tokenize();
+}
+
+TEST_F(ProtoTraceParserTest, TrackEventWithoutInternedData) {
+  InitStorage();
+  context_.sorter.reset(new TraceSorter(
+      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
+
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    packet->set_incremental_state_cleared(true);
+    auto* thread_desc = packet->set_thread_descriptor();
+    thread_desc->set_pid(15);
+    thread_desc->set_tid(16);
+    thread_desc->set_reference_timestamp_us(1000);
+    thread_desc->set_reference_thread_time_us(2000);
+  }
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    auto* event = packet->set_track_event();
+    event->set_timestamp_delta_us(10);   // absolute: 1010.
+    event->set_thread_time_delta_us(5);  // absolute: 2005.
+    event->add_category_iids(1);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(1);
+    legacy_event->set_phase('B');
+  }
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    auto* event = packet->set_track_event();
+    event->set_timestamp_delta_us(10);   // absolute: 1020.
+    event->set_thread_time_delta_us(5);  // absolute: 2010.
+    event->add_category_iids(1);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(1);
+    legacy_event->set_phase('E');
+  }
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    auto* event = packet->set_track_event();
+    event->set_timestamp_absolute_us(1005);
+    event->set_thread_time_absolute_us(2003);
+    event->add_category_iids(2);
+    event->add_category_iids(3);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(2);
+    legacy_event->set_phase('X');
+    legacy_event->set_duration_us(23);         // absolute end: 1028.
+    legacy_event->set_thread_duration_us(12);  // absolute end: 2015.
+  }
+
+  Tokenize();
+
+  EXPECT_CALL(*process_, UpdateThread(16, 15))
+      .Times(3)
+      .WillRepeatedly(Return(1));
+
+  InSequence in_sequence;  // Below slices should be sorted by timestamp.
+  EXPECT_CALL(*slice_, Scoped(1005000, 1, 0, 0, 23000));
+  EXPECT_CALL(*slice_, Begin(1010000, 1, 0, 0));
+  EXPECT_CALL(*slice_, End(1020000, 1, 0, 0));
+
+  context_.sorter->ExtractEventsForced();
+}
+
+TEST_F(ProtoTraceParserTest, TrackEventWithInternedData) {
+  InitStorage();
+  context_.sorter.reset(new TraceSorter(
+      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
+
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    packet->set_incremental_state_cleared(true);
+    auto* thread_desc = packet->set_thread_descriptor();
+    thread_desc->set_pid(15);
+    thread_desc->set_tid(16);
+    thread_desc->set_reference_timestamp_us(1000);
+    thread_desc->set_reference_thread_time_us(2000);
+  }
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    auto* event = packet->set_track_event();
+    event->set_timestamp_delta_us(10);   // absolute: 1010.
+    event->set_thread_time_delta_us(5);  // absolute: 2005.
+    event->add_category_iids(1);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(1);
+    legacy_event->set_phase('B');
+
+    auto* interned_data = packet->set_interned_data();
+    auto cat1 = interned_data->add_event_categories();
+    cat1->set_iid(1);
+    cat1->set_name("cat1");
+    auto ev1 = interned_data->add_legacy_event_names();
+    ev1->set_iid(1);
+    ev1->set_name("ev1");
+  }
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    auto* event = packet->set_track_event();
+    event->set_timestamp_delta_us(10);   // absolute: 1020.
+    event->set_thread_time_delta_us(5);  // absolute: 2010.
+    event->add_category_iids(1);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(1);
+    legacy_event->set_phase('E');
+  }
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    auto* event = packet->set_track_event();
+    event->set_timestamp_absolute_us(1005);
+    event->set_thread_time_absolute_us(2003);
+    event->add_category_iids(2);
+    event->add_category_iids(3);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(2);
+    legacy_event->set_phase('X');
+    legacy_event->set_duration_us(23);         // absolute end: 1028.
+    legacy_event->set_thread_duration_us(12);  // absolute end: 2015.
+
+    auto* interned_data = packet->set_interned_data();
+    auto cat2 = interned_data->add_event_categories();
+    cat2->set_iid(2);
+    cat2->set_name("cat2");
+    auto cat3 = interned_data->add_event_categories();
+    cat3->set_iid(3);
+    cat3->set_name("cat3");
+    auto ev2 = interned_data->add_legacy_event_names();
+    ev2->set_iid(2);
+    ev2->set_name("ev2");
+  }
+
+  Tokenize();
+
+  EXPECT_CALL(*process_, UpdateThread(16, 15))
+      .Times(3)
+      .WillRepeatedly(Return(1));
+
+  InSequence in_sequence;  // Below slices should be sorted by timestamp.
+
+  EXPECT_CALL(*storage_, InternString(base::StringView("cat2,cat3")))
+      .WillOnce(Return(1));
+  EXPECT_CALL(*storage_, InternString(base::StringView("ev2")))
+      .WillOnce(Return(2));
+  EXPECT_CALL(*slice_, Scoped(1005000, 1, 1, 2, 23000));
+
+  EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
+      .WillOnce(Return(3));
+  EXPECT_CALL(*storage_, InternString(base::StringView("ev1")))
+      .WillOnce(Return(4));
+  EXPECT_CALL(*slice_, Begin(1010000, 1, 3, 4));
+
+  EXPECT_CALL(*slice_, End(1020000, 1, 3, 4));
+
+  context_.sorter->ExtractEventsForced();
+}
+
+TEST_F(ProtoTraceParserTest, TrackEventWithoutIncrementalStateReset) {
+  InitStorage();
+  context_.sorter.reset(new TraceSorter(
+      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
+
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    auto* thread_desc = packet->set_thread_descriptor();
+    thread_desc->set_pid(15);
+    thread_desc->set_tid(16);
+    thread_desc->set_reference_timestamp_us(1000);
+    thread_desc->set_reference_thread_time_us(2000);
+  }
+  {
+    // Event should be discarded because incremental state was never cleared.
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    auto* event = packet->set_track_event();
+    event->set_timestamp_delta_us(10);   // absolute: 1010.
+    event->set_thread_time_delta_us(5);  // absolute: 2005.
+    event->add_category_iids(1);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(1);
+    legacy_event->set_phase('B');
+  }
+
+  Tokenize();
+
+  EXPECT_CALL(*slice_, Begin(_, _, _, _)).Times(0);
+  context_.sorter->ExtractEventsForced();
+}
+
+TEST_F(ProtoTraceParserTest, TrackEventWithoutThreadDescriptor) {
+  InitStorage();
+  context_.sorter.reset(new TraceSorter(
+      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
+
+  {
+    // Event should be discarded because no thread descriptor was seen yet.
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    packet->set_incremental_state_cleared(true);
+    auto* event = packet->set_track_event();
+    event->set_timestamp_delta_us(10);
+    event->set_thread_time_delta_us(5);
+    event->add_category_iids(1);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(1);
+    legacy_event->set_phase('B');
+  }
+
+  Tokenize();
+
+  EXPECT_CALL(*slice_, Begin(_, _, _, _)).Times(0);
+  context_.sorter->ExtractEventsForced();
+}
+
+TEST_F(ProtoTraceParserTest, TrackEventWithDataLoss) {
+  InitStorage();
+  context_.sorter.reset(new TraceSorter(
+      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
+
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    packet->set_incremental_state_cleared(true);
+    auto* thread_desc = packet->set_thread_descriptor();
+    thread_desc->set_pid(15);
+    thread_desc->set_tid(16);
+    thread_desc->set_reference_timestamp_us(1000);
+    thread_desc->set_reference_thread_time_us(2000);
+  }
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    auto* event = packet->set_track_event();
+    event->set_timestamp_delta_us(10);   // absolute: 1010.
+    event->set_thread_time_delta_us(5);  // absolute: 2005.
+    event->add_category_iids(1);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(1);
+    legacy_event->set_phase('B');
+  }
+  {
+    // Event should be dropped because data loss occurred before.
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    packet->set_previous_packet_dropped(true);  // Data loss occurred.
+    auto* event = packet->set_track_event();
+    event->set_timestamp_delta_us(10);
+    event->set_thread_time_delta_us(5);
+    event->add_category_iids(1);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(1);
+    legacy_event->set_phase('E');
+  }
+  {
+    // Event should be dropped because incremental state is invalid.
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    auto* event = packet->set_track_event();
+    event->set_timestamp_delta_us(10);
+    event->set_thread_time_delta_us(5);
+    event->add_category_iids(1);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(1);
+    legacy_event->set_phase('E');
+  }
+  {
+    // Event should be dropped because no new thread descriptor was seen yet.
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    packet->set_incremental_state_cleared(true);
+    auto* event = packet->set_track_event();
+    event->set_timestamp_delta_us(10);
+    event->set_thread_time_delta_us(5);
+    event->add_category_iids(1);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(1);
+    legacy_event->set_phase('E');
+  }
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    auto* thread_desc = packet->set_thread_descriptor();
+    thread_desc->set_pid(15);
+    thread_desc->set_tid(16);
+    thread_desc->set_reference_timestamp_us(2000);
+    thread_desc->set_reference_thread_time_us(3000);
+  }
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    auto* event = packet->set_track_event();
+    event->set_timestamp_delta_us(10);   // absolute: 2010.
+    event->set_thread_time_delta_us(5);  // absolute: 3005.
+    event->add_category_iids(1);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(1);
+    legacy_event->set_phase('E');
+  }
+
+  Tokenize();
+
+  EXPECT_CALL(*process_, UpdateThread(16, 15))
+      .Times(2)
+      .WillRepeatedly(Return(1));
+
+  InSequence in_sequence;  // Below slices should be sorted by timestamp.
+  EXPECT_CALL(*slice_, Begin(1010000, 1, 0, 0));
+  EXPECT_CALL(*slice_, End(2010000, 1, 0, 0));
+
+  context_.sorter->ExtractEventsForced();
+}
+
+TEST_F(ProtoTraceParserTest, TrackEventMultipleSequences) {
+  InitStorage();
+  context_.sorter.reset(new TraceSorter(
+      &context_, std::numeric_limits<int64_t>::max() /*window size*/));
+
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    packet->set_incremental_state_cleared(true);
+    auto* thread_desc = packet->set_thread_descriptor();
+    thread_desc->set_pid(15);
+    thread_desc->set_tid(16);
+    thread_desc->set_reference_timestamp_us(1000);
+    thread_desc->set_reference_thread_time_us(2000);
+  }
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    auto* event = packet->set_track_event();
+    event->set_timestamp_delta_us(10);   // absolute: 1010.
+    event->set_thread_time_delta_us(5);  // absolute: 2005.
+    event->add_category_iids(1);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(1);
+    legacy_event->set_phase('B');
+
+    auto* interned_data = packet->set_interned_data();
+    auto cat1 = interned_data->add_event_categories();
+    cat1->set_iid(1);
+    cat1->set_name("cat1");
+    auto ev1 = interned_data->add_legacy_event_names();
+    ev1->set_iid(1);
+    ev1->set_name("ev1");
+  }
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(2);
+    packet->set_incremental_state_cleared(true);
+    auto* thread_desc = packet->set_thread_descriptor();
+    thread_desc->set_pid(15);
+    thread_desc->set_tid(17);
+    thread_desc->set_reference_timestamp_us(995);
+    thread_desc->set_reference_thread_time_us(3000);
+  }
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(2);
+    auto* event = packet->set_track_event();
+    event->set_timestamp_delta_us(10);   // absolute: 1005.
+    event->set_thread_time_delta_us(5);  // absolute: 3005.
+    event->add_category_iids(1);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(1);
+    legacy_event->set_phase('B');
+
+    auto* interned_data = packet->set_interned_data();
+    auto cat1 = interned_data->add_event_categories();
+    cat1->set_iid(1);
+    cat1->set_name("cat1");
+    auto ev2 = interned_data->add_legacy_event_names();
+    ev2->set_iid(1);
+    ev2->set_name("ev2");
+  }
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(1);
+    auto* event = packet->set_track_event();
+    event->set_timestamp_delta_us(10);   // absolute: 1020.
+    event->set_thread_time_delta_us(5);  // absolute: 2010.
+    event->add_category_iids(1);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(1);
+    legacy_event->set_phase('E');
+  }
+  {
+    auto* packet = trace_.add_packet();
+    packet->set_trusted_packet_sequence_id(2);
+    auto* event = packet->set_track_event();
+    event->set_timestamp_delta_us(10);   // absolute: 1015.
+    event->set_thread_time_delta_us(5);  // absolute: 3015.
+    event->add_category_iids(1);
+    auto* legacy_event = event->set_legacy_event();
+    legacy_event->set_name_iid(1);
+    legacy_event->set_phase('E');
+  }
+
+  Tokenize();
+
+  EXPECT_CALL(*process_, UpdateThread(16, 15))
+      .Times(2)
+      .WillRepeatedly(Return(1));
+  EXPECT_CALL(*process_, UpdateThread(17, 15))
+      .Times(2)
+      .WillRepeatedly(Return(2));
+
+  InSequence in_sequence;  // Below slices should be sorted by timestamp.
+
+  EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
+      .WillOnce(Return(1));
+  EXPECT_CALL(*storage_, InternString(base::StringView("ev2")))
+      .WillOnce(Return(2));
+
+  EXPECT_CALL(*slice_, Begin(1005000, 2, 1, 2));
+
+  EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
+      .WillOnce(Return(1));
+  EXPECT_CALL(*storage_, InternString(base::StringView("ev1")))
+      .WillOnce(Return(3));
+
+  EXPECT_CALL(*slice_, Begin(1010000, 1, 1, 3));
+  EXPECT_CALL(*slice_, End(1015000, 2, 1, 2));
+  EXPECT_CALL(*slice_, End(1020000, 1, 1, 3));
+
+  context_.sorter->ExtractEventsForced();
+}
+
+TEST(SystraceParserTest, SystraceEvent) {
+  SystraceTracePoint result{};
+
+  ASSERT_EQ(ParseSystraceTracePoint(base::StringView(""), &result),
+            SystraceParseResult::kFailure);
+
+  ASSERT_EQ(ParseSystraceTracePoint(base::StringView("B|1|foo"), &result),
+            SystraceParseResult::kSuccess);
+  EXPECT_EQ(result, (SystraceTracePoint{'B', 1, base::StringView("foo"), 0}));
+
+  ASSERT_EQ(ParseSystraceTracePoint(base::StringView("B|42|Bar"), &result),
+            SystraceParseResult::kSuccess);
+  EXPECT_EQ(result, (SystraceTracePoint{'B', 42, base::StringView("Bar"), 0}));
+
+  ASSERT_EQ(ParseSystraceTracePoint(base::StringView("C|543|foo|8"), &result),
+            SystraceParseResult::kSuccess);
+  EXPECT_EQ(result, (SystraceTracePoint{'C', 543, base::StringView("foo"), 8}));
+
+  ASSERT_EQ(ParseSystraceTracePoint(base::StringView("S|"), &result),
+            SystraceParseResult::kUnsupported);
+}
+
+}  // namespace
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/proto_trace_tokenizer.cc b/src/trace_processor/proto_trace_tokenizer.cc
new file mode 100644
index 0000000..2e54577
--- /dev/null
+++ b/src/trace_processor/proto_trace_tokenizer.cc
@@ -0,0 +1,463 @@
+/*
+ * 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.
+ */
+
+#include "src/trace_processor/proto_trace_tokenizer.h"
+
+#include <string>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/protozero/proto_decoder.h"
+#include "perfetto/protozero/proto_utils.h"
+#include "src/trace_processor/event_tracker.h"
+#include "src/trace_processor/process_tracker.h"
+#include "src/trace_processor/stats.h"
+#include "src/trace_processor/trace_blob_view.h"
+#include "src/trace_processor/trace_sorter.h"
+#include "src/trace_processor/trace_storage.h"
+
+#include "perfetto/trace/ftrace/ftrace_event.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
+#include "perfetto/trace/interned_data/interned_data.pbzero.h"
+#include "perfetto/trace/trace.pbzero.h"
+#include "perfetto/trace/track_event/task_execution.pbzero.h"
+#include "perfetto/trace/track_event/thread_descriptor.pbzero.h"
+#include "perfetto/trace/track_event/track_event.pbzero.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+using protozero::ProtoDecoder;
+using protozero::proto_utils::MakeTagLengthDelimited;
+using protozero::proto_utils::MakeTagVarInt;
+using protozero::proto_utils::ParseVarInt;
+
+namespace {
+
+template <typename MessageType>
+void InternMessage(TraceProcessorContext* context,
+                   ProtoIncrementalState::PacketSequenceState* state,
+                   TraceBlobView message) {
+  constexpr auto kIidFieldNumber = MessageType::kIidFieldNumber;
+
+  uint32_t iid = 0;
+  auto message_start = message.data();
+  auto message_size = message.length();
+  protozero::ProtoDecoder decoder(message_start, message_size);
+
+  auto field = decoder.FindField(kIidFieldNumber);
+  if (PERFETTO_UNLIKELY(!field)) {
+    PERFETTO_ELOG("Interned message without interning_id");
+    context->storage->IncrementStats(stats::interned_data_tokenizer_errors);
+    return;
+  }
+  iid = field.as_uint32();
+
+  auto res = state->GetInternedDataMap<MessageType>()->emplace(
+      iid,
+      ProtoIncrementalState::InternedDataView<MessageType>(std::move(message)));
+  // If a message with this ID is already interned, its data should not have
+  // changed (this is forbidden by the InternedData proto).
+  // TODO(eseckler): This DCHECK assumes that the message is encoded the
+  // same way whenever it is re-emitted.
+  PERFETTO_DCHECK(res.second ||
+                  (res.first->second.message.length() == message_size &&
+                   memcmp(res.first->second.message.data(), message_start,
+                          message_size) == 0));
+}
+
+}  // namespace
+
+// static
+TraceType ProtoTraceTokenizer::GuessProtoTraceType(const uint8_t* data,
+                                                   size_t size) {
+  // Scan at most the first 128MB for a track event packet.
+  constexpr size_t kMaxScanSize = 128 * 1024 * 1024;
+  protos::pbzero::Trace::Decoder decoder(data, std::min(size, kMaxScanSize));
+  if (!decoder.has_packet())
+    return TraceType::kUnknownTraceType;
+  for (auto it = decoder.packet(); it; ++it) {
+    ProtoDecoder packet_decoder(it->data(), it->size());
+    if (PERFETTO_UNLIKELY(packet_decoder.FindField(
+            protos::pbzero::TracePacket::kTrackEventFieldNumber))) {
+      return TraceType::kProtoWithTrackEventsTraceType;
+    }
+  }
+  return TraceType::kProtoTraceType;
+}
+
+ProtoTraceTokenizer::ProtoTraceTokenizer(TraceProcessorContext* ctx)
+    : context_(ctx) {}
+ProtoTraceTokenizer::~ProtoTraceTokenizer() = default;
+
+bool ProtoTraceTokenizer::Parse(std::unique_ptr<uint8_t[]> owned_buf,
+                                size_t size) {
+  uint8_t* data = &owned_buf[0];
+  if (!partial_buf_.empty()) {
+    // It takes ~5 bytes for a proto preamble + the varint size.
+    const size_t kHeaderBytes = 5;
+    if (PERFETTO_UNLIKELY(partial_buf_.size() < kHeaderBytes)) {
+      size_t missing_len = std::min(kHeaderBytes - partial_buf_.size(), size);
+      partial_buf_.insert(partial_buf_.end(), &data[0], &data[missing_len]);
+      if (partial_buf_.size() < kHeaderBytes)
+        return true;
+      data += missing_len;
+      size -= missing_len;
+    }
+
+    // At this point we have enough data in |partial_buf_| to read at least the
+    // field header and know the size of the next TracePacket.
+    constexpr uint8_t kTracePacketTag =
+        MakeTagLengthDelimited(protos::pbzero::Trace::kPacketFieldNumber);
+    const uint8_t* pos = &partial_buf_[0];
+    uint8_t proto_field_tag = *pos;
+    uint64_t field_size = 0;
+    const uint8_t* next = ParseVarInt(++pos, &*partial_buf_.end(), &field_size);
+    bool parse_failed = next == pos;
+    pos = next;
+    if (proto_field_tag != kTracePacketTag || field_size == 0 || parse_failed) {
+      PERFETTO_ELOG("Failed parsing a TracePacket from the partial buffer");
+      return false;  // Unrecoverable error, stop parsing.
+    }
+
+    // At this point we know how big the TracePacket is.
+    size_t hdr_size = static_cast<size_t>(pos - &partial_buf_[0]);
+    size_t size_incl_header = static_cast<size_t>(field_size + hdr_size);
+    PERFETTO_DCHECK(size_incl_header > partial_buf_.size());
+
+    // There is a good chance that between the |partial_buf_| and the new |data|
+    // of the current call we have enough bytes to parse a TracePacket.
+    if (partial_buf_.size() + size >= size_incl_header) {
+      // Create a new buffer for the whole TracePacket and copy into that:
+      // 1) The beginning of the TracePacket (including the proto header) from
+      //    the partial buffer.
+      // 2) The rest of the TracePacket from the current |data| buffer (note
+      //    that we might have consumed already a few bytes form |data| earlier
+      //    in this function, hence we need to keep |off| into account).
+      std::unique_ptr<uint8_t[]> buf(new uint8_t[size_incl_header]);
+      memcpy(&buf[0], partial_buf_.data(), partial_buf_.size());
+      // |size_missing| is the number of bytes for the rest of the TracePacket
+      // in |data|.
+      size_t size_missing = size_incl_header - partial_buf_.size();
+      memcpy(&buf[partial_buf_.size()], &data[0], size_missing);
+      data += size_missing;
+      size -= size_missing;
+      partial_buf_.clear();
+      uint8_t* buf_start = &buf[0];  // Note that buf is std::moved below.
+      ParseInternal(std::move(buf), buf_start, size_incl_header);
+    } else {
+      partial_buf_.insert(partial_buf_.end(), data, &data[size]);
+      return true;
+    }
+  }
+  ParseInternal(std::move(owned_buf), data, size);
+  return true;
+}
+
+void ProtoTraceTokenizer::ParseInternal(std::unique_ptr<uint8_t[]> owned_buf,
+                                        uint8_t* data,
+                                        size_t size) {
+  PERFETTO_DCHECK(data >= &owned_buf[0]);
+  const uint8_t* start = &owned_buf[0];
+  const size_t data_off = static_cast<size_t>(data - start);
+  TraceBlobView whole_buf(std::move(owned_buf), data_off, size);
+
+  protos::pbzero::Trace::Decoder decoder(data, size);
+  for (auto it = decoder.packet(); it; ++it) {
+    size_t field_offset = whole_buf.offset_of(it->data());
+    ParsePacket(whole_buf.slice(field_offset, it->size()));
+  }
+
+  const size_t bytes_left = decoder.bytes_left();
+  if (bytes_left > 0) {
+    PERFETTO_DCHECK(partial_buf_.empty());
+    partial_buf_.insert(partial_buf_.end(), &data[decoder.read_offset()],
+                        &data[decoder.read_offset() + bytes_left]);
+  }
+}
+
+void ProtoTraceTokenizer::ParsePacket(TraceBlobView packet) {
+  protos::pbzero::TracePacket::Decoder decoder(packet.data(), packet.length());
+  PERFETTO_DCHECK(!decoder.bytes_left());
+
+  auto timestamp = decoder.has_timestamp()
+                       ? static_cast<int64_t>(decoder.timestamp())
+                       : latest_timestamp_;
+  latest_timestamp_ = std::max(timestamp, latest_timestamp_);
+
+  if (decoder.incremental_state_cleared()) {
+    HandleIncrementalStateCleared(decoder);
+  } else if (decoder.previous_packet_dropped()) {
+    HandlePreviousPacketDropped(decoder);
+  }
+
+  if (decoder.has_interned_data()) {
+    auto field = decoder.interned_data();
+    const size_t offset = packet.offset_of(field.data);
+    ParseInternedData(decoder, packet.slice(offset, field.size));
+  }
+
+  if (decoder.has_ftrace_events()) {
+    auto ftrace_field = decoder.ftrace_events();
+    const size_t fld_off = packet.offset_of(ftrace_field.data);
+    ParseFtraceBundle(packet.slice(fld_off, ftrace_field.size));
+    return;
+  }
+
+  if (decoder.has_track_event()) {
+    ParseTrackEventPacket(decoder, std::move(packet));
+    return;
+  }
+
+  if (decoder.has_thread_descriptor()) {
+    ParseThreadDescriptorPacket(decoder);
+    return;
+  }
+
+  // Use parent data and length because we want to parse this again
+  // later to get the exact type of the packet.
+  context_->sorter->PushTracePacket(timestamp, std::move(packet));
+}
+
+void ProtoTraceTokenizer::HandleIncrementalStateCleared(
+    const protos::pbzero::TracePacket::Decoder& packet_decoder) {
+  if (PERFETTO_UNLIKELY(!packet_decoder.has_trusted_packet_sequence_id())) {
+    PERFETTO_ELOG(
+        "incremental_state_cleared without trusted_packet_sequence_id");
+    context_->storage->IncrementStats(stats::interned_data_tokenizer_errors);
+    return;
+  }
+  GetIncrementalStateForPacketSequence(
+      packet_decoder.trusted_packet_sequence_id())
+      ->OnIncrementalStateCleared();
+}
+
+void ProtoTraceTokenizer::HandlePreviousPacketDropped(
+    const protos::pbzero::TracePacket::Decoder& packet_decoder) {
+  if (PERFETTO_UNLIKELY(!packet_decoder.has_trusted_packet_sequence_id())) {
+    PERFETTO_ELOG("previous_packet_dropped without trusted_packet_sequence_id");
+    context_->storage->IncrementStats(stats::interned_data_tokenizer_errors);
+    return;
+  }
+  GetIncrementalStateForPacketSequence(
+      packet_decoder.trusted_packet_sequence_id())
+      ->OnPacketLoss();
+}
+
+void ProtoTraceTokenizer::ParseInternedData(
+    const protos::pbzero::TracePacket::Decoder& packet_decoder,
+    TraceBlobView interned_data) {
+  if (PERFETTO_UNLIKELY(!packet_decoder.has_trusted_packet_sequence_id())) {
+    PERFETTO_ELOG("InternedData packet without trusted_packet_sequence_id");
+    context_->storage->IncrementStats(stats::interned_data_tokenizer_errors);
+    return;
+  }
+
+  auto* state = GetIncrementalStateForPacketSequence(
+      packet_decoder.trusted_packet_sequence_id());
+
+  protos::pbzero::InternedData::Decoder interned_data_decoder(
+      interned_data.data(), interned_data.length());
+
+  // Store references to interned data submessages into the sequence's state.
+  for (auto it = interned_data_decoder.event_categories(); it; ++it) {
+    size_t offset = interned_data.offset_of(it->data());
+    InternMessage<protos::pbzero::EventCategory>(
+        context_, state, interned_data.slice(offset, it->size()));
+  }
+
+  for (auto it = interned_data_decoder.legacy_event_names(); it; ++it) {
+    size_t offset = interned_data.offset_of(it->data());
+    InternMessage<protos::pbzero::LegacyEventName>(
+        context_, state, interned_data.slice(offset, it->size()));
+  }
+
+  for (auto it = interned_data_decoder.debug_annotation_names(); it; ++it) {
+    size_t offset = interned_data.offset_of(it->data());
+    InternMessage<protos::pbzero::DebugAnnotationName>(
+        context_, state, interned_data.slice(offset, it->size()));
+  }
+
+  for (auto it = interned_data_decoder.source_locations(); it; ++it) {
+    size_t offset = interned_data.offset_of(it->data());
+    InternMessage<protos::pbzero::SourceLocation>(
+        context_, state, interned_data.slice(offset, it->size()));
+  }
+}
+
+void ProtoTraceTokenizer::ParseThreadDescriptorPacket(
+    const protos::pbzero::TracePacket::Decoder& packet_decoder) {
+  if (PERFETTO_UNLIKELY(!packet_decoder.has_trusted_packet_sequence_id())) {
+    PERFETTO_ELOG("ThreadDescriptor packet without trusted_packet_sequence_id");
+    context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
+    return;
+  }
+
+  auto* state = GetIncrementalStateForPacketSequence(
+      packet_decoder.trusted_packet_sequence_id());
+
+  // TrackEvents will be ignored while incremental state is invalid. As a
+  // consequence, we should also ignore any ThreadDescriptors received in this
+  // state. Otherwise, any delta-encoded timestamps would be calculated
+  // incorrectly once we move out of the packet loss state. Instead, wait until
+  // the first subsequent descriptor after incremental state is cleared.
+  if (!state->IsIncrementalStateValid()) {
+    context_->storage->IncrementStats(
+        stats::track_event_tokenizer_skipped_packets);
+    return;
+  }
+
+  auto thread_descriptor_field = packet_decoder.thread_descriptor();
+  protos::pbzero::ThreadDescriptor::Decoder thread_descriptor_decoder(
+      thread_descriptor_field.data, thread_descriptor_field.size);
+
+  state->SetThreadDescriptor(
+      thread_descriptor_decoder.pid(), thread_descriptor_decoder.tid(),
+      thread_descriptor_decoder.reference_timestamp_us() * 1000,
+      thread_descriptor_decoder.reference_thread_time_us() * 1000);
+  // TODO(eseckler): Handle other thread_descriptor fields (e.g. thread
+  // name/type).
+}
+
+void ProtoTraceTokenizer::ParseTrackEventPacket(
+    const protos::pbzero::TracePacket::Decoder& packet_decoder,
+    TraceBlobView packet) {
+  constexpr auto kTimestampDeltaUsFieldNumber =
+      protos::pbzero::TrackEvent::kTimestampDeltaUsFieldNumber;
+  constexpr auto kTimestampAbsoluteUsFieldNumber =
+      protos::pbzero::TrackEvent::kTimestampAbsoluteUsFieldNumber;
+  constexpr auto kThreadTimeDeltaUsFieldNumber =
+      protos::pbzero::TrackEvent::kThreadTimeDeltaUsFieldNumber;
+  constexpr auto kThreadTimeAbsoluteUsFieldNumber =
+      protos::pbzero::TrackEvent::kThreadTimeAbsoluteUsFieldNumber;
+
+  if (PERFETTO_UNLIKELY(!packet_decoder.has_trusted_packet_sequence_id())) {
+    PERFETTO_ELOG("TrackEvent packet without trusted_packet_sequence_id");
+    context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
+    return;
+  }
+
+  auto* state = GetIncrementalStateForPacketSequence(
+      packet_decoder.trusted_packet_sequence_id());
+
+  // TrackEvents can only be parsed correctly while incremental state for their
+  // sequence is valid and after a ThreadDescriptor has been parsed.
+  if (!state->IsTrackEventStateValid()) {
+    context_->storage->IncrementStats(
+        stats::track_event_tokenizer_skipped_packets);
+    return;
+  }
+
+  auto field = packet_decoder.track_event();
+  ProtoDecoder event_decoder(field.data, field.size);
+
+  int64_t timestamp;
+  int64_t thread_timestamp = 0;
+
+  if (auto ts_delta_field =
+          event_decoder.FindField(kTimestampDeltaUsFieldNumber)) {
+    timestamp = state->IncrementAndGetTrackEventTimeNs(
+        ts_delta_field.as_int64() * 1000);
+  } else if (auto ts_absolute_field =
+                 event_decoder.FindField(kTimestampAbsoluteUsFieldNumber)) {
+    // One-off absolute timestamps don't affect delta computation.
+    timestamp = ts_absolute_field.as_int64() * 1000;
+  } else {
+    PERFETTO_ELOG("TrackEvent without timestamp");
+    context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
+    return;
+  }
+
+  if (auto tt_delta_field =
+          event_decoder.FindField(kThreadTimeDeltaUsFieldNumber)) {
+    thread_timestamp = state->IncrementAndGetTrackEventThreadTimeNs(
+        tt_delta_field.as_int64() * 1000);
+  } else if (auto tt_absolute_field =
+                 event_decoder.FindField(kThreadTimeAbsoluteUsFieldNumber)) {
+    // One-off absolute timestamps don't affect delta computation.
+    thread_timestamp = tt_absolute_field.as_int64() * 1000;
+  }
+
+  context_->sorter->PushTrackEventPacket(timestamp, thread_timestamp, state,
+                                         std::move(packet));
+}
+
+PERFETTO_ALWAYS_INLINE
+void ProtoTraceTokenizer::ParseFtraceBundle(TraceBlobView bundle) {
+  protos::pbzero::FtraceEventBundle::Decoder decoder(bundle.data(),
+                                                     bundle.length());
+
+  if (PERFETTO_UNLIKELY(!decoder.has_cpu())) {
+    PERFETTO_ELOG("CPU field not found in FtraceEventBundle");
+    context_->storage->IncrementStats(stats::ftrace_bundle_tokenizer_errors);
+    return;
+  }
+
+  uint32_t cpu = decoder.cpu();
+  if (PERFETTO_UNLIKELY(cpu > base::kMaxCpus)) {
+    PERFETTO_ELOG("CPU larger than kMaxCpus (%u > %zu)", cpu, base::kMaxCpus);
+    return;
+  }
+
+  for (auto it = decoder.event(); it; ++it) {
+    size_t off = bundle.offset_of(it->data());
+    ParseFtraceEvent(cpu, bundle.slice(off, it->size()));
+  }
+  context_->sorter->FinalizeFtraceEventBatch(cpu);
+}
+
+PERFETTO_ALWAYS_INLINE
+void ProtoTraceTokenizer::ParseFtraceEvent(uint32_t cpu, TraceBlobView event) {
+  constexpr auto kTimestampFieldNumber =
+      protos::pbzero::FtraceEvent::kTimestampFieldNumber;
+  const uint8_t* data = event.data();
+  const size_t length = event.length();
+  ProtoDecoder decoder(data, length);
+  uint64_t raw_timestamp = 0;
+  bool timestamp_found = false;
+
+  // Speculate on the fact that the timestamp is often the 1st field of the
+  // event.
+  constexpr auto timestampFieldTag = MakeTagVarInt(kTimestampFieldNumber);
+  if (PERFETTO_LIKELY(length > 10 && data[0] == timestampFieldTag)) {
+    // Fastpath.
+    const uint8_t* next = ParseVarInt(data + 1, data + 11, &raw_timestamp);
+    timestamp_found = next != data + 1;
+    decoder.Reset(next);
+  } else {
+    // Slowpath.
+    if (auto ts_field = decoder.FindField(kTimestampFieldNumber)) {
+      timestamp_found = true;
+      raw_timestamp = ts_field.as_uint64();
+    }
+  }
+
+  if (PERFETTO_UNLIKELY(!timestamp_found)) {
+    PERFETTO_ELOG("Timestamp field not found in FtraceEvent");
+    context_->storage->IncrementStats(stats::ftrace_bundle_tokenizer_errors);
+    return;
+  }
+
+  int64_t timestamp = static_cast<int64_t>(raw_timestamp);
+  latest_timestamp_ = std::max(timestamp, latest_timestamp_);
+
+  // We don't need to parse this packet, just push it to be sorted with
+  // the timestamp.
+  context_->sorter->PushFtraceEvent(cpu, timestamp, std::move(event));
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/proto_trace_tokenizer.h b/src/trace_processor/proto_trace_tokenizer.h
new file mode 100644
index 0000000..95b1a22
--- /dev/null
+++ b/src/trace_processor/proto_trace_tokenizer.h
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_PROTO_TRACE_TOKENIZER_H_
+#define SRC_TRACE_PROCESSOR_PROTO_TRACE_TOKENIZER_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <vector>
+
+#include "src/trace_processor/chunked_trace_reader.h"
+#include "src/trace_processor/proto_incremental_state.h"
+#include "src/trace_processor/trace_processor_impl.h"
+
+#include "perfetto/trace/trace_packet.pbzero.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class TraceProcessorContext;
+class TraceBlobView;
+class TraceSorter;
+class TraceStorage;
+
+// Reads a protobuf trace in chunks and extracts boundaries of trace packets
+// (or subfields, for the case of ftrace) with their timestamps.
+class ProtoTraceTokenizer : public ChunkedTraceReader {
+ public:
+  // Scans the beginning of the trace for valid TracePackets to determine if the
+  // trace contains TrackEvents.
+  //
+  // TODO(eseckler): This is a pretty bad hack to enable us to choose a
+  // different sorting window size for traces with TrackEvents. We should
+  // reconsider and redesign our sorting strategy, so that we don't need to
+  // change global trace processor options if TrackEvents are present.
+  static TraceType GuessProtoTraceType(const uint8_t* data, size_t size);
+
+  // |reader| is the abstract method of getting chunks of size |chunk_size_b|
+  // from a trace file with these chunks parsed into |trace|.
+  explicit ProtoTraceTokenizer(TraceProcessorContext*);
+  ~ProtoTraceTokenizer() override;
+
+  // ChunkedTraceReader implementation.
+  bool Parse(std::unique_ptr<uint8_t[]>, size_t size) override;
+
+ private:
+  void ParseInternal(std::unique_ptr<uint8_t[]> owned_buf,
+                     uint8_t* data,
+                     size_t size);
+  void ParsePacket(TraceBlobView);
+  void HandleIncrementalStateCleared(
+      const protos::pbzero::TracePacket::Decoder& packet_decoder);
+  void HandlePreviousPacketDropped(
+      const protos::pbzero::TracePacket::Decoder& packet_decoder);
+  void ParseInternedData(
+      const protos::pbzero::TracePacket::Decoder& packet_decoder,
+      TraceBlobView interned_data);
+  void ParseThreadDescriptorPacket(
+      const protos::pbzero::TracePacket::Decoder& packet_decoder);
+  void ParseTrackEventPacket(
+      const protos::pbzero::TracePacket::Decoder& packet_decoder,
+      TraceBlobView packet);
+  void ParseFtraceBundle(TraceBlobView);
+  void ParseFtraceEvent(uint32_t cpu, TraceBlobView);
+
+  ProtoIncrementalState::PacketSequenceState*
+  GetIncrementalStateForPacketSequence(uint32_t sequence_id) {
+    if (!incremental_state)
+      incremental_state.reset(new ProtoIncrementalState());
+    return incremental_state->GetOrCreateStateForPacketSequence(sequence_id);
+  }
+
+  TraceProcessorContext* context_;
+
+  // Used to glue together trace packets that span across two (or more)
+  // Parse() boundaries.
+  std::vector<uint8_t> partial_buf_;
+
+  // Temporary. Currently trace packets do not have a timestamp, so the
+  // timestamp given is latest_timestamp_.
+  int64_t latest_timestamp_ = 0;
+
+  // Stores incremental state and references to interned data, e.g. for track
+  // event protos.
+  std::unique_ptr<ProtoIncrementalState> incremental_state;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_PROTO_TRACE_TOKENIZER_H_
diff --git a/src/trace_processor/query_constraints.cc b/src/trace_processor/query_constraints.cc
new file mode 100644
index 0000000..9092cb7
--- /dev/null
+++ b/src/trace_processor/query_constraints.cc
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+#include "src/trace_processor/query_constraints.h"
+
+#include <sqlite3.h>
+#include <string>
+
+#include "perfetto/base/string_splitter.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+QueryConstraints::QueryConstraints() = default;
+QueryConstraints::~QueryConstraints() = default;
+QueryConstraints::QueryConstraints(QueryConstraints&&) noexcept = default;
+QueryConstraints& QueryConstraints::operator=(QueryConstraints&&) = default;
+
+int QueryConstraints::FreeSqliteString(char* resource) {
+  sqlite3_free(resource);
+  return 0;
+}
+
+bool QueryConstraints::operator==(const QueryConstraints& other) const {
+  if ((other.constraints().size() != constraints().size()) ||
+      (other.order_by().size() != order_by().size())) {
+    return false;
+  }
+
+  for (size_t i = 0; i < constraints().size(); ++i) {
+    if ((constraints()[i].iColumn != other.constraints()[i].iColumn) ||
+        (constraints()[i].op != other.constraints()[i].op)) {
+      return false;
+    }
+  }
+
+  for (size_t i = 0; i < order_by().size(); ++i) {
+    if ((order_by()[i].iColumn != other.order_by()[i].iColumn) ||
+        (order_by()[i].desc != other.order_by()[i].desc)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+void QueryConstraints::AddConstraint(int column, unsigned char op) {
+  Constraint c{};
+  c.iColumn = column;
+  c.op = op;
+  constraints_.emplace_back(c);
+}
+
+void QueryConstraints::AddOrderBy(int column, unsigned char desc) {
+  OrderBy ob{};
+  ob.iColumn = column;
+  ob.desc = desc;
+  order_by_.emplace_back(ob);
+}
+
+QueryConstraints::SqliteString QueryConstraints::ToNewSqlite3String() const {
+  std::string str_result;
+  str_result.reserve(512);
+  str_result.append("C");
+  str_result.append(std::to_string(constraints_.size()));
+  str_result.append(",");
+  for (const auto& cs : constraints_) {
+    str_result.append(std::to_string(cs.iColumn));
+    str_result.append(",");
+    str_result.append(std::to_string(cs.op));
+    str_result.append(",");
+  }
+  str_result.append("O");
+  str_result.append(std::to_string(order_by_.size()));
+  str_result.append(",");
+  for (const auto& ob : order_by_) {
+    str_result.append(std::to_string(ob.iColumn));
+    str_result.append(",");
+    str_result.append(std::to_string(ob.desc));
+    str_result.append(",");
+  }
+
+  // The last char is a "," so overwriting with the null terminator on purpose.
+  SqliteString result(
+      static_cast<char*>(sqlite3_malloc(static_cast<int>(str_result.size()))));
+  strncpy(result.get(), str_result.c_str(), str_result.size());
+  (*result)[str_result.size() - 1] = '\0';
+
+  return result;
+}
+
+QueryConstraints QueryConstraints::FromString(const char* idxStr) {
+  QueryConstraints qc;
+
+  base::StringSplitter splitter(std::string(idxStr), ',');
+
+  PERFETTO_CHECK(splitter.Next() && splitter.cur_token_size() > 1);
+  // The '+ 1' skips the letter 'C' in the first token.
+  long num_constraints = strtol(splitter.cur_token() + 1, nullptr, 10);
+  for (int i = 0; i < num_constraints; ++i) {
+    PERFETTO_CHECK(splitter.Next());
+    int col = static_cast<int>(strtol(splitter.cur_token(), nullptr, 10));
+    PERFETTO_CHECK(splitter.Next());
+    unsigned char op =
+        static_cast<unsigned char>(strtol(splitter.cur_token(), nullptr, 10));
+    qc.AddConstraint(col, op);
+  }
+
+  PERFETTO_CHECK(splitter.Next() && splitter.cur_token_size() > 1);
+  // The '+ 1' skips the letter 'O' in the current token.
+  long num_order_by = strtol(splitter.cur_token() + 1, nullptr, 10);
+  for (int i = 0; i < num_order_by; ++i) {
+    PERFETTO_CHECK(splitter.Next());
+    int col = static_cast<int>(strtol(splitter.cur_token(), nullptr, 10));
+    PERFETTO_CHECK(splitter.Next());
+    unsigned char desc =
+        static_cast<unsigned char>(strtol(splitter.cur_token(), nullptr, 10));
+    qc.AddOrderBy(col, desc);
+  }
+
+  PERFETTO_DCHECK(!splitter.Next());
+  return qc;
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/query_constraints.h b/src/trace_processor/query_constraints.h
new file mode 100644
index 0000000..e9dc48b
--- /dev/null
+++ b/src/trace_processor/query_constraints.h
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_QUERY_CONSTRAINTS_H_
+#define SRC_TRACE_PROCESSOR_QUERY_CONSTRAINTS_H_
+
+#include <sqlite3.h>
+
+#include <vector>
+
+#include "perfetto/base/scoped_file.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+// This class stores the constraints (including the order-by information) for
+// a query on a sqlite3 virtual table and handles their de/serialization into
+// strings.
+// This is because the constraint columns and the order-by clauses are passed
+// to the xBestIndex method but the constraint values are available only in the
+// xFilter method. Unfortunately sqlite vtable API don't give any hint about
+// the validity of the constraints (i.e. constraints passed to xBestIndex can
+// be used by future xFilter calls in the far future). The only mechanism
+// offered by sqlite is the idxStr string which is returned by the vtable
+// in the xBestIndex call and passed to each corresponding xFilter call.
+class QueryConstraints {
+ public:
+  using Constraint = sqlite3_index_info::sqlite3_index_constraint;
+  using OrderBy = sqlite3_index_info::sqlite3_index_orderby;
+
+  static int FreeSqliteString(char* resource);
+
+  using SqliteString = base::ScopedResource<char*, FreeSqliteString, nullptr>;
+
+  QueryConstraints();
+  ~QueryConstraints();
+  QueryConstraints(QueryConstraints&&) noexcept;
+  QueryConstraints& operator=(QueryConstraints&&);
+
+  // Two QueryConstraints with the same constraint and orderby vectors
+  // are equal.
+  bool operator==(const QueryConstraints& other) const;
+
+  void AddConstraint(int column, unsigned char op);
+
+  void AddOrderBy(int column, unsigned char desc);
+
+  void ClearOrderBy() { order_by_.clear(); }
+
+  // Converts the constraints and order by information to a string for
+  // use by sqlite.
+  SqliteString ToNewSqlite3String() const;
+
+  // Deserializes the string into QueryConstraints. String given is in the form
+  // C{# of constraints},col1,op1,col2,op2...,O{# of order by},col1,desc1...
+  // For example C1,0,3,O2,1,0,4,1
+  static QueryConstraints FromString(const char* idxStr);
+
+  const std::vector<OrderBy>& order_by() const { return order_by_; }
+
+  const std::vector<Constraint>& constraints() const { return constraints_; }
+
+ private:
+  QueryConstraints(const QueryConstraints&) = delete;
+  QueryConstraints& operator=(const QueryConstraints&) = delete;
+
+  std::vector<OrderBy> order_by_;
+  std::vector<Constraint> constraints_;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_QUERY_CONSTRAINTS_H_
diff --git a/src/trace_processor/query_constraints_unittest.cc b/src/trace_processor/query_constraints_unittest.cc
new file mode 100644
index 0000000..0435087
--- /dev/null
+++ b/src/trace_processor/query_constraints_unittest.cc
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+#include "src/trace_processor/query_constraints.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/logging.h"
+
+using testing::ElementsAreArray;
+using testing::Matcher;
+using testing::Field;
+using testing::Pointwise;
+using testing::Matches;
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+TEST(QueryConstraintsTest, ConvertToAndFromSqlString) {
+  QueryConstraints qc;
+  qc.AddConstraint(12, 0);
+
+  QueryConstraints::SqliteString only_constraint = qc.ToNewSqlite3String();
+  ASSERT_TRUE(strcmp(only_constraint.get(), "C1,12,0,O0") == 0);
+
+  QueryConstraints qc_constraint =
+      QueryConstraints::FromString(only_constraint.get());
+  ASSERT_EQ(qc, qc_constraint);
+
+  qc.AddOrderBy(1, false);
+  qc.AddOrderBy(21, true);
+
+  QueryConstraints::SqliteString result = qc.ToNewSqlite3String();
+  ASSERT_TRUE(strcmp(result.get(), "C1,12,0,O2,1,0,21,1") == 0);
+
+  QueryConstraints qc_result = QueryConstraints::FromString(result.get());
+  ASSERT_EQ(qc, qc_result);
+}
+
+TEST(QueryConstraintsTest, CheckEmptyConstraints) {
+  QueryConstraints qc;
+
+  QueryConstraints::SqliteString string_result = qc.ToNewSqlite3String();
+  ASSERT_TRUE(strcmp(string_result.get(), "C0,O0") == 0);
+
+  QueryConstraints qc_result =
+      QueryConstraints::FromString(string_result.get());
+  ASSERT_EQ(qc_result.constraints().size(), 0);
+  ASSERT_EQ(qc_result.order_by().size(), 0);
+}
+
+TEST(QueryConstraintsTest, OnlyOrderBy) {
+  QueryConstraints qc;
+  qc.AddOrderBy(3, true);
+
+  QueryConstraints::SqliteString string_result = qc.ToNewSqlite3String();
+  ASSERT_TRUE(strcmp(string_result.get(), "C0,O1,3,1") == 0);
+
+  QueryConstraints qc_result =
+      QueryConstraints::FromString(string_result.get());
+  ASSERT_EQ(qc, qc_result);
+}
+
+}  // namespace
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/raw_table.cc b/src/trace_processor/raw_table.cc
index 29d86ef..c18e851 100644
--- a/src/trace_processor/raw_table.cc
+++ b/src/trace_processor/raw_table.cc
@@ -18,24 +18,20 @@
 
 #include <inttypes.h>
 
-#include "perfetto/base/compiler.h"
-#include "src/trace_processor/sqlite/sqlite_utils.h"
-#include "src/trace_processor/variadic.h"
+#include "src/trace_processor/ftrace_descriptors.h"
+#include "src/trace_processor/sqlite_utils.h"
 
-#include "protos/perfetto/trace/ftrace/binder.pbzero.h"
-#include "protos/perfetto/trace/ftrace/clk.pbzero.h"
-#include "protos/perfetto/trace/ftrace/filemap.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/sched.pbzero.h"
-#include "protos/perfetto/trace/ftrace/workqueue.pbzero.h"
+#include "perfetto/trace/ftrace/binder.pbzero.h"
+#include "perfetto/trace/ftrace/clk.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace_event.pbzero.h"
+#include "perfetto/trace/ftrace/sched.pbzero.h"
 
 namespace perfetto {
 namespace trace_processor {
 
 RawTable::RawTable(sqlite3* db, const TraceStorage* storage)
     : storage_(storage) {
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
   auto fn = [](sqlite3_context* ctx, int argc, sqlite3_value** argv) {
     auto* thiz = static_cast<RawTable*>(sqlite3_user_data(ctx));
     thiz->ToSystrace(ctx, argc, argv);
@@ -43,13 +39,10 @@
   sqlite3_create_function(db, "to_ftrace", 1,
                           SQLITE_UTF8 | SQLITE_DETERMINISTIC, this, fn, nullptr,
                           nullptr);
-#else   // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-  base::ignore_result(db);
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
 }
 
 void RawTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
-  SqliteTable::Register<RawTable>(db, storage, "raw");
+  Table::Register<RawTable>(db, storage, "raw");
 }
 
 StorageSchema RawTable::CreateStorageSchema() {
@@ -70,19 +63,17 @@
 
 int RawTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
   info->estimated_cost = RowCount();
-  info->sqlite_omit_order_by = true;
 
   // Only the string columns are handled by SQLite
+  info->order_by_consumed = true;
   size_t name_index = schema().ColumnIndexFromName("name");
   for (size_t i = 0; i < qc.constraints().size(); i++) {
-    info->constraint_info[i].sqlite_omit =
-        qc.constraints()[i].iColumn != static_cast<int>(name_index);
+    info->omit[i] = qc.constraints()[i].iColumn != static_cast<int>(name_index);
   }
 
   return SQLITE_OK;
 }
 
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
 void RawTable::FormatSystraceArgs(NullTermStringView event_name,
                                   ArgSetId arg_set_id,
                                   base::StringWriter* writer) {
@@ -91,34 +82,20 @@
   auto ub = std::find(lb, set_ids.end(), arg_set_id + 1);
 
   auto start_row = static_cast<uint32_t>(std::distance(set_ids.begin(), lb));
-  auto end_row = static_cast<uint32_t>(std::distance(set_ids.begin(), ub));
+
+  using Variadic = TraceStorage::Args::Variadic;
   using ValueWriter = std::function<void(const Variadic&)>;
   auto write_value = [this, writer](const Variadic& value) {
     switch (value.type) {
-      case Variadic::kInt:
+      case TraceStorage::Args::Variadic::kInt:
         writer->AppendInt(value.int_value);
         break;
-      case Variadic::kUint:
-        writer->AppendUnsignedInt(value.uint_value);
-        break;
-      case Variadic::kString: {
-        const auto& str = storage_->GetString(value.string_value);
-        writer->AppendString(str.c_str(), str.size());
-        break;
-      }
-      case Variadic::kReal:
+      case TraceStorage::Args::Variadic::kReal:
         writer->AppendDouble(value.real_value);
         break;
-      case Variadic::kPointer:
-        writer->AppendUnsignedInt(value.pointer_value);
-        break;
-      case Variadic::kBool:
-        writer->AppendBool(value.bool_value);
-        break;
-      case Variadic::kJson: {
-        const auto& str = storage_->GetString(value.json_value);
+      case TraceStorage::Args::Variadic::kString: {
+        const auto& str = storage_->GetString(value.string_value);
         writer->AppendString(str.c_str(), str.size());
-        break;
       }
     }
   };
@@ -145,9 +122,8 @@
     write_arg(SS::kPrevPidFieldNumber - 1, write_value);
     write_arg(SS::kPrevPrioFieldNumber - 1, write_value);
     write_arg(SS::kPrevStateFieldNumber - 1, [writer](const Variadic& value) {
-      PERFETTO_DCHECK(value.type == Variadic::Type::kInt);
       auto state = static_cast<uint16_t>(value.int_value);
-      writer->AppendString(ftrace_utils::TaskState(state).ToString('|').data());
+      writer->AppendString(ftrace_utils::TaskState(state).ToString().data());
     });
     writer->AppendLiteral(" ==>");
     write_arg(SS::kNextCommFieldNumber - 1, write_value);
@@ -160,7 +136,6 @@
     write_arg(SW::kPidFieldNumber - 1, write_value);
     write_arg(SW::kPrioFieldNumber - 1, write_value);
     write_arg(SW::kTargetCpuFieldNumber - 1, [writer](const Variadic& value) {
-      PERFETTO_DCHECK(value.type == Variadic::Type::kInt);
       writer->AppendPaddedInt<'0', 3>(value.int_value);
     });
     return;
@@ -196,14 +171,12 @@
     writer->AppendString(" flags=0x");
     write_value_at_index(
         BT::kFlagsFieldNumber - 1, [writer](const Variadic& value) {
-          PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-          writer->AppendHexInt(value.uint_value);
+          writer->AppendHexInt(static_cast<uint32_t>(value.int_value));
         });
     writer->AppendString(" code=0x");
     write_value_at_index(
         BT::kCodeFieldNumber - 1, [writer](const Variadic& value) {
-          PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-          writer->AppendHexInt(value.uint_value);
+          writer->AppendHexInt(static_cast<uint32_t>(value.int_value));
         });
     return;
   } else if (event_name == "binder_transaction_alloc_buf") {
@@ -218,40 +191,10 @@
     writer->AppendString(" transaction=");
     write_value_at_index(BTR::kDebugIdFieldNumber - 1, write_value);
     return;
-  } else if (event_name == "mm_filemap_add_to_page_cache") {
-    using MFA = protos::pbzero::MmFilemapAddToPageCacheFtraceEvent;
-    writer->AppendString(" dev ");
-    write_value_at_index(MFA::kSDevFieldNumber - 1,
-                         [writer](const Variadic& value) {
-                           PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-                           writer->AppendUnsignedInt(value.uint_value >> 20);
-                         });
-    writer->AppendString(":");
-    write_value_at_index(
-        MFA::kSDevFieldNumber - 1, [writer](const Variadic& value) {
-          PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-          writer->AppendUnsignedInt(value.uint_value & ((1 << 20) - 1));
-        });
-    writer->AppendString(" ino ");
-    write_value_at_index(MFA::kIInoFieldNumber - 1,
-                         [writer](const Variadic& value) {
-                           PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-                           writer->AppendHexInt(value.uint_value);
-                         });
-    writer->AppendString(" page=0000000000000000");
-    writer->AppendString(" pfn=");
-    write_value_at_index(MFA::kPfnFieldNumber - 1, write_value);
-    writer->AppendString(" ofs=");
-    write_value_at_index(MFA::kIndexFieldNumber - 1,
-                         [writer](const Variadic& value) {
-                           PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-                           writer->AppendUnsignedInt(value.uint_value << 12);
-                         });
-    return;
   } else if (event_name == "print") {
-    // 'ip' may be the first field or it may be dropped. We only care
-    // about the 'buf' field which will always appear last.
-    uint32_t arg_row = end_row - 1;
+    using P = protos::pbzero::PrintFtraceEvent;
+
+    uint32_t arg_row = start_row + P::kBufFieldNumber - 1;
     const auto& args = storage_->args();
     const auto& value = args.arg_values()[arg_row];
     const auto& str = storage_->GetString(value.string_value);
@@ -262,67 +205,6 @@
     writer->AppendChar(' ');
     writer->AppendString(str.c_str(), chars_to_print);
     return;
-  } else if (event_name == "sched_blocked_reason") {
-    using SBR = protos::pbzero::SchedBlockedReasonFtraceEvent;
-    write_arg(SBR::kPidFieldNumber - 1, write_value);
-    write_arg(SBR::kIoWaitFieldNumber - 1, write_value);
-    write_arg(SBR::kCallerFieldNumber - 1, [writer](const Variadic& value) {
-      PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-      writer->AppendHexInt(value.uint_value);
-    });
-    return;
-  } else if (event_name == "workqueue_activate_work") {
-    using WAW = protos::pbzero::WorkqueueActivateWorkFtraceEvent;
-    writer->AppendString(" work struct ");
-    write_value_at_index(WAW::kWorkFieldNumber - 1,
-                         [writer](const Variadic& value) {
-                           PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-                           writer->AppendHexInt(value.uint_value);
-                         });
-    return;
-  } else if (event_name == "workqueue_execute_start") {
-    using WES = protos::pbzero::WorkqueueExecuteStartFtraceEvent;
-    writer->AppendString(" work struct ");
-    write_value_at_index(WES::kWorkFieldNumber - 1,
-                         [writer](const Variadic& value) {
-                           PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-                           writer->AppendHexInt(value.uint_value);
-                         });
-    writer->AppendString(": function ");
-    write_value_at_index(WES::kFunctionFieldNumber - 1,
-                         [writer](const Variadic& value) {
-                           PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-                           writer->AppendHexInt(value.uint_value);
-                         });
-    return;
-  } else if (event_name == "workqueue_execute_end") {
-    using WE = protos::pbzero::WorkqueueExecuteEndFtraceEvent;
-    writer->AppendString(" work struct ");
-    write_value_at_index(WE::kWorkFieldNumber - 1,
-                         [writer](const Variadic& value) {
-                           PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-                           writer->AppendHexInt(value.uint_value);
-                         });
-    return;
-  } else if (event_name == "workqueue_queue_work") {
-    using WQW = protos::pbzero::WorkqueueQueueWorkFtraceEvent;
-    writer->AppendString(" work struct=");
-    write_value_at_index(WQW::kWorkFieldNumber - 1,
-                         [writer](const Variadic& value) {
-                           PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-                           writer->AppendHexInt(value.uint_value);
-                         });
-    write_arg(WQW::kFunctionFieldNumber - 1, [writer](const Variadic& value) {
-      PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-      writer->AppendHexInt(value.uint_value);
-    });
-    write_arg(WQW::kWorkqueueFieldNumber - 1, [writer](const Variadic& value) {
-      PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
-      writer->AppendHexInt(value.uint_value);
-    });
-    write_value_at_index(WQW::kReqCpuFieldNumber - 1, write_value);
-    write_value_at_index(WQW::kCpuFieldNumber - 1, write_value);
-    return;
   }
 
   uint32_t arg = 0;
@@ -372,7 +254,6 @@
   FormatSystraceArgs(event_name, raw_evts.arg_set_ids()[row], &writer);
   sqlite3_result_text(ctx, writer.CreateStringCopy(), -1, free);
 }
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
 
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/raw_table.h b/src/trace_processor/raw_table.h
index 690c0ac..5bc02f3 100644
--- a/src/trace_processor/raw_table.h
+++ b/src/trace_processor/raw_table.h
@@ -17,7 +17,6 @@
 #ifndef SRC_TRACE_PROCESSOR_RAW_TABLE_H_
 #define SRC_TRACE_PROCESSOR_RAW_TABLE_H_
 
-#include "perfetto/base/logging.h"
 #include "src/trace_processor/storage_table.h"
 #include "src/trace_processor/trace_storage.h"
 
@@ -36,12 +35,10 @@
   int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
 
  private:
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
   void FormatSystraceArgs(NullTermStringView event_name,
                           ArgSetId arg_set_id,
                           base::StringWriter* writer);
   void ToSystrace(sqlite3_context* ctx, int argc, sqlite3_value** argv);
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
 
   const TraceStorage* const storage_;
 };
diff --git a/src/trace_processor/read_trace.cc b/src/trace_processor/read_trace.cc
deleted file mode 100644
index 0d73cf9..0000000
--- a/src/trace_processor/read_trace.cc
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/trace_processor/read_trace.h"
-
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/trace_processor/trace_processor.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
-#define PERFETTO_HAS_AIO_H() 1
-#else
-#define PERFETTO_HAS_AIO_H() 0
-#endif
-
-#if PERFETTO_HAS_AIO_H()
-#include <aio.h>
-#endif
-
-namespace perfetto {
-namespace trace_processor {
-
-util::Status ReadTrace(
-    TraceProcessor* tp,
-    const char* filename,
-    const std::function<void(uint64_t parsed_size)>& progress_callback) {
-  base::ScopedFile fd(base::OpenFile(filename, O_RDONLY));
-  if (!fd)
-    return util::ErrStatus("Could not open trace file (path: %s)", filename);
-
-  // 1MB chunk size seems the best tradeoff on a MacBook Pro 2013 - i7 2.8 GHz.
-  constexpr size_t kChunkSize = 1024 * 1024;
-  uint64_t file_size = 0;
-
-#if PERFETTO_HAS_AIO_H()
-  // Load the trace in chunks using async IO. We create a simple pipeline where,
-  // at each iteration, we parse the current chunk and asynchronously start
-  // reading the next chunk.
-  struct aiocb cb {};
-  cb.aio_nbytes = kChunkSize;
-  cb.aio_fildes = *fd;
-
-  std::unique_ptr<uint8_t[]> aio_buf(new uint8_t[kChunkSize]);
-#if defined(MEMORY_SANITIZER)
-  // Just initialize the memory to make the memory sanitizer happy as it
-  // cannot track aio calls below.
-  memset(aio_buf.get(), 0, kChunkSize);
-#endif  // defined(MEMORY_SANITIZER)
-  cb.aio_buf = aio_buf.get();
-
-  PERFETTO_CHECK(aio_read(&cb) == 0);
-  struct aiocb* aio_list[1] = {&cb};
-
-  for (int i = 0;; i++) {
-    if (progress_callback && i % 128 == 0)
-      progress_callback(file_size);
-
-    // Block waiting for the pending read to complete.
-    PERFETTO_CHECK(aio_suspend(aio_list, 1, nullptr) == 0);
-    auto rsize = aio_return(&cb);
-    if (rsize <= 0)
-      break;
-    file_size += static_cast<uint64_t>(rsize);
-
-    // Take ownership of the completed buffer and enqueue a new async read
-    // with a fresh buffer.
-    std::unique_ptr<uint8_t[]> buf(std::move(aio_buf));
-    aio_buf.reset(new uint8_t[kChunkSize]);
-#if defined(MEMORY_SANITIZER)
-    // Just initialize the memory to make the memory sanitizer happy as it
-    // cannot track aio calls below.
-    memset(aio_buf.get(), 0, kChunkSize);
-#endif  // defined(MEMORY_SANITIZER)
-    cb.aio_buf = aio_buf.get();
-    cb.aio_offset += rsize;
-    PERFETTO_CHECK(aio_read(&cb) == 0);
-
-    // Parse the completed buffer while the async read is in-flight.
-    util::Status status = tp->Parse(std::move(buf), static_cast<size_t>(rsize));
-    if (PERFETTO_UNLIKELY(!status.ok()))
-      return status;
-  }
-#else   // PERFETTO_HAS_AIO_H()
-  // Load the trace in chunks using ordinary read().
-  // This version is used on Windows, since there's no aio library.
-  for (int i = 0;; i++) {
-    if (progress_callback && i % 128 == 0)
-      progress_callback(file_size);
-
-    std::unique_ptr<uint8_t[]> buf(new uint8_t[kChunkSize]);
-    auto rsize = read(*fd, buf.get(), kChunkSize);
-    if (rsize <= 0)
-      break;
-    file_size += static_cast<uint64_t>(rsize);
-
-    util::Status status = tp->Parse(std::move(buf), static_cast<size_t>(rsize));
-    if (PERFETTO_UNLIKELY(!status.ok()))
-      return status;
-  }
-#endif  // PERFETTO_HAS_AIO_H()
-
-  tp->NotifyEndOfFile();
-  tp->SetCurrentTraceName(filename);
-
-  if (progress_callback)
-    progress_callback(file_size);
-  return util::OkStatus();
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/row_iterators.cc b/src/trace_processor/row_iterators.cc
index 98816c5..41cb359 100644
--- a/src/trace_processor/row_iterators.cc
+++ b/src/trace_processor/row_iterators.cc
@@ -18,7 +18,7 @@
 
 #include <algorithm>
 
-#include "src/trace_processor/sqlite/sqlite_utils.h"
+#include "src/trace_processor/sqlite_utils.h"
 
 namespace perfetto {
 namespace trace_processor {
diff --git a/src/trace_processor/rpc/BUILD.gn b/src/trace_processor/rpc/BUILD.gn
deleted file mode 100644
index 02ef12f..0000000
--- a/src/trace_processor/rpc/BUILD.gn
+++ /dev/null
@@ -1,67 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../../gn/perfetto.gni")
-import("../../../gn/wasm.gni")
-
-# Prevent that this file is accidentally included in embedder builds.
-assert(enable_perfetto_trace_processor)
-
-# This source_set is used both by WASM (for the function-call-based query
-# interface) and by the :httpd module for the HTTP interface.
-source_set("rpc") {
-  sources = [
-    "rpc.cc",
-    "rpc.h",
-  ]
-  deps = [
-    "../../../gn:default_deps",
-    "../../../include/perfetto/trace_processor",
-    "../../../protos/perfetto/trace_processor:zero",
-    "../../base",
-    "../../protozero",
-  ]
-}
-
-if (enable_perfetto_trace_processor_httpd) {
-  source_set("httpd") {
-    sources = [
-      "httpd.cc",
-      "httpd.h",
-    ]
-    deps = [
-      ":rpc",
-      "../../../gn:default_deps",
-      "../../../include/perfetto/trace_processor",
-      "../../../protos/perfetto/trace_processor:zero",
-      "../../base",
-      "../../base:unix_socket",
-      "../../protozero",
-    ]
-  }
-}
-
-if (enable_perfetto_ui && is_wasm) {
-  source_set("wasm_bridge") {
-    sources = [
-      "wasm_bridge.cc",
-    ]
-    deps = [
-      ":rpc",
-      "../../../gn:default_deps",
-      "../../../include/perfetto/trace_processor",
-      "../../base",
-    ]
-  }
-}
diff --git a/src/trace_processor/rpc/README.md b/src/trace_processor/rpc/README.md
deleted file mode 100644
index 802be0e..0000000
--- a/src/trace_processor/rpc/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# TraceProcessor RPC
-
-This directory contains the RPC interfaces to use the Perfetto Trace Processor
-remotely (i.e. not just in-process). It consists of two targets:
-
-## `wasm_bridge`
-
-The WASM (Web Asssembly) interop bridge. It's used to call the Trace Processor
-from HTML/JS using WASM's `ccall`.
-
-## `httpd`
-
-The HTTP RPC module. It exposes a protobuf-over-HTTP RPC interface that allows
-interacting with a remote trace processor instance. It's used for special UI
-use cases (very large traces > 2GB) and for python interoperability.
diff --git a/src/trace_processor/rpc/httpd.cc b/src/trace_processor/rpc/httpd.cc
deleted file mode 100644
index 73c1bca..0000000
--- a/src/trace_processor/rpc/httpd.cc
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/base/build_config.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_HTTPD)
-
-#include "src/trace_processor/rpc/httpd.h"
-
-#include <map>
-#include <string>
-
-#include "perfetto/ext/base/paged_memory.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/ext/base/unix_socket.h"
-#include "perfetto/ext/base/unix_task_runner.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "perfetto/trace_processor/trace_processor.h"
-#include "src/trace_processor/rpc/rpc.h"
-
-#include "protos/perfetto/trace_processor/trace_processor.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-
-constexpr char kBindAddr[] = "127.0.0.1:9001";
-constexpr auto kBlocking = base::UnixSocket::BlockingMode::kBlocking;
-
-// 32 MiB payload + 128K for HTTP headers.
-constexpr size_t kMaxRequestSize = (32 * 1024 + 128) * 1024;
-
-// Owns the socket and data for one HTTP client connection.
-struct Client {
-  Client(std::unique_ptr<base::UnixSocket> s)
-      : sock(std::move(s)),
-        rxbuf(base::PagedMemory::Allocate(kMaxRequestSize)) {}
-  size_t rxbuf_avail() { return rxbuf.size() - rxbuf_used; }
-
-  std::unique_ptr<base::UnixSocket> sock;
-  base::PagedMemory rxbuf;
-  size_t rxbuf_used = 0;
-};
-
-struct HttpRequest {
-  base::StringView method;
-  base::StringView uri;
-  base::StringView origin;
-  base::StringView body;
-};
-
-class HttpServer : public base::UnixSocket::EventListener {
- public:
-  explicit HttpServer(std::unique_ptr<TraceProcessor>);
-  ~HttpServer() override;
-  void Run();
-
- private:
-  size_t ParseOneHttpRequest(Client* client);
-  void HandleRequest(Client*, const HttpRequest&);
-
-  void OnNewIncomingConnection(base::UnixSocket*,
-                               std::unique_ptr<base::UnixSocket>) override;
-  void OnConnect(base::UnixSocket* self, bool connected) override;
-  void OnDisconnect(base::UnixSocket* self) override;
-  void OnDataAvailable(base::UnixSocket* self) override;
-
-  Rpc trace_processor_rpc_;
-  base::UnixTaskRunner task_runner_;
-  std::unique_ptr<base::UnixSocket> sock_;
-  std::vector<Client> clients_;
-};
-
-void Append(std::vector<char>& buf, const char* str) {
-  buf.insert(buf.end(), str, str + strlen(str));
-}
-
-void Append(std::vector<char>& buf, const std::string& str) {
-  buf.insert(buf.end(), str.begin(), str.end());
-}
-
-void HttpReply(base::UnixSocket* sock,
-               const char* http_code,
-               std::initializer_list<const char*> headers = {},
-               const uint8_t* body = nullptr,
-               size_t body_len = 0) {
-  std::vector<char> response;
-  response.reserve(4096);
-  Append(response, "HTTP/1.1 ");
-  Append(response, http_code);
-  Append(response, "\r\n");
-  for (const char* hdr : headers) {
-    Append(response, hdr);
-    Append(response, "\r\n");
-  }
-  Append(response, "Content-Length: ");
-  Append(response, std::to_string(body_len));
-  Append(response, "\r\n\r\n");  // End-of-headers marker.
-  sock->Send(response.data(), response.size(), /*fd=*/-1, kBlocking);
-  if (body_len)
-    sock->Send(body, body_len, /*fd=*/-1, kBlocking);
-}
-
-void ShutdownBadRequest(base::UnixSocket* sock, const char* reason) {
-  HttpReply(sock, "500 Bad Request", {},
-            reinterpret_cast<const uint8_t*>(reason), strlen(reason));
-  sock->Shutdown(/*notify=*/true);
-}
-
-HttpServer::HttpServer(std::unique_ptr<TraceProcessor> preloaded_instance)
-    : trace_processor_rpc_(std::move(preloaded_instance)) {}
-HttpServer::~HttpServer() = default;
-
-void HttpServer::Run() {
-  PERFETTO_ILOG("[HTTP] Starting RPC server on %s", kBindAddr);
-  sock_ = base::UnixSocket::Listen(kBindAddr, this, &task_runner_,
-                                   base::SockFamily::kInet,
-                                   base::SockType::kStream);
-  task_runner_.Run();
-}
-
-void HttpServer::OnNewIncomingConnection(
-    base::UnixSocket*,
-    std::unique_ptr<base::UnixSocket> sock) {
-  PERFETTO_DLOG("[HTTP] New connection");
-  clients_.emplace_back(std::move(sock));
-}
-
-void HttpServer::OnConnect(base::UnixSocket*, bool) {}
-
-void HttpServer::OnDisconnect(base::UnixSocket* sock) {
-  PERFETTO_DLOG("[HTTP] Client disconnected");
-  for (auto it = clients_.begin(); it != clients_.end(); ++it) {
-    if (it->sock.get() == sock) {
-      clients_.erase(it);
-      return;
-    }
-  }
-  PERFETTO_DFATAL("[HTTP] untracked client in OnDisconnect()");
-}
-
-void HttpServer::OnDataAvailable(base::UnixSocket* sock) {
-  Client* client = nullptr;
-  for (auto it = clients_.begin(); it != clients_.end() && !client; ++it)
-    client = (it->sock.get() == sock) ? &*it : nullptr;
-  PERFETTO_CHECK(client);
-
-  char* rxbuf = reinterpret_cast<char*>(client->rxbuf.Get());
-  for (;;) {
-    size_t avail = client->rxbuf_avail();
-    PERFETTO_CHECK(avail <= kMaxRequestSize);
-    if (avail == 0)
-      return ShutdownBadRequest(sock, "Request body too big");
-    size_t rsize = sock->Receive(&rxbuf[client->rxbuf_used], avail);
-    client->rxbuf_used += rsize;
-    if (rsize == 0 || client->rxbuf_avail() == 0)
-      break;
-  }
-
-  // At this point |rxbuf| can contain a partial HTTP request, a full one or
-  // more (in case of HTTP Keepalive pipelining).
-  for (;;) {
-    size_t bytes_consumed = ParseOneHttpRequest(client);
-    if (bytes_consumed == 0)
-      break;
-    memmove(rxbuf, &rxbuf[bytes_consumed], client->rxbuf_used - bytes_consumed);
-    client->rxbuf_used -= bytes_consumed;
-  }
-}
-
-// Parses the HTTP request and invokes HandleRequest(). It returns the size of
-// the HTTP header + body that has been processed or 0 if there isn't enough
-// data for a full HTTP request in the buffer.
-size_t HttpServer::ParseOneHttpRequest(Client* client) {
-  auto* rxbuf = reinterpret_cast<char*>(client->rxbuf.Get());
-  base::StringView buf_view(rxbuf, client->rxbuf_used);
-  size_t pos = 0;
-  size_t body_offset = 0;
-  size_t body_size = 0;
-  bool has_parsed_first_line = false;
-  HttpRequest http_req;
-
-  // This loop parses the HTTP request headers and sets the |body_offset|.
-  for (;;) {
-    size_t next = buf_view.find("\r\n", pos);
-    size_t col;
-    if (next == std::string::npos)
-      break;
-
-    if (!has_parsed_first_line) {
-      // Parse the "GET /xxx HTTP/1.1" line.
-      has_parsed_first_line = true;
-      size_t space = buf_view.find(' ');
-      if (space == std::string::npos || space + 2 >= client->rxbuf_used) {
-        ShutdownBadRequest(client->sock.get(), "Malformed HTTP request");
-        return 0;
-      }
-      http_req.method = buf_view.substr(0, space);
-      size_t uri_size = buf_view.find(' ', space + 1) - space - 1;
-      http_req.uri = buf_view.substr(space + 1, uri_size);
-    } else if (next == pos) {
-      // The CR-LF marker that separates headers from body.
-      body_offset = next + 2;
-      break;
-    } else if ((col = buf_view.find(':', pos)) < next) {
-      // Parse HTTP headers. They look like: "Content-Length: 1234".
-      auto hdr_name = buf_view.substr(pos, col - pos);
-      auto hdr_value = buf_view.substr(col + 2, next - col - 2);
-      if (hdr_name.CaseInsensitiveEq("content-length")) {
-        body_size = static_cast<size_t>(atoi(hdr_value.ToStdString().c_str()));
-      } else if (hdr_name.CaseInsensitiveEq("origin")) {
-        http_req.origin = hdr_value;
-      }
-    }
-    pos = next + 2;
-  }
-
-  // If we have a full header but not yet the full body, return and try again
-  // next time we receive some more data.
-  size_t http_req_size = body_offset + body_size;
-  if (!body_offset || client->rxbuf_used < http_req_size)
-    return 0;
-
-  http_req.body = base::StringView(&rxbuf[body_offset], body_size);
-  HandleRequest(client, http_req);
-  return http_req_size;
-}
-
-void HttpServer::HandleRequest(Client* client, const HttpRequest& req) {
-  PERFETTO_LOG("[HTTP] %s %s (body: %zu bytes)",
-               req.method.ToStdString().c_str(), req.uri.ToStdString().c_str(),
-               req.body.size());
-  std::string allow_origin_hdr =
-      "Access-Control-Allow-Origin: " + req.origin.ToStdString();
-  std::initializer_list<const char*> headers = {
-      "Connection: Keep-Alive",                //
-      "Access-Control-Expose-Headers: *",      //
-      "Keep-Alive: timeout=5, max=1000",       //
-      "Content-Type: application/x-protobuf",  //
-      allow_origin_hdr.c_str()};
-
-  if (req.method == "OPTIONS") {
-    // CORS headers.
-    return HttpReply(client->sock.get(), "204 No Content",
-                     {
-                         "Access-Control-Allow-Methods: POST, GET, OPTIONS",
-                         "Access-Control-Allow-Headers: *",
-                         "Access-Control-Max-Age: 600",
-                         allow_origin_hdr.c_str(),
-                     });
-  }
-
-  if (req.uri == "/parse") {
-    trace_processor_rpc_.Parse(
-        reinterpret_cast<const uint8_t*>(req.body.data()), req.body.size());
-    return HttpReply(client->sock.get(), "200 OK", headers);
-  }
-
-  if (req.uri == "/notify_eof") {
-    trace_processor_rpc_.NotifyEndOfFile();
-    return HttpReply(client->sock.get(), "200 OK", headers);
-  }
-
-  if (req.uri == "/restore_initial_tables") {
-    trace_processor_rpc_.RestoreInitialTables();
-    return HttpReply(client->sock.get(), "200 OK", headers);
-  }
-
-  if (req.uri == "/raw_query") {
-    PERFETTO_CHECK(req.body.size() > 0u);
-    std::vector<uint8_t> response = trace_processor_rpc_.RawQuery(
-        reinterpret_cast<const uint8_t*>(req.body.data()), req.body.size());
-    return HttpReply(client->sock.get(), "200 OK", headers, response.data(),
-                     response.size());
-  }
-
-  if (req.uri == "/status") {
-    protozero::HeapBuffered<protos::pbzero::StatusResult> res;
-    res->set_loaded_trace_name(
-        trace_processor_rpc_.GetCurrentTraceName().c_str());
-    std::vector<uint8_t> buf = res.SerializeAsArray();
-    return HttpReply(client->sock.get(), "200 OK", headers, buf.data(),
-                     buf.size());
-  }
-
-  return HttpReply(client->sock.get(), "404 Not Found", headers);
-}
-
-}  // namespace
-
-void RunHttpRPCServer(std::unique_ptr<TraceProcessor> preloaded_instance) {
-  HttpServer srv(std::move(preloaded_instance));
-  srv.Run();
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // PERFETTO_TP_HTTPD
diff --git a/src/trace_processor/rpc/httpd.h b/src/trace_processor/rpc/httpd.h
deleted file mode 100644
index b145da8..0000000
--- a/src/trace_processor/rpc/httpd.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_RPC_HTTPD_H_
-#define SRC_TRACE_PROCESSOR_RPC_HTTPD_H_
-
-#include <memory>
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessor;
-
-// Starts a RPC server that handles requests using protobuf-over-HTTP.
-// It takes control of the calling thread and does not return.
-// The unique_ptr argument is optional. If non-null, the HTTP server will adopt
-// an existing instance with a pre-loaded trace. If null, it will create a new
-// instance when pushing data into the /parse endpoint.
-void RunHttpRPCServer(std::unique_ptr<TraceProcessor>);
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_RPC_HTTPD_H_
diff --git a/src/trace_processor/rpc/rpc.cc b/src/trace_processor/rpc/rpc.cc
deleted file mode 100644
index f943b80..0000000
--- a/src/trace_processor/rpc/rpc.cc
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/rpc/rpc.h"
-
-#include <vector>
-
-#include "perfetto/base/time.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "perfetto/trace_processor/trace_processor.h"
-#include "protos/perfetto/trace_processor/trace_processor.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-using ColumnValues = protos::pbzero::RawQueryResult::ColumnValues;
-using ColumnDesc = protos::pbzero::RawQueryResult::ColumnDesc;
-
-// Writes a "Loading trace ..." update every N bytes.
-constexpr size_t kProgressUpdateBytes = 50 * 1000 * 1000;
-
-Rpc::Rpc(std::unique_ptr<TraceProcessor> preloaded_instance)
-    : trace_processor_(std::move(preloaded_instance)) {}
-
-Rpc::Rpc() : Rpc(nullptr) {}
-
-Rpc::~Rpc() = default;
-
-util::Status Rpc::Parse(const uint8_t* data, size_t len) {
-  if (eof_) {
-    // Reset the trace processor state if this is either the first call ever or
-    // if another trace has been previously fully loaded.
-    trace_processor_ = TraceProcessor::CreateInstance(Config());
-    bytes_parsed_ = bytes_last_progress_ = 0;
-    t_parse_started_ = base::GetWallTimeNs().count();
-  }
-
-  eof_ = false;
-  bytes_parsed_ += len;
-  MaybePrintProgress();
-
-  if (len == 0)
-    return util::OkStatus();
-
-  // TraceProcessor needs take ownership of the memory chunk.
-  std::unique_ptr<uint8_t[]> data_copy(new uint8_t[len]);
-  memcpy(data_copy.get(), data, len);
-  return trace_processor_->Parse(std::move(data_copy), len);
-}
-
-void Rpc::NotifyEndOfFile() {
-  if (!trace_processor_)
-    return;
-  trace_processor_->NotifyEndOfFile();
-  eof_ = true;
-  MaybePrintProgress();
-}
-
-void Rpc::MaybePrintProgress() {
-  if (eof_ || bytes_parsed_ - bytes_last_progress_ > kProgressUpdateBytes) {
-    bytes_last_progress_ = bytes_parsed_;
-    auto t_load_s = (base::GetWallTimeNs().count() - t_parse_started_) / 1e9;
-    fprintf(stderr, "\rLoading trace %.2f MB (%.1f MB/s)%s",
-            bytes_parsed_ / 1e6, bytes_parsed_ / 1e6 / t_load_s,
-            (eof_ ? "\n" : ""));
-    fflush(stderr);
-  }
-}
-
-std::vector<uint8_t> Rpc::RawQuery(const uint8_t* args, size_t len) {
-  protozero::HeapBuffered<protos::pbzero::RawQueryResult> result;
-  protos::pbzero::RawQueryArgs::Decoder query(args, len);
-  std::string sql_query = query.sql_query().ToStdString();
-  PERFETTO_DLOG("[RPC] RawQuery < %s", sql_query.c_str());
-
-  if (!trace_processor_) {
-    static const char kErr[] = "RawQuery() called before Parse()";
-    PERFETTO_ELOG("[RPC] %s", kErr);
-    result->set_error(kErr);
-    return result.SerializeAsArray();
-  }
-
-  auto it = trace_processor_->ExecuteQuery(sql_query.c_str());
-
-  // This vector contains a standalone protozero message per column. The problem
-  // it's solving is the following: (i) sqlite iterators are row-based; (ii) the
-  // RawQueryResult proto is column-based (that was a poor design choice we
-  // should revisit at some point); (iii) the protozero API doesn't allow to
-  // begin a new nested message before the previous one is completed.
-  // In order to avoid the interleaved-writing, we write each column in a
-  // dedicated heap buffer and then we merge all the column data at the end,
-  // after having iterated all rows.
-  std::vector<protozero::HeapBuffered<ColumnValues>> cols(it.ColumnCount());
-
-  // This constexpr is to avoid ODR-use of protozero constants which are only
-  // declared but not defined. Putting directly UNKONWN in the vector ctor
-  // causes a linker error in the WASM toolchain.
-  static constexpr auto kUnknown = ColumnDesc::UNKNOWN;
-  std::vector<ColumnDesc::Type> col_types(it.ColumnCount(), kUnknown);
-  uint32_t rows = 0;
-
-  for (; it.Next(); ++rows) {
-    for (uint32_t col_idx = 0; col_idx < it.ColumnCount(); ++col_idx) {
-      auto& col = cols[col_idx];
-      auto& col_type = col_types[col_idx];
-
-      using SqlValue = trace_processor::SqlValue;
-      auto cell = it.Get(col_idx);
-      if (col_type == ColumnDesc::UNKNOWN) {
-        switch (cell.type) {
-          case SqlValue::Type::kLong:
-            col_type = ColumnDesc::LONG;
-            break;
-          case SqlValue::Type::kString:
-            col_type = ColumnDesc::STRING;
-            break;
-          case SqlValue::Type::kDouble:
-            col_type = ColumnDesc::DOUBLE;
-            break;
-          case SqlValue::Type::kBytes:
-            col_type = ColumnDesc::STRING;
-            break;
-          case SqlValue::Type::kNull:
-            break;
-        }
-      }
-
-      // If either the column type is null or we still don't know the type,
-      // just add null values to all the columns.
-      if (cell.type == SqlValue::Type::kNull ||
-          col_type == ColumnDesc::UNKNOWN) {
-        col->add_long_values(0);
-        col->add_string_values("[NULL]");
-        col->add_double_values(0);
-        col->add_is_nulls(true);
-        continue;
-      }
-
-      // Cast the sqlite value to the type of the column.
-      switch (col_type) {
-        case ColumnDesc::LONG:
-          PERFETTO_CHECK(cell.type == SqlValue::Type::kLong ||
-                         cell.type == SqlValue::Type::kDouble);
-          if (cell.type == SqlValue::Type::kLong) {
-            col->add_long_values(cell.long_value);
-          } else /* if (cell.type == SqlValue::Type::kDouble) */ {
-            col->add_long_values(static_cast<int64_t>(cell.double_value));
-          }
-          col->add_is_nulls(false);
-          break;
-        case ColumnDesc::STRING: {
-          if (cell.type == SqlValue::Type::kBytes) {
-            col->add_string_values("<bytes>");
-          } else {
-            PERFETTO_CHECK(cell.type == SqlValue::Type::kString);
-            col->add_string_values(cell.string_value);
-          }
-          col->add_is_nulls(false);
-          break;
-        }
-        case ColumnDesc::DOUBLE:
-          PERFETTO_CHECK(cell.type == SqlValue::Type::kLong ||
-                         cell.type == SqlValue::Type::kDouble);
-          if (cell.type == SqlValue::Type::kLong) {
-            col->add_double_values(static_cast<double>(cell.long_value));
-          } else /* if (cell.type == SqlValue::Type::kDouble) */ {
-            col->add_double_values(cell.double_value);
-          }
-          col->add_is_nulls(false);
-          break;
-        case ColumnDesc::UNKNOWN:
-          PERFETTO_FATAL("Handled in if statement above.");
-      }
-    }  // for(col)
-  }    // for(row)
-
-  // Write the column descriptors.
-  for (uint32_t col_idx = 0; col_idx < it.ColumnCount(); ++col_idx) {
-    auto* descriptor = result->add_column_descriptors();
-    std::string col_name = it.GetColumName(col_idx);
-    descriptor->set_name(col_name.data(), col_name.size());
-    descriptor->set_type(col_types[col_idx]);
-  }
-
-  // Merge the column values.
-  for (uint32_t col_idx = 0; col_idx < it.ColumnCount(); ++col_idx) {
-    std::vector<uint8_t> col_data = cols[col_idx].SerializeAsArray();
-    result->AppendBytes(protos::pbzero::RawQueryResult::kColumnsFieldNumber,
-                        col_data.data(), col_data.size());
-  }
-
-  util::Status status = it.Status();
-  result->set_num_records(rows);
-  if (!status.ok())
-    result->set_error(status.c_message());
-  PERFETTO_DLOG("[RPC] RawQuery > %d rows (err: %d)", rows, !status.ok());
-
-  return result.SerializeAsArray();
-}
-
-std::string Rpc::GetCurrentTraceName() {
-  if (!trace_processor_)
-    return "";
-  return trace_processor_->GetCurrentTraceName();
-}
-
-void Rpc::RestoreInitialTables() {
-  if (trace_processor_)
-    trace_processor_->RestoreInitialTables();
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/rpc/rpc.h b/src/trace_processor/rpc/rpc.h
deleted file mode 100644
index 22a12fa..0000000
--- a/src/trace_processor/rpc/rpc.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_RPC_RPC_H_
-#define SRC_TRACE_PROCESSOR_RPC_RPC_H_
-
-#include <memory>
-#include <vector>
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "perfetto/trace_processor/status.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessor;
-
-// This class handles the binary {,un}marshalling for the Trace Processor RPC
-// API (see protos/perfetto/trace_processor/trace_processor.proto).
-// This is to deal with cases where the client of the trace processor is not
-// some in-process C++ code but a remote process:
-// There are two use cases of this:
-//   1. The JS<>WASM interop for the web-based UI.
-//   2. The HTTP RPC mode of trace_processor_shell that allows the UI to talk
-//      to a native trace processor instead of the bundled WASM one.
-// This class has (a subset of) the same methods of the public TraceProcessor
-// interface, but the methods just take and return proto-encoded binary buffers.
-// This class does NOT define how the transport works (e.g. HTTP vs WASM interop
-// calls), it just deals with {,un}marshalling.
-// This class internally creates and owns a TraceProcessor instance, which
-// lifetime is tied to the lifetime of the Rpc instance.
-class Rpc {
- public:
-  // The unique_ptr argument is optional. If non-null it will adopt the passed
-  // instance and allow to directly query that. If null, a new instanace will be
-  // created internally by calling Parse().
-  explicit Rpc(std::unique_ptr<TraceProcessor>);
-  Rpc();
-  ~Rpc();
-
-  // The methods of this class are mirrors (modulo {un,}marshalling of args) of
-  // the corresponding names in trace_processor.h . See that header for docs.
-
-  util::Status Parse(const uint8_t* data, size_t len);
-  void NotifyEndOfFile();
-  std::vector<uint8_t> RawQuery(const uint8_t* args, size_t len);
-  void RestoreInitialTables();
-  std::string GetCurrentTraceName();
-
- private:
-  void MaybePrintProgress();
-
-  std::unique_ptr<TraceProcessor> trace_processor_;
-  bool eof_ = true;  // Reset when calling Parse().
-  int64_t t_parse_started_ = 0;
-  size_t bytes_last_progress_ = 0;
-  size_t bytes_parsed_ = 0;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_RPC_RPC_H_
diff --git a/src/trace_processor/rpc/wasm_bridge.cc b/src/trace_processor/rpc/wasm_bridge.cc
deleted file mode 100644
index 82ae660..0000000
--- a/src/trace_processor/rpc/wasm_bridge.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.
- */
-
-#include <emscripten/emscripten.h>
-#include <map>
-#include <string>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/trace_processor/trace_processor.h"
-#include "src/trace_processor/rpc/rpc.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-using RequestID = uint32_t;
-
-// Reply(): replies to a RPC method invocation.
-// Called asynchronously (i.e. in a separate task) by the C++ code inside the
-// trace processor to return data for a RPC method call.
-// The function is generic and thankfully we need just one for all methods
-// because the output is always a protobuf buffer.
-using ReplyFunction = void (*)(const char* /*proto_reply_data*/,
-                               uint32_t /*len*/);
-
-namespace {
-Rpc* g_trace_processor_rpc;
-ReplyFunction g_reply;
-
-// The buffer used to pass the request arguments. The caller (JS) decides how
-// big this buffer should be in the Initialize() call.
-uint8_t* g_req_buf;
-
-}  // namespace
-
-// +---------------------------------------------------------------------------+
-// | Exported functions called by the JS/TS running in the worker.             |
-// +---------------------------------------------------------------------------+
-extern "C" {
-
-// Returns the address of the allocated request buffer.
-uint8_t* EMSCRIPTEN_KEEPALIVE Initialize(ReplyFunction, uint32_t);
-uint8_t* Initialize(ReplyFunction reply_function, uint32_t req_buffer_size) {
-  g_trace_processor_rpc = new Rpc();
-  g_reply = reply_function;
-  g_req_buf = new uint8_t[req_buffer_size];
-  return g_req_buf;
-}
-
-// Ingests trace data.
-void EMSCRIPTEN_KEEPALIVE trace_processor_parse(uint32_t);
-void trace_processor_parse(size_t size) {
-  // TODO(primiano): Parse() makes a copy of the data, which is unfortunate.
-  // Ideally there should be a way to take the Blob coming from JS and move it.
-  // See https://github.com/WebAssembly/design/issues/1162.
-  auto status = g_trace_processor_rpc->Parse(g_req_buf, size);
-  if (status.ok()) {
-    g_reply("", 0);
-  } else {
-    PERFETTO_FATAL("Fatal failure while parsing the trace: %s",
-                   status.c_message());
-  }
-}
-
-// We keep the same signature as other methods even though we don't take input
-// arguments for simplicity.
-void EMSCRIPTEN_KEEPALIVE trace_processor_notify_eof(uint32_t);
-void trace_processor_notify_eof(uint32_t /* size, not used. */) {
-  g_trace_processor_rpc->NotifyEndOfFile();
-  g_reply("", 0);
-}
-
-void EMSCRIPTEN_KEEPALIVE trace_processor_raw_query(uint32_t);
-void trace_processor_raw_query(uint32_t size) {
-  std::vector<uint8_t> res = g_trace_processor_rpc->RawQuery(g_req_buf, size);
-  g_reply(reinterpret_cast<const char*>(res.data()),
-          static_cast<uint32_t>(res.size()));
-}
-
-}  // extern "C"
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/sched_slice_table.cc b/src/trace_processor/sched_slice_table.cc
index 0385fab..551f3b7 100644
--- a/src/trace_processor/sched_slice_table.cc
+++ b/src/trace_processor/sched_slice_table.cc
@@ -23,7 +23,7 @@
     : storage_(storage) {}
 
 void SchedSliceTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
-  SqliteTable::Register<SchedSliceTable>(db, storage, "sched");
+  Table::Register<SchedSliceTable>(db, storage, "sched");
 }
 
 StorageSchema SchedSliceTable::CreateStorageSchema() {
@@ -51,9 +51,8 @@
 
   // We should be able to handle any constraint and any order by clause given
   // to us.
-  info->sqlite_omit_order_by = true;
-  for (auto& c_info : info->constraint_info)
-    c_info.sqlite_omit = true;
+  info->order_by_consumed = true;
+  std::fill(info->omit.begin(), info->omit.end(), true);
 
   return SQLITE_OK;
 }
@@ -203,8 +202,8 @@
   };
 }
 
-SqlValue::Type SchedSliceTable::EndStateColumn::GetType() const {
-  return SqlValue::Type::kString;
+Table::ColumnType SchedSliceTable::EndStateColumn::GetType() const {
+  return Table::ColumnType::kString;
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/sched_slice_table.h b/src/trace_processor/sched_slice_table.h
index bcac09a..e30e742 100644
--- a/src/trace_processor/sched_slice_table.h
+++ b/src/trace_processor/sched_slice_table.h
@@ -51,7 +51,7 @@
 
     Comparator Sort(const QueryConstraints::OrderBy&) const override;
 
-    SqlValue::Type GetType() const override;
+    Table::ColumnType GetType() const override;
 
    private:
     static constexpr uint16_t kNumStateStrings =
diff --git a/src/trace_processor/sched_slice_table_unittest.cc b/src/trace_processor/sched_slice_table_unittest.cc
index 655033a..ab43301 100644
--- a/src/trace_processor/sched_slice_table_unittest.cc
+++ b/src/trace_processor/sched_slice_table_unittest.cc
@@ -18,11 +18,12 @@
 
 #include "src/trace_processor/args_tracker.h"
 #include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
 #include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/sqlite/scoped_db.h"
+#include "src/trace_processor/scoped_db.h"
 #include "src/trace_processor/trace_processor_context.h"
-#include "test/gtest_and_gmock.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -36,7 +37,6 @@
  public:
   SchedSliceTableTest() {
     sqlite3* db = nullptr;
-    PERFETTO_CHECK(sqlite3_initialize() == SQLITE_OK);
     PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
     db_.reset(db);
 
@@ -44,7 +44,6 @@
     context_.args_tracker.reset(new ArgsTracker(&context_));
     context_.process_tracker.reset(new ProcessTracker(&context_));
     context_.event_tracker.reset(new EventTracker(&context_));
-    context_.sched_tracker.reset(new SchedEventTracker(&context_));
 
     SchedSliceTable::RegisterTable(db_.get(), context_.storage.get());
   }
@@ -57,6 +56,8 @@
     stmt_.reset(stmt);
   }
 
+  ~SchedSliceTableTest() override { context_.storage->ResetStorage(); }
+
  protected:
   TraceProcessorContext context_;
   ScopedDb db_;
@@ -72,16 +73,16 @@
   static const char kCommProc2[] = "process2";
   uint32_t pid_2 = 4;
   int32_t prio = 1024;
-  context_.sched_tracker->PushSchedSwitch(cpu, timestamp, pid_1, kCommProc2,
+  context_.event_tracker->PushSchedSwitch(cpu, timestamp, pid_1, kCommProc2,
                                           prio, prev_state, pid_2, kCommProc1,
                                           prio);
-  context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 3, pid_2, kCommProc1,
+  context_.event_tracker->PushSchedSwitch(cpu, timestamp + 3, pid_2, kCommProc1,
                                           prio, prev_state, pid_1, kCommProc2,
                                           prio);
-  context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 4, pid_1, kCommProc2,
+  context_.event_tracker->PushSchedSwitch(cpu, timestamp + 4, pid_1, kCommProc2,
                                           prio, prev_state, pid_2, kCommProc1,
                                           prio);
-  context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 10, pid_2,
+  context_.event_tracker->PushSchedSwitch(cpu, timestamp + 10, pid_2,
                                           kCommProc1, prio, prev_state, pid_1,
                                           kCommProc2, prio);
 
@@ -117,22 +118,22 @@
   static const char kCommProc2[] = "process2";
   uint32_t pid_2 = 4;
   int32_t prio = 1024;
-  context_.sched_tracker->PushSchedSwitch(cpu_3, timestamp - 2, pid_1,
+  context_.event_tracker->PushSchedSwitch(cpu_3, timestamp - 2, pid_1,
                                           kCommProc2, prio, prev_state, pid_2,
                                           kCommProc1, prio);
-  context_.sched_tracker->PushSchedSwitch(cpu_3, timestamp - 1, pid_2,
+  context_.event_tracker->PushSchedSwitch(cpu_3, timestamp - 1, pid_2,
                                           kCommProc1, prio, prev_state, pid_1,
                                           kCommProc2, prio);
-  context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp, pid_1, kCommProc2,
+  context_.event_tracker->PushSchedSwitch(cpu_1, timestamp, pid_1, kCommProc2,
                                           prio, prev_state, pid_2, kCommProc1,
                                           prio);
-  context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 3, pid_2,
+  context_.event_tracker->PushSchedSwitch(cpu_2, timestamp + 3, pid_2,
                                           kCommProc1, prio, prev_state, pid_1,
                                           kCommProc2, prio);
-  context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp + 4, pid_2,
+  context_.event_tracker->PushSchedSwitch(cpu_1, timestamp + 4, pid_2,
                                           kCommProc1, prio, prev_state, pid_1,
                                           kCommProc2, prio);
-  context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 10, pid_1,
+  context_.event_tracker->PushSchedSwitch(cpu_2, timestamp + 10, pid_1,
                                           kCommProc2, prio, prev_state, pid_2,
                                           kCommProc1, prio);
 
@@ -167,16 +168,16 @@
   static const char kCommProc2[] = "process2";
   uint32_t pid_2 = 4;
   int32_t prio = 1024;
-  context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp, pid_1, kCommProc2,
+  context_.event_tracker->PushSchedSwitch(cpu_1, timestamp, pid_1, kCommProc2,
                                           prio, prev_state, pid_2, kCommProc1,
                                           prio);
-  context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 3, pid_2,
+  context_.event_tracker->PushSchedSwitch(cpu_2, timestamp + 3, pid_2,
                                           kCommProc1, prio, prev_state, pid_1,
                                           kCommProc2, prio);
-  context_.sched_tracker->PushSchedSwitch(cpu_1, timestamp + 4, pid_2,
+  context_.event_tracker->PushSchedSwitch(cpu_1, timestamp + 4, pid_2,
                                           kCommProc1, prio, prev_state, pid_1,
                                           kCommProc2, prio);
-  context_.sched_tracker->PushSchedSwitch(cpu_2, timestamp + 10, pid_1,
+  context_.event_tracker->PushSchedSwitch(cpu_2, timestamp + 10, pid_1,
                                           kCommProc2, prio, prev_state, pid_2,
                                           kCommProc1, prio);
 
@@ -200,16 +201,16 @@
   static const char kCommProc2[] = "process2";
   uint32_t pid_2 = 4;
   int32_t prio = 1024;
-  context_.sched_tracker->PushSchedSwitch(cpu, timestamp, pid_1, kCommProc2,
+  context_.event_tracker->PushSchedSwitch(cpu, timestamp, pid_1, kCommProc2,
                                           prio, prev_state, pid_2, kCommProc1,
                                           prio);
-  context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 3, pid_2, kCommProc1,
+  context_.event_tracker->PushSchedSwitch(cpu, timestamp + 3, pid_2, kCommProc1,
                                           prio, prev_state, pid_1, kCommProc2,
                                           prio);
-  context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 4, pid_1, kCommProc2,
+  context_.event_tracker->PushSchedSwitch(cpu, timestamp + 4, pid_1, kCommProc2,
                                           prio, prev_state, pid_2, kCommProc1,
                                           prio);
-  context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 10, pid_2,
+  context_.event_tracker->PushSchedSwitch(cpu, timestamp + 10, pid_2,
                                           kCommProc1, prio, prev_state, pid_1,
                                           kCommProc2, prio);
 
@@ -238,11 +239,11 @@
   // Fill |cpu_5| and |cpu_7) with one sched switch per time unit starting,
   // respectively, @ T=50 and T=70.
   for (int64_t i = 0; i <= 11; i++) {
-    context_.sched_tracker->PushSchedSwitch(cpu_5, 50 + i, pid_1, "pid_1", prio,
+    context_.event_tracker->PushSchedSwitch(cpu_5, 50 + i, pid_1, "pid_1", prio,
                                             prev_state, pid_1, "pid_1", prio);
   }
   for (int64_t i = 0; i <= 11; i++) {
-    context_.sched_tracker->PushSchedSwitch(cpu_7, 70 + i, pid_2, "pid_2", prio,
+    context_.event_tracker->PushSchedSwitch(cpu_7, 70 + i, pid_2, "pid_2", prio,
                                             prev_state, pid_2, "pid_2", prio);
   }
 
diff --git a/src/trace_processor/scoped_db.h b/src/trace_processor/scoped_db.h
new file mode 100644
index 0000000..7c1e44f
--- /dev/null
+++ b/src/trace_processor/scoped_db.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_SCOPED_DB_H_
+#define SRC_TRACE_PROCESSOR_SCOPED_DB_H_
+
+#include "perfetto/base/scoped_file.h"
+
+extern "C" {
+struct sqlite3;
+struct sqlite3_stmt;
+extern int sqlite3_close(sqlite3*);
+extern int sqlite3_finalize(sqlite3_stmt* pStmt);
+}
+
+namespace perfetto {
+namespace trace_processor {
+
+using ScopedDb = base::ScopedResource<sqlite3*, sqlite3_close, nullptr>;
+using ScopedStmt = base::ScopedResource<sqlite3_stmt*,
+                                        sqlite3_finalize,
+                                        nullptr,
+                                        /*CheckClose=*/false>;
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_SCOPED_DB_H_
diff --git a/src/trace_processor/slice_table.cc b/src/trace_processor/slice_table.cc
index 5eef8c0..8e8691c 100644
--- a/src/trace_processor/slice_table.cc
+++ b/src/trace_processor/slice_table.cc
@@ -25,7 +25,7 @@
     : storage_(storage) {}
 
 void SliceTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
-  SqliteTable::Register<SliceTable>(db, storage, "internal_slice");
+  Table::Register<SliceTable>(db, storage, "internal_slice");
 }
 
 StorageSchema SliceTable::CreateStorageSchema() {
@@ -34,16 +34,13 @@
       .AddGenericNumericColumn("slice_id", RowAccessor())
       .AddOrderedNumericColumn("ts", &slices.start_ns())
       .AddNumericColumn("dur", &slices.durations())
-      .AddNumericColumn("track_id", &slices.track_id())
       .AddNumericColumn("ref", &slices.refs())
       .AddStringColumn("ref_type", &slices.types(), &GetRefTypeStringMap())
-      .AddStringColumn("category", &slices.categories(),
-                       &storage_->string_pool())
+      .AddStringColumn("cat", &slices.cats(), &storage_->string_pool())
       .AddStringColumn("name", &slices.names(), &storage_->string_pool())
       .AddNumericColumn("depth", &slices.depths())
       .AddNumericColumn("stack_id", &slices.stack_ids())
       .AddNumericColumn("parent_stack_id", &slices.parent_stack_ids())
-      .AddNumericColumn("arg_set_id", &slices.arg_set_ids())
       .Build({"slice_id"});
 }
 
@@ -53,15 +50,15 @@
 
 int SliceTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
   info->estimated_cost = EstimateCost(qc);
-  info->sqlite_omit_order_by = true;
 
   // Only the string columns are handled by SQLite
+  info->order_by_consumed = true;
   size_t name_index = schema().ColumnIndexFromName("name");
-  size_t cat_index = schema().ColumnIndexFromName("category");
+  size_t cat_index = schema().ColumnIndexFromName("cat");
   size_t ref_type_index = schema().ColumnIndexFromName("ref_type");
   for (size_t i = 0; i < qc.constraints().size(); i++) {
     auto col = static_cast<size_t>(qc.constraints()[i].iColumn);
-    info->constraint_info[i].sqlite_omit =
+    info->omit[i] =
         col != name_index && col != cat_index && col != ref_type_index;
   }
   return SQLITE_OK;
diff --git a/src/trace_processor/slice_tracker.cc b/src/trace_processor/slice_tracker.cc
index 3317787..d021979 100644
--- a/src/trace_processor/slice_tracker.cc
+++ b/src/trace_processor/slice_tracker.cc
@@ -18,12 +18,10 @@
 
 #include <stdint.h>
 
-#include "src/trace_processor/args_tracker.h"
 #include "src/trace_processor/process_tracker.h"
 #include "src/trace_processor/slice_tracker.h"
 #include "src/trace_processor/trace_processor_context.h"
 #include "src/trace_processor/trace_storage.h"
-#include "src/trace_processor/track_tracker.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -31,107 +29,72 @@
 // Slices which have been opened but haven't been closed yet will be marked
 // with this duration placeholder.
 constexpr int64_t kPendingDuration = -1;
-}  // namespace
+};  // namespace
 
 SliceTracker::SliceTracker(TraceProcessorContext* context)
     : context_(context) {}
 
 SliceTracker::~SliceTracker() = default;
 
-base::Optional<uint32_t> SliceTracker::BeginAndroid(int64_t timestamp,
-                                                    uint32_t ftrace_tid,
-                                                    uint32_t atrace_tgid,
-                                                    StringId category,
-                                                    StringId name) {
+void SliceTracker::BeginAndroid(int64_t timestamp,
+                                uint32_t ftrace_tid,
+                                uint32_t atrace_tgid,
+                                StringId cat,
+                                StringId name) {
   UniqueTid utid =
       context_->process_tracker->UpdateThread(ftrace_tid, atrace_tgid);
   ftrace_to_atrace_tgid_[ftrace_tid] = atrace_tgid;
-
-  TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-  return Begin(timestamp, track_id, utid, RefType::kRefUtid, category, name);
+  Begin(timestamp, utid, cat, name);
 }
 
-base::Optional<uint32_t> SliceTracker::Begin(int64_t timestamp,
-                                             TrackId track_id,
-                                             int64_t ref,
-                                             RefType ref_type,
-                                             StringId category,
-                                             StringId name,
-                                             SetArgsCallback args_callback) {
-  // At this stage all events should be globally timestamp ordered.
-  if (timestamp < prev_timestamp_) {
-    context_->storage->IncrementStats(stats::slice_out_of_order);
-    return base::nullopt;
-  }
-  prev_timestamp_ = timestamp;
-
-  MaybeCloseStack(timestamp, &stacks_[track_id]);
-  return StartSlice(timestamp, kPendingDuration, track_id, ref, ref_type,
-                    category, name, args_callback);
+void SliceTracker::Begin(int64_t timestamp,
+                         UniqueTid utid,
+                         StringId cat,
+                         StringId name) {
+  MaybeCloseStack(timestamp, &threads_[utid]);
+  StartSlice(timestamp, kPendingDuration, utid, cat, name);
 }
 
-base::Optional<uint32_t> SliceTracker::Scoped(int64_t timestamp,
-                                              TrackId track_id,
-                                              int64_t ref,
-                                              RefType ref_type,
-                                              StringId category,
-                                              StringId name,
-                                              int64_t duration,
-                                              SetArgsCallback args_callback) {
-  // At this stage all events should be globally timestamp ordered.
-  if (timestamp < prev_timestamp_) {
-    context_->storage->IncrementStats(stats::slice_out_of_order);
-    return base::nullopt;
-  }
-  prev_timestamp_ = timestamp;
-
+void SliceTracker::Scoped(int64_t timestamp,
+                          UniqueTid utid,
+                          StringId cat,
+                          StringId name,
+                          int64_t duration) {
   PERFETTO_DCHECK(duration >= 0);
-  MaybeCloseStack(timestamp, &stacks_[track_id]);
-  return StartSlice(timestamp, duration, track_id, ref, ref_type, category,
-                    name, args_callback);
+  MaybeCloseStack(timestamp, &threads_[utid]);
+  StartSlice(timestamp, duration, utid, cat, name);
 }
 
-base::Optional<uint32_t> SliceTracker::StartSlice(
-    int64_t timestamp,
-    int64_t duration,
-    TrackId track_id,
-    int64_t ref,
-    RefType ref_type,
-    StringId category,
-    StringId name,
-    SetArgsCallback args_callback) {
-  auto* stack = &stacks_[track_id];
+void SliceTracker::StartSlice(int64_t timestamp,
+                              int64_t duration,
+                              UniqueTid utid,
+                              StringId cat,
+                              StringId name) {
+  auto* stack = &threads_[utid];
   auto* slices = context_->storage->mutable_nestable_slices();
 
   const uint8_t depth = static_cast<uint8_t>(stack->size());
   if (depth >= std::numeric_limits<uint8_t>::max()) {
     PERFETTO_DFATAL("Slices with too large depth found.");
-    return base::nullopt;
+    return;
   }
-  int64_t parent_stack_id =
-      depth == 0 ? 0 : slices->stack_ids()[stack->back().first];
-  uint32_t slice_idx =
-      slices->AddSlice(timestamp, duration, track_id, ref, ref_type, category,
-                       name, depth, 0, parent_stack_id);
-  stack->emplace_back(std::make_pair(slice_idx, ArgsTracker(context_)));
+  int64_t parent_stack_id = depth == 0 ? 0 : slices->stack_ids()[stack->back()];
+  size_t slice_idx =
+      slices->AddSlice(timestamp, duration, utid, RefType::kRefUtid, cat, name,
+                       depth, 0, parent_stack_id);
+  stack->emplace_back(slice_idx);
 
-  if (args_callback) {
-    args_callback(
-        &stack->back().second,
-        TraceStorage::CreateRowId(TableId::kNestableSlices, slice_idx));
-  }
   slices->set_stack_id(slice_idx, GetStackHash(*stack));
-  return slice_idx;
 }
 
-base::Optional<uint32_t> SliceTracker::EndAndroid(int64_t timestamp,
-                                                  uint32_t ftrace_tid,
-                                                  uint32_t atrace_tgid) {
+void SliceTracker::EndAndroid(int64_t timestamp,
+                              uint32_t ftrace_tid,
+                              uint32_t atrace_tgid) {
   auto actual_tgid_it = ftrace_to_atrace_tgid_.find(ftrace_tid);
   if (actual_tgid_it == ftrace_to_atrace_tgid_.end()) {
     // This is possible if we start tracing after a begin slice.
     PERFETTO_DLOG("Unknown tgid for ftrace tid %u", ftrace_tid);
-    return base::nullopt;
+    return;
   }
   uint32_t actual_tgid = actual_tgid_it->second;
   // atrace_tgid can be 0 in older android versions where the end event would
@@ -143,135 +106,56 @@
   }
   UniqueTid utid =
       context_->process_tracker->UpdateThread(ftrace_tid, actual_tgid);
-  TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-  return End(timestamp, track_id);
+  End(timestamp, utid);
 }
 
-// Returns the first incomplete slice in the stack with matching name and
-// category. We assume null category/name matches everything. Returns
-// nullopt if no matching slice is found.
-base::Optional<size_t> SliceTracker::MatchingIncompleteSliceIndex(
-    SlicesStack& stack,
-    StringId name,
-    StringId category) {
-  auto* slices = context_->storage->mutable_nestable_slices();
-  for (int i = static_cast<int>(stack.size()) - 1; i >= 0; i--) {
-    uint32_t slice_idx = stack[static_cast<size_t>(i)].first;
-    if (slices->durations()[slice_idx] != kPendingDuration)
-      continue;
-    const StringId& other_category = slices->categories()[slice_idx];
-    if (!category.is_null() && !other_category.is_null() &&
-        category != other_category)
-      continue;
-    const StringId& other_name = slices->names()[slice_idx];
-    if (!name.is_null() && !other_name.is_null() && name != other_name)
-      continue;
-    return static_cast<size_t>(i);
-  }
-  return base::nullopt;
-}
+void SliceTracker::End(int64_t timestamp,
+                       UniqueTid utid,
+                       StringId cat,
+                       StringId name) {
+  MaybeCloseStack(timestamp, &threads_[utid]);
 
-base::Optional<uint32_t> SliceTracker::End(int64_t timestamp,
-                                           TrackId track_id,
-                                           StringId category,
-                                           StringId name,
-                                           SetArgsCallback args_callback) {
-  // At this stage all events should be globally timestamp ordered.
-  if (timestamp < prev_timestamp_) {
-    context_->storage->IncrementStats(stats::slice_out_of_order);
-    return base::nullopt;
-  }
-  prev_timestamp_ = timestamp;
-
-  MaybeCloseStack(timestamp, &stacks_[track_id]);
-
-  auto& stack = stacks_[track_id];
+  const auto& stack = threads_[utid];
   if (stack.empty())
-    return base::nullopt;
+    return;
 
   auto* slices = context_->storage->mutable_nestable_slices();
-  base::Optional<size_t> stack_idx =
-      MatchingIncompleteSliceIndex(stack, name, category);
+  size_t slice_idx = stack.back();
 
-  // If we are trying to close slices that are not open on the stack (e.g.,
-  // slices that began before tracing started), bail out.
-  if (!stack_idx)
-    return base::nullopt;
-
-  if (*stack_idx != stack.size() - 1) {
-    // This usually happens because we have two slices that are partially
-    // overlapping.
-    // [  slice  1    ]
-    //          [     slice 2     ]
-    // This is invalid in chrome and should be fixed. Duration events should
-    // either be nested or disjoint, never partially intersecting.
-    PERFETTO_DLOG(
-        "Incorrect ordering of End slice event around timestamp "
-        "%" PRId64,
-        timestamp);
-    context_->storage->IncrementStats(stats::misplaced_end_event);
-  }
-
-  uint32_t slice_idx = stack[stack_idx.value()].first;
+  // If we are trying to close mismatching slices (e.g., slices that began
+  // before tracing started), bail out.
+  if (cat && slices->cats()[slice_idx] != cat)
+    return;
+  if (name && slices->names()[slice_idx] != name)
+    return;
 
   PERFETTO_DCHECK(slices->durations()[slice_idx] == kPendingDuration);
   slices->set_duration(slice_idx, timestamp - slices->start_ns()[slice_idx]);
 
-  if (args_callback) {
-    args_callback(
-        &stack.back().second,
-        TraceStorage::CreateRowId(TableId::kNestableSlices, slice_idx));
-  }
-
-  return CompleteSlice(track_id);
+  CompleteSlice(utid);
   // TODO(primiano): auto-close B slices left open at the end.
 }
 
-void SliceTracker::FlushPendingSlices() {
-  // Clear the remaining stack entries. This ensures that any pending args are
-  // written to the storage. We don't close any slices with kPendingDuration so
-  // that the UI can still distinguish such "incomplete" slices.
-  //
-  // TODO(eseckler): Reconsider whether we want to close pending slices by
-  // setting their duration to |trace_end - event_start|. Might still want some
-  // additional way of flagging these events as "incomplete" to the UI.
-  stacks_.clear();
-}
-
-base::Optional<uint32_t> SliceTracker::CompleteSlice(TrackId track_id) {
-  auto& stack = stacks_[track_id];
-  uint32_t slice_idx = stack.back().first;
-  stack.pop_back();
-  return slice_idx;
+void SliceTracker::CompleteSlice(UniqueTid utid) {
+  threads_[utid].pop_back();
 }
 
 void SliceTracker::MaybeCloseStack(int64_t ts, SlicesStack* stack) {
   const auto& slices = context_->storage->nestable_slices();
-  bool pending_dur_descendent = false;
+  bool check_only = false;
   for (int i = static_cast<int>(stack->size()) - 1; i >= 0; i--) {
-    uint32_t slice_idx = (*stack)[static_cast<size_t>(i)].first;
+    size_t slice_idx = (*stack)[static_cast<size_t>(i)];
 
     int64_t start_ts = slices.start_ns()[slice_idx];
     int64_t dur = slices.durations()[slice_idx];
     int64_t end_ts = start_ts + dur;
     if (dur == kPendingDuration) {
-      pending_dur_descendent = true;
+      check_only = true;
     }
 
-    if (pending_dur_descendent) {
-      PERFETTO_DCHECK(ts >= start_ts);
-      // Some trace producers emit END events in the wrong order (even after
-      // sorting by timestamp), e.g. BEGIN A, BEGIN B, END A, END B. We discard
-      // the mismatching END A in End(). Because of this, we can end up in a
-      // situation where we attempt to close the stack on top of A at a
-      // timestamp beyond A's parent. To avoid crashing in such a case, we just
-      // emit a warning instead.
-      if (dur != kPendingDuration && ts > end_ts) {
-        PERFETTO_DLOG(
-            "Incorrect ordering of begin/end slice events around timestamp "
-            "%" PRId64,
-            ts);
-      }
+    if (check_only) {
+      PERFETTO_CHECK(ts >= start_ts);
+      PERFETTO_CHECK(dur == kPendingDuration || ts <= end_ts);
       continue;
     }
 
@@ -289,9 +173,9 @@
   std::string s;
   s.reserve(stack.size() * sizeof(uint64_t) * 2);
   for (size_t i = 0; i < stack.size(); i++) {
-    uint32_t slice_idx = stack[i].first;
-    s.append(reinterpret_cast<const char*>(&slices.categories()[slice_idx]),
-             sizeof(slices.categories()[slice_idx]));
+    size_t slice_idx = stack[i];
+    s.append(reinterpret_cast<const char*>(&slices.cats()[slice_idx]),
+             sizeof(slices.cats()[slice_idx]));
     s.append(reinterpret_cast<const char*>(&slices.names()[slice_idx]),
              sizeof(slices.names()[slice_idx]));
   }
diff --git a/src/trace_processor/slice_tracker.h b/src/trace_processor/slice_tracker.h
index 726c25f..e4986b6 100644
--- a/src/trace_processor/slice_tracker.h
+++ b/src/trace_processor/slice_tracker.h
@@ -24,83 +24,55 @@
 namespace perfetto {
 namespace trace_processor {
 
-class ArgsTracker;
 class TraceProcessorContext;
 
 class SliceTracker {
  public:
-  using SetArgsCallback = std::function<void(ArgsTracker*, RowId row_id)>;
-
   explicit SliceTracker(TraceProcessorContext*);
   virtual ~SliceTracker();
 
-  base::Optional<uint32_t> BeginAndroid(int64_t timestamp,
-                                        uint32_t ftrace_tid,
-                                        uint32_t atrace_tgid,
-                                        StringId category,
-                                        StringId name);
+  void BeginAndroid(int64_t timestamp,
+                    uint32_t ftrace_tid,
+                    uint32_t atrace_tgid,
+                    StringId cat,
+                    StringId name);
 
   // virtual for testing
-  virtual base::Optional<uint32_t> Begin(
-      int64_t timestamp,
-      TrackId track_id,
-      int64_t ref,
-      RefType ref_type,
-      StringId category,
-      StringId name,
-      SetArgsCallback args_callback = SetArgsCallback());
+  virtual void Begin(int64_t timestamp,
+                     UniqueTid utid,
+                     StringId cat,
+                     StringId name);
 
   // virtual for testing
-  virtual base::Optional<uint32_t> Scoped(
-      int64_t timestamp,
-      TrackId track_id,
-      int64_t ref,
-      RefType ref_type,
-      StringId category,
-      StringId name,
-      int64_t duration,
-      SetArgsCallback args_callback = SetArgsCallback());
+  virtual void Scoped(int64_t timestamp,
+                      UniqueTid utid,
+                      StringId cat,
+                      StringId name,
+                      int64_t duration);
 
-  base::Optional<uint32_t> EndAndroid(int64_t timestamp,
-                                      uint32_t ftrace_tid,
-                                      uint32_t atrace_tgid);
+  void EndAndroid(int64_t timestamp, uint32_t ftrace_tid, uint32_t atrace_tgid);
 
   // virtual for testing
-  virtual base::Optional<uint32_t> End(
-      int64_t timestamp,
-      TrackId track_id,
-      StringId opt_category = {},
-      StringId opt_name = {},
-      SetArgsCallback args_callback = SetArgsCallback());
-
-  void FlushPendingSlices();
+  virtual void End(int64_t timestamp,
+                   UniqueTid utid,
+                   StringId opt_cat = {},
+                   StringId opt_name = {});
 
  private:
-  using SlicesStack = std::vector<std::pair<uint32_t /* row */, ArgsTracker>>;
-  using StackMap = std::unordered_map<TrackId, SlicesStack>;
+  using SlicesStack = std::vector<size_t>;
 
-  base::Optional<uint32_t> StartSlice(int64_t timestamp,
-                                      int64_t duration,
-                                      TrackId track_id,
-                                      int64_t ref,
-                                      RefType ref_type,
-                                      StringId category,
-                                      StringId name,
-                                      SetArgsCallback args_callback);
-  base::Optional<uint32_t> CompleteSlice(TrackId track_id);
+  void StartSlice(int64_t timestamp,
+                  int64_t duration,
+                  UniqueTid utid,
+                  StringId cat,
+                  StringId name);
+  void CompleteSlice(UniqueTid tid);
 
   void MaybeCloseStack(int64_t end_ts, SlicesStack*);
-  base::Optional<size_t> MatchingIncompleteSliceIndex(SlicesStack& stack,
-                                                      StringId name,
-                                                      StringId category);
   int64_t GetStackHash(const SlicesStack&);
 
-  // Timestamp of the previous event. Used to discard events arriving out
-  // of order.
-  int64_t prev_timestamp_ = 0;
-
   TraceProcessorContext* const context_;
-  StackMap stacks_;
+  std::unordered_map<UniqueTid, SlicesStack> threads_;
   std::unordered_map<uint32_t, uint32_t> ftrace_to_atrace_tgid_;
 };
 
diff --git a/src/trace_processor/slice_tracker_unittest.cc b/src/trace_processor/slice_tracker_unittest.cc
index 33f0d5e..a9750d3 100644
--- a/src/trace_processor/slice_tracker_unittest.cc
+++ b/src/trace_processor/slice_tracker_unittest.cc
@@ -16,11 +16,12 @@
 
 #include <vector>
 
-#include "src/trace_processor/args_tracker.h"
 #include "src/trace_processor/slice_tracker.h"
 #include "src/trace_processor/trace_processor_context.h"
 #include "src/trace_processor/trace_storage.h"
-#include "test/gtest_and_gmock.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -55,62 +56,18 @@
   context.storage.reset(new TraceStorage());
   SliceTracker tracker(&context);
 
-  constexpr TrackId track = 22u;
-  tracker.Begin(2 /*ts*/, track, 42 /*ref*/, RefType::kRefUtid, 0 /*cat*/,
-                1 /*name*/);
-  tracker.End(10 /*ts*/, track, 0 /*cat*/, 1 /*name*/);
+  tracker.Begin(2 /*ts*/, 42 /*tid*/, 0 /*cat*/, 1 /*name*/);
+  tracker.End(10 /*ts*/, 42 /*tid*/, 0 /*cat*/, 1 /*name*/);
 
   auto slices = context.storage->nestable_slices();
-  EXPECT_EQ(slices.slice_count(), 1u);
+  EXPECT_EQ(slices.slice_count(), 1);
   EXPECT_EQ(slices.start_ns()[0], 2);
   EXPECT_EQ(slices.durations()[0], 8);
-  EXPECT_EQ(slices.track_id()[0], track);
-  EXPECT_EQ(slices.categories()[0], 0u);
-  EXPECT_EQ(slices.names()[0], 1u);
+  EXPECT_EQ(slices.cats()[0], 0);
+  EXPECT_EQ(slices.names()[0], 1);
   EXPECT_EQ(slices.refs()[0], 42);
-  EXPECT_EQ(slices.types()[0], RefType::kRefUtid);
+  EXPECT_EQ(slices.types()[0], kRefUtid);
   EXPECT_EQ(slices.depths()[0], 0);
-  EXPECT_EQ(slices.arg_set_ids()[0], kInvalidArgSetId);
-}
-
-TEST(SliceTrackerTest, OneSliceWithArgs) {
-  TraceProcessorContext context;
-  context.storage.reset(new TraceStorage());
-  SliceTracker tracker(&context);
-
-  constexpr TrackId track = 22u;
-  tracker.Begin(2 /*ts*/, track, 42 /*ref*/, RefType::kRefUtid, 0 /*cat*/,
-                1 /*name*/, [](ArgsTracker* args_tracker, RowId row) {
-                  args_tracker->AddArg(row, /*flat_key=*/1, /*key=*/2,
-                                       /*value=*/Variadic::Integer(10));
-                });
-  tracker.End(10 /*ts*/, track, 0 /*cat*/, 1 /*name*/,
-              [](ArgsTracker* args_tracker, RowId row) {
-                args_tracker->AddArg(row, /*flat_key=*/3, /*key=*/4,
-                                     /*value=*/Variadic::Integer(20));
-              });
-
-  auto slices = context.storage->nestable_slices();
-  EXPECT_EQ(slices.slice_count(), 1u);
-  EXPECT_EQ(slices.start_ns()[0], 2);
-  EXPECT_EQ(slices.durations()[0], 8);
-  EXPECT_EQ(slices.track_id()[0], track);
-  EXPECT_EQ(slices.categories()[0], 0u);
-  EXPECT_EQ(slices.names()[0], 1u);
-  EXPECT_EQ(slices.refs()[0], 42);
-  EXPECT_EQ(slices.types()[0], RefType::kRefUtid);
-  EXPECT_EQ(slices.depths()[0], 0);
-  auto set_id = slices.arg_set_ids()[0];
-
-  auto args = context.storage->args();
-  EXPECT_EQ(args.set_ids()[0], set_id);
-  EXPECT_EQ(args.flat_keys()[0], 1u);
-  EXPECT_EQ(args.keys()[0], 2u);
-  EXPECT_EQ(args.arg_values()[0], Variadic::Integer(10));
-  EXPECT_EQ(args.set_ids()[1], set_id);
-  EXPECT_EQ(args.flat_keys()[1], 3u);
-  EXPECT_EQ(args.keys()[1], 4u);
-  EXPECT_EQ(args.arg_values()[1], Variadic::Integer(20));
 }
 
 TEST(SliceTrackerTest, TwoSliceDetailed) {
@@ -118,35 +75,30 @@
   context.storage.reset(new TraceStorage());
   SliceTracker tracker(&context);
 
-  constexpr TrackId track = 22u;
-  tracker.Begin(2 /*ts*/, track, 42 /*ref*/, RefType::kRefUtid, 0 /*cat*/,
-                1 /*name*/);
-  tracker.Begin(3 /*ts*/, track, 42 /*ref*/, RefType::kRefUtid, 0 /*cat*/,
-                2 /*name*/);
-  tracker.End(5 /*ts*/, track);
-  tracker.End(10 /*ts*/, track);
+  tracker.Begin(2 /*ts*/, 42 /*tid*/, 0 /*cat*/, 1 /*name*/);
+  tracker.Begin(3 /*ts*/, 42 /*tid*/, 0 /*cat*/, 2 /*name*/);
+  tracker.End(5 /*ts*/, 42 /*tid*/);
+  tracker.End(10 /*ts*/, 42 /*tid*/);
 
   auto slices = context.storage->nestable_slices();
 
-  EXPECT_EQ(slices.slice_count(), 2u);
+  EXPECT_EQ(slices.slice_count(), 2);
 
   size_t idx = 0;
   EXPECT_EQ(slices.start_ns()[idx], 2);
   EXPECT_EQ(slices.durations()[idx], 8);
-  EXPECT_EQ(slices.track_id()[idx], track);
-  EXPECT_EQ(slices.categories()[idx], 0u);
-  EXPECT_EQ(slices.names()[idx], 1u);
+  EXPECT_EQ(slices.cats()[idx], 0);
+  EXPECT_EQ(slices.names()[idx], 1);
   EXPECT_EQ(slices.refs()[idx], 42);
-  EXPECT_EQ(slices.types()[idx], RefType::kRefUtid);
+  EXPECT_EQ(slices.types()[idx], kRefUtid);
   EXPECT_EQ(slices.depths()[idx++], 0);
 
   EXPECT_EQ(slices.start_ns()[idx], 3);
   EXPECT_EQ(slices.durations()[idx], 2);
-  EXPECT_EQ(slices.track_id()[idx], track);
-  EXPECT_EQ(slices.categories()[idx], 0u);
-  EXPECT_EQ(slices.names()[idx], 2u);
+  EXPECT_EQ(slices.cats()[idx], 0);
+  EXPECT_EQ(slices.names()[idx], 2);
   EXPECT_EQ(slices.refs()[idx], 42);
-  EXPECT_EQ(slices.types()[idx], RefType::kRefUtid);
+  EXPECT_EQ(slices.types()[idx], kRefUtid);
   EXPECT_EQ(slices.depths()[idx], 1);
 
   EXPECT_EQ(slices.parent_stack_ids()[0], 0);
@@ -159,12 +111,11 @@
   context.storage.reset(new TraceStorage());
   SliceTracker tracker(&context);
 
-  constexpr TrackId track = 22u;
-  tracker.Begin(0 /*ts*/, track, 42 /*ref*/, RefType::kRefUtid, 0, 0);
-  tracker.Begin(1 /*ts*/, track, 42 /*ref*/, RefType::kRefUtid, 0, 0);
-  tracker.Scoped(2 /*ts*/, track, 42 /*ref*/, RefType::kRefUtid, 0, 0, 6);
-  tracker.End(9 /*ts*/, track);
-  tracker.End(10 /*ts*/, track);
+  tracker.Begin(0 /*ts*/, 42 /*tid*/, 0, 0);
+  tracker.Begin(1 /*ts*/, 42 /*tid*/, 0, 0);
+  tracker.Scoped(2 /*ts*/, 42 /*tid*/, 0, 0, 6);
+  tracker.End(9 /*ts*/, 42 /*tid*/);
+  tracker.End(10 /*ts*/, 42 /*tid*/);
 
   auto slices = ToSliceInfo(context.storage->nestable_slices());
   EXPECT_THAT(slices,
@@ -176,12 +127,10 @@
   context.storage.reset(new TraceStorage());
   SliceTracker tracker(&context);
 
-  constexpr TrackId track = 22u;
-  tracker.Begin(2 /*ts*/, track, 42 /*ref*/, RefType::kRefUtid, 5 /*cat*/,
-                1 /*name*/);
-  tracker.End(3 /*ts*/, track, 1 /*cat*/, 1 /*name*/);
-  tracker.End(4 /*ts*/, track, 0 /*cat*/, 2 /*name*/);
-  tracker.End(5 /*ts*/, track, 5 /*cat*/, 1 /*name*/);
+  tracker.Begin(2 /*ts*/, 42 /*tid*/, 0 /*cat*/, 1 /*name*/);
+  tracker.End(3 /*ts*/, 42 /*tid*/, 1 /*cat*/, 1 /*name*/);
+  tracker.End(4 /*ts*/, 42 /*tid*/, 0 /*cat*/, 2 /*name*/);
+  tracker.End(5 /*ts*/, 42 /*tid*/, 0 /*cat*/, 1 /*name*/);
 
   auto slices = ToSliceInfo(context.storage->nestable_slices());
   EXPECT_THAT(slices, ElementsAre(SliceInfo{2, 3}));
@@ -195,89 +144,16 @@
   // Bug scenario: the second zero-length scoped slice prevents the first slice
   // from being closed, leading to an inconsistency when we try to insert the
   // final slice and it doesn't intersect with the still pending first slice.
-  constexpr TrackId track = 22u;
-  tracker.Scoped(2 /*ts*/, track, 42 /*ref*/, RefType::kRefUtid, 0 /*cat*/,
-                 1 /*name*/, 10 /* dur */);
-  tracker.Scoped(2 /*ts*/, track, 42 /*ref*/, RefType::kRefUtid, 0 /*cat*/,
-                 1 /*name*/, 0 /* dur */);
-  tracker.Scoped(12 /*ts*/, track, 42 /*ref*/, RefType::kRefUtid, 0 /*cat*/,
-                 1 /*name*/, 1 /* dur */);
-  tracker.Scoped(13 /*ts*/, track, 42 /*ref*/, RefType::kRefUtid, 0 /*cat*/,
-                 1 /*name*/, 1 /* dur */);
+  tracker.Scoped(2 /*ts*/, 42 /*tid*/, 0 /*cat*/, 1 /*name*/, 10 /* dur */);
+  tracker.Scoped(2 /*ts*/, 42 /*tid*/, 0 /*cat*/, 1 /*name*/, 0 /* dur */);
+  tracker.Scoped(12 /*ts*/, 42 /*tid*/, 0 /*cat*/, 1 /*name*/, 1 /* dur */);
+  tracker.Scoped(13 /*ts*/, 42 /*tid*/, 0 /*cat*/, 1 /*name*/, 1 /* dur */);
 
   auto slices = ToSliceInfo(context.storage->nestable_slices());
   EXPECT_THAT(slices, ElementsAre(SliceInfo{2, 10}, SliceInfo{2, 0},
                                   SliceInfo{12, 1}, SliceInfo{13, 1}));
 }
 
-TEST(SliceTrackerTest, DifferentTracks) {
-  TraceProcessorContext context;
-  context.storage.reset(new TraceStorage());
-  SliceTracker tracker(&context);
-
-  constexpr TrackId track_a = 22u;
-  constexpr TrackId track_b = 23u;
-  tracker.Begin(0 /*ts*/, track_a, 42 /*ref*/, RefType::kRefUtid, 0, 0);
-  tracker.Scoped(2 /*ts*/, track_b, 42 /*ref*/, RefType::kRefUtid, 0, 0, 6);
-  tracker.Scoped(3 /*ts*/, track_b, 42 /*ref*/, RefType::kRefUtid, 0, 0, 4);
-  tracker.End(10 /*ts*/, track_a);
-  tracker.FlushPendingSlices();
-
-  auto slices = ToSliceInfo(context.storage->nestable_slices());
-  EXPECT_THAT(slices,
-              ElementsAre(SliceInfo{0, 10}, SliceInfo{2, 6}, SliceInfo{3, 4}));
-
-  EXPECT_EQ(context.storage->nestable_slices().track_id()[0], track_a);
-  EXPECT_EQ(context.storage->nestable_slices().track_id()[1], track_b);
-  EXPECT_EQ(context.storage->nestable_slices().track_id()[2], track_b);
-  EXPECT_EQ(context.storage->nestable_slices().depths()[0], 0);
-  EXPECT_EQ(context.storage->nestable_slices().depths()[1], 0);
-  EXPECT_EQ(context.storage->nestable_slices().depths()[2], 1);
-}
-
-TEST(SliceTrackerTest, EndEventOutOfOrder) {
-  TraceProcessorContext context;
-  context.storage.reset(new TraceStorage());
-  SliceTracker tracker(&context);
-
-  constexpr TrackId track = 22u;
-  tracker.Scoped(50 /*ts*/, track, 42 /*ref*/, RefType::kRefUtid, 11 /*cat*/,
-                 21 /*name*/, 100 /*dur*/);
-  tracker.Begin(100 /*ts*/, track, 42 /*ref*/, RefType::kRefUtid, 12 /*cat*/,
-                22 /*name*/);
-  tracker.Scoped(450 /*ts*/, track, 42 /*ref*/, RefType::kRefUtid, 12 /*cat*/,
-                 22 /*name*/, 100 /*dur*/);
-  tracker.End(500 /*ts*/, track, 12 /*cat*/, 22 /*name*/);
-
-  // This slice should now have depth 0.
-  tracker.Begin(800 /*ts*/, track, 42 /*ref*/, RefType::kRefUtid, 13 /*cat*/,
-                23 /*name*/);
-  // Null cat and name matches everything.
-  tracker.End(1000 /*ts*/, track, 0 /*cat*/, 0 /*name*/);
-
-  // Slice will not close if category is different.
-  tracker.Begin(1100 /*ts*/, track, 42 /*ref*/, RefType::kRefUtid, 11 /*cat*/,
-                21 /*name*/);
-  tracker.End(1200 /*ts*/, track, 12 /*cat*/, 21 /*name*/);
-
-  // Slice will not close if name is different.
-  tracker.Begin(1300 /*ts*/, track, 42 /*ref*/, RefType::kRefUtid, 11 /*cat*/,
-                21 /*name*/);
-  tracker.End(1400 /*ts*/, track, 11 /*cat*/, 22 /*name*/);
-
-  tracker.FlushPendingSlices();
-
-  auto slices = ToSliceInfo(context.storage->nestable_slices());
-  EXPECT_THAT(slices, ElementsAre(SliceInfo{50, 100}, SliceInfo{100, 400},
-                                  SliceInfo{450, 100}, SliceInfo{800, 200},
-                                  SliceInfo{1100, -1}, SliceInfo{1300, 0 - 1}));
-
-  EXPECT_EQ(context.storage->nestable_slices().depths()[0], 0);
-  EXPECT_EQ(context.storage->nestable_slices().depths()[1], 1);
-  EXPECT_EQ(context.storage->nestable_slices().depths()[2], 2);
-  EXPECT_EQ(context.storage->nestable_slices().depths()[3], 0);
-}
-
 }  // namespace
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/span_join_operator_table.cc b/src/trace_processor/span_join_operator_table.cc
index 57b1598..38ae073 100644
--- a/src/trace_processor/span_join_operator_table.cc
+++ b/src/trace_processor/span_join_operator_table.cc
@@ -18,16 +18,15 @@
 
 #include <sqlite3.h>
 #include <string.h>
-
 #include <algorithm>
 #include <set>
 #include <utility>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/string_view.h"
-#include "src/trace_processor/sqlite/sqlite_utils.h"
+#include "perfetto/base/string_splitter.h"
+#include "perfetto/base/string_utils.h"
+#include "perfetto/base/string_view.h"
+#include "src/trace_processor/sqlite_utils.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -41,17 +40,18 @@
   return name == kTsColumnName || name == kDurColumnName;
 }
 
-base::Optional<std::string> HasDuplicateColumns(
-    const std::vector<SqliteTable::Column>& cols) {
+bool HasDuplicateColumns(const std::vector<Table::Column>& cols) {
   std::set<std::string> names;
   for (const auto& col : cols) {
-    if (names.count(col.name()) > 0)
-      return col.name();
+    if (names.count(col.name()) > 0) {
+      PERFETTO_ELOG("Column '%s' present in the output schema more than once.",
+                    col.name().c_str());
+      return true;
+    }
     names.insert(col.name());
   }
-  return base::nullopt;
+  return false;
 }
-
 }  // namespace
 
 SpanJoinOperatorTable::SpanJoinOperatorTable(sqlite3* db, const TraceStorage*)
@@ -59,99 +59,94 @@
 
 void SpanJoinOperatorTable::RegisterTable(sqlite3* db,
                                           const TraceStorage* storage) {
-  SqliteTable::Register<SpanJoinOperatorTable>(db, storage, "span_join",
-                                               /* read_write */ false,
-                                               /* requires_args */ true);
+  Table::Register<SpanJoinOperatorTable>(db, storage, "span_join",
+                                         /* read_write */ false,
+                                         /* requires_args */ true);
 
-  SqliteTable::Register<SpanJoinOperatorTable>(db, storage, "span_left_join",
-                                               /* read_write */ false,
-                                               /* requires_args */ true);
+  Table::Register<SpanJoinOperatorTable>(db, storage, "span_left_join",
+                                         /* read_write */ false,
+                                         /* requires_args */ true);
 
-  SqliteTable::Register<SpanJoinOperatorTable>(db, storage, "span_outer_join",
-                                               /* read_write */ false,
-                                               /* requires_args */ true);
+  Table::Register<SpanJoinOperatorTable>(db, storage, "span_outer_join",
+                                         /* read_write */ false,
+                                         /* requires_args */ true);
 }
 
-util::Status SpanJoinOperatorTable::Init(int argc,
-                                         const char* const* argv,
-                                         Schema* schema) {
+base::Optional<Table::Schema> SpanJoinOperatorTable::Init(
+    int argc,
+    const char* const* argv) {
   // argv[0] - argv[2] are SQLite populated fields which are always present.
-  if (argc < 5)
-    return util::Status("SPAN_JOIN: expected at least 2 args");
+  if (argc < 5) {
+    PERFETTO_ELOG("SPAN JOIN expected at least 2 args, received %d", argc - 3);
+    return base::nullopt;
+  }
 
-  TableDescriptor t1_desc;
-  auto status = TableDescriptor::Parse(
-      std::string(reinterpret_cast<const char*>(argv[3])), &t1_desc);
-  if (!status.ok())
-    return status;
+  auto maybe_t1_desc = TableDescriptor::Parse(
+      std::string(reinterpret_cast<const char*>(argv[3])));
+  if (!maybe_t1_desc.has_value())
+    return base::nullopt;
+  auto t1_desc = *maybe_t1_desc;
 
-  TableDescriptor t2_desc;
-  status = TableDescriptor::Parse(
-      std::string(reinterpret_cast<const char*>(argv[4])), &t2_desc);
-  if (!status.ok())
-    return status;
+  auto maybe_t2_desc = TableDescriptor::Parse(
+      std::string(reinterpret_cast<const char*>(argv[4])));
+  if (!maybe_t2_desc.has_value())
+    return base::nullopt;
+  auto t2_desc = *maybe_t2_desc;
 
-  // Check that the partition columns match between the two tables.
   if (t1_desc.partition_col == t2_desc.partition_col) {
     partitioning_ = t1_desc.IsPartitioned()
                         ? PartitioningType::kSamePartitioning
                         : PartitioningType::kNoPartitioning;
     if (partitioning_ == PartitioningType::kNoPartitioning && IsOuterJoin()) {
-      return util::ErrStatus(
-          "SPAN_JOIN: Outer join not supported for no partition tables");
+      PERFETTO_ELOG("Outer join not supported for no partition tables");
+      return base::nullopt;
     }
   } else if (t1_desc.IsPartitioned() && t2_desc.IsPartitioned()) {
-    return util::ErrStatus(
-        "SPAN_JOIN: mismatching partitions between the two tables; "
-        "(partition %s in table %s, partition %s in table %s)",
-        t1_desc.partition_col.c_str(), t1_desc.name.c_str(),
-        t2_desc.partition_col.c_str(), t2_desc.name.c_str());
+    PERFETTO_ELOG("Mismatching partitions (%s, %s)",
+                  t1_desc.partition_col.c_str(), t2_desc.partition_col.c_str());
+    return base::nullopt;
   } else {
     if (IsOuterJoin()) {
-      return util::ErrStatus(
-          "SPAN_JOIN: Outer join not supported for mixed partitioned tables");
+      PERFETTO_ELOG("Outer join not supported for mixed partitioned tables");
+      return base::nullopt;
     }
     partitioning_ = PartitioningType::kMixedPartitioning;
   }
 
-  status = CreateTableDefinition(t1_desc, IsOuterJoin(), &t1_defn_);
-  if (!status.ok())
-    return status;
+  auto maybe_t1_defn = CreateTableDefinition(t1_desc, IsOuterJoin());
+  if (!maybe_t1_defn.has_value())
+    return base::nullopt;
+  t1_defn_ = maybe_t1_defn.value();
 
-  status =
-      CreateTableDefinition(t2_desc, IsOuterJoin() || IsLeftJoin(), &t2_defn_);
-  if (!status.ok())
-    return status;
+  auto maybe_t2_defn =
+      CreateTableDefinition(t2_desc, IsOuterJoin() || IsLeftJoin());
+  if (!maybe_t2_defn.has_value())
+    return base::nullopt;
+  t2_defn_ = maybe_t2_defn.value();
 
-  std::vector<SqliteTable::Column> cols;
+  std::vector<Table::Column> cols;
   // Ensure the shared columns are consistently ordered and are not
   // present twice in the final schema
-  cols.emplace_back(Column::kTimestamp, kTsColumnName, SqlValue::Type::kLong);
-  cols.emplace_back(Column::kDuration, kDurColumnName, SqlValue::Type::kLong);
+  cols.emplace_back(Column::kTimestamp, kTsColumnName, ColumnType::kLong);
+  cols.emplace_back(Column::kDuration, kDurColumnName, ColumnType::kLong);
   if (partitioning_ != PartitioningType::kNoPartitioning)
-    cols.emplace_back(Column::kPartition, partition_col(),
-                      SqlValue::Type::kLong);
+    cols.emplace_back(Column::kPartition, partition_col(), ColumnType::kLong);
 
   CreateSchemaColsForDefn(t1_defn_, &cols);
   CreateSchemaColsForDefn(t2_defn_, &cols);
 
-  if (auto opt_dupe_col = HasDuplicateColumns(cols)) {
-    return util::ErrStatus(
-        "SPAN_JOIN: column %s present in both tables %s and %s",
-        opt_dupe_col->c_str(), t1_defn_.name().c_str(),
-        t2_defn_.name().c_str());
+  if (HasDuplicateColumns(cols)) {
+    return base::nullopt;
   }
   std::vector<size_t> primary_keys = {Column::kTimestamp};
   if (partitioning_ != PartitioningType::kNoPartitioning)
     primary_keys.push_back(Column::kPartition);
-  *schema = Schema(cols, primary_keys);
-
-  return util::OkStatus();
+  return Schema(cols, primary_keys);
 }
 
 void SpanJoinOperatorTable::CreateSchemaColsForDefn(
     const TableDefinition& defn,
-    std::vector<SqliteTable::Column>* cols) {
+    std::vector<Table::Column>* cols) {
   for (size_t i = 0; i < defn.columns().size(); i++) {
     const auto& n = defn.columns()[i].name();
     if (IsRequiredColumn(n) || n == defn.partition_col())
@@ -165,7 +160,7 @@
   }
 }
 
-std::unique_ptr<SqliteTable::Cursor> SpanJoinOperatorTable::CreateCursor() {
+std::unique_ptr<Table::Cursor> SpanJoinOperatorTable::CreateCursor() {
   return std::unique_ptr<SpanJoinOperatorTable::Cursor>(new Cursor(this, db_));
 }
 
@@ -199,17 +194,9 @@
   return constraints;
 }
 
-util::Status SpanJoinOperatorTable::CreateTableDefinition(
-    const TableDescriptor& desc,
-    bool emit_shadow_slices,
-    SpanJoinOperatorTable::TableDefinition* defn) {
-  if (desc.partition_col == kTsColumnName ||
-      desc.partition_col == kDurColumnName) {
-    return util::ErrStatus(
-        "SPAN_JOIN: partition column cannot be any of {ts, dur} for table %s",
-        desc.name.c_str());
-  }
-
+base::Optional<SpanJoinOperatorTable::TableDefinition>
+SpanJoinOperatorTable::CreateTableDefinition(const TableDescriptor& desc,
+                                             bool emit_shadow_slices) {
   auto cols = sqlite_utils::GetColumnsForTable(db_, desc.name);
 
   uint32_t required_columns_found = 0;
@@ -220,11 +207,10 @@
     auto col = cols[i];
     if (IsRequiredColumn(col.name())) {
       ++required_columns_found;
-      if (col.type() != SqlValue::Type::kLong &&
-          col.type() != SqlValue::Type::kNull) {
-        return util::ErrStatus(
-            "SPAN_JOIN: Invalid type for column %s in table %s",
-            col.name().c_str(), desc.name.c_str());
+      if (col.type() != Table::ColumnType::kLong &&
+          col.type() != Table::ColumnType::kUnknown) {
+        PERFETTO_ELOG("Invalid column type for %s", col.name().c_str());
+        return base::nullopt;
       }
     }
 
@@ -237,20 +223,17 @@
     }
   }
   if (required_columns_found != 2) {
-    return util::ErrStatus(
-        "SPAN_JOIN: Missing one of columns {ts, dur} in table %s",
-        desc.name.c_str());
-  } else if (desc.IsPartitioned() && partition_idx >= cols.size()) {
-    return util::ErrStatus("SPAN_JOIN: Missing partition column %s in table %s",
-                           desc.partition_col.c_str(), desc.name.c_str());
+    PERFETTO_ELOG("Required columns not found (found %d)",
+                  required_columns_found);
+    return base::nullopt;
   }
 
   PERFETTO_DCHECK(ts_idx < cols.size());
   PERFETTO_DCHECK(dur_idx < cols.size());
+  PERFETTO_DCHECK(desc.partition_col.empty() || partition_idx < cols.size());
 
-  *defn = TableDefinition(desc.name, desc.partition_col, std::move(cols),
-                          emit_shadow_slices, ts_idx, dur_idx, partition_idx);
-  return util::OkStatus();
+  return TableDefinition(desc.name, desc.partition_col, std::move(cols),
+                         emit_shadow_slices, ts_idx, dur_idx, partition_idx);
 }
 
 std::string SpanJoinOperatorTable::GetNameForGlobalColumnIndex(
@@ -272,7 +255,7 @@
 }
 
 SpanJoinOperatorTable::Cursor::Cursor(SpanJoinOperatorTable* table, sqlite3* db)
-    : SqliteTable::Cursor(table),
+    : Table::Cursor(table),
       t1_(table, &table->t1_defn_, db),
       t2_(table, &table->t2_defn_, db),
       table_(table) {}
@@ -585,7 +568,7 @@
   if (defn_->IsPartitioned()) {
     while (partition_ < target_partition) {
       if (IsFullPartitionShadowSlice() &&
-          (cursor_eof_ || target_partition < CursorPartition())) {
+          target_partition < CursorPartition()) {
         partition_ = target_partition;
         return StepRet(StepRet::Code::kRow);
       }
@@ -618,7 +601,7 @@
 std::string SpanJoinOperatorTable::Query::CreateSqlQuery(
     const std::vector<std::string>& cs) const {
   std::vector<std::string> col_names;
-  for (const SqliteTable::Column& c : defn_->columns()) {
+  for (const Table::Column& c : defn_->columns()) {
     col_names.push_back("`" + c.name() + "`");
   }
 
@@ -684,7 +667,7 @@
 SpanJoinOperatorTable::TableDefinition::TableDefinition(
     std::string name,
     std::string partition_col,
-    std::vector<SqliteTable::Column> cols,
+    std::vector<Table::Column> cols,
     bool emit_shadow_slices,
     uint32_t ts_idx,
     uint32_t dur_idx,
@@ -697,29 +680,33 @@
       dur_idx_(dur_idx),
       partition_idx_(partition_idx) {}
 
-util::Status SpanJoinOperatorTable::TableDescriptor::Parse(
-    const std::string& raw_descriptor,
-    SpanJoinOperatorTable::TableDescriptor* descriptor) {
+base::Optional<SpanJoinOperatorTable::TableDescriptor>
+SpanJoinOperatorTable::TableDescriptor::Parse(
+    const std::string& raw_descriptor) {
   // Descriptors have one of the following forms:
   // table_name [PARTITIONED column_name]
 
   // Find the table name.
   base::StringSplitter splitter(raw_descriptor, ' ');
   if (!splitter.Next())
-    return util::ErrStatus("SPAN_JOIN: Missing table name");
+    return base::nullopt;
 
-  descriptor->name = splitter.cur_token();
+  TableDescriptor descriptor;
+  descriptor.name = splitter.cur_token();
   if (!splitter.Next())
-    return util::OkStatus();
+    return std::move(descriptor);
 
-  if (!base::CaseInsensitiveEqual(splitter.cur_token(), "PARTITIONED"))
-    return util::ErrStatus("SPAN_JOIN: Invalid token");
+  if (strcasecmp(splitter.cur_token(), "PARTITIONED") != 0) {
+    PERFETTO_ELOG("Invalid SPAN_JOIN token %s", splitter.cur_token());
+    return base::nullopt;
+  }
+  if (!splitter.Next()) {
+    PERFETTO_ELOG("Missing partitioning column");
+    return base::nullopt;
+  }
 
-  if (!splitter.Next())
-    return util::ErrStatus("SPAN_JOIN: Missing partitioning column");
-
-  descriptor->partition_col = splitter.cur_token();
-  return util::OkStatus();
+  descriptor.partition_col = splitter.cur_token();
+  return std::move(descriptor);
 }
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/span_join_operator_table.h b/src/trace_processor/span_join_operator_table.h
index eb96161..6d62d8b 100644
--- a/src/trace_processor/span_join_operator_table.h
+++ b/src/trace_processor/span_join_operator_table.h
@@ -18,7 +18,6 @@
 #define SRC_TRACE_PROCESSOR_SPAN_JOIN_OPERATOR_TABLE_H_
 
 #include <sqlite3.h>
-
 #include <array>
 #include <deque>
 #include <limits>
@@ -28,10 +27,8 @@
 #include <unordered_map>
 #include <vector>
 
-#include "perfetto/trace_processor/basic_types.h"
-#include "perfetto/trace_processor/status.h"
-#include "src/trace_processor/sqlite/scoped_db.h"
-#include "src/trace_processor/sqlite/sqlite_table.h"
+#include "src/trace_processor/scoped_db.h"
+#include "src/trace_processor/table.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -68,7 +65,7 @@
 //
 // All other columns apart from timestamp (ts), duration (dur) and the join key
 // are passed through unchanged.
-class SpanJoinOperatorTable : public SqliteTable {
+class SpanJoinOperatorTable : public Table {
  public:
   // Columns of the span operator table.
   enum Column {
@@ -86,8 +83,8 @@
 
   // Parsed version of a table descriptor.
   struct TableDescriptor {
-    static util::Status Parse(const std::string& raw_descriptor,
-                              TableDescriptor* descriptor);
+    static base::Optional<TableDescriptor> Parse(
+        const std::string& raw_descriptor);
 
     bool IsPartitioned() const { return !partition_col.empty(); }
 
@@ -102,7 +99,7 @@
 
     TableDefinition(std::string name,
                     std::string partition_col,
-                    std::vector<SqliteTable::Column> cols,
+                    std::vector<Table::Column> cols,
                     bool emit_shadow_slices,
                     uint32_t ts_idx,
                     uint32_t dur_idx,
@@ -110,7 +107,7 @@
 
     const std::string& name() const { return name_; }
     const std::string& partition_col() const { return partition_col_; }
-    const std::vector<SqliteTable::Column>& columns() const { return cols_; }
+    const std::vector<Table::Column>& columns() const { return cols_; }
 
     bool emit_shadow_slices() const { return emit_shadow_slices_; }
     uint32_t ts_idx() const { return ts_idx_; }
@@ -122,7 +119,7 @@
    private:
     std::string name_;
     std::string partition_col_;
-    std::vector<SqliteTable::Column> cols_;
+    std::vector<Table::Column> cols_;
     bool emit_shadow_slices_;
     uint32_t ts_idx_ = std::numeric_limits<uint32_t>::max();
     uint32_t dur_idx_ = std::numeric_limits<uint32_t>::max();
@@ -222,7 +219,7 @@
   };
 
   // Base class for a cursor on the span table.
-  class Cursor : public SqliteTable::Cursor {
+  class Cursor : public Table::Cursor {
    public:
     Cursor(SpanJoinOperatorTable*, sqlite3* db);
     ~Cursor() override = default;
@@ -254,8 +251,8 @@
   static void RegisterTable(sqlite3* db, const TraceStorage* storage);
 
   // Table implementation.
-  util::Status Init(int, const char* const*, SqliteTable::Schema*) override;
-  std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
+  base::Optional<Table::Schema> Init(int, const char* const*) override;
+  std::unique_ptr<Table::Cursor> CreateCursor() override;
   int BestIndex(const QueryConstraints& qc, BestIndexInfo* info) override;
 
  private:
@@ -273,10 +270,9 @@
                                     : t2_defn_.partition_col();
   }
 
-  util::Status CreateTableDefinition(
+  base::Optional<TableDefinition> CreateTableDefinition(
       const TableDescriptor& desc,
-      bool emit_shadow_slices,
-      SpanJoinOperatorTable::TableDefinition* defn);
+      bool emit_shadow_slices);
 
   std::vector<std::string> ComputeSqlConstraintsForDefinition(
       const TableDefinition& defn,
@@ -287,7 +283,7 @@
                                           int global_column);
 
   void CreateSchemaColsForDefn(const TableDefinition& defn,
-                               std::vector<SqliteTable::Column>* cols);
+                               std::vector<Table::Column>* cols);
 
   TableDefinition t1_defn_;
   TableDefinition t2_defn_;
diff --git a/src/trace_processor/span_join_operator_table_unittest.cc b/src/trace_processor/span_join_operator_table_unittest.cc
index 503360e..c67488d 100644
--- a/src/trace_processor/span_join_operator_table_unittest.cc
+++ b/src/trace_processor/span_join_operator_table_unittest.cc
@@ -16,9 +16,10 @@
 
 #include "src/trace_processor/span_join_operator_table.h"
 
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 #include "src/trace_processor/trace_processor_context.h"
 #include "src/trace_processor/trace_storage.h"
-#include "test/gtest_and_gmock.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -28,7 +29,6 @@
  public:
   SpanJoinOperatorTableTest() {
     sqlite3* db = nullptr;
-    PERFETTO_CHECK(sqlite3_initialize() == SQLITE_OK);
     PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
     db_.reset(db);
 
@@ -58,6 +58,8 @@
     }
   }
 
+  ~SpanJoinOperatorTableTest() override { context_.storage->ResetStorage(); }
+
  protected:
   TraceProcessorContext context_;
   ScopedDb db_;
diff --git a/src/trace_processor/sql_stats_table.cc b/src/trace_processor/sql_stats_table.cc
index 0d434a0..25e4a17 100644
--- a/src/trace_processor/sql_stats_table.cc
+++ b/src/trace_processor/sql_stats_table.cc
@@ -22,7 +22,7 @@
 #include <bitset>
 #include <numeric>
 
-#include "src/trace_processor/sqlite/sqlite_utils.h"
+#include "src/trace_processor/sqlite_utils.h"
 #include "src/trace_processor/trace_storage.h"
 
 namespace perfetto {
@@ -32,37 +32,33 @@
     : storage_(storage) {}
 
 void SqlStatsTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
-  SqliteTable::Register<SqlStatsTable>(db, storage, "sqlstats");
+  Table::Register<SqlStatsTable>(db, storage, "sqlstats");
 }
 
-util::Status SqlStatsTable::Init(int, const char* const*, Schema* schema) {
-  *schema = Schema(
+base::Optional<Table::Schema> SqlStatsTable::Init(int, const char* const*) {
+  return Schema(
       {
-          SqliteTable::Column(Column::kQuery, "query", SqlValue::Type::kString),
-          SqliteTable::Column(Column::kTimeQueued, "queued",
-                              SqlValue::Type::kLong),
-          SqliteTable::Column(Column::kTimeStarted, "started",
-                              SqlValue::Type::kLong),
-          SqliteTable::Column(Column::kTimeFirstNext, "first_next",
-                              SqlValue::Type::kLong),
-          SqliteTable::Column(Column::kTimeEnded, "ended",
-                              SqlValue::Type::kLong),
+          Table::Column(Column::kQuery, "query", ColumnType::kString),
+          Table::Column(Column::kTimeQueued, "queued", ColumnType::kLong),
+          Table::Column(Column::kTimeStarted, "started", ColumnType::kLong),
+          Table::Column(Column::kTimeFirstNext, "first_next",
+                        ColumnType::kLong),
+          Table::Column(Column::kTimeEnded, "ended", ColumnType::kLong),
       },
       {Column::kTimeQueued});
-  return util::OkStatus();
 }
 
-std::unique_ptr<SqliteTable::Cursor> SqlStatsTable::CreateCursor() {
-  return std::unique_ptr<SqliteTable::Cursor>(new Cursor(this));
+std::unique_ptr<Table::Cursor> SqlStatsTable::CreateCursor() {
+  return std::unique_ptr<Table::Cursor>(new Cursor(this));
 }
 
 int SqlStatsTable::BestIndex(const QueryConstraints&, BestIndexInfo* info) {
-  info->sqlite_omit_order_by = true;
+  info->order_by_consumed = false;  // Delegate sorting to SQLite.
   return SQLITE_OK;
 }
 
 SqlStatsTable::Cursor::Cursor(SqlStatsTable* table)
-    : SqliteTable::Cursor(table), storage_(table->storage_), table_(table) {}
+    : Table::Cursor(table), storage_(table->storage_), table_(table) {}
 
 SqlStatsTable::Cursor::~Cursor() = default;
 
diff --git a/src/trace_processor/sql_stats_table.h b/src/trace_processor/sql_stats_table.h
index 0ff06a7..ebbe120 100644
--- a/src/trace_processor/sql_stats_table.h
+++ b/src/trace_processor/sql_stats_table.h
@@ -20,7 +20,7 @@
 #include <limits>
 #include <memory>
 
-#include "src/trace_processor/sqlite/sqlite_table.h"
+#include "src/trace_processor/table.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -30,7 +30,7 @@
 
 // A virtual table that allows to introspect performances of the SQL engine
 // for the kMaxLogEntries queries.
-class SqlStatsTable : public SqliteTable {
+class SqlStatsTable : public Table {
  public:
   enum Column {
     kQuery = 0,
@@ -41,12 +41,12 @@
   };
 
   // Implementation of the SQLite cursor interface.
-  class Cursor : public SqliteTable::Cursor {
+  class Cursor : public Table::Cursor {
    public:
     Cursor(SqlStatsTable* storage);
     ~Cursor() override;
 
-    // Implementation of SqliteTable::Cursor.
+    // Implementation of Table::Cursor.
     int Filter(const QueryConstraints&, sqlite3_value**) override;
     int Next() override;
     int Eof() override;
@@ -70,8 +70,8 @@
   static void RegisterTable(sqlite3* db, const TraceStorage* storage);
 
   // Table implementation.
-  util::Status Init(int, const char* const*, Schema*) override;
-  std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
+  base::Optional<Table::Schema> Init(int, const char* const*) override;
+  std::unique_ptr<Table::Cursor> CreateCursor() override;
   int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
 
  private:
diff --git a/src/trace_processor/sqlite/BUILD.gn b/src/trace_processor/sqlite/BUILD.gn
deleted file mode 100644
index 6f8c9e4..0000000
--- a/src/trace_processor/sqlite/BUILD.gn
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../../gn/test.gni")
-
-if (enable_perfetto_trace_processor_sqlite) {
-  source_set("sqlite") {
-    sources = [
-      "db_sqlite_table.cc",
-      "db_sqlite_table.h",
-      "query_constraints.cc",
-      "query_constraints.h",
-      "scoped_db.h",
-      "sqlite3_str_split.cc",
-      "sqlite3_str_split.h",
-      "sqlite_table.cc",
-      "sqlite_table.h",
-      "sqlite_utils.h",
-    ]
-    deps = [
-      "../../../gn:default_deps",
-      "../../../gn:sqlite",
-      "../../../include/perfetto/trace_processor",
-      "../../base",
-      "../db:lib",
-    ]
-  }
-
-  perfetto_unittest_source_set("unittests") {
-    testonly = true
-    sources = [
-      "query_constraints_unittest.cc",
-      "sqlite3_str_split_unittest.cc",
-    ]
-    deps = [
-      ":sqlite",
-      "../../../gn:default_deps",
-      "../../../gn:gtest_and_gmock",
-      "../../../gn:sqlite",
-      "../../base",
-    ]
-  }
-}  # if (enable_perfetto_trace_processor_sqlite)
diff --git a/src/trace_processor/sqlite/db_sqlite_table.cc b/src/trace_processor/sqlite/db_sqlite_table.cc
deleted file mode 100644
index b2298ca..0000000
--- a/src/trace_processor/sqlite/db_sqlite_table.cc
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/sqlite/db_sqlite_table.h"
-
-#include "src/trace_processor/sqlite/sqlite_utils.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-
-FilterOp SqliteOpToFilterOp(int sqlite_op) {
-  switch (sqlite_op) {
-    case SQLITE_INDEX_CONSTRAINT_EQ:
-    case SQLITE_INDEX_CONSTRAINT_IS:
-      return FilterOp::kEq;
-    case SQLITE_INDEX_CONSTRAINT_GT:
-      return FilterOp::kGt;
-    case SQLITE_INDEX_CONSTRAINT_LT:
-      return FilterOp::kLt;
-    case SQLITE_INDEX_CONSTRAINT_ISNOT:
-    case SQLITE_INDEX_CONSTRAINT_NE:
-      return FilterOp::kNe;
-    case SQLITE_INDEX_CONSTRAINT_GE:
-      return FilterOp::kGe;
-    case SQLITE_INDEX_CONSTRAINT_LE:
-      return FilterOp::kLe;
-    case SQLITE_INDEX_CONSTRAINT_ISNULL:
-      return FilterOp::kIsNull;
-    case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
-      return FilterOp::kIsNotNull;
-    case SQLITE_INDEX_CONSTRAINT_LIKE:
-      return FilterOp::kLike;
-    default:
-      PERFETTO_FATAL("Currently unsupported constraint");
-  }
-}
-
-SqlValue SqliteValueToSqlValue(sqlite3_value* sqlite_val) {
-  auto col_type = sqlite3_value_type(sqlite_val);
-  SqlValue value;
-  switch (col_type) {
-    case SQLITE_INTEGER:
-      value.type = SqlValue::kLong;
-      value.long_value = sqlite3_value_int64(sqlite_val);
-      break;
-    case SQLITE_TEXT:
-      value.type = SqlValue::kString;
-      value.string_value =
-          reinterpret_cast<const char*>(sqlite3_value_text(sqlite_val));
-      break;
-    case SQLITE_FLOAT:
-      value.type = SqlValue::kDouble;
-      value.double_value = sqlite3_value_double(sqlite_val);
-      break;
-    case SQLITE_BLOB:
-      value.type = SqlValue::kBytes;
-      value.bytes_value = sqlite3_value_blob(sqlite_val);
-      value.bytes_count = static_cast<size_t>(sqlite3_value_bytes(sqlite_val));
-      break;
-    case SQLITE_NULL:
-      value.type = SqlValue::kNull;
-      break;
-  }
-  return value;
-}
-
-}  // namespace
-
-DbSqliteTable::DbSqliteTable(sqlite3*, const Table* table) : table_(table) {}
-DbSqliteTable::~DbSqliteTable() = default;
-
-void DbSqliteTable::RegisterTable(sqlite3* db,
-                                  const Table* table,
-                                  const std::string& name) {
-  SqliteTable::Register<DbSqliteTable, const Table*>(db, table, name);
-}
-
-util::Status DbSqliteTable::Init(int, const char* const*, Schema* schema) {
-  std::vector<SqliteTable::Column> schema_cols;
-  for (uint32_t i = 0; i < table_->GetColumnCount(); ++i) {
-    const auto& col = table_->GetColumn(i);
-    schema_cols.emplace_back(i, col.name(), col.type());
-  }
-  // TODO(lalitm): this is hardcoded to be the id column but change this to be
-  // more generic in the future.
-  auto opt_idx = table_->FindColumnIdxByName("id");
-  if (!opt_idx) {
-    PERFETTO_FATAL(
-        "id column not found in %s. Currently all db Tables need to contain an "
-        "id column; this constraint will be relaxed in the future.",
-        name().c_str());
-  }
-
-  std::vector<size_t> primary_keys;
-  primary_keys.emplace_back(*opt_idx);
-
-  *schema = Schema(std::move(schema_cols), std::move(primary_keys));
-  return util::OkStatus();
-}
-
-int DbSqliteTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
-  // TODO(lalitm): investigate SQLITE_INDEX_SCAN_UNIQUE for id columns.
-  info->estimated_cost = static_cast<uint32_t>(EstimateCost(qc));
-  return SQLITE_OK;
-}
-
-double DbSqliteTable::EstimateCost(const QueryConstraints& qc) {
-  // Currently our cost estimation algorithm is quite simplistic but is good
-  // enough for the simplest cases.
-  // TODO(lalitm): flesh out this algorithm to cover more complex cases.
-
-  // If we have no constraints, we always return the size of the table as we
-  // want to discourage the query planner from taking this road.
-  const auto& constraints = qc.constraints();
-  if (constraints.empty())
-    return table_->size();
-
-  // This means we have at least one constraint. Check if any of the constraints
-  // is an equality constraint on an id column.
-  auto id_filter = [this](const QueryConstraints::Constraint& c) {
-    uint32_t col_idx = static_cast<uint32_t>(c.iColumn);
-    const auto& col = table_->GetColumn(col_idx);
-    return sqlite_utils::IsOpEq(c.op) && col.IsId();
-  };
-
-  // If we have a eq constraint on an id column, we return 0 as it's an O(1)
-  // operation regardless of all the other constriants.
-  auto it = std::find_if(constraints.begin(), constraints.end(), id_filter);
-  if (it != constraints.end())
-    return 1;
-
-  // Otherwise, we divide the number of rows in the table by the number of
-  // constraints as a simple way of indiciating the more constraints we have
-  // the better we can do.
-  return table_->size() / constraints.size();
-}
-
-std::unique_ptr<SqliteTable::Cursor> DbSqliteTable::CreateCursor() {
-  return std::unique_ptr<Cursor>(new Cursor(this));
-}
-
-DbSqliteTable::Cursor::Cursor(DbSqliteTable* table)
-    : SqliteTable::Cursor(table), initial_db_table_(table->table_) {}
-
-int DbSqliteTable::Cursor::Filter(const QueryConstraints& qc,
-                                  sqlite3_value** argv) {
-  // Clear out the iterator before filtering to ensure the destructor is run
-  // before the table's destructor.
-  iterator_ = base::nullopt;
-
-  // We reuse this vector to reduce memory allocations on nested subqueries.
-  constraints_.resize(qc.constraints().size());
-  for (size_t i = 0; i < qc.constraints().size(); ++i) {
-    const auto& cs = qc.constraints()[i];
-    uint32_t col = static_cast<uint32_t>(cs.iColumn);
-
-    FilterOp op = SqliteOpToFilterOp(cs.op);
-    SqlValue value = SqliteValueToSqlValue(argv[i]);
-
-    constraints_[i] = Constraint{col, op, value};
-  }
-
-  // We reuse this vector to reduce memory allocations on nested subqueries.
-  orders_.resize(qc.order_by().size());
-  for (size_t i = 0; i < qc.order_by().size(); ++i) {
-    const auto& ob = qc.order_by()[i];
-    uint32_t col = static_cast<uint32_t>(ob.iColumn);
-    orders_[i] = Order{col, static_cast<bool>(ob.desc)};
-  }
-
-  db_table_ = initial_db_table_->Filter(constraints_).Sort(orders_);
-  iterator_ = db_table_->IterateRows();
-
-  return SQLITE_OK;
-}
-
-int DbSqliteTable::Cursor::Next() {
-  iterator_->Next();
-  return SQLITE_OK;
-}
-
-int DbSqliteTable::Cursor::Eof() {
-  return !*iterator_;
-}
-
-int DbSqliteTable::Cursor::Column(sqlite3_context* ctx, int raw_col) {
-  uint32_t column = static_cast<uint32_t>(raw_col);
-  SqlValue value = iterator_->Get(column);
-  switch (value.type) {
-    case SqlValue::Type::kLong:
-      sqlite3_result_int64(ctx, value.long_value);
-      break;
-    case SqlValue::Type::kDouble:
-      sqlite3_result_double(ctx, value.double_value);
-      break;
-    case SqlValue::Type::kString: {
-      // We can say kSqliteStatic here because all strings are expected to
-      // come from the string pool and thus will be valid for the lifetime
-      // of trace processor.
-      sqlite3_result_text(ctx, value.string_value, -1,
-                          sqlite_utils::kSqliteStatic);
-      break;
-    }
-    case SqlValue::Type::kBytes: {
-      // We can say kSqliteStatic here because for our iterator will hold
-      // onto the pointer as long as we don't call Next() but that only
-      // happens with Next() is called on the Cursor itself at which point
-      // SQLite no longer cares about the bytes pointer.
-      sqlite3_result_blob(ctx, value.bytes_value,
-                          static_cast<int>(value.bytes_count),
-                          sqlite_utils::kSqliteStatic);
-      break;
-    }
-    case SqlValue::Type::kNull:
-      sqlite3_result_null(ctx);
-      break;
-  }
-  return SQLITE_OK;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/sqlite/db_sqlite_table.h b/src/trace_processor/sqlite/db_sqlite_table.h
deleted file mode 100644
index 6afcbfe..0000000
--- a/src/trace_processor/sqlite/db_sqlite_table.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_SQLITE_DB_SQLITE_TABLE_H_
-#define SRC_TRACE_PROCESSOR_SQLITE_DB_SQLITE_TABLE_H_
-
-#include "src/trace_processor/db/table.h"
-#include "src/trace_processor/sqlite/sqlite_table.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Implements the SQLite table interface for db tables.
-class DbSqliteTable : public SqliteTable {
- public:
-  class Cursor final : public SqliteTable::Cursor {
-   public:
-    explicit Cursor(DbSqliteTable* table);
-
-    // Implementation of SqliteTable::Cursor.
-    int Filter(const QueryConstraints& qc, sqlite3_value** argv) override;
-    int Next() override;
-    int Eof() override;
-    int Column(sqlite3_context*, int N) override;
-
-   private:
-    const Table* initial_db_table_ = nullptr;
-
-    base::Optional<Table> db_table_;
-    base::Optional<Table::Iterator> iterator_;
-
-    std::vector<Constraint> constraints_;
-    std::vector<Order> orders_;
-  };
-
-  static void RegisterTable(sqlite3* db,
-                            const Table* table,
-                            const std::string& name);
-
-  DbSqliteTable(sqlite3*, const Table* table);
-  virtual ~DbSqliteTable() override;
-
-  // Table implementation.
-  util::Status Init(int,
-                    const char* const*,
-                    SqliteTable::Schema*) override final;
-  std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
-  int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
-
- private:
-  double EstimateCost(const QueryConstraints& qc);
-
-  const Table* table_ = nullptr;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_SQLITE_DB_SQLITE_TABLE_H_
diff --git a/src/trace_processor/sqlite/query_constraints.cc b/src/trace_processor/sqlite/query_constraints.cc
deleted file mode 100644
index cc57838..0000000
--- a/src/trace_processor/sqlite/query_constraints.cc
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * 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.
- */
-
-#include "src/trace_processor/sqlite/query_constraints.h"
-
-#include <sqlite3.h>
-
-#include <string>
-
-#include "perfetto/ext/base/string_splitter.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-QueryConstraints::QueryConstraints() = default;
-QueryConstraints::~QueryConstraints() = default;
-QueryConstraints::QueryConstraints(QueryConstraints&&) noexcept = default;
-QueryConstraints& QueryConstraints::operator=(QueryConstraints&&) = default;
-
-int QueryConstraints::FreeSqliteString(char* resource) {
-  sqlite3_free(resource);
-  return 0;
-}
-
-bool QueryConstraints::operator==(const QueryConstraints& other) const {
-  if ((other.constraints().size() != constraints().size()) ||
-      (other.order_by().size() != order_by().size())) {
-    return false;
-  }
-
-  for (size_t i = 0; i < constraints().size(); ++i) {
-    if ((constraints()[i].iColumn != other.constraints()[i].iColumn) ||
-        (constraints()[i].op != other.constraints()[i].op)) {
-      return false;
-    }
-  }
-
-  for (size_t i = 0; i < order_by().size(); ++i) {
-    if ((order_by()[i].iColumn != other.order_by()[i].iColumn) ||
-        (order_by()[i].desc != other.order_by()[i].desc)) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-void QueryConstraints::AddConstraint(int column, unsigned char op) {
-  Constraint c{};
-  c.iColumn = column;
-  c.op = op;
-  constraints_.emplace_back(c);
-}
-
-void QueryConstraints::AddOrderBy(int column, unsigned char desc) {
-  OrderBy ob{};
-  ob.iColumn = column;
-  ob.desc = desc;
-  order_by_.emplace_back(ob);
-}
-
-QueryConstraints::SqliteString QueryConstraints::ToNewSqlite3String() const {
-  std::string str_result;
-  str_result.reserve(512);
-  str_result.append("C");
-  str_result.append(std::to_string(constraints_.size()));
-  str_result.append(",");
-  for (const auto& cs : constraints_) {
-    str_result.append(std::to_string(cs.iColumn));
-    str_result.append(",");
-    str_result.append(std::to_string(cs.op));
-    str_result.append(",");
-  }
-  str_result.append("O");
-  str_result.append(std::to_string(order_by_.size()));
-  str_result.append(",");
-  for (const auto& ob : order_by_) {
-    str_result.append(std::to_string(ob.iColumn));
-    str_result.append(",");
-    str_result.append(std::to_string(ob.desc));
-    str_result.append(",");
-  }
-
-  // The last char is a "," so overwriting with the null terminator on purpose.
-  SqliteString result(
-      static_cast<char*>(sqlite3_malloc(static_cast<int>(str_result.size()))));
-  strncpy(result.get(), str_result.c_str(), str_result.size());
-  (*result)[str_result.size() - 1] = '\0';
-
-  return result;
-}
-
-QueryConstraints QueryConstraints::FromString(const char* idxStr) {
-  QueryConstraints qc;
-
-  base::StringSplitter splitter(std::string(idxStr), ',');
-
-  PERFETTO_CHECK(splitter.Next() && splitter.cur_token_size() > 1);
-  // The '+ 1' skips the letter 'C' in the first token.
-  long num_constraints = strtol(splitter.cur_token() + 1, nullptr, 10);
-  for (int i = 0; i < num_constraints; ++i) {
-    PERFETTO_CHECK(splitter.Next());
-    int col = static_cast<int>(strtol(splitter.cur_token(), nullptr, 10));
-    PERFETTO_CHECK(splitter.Next());
-    unsigned char op =
-        static_cast<unsigned char>(strtol(splitter.cur_token(), nullptr, 10));
-    qc.AddConstraint(col, op);
-  }
-
-  PERFETTO_CHECK(splitter.Next() && splitter.cur_token_size() > 1);
-  // The '+ 1' skips the letter 'O' in the current token.
-  long num_order_by = strtol(splitter.cur_token() + 1, nullptr, 10);
-  for (int i = 0; i < num_order_by; ++i) {
-    PERFETTO_CHECK(splitter.Next());
-    int col = static_cast<int>(strtol(splitter.cur_token(), nullptr, 10));
-    PERFETTO_CHECK(splitter.Next());
-    unsigned char desc =
-        static_cast<unsigned char>(strtol(splitter.cur_token(), nullptr, 10));
-    qc.AddOrderBy(col, desc);
-  }
-
-  PERFETTO_DCHECK(!splitter.Next());
-  return qc;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/sqlite/query_constraints.h b/src/trace_processor/sqlite/query_constraints.h
deleted file mode 100644
index 2c47562..0000000
--- a/src/trace_processor/sqlite/query_constraints.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_SQLITE_QUERY_CONSTRAINTS_H_
-#define SRC_TRACE_PROCESSOR_SQLITE_QUERY_CONSTRAINTS_H_
-
-#include <sqlite3.h>
-
-#include <vector>
-
-#include "perfetto/ext/base/scoped_file.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// This class stores the constraints (including the order-by information) for
-// a query on a sqlite3 virtual table and handles their de/serialization into
-// strings.
-// This is because the constraint columns and the order-by clauses are passed
-// to the xBestIndex method but the constraint values are available only in the
-// xFilter method. Unfortunately sqlite vtable API don't give any hint about
-// the validity of the constraints (i.e. constraints passed to xBestIndex can
-// be used by future xFilter calls in the far future). The only mechanism
-// offered by sqlite is the idxStr string which is returned by the vtable
-// in the xBestIndex call and passed to each corresponding xFilter call.
-class QueryConstraints {
- public:
-  using Constraint = sqlite3_index_info::sqlite3_index_constraint;
-  using OrderBy = sqlite3_index_info::sqlite3_index_orderby;
-
-  static int FreeSqliteString(char* resource);
-
-  using SqliteString = base::ScopedResource<char*, FreeSqliteString, nullptr>;
-
-  QueryConstraints();
-  ~QueryConstraints();
-  QueryConstraints(QueryConstraints&&) noexcept;
-  QueryConstraints& operator=(QueryConstraints&&);
-
-  // Two QueryConstraints with the same constraint and orderby vectors
-  // are equal.
-  bool operator==(const QueryConstraints& other) const;
-
-  void AddConstraint(int column, unsigned char op);
-
-  void AddOrderBy(int column, unsigned char desc);
-
-  void ClearOrderBy() { order_by_.clear(); }
-
-  // Converts the constraints and order by information to a string for
-  // use by sqlite.
-  SqliteString ToNewSqlite3String() const;
-
-  // Deserializes the string into QueryConstraints. String given is in the form
-  // C{# of constraints},col1,op1,col2,op2...,O{# of order by},col1,desc1...
-  // For example C1,0,3,O2,1,0,4,1
-  static QueryConstraints FromString(const char* idxStr);
-
-  const std::vector<OrderBy>& order_by() const { return order_by_; }
-
-  const std::vector<Constraint>& constraints() const { return constraints_; }
-
- private:
-  QueryConstraints(const QueryConstraints&) = delete;
-  QueryConstraints& operator=(const QueryConstraints&) = delete;
-
-  std::vector<OrderBy> order_by_;
-  std::vector<Constraint> constraints_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_SQLITE_QUERY_CONSTRAINTS_H_
diff --git a/src/trace_processor/sqlite/query_constraints_unittest.cc b/src/trace_processor/sqlite/query_constraints_unittest.cc
deleted file mode 100644
index 276cec1..0000000
--- a/src/trace_processor/sqlite/query_constraints_unittest.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.
- */
-
-#include "src/trace_processor/sqlite/query_constraints.h"
-
-#include "perfetto/base/logging.h"
-#include "test/gtest_and_gmock.h"
-
-using testing::ElementsAreArray;
-using testing::Field;
-using testing::Matcher;
-using testing::Matches;
-using testing::Pointwise;
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-class QueryConstraintsTest : public ::testing::Test {
- public:
-  QueryConstraintsTest() { PERFETTO_CHECK(sqlite3_initialize() == SQLITE_OK); }
-};
-
-TEST_F(QueryConstraintsTest, ConvertToAndFromSqlString) {
-  QueryConstraints qc;
-  qc.AddConstraint(12, 0);
-
-  QueryConstraints::SqliteString only_constraint = qc.ToNewSqlite3String();
-  ASSERT_TRUE(strcmp(only_constraint.get(), "C1,12,0,O0") == 0);
-
-  QueryConstraints qc_constraint =
-      QueryConstraints::FromString(only_constraint.get());
-  ASSERT_EQ(qc, qc_constraint);
-
-  qc.AddOrderBy(1, false);
-  qc.AddOrderBy(21, true);
-
-  QueryConstraints::SqliteString result = qc.ToNewSqlite3String();
-  ASSERT_TRUE(strcmp(result.get(), "C1,12,0,O2,1,0,21,1") == 0);
-
-  QueryConstraints qc_result = QueryConstraints::FromString(result.get());
-  ASSERT_EQ(qc, qc_result);
-}
-
-TEST_F(QueryConstraintsTest, CheckEmptyConstraints) {
-  QueryConstraints qc;
-
-  QueryConstraints::SqliteString string_result = qc.ToNewSqlite3String();
-  ASSERT_TRUE(strcmp(string_result.get(), "C0,O0") == 0);
-
-  QueryConstraints qc_result =
-      QueryConstraints::FromString(string_result.get());
-  ASSERT_EQ(qc_result.constraints().size(), 0u);
-  ASSERT_EQ(qc_result.order_by().size(), 0u);
-}
-
-TEST_F(QueryConstraintsTest, OnlyOrderBy) {
-  QueryConstraints qc;
-  qc.AddOrderBy(3, true);
-
-  QueryConstraints::SqliteString string_result = qc.ToNewSqlite3String();
-  ASSERT_TRUE(strcmp(string_result.get(), "C0,O1,3,1") == 0);
-
-  QueryConstraints qc_result =
-      QueryConstraints::FromString(string_result.get());
-  ASSERT_EQ(qc, qc_result);
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/sqlite/scoped_db.h b/src/trace_processor/sqlite/scoped_db.h
deleted file mode 100644
index 857b316..0000000
--- a/src/trace_processor/sqlite/scoped_db.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_SQLITE_SCOPED_DB_H_
-#define SRC_TRACE_PROCESSOR_SQLITE_SCOPED_DB_H_
-
-#include <sqlite3.h>
-
-#include "perfetto/ext/base/scoped_file.h"
-
-extern "C" {
-struct sqlite3;
-struct sqlite3_stmt;
-SQLITE_API extern int sqlite3_close(sqlite3*);
-SQLITE_API extern int sqlite3_finalize(sqlite3_stmt* pStmt);
-}
-
-namespace perfetto {
-namespace trace_processor {
-
-using ScopedDb = base::ScopedResource<sqlite3*, sqlite3_close, nullptr>;
-using ScopedStmt = base::ScopedResource<sqlite3_stmt*,
-                                        sqlite3_finalize,
-                                        nullptr,
-                                        /*CheckClose=*/false>;
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_SQLITE_SCOPED_DB_H_
diff --git a/src/trace_processor/sqlite/sqlite3_str_split.cc b/src/trace_processor/sqlite/sqlite3_str_split.cc
deleted file mode 100644
index 7907e9b..0000000
--- a/src/trace_processor/sqlite/sqlite3_str_split.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/sqlite/sqlite3_str_split.h"
-
-#include "src/trace_processor/sqlite/sqlite_utils.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-constexpr char kDelimiterError[] =
-    "str_split: delimiter must be a non-empty string";
-constexpr char kSplitFieldIndexError[] =
-    "str_split: field number must be a non-negative integer";
-
-void sqlite_str_split(sqlite3_context* context,
-                      int argc,
-                      sqlite3_value** argv) {
-  PERFETTO_DCHECK(argc == 3);
-  if (sqlite3_value_type(argv[1]) != SQLITE_TEXT) {
-    sqlite3_result_error(context, kDelimiterError, -1);
-    return;
-  }
-  const char* delimiter =
-      reinterpret_cast<const char*>(sqlite3_value_text(argv[1]));
-  const size_t delimiter_len = strlen(delimiter);
-  if (delimiter_len == 0) {
-    sqlite3_result_error(context, kDelimiterError, -1);
-    return;
-  }
-  if (sqlite3_value_type(argv[2]) != SQLITE_INTEGER) {
-    sqlite3_result_error(context, kSplitFieldIndexError, -1);
-    return;
-  }
-  int fld = sqlite3_value_int(argv[2]);
-  if (fld < 0) {
-    sqlite3_result_error(context, kSplitFieldIndexError, -1);
-    return;
-  }
-  if (sqlite3_value_type(argv[0]) != SQLITE_TEXT) {
-    sqlite3_result_null(context);
-    return;
-  }
-  const char* in = reinterpret_cast<const char*>(sqlite3_value_text(argv[0]));
-  const char* next;
-  do {
-    next = strstr(in, delimiter);
-    if (fld == 0) {
-      int size = next != nullptr ? static_cast<int>(next - in)
-                                 : static_cast<int>(strlen(in));
-      sqlite3_result_text(context, in, size, sqlite_utils::kSqliteTransient);
-      return;
-    } else if (next == nullptr) {
-      break;
-    }
-    in = next + delimiter_len;
-    --fld;
-  } while (fld >= 0);
-  sqlite3_result_null(context);
-}
-}  // namespace
-
-void sqlite3_str_split_init(sqlite3* db) {
-  PERFETTO_CHECK(sqlite3_create_function(db, "str_split", 3,
-                                         SQLITE_UTF8 | SQLITE_DETERMINISTIC,
-                                         nullptr, &sqlite_str_split, nullptr,
-                                         nullptr) == SQLITE_OK);
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/sqlite/sqlite3_str_split.h b/src/trace_processor/sqlite/sqlite3_str_split.h
deleted file mode 100644
index c1aa7cf..0000000
--- a/src/trace_processor/sqlite/sqlite3_str_split.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_SQLITE_SQLITE3_STR_SPLIT_H_
-#define SRC_TRACE_PROCESSOR_SQLITE_SQLITE3_STR_SPLIT_H_
-
-struct sqlite3;
-
-namespace perfetto {
-namespace trace_processor {
-
-void sqlite3_str_split_init(sqlite3* db);
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_SQLITE_SQLITE3_STR_SPLIT_H_
diff --git a/src/trace_processor/sqlite/sqlite3_str_split_unittest.cc b/src/trace_processor/sqlite/sqlite3_str_split_unittest.cc
deleted file mode 100644
index 35e0003..0000000
--- a/src/trace_processor/sqlite/sqlite3_str_split_unittest.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/sqlite/sqlite3_str_split.h"
-
-#include <sqlite3.h>
-#include <string>
-
-#include "perfetto/base/logging.h"
-#include "src/trace_processor/sqlite/scoped_db.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-class Sqlite3StrSplitTest : public ::testing::Test {
- public:
-  Sqlite3StrSplitTest() {
-    sqlite3* db = nullptr;
-    PERFETTO_CHECK(sqlite3_initialize() == SQLITE_OK);
-    PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
-    db_.reset(db);
-    sqlite3_str_split_init(db_.get());
-  }
-
-  const char* SplitStmt(const std::string& str,
-                        const std::string& delim,
-                        int field) {
-    const std::string sql = "SELECT STR_SPLIT(\"" + str + "\", \"" + delim +
-                            "\", " + std::to_string(field) + ");";
-    sqlite3_stmt* stmt = nullptr;
-    PERFETTO_CHECK(sqlite3_prepare_v2(*db_, sql.c_str(),
-                                      static_cast<int>(sql.size()), &stmt,
-                                      nullptr) == SQLITE_OK);
-    stmt_.reset(stmt);
-    PERFETTO_CHECK(sqlite3_step(stmt) == SQLITE_ROW);
-    if (sqlite3_column_type(stmt, 0) == SQLITE_NULL) {
-      return nullptr;
-    }
-    return reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
-  }
-
- protected:
-  ScopedDb db_;
-  ScopedStmt stmt_;
-};
-
-TEST_F(Sqlite3StrSplitTest, SplitNoDelimiter) {
-  ASSERT_STREQ(SplitStmt("abc", ":", 0), "abc");
-  ASSERT_EQ(SplitStmt("abc", ":", 1), nullptr);
-}
-
-TEST_F(Sqlite3StrSplitTest, SplitSingleCharDelim) {
-  ASSERT_STREQ(SplitStmt("a:bc", ":", 0), "a");
-  ASSERT_STREQ(SplitStmt("a:bc", ":", 1), "bc");
-  ASSERT_EQ(SplitStmt("a:bc", ":", 2), nullptr);
-}
-
-TEST_F(Sqlite3StrSplitTest, SplitInputConsecutiveDelim) {
-  ASSERT_STREQ(SplitStmt("a::b::c", ":", 0), "a");
-  ASSERT_STREQ(SplitStmt("a::b::c", ":", 1), "");
-  ASSERT_STREQ(SplitStmt("a::b::c", ":", 2), "b");
-  ASSERT_STREQ(SplitStmt("a::b::c", ":", 3), "");
-  ASSERT_STREQ(SplitStmt("a::b::c", ":", 4), "c");
-  ASSERT_EQ(SplitStmt("a::b::c", ":", 5), nullptr);
-}
-
-TEST_F(Sqlite3StrSplitTest, SplitStringDelim) {
-  ASSERT_STREQ(SplitStmt("abczzdefzzghi", "zz", 0), "abc");
-  ASSERT_STREQ(SplitStmt("abczzdefzzghi", "zz", 1), "def");
-  ASSERT_STREQ(SplitStmt("abczzdefzzghi", "zz", 2), "ghi");
-}
-
-TEST_F(Sqlite3StrSplitTest, SplitEmptyInput) {
-  ASSERT_STREQ(SplitStmt("", "zz", 0), "");
-  ASSERT_EQ(SplitStmt("", "zz", 1), nullptr);
-  ASSERT_EQ(SplitStmt("", "zz", 1000), nullptr);
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/sqlite/sqlite_table.cc b/src/trace_processor/sqlite/sqlite_table.cc
deleted file mode 100644
index 9a41763..0000000
--- a/src/trace_processor/sqlite/sqlite_table.cc
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * 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.
- */
-
-#include "src/trace_processor/sqlite/sqlite_table.h"
-
-#include <ctype.h>
-#include <string.h>
-#include <algorithm>
-
-#include "perfetto/base/logging.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-
-std::string TypeToString(SqlValue::Type type) {
-  switch (type) {
-    case SqlValue::Type::kString:
-      return "STRING";
-    case SqlValue::Type::kLong:
-      return "BIG INT";
-    case SqlValue::Type::kDouble:
-      return "DOUBLE";
-    case SqlValue::Type::kBytes:
-      return "BLOB";
-    case SqlValue::Type::kNull:
-      PERFETTO_FATAL("Cannot map unknown column type");
-  }
-  PERFETTO_FATAL("Not reached");  // For gcc
-}
-
-}  // namespace
-
-// static
-bool SqliteTable::debug = false;
-
-SqliteTable::SqliteTable() = default;
-SqliteTable::~SqliteTable() = default;
-
-int SqliteTable::OpenInternal(sqlite3_vtab_cursor** ppCursor) {
-  // Freed in xClose().
-  *ppCursor = static_cast<sqlite3_vtab_cursor*>(CreateCursor().release());
-  return SQLITE_OK;
-}
-
-int SqliteTable::BestIndexInternal(sqlite3_index_info* idx) {
-  using ConstraintInfo = BestIndexInfo::ConstraintInfo;
-
-  QueryConstraints in_qc;
-  BestIndexInfo info;
-  for (int i = 0; i < idx->nConstraint; i++) {
-    const auto& cs = idx->aConstraint[i];
-    if (!cs.usable)
-      continue;
-    in_qc.AddConstraint(cs.iColumn, cs.op);
-
-    ConstraintInfo c_info;
-    c_info.qc_idx = static_cast<uint32_t>(in_qc.constraints().size() - 1);
-    info.constraint_info.emplace_back(c_info);
-  }
-
-  for (int i = 0; i < idx->nOrderBy; i++) {
-    int column = idx->aOrderBy[i].iColumn;
-    bool desc = idx->aOrderBy[i].desc;
-    in_qc.AddOrderBy(column, desc);
-  }
-
-  int ret = BestIndex(in_qc, &info);
-  if (ret != SQLITE_OK)
-    return ret;
-
-  auto& cs_info = info.constraint_info;
-
-  // Remove all the pruned terms from the constraints.
-  {
-    auto prune_fn = [](const ConstraintInfo& t) { return t.prune; };
-    auto prune_cs_it = std::remove_if(cs_info.begin(), cs_info.end(), prune_fn);
-    cs_info.erase(prune_cs_it, cs_info.end());
-  }
-
-  idx->orderByConsumed = info.prune_order_by || info.sqlite_omit_order_by;
-  idx->estimatedCost = info.estimated_cost;
-
-  uint32_t in_qc_idx = 0;
-  for (int i = 0; i < idx->nConstraint; i++) {
-    const auto& c = idx->aConstraint[i];
-    if (c.usable) {
-      auto cs_fn = [in_qc_idx](const ConstraintInfo& t) {
-        return t.qc_idx == in_qc_idx;
-      };
-      auto it = std::find_if(cs_info.begin(), cs_info.end(), cs_fn);
-
-      // If the iterator no longer exists, we must have pruned it.
-      if (it == cs_info.end()) {
-        idx->aConstraintUsage[i].omit = true;
-      } else {
-        idx->aConstraintUsage[i].argvIndex =
-            static_cast<int>(std::distance(cs_info.begin(), it)) + 1;
-        idx->aConstraintUsage[i].omit = it->sqlite_omit;
-      }
-      in_qc_idx++;
-    }
-  }
-
-  QueryConstraints out_qc;
-  for (const auto& c_info : cs_info) {
-    const auto& c = in_qc.constraints()[c_info.qc_idx];
-    out_qc.AddConstraint(c.iColumn, c.op);
-  }
-  if (!info.prune_order_by) {
-    for (const auto& o : in_qc.order_by()) {
-      out_qc.AddOrderBy(o.iColumn, o.desc);
-    }
-  }
-
-  auto out_qc_str = out_qc.ToNewSqlite3String();
-  if (SqliteTable::debug) {
-    PERFETTO_LOG(
-        "[%s::BestIndex] constraints=%s orderByConsumed=%d estimatedCost=%d",
-        name_.c_str(), out_qc_str.get(), idx->orderByConsumed,
-        info.estimated_cost);
-  }
-
-  idx->idxStr = out_qc_str.release();
-  idx->needToFreeIdxStr = true;
-  idx->idxNum = ++best_index_num_;
-
-  return SQLITE_OK;
-}
-
-int SqliteTable::FindFunction(const char*, FindFunctionFn, void**) {
-  return 0;
-}
-
-int SqliteTable::Update(int, sqlite3_value**, sqlite3_int64*) {
-  return SQLITE_READONLY;
-}
-
-const QueryConstraints& SqliteTable::ParseConstraints(int idxNum,
-                                                      const char* idxStr,
-                                                      int argc) {
-  bool cache_hit = true;
-  if (idxNum != qc_hash_) {
-    qc_cache_ = QueryConstraints::FromString(idxStr);
-    qc_hash_ = idxNum;
-    cache_hit = false;
-  }
-  if (SqliteTable::debug) {
-    PERFETTO_LOG("[%s::ParseConstraints] constraints=%s argc=%d cache_hit=%d",
-                 name_.c_str(), idxStr, argc, cache_hit);
-  }
-  return qc_cache_;
-}
-
-SqliteTable::Cursor::Cursor(SqliteTable* table) : table_(table) {
-  // This is required to prevent us from leaving this field uninitialised if
-  // we ever move construct the Cursor.
-  pVtab = table;
-}
-SqliteTable::Cursor::~Cursor() = default;
-
-int SqliteTable::Cursor::RowId(sqlite3_int64*) {
-  return SQLITE_ERROR;
-}
-
-SqliteTable::Column::Column(size_t index,
-                            std::string name,
-                            SqlValue::Type type,
-                            bool hidden)
-    : index_(index), name_(name), type_(type), hidden_(hidden) {}
-
-SqliteTable::Schema::Schema(std::vector<Column> columns,
-                            std::vector<size_t> primary_keys)
-    : columns_(std::move(columns)), primary_keys_(std::move(primary_keys)) {
-  for (size_t i = 0; i < columns_.size(); i++) {
-    PERFETTO_CHECK(columns_[i].index() == i);
-  }
-  for (auto key : primary_keys_) {
-    PERFETTO_CHECK(key < columns_.size());
-  }
-}
-
-SqliteTable::Schema::Schema() = default;
-SqliteTable::Schema::Schema(const Schema&) = default;
-SqliteTable::Schema& SqliteTable::Schema::operator=(const Schema&) = default;
-
-std::string SqliteTable::Schema::ToCreateTableStmt() const {
-  std::string stmt = "CREATE TABLE x(";
-  for (size_t i = 0; i < columns_.size(); ++i) {
-    const Column& col = columns_[i];
-    stmt += " " + col.name();
-
-    if (col.type() != SqlValue::Type::kNull) {
-      stmt += " " + TypeToString(col.type());
-    } else if (std::find(primary_keys_.begin(), primary_keys_.end(), i) !=
-               primary_keys_.end()) {
-      PERFETTO_FATAL("Unknown type for primary key column %s",
-                     col.name().c_str());
-    }
-    if (col.hidden()) {
-      stmt += " HIDDEN";
-    }
-    stmt += ",";
-  }
-  stmt += " PRIMARY KEY(";
-  for (size_t i = 0; i < primary_keys_.size(); i++) {
-    if (i != 0)
-      stmt += ", ";
-    stmt += columns_[primary_keys_[i]].name();
-  }
-  stmt += ")) WITHOUT ROWID;";
-  return stmt;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/sqlite/sqlite_table.h b/src/trace_processor/sqlite/sqlite_table.h
deleted file mode 100644
index 3b9f83c..0000000
--- a/src/trace_processor/sqlite/sqlite_table.h
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_SQLITE_SQLITE_TABLE_H_
-#define SRC_TRACE_PROCESSOR_SQLITE_SQLITE_TABLE_H_
-
-#include <sqlite3.h>
-
-#include <functional>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/trace_processor/basic_types.h"
-#include "perfetto/trace_processor/status.h"
-#include "src/trace_processor/sqlite/query_constraints.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceStorage;
-
-// Abstract base class representing a SQLite virtual table. Implements the
-// common bookeeping required across all tables and allows subclasses to
-// implement a friendlier API than that required by SQLite.
-class SqliteTable : public sqlite3_vtab {
- public:
-  template <typename Context>
-  using Factory =
-      std::function<std::unique_ptr<SqliteTable>(sqlite3*, Context)>;
-
-  // Describes a column of this table.
-  class Column {
-   public:
-    Column(size_t idx,
-           std::string name,
-           SqlValue::Type type,
-           bool hidden = false);
-
-    size_t index() const { return index_; }
-    const std::string& name() const { return name_; }
-    SqlValue::Type type() const { return type_; }
-    bool hidden() const { return hidden_; }
-
-   private:
-    size_t index_ = 0;
-    std::string name_;
-    SqlValue::Type type_ = SqlValue::Type::kNull;
-    bool hidden_ = false;
-  };
-
-  // When set it logs all BestIndex and Filter actions on the console.
-  static bool debug;
-
-  // Public for unique_ptr destructor calls.
-  virtual ~SqliteTable();
-
-  // Abstract base class representing an SQLite Cursor. Presents a friendlier
-  // API for subclasses to implement.
-  class Cursor : public sqlite3_vtab_cursor {
-   public:
-    Cursor(SqliteTable* table);
-    virtual ~Cursor();
-
-    // Methods to be implemented by derived table classes.
-
-    // Called to intialise the cursor with the constraints of the query.
-    virtual int Filter(const QueryConstraints& qc, sqlite3_value**) = 0;
-
-    // Called to forward the cursor to the next row in the table.
-    virtual int Next() = 0;
-
-    // Called to check if the cursor has reached eof. Column will be called iff
-    // this method returns true.
-    virtual int Eof() = 0;
-
-    // Used to extract the value from the column at index |N|.
-    virtual int Column(sqlite3_context* context, int N) = 0;
-
-    // Optional methods to implement.
-    virtual int RowId(sqlite3_int64*);
-
-   protected:
-    Cursor(Cursor&) = delete;
-    Cursor& operator=(const Cursor&) = delete;
-
-    Cursor(Cursor&&) noexcept = default;
-    Cursor& operator=(Cursor&&) = default;
-
-   private:
-    friend class SqliteTable;
-
-    SqliteTable* table_ = nullptr;
-  };
-
-  // The schema of the table. Created by subclasses to allow the table class to
-  // do filtering and inform SQLite about the CREATE table statement.
-  class Schema {
-   public:
-    Schema();
-    Schema(std::vector<Column>, std::vector<size_t> primary_keys);
-
-    // This class is explicitly copiable.
-    Schema(const Schema&);
-    Schema& operator=(const Schema& t);
-
-    std::string ToCreateTableStmt() const;
-
-    const std::vector<Column>& columns() const { return columns_; }
-    const std::vector<size_t> primary_keys() { return primary_keys_; }
-
-   private:
-    // The names and types of the columns of the table.
-    std::vector<Column> columns_;
-
-    // The primary keys of the table given by an offset into |columns|.
-    std::vector<size_t> primary_keys_;
-  };
-
- protected:
-  // Populated by a BestIndex call to allow subclasses to tweak SQLite's
-  // handling of sets of constraints.
-  struct BestIndexInfo {
-    // Contains info about a single constraint.
-    struct ConstraintInfo {
-      // Gives the index of this constraint in the QueryConstraints class.
-      uint32_t qc_idx = 0;
-
-      // Indicates whether this constraint should be removed from the
-      // QueryConstraint class when passed to SqliteTable::Filter.
-      bool prune = false;
-
-      // Indiciates whether SQLite should omit double checking this constraint.
-      //
-      // If |prune| is set to true, this value will be ignored and SQLite will
-      // be told that it can omit double checking (i.e. this value will
-      // implicitly be taken to be true).
-      bool sqlite_omit = false;
-    };
-
-    // Stores the estimated cost of this query.
-    uint32_t estimated_cost = 0;
-
-    // Stores the information about each constraint.
-    std::vector<ConstraintInfo> constraint_info;
-
-    // Indicates that all the order by constraints should be pruned. This should
-    // be set to true if the table is exactly ordered by the order by terms in
-    // QueryConstraints.
-    bool prune_order_by = false;
-
-    // Indicates that SQLite should not double check the result of the order by
-    // clause.
-    //
-    // If |prune_order_by| is set to true, this value will be ignored and SQLite
-    // will be told that it can omit double checking (i.e. this value will
-    // implicitly be taken to be true).
-    bool sqlite_omit_order_by = false;
-  };
-
-  template <typename Context>
-  struct TableDescriptor {
-    SqliteTable::Factory<Context> factory;
-    Context context;
-    std::string name;
-    sqlite3_module module = {};
-  };
-
-  SqliteTable();
-
-  // Called by derived classes to register themselves with the SQLite db.
-  // |read_write| specifies whether the table can also be written to.
-  // |requires_args| should be true if the table requires arguments in order to
-  // be instantiated.
-  // Note: this function is inlined here because we use the TTable template to
-  // devirtualise the function calls.
-  template <typename TTable, typename Context = const TraceStorage*>
-  static void Register(sqlite3* db,
-                       Context ctx,
-                       const std::string& table_name,
-                       bool read_write = false,
-                       bool requires_args = false) {
-    using TCursor = typename TTable::Cursor;
-
-    std::unique_ptr<TableDescriptor<Context>> desc(
-        new TableDescriptor<Context>());
-    desc->context = std::move(ctx);
-    desc->factory = GetFactory<TTable, Context>();
-    desc->name = table_name;
-    sqlite3_module* module = &desc->module;
-    memset(module, 0, sizeof(*module));
-
-    auto create_fn = [](sqlite3* xdb, void* arg, int argc,
-                        const char* const* argv, sqlite3_vtab** tab,
-                        char** pzErr) {
-      const auto* xdesc = static_cast<const TableDescriptor<Context>*>(arg);
-      auto table = xdesc->factory(xdb, std::move(xdesc->context));
-      table->name_ = xdesc->name;
-
-      Schema schema;
-      util::Status status = table->Init(argc, argv, &schema);
-      if (!status.ok()) {
-        *pzErr = sqlite3_mprintf("%s", status.c_message());
-        return SQLITE_ERROR;
-      }
-
-      auto create_stmt = schema.ToCreateTableStmt();
-      PERFETTO_DLOG("Create table statement: %s", create_stmt.c_str());
-
-      int res = sqlite3_declare_vtab(xdb, create_stmt.c_str());
-      if (res != SQLITE_OK)
-        return res;
-
-      // Freed in xDisconnect().
-      table->schema_ = std::move(schema);
-      *tab = table.release();
-
-      return SQLITE_OK;
-    };
-    auto destroy_fn = [](sqlite3_vtab* t) {
-      delete static_cast<TTable*>(t);
-      return SQLITE_OK;
-    };
-
-    module->xCreate = create_fn;
-    module->xConnect = create_fn;
-    module->xDisconnect = destroy_fn;
-    module->xDestroy = destroy_fn;
-    module->xOpen = [](sqlite3_vtab* t, sqlite3_vtab_cursor** c) {
-      return static_cast<TTable*>(t)->OpenInternal(c);
-    };
-    module->xClose = [](sqlite3_vtab_cursor* c) {
-      delete static_cast<TCursor*>(c);
-      return SQLITE_OK;
-    };
-    module->xBestIndex = [](sqlite3_vtab* t, sqlite3_index_info* i) {
-      return static_cast<TTable*>(t)->BestIndexInternal(i);
-    };
-    module->xFilter = [](sqlite3_vtab_cursor* c, int i, const char* s, int a,
-                         sqlite3_value** v) {
-      const auto& qc =
-          static_cast<Cursor*>(c)->table_->ParseConstraints(i, s, a);
-      return static_cast<TCursor*>(c)->Filter(qc, v);
-    };
-    module->xNext = [](sqlite3_vtab_cursor* c) {
-      return static_cast<TCursor*>(c)->Next();
-    };
-    module->xEof = [](sqlite3_vtab_cursor* c) {
-      return static_cast<TCursor*>(c)->Eof();
-    };
-    module->xColumn = [](sqlite3_vtab_cursor* c, sqlite3_context* a, int b) {
-      return static_cast<TCursor*>(c)->Column(a, b);
-    };
-    module->xRowid = [](sqlite3_vtab_cursor* c, sqlite3_int64* r) {
-      return static_cast<TCursor*>(c)->RowId(r);
-    };
-    module->xFindFunction =
-        [](sqlite3_vtab* t, int, const char* name,
-           void (**fn)(sqlite3_context*, int, sqlite3_value**), void** args) {
-          return static_cast<TTable*>(t)->FindFunction(name, fn, args);
-        };
-
-    if (read_write) {
-      module->xUpdate = [](sqlite3_vtab* t, int a, sqlite3_value** v,
-                           sqlite3_int64* r) {
-        return static_cast<TTable*>(t)->Update(a, v, r);
-      };
-    }
-
-    int res = sqlite3_create_module_v2(
-        db, table_name.c_str(), module, desc.release(),
-        [](void* arg) { delete static_cast<TableDescriptor<Context>*>(arg); });
-    PERFETTO_CHECK(res == SQLITE_OK);
-
-    // Register virtual tables into an internal 'perfetto_tables' table. This is
-    // used for iterating through all the tables during a database export. Note
-    // that virtual tables requiring arguments aren't registered because they
-    // can't be automatically instantiated for exporting.
-    if (!requires_args) {
-      char* insert_sql = sqlite3_mprintf(
-          "INSERT INTO perfetto_tables(name) VALUES('%q')", table_name.c_str());
-      char* error = nullptr;
-      sqlite3_exec(db, insert_sql, nullptr, nullptr, &error);
-      sqlite3_free(insert_sql);
-      if (error) {
-        PERFETTO_ELOG("Error registering table: %s", error);
-        sqlite3_free(error);
-      }
-    }
-  }
-
-  // Methods to be implemented by derived table classes.
-  virtual util::Status Init(int argc, const char* const* argv, Schema*) = 0;
-  virtual std::unique_ptr<Cursor> CreateCursor() = 0;
-  virtual int BestIndex(const QueryConstraints& qc, BestIndexInfo* info) = 0;
-
-  // Optional metods to implement.
-  using FindFunctionFn = void (**)(sqlite3_context*, int, sqlite3_value**);
-  virtual int FindFunction(const char* name, FindFunctionFn fn, void** args);
-
-  // At registration time, the function should also pass true for |read_write|.
-  virtual int Update(int, sqlite3_value**, sqlite3_int64*);
-
-  void SetErrorMessage(char* error) {
-    sqlite3_free(zErrMsg);
-    zErrMsg = error;
-  }
-
-  const Schema& schema() const { return schema_; }
-  const std::string& name() const { return name_; }
-
- private:
-  template <typename TableType, typename Context>
-  static Factory<Context> GetFactory() {
-    return [](sqlite3* db, Context ctx) {
-      return std::unique_ptr<SqliteTable>(new TableType(db, std::move(ctx)));
-    };
-  }
-
-  const QueryConstraints& ParseConstraints(int idxNum,
-                                           const char* idxStr,
-                                           int argc);
-
-  // Overriden functions from sqlite3_vtab.
-  int OpenInternal(sqlite3_vtab_cursor**);
-  int BestIndexInternal(sqlite3_index_info*);
-
-  SqliteTable(const SqliteTable&) = delete;
-  SqliteTable& operator=(const SqliteTable&) = delete;
-
-  std::string name_;
-  Schema schema_;
-
-  QueryConstraints qc_cache_;
-  int qc_hash_ = 0;
-  int best_index_num_ = 0;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_SQLITE_SQLITE_TABLE_H_
diff --git a/src/trace_processor/sqlite/sqlite_utils.h b/src/trace_processor/sqlite/sqlite_utils.h
deleted file mode 100644
index 8e97c03..0000000
--- a/src/trace_processor/sqlite/sqlite_utils.h
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_SQLITE_SQLITE_UTILS_H_
-#define SRC_TRACE_PROCESSOR_SQLITE_SQLITE_UTILS_H_
-
-#include <math.h>
-#include <sqlite3.h>
-
-#include <functional>
-#include <limits>
-#include <string>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/optional.h"
-#include "src/trace_processor/sqlite/scoped_db.h"
-#include "src/trace_processor/sqlite/sqlite_table.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace sqlite_utils {
-
-const auto kSqliteStatic = reinterpret_cast<sqlite3_destructor_type>(0);
-const auto kSqliteTransient = reinterpret_cast<sqlite3_destructor_type>(-1);
-
-template <typename T>
-using is_numeric =
-    typename std::enable_if<std::is_arithmetic<T>::value, T>::type;
-
-template <typename T>
-using is_float =
-    typename std::enable_if<std::is_floating_point<T>::value, T>::type;
-
-template <typename T>
-using is_int = typename std::enable_if<std::is_integral<T>::value, T>::type;
-
-inline bool IsOpEq(int op) {
-  return op == SQLITE_INDEX_CONSTRAINT_EQ;
-}
-
-inline bool IsOpGe(int op) {
-  return op == SQLITE_INDEX_CONSTRAINT_GE;
-}
-
-inline bool IsOpGt(int op) {
-  return op == SQLITE_INDEX_CONSTRAINT_GT;
-}
-
-inline bool IsOpLe(int op) {
-  return op == SQLITE_INDEX_CONSTRAINT_LE;
-}
-
-inline bool IsOpLt(int op) {
-  return op == SQLITE_INDEX_CONSTRAINT_LT;
-}
-
-inline std::string OpToString(int op) {
-  switch (op) {
-    case SQLITE_INDEX_CONSTRAINT_EQ:
-      return "=";
-    case SQLITE_INDEX_CONSTRAINT_NE:
-      return "!=";
-    case SQLITE_INDEX_CONSTRAINT_GE:
-      return ">=";
-    case SQLITE_INDEX_CONSTRAINT_GT:
-      return ">";
-    case SQLITE_INDEX_CONSTRAINT_LE:
-      return "<=";
-    case SQLITE_INDEX_CONSTRAINT_LT:
-      return "<";
-    case SQLITE_INDEX_CONSTRAINT_LIKE:
-      return "like";
-    default:
-      PERFETTO_FATAL("Operator to string conversion not impemented for %d", op);
-  }
-}
-
-inline bool IsOpIsNull(int op) {
-  return op == SQLITE_INDEX_CONSTRAINT_ISNULL;
-}
-
-inline bool IsOpIsNotNull(int op) {
-  return op == SQLITE_INDEX_CONSTRAINT_ISNOTNULL;
-}
-
-template <typename T>
-T ExtractSqliteValue(sqlite3_value* value);
-
-template <>
-inline uint8_t ExtractSqliteValue(sqlite3_value* value) {
-  auto type = sqlite3_value_type(value);
-  PERFETTO_DCHECK(type == SQLITE_INTEGER);
-  return static_cast<uint8_t>(sqlite3_value_int(value));
-}
-
-template <>
-inline uint32_t ExtractSqliteValue(sqlite3_value* value) {
-  auto type = sqlite3_value_type(value);
-  PERFETTO_DCHECK(type == SQLITE_INTEGER);
-  return static_cast<uint32_t>(sqlite3_value_int64(value));
-}
-
-template <>
-inline int32_t ExtractSqliteValue(sqlite3_value* value) {
-  auto type = sqlite3_value_type(value);
-  PERFETTO_DCHECK(type == SQLITE_INTEGER);
-  return sqlite3_value_int(value);
-}
-
-template <>
-inline int64_t ExtractSqliteValue(sqlite3_value* value) {
-  auto type = sqlite3_value_type(value);
-  PERFETTO_DCHECK(type == SQLITE_INTEGER);
-  return static_cast<int64_t>(sqlite3_value_int64(value));
-}
-
-template <>
-inline double ExtractSqliteValue(sqlite3_value* value) {
-  auto type = sqlite3_value_type(value);
-  PERFETTO_DCHECK(type == SQLITE_FLOAT || type == SQLITE_INTEGER);
-  return sqlite3_value_double(value);
-}
-
-template <>
-inline bool ExtractSqliteValue(sqlite3_value* value) {
-  auto type = sqlite3_value_type(value);
-  PERFETTO_DCHECK(type == SQLITE_INTEGER);
-  return static_cast<bool>(sqlite3_value_int(value));
-}
-
-// Do not add a uint64_t version of ExtractSqliteValue. You should not be using
-// uint64_t at all given that SQLite doesn't support it.
-
-template <>
-inline const char* ExtractSqliteValue(sqlite3_value* value) {
-  auto type = sqlite3_value_type(value);
-  PERFETTO_DCHECK(type == SQLITE_TEXT);
-  return reinterpret_cast<const char*>(sqlite3_value_text(value));
-}
-
-template <>
-inline std::string ExtractSqliteValue(sqlite3_value* value) {
-  return ExtractSqliteValue<const char*>(value);
-}
-
-template <typename T>
-class NumericPredicate {
- public:
-  NumericPredicate(int op, T constant) : op_(op), constant_(constant) {}
-
-  PERFETTO_ALWAYS_INLINE bool operator()(T other) const {
-    switch (op_) {
-      case SQLITE_INDEX_CONSTRAINT_ISNULL:
-        return false;
-      case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
-        return true;
-      case SQLITE_INDEX_CONSTRAINT_EQ:
-      case SQLITE_INDEX_CONSTRAINT_IS:
-        return std::equal_to<T>()(other, constant_);
-      case SQLITE_INDEX_CONSTRAINT_NE:
-      case SQLITE_INDEX_CONSTRAINT_ISNOT:
-        return std::not_equal_to<T>()(other, constant_);
-      case SQLITE_INDEX_CONSTRAINT_GE:
-        return std::greater_equal<T>()(other, constant_);
-      case SQLITE_INDEX_CONSTRAINT_GT:
-        return std::greater<T>()(other, constant_);
-      case SQLITE_INDEX_CONSTRAINT_LE:
-        return std::less_equal<T>()(other, constant_);
-      case SQLITE_INDEX_CONSTRAINT_LT:
-        return std::less<T>()(other, constant_);
-      default:
-        PERFETTO_FATAL("For GCC");
-    }
-  }
-
- private:
-  int op_;
-  T constant_;
-};
-
-template <typename T, typename sqlite_utils::is_numeric<T>* = nullptr>
-NumericPredicate<T> CreateNumericPredicate(int op, sqlite3_value* value) {
-  T extracted =
-      IsOpIsNull(op) || IsOpIsNotNull(op) ? 0 : ExtractSqliteValue<T>(value);
-  return NumericPredicate<T>(op, extracted);
-}
-
-inline std::function<bool(const char*)> CreateStringPredicate(
-    int op,
-    sqlite3_value* value) {
-  switch (op) {
-    case SQLITE_INDEX_CONSTRAINT_ISNULL:
-      return [](const char* f) { return f == nullptr; };
-    case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
-      return [](const char* f) { return f != nullptr; };
-  }
-
-  const char* val = reinterpret_cast<const char*>(sqlite3_value_text(value));
-
-  // If the value compared against is null, then to stay consistent with SQL
-  // handling, we have to return false for non-null operators.
-  if (val == nullptr) {
-    PERFETTO_CHECK(op != SQLITE_INDEX_CONSTRAINT_IS &&
-                   op != SQLITE_INDEX_CONSTRAINT_ISNOT);
-    return [](const char*) { return false; };
-  }
-
-  switch (op) {
-    case SQLITE_INDEX_CONSTRAINT_EQ:
-    case SQLITE_INDEX_CONSTRAINT_IS:
-      return [val](const char* str) {
-        return str != nullptr && strcmp(str, val) == 0;
-      };
-    case SQLITE_INDEX_CONSTRAINT_NE:
-    case SQLITE_INDEX_CONSTRAINT_ISNOT:
-      return [val](const char* str) {
-        return str != nullptr && strcmp(str, val) != 0;
-      };
-    case SQLITE_INDEX_CONSTRAINT_GE:
-      return [val](const char* str) {
-        return str != nullptr && strcmp(str, val) >= 0;
-      };
-    case SQLITE_INDEX_CONSTRAINT_GT:
-      return [val](const char* str) {
-        return str != nullptr && strcmp(str, val) > 0;
-      };
-    case SQLITE_INDEX_CONSTRAINT_LE:
-      return [val](const char* str) {
-        return str != nullptr && strcmp(str, val) <= 0;
-      };
-    case SQLITE_INDEX_CONSTRAINT_LT:
-      return [val](const char* str) {
-        return str != nullptr && strcmp(str, val) < 0;
-      };
-    case SQLITE_INDEX_CONSTRAINT_LIKE:
-      return [val](const char* str) {
-        return str != nullptr && sqlite3_strlike(val, str, 0) == 0;
-      };
-    case SQLITE_INDEX_CONSTRAINT_GLOB:
-      return [val](const char* str) {
-        return str != nullptr && sqlite3_strglob(val, str) == 0;
-      };
-    default:
-      PERFETTO_FATAL("For GCC");
-  }
-}
-
-// Greater bound for floating point numbers.
-template <typename T, typename sqlite_utils::is_float<T>* = nullptr>
-T FindGtBound(bool is_eq, sqlite3_value* sqlite_val) {
-  constexpr auto kMax = static_cast<long double>(std::numeric_limits<T>::max());
-  auto type = sqlite3_value_type(sqlite_val);
-  if (type != SQLITE_INTEGER && type != SQLITE_FLOAT) {
-    return kMax;
-  }
-
-  // If this is a strict gt bound then just get the next highest float
-  // after value.
-  auto value = ExtractSqliteValue<T>(sqlite_val);
-  return is_eq ? value : nexttoward(value, kMax);
-}
-
-template <typename T, typename sqlite_utils::is_int<T>* = nullptr>
-T FindGtBound(bool is_eq, sqlite3_value* sqlite_val) {
-  auto type = sqlite3_value_type(sqlite_val);
-  if (type == SQLITE_INTEGER) {
-    auto value = ExtractSqliteValue<T>(sqlite_val);
-    return is_eq ? value : value + 1;
-  } else if (type == SQLITE_FLOAT) {
-    auto value = ExtractSqliteValue<double>(sqlite_val);
-    auto above = ceil(value);
-    auto cast = static_cast<T>(above);
-    return value < above ? cast : (is_eq ? cast : cast + 1);
-  } else {
-    return std::numeric_limits<T>::max();
-  }
-}
-
-template <typename T, typename sqlite_utils::is_float<T>* = nullptr>
-T FindLtBound(bool is_eq, sqlite3_value* sqlite_val) {
-  constexpr auto kMin =
-      static_cast<long double>(std::numeric_limits<T>::lowest());
-  auto type = sqlite3_value_type(sqlite_val);
-  if (type != SQLITE_INTEGER && type != SQLITE_FLOAT) {
-    return kMin;
-  }
-
-  // If this is a strict lt bound then just get the next lowest float
-  // before value.
-  auto value = ExtractSqliteValue<T>(sqlite_val);
-  return is_eq ? value : nexttoward(value, kMin);
-}
-
-template <typename T, typename sqlite_utils::is_int<T>* = nullptr>
-T FindLtBound(bool is_eq, sqlite3_value* sqlite_val) {
-  auto type = sqlite3_value_type(sqlite_val);
-  if (type == SQLITE_INTEGER) {
-    auto value = ExtractSqliteValue<T>(sqlite_val);
-    return is_eq ? value : value - 1;
-  } else if (type == SQLITE_FLOAT) {
-    auto value = ExtractSqliteValue<double>(sqlite_val);
-    auto below = floor(value);
-    auto cast = static_cast<T>(below);
-    return value > below ? cast : (is_eq ? cast : cast - 1);
-  } else {
-    return std::numeric_limits<T>::max();
-  }
-}
-
-template <typename T, typename sqlite_utils::is_float<T>* = nullptr>
-T FindEqBound(sqlite3_value* sqlite_val) {
-  auto type = sqlite3_value_type(sqlite_val);
-  if (type != SQLITE_INTEGER && type != SQLITE_FLOAT) {
-    return std::numeric_limits<T>::max();
-  }
-  return ExtractSqliteValue<T>(sqlite_val);
-}
-
-template <typename T, typename sqlite_utils::is_int<T>* = nullptr>
-T FindEqBound(sqlite3_value* sqlite_val) {
-  auto type = sqlite3_value_type(sqlite_val);
-  if (type == SQLITE_INTEGER) {
-    return ExtractSqliteValue<T>(sqlite_val);
-  } else if (type == SQLITE_FLOAT) {
-    auto value = ExtractSqliteValue<double>(sqlite_val);
-    auto below = floor(value);
-    auto cast = static_cast<T>(below);
-    return value > below ? std::numeric_limits<T>::max() : cast;
-  } else {
-    return std::numeric_limits<T>::max();
-  }
-}
-
-template <typename T>
-void ReportSqliteResult(sqlite3_context*, T value);
-
-// Do not add a uint64_t version of ReportSqliteResult. You should not be using
-// uint64_t at all given that SQLite doesn't support it.
-
-template <>
-inline void ReportSqliteResult(sqlite3_context* ctx, int32_t value) {
-  sqlite3_result_int(ctx, value);
-}
-
-template <>
-inline void ReportSqliteResult(sqlite3_context* ctx, int64_t value) {
-  sqlite3_result_int64(ctx, value);
-}
-
-template <>
-inline void ReportSqliteResult(sqlite3_context* ctx, uint8_t value) {
-  sqlite3_result_int(ctx, value);
-}
-
-template <>
-inline void ReportSqliteResult(sqlite3_context* ctx, uint32_t value) {
-  sqlite3_result_int64(ctx, value);
-}
-
-template <>
-inline void ReportSqliteResult(sqlite3_context* ctx, bool value) {
-  sqlite3_result_int(ctx, value);
-}
-
-template <>
-inline void ReportSqliteResult(sqlite3_context* ctx, double value) {
-  sqlite3_result_double(ctx, value);
-}
-
-inline std::string SqliteValueAsString(sqlite3_value* value) {
-  switch (sqlite3_value_type(value)) {
-    case SQLITE_INTEGER:
-      return std::to_string(sqlite3_value_int64(value));
-    case SQLITE_FLOAT:
-      return std::to_string(sqlite3_value_double(value));
-    case SQLITE_TEXT: {
-      const char* str =
-          reinterpret_cast<const char*>(sqlite3_value_text(value));
-      return "'" + std::string(str) + "'";
-    }
-    default:
-      PERFETTO_FATAL("Unknown value type %d", sqlite3_value_type(value));
-  }
-}
-
-inline std::vector<SqliteTable::Column> GetColumnsForTable(
-    sqlite3* db,
-    const std::string& raw_table_name) {
-  char sql[1024];
-  const char kRawSql[] = "SELECT name, type from pragma_table_info(\"%s\")";
-
-  // Support names which are table valued functions with arguments.
-  std::string table_name = raw_table_name.substr(0, raw_table_name.find('('));
-  int n = snprintf(sql, sizeof(sql), kRawSql, table_name.c_str());
-  PERFETTO_DCHECK(n >= 0 || static_cast<size_t>(n) < sizeof(sql));
-
-  sqlite3_stmt* raw_stmt = nullptr;
-  int err = sqlite3_prepare_v2(db, sql, n, &raw_stmt, nullptr);
-  if (err != SQLITE_OK) {
-    PERFETTO_ELOG("Preparing database failed");
-    return {};
-  }
-  ScopedStmt stmt(raw_stmt);
-  PERFETTO_DCHECK(sqlite3_column_count(*stmt) == 2);
-
-  std::vector<SqliteTable::Column> columns;
-  for (;;) {
-    err = sqlite3_step(raw_stmt);
-    if (err == SQLITE_DONE)
-      break;
-    if (err != SQLITE_ROW) {
-      PERFETTO_ELOG("Querying schema of table %s failed",
-                    raw_table_name.c_str());
-      return {};
-    }
-
-    const char* name =
-        reinterpret_cast<const char*>(sqlite3_column_text(*stmt, 0));
-    const char* raw_type =
-        reinterpret_cast<const char*>(sqlite3_column_text(*stmt, 1));
-    if (!name || !raw_type || !*name) {
-      PERFETTO_FATAL("Schema for %s has invalid column values",
-                     raw_table_name.c_str());
-    }
-
-    SqlValue::Type type;
-    if (strcmp(raw_type, "STRING") == 0) {
-      type = SqlValue::Type::kString;
-    } else if (strcmp(raw_type, "DOUBLE") == 0) {
-      type = SqlValue::Type::kDouble;
-    } else if (strcmp(raw_type, "BIG INT") == 0 ||
-               strcmp(raw_type, "UNSIGNED INT") == 0 ||
-               strcmp(raw_type, "INT") == 0 ||
-               strcmp(raw_type, "BOOLEAN") == 0) {
-      type = SqlValue::Type::kLong;
-    } else if (!*raw_type) {
-      PERFETTO_DLOG("Unknown column type for %s %s", raw_table_name.c_str(),
-                    name);
-      type = SqlValue::Type::kNull;
-    } else {
-      PERFETTO_FATAL("Unknown column type '%s' on table %s", raw_type,
-                     raw_table_name.c_str());
-    }
-    columns.emplace_back(columns.size(), name, type);
-  }
-  return columns;
-}
-
-template <typename T>
-int CompareValuesAsc(const T& f, const T& s) {
-  return f < s ? -1 : (f > s ? 1 : 0);
-}
-
-template <typename T>
-int CompareValuesDesc(const T& f, const T& s) {
-  return -CompareValuesAsc(f, s);
-}
-
-}  // namespace sqlite_utils
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_SQLITE_SQLITE_UTILS_H_
diff --git a/src/trace_processor/sqlite3_str_split.cc b/src/trace_processor/sqlite3_str_split.cc
new file mode 100644
index 0000000..f7b584a
--- /dev/null
+++ b/src/trace_processor/sqlite3_str_split.cc
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 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 "src/trace_processor/sqlite3_str_split.h"
+
+#include "src/trace_processor/sqlite_utils.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+namespace {
+constexpr char kDelimiterError[] =
+    "str_split: delimiter must be a non-empty string";
+constexpr char kSplitFieldIndexError[] =
+    "str_split: field number must be a non-negative integer";
+
+void sqlite_str_split(sqlite3_context* context,
+                      int argc,
+                      sqlite3_value** argv) {
+  PERFETTO_DCHECK(argc == 3);
+  if (sqlite3_value_type(argv[1]) != SQLITE_TEXT) {
+    sqlite3_result_error(context, kDelimiterError, -1);
+    return;
+  }
+  const char* delimiter =
+      reinterpret_cast<const char*>(sqlite3_value_text(argv[1]));
+  const size_t delimiter_len = strlen(delimiter);
+  if (delimiter_len == 0) {
+    sqlite3_result_error(context, kDelimiterError, -1);
+    return;
+  }
+  if (sqlite3_value_type(argv[2]) != SQLITE_INTEGER) {
+    sqlite3_result_error(context, kSplitFieldIndexError, -1);
+    return;
+  }
+  int fld = sqlite3_value_int(argv[2]);
+  if (fld < 0) {
+    sqlite3_result_error(context, kSplitFieldIndexError, -1);
+    return;
+  }
+  if (sqlite3_value_type(argv[0]) != SQLITE_TEXT) {
+    sqlite3_result_null(context);
+    return;
+  }
+  const char* in = reinterpret_cast<const char*>(sqlite3_value_text(argv[0]));
+  const char* next;
+  do {
+    next = strstr(in, delimiter);
+    if (fld == 0) {
+      int size = next != nullptr ? static_cast<int>(next - in)
+                                 : static_cast<int>(strlen(in));
+      sqlite3_result_text(context, in, size, sqlite_utils::kSqliteTransient);
+      return;
+    } else if (next == nullptr) {
+      break;
+    }
+    in = next + delimiter_len;
+    --fld;
+  } while (fld >= 0);
+  sqlite3_result_null(context);
+}
+}  // namespace
+
+void sqlite3_str_split_init(sqlite3* db) {
+  PERFETTO_CHECK(sqlite3_create_function(db, "str_split", 3,
+                                         SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
+                                         &sqlite_str_split, 0, 0) == SQLITE_OK);
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/sqlite3_str_split.h b/src/trace_processor/sqlite3_str_split.h
new file mode 100644
index 0000000..3a16d7d
--- /dev/null
+++ b/src/trace_processor/sqlite3_str_split.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_SQLITE3_STR_SPLIT_H_
+#define SRC_TRACE_PROCESSOR_SQLITE3_STR_SPLIT_H_
+
+struct sqlite3;
+
+namespace perfetto {
+namespace trace_processor {
+
+void sqlite3_str_split_init(sqlite3* db);
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_SQLITE3_STR_SPLIT_H_
diff --git a/src/trace_processor/sqlite3_str_split_unittest.cc b/src/trace_processor/sqlite3_str_split_unittest.cc
new file mode 100644
index 0000000..4896f27
--- /dev/null
+++ b/src/trace_processor/sqlite3_str_split_unittest.cc
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2019 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 "src/trace_processor/sqlite3_str_split.h"
+
+#include <sqlite3.h>
+#include <string>
+#include "perfetto/base/logging.h"
+#include "src/trace_processor/scoped_db.h"
+
+#include "gtest/gtest.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+class Sqlite3StrSplitTest : public ::testing::Test {
+ public:
+  Sqlite3StrSplitTest() {
+    sqlite3* db = nullptr;
+    PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
+    db_.reset(db);
+    sqlite3_str_split_init(db_.get());
+  }
+
+  const char* SplitStmt(const std::string& str,
+                        const std::string& delim,
+                        int field) {
+    const std::string sql = "SELECT STR_SPLIT(\"" + str + "\", \"" + delim +
+                            "\", " + std::to_string(field) + ");";
+    sqlite3_stmt* stmt = nullptr;
+    PERFETTO_CHECK(sqlite3_prepare_v2(*db_, sql.c_str(),
+                                      static_cast<int>(sql.size()), &stmt,
+                                      nullptr) == SQLITE_OK);
+    stmt_.reset(stmt);
+    PERFETTO_CHECK(sqlite3_step(stmt) == SQLITE_ROW);
+    if (sqlite3_column_type(stmt, 0) == SQLITE_NULL) {
+      return nullptr;
+    }
+    return reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
+  }
+
+ protected:
+  ScopedDb db_;
+  ScopedStmt stmt_;
+};
+
+TEST_F(Sqlite3StrSplitTest, SplitNoDelimiter) {
+  ASSERT_STREQ(SplitStmt("abc", ":", 0), "abc");
+  ASSERT_EQ(SplitStmt("abc", ":", 1), nullptr);
+}
+
+TEST_F(Sqlite3StrSplitTest, SplitSingleCharDelim) {
+  ASSERT_STREQ(SplitStmt("a:bc", ":", 0), "a");
+  ASSERT_STREQ(SplitStmt("a:bc", ":", 1), "bc");
+  ASSERT_EQ(SplitStmt("a:bc", ":", 2), nullptr);
+}
+
+TEST_F(Sqlite3StrSplitTest, SplitInputConsecutiveDelim) {
+  ASSERT_STREQ(SplitStmt("a::b::c", ":", 0), "a");
+  ASSERT_STREQ(SplitStmt("a::b::c", ":", 1), "");
+  ASSERT_STREQ(SplitStmt("a::b::c", ":", 2), "b");
+  ASSERT_STREQ(SplitStmt("a::b::c", ":", 3), "");
+  ASSERT_STREQ(SplitStmt("a::b::c", ":", 4), "c");
+  ASSERT_EQ(SplitStmt("a::b::c", ":", 5), nullptr);
+}
+
+TEST_F(Sqlite3StrSplitTest, SplitStringDelim) {
+  ASSERT_STREQ(SplitStmt("abczzdefzzghi", "zz", 0), "abc");
+  ASSERT_STREQ(SplitStmt("abczzdefzzghi", "zz", 1), "def");
+  ASSERT_STREQ(SplitStmt("abczzdefzzghi", "zz", 2), "ghi");
+}
+
+TEST_F(Sqlite3StrSplitTest, SplitEmptyInput) {
+  ASSERT_STREQ(SplitStmt("", "zz", 0), "");
+  ASSERT_EQ(SplitStmt("", "zz", 1), nullptr);
+  ASSERT_EQ(SplitStmt("", "zz", 1000), nullptr);
+}
+
+}  // namespace
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/sqlite_utils.h b/src/trace_processor/sqlite_utils.h
new file mode 100644
index 0000000..7f5d732
--- /dev/null
+++ b/src/trace_processor/sqlite_utils.h
@@ -0,0 +1,457 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_SQLITE_UTILS_H_
+#define SRC_TRACE_PROCESSOR_SQLITE_UTILS_H_
+
+#include <math.h>
+#include <sqlite3.h>
+
+#include <functional>
+#include <limits>
+#include <string>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/base/optional.h"
+#include "src/trace_processor/scoped_db.h"
+#include "src/trace_processor/table.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace sqlite_utils {
+
+const auto kSqliteStatic = reinterpret_cast<sqlite3_destructor_type>(0);
+const auto kSqliteTransient = reinterpret_cast<sqlite3_destructor_type>(-1);
+
+template <typename T>
+using is_numeric =
+    typename std::enable_if<std::is_arithmetic<T>::value, T>::type;
+
+template <typename T>
+using is_float =
+    typename std::enable_if<std::is_floating_point<T>::value, T>::type;
+
+template <typename T>
+using is_int = typename std::enable_if<std::is_integral<T>::value, T>::type;
+
+inline bool IsOpEq(int op) {
+  return op == SQLITE_INDEX_CONSTRAINT_EQ;
+}
+
+inline bool IsOpGe(int op) {
+  return op == SQLITE_INDEX_CONSTRAINT_GE;
+}
+
+inline bool IsOpGt(int op) {
+  return op == SQLITE_INDEX_CONSTRAINT_GT;
+}
+
+inline bool IsOpLe(int op) {
+  return op == SQLITE_INDEX_CONSTRAINT_LE;
+}
+
+inline bool IsOpLt(int op) {
+  return op == SQLITE_INDEX_CONSTRAINT_LT;
+}
+
+inline std::string OpToString(int op) {
+  switch (op) {
+    case SQLITE_INDEX_CONSTRAINT_EQ:
+      return "=";
+    case SQLITE_INDEX_CONSTRAINT_NE:
+      return "!=";
+    case SQLITE_INDEX_CONSTRAINT_GE:
+      return ">=";
+    case SQLITE_INDEX_CONSTRAINT_GT:
+      return ">";
+    case SQLITE_INDEX_CONSTRAINT_LE:
+      return "<=";
+    case SQLITE_INDEX_CONSTRAINT_LT:
+      return "<";
+    default:
+      PERFETTO_FATAL("Operator to string conversion not impemented for %d", op);
+  }
+}
+
+inline bool IsOpIsNull(int op) {
+  return op == SQLITE_INDEX_CONSTRAINT_ISNULL;
+}
+
+inline bool IsOpIsNotNull(int op) {
+  return op == SQLITE_INDEX_CONSTRAINT_ISNOTNULL;
+}
+
+template <typename T>
+T ExtractSqliteValue(sqlite3_value* value);
+
+template <>
+inline uint8_t ExtractSqliteValue(sqlite3_value* value) {
+  auto type = sqlite3_value_type(value);
+  PERFETTO_DCHECK(type == SQLITE_INTEGER);
+  return static_cast<uint8_t>(sqlite3_value_int(value));
+}
+
+template <>
+inline uint32_t ExtractSqliteValue(sqlite3_value* value) {
+  auto type = sqlite3_value_type(value);
+  PERFETTO_DCHECK(type == SQLITE_INTEGER);
+  return static_cast<uint32_t>(sqlite3_value_int64(value));
+}
+
+template <>
+inline int32_t ExtractSqliteValue(sqlite3_value* value) {
+  auto type = sqlite3_value_type(value);
+  PERFETTO_DCHECK(type == SQLITE_INTEGER);
+  return sqlite3_value_int(value);
+}
+
+template <>
+inline int64_t ExtractSqliteValue(sqlite3_value* value) {
+  auto type = sqlite3_value_type(value);
+  PERFETTO_DCHECK(type == SQLITE_INTEGER);
+  return static_cast<int64_t>(sqlite3_value_int64(value));
+}
+
+template <>
+inline double ExtractSqliteValue(sqlite3_value* value) {
+  auto type = sqlite3_value_type(value);
+  PERFETTO_DCHECK(type == SQLITE_FLOAT || type == SQLITE_INTEGER);
+  return sqlite3_value_double(value);
+}
+
+// Do not add a uint64_t version of ExtractSqliteValue. You should not be using
+// uint64_t at all given that SQLite doesn't support it.
+
+template <>
+inline std::string ExtractSqliteValue(sqlite3_value* value) {
+  auto type = sqlite3_value_type(value);
+  PERFETTO_DCHECK(type == SQLITE_TEXT);
+  const auto* extracted =
+      reinterpret_cast<const char*>(sqlite3_value_text(value));
+  return std::string(extracted);
+}
+
+template <typename T>
+class NumericPredicate {
+ public:
+  NumericPredicate(int op, T constant) : op_(op), constant_(constant) {}
+
+  PERFETTO_ALWAYS_INLINE bool operator()(T other) const {
+    switch (op_) {
+      case SQLITE_INDEX_CONSTRAINT_ISNULL:
+        return false;
+      case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
+        return true;
+      case SQLITE_INDEX_CONSTRAINT_EQ:
+      case SQLITE_INDEX_CONSTRAINT_IS:
+        return std::equal_to<T>()(other, constant_);
+      case SQLITE_INDEX_CONSTRAINT_NE:
+      case SQLITE_INDEX_CONSTRAINT_ISNOT:
+        return std::not_equal_to<T>()(other, constant_);
+      case SQLITE_INDEX_CONSTRAINT_GE:
+        return std::greater_equal<T>()(other, constant_);
+      case SQLITE_INDEX_CONSTRAINT_GT:
+        return std::greater<T>()(other, constant_);
+      case SQLITE_INDEX_CONSTRAINT_LE:
+        return std::less_equal<T>()(other, constant_);
+      case SQLITE_INDEX_CONSTRAINT_LT:
+        return std::less<T>()(other, constant_);
+      default:
+        PERFETTO_FATAL("For GCC");
+    }
+  }
+
+ private:
+  int op_;
+  T constant_;
+};
+
+template <typename T, typename sqlite_utils::is_numeric<T>* = nullptr>
+NumericPredicate<T> CreateNumericPredicate(int op, sqlite3_value* value) {
+  T extracted =
+      IsOpIsNull(op) || IsOpIsNotNull(op) ? 0 : ExtractSqliteValue<T>(value);
+  return NumericPredicate<T>(op, extracted);
+}
+
+inline std::function<bool(const char*)> CreateStringPredicate(
+    int op,
+    sqlite3_value* value) {
+  switch (op) {
+    case SQLITE_INDEX_CONSTRAINT_ISNULL:
+      return [](const char* f) { return f == nullptr; };
+    case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
+      return [](const char* f) { return f != nullptr; };
+  }
+
+  const char* val = reinterpret_cast<const char*>(sqlite3_value_text(value));
+
+  // If the value compared against is null, then to stay consistent with SQL
+  // handling, we have to return false for non-null operators.
+  if (val == nullptr) {
+    PERFETTO_CHECK(op != SQLITE_INDEX_CONSTRAINT_IS &&
+                   op != SQLITE_INDEX_CONSTRAINT_ISNOT);
+    return [](const char*) { return false; };
+  }
+
+  switch (op) {
+    case SQLITE_INDEX_CONSTRAINT_EQ:
+    case SQLITE_INDEX_CONSTRAINT_IS:
+      return [val](const char* str) {
+        return str != nullptr && strcmp(str, val) == 0;
+      };
+    case SQLITE_INDEX_CONSTRAINT_NE:
+    case SQLITE_INDEX_CONSTRAINT_ISNOT:
+      return [val](const char* str) {
+        return str != nullptr && strcmp(str, val) != 0;
+      };
+    case SQLITE_INDEX_CONSTRAINT_GE:
+      return [val](const char* str) {
+        return str != nullptr && strcmp(str, val) >= 0;
+      };
+    case SQLITE_INDEX_CONSTRAINT_GT:
+      return [val](const char* str) {
+        return str != nullptr && strcmp(str, val) > 0;
+      };
+    case SQLITE_INDEX_CONSTRAINT_LE:
+      return [val](const char* str) {
+        return str != nullptr && strcmp(str, val) <= 0;
+      };
+    case SQLITE_INDEX_CONSTRAINT_LT:
+      return [val](const char* str) {
+        return str != nullptr && strcmp(str, val) < 0;
+      };
+    case SQLITE_INDEX_CONSTRAINT_LIKE:
+      return [val](const char* str) {
+        return str != nullptr && sqlite3_strlike(val, str, 0) == 0;
+      };
+    case SQLITE_INDEX_CONSTRAINT_GLOB:
+      return [val](const char* str) {
+        return str != nullptr && sqlite3_strglob(val, str) == 0;
+      };
+    default:
+      PERFETTO_FATAL("For GCC");
+  }
+}
+
+// Greater bound for floating point numbers.
+template <typename T, typename sqlite_utils::is_float<T>* = nullptr>
+T FindGtBound(bool is_eq, sqlite3_value* sqlite_val) {
+  constexpr auto kMax = static_cast<long double>(std::numeric_limits<T>::max());
+  auto type = sqlite3_value_type(sqlite_val);
+  if (type != SQLITE_INTEGER && type != SQLITE_FLOAT) {
+    return kMax;
+  }
+
+  // If this is a strict gt bound then just get the next highest float
+  // after value.
+  auto value = ExtractSqliteValue<T>(sqlite_val);
+  return is_eq ? value : nexttoward(value, kMax);
+}
+
+template <typename T, typename sqlite_utils::is_int<T>* = nullptr>
+T FindGtBound(bool is_eq, sqlite3_value* sqlite_val) {
+  auto type = sqlite3_value_type(sqlite_val);
+  if (type == SQLITE_INTEGER) {
+    auto value = ExtractSqliteValue<T>(sqlite_val);
+    return is_eq ? value : value + 1;
+  } else if (type == SQLITE_FLOAT) {
+    auto value = ExtractSqliteValue<double>(sqlite_val);
+    auto above = ceil(value);
+    auto cast = static_cast<T>(above);
+    return value < above ? cast : (is_eq ? cast : cast + 1);
+  } else {
+    return std::numeric_limits<T>::max();
+  }
+}
+
+template <typename T, typename sqlite_utils::is_float<T>* = nullptr>
+T FindLtBound(bool is_eq, sqlite3_value* sqlite_val) {
+  constexpr auto kMin =
+      static_cast<long double>(std::numeric_limits<T>::lowest());
+  auto type = sqlite3_value_type(sqlite_val);
+  if (type != SQLITE_INTEGER && type != SQLITE_FLOAT) {
+    return kMin;
+  }
+
+  // If this is a strict lt bound then just get the next lowest float
+  // before value.
+  auto value = ExtractSqliteValue<T>(sqlite_val);
+  return is_eq ? value : nexttoward(value, kMin);
+}
+
+template <typename T, typename sqlite_utils::is_int<T>* = nullptr>
+T FindLtBound(bool is_eq, sqlite3_value* sqlite_val) {
+  auto type = sqlite3_value_type(sqlite_val);
+  if (type == SQLITE_INTEGER) {
+    auto value = ExtractSqliteValue<T>(sqlite_val);
+    return is_eq ? value : value - 1;
+  } else if (type == SQLITE_FLOAT) {
+    auto value = ExtractSqliteValue<double>(sqlite_val);
+    auto below = floor(value);
+    auto cast = static_cast<T>(below);
+    return value > below ? cast : (is_eq ? cast : cast - 1);
+  } else {
+    return std::numeric_limits<T>::max();
+  }
+}
+
+template <typename T, typename sqlite_utils::is_float<T>* = nullptr>
+T FindEqBound(sqlite3_value* sqlite_val) {
+  auto type = sqlite3_value_type(sqlite_val);
+  if (type != SQLITE_INTEGER && type != SQLITE_FLOAT) {
+    return std::numeric_limits<T>::max();
+  }
+  return ExtractSqliteValue<T>(sqlite_val);
+}
+
+template <typename T, typename sqlite_utils::is_int<T>* = nullptr>
+T FindEqBound(sqlite3_value* sqlite_val) {
+  auto type = sqlite3_value_type(sqlite_val);
+  if (type == SQLITE_INTEGER) {
+    return ExtractSqliteValue<T>(sqlite_val);
+  } else if (type == SQLITE_FLOAT) {
+    auto value = ExtractSqliteValue<double>(sqlite_val);
+    auto below = floor(value);
+    auto cast = static_cast<T>(below);
+    return value > below ? std::numeric_limits<T>::max() : cast;
+  } else {
+    return std::numeric_limits<T>::max();
+  }
+}
+
+template <typename T>
+void ReportSqliteResult(sqlite3_context*, T value);
+
+// Do not add a uint64_t version of ReportSqliteResult. You should not be using
+// uint64_t at all given that SQLite doesn't support it.
+
+template <>
+inline void ReportSqliteResult(sqlite3_context* ctx, int32_t value) {
+  sqlite3_result_int(ctx, value);
+}
+
+template <>
+inline void ReportSqliteResult(sqlite3_context* ctx, int64_t value) {
+  sqlite3_result_int64(ctx, value);
+}
+
+template <>
+inline void ReportSqliteResult(sqlite3_context* ctx, uint8_t value) {
+  sqlite3_result_int(ctx, value);
+}
+
+template <>
+inline void ReportSqliteResult(sqlite3_context* ctx, uint32_t value) {
+  sqlite3_result_int64(ctx, value);
+}
+
+template <>
+inline void ReportSqliteResult(sqlite3_context* ctx, double value) {
+  sqlite3_result_double(ctx, value);
+}
+
+inline std::string SqliteValueAsString(sqlite3_value* value) {
+  switch (sqlite3_value_type(value)) {
+    case SQLITE_INTEGER:
+      return std::to_string(sqlite3_value_int64(value));
+    case SQLITE_FLOAT:
+      return std::to_string(sqlite3_value_double(value));
+    case SQLITE_TEXT: {
+      const char* str =
+          reinterpret_cast<const char*>(sqlite3_value_text(value));
+      return "'" + std::string(str) + "'";
+    }
+    default:
+      PERFETTO_FATAL("Unknown value type %d", sqlite3_value_type(value));
+  }
+}
+
+inline std::vector<Table::Column> GetColumnsForTable(
+    sqlite3* db,
+    const std::string& raw_table_name) {
+  char sql[1024];
+  const char kRawSql[] = "SELECT name, type from pragma_table_info(\"%s\")";
+
+  // Support names which are table valued functions with arguments.
+  std::string table_name = raw_table_name.substr(0, raw_table_name.find('('));
+  int n = snprintf(sql, sizeof(sql), kRawSql, table_name.c_str());
+  PERFETTO_DCHECK(n >= 0 || static_cast<size_t>(n) < sizeof(sql));
+
+  sqlite3_stmt* raw_stmt = nullptr;
+  int err = sqlite3_prepare_v2(db, sql, n, &raw_stmt, nullptr);
+
+  ScopedStmt stmt(raw_stmt);
+  PERFETTO_DCHECK(sqlite3_column_count(*stmt) == 2);
+
+  std::vector<Table::Column> columns;
+  for (;;) {
+    err = sqlite3_step(raw_stmt);
+    if (err == SQLITE_DONE)
+      break;
+    if (err != SQLITE_ROW) {
+      PERFETTO_ELOG("Querying schema of table %s failed",
+                    raw_table_name.c_str());
+      return {};
+    }
+
+    const char* name =
+        reinterpret_cast<const char*>(sqlite3_column_text(*stmt, 0));
+    const char* raw_type =
+        reinterpret_cast<const char*>(sqlite3_column_text(*stmt, 1));
+    if (!name || !raw_type || !*name) {
+      PERFETTO_FATAL("Schema for %s has invalid column values",
+                     raw_table_name.c_str());
+    }
+
+    Table::ColumnType type;
+    if (strcmp(raw_type, "UNSIGNED INT") == 0) {
+      type = Table::ColumnType::kUint;
+    } else if (strcmp(raw_type, "BIG INT") == 0) {
+      type = Table::ColumnType::kLong;
+    } else if (strcmp(raw_type, "INT") == 0) {
+      type = Table::ColumnType::kInt;
+    } else if (strcmp(raw_type, "STRING") == 0) {
+      type = Table::ColumnType::kString;
+    } else if (strcmp(raw_type, "DOUBLE") == 0) {
+      type = Table::ColumnType::kDouble;
+    } else if (!*raw_type) {
+      PERFETTO_DLOG("Unknown column type for %s %s", raw_table_name.c_str(),
+                    name);
+      type = Table::ColumnType::kUnknown;
+    } else {
+      PERFETTO_FATAL("Unknown column type '%s' on table %s", raw_type,
+                     raw_table_name.c_str());
+    }
+    columns.emplace_back(columns.size(), name, type);
+  }
+  return columns;
+}
+
+template <typename T>
+int CompareValuesAsc(const T& f, const T& s) {
+  return f < s ? -1 : (f > s ? 1 : 0);
+}
+
+template <typename T>
+int CompareValuesDesc(const T& f, const T& s) {
+  return -CompareValuesAsc(f, s);
+}
+
+}  // namespace sqlite_utils
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_SQLITE_UTILS_H_
diff --git a/src/trace_processor/stack_profile_frame_table.cc b/src/trace_processor/stack_profile_frame_table.cc
deleted file mode 100644
index 6939873..0000000
--- a/src/trace_processor/stack_profile_frame_table.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/stack_profile_frame_table.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-StackProfileFrameTable::StackProfileFrameTable(sqlite3*,
-                                               const TraceStorage* storage)
-    : storage_(storage) {}
-
-void StackProfileFrameTable::RegisterTable(sqlite3* db,
-                                           const TraceStorage* storage) {
-  SqliteTable::Register<StackProfileFrameTable>(db, storage,
-                                                "stack_profile_frame");
-}
-
-StorageSchema StackProfileFrameTable::CreateStorageSchema() {
-  const auto& frames = storage_->stack_profile_frames();
-  return StorageSchema::Builder()
-      .AddGenericNumericColumn("id", RowAccessor())
-      .AddStringColumn("name", &frames.names(), &storage_->string_pool())
-      .AddNumericColumn("mapping", &frames.mappings())
-      .AddNumericColumn("rel_pc", &frames.rel_pcs())
-      .AddNumericColumn("symbol_set_id", &frames.symbol_set_ids())
-      .Build({"id"});
-}
-
-uint32_t StackProfileFrameTable::RowCount() {
-  return storage_->stack_profile_frames().size();
-}
-
-int StackProfileFrameTable::BestIndex(const QueryConstraints& qc,
-                                      BestIndexInfo* info) {
-  info->sqlite_omit_order_by = true;
-  info->estimated_cost = HasEqConstraint(qc, "id") ? 1 : RowCount();
-  return SQLITE_OK;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/stack_profile_frame_table.h b/src/trace_processor/stack_profile_frame_table.h
deleted file mode 100644
index c4c2508..0000000
--- a/src/trace_processor/stack_profile_frame_table.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_STACK_PROFILE_FRAME_TABLE_H_
-#define SRC_TRACE_PROCESSOR_STACK_PROFILE_FRAME_TABLE_H_
-
-#include "src/trace_processor/storage_table.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class StackProfileFrameTable : public StorageTable {
- public:
-  static void RegisterTable(sqlite3* db, const TraceStorage* storage);
-
-  StackProfileFrameTable(sqlite3*, const TraceStorage*);
-
-  // StorageTable implementation.
-  StorageSchema CreateStorageSchema() override;
-  uint32_t RowCount() override;
-  int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
-
- private:
-  const TraceStorage* const storage_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_STACK_PROFILE_FRAME_TABLE_H_
diff --git a/src/trace_processor/stack_profile_mapping_table.cc b/src/trace_processor/stack_profile_mapping_table.cc
deleted file mode 100644
index 52a9038..0000000
--- a/src/trace_processor/stack_profile_mapping_table.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/stack_profile_mapping_table.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-StackProfileMappingTable::StackProfileMappingTable(sqlite3*,
-                                                   const TraceStorage* storage)
-    : storage_(storage) {}
-
-void StackProfileMappingTable::RegisterTable(sqlite3* db,
-                                             const TraceStorage* storage) {
-  SqliteTable::Register<StackProfileMappingTable>(db, storage,
-                                                  "stack_profile_mapping");
-}
-
-StorageSchema StackProfileMappingTable::CreateStorageSchema() {
-  const auto& mappings = storage_->stack_profile_mappings();
-  return StorageSchema::Builder()
-      .AddGenericNumericColumn("id", RowAccessor())
-      .AddStringColumn("build_id", &mappings.build_ids(),
-                       &storage_->string_pool())
-      .AddNumericColumn("exact_offset", &mappings.exact_offsets())
-      .AddNumericColumn("start_offset", &mappings.start_offsets())
-      .AddNumericColumn("start", &mappings.starts())
-      .AddNumericColumn("end", &mappings.ends())
-      .AddNumericColumn("load_bias", &mappings.load_biases())
-      .AddStringColumn("name", &mappings.names(), &storage_->string_pool())
-      .Build({"id"});
-}
-
-uint32_t StackProfileMappingTable::RowCount() {
-  return storage_->stack_profile_mappings().size();
-}
-
-int StackProfileMappingTable::BestIndex(const QueryConstraints& qc,
-                                        BestIndexInfo* info) {
-  info->sqlite_omit_order_by = true;
-  info->estimated_cost = HasEqConstraint(qc, "id") ? 1 : RowCount();
-  return SQLITE_OK;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/stack_profile_mapping_table.h b/src/trace_processor/stack_profile_mapping_table.h
deleted file mode 100644
index c627a1e..0000000
--- a/src/trace_processor/stack_profile_mapping_table.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_STACK_PROFILE_MAPPING_TABLE_H_
-#define SRC_TRACE_PROCESSOR_STACK_PROFILE_MAPPING_TABLE_H_
-
-#include "src/trace_processor/storage_table.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class StackProfileMappingTable : public StorageTable {
- public:
-  static void RegisterTable(sqlite3* db, const TraceStorage* storage);
-
-  StackProfileMappingTable(sqlite3*, const TraceStorage*);
-
-  // StorageTable implementation.
-  StorageSchema CreateStorageSchema() override;
-  uint32_t RowCount() override;
-  int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
-
- private:
-  const TraceStorage* const storage_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_STACK_PROFILE_MAPPING_TABLE_H_
diff --git a/src/trace_processor/stack_profile_tracker.cc b/src/trace_processor/stack_profile_tracker.cc
deleted file mode 100644
index 25815ea..0000000
--- a/src/trace_processor/stack_profile_tracker.cc
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/stack_profile_tracker.h"
-
-#include "src/trace_processor/trace_processor_context.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_utils.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-StackProfileTracker::InternLookup::~InternLookup() = default;
-
-StackProfileTracker::StackProfileTracker(TraceProcessorContext* context)
-    : context_(context), empty_(kNullStringId) {}
-
-StackProfileTracker::~StackProfileTracker() = default;
-
-StringId StackProfileTracker::GetEmptyStringId() {
-  if (empty_ == kNullStringId) {
-    empty_ = context_->storage->InternString({"", 0});
-  }
-
-  return empty_;
-}
-
-void StackProfileTracker::AddString(SourceStringId id, base::StringView str) {
-  string_map_.emplace(id, str.ToStdString());
-}
-
-base::Optional<int64_t> StackProfileTracker::AddMapping(
-    SourceMappingId id,
-    const SourceMapping& mapping,
-    const InternLookup* intern_lookup) {
-  std::string path;
-  for (SourceStringId str_id : mapping.name_ids) {
-    auto opt_str =
-        FindString(str_id, intern_lookup, InternedStringType::kMappingPath);
-    if (!opt_str)
-      break;
-    path += "/" + *opt_str;
-  }
-
-  auto opt_build_id = FindAndInternString(mapping.build_id, intern_lookup,
-                                          InternedStringType::kBuildId);
-  if (!opt_build_id) {
-    context_->storage->IncrementStats(stats::stackprofile_invalid_string_id);
-    PERFETTO_DFATAL("Invalid string.");
-    return base::nullopt;
-  }
-  const StringId raw_build_id = opt_build_id.value();
-  NullTermStringView raw_build_id_str =
-      context_->storage->GetString(raw_build_id);
-  StringId build_id = GetEmptyStringId();
-  if (raw_build_id_str.size() > 0) {
-    std::string hex_build_id =
-        base::ToHex(raw_build_id_str.c_str(), raw_build_id_str.size());
-    build_id = context_->storage->InternString(base::StringView(hex_build_id));
-  }
-
-  TraceStorage::StackProfileMappings::Row row{
-      build_id,
-      static_cast<int64_t>(mapping.exact_offset),
-      static_cast<int64_t>(mapping.start_offset),
-      static_cast<int64_t>(mapping.start),
-      static_cast<int64_t>(mapping.end),
-      static_cast<int64_t>(mapping.load_bias),
-      context_->storage->InternString(base::StringView(path))};
-
-  TraceStorage::StackProfileMappings* mappings =
-      context_->storage->mutable_stack_profile_mappings();
-  int64_t cur_row = -1;
-  auto it = mapping_idx_.find(row);
-  if (it != mapping_idx_.end()) {
-    cur_row = it->second;
-  } else {
-    std::vector<int64_t> db_mappings =
-        mappings->FindMappingRow(row.name_id, row.build_id);
-    for (const int64_t preexisting_mapping : db_mappings) {
-      PERFETTO_DCHECK(preexisting_mapping >= 0);
-      size_t preexisting_row_id = static_cast<size_t>(preexisting_mapping);
-      TraceStorage::StackProfileMappings::Row preexisting_row{
-          mappings->build_ids()[preexisting_row_id],
-          mappings->exact_offsets()[preexisting_row_id],
-          mappings->start_offsets()[preexisting_row_id],
-          mappings->starts()[preexisting_row_id],
-          mappings->ends()[preexisting_row_id],
-          mappings->load_biases()[preexisting_row_id],
-          mappings->names()[preexisting_row_id]};
-
-      if (row == preexisting_row) {
-        cur_row = preexisting_mapping;
-      }
-    }
-    if (cur_row == -1) {
-      cur_row =
-          context_->storage->mutable_stack_profile_mappings()->Insert(row);
-    }
-    mapping_idx_.emplace(row, cur_row);
-  }
-  mappings_.emplace(id, cur_row);
-  return cur_row;
-}
-
-base::Optional<int64_t> StackProfileTracker::AddFrame(
-    SourceFrameId id,
-    const SourceFrame& frame,
-    const InternLookup* intern_lookup) {
-  auto opt_str_id = FindAndInternString(frame.name_id, intern_lookup,
-                                        InternedStringType::kFunctionName);
-  if (!opt_str_id) {
-    context_->storage->IncrementStats(stats::stackprofile_invalid_string_id);
-    PERFETTO_DFATAL("Invalid string.");
-    return base::nullopt;
-  }
-  const StringId& str_id = opt_str_id.value();
-
-  auto maybe_mapping = FindMapping(frame.mapping_id, intern_lookup);
-  if (!maybe_mapping) {
-    context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
-    PERFETTO_ELOG("Invalid mapping for frame %" PRIu64, id);
-    return base::nullopt;
-  }
-  int64_t mapping_row = *maybe_mapping;
-
-  TraceStorage::StackProfileFrames::Row row{str_id, mapping_row,
-                                            static_cast<int64_t>(frame.rel_pc)};
-
-  TraceStorage::StackProfileFrames* frames =
-      context_->storage->mutable_stack_profile_frames();
-
-  int64_t cur_row = -1;
-  auto it = frame_idx_.find(row);
-  if (it != frame_idx_.end()) {
-    cur_row = it->second;
-  } else {
-    std::vector<int64_t> db_frames =
-        frames->FindFrameRow(static_cast<size_t>(mapping_row), frame.rel_pc);
-    for (const int64_t preexisting_frame : db_frames) {
-      PERFETTO_DCHECK(preexisting_frame >= 0);
-      size_t preexisting_row_id = static_cast<size_t>(preexisting_frame);
-      TraceStorage::StackProfileFrames::Row preexisting_row{
-          frames->names()[preexisting_row_id],
-          frames->mappings()[preexisting_row_id],
-          frames->rel_pcs()[preexisting_row_id]};
-
-      if (row == preexisting_row) {
-        cur_row = preexisting_frame;
-      }
-    }
-    if (cur_row == -1) {
-      cur_row = context_->storage->mutable_stack_profile_frames()->Insert(row);
-    }
-    frame_idx_.emplace(row, cur_row);
-  }
-  frames_.emplace(id, cur_row);
-  return cur_row;
-}
-
-base::Optional<int64_t> StackProfileTracker::AddCallstack(
-    SourceCallstackId id,
-    const SourceCallstack& frame_ids,
-    const InternLookup* intern_lookup) {
-  // TODO(fmayer): This should be NULL.
-  int64_t parent_id = -1;
-  for (size_t depth = 0; depth < frame_ids.size(); ++depth) {
-    std::vector<SourceFrameId> frame_subset = frame_ids;
-    frame_subset.resize(depth + 1);
-    auto self_it = callstacks_from_frames_.find(frame_subset);
-    if (self_it != callstacks_from_frames_.end()) {
-      parent_id = self_it->second;
-      continue;
-    }
-
-    SourceFrameId frame_id = frame_ids[depth];
-    auto maybe_frame_row = FindFrame(frame_id, intern_lookup);
-    if (!maybe_frame_row) {
-      context_->storage->IncrementStats(stats::stackprofile_invalid_frame_id);
-      PERFETTO_ELOG("Unknown frame in callstack; ignoring.");
-      return base::nullopt;
-    }
-    int64_t frame_row = *maybe_frame_row;
-
-    tables::StackProfileCallsiteTable::Row row{static_cast<int64_t>(depth),
-                                               parent_id, frame_row};
-
-    int64_t self_id;
-    auto callsite_it = callsite_idx_.find(row);
-    if (callsite_it != callsite_idx_.end()) {
-      self_id = callsite_it->second;
-    } else {
-      self_id =
-          context_->storage->mutable_stack_profile_callsite_table()->Insert(
-              row);
-      callsite_idx_.emplace(row, self_id);
-    }
-    parent_id = self_id;
-  }
-  callstacks_.emplace(id, parent_id);
-  return parent_id;
-}
-
-int64_t StackProfileTracker::GetDatabaseFrameIdForTesting(
-    SourceFrameId frame_id) {
-  auto it = frames_.find(frame_id);
-  if (it == frames_.end()) {
-    PERFETTO_DFATAL("Invalid frame.");
-    return -1;
-  }
-  return it->second;
-}
-
-base::Optional<StringId> StackProfileTracker::FindAndInternString(
-    SourceStringId id,
-    const InternLookup* intern_lookup,
-    StackProfileTracker::InternedStringType type) {
-  if (id == 0)
-    return GetEmptyStringId();
-
-  auto opt_str = FindString(id, intern_lookup, type);
-  if (!opt_str)
-    return GetEmptyStringId();
-
-  return context_->storage->InternString(base::StringView(*opt_str));
-}
-
-base::Optional<std::string> StackProfileTracker::FindString(
-    SourceStringId id,
-    const InternLookup* intern_lookup,
-    StackProfileTracker::InternedStringType type) {
-  if (id == 0)
-    return "";
-
-  auto it = string_map_.find(id);
-  if (it == string_map_.end()) {
-    if (intern_lookup) {
-      auto str = intern_lookup->GetString(id, type);
-      if (!str) {
-        context_->storage->IncrementStats(
-            stats::stackprofile_invalid_string_id);
-        PERFETTO_DFATAL("Invalid string.");
-        return base::nullopt;
-      }
-      return str->ToStdString();
-    }
-    return base::nullopt;
-  }
-
-  return it->second;
-}
-
-base::Optional<int64_t> StackProfileTracker::FindMapping(
-    SourceMappingId mapping_id,
-    const InternLookup* intern_lookup) {
-  base::Optional<int64_t> res;
-  auto it = mappings_.find(mapping_id);
-  if (it == mappings_.end()) {
-    if (intern_lookup) {
-      auto interned_mapping = intern_lookup->GetMapping(mapping_id);
-      if (interned_mapping) {
-        res = AddMapping(mapping_id, *interned_mapping, intern_lookup);
-        return res;
-      }
-    }
-    context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
-    PERFETTO_ELOG("Unknown mapping %" PRIu64 " : %zu", mapping_id,
-                  mappings_.size());
-    return res;
-  }
-  res = it->second;
-  return res;
-}
-
-base::Optional<int64_t> StackProfileTracker::FindFrame(
-    SourceFrameId frame_id,
-    const InternLookup* intern_lookup) {
-  base::Optional<int64_t> res;
-  auto it = frames_.find(frame_id);
-  if (it == frames_.end()) {
-    if (intern_lookup) {
-      auto interned_frame = intern_lookup->GetFrame(frame_id);
-      if (interned_frame) {
-        res = AddFrame(frame_id, *interned_frame, intern_lookup);
-        return res;
-      }
-    }
-    context_->storage->IncrementStats(stats::stackprofile_invalid_frame_id);
-    PERFETTO_DFATAL("Unknown frame %" PRIu64 " : %zu", frame_id,
-                    frames_.size());
-    return res;
-  }
-  res = it->second;
-  return res;
-}
-
-base::Optional<int64_t> StackProfileTracker::FindCallstack(
-    SourceCallstackId callstack_id,
-    const InternLookup* intern_lookup) {
-  base::Optional<int64_t> res;
-  auto it = callstacks_.find(callstack_id);
-  if (it == callstacks_.end()) {
-    auto interned_callstack = intern_lookup->GetCallstack(callstack_id);
-    if (interned_callstack) {
-      res = AddCallstack(callstack_id, *interned_callstack, intern_lookup);
-      return res;
-    }
-    context_->storage->IncrementStats(stats::stackprofile_invalid_callstack_id);
-    PERFETTO_DFATAL("Unknown callstack %" PRIu64 " : %zu", callstack_id,
-                    callstacks_.size());
-    return res;
-  }
-  res = it->second;
-  return res;
-}
-
-void StackProfileTracker::ClearIndices() {
-  string_map_.clear();
-  mappings_.clear();
-  callstacks_from_frames_.clear();
-  callstacks_.clear();
-  frames_.clear();
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/stack_profile_tracker.h b/src/trace_processor/stack_profile_tracker.h
deleted file mode 100644
index 9496929..0000000
--- a/src/trace_processor/stack_profile_tracker.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_STACK_PROFILE_TRACKER_H_
-#define SRC_TRACE_PROCESSOR_STACK_PROFILE_TRACKER_H_
-
-#include <deque>
-
-#include "perfetto/ext/base/optional.h"
-
-#include "protos/perfetto/trace/profiling/profile_common.pbzero.h"
-#include "protos/perfetto/trace/profiling/profile_packet.pbzero.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace std {
-
-template <>
-struct hash<std::pair<uint32_t, int64_t>> {
-  using argument_type = std::pair<uint32_t, int64_t>;
-  using result_type = size_t;
-
-  result_type operator()(const argument_type& p) const {
-    return std::hash<uint32_t>{}(p.first) ^ std::hash<int64_t>{}(p.second);
-  }
-};
-
-template <>
-struct hash<std::vector<uint64_t>> {
-  using argument_type = std::vector<uint64_t>;
-  using result_type = size_t;
-
-  result_type operator()(const argument_type& p) const {
-    size_t h = 0u;
-    for (auto v : p)
-      h = h ^ std::hash<uint64_t>{}(v);
-    return h;
-  }
-};
-
-}  // namespace std
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-class StackProfileTracker {
- public:
-  using SourceStringId = uint64_t;
-
-  enum class InternedStringType {
-    kMappingPath,
-    kBuildId,
-    kFunctionName,
-  };
-
-  struct SourceMapping {
-    SourceStringId build_id = 0;
-    uint64_t exact_offset = 0;
-    uint64_t start_offset = 0;
-    uint64_t start = 0;
-    uint64_t end = 0;
-    uint64_t load_bias = 0;
-    std::vector<SourceStringId> name_ids;
-  };
-  using SourceMappingId = uint64_t;
-
-  struct SourceFrame {
-    SourceStringId name_id = 0;
-    SourceMappingId mapping_id = 0;
-    uint64_t rel_pc = 0;
-  };
-  using SourceFrameId = uint64_t;
-
-  using SourceCallstack = std::vector<SourceFrameId>;
-  using SourceCallstackId = uint64_t;
-
-  struct SourceAllocation {
-    uint64_t pid = 0;
-    // This is int64_t, because we get this from the TraceSorter which also
-    // converts this for us.
-    int64_t timestamp = 0;
-    SourceCallstackId callstack_id = 0;
-    uint64_t self_allocated = 0;
-    uint64_t self_freed = 0;
-    uint64_t alloc_count = 0;
-    uint64_t free_count = 0;
-  };
-
-  class InternLookup {
-   public:
-    virtual ~InternLookup();
-
-    virtual base::Optional<base::StringView> GetString(
-        SourceStringId,
-        InternedStringType) const = 0;
-    virtual base::Optional<SourceMapping> GetMapping(SourceMappingId) const = 0;
-    virtual base::Optional<SourceFrame> GetFrame(SourceFrameId) const = 0;
-    virtual base::Optional<SourceCallstack> GetCallstack(
-        SourceCallstackId) const = 0;
-  };
-
-  explicit StackProfileTracker(TraceProcessorContext* context);
-  ~StackProfileTracker();
-
-  void AddString(SourceStringId, base::StringView);
-  base::Optional<int64_t> AddMapping(
-      SourceMappingId,
-      const SourceMapping&,
-      const InternLookup* intern_lookup = nullptr);
-  base::Optional<int64_t> AddFrame(SourceFrameId,
-                                   const SourceFrame&,
-                                   const InternLookup* intern_lookup = nullptr);
-  base::Optional<int64_t> AddCallstack(
-      SourceCallstackId,
-      const SourceCallstack&,
-      const InternLookup* intern_lookup = nullptr);
-
-  int64_t GetDatabaseFrameIdForTesting(SourceFrameId);
-
-  // Gets the row number of string / mapping / frame / callstack previously
-  // added through AddString / AddMapping/ AddFrame / AddCallstack.
-  //
-  // If it is not found, look up the string / mapping / frame / callstack in
-  // the global InternedData state, and if found, add to the database, if not
-  // already added before.
-  //
-  // This is to support both ProfilePackets that contain the interned data
-  // (for Android Q) and where the interned data is kept globally in
-  // InternedData (for versions newer than Q).
-  base::Optional<StringId> FindAndInternString(
-      SourceStringId,
-      const InternLookup* intern_lookup,
-      InternedStringType type);
-  base::Optional<std::string> FindString(SourceStringId,
-                                         const InternLookup* intern_lookup,
-                                         InternedStringType type);
-  base::Optional<int64_t> FindMapping(SourceMappingId,
-                                      const InternLookup* intern_lookup);
-  base::Optional<int64_t> FindFrame(SourceFrameId,
-                                    const InternLookup* intern_lookup);
-  base::Optional<int64_t> FindCallstack(SourceCallstackId,
-                                        const InternLookup* intern_lookup);
-
-  // Clear indices when they're no longer needed.
-  void ClearIndices();
-
- private:
-  StringId GetEmptyStringId();
-
-  std::unordered_map<SourceStringId, std::string> string_map_;
-  std::unordered_map<SourceMappingId, int64_t> mappings_;
-  std::unordered_map<SourceFrameId, int64_t> frames_;
-  std::unordered_map<SourceCallstack, int64_t> callstacks_from_frames_;
-  std::unordered_map<SourceCallstackId, int64_t> callstacks_;
-
-  // TODO(oysteine): Share these indices between the StackProfileTrackers,
-  // since they're not sequence-specific.
-  std::unordered_map<TraceStorage::StackProfileMappings::Row, int64_t>
-      mapping_idx_;
-  std::unordered_map<TraceStorage::StackProfileFrames::Row, int64_t> frame_idx_;
-  std::unordered_map<tables::StackProfileCallsiteTable::Row, int64_t>
-      callsite_idx_;
-
-  TraceProcessorContext* const context_;
-  StringId empty_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_STACK_PROFILE_TRACKER_H_
diff --git a/src/trace_processor/stats.h b/src/trace_processor/stats.h
index 583dfa2..a23f796 100644
--- a/src/trace_processor/stats.h
+++ b/src/trace_processor/stats.h
@@ -25,106 +25,82 @@
 
 // Compile time list of parsing and processing stats.
 // clang-format off
-#define PERFETTO_TP_STATS(F)                                                     \
-  F(android_log_num_failed,                   kSingle,  kError,    kTrace),    \
-  F(android_log_num_skipped,                  kSingle,  kError,    kTrace),    \
-  F(android_log_num_total,                    kSingle,  kInfo,     kTrace),    \
-  F(atrace_tgid_mismatch,                     kSingle,  kError,    kTrace),    \
-  F(counter_events_out_of_order,              kSingle,  kError,    kAnalysis), \
-  F(ftrace_bundle_tokenizer_errors,           kSingle,  kError,    kAnalysis), \
-  F(ftrace_cpu_bytes_read_begin,              kIndexed, kInfo,     kTrace),    \
-  F(ftrace_cpu_bytes_read_end,                kIndexed, kInfo,     kTrace),    \
-  F(ftrace_cpu_commit_overrun_begin,          kIndexed, kError,    kTrace),    \
-  F(ftrace_cpu_commit_overrun_end,            kIndexed, kError,    kTrace),    \
-  F(ftrace_cpu_dropped_events_begin,          kIndexed, kError,    kTrace),    \
-  F(ftrace_cpu_dropped_events_end,            kIndexed, kError,    kTrace),    \
-  F(ftrace_cpu_entries_begin,                 kIndexed, kInfo,     kTrace),    \
-  F(ftrace_cpu_entries_end,                   kIndexed, kInfo,     kTrace),    \
-  F(ftrace_cpu_now_ts_begin,                  kIndexed, kInfo,     kTrace),    \
-  F(ftrace_cpu_now_ts_end,                    kIndexed, kInfo,     kTrace),    \
-  F(ftrace_cpu_oldest_event_ts_begin,         kIndexed, kInfo,     kTrace),    \
-  F(ftrace_cpu_oldest_event_ts_end,           kIndexed, kInfo,     kTrace),    \
-  F(ftrace_cpu_overrun_begin,                 kIndexed, kInfo,     kTrace),    \
-  F(ftrace_cpu_overrun_end,                   kIndexed, kDataLoss, kTrace),    \
-  F(ftrace_cpu_read_events_begin,             kIndexed, kInfo,     kTrace),    \
-  F(ftrace_cpu_read_events_end,               kIndexed, kInfo,     kTrace),    \
-  F(fuchsia_non_numeric_counters,             kSingle,  kError,    kAnalysis), \
-  F(fuchsia_timestamp_overflow,               kSingle,  kError,    kAnalysis), \
-  F(fuchsia_invalid_event,                    kSingle,  kError,    kAnalysis), \
-  F(gpu_counters_invalid_spec,                kSingle,  kError,    kAnalysis), \
-  F(gpu_counters_missing_spec,                kSingle,  kError,    kAnalysis), \
-  F(graphics_frame_event_parser_errors,       kSingle,  kInfo,     kAnalysis), \
-  F(guess_trace_type_duration_ns,             kSingle,  kInfo,     kAnalysis), \
-  F(interned_data_tokenizer_errors,           kSingle,  kInfo,     kAnalysis), \
-  F(invalid_clock_snapshots,                  kSingle,  kError,    kAnalysis), \
-  F(invalid_cpu_times,                        kSingle,  kError,    kAnalysis), \
-  F(meminfo_unknown_keys,                     kSingle,  kError,    kAnalysis), \
-  F(mismatched_sched_switch_tids,             kSingle,  kError,    kAnalysis), \
-  F(mm_unknown_type,                          kSingle,  kError,    kAnalysis), \
-  F(parse_trace_duration_ns,                  kSingle,  kInfo,     kAnalysis), \
-  F(power_rail_unknown_index,                 kSingle,  kError,    kTrace),    \
-  F(proc_stat_unknown_counters,               kSingle,  kError,    kAnalysis), \
-  F(rss_stat_unknown_keys,                    kSingle,  kError,    kAnalysis), \
-  F(rss_stat_negative_size,                   kSingle,  kInfo,     kAnalysis), \
-  F(sched_switch_out_of_order,                kSingle,  kError,    kAnalysis), \
-  F(slice_out_of_order,                       kSingle,  kError,    kAnalysis), \
-  F(stackprofile_invalid_string_id,           kSingle,  kError,    kTrace),    \
-  F(stackprofile_invalid_mapping_id,          kSingle,  kError,    kTrace),    \
-  F(stackprofile_invalid_frame_id,            kSingle,  kError,    kTrace),    \
-  F(stackprofile_invalid_callstack_id,        kSingle,  kError,    kTrace),    \
-  F(stackprofile_parser_error,                kSingle,  kError,    kTrace),    \
-  F(systrace_parse_failure,                   kSingle,  kError,    kAnalysis), \
-  F(task_state_invalid,                       kSingle,  kError,    kAnalysis), \
-  F(traced_buf_buffer_size,                   kIndexed, kInfo,     kTrace),    \
-  F(traced_buf_bytes_overwritten,             kIndexed, kDataLoss, kTrace),    \
-  F(traced_buf_bytes_read,                    kIndexed, kInfo,     kTrace),    \
-  F(traced_buf_bytes_written,                 kIndexed, kInfo,     kTrace),    \
-  F(traced_buf_chunks_discarded,              kIndexed, kInfo,     kTrace),    \
-  F(traced_buf_chunks_overwritten,            kIndexed, kDataLoss, kTrace),    \
-  F(traced_buf_chunks_read,                   kIndexed, kInfo,     kTrace),    \
-  F(traced_buf_chunks_rewritten,              kIndexed, kInfo,     kTrace),    \
-  F(traced_buf_chunks_written,                kIndexed, kInfo,     kTrace),    \
-  F(traced_buf_chunks_committed_out_of_order, kIndexed, kInfo,     kTrace),    \
-  F(traced_buf_padding_bytes_cleared,         kIndexed, kInfo,     kTrace),    \
-  F(traced_buf_padding_bytes_written,         kIndexed, kInfo,     kTrace),    \
-  F(traced_buf_patches_failed,                kIndexed, kInfo,     kTrace),    \
-  F(traced_buf_patches_succeeded,             kIndexed, kInfo,     kTrace),    \
-  F(traced_buf_readaheads_failed,             kIndexed, kInfo,     kTrace),    \
-  F(traced_buf_readaheads_succeeded,          kIndexed, kInfo,     kTrace),    \
-  F(traced_buf_trace_writer_packet_loss,      kIndexed, kInfo,     kTrace),    \
-  F(traced_buf_write_wrap_count,              kIndexed, kInfo,     kTrace),    \
-  F(traced_chunks_discarded,                  kSingle,  kInfo,     kTrace),    \
-  F(traced_data_sources_registered,           kSingle,  kInfo,     kTrace),    \
-  F(traced_data_sources_seen,                 kSingle,  kInfo,     kTrace),    \
-  F(traced_patches_discarded,                 kSingle,  kInfo,     kTrace),    \
-  F(traced_producers_connected,               kSingle,  kInfo,     kTrace),    \
-  F(traced_producers_seen,                    kSingle,  kInfo,     kTrace),    \
-  F(traced_total_buffers,                     kSingle,  kInfo,     kTrace),    \
-  F(traced_tracing_sessions,                  kSingle,  kInfo,     kTrace),    \
-  F(track_event_parser_errors,                kSingle,  kInfo,     kAnalysis), \
-  F(track_event_tokenizer_errors,             kSingle,  kInfo,     kAnalysis), \
-  F(tokenizer_skipped_packets,                kSingle,  kInfo,     kAnalysis), \
-  F(vmstat_unknown_keys,                      kSingle,  kError,    kAnalysis), \
-  F(vulkan_allocations_invalid_string_id,     kSingle,  kError,    kTrace),    \
-  F(clock_sync_failure,                       kSingle,  kError,    kAnalysis), \
-  F(process_tracker_errors,                   kSingle,  kError,    kAnalysis), \
-  F(json_tokenizer_failure,                   kSingle,  kError,    kTrace),    \
-  F(heap_graph_invalid_string_id,             kIndexed, kError,    kTrace),    \
-  F(heap_graph_non_finalized_graph,           kSingle,  kError,    kTrace),    \
-  F(heap_graph_malformed_packet,              kIndexed, kError,    kTrace),    \
-  F(heap_graph_missing_packet,                kIndexed, kDataLoss, kTrace),    \
-  F(heapprofd_buffer_corrupted,               kIndexed, kError,    kTrace),    \
-  F(heapprofd_buffer_overran,                 kIndexed, kDataLoss, kTrace),    \
-  F(heapprofd_missing_packet,                 kSingle,  kError,    kTrace),    \
-  F(heapprofd_rejected_concurrent,            kIndexed, kError,    kTrace),    \
-  F(metatrace_overruns,                       kSingle,  kError,    kTrace),    \
-  F(packages_list_has_parse_errors,           kSingle,  kError,    kTrace),    \
-  F(packages_list_has_read_errors,            kSingle,  kError,    kTrace),    \
-  F(compact_sched_has_parse_errors,           kSingle,  kError,    kTrace),    \
-  F(misplaced_end_event,                      kSingle,  kDataLoss, kAnalysis), \
-  F(sched_waking_out_of_order,                kSingle,  kError,    kAnalysis), \
-  F(compact_sched_switch_skipped,             kSingle,  kInfo,     kAnalysis), \
-  F(compact_sched_waking_skipped,             kSingle,  kInfo,     kAnalysis)
+#define PERFETTO_TP_STATS(F)                                                  \
+  F(android_log_num_failed,                     kSingle,  kError, kTrace),    \
+  F(android_log_num_skipped,                    kSingle,  kError, kTrace),    \
+  F(android_log_num_total,                      kSingle,  kInfo,  kTrace),    \
+  F(atrace_tgid_mismatch,                       kSingle,  kError, kTrace),    \
+  F(clock_snapshot_not_monotonic,               kSingle,  kError, kTrace),    \
+  F(counter_events_out_of_order,                kSingle,  kError, kAnalysis), \
+  F(ftrace_bundle_tokenizer_errors,             kSingle,  kError, kAnalysis), \
+  F(ftrace_cpu_bytes_read_begin,                kIndexed, kInfo,  kTrace),    \
+  F(ftrace_cpu_bytes_read_end,                  kIndexed, kInfo,  kTrace),    \
+  F(ftrace_cpu_commit_overrun_begin,            kIndexed, kError, kTrace),    \
+  F(ftrace_cpu_commit_overrun_end,              kIndexed, kError, kTrace),    \
+  F(ftrace_cpu_dropped_events_begin,            kIndexed, kError, kTrace),    \
+  F(ftrace_cpu_dropped_events_end,              kIndexed, kError, kTrace),    \
+  F(ftrace_cpu_entries_begin,                   kIndexed, kInfo,  kTrace),    \
+  F(ftrace_cpu_entries_end,                     kIndexed, kInfo,  kTrace),    \
+  F(ftrace_cpu_now_ts_begin,                    kIndexed, kInfo,  kTrace),    \
+  F(ftrace_cpu_now_ts_end,                      kIndexed, kInfo,  kTrace),    \
+  F(ftrace_cpu_oldest_event_ts_begin,           kIndexed, kInfo,  kTrace),    \
+  F(ftrace_cpu_oldest_event_ts_end,             kIndexed, kInfo,  kTrace),    \
+  F(ftrace_cpu_overrun_begin,                   kIndexed, kError, kTrace),    \
+  F(ftrace_cpu_overrun_end,                     kIndexed, kError, kTrace),    \
+  F(ftrace_cpu_read_events_begin,               kIndexed, kInfo,  kTrace),    \
+  F(ftrace_cpu_read_events_end,                 kIndexed, kInfo,  kTrace),    \
+  F(guess_trace_type_duration_ns,               kSingle,  kInfo,  kAnalysis), \
+  F(interned_data_tokenizer_errors,             kSingle,  kInfo,  kAnalysis), \
+  F(invalid_clock_snapshots,                    kSingle,  kError, kAnalysis), \
+  F(invalid_cpu_times,                          kSingle,  kError, kAnalysis), \
+  F(meminfo_unknown_keys,                       kSingle,  kError, kAnalysis), \
+  F(mismatched_sched_switch_tids,               kSingle,  kError, kAnalysis), \
+  F(mm_unknown_type,                            kSingle,  kError, kAnalysis), \
+  F(parse_trace_duration_ns,                    kSingle,  kInfo,  kAnalysis), \
+  F(power_rail_unknown_index,                   kSingle,  kError, kTrace), \
+  F(proc_stat_unknown_counters,                 kSingle,  kError, kAnalysis), \
+  F(rss_stat_unknown_keys,                      kSingle,  kError, kAnalysis), \
+  F(rss_stat_negative_size,                     kSingle,  kInfo,  kAnalysis), \
+  F(sched_switch_out_of_order,                  kSingle,  kError, kAnalysis), \
+  F(systrace_parse_failure,                     kSingle,  kError, kAnalysis), \
+  F(traced_buf_buffer_size,                     kIndexed, kInfo,  kTrace),    \
+  F(traced_buf_bytes_overwritten,               kIndexed, kInfo,  kTrace),    \
+  F(traced_buf_bytes_read,                      kIndexed, kInfo,  kTrace),    \
+  F(traced_buf_bytes_written,                   kIndexed, kInfo,  kTrace),    \
+  F(traced_buf_chunks_discarded,                kIndexed, kInfo,  kTrace),    \
+  F(traced_buf_chunks_overwritten,              kIndexed, kInfo,  kTrace),    \
+  F(traced_buf_chunks_read,                     kIndexed, kInfo,  kTrace),    \
+  F(traced_buf_chunks_rewritten,                kIndexed, kInfo,  kTrace),    \
+  F(traced_buf_chunks_written,                  kIndexed, kInfo,  kTrace),    \
+  F(traced_buf_chunks_committed_out_of_order,   kIndexed, kInfo,  kTrace),    \
+  F(traced_buf_padding_bytes_cleared,           kIndexed, kInfo,  kTrace),    \
+  F(traced_buf_padding_bytes_written,           kIndexed, kInfo,  kTrace),    \
+  F(traced_buf_patches_failed,                  kIndexed, kInfo,  kTrace),    \
+  F(traced_buf_patches_succeeded,               kIndexed, kInfo,  kTrace),    \
+  F(traced_buf_readaheads_failed,               kIndexed, kInfo,  kTrace),    \
+  F(traced_buf_readaheads_succeeded,            kIndexed, kInfo,  kTrace),    \
+  F(traced_buf_write_wrap_count,                kIndexed, kInfo,  kTrace),    \
+  F(traced_chunks_discarded,                    kSingle,  kInfo,  kTrace),    \
+  F(traced_data_sources_registered,             kSingle,  kInfo,  kTrace),    \
+  F(traced_data_sources_seen,                   kSingle,  kInfo,  kTrace),    \
+  F(traced_patches_discarded,                   kSingle,  kInfo,  kTrace),    \
+  F(traced_producers_connected,                 kSingle,  kInfo,  kTrace),    \
+  F(traced_producers_seen,                      kSingle,  kInfo,  kTrace),    \
+  F(traced_total_buffers,                       kSingle,  kInfo,  kTrace),    \
+  F(traced_tracing_sessions,                    kSingle,  kInfo,  kTrace),    \
+  F(track_event_tokenizer_errors,               kSingle,  kInfo,  kAnalysis), \
+  F(track_event_tokenizer_skipped_packets,      kSingle,  kInfo,  kAnalysis), \
+  F(vmstat_unknown_keys,                        kSingle,  kError, kAnalysis), \
+  F(clock_sync_failure,                         kSingle,  kError, kAnalysis), \
+  F(process_tracker_errors,                     kSingle,  kError, kAnalysis), \
+  F(json_tokenizer_failure,                     kSingle,  kError, kTrace),    \
+  F(heapprofd_buffer_corrupted,                 kIndexed, kError, kTrace),    \
+  F(heapprofd_buffer_overran,                   kIndexed, kError, kTrace),    \
+  F(heapprofd_rejected_concurrent,              kIndexed, kError, kTrace),    \
+  F(heapprofd_invalid_string_id,                kSingle,  kError, kTrace),    \
+  F(heapprofd_invalid_mapping_id,               kSingle,  kError, kTrace),    \
+  F(heapprofd_invalid_frame_id,                 kSingle,  kError, kTrace),    \
+  F(heapprofd_invalid_callstack_id,             kSingle,  kError, kTrace)
 // clang-format on
 
 enum Type {
@@ -133,9 +109,8 @@
 };
 
 enum Severity {
-  kInfo,      // Diagnostic counters
-  kDataLoss,  // Correct operation that still resulted in data loss
-  kError      // If any kError counter is > 0 the UI will raise an error
+  kInfo,  // Diagnostic counters
+  kError  // If any kError counter is > 0 the UI will raise an error.
 };
 
 enum Source {
diff --git a/src/trace_processor/stats_table.cc b/src/trace_processor/stats_table.cc
index 8881897..f43c36a 100644
--- a/src/trace_processor/stats_table.cc
+++ b/src/trace_processor/stats_table.cc
@@ -16,7 +16,7 @@
 
 #include "src/trace_processor/stats_table.h"
 
-#include "src/trace_processor/sqlite/sqlite_utils.h"
+#include "src/trace_processor/sqlite_utils.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -25,27 +25,24 @@
     : storage_(storage) {}
 
 void StatsTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
-  SqliteTable::Register<StatsTable>(db, storage, "stats");
+  Table::Register<StatsTable>(db, storage, "stats");
 }
 
-util::Status StatsTable::Init(int, const char* const*, Schema* schema) {
-  *schema = Schema(
+base::Optional<Table::Schema> StatsTable::Init(int, const char* const*) {
+  return Schema(
       {
-          SqliteTable::Column(Column::kName, "name", SqlValue::Type::kString),
+          Table::Column(Column::kName, "name", ColumnType::kString),
           // Calling a column "index" causes sqlite to silently fail, hence idx.
-          SqliteTable::Column(Column::kIndex, "idx", SqlValue::Type::kLong),
-          SqliteTable::Column(Column::kSeverity, "severity",
-                              SqlValue::Type::kString),
-          SqliteTable::Column(Column::kSource, "source",
-                              SqlValue::Type::kString),
-          SqliteTable::Column(Column::kValue, "value", SqlValue::Type::kLong),
+          Table::Column(Column::kIndex, "idx", ColumnType::kUint),
+          Table::Column(Column::kSeverity, "severity", ColumnType::kString),
+          Table::Column(Column::kSource, "source", ColumnType::kString),
+          Table::Column(Column::kValue, "value", ColumnType::kLong),
       },
       {Column::kName});
-  return util::OkStatus();
 }
 
-std::unique_ptr<SqliteTable::Cursor> StatsTable::CreateCursor() {
-  return std::unique_ptr<SqliteTable::Cursor>(new Cursor(this));
+std::unique_ptr<Table::Cursor> StatsTable::CreateCursor() {
+  return std::unique_ptr<Table::Cursor>(new Cursor(this));
 }
 
 int StatsTable::BestIndex(const QueryConstraints&, BestIndexInfo*) {
@@ -53,7 +50,7 @@
 }
 
 StatsTable::Cursor::Cursor(StatsTable* table)
-    : SqliteTable::Cursor(table), table_(table), storage_(table->storage_) {}
+    : Table::Cursor(table), table_(table), storage_(table->storage_) {}
 
 int StatsTable::Cursor::Filter(const QueryConstraints&, sqlite3_value**) {
   *this = Cursor(table_);
@@ -78,9 +75,6 @@
         case stats::kInfo:
           sqlite3_result_text(ctx, "info", -1, kSqliteStatic);
           break;
-        case stats::kDataLoss:
-          sqlite3_result_text(ctx, "data_loss", -1, kSqliteStatic);
-          break;
         case stats::kError:
           sqlite3_result_text(ctx, "error", -1, kSqliteStatic);
           break;
diff --git a/src/trace_processor/stats_table.h b/src/trace_processor/stats_table.h
index 3a1a591..9ae2165 100644
--- a/src/trace_processor/stats_table.h
+++ b/src/trace_processor/stats_table.h
@@ -20,8 +20,8 @@
 #include <limits>
 #include <memory>
 
-#include "src/trace_processor/sqlite/sqlite_table.h"
 #include "src/trace_processor/stats.h"
+#include "src/trace_processor/table.h"
 #include "src/trace_processor/trace_storage.h"
 
 namespace perfetto {
@@ -30,14 +30,14 @@
 // The stats table contains diagnostic info and errors that are either:
 // - Collected at trace time (e.g., ftrace buffer overruns).
 // - Generated at parsing time (e.g., clock events out-of-order).
-class StatsTable : public SqliteTable {
+class StatsTable : public Table {
  public:
   enum Column { kName = 0, kIndex, kSeverity, kSource, kValue };
-  class Cursor : public SqliteTable::Cursor {
+  class Cursor : public Table::Cursor {
    public:
     Cursor(StatsTable*);
 
-    // Implementation of SqliteTable::Cursor.
+    // Implementation of Table::Cursor.
     int Filter(const QueryConstraints&, sqlite3_value**) override;
     int Next() override;
     int Eof() override;
@@ -61,8 +61,8 @@
   StatsTable(sqlite3*, const TraceStorage*);
 
   // Table implementation.
-  util::Status Init(int, const char* const*, SqliteTable::Schema*) override;
-  std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
+  base::Optional<Table::Schema> Init(int, const char* const*) override;
+  std::unique_ptr<Table::Cursor> CreateCursor() override;
   int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
 
  private:
diff --git a/src/trace_processor/storage_columns.h b/src/trace_processor/storage_columns.h
index 83e855b..6dca96a 100644
--- a/src/trace_processor/storage_columns.h
+++ b/src/trace_processor/storage_columns.h
@@ -22,7 +22,7 @@
 #include <vector>
 
 #include "src/trace_processor/filtered_row_index.h"
-#include "src/trace_processor/sqlite/sqlite_utils.h"
+#include "src/trace_processor/sqlite_utils.h"
 #include "src/trace_processor/trace_storage.h"
 
 namespace perfetto {
@@ -55,7 +55,7 @@
   virtual Comparator Sort(const QueryConstraints::OrderBy& ob) const = 0;
 
   // Returns the type of this column.
-  virtual SqlValue::Type GetType() const = 0;
+  virtual Table::ColumnType GetType() const = 0;
 
   // Bounds a filter on this column between a minimum and maximum index.
   // Generally this is only possible if the column is sorted.
@@ -113,7 +113,9 @@
     };
   }
 
-  SqlValue::Type GetType() const override { return SqlValue::Type::kString; }
+  Table::ColumnType GetType() const override {
+    return Table::ColumnType::kString;
+  }
 
   bool HasOrdering() const override { return accessor_.HasOrdering(); }
 
@@ -126,14 +128,14 @@
 // Acessor trait (see below for definition).
 template <typename Accessor,
           typename sqlite_utils::is_numeric<typename Accessor::Type>* = nullptr>
-class NumericStorageColumn : public StorageColumn {
+class NumericColumn : public StorageColumn {
  public:
   // The type of the column. This is one of uint32_t, int32_t, uint64_t etc.
   using NumericType = typename Accessor::Type;
 
-  NumericStorageColumn(std::string col_name, bool hidden, Accessor accessor)
+  NumericColumn(std::string col_name, bool hidden, Accessor accessor)
       : StorageColumn(col_name, hidden), accessor_(accessor) {}
-  ~NumericStorageColumn() override = default;
+  ~NumericColumn() override = default;
 
   void ReportResult(sqlite3_context* ctx, uint32_t row) const override {
     sqlite_utils::ReportSqliteResult(ctx, accessor_.Get(row));
@@ -209,14 +211,16 @@
 
   bool HasOrdering() const override { return accessor_.HasOrdering(); }
 
-  SqlValue::Type GetType() const override {
-    if (std::is_same<NumericType, uint8_t>::value ||
-        std::is_same<NumericType, uint32_t>::value ||
-        std::is_same<NumericType, int32_t>::value ||
-        std::is_same<NumericType, int64_t>::value) {
-      return SqlValue::Type::kLong;
+  Table::ColumnType GetType() const override {
+    if (std::is_same<NumericType, int32_t>::value) {
+      return Table::ColumnType::kInt;
+    } else if (std::is_same<NumericType, uint8_t>::value ||
+               std::is_same<NumericType, uint32_t>::value) {
+      return Table::ColumnType::kUint;
+    } else if (std::is_same<NumericType, int64_t>::value) {
+      return Table::ColumnType::kLong;
     } else if (std::is_same<NumericType, double>::value) {
-      return SqlValue::Type::kDouble;
+      return Table::ColumnType::kDouble;
     }
     PERFETTO_FATAL("Unexpected column type");
   }
@@ -334,7 +338,7 @@
   }
 
   NullTermStringView Get(uint32_t idx) const override {
-    const char* ptr = (*string_map_)[static_cast<size_t>((*deque_)[idx])];
+    const char* ptr = (*string_map_)[(*deque_)[idx]];
     return ptr ? NullTermStringView(ptr) : NullTermStringView();
   }
 
diff --git a/src/trace_processor/storage_schema.cc b/src/trace_processor/storage_schema.cc
index 7c43ea7..2dd726c 100644
--- a/src/trace_processor/storage_schema.cc
+++ b/src/trace_processor/storage_schema.cc
@@ -26,8 +26,8 @@
                              std::vector<std::string> primary_keys)
     : columns_(std::move(columns)), primary_keys_(std::move(primary_keys)) {}
 
-SqliteTable::Schema StorageSchema::ToTableSchema() {
-  std::vector<SqliteTable::Column> columns;
+Table::Schema StorageSchema::ToTableSchema() {
+  std::vector<Table::Column> columns;
   size_t i = 0;
   for (const auto& col : columns_)
     columns.emplace_back(i++, col->name(), col->GetType(), col->hidden());
@@ -35,7 +35,7 @@
   std::vector<size_t> primary_keys;
   for (const auto& p_key : primary_keys_)
     primary_keys.emplace_back(ColumnIndexFromName(p_key));
-  return SqliteTable::Schema(std::move(columns), std::move(primary_keys));
+  return Table::Schema(std::move(columns), std::move(primary_keys));
 }
 
 size_t StorageSchema::ColumnIndexFromName(const std::string& name) const {
diff --git a/src/trace_processor/storage_schema.h b/src/trace_processor/storage_schema.h
index 96888b2..86895ce 100644
--- a/src/trace_processor/storage_schema.h
+++ b/src/trace_processor/storage_schema.h
@@ -23,9 +23,9 @@
 #include <vector>
 
 #include "src/trace_processor/filtered_row_index.h"
-#include "src/trace_processor/sqlite/sqlite_table.h"
-#include "src/trace_processor/sqlite/sqlite_utils.h"
+#include "src/trace_processor/sqlite_utils.h"
 #include "src/trace_processor/storage_columns.h"
+#include "src/trace_processor/table.h"
 #include "src/trace_processor/trace_storage.h"
 
 namespace perfetto {
@@ -68,7 +68,7 @@
     template <class Accessor>
     Builder& AddGenericNumericColumn(std::string column_name,
                                      Accessor accessor) {
-      columns_.emplace_back(new NumericStorageColumn<decltype(accessor)>(
+      columns_.emplace_back(new NumericColumn<decltype(accessor)>(
           column_name, false /* hidden */, accessor));
       return *this;
     }
@@ -103,7 +103,7 @@
   StorageSchema();
   StorageSchema(Columns columns, std::vector<std::string> primary_keys);
 
-  SqliteTable::Schema ToTableSchema();
+  Table::Schema ToTableSchema();
 
   size_t ColumnIndexFromName(const std::string& name) const;
 
diff --git a/src/trace_processor/storage_table.cc b/src/trace_processor/storage_table.cc
index 8cac8b2..7de67a5 100644
--- a/src/trace_processor/storage_table.cc
+++ b/src/trace_processor/storage_table.cc
@@ -22,13 +22,12 @@
 StorageTable::StorageTable() = default;
 StorageTable::~StorageTable() = default;
 
-util::Status StorageTable::Init(int, const char* const*, Schema* schema) {
+base::Optional<Table::Schema> StorageTable::Init(int, const char* const*) {
   schema_ = CreateStorageSchema();
-  *schema = schema_.ToTableSchema();
-  return util::OkStatus();
+  return schema_.ToTableSchema();
 }
 
-std::unique_ptr<SqliteTable::Cursor> StorageTable::CreateCursor() {
+std::unique_ptr<Table::Cursor> StorageTable::CreateCursor() {
   return std::unique_ptr<Cursor>(new Cursor(this));
 }
 
@@ -167,7 +166,7 @@
 }
 
 StorageTable::Cursor::Cursor(StorageTable* table)
-    : SqliteTable::Cursor(table), table_(table) {}
+    : Table::Cursor(table), table_(table) {}
 
 int StorageTable::Cursor::Filter(const QueryConstraints& qc,
                                  sqlite3_value** argv) {
diff --git a/src/trace_processor/storage_table.h b/src/trace_processor/storage_table.h
index 74247f6..3afe5cea 100644
--- a/src/trace_processor/storage_table.h
+++ b/src/trace_processor/storage_table.h
@@ -18,25 +18,25 @@
 #include <set>
 
 #include "src/trace_processor/row_iterators.h"
-#include "src/trace_processor/sqlite/sqlite_table.h"
 #include "src/trace_processor/storage_columns.h"
 #include "src/trace_processor/storage_schema.h"
+#include "src/trace_processor/table.h"
 
 namespace perfetto {
 namespace trace_processor {
 
 // Base class for all table implementations which are backed by some data
 // storage.
-class StorageTable : public SqliteTable {
+class StorageTable : public Table {
  public:
   // A cursor which abstracts common patterns found in storage backed tables. It
   // takes a strategy to iterate through rows and a column reporter for each
   // column to implement the Cursor interface.
-  class Cursor final : public SqliteTable::Cursor {
+  class Cursor final : public Table::Cursor {
    public:
     Cursor(StorageTable* table);
 
-    // Implementation of SqliteTable::Cursor.
+    // Implementation of Table::Cursor.
     int Filter(const QueryConstraints& qc, sqlite3_value** argv) override;
     int Next() override;
     int Eof() override;
@@ -52,10 +52,8 @@
   virtual ~StorageTable() override;
 
   // Table implementation.
-  util::Status Init(int,
-                    const char* const*,
-                    SqliteTable::Schema*) override final;
-  std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
+  base::Optional<Table::Schema> Init(int, const char* const*) override final;
+  std::unique_ptr<Table::Cursor> CreateCursor() override;
 
   // Required methods for subclasses to implement.
   virtual StorageSchema CreateStorageSchema() = 0;
diff --git a/src/trace_processor/string_pool.cc b/src/trace_processor/string_pool.cc
index 6c25229..fda57f5 100644
--- a/src/trace_processor/string_pool.cc
+++ b/src/trace_processor/string_pool.cc
@@ -17,13 +17,12 @@
 #include "src/trace_processor/string_pool.h"
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
 
 namespace perfetto {
 namespace trace_processor {
 
 StringPool::StringPool() {
-  blocks_.emplace_back(kDefaultBlockSize);
+  blocks_.emplace_back();
 
   // Reserve a slot for the null string.
   PERFETTO_CHECK(blocks_.back().TryInsert(NullTermStringView()));
@@ -35,22 +34,20 @@
 StringPool& StringPool::operator=(StringPool&&) = default;
 
 StringPool::Id StringPool::InsertString(base::StringView str, uint64_t hash) {
+  // We shouldn't be writing string with more than 2^16 characters to the pool.
+  PERFETTO_CHECK(str.size() < std::numeric_limits<uint16_t>::max());
+
   // Try and find enough space in the current block for the string and the
-  // metadata (varint-encoded size + the string data + the null terminator).
-  const uint8_t* ptr = blocks_.back().TryInsert(str);
+  // metadata (the size of the string + the null terminator + 2 bytes to encode
+  // the size itself).
+  auto* ptr = blocks_.back().TryInsert(str);
   if (PERFETTO_UNLIKELY(!ptr)) {
     // This means the block did not have enough space. This should only happen
     // on 32-bit platforms as we allocate a 4GB mmap on 64 bit.
     PERFETTO_CHECK(sizeof(uint8_t*) == 4);
 
-    // Add a new block to store the data. If the string is larger that the
-    // default block size, add a bigger block exlusively for this string.
-    if (str.size() + kMaxMetadataSize > kDefaultBlockSize) {
-      blocks_.emplace_back(str.size() +
-                           base::AlignUp<base::kPageSize>(kMaxMetadataSize));
-    } else {
-      blocks_.emplace_back(kDefaultBlockSize);
-    }
+    // Add a new block to store the data.
+    blocks_.emplace_back();
 
     // Try and reserve space again - this time we should definitely succeed.
     ptr = blocks_.back().TryInsert(str);
@@ -64,29 +61,28 @@
   return string_id;
 }
 
-const uint8_t* StringPool::Block::TryInsert(base::StringView str) {
+uint8_t* StringPool::Block::TryInsert(base::StringView str) {
   auto str_size = str.size();
-  if (static_cast<uint64_t>(pos_) + str_size + kMaxMetadataSize > size_)
+  auto size = str_size + kMetadataSize;
+  if (static_cast<uint64_t>(pos_) + size >= kBlockSize)
     return nullptr;
 
   // Get where we should start writing this string.
-  uint8_t* begin = Get(pos_);
+  uint8_t* ptr = Get(pos_);
 
-  // First write the size of the string using varint encoding.
-  uint8_t* end = protozero::proto_utils::WriteVarInt(str_size, begin);
+  // First memcpy the size of the string into the buffer.
+  memcpy(ptr, &str_size, sizeof(str_size));
 
-  // Next the string itself.
-  if (PERFETTO_LIKELY(str_size > 0)) {
-    memcpy(end, str.data(), str_size);
-    end += str_size;
-  }
+  // Next the string itself which starts at offset 2.
+  if (PERFETTO_LIKELY(str_size > 0))
+    memcpy(&ptr[2], str.data(), str_size);
 
   // Finally add a null terminator.
-  *(end++) = '\0';
+  ptr[2 + str_size] = '\0';
 
   // Update the end of the block and return the pointer to the string.
-  pos_ = OffsetOf(end);
-  return begin;
+  pos_ += size;
+  return ptr;
 }
 
 StringPool::Iterator::Iterator(const StringPool* pool) : pool_(pool) {}
@@ -99,13 +95,10 @@
 
   // Find the size of the string at the current offset in the block
   // and increment the offset by that size.
-  uint32_t str_size = 0;
-  const uint8_t* ptr = block.Get(block_offset_);
-  ptr = ReadSize(ptr, &str_size);
-  ptr += str_size + 1;
-  block_offset_ = block.OffsetOf(ptr);
+  auto str_size = GetSize(block.Get(block_offset_));
+  block_offset_ += kMetadataSize + str_size;
 
-  // If we're out of bounds for this block, go to the start of the next block.
+  // If we're out of bounds for this block, go the the start of the next block.
   if (block.pos() <= block_offset_) {
     block_id_++;
     block_offset_ = 0;
diff --git a/src/trace_processor/string_pool.h b/src/trace_processor/string_pool.h
index e2502e7..f4a1523 100644
--- a/src/trace_processor/string_pool.h
+++ b/src/trace_processor/string_pool.h
@@ -17,9 +17,7 @@
 #ifndef SRC_TRACE_PROCESSOR_STRING_POOL_H_
 #define SRC_TRACE_PROCESSOR_STRING_POOL_H_
 
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/paged_memory.h"
-#include "perfetto/protozero/proto_utils.h"
+#include "perfetto/base/paged_memory.h"
 #include "src/trace_processor/null_term_string_view.h"
 
 #include <unordered_map>
@@ -28,31 +26,15 @@
 namespace perfetto {
 namespace trace_processor {
 
+// Interns strings in a string pool and hands out compact StringIds which can
+// be used to retrieve the string in O(1).
 // On 64-bit platforms, the string pool is implemented as a mmaped buffer
 // of 4GB with the id being equal ot the offset into this buffer of the string.
 // On 32-bit platforms instead, the implementation allocates 32MB blocks of
 // mmaped memory with the pointer being directly converted to the id.
-constexpr size_t kDefaultBlockSize =
-    sizeof(void*) == 8
-        ? static_cast<size_t>(4ull * 1024ull * 1024ull * 1024ull) /* 4GB */
-        : 32ull * 1024ull * 1024ull /* 32MB */;
-
-// Interns strings in a string pool and hands out compact StringIds which can
-// be used to retrieve the string in O(1).
 class StringPool {
  public:
-  struct Id {
-    Id() = default;
-    constexpr Id(uint32_t i) : id(i) {}
-
-    bool operator==(const Id& other) const { return other.id == id; }
-    bool operator!=(const Id& other) const { return !(other == *this); }
-    bool operator<(const Id& other) const { return id < other.id; }
-
-    bool is_null() const { return id == 0u; }
-
-    uint32_t id;
-  };
+  using Id = uint32_t;
 
   // Iterator over the strings in the pool.
   class Iterator {
@@ -84,7 +66,7 @@
 
   Id InternString(base::StringView str) {
     if (str.data() == nullptr)
-      return Id(0);
+      return 0;
 
     auto hash = str.Hash();
     auto id_it = string_index_.find(hash);
@@ -95,21 +77,8 @@
     return InsertString(str, hash);
   }
 
-  base::Optional<Id> GetId(base::StringView str) const {
-    if (str.data() == nullptr)
-      return Id(0u);
-
-    auto hash = str.Hash();
-    auto id_it = string_index_.find(hash);
-    if (id_it != string_index_.end()) {
-      PERFETTO_DCHECK(Get(id_it->second) == str);
-      return id_it->second;
-    }
-    return base::nullopt;
-  }
-
   NullTermStringView Get(Id id) const {
-    if (id.id == 0)
+    if (id == 0)
       return NullTermStringView();
     return GetFromPtr(IdToPtr(id));
   }
@@ -120,10 +89,8 @@
 
  private:
   using StringHash = uint64_t;
-
   struct Block {
-    explicit Block(size_t size)
-        : mem_(base::PagedMemory::Allocate(size)), size_(size) {}
+    Block() : mem_(base::PagedMemory::Allocate(kBlockSize)) {}
     ~Block() = default;
 
     // Allow std::move().
@@ -138,81 +105,78 @@
       return static_cast<uint8_t*>(mem_.Get()) + offset;
     }
 
-    const uint8_t* TryInsert(base::StringView str);
+    uint8_t* TryInsert(base::StringView str);
 
-    uint32_t OffsetOf(const uint8_t* ptr) const {
-      PERFETTO_DCHECK(Get(0) < ptr &&
-                      ptr < Get(static_cast<uint32_t>(size_ - 1)));
+    uint32_t OffsetOf(uint8_t* ptr) const {
+      PERFETTO_DCHECK(Get(0) < ptr && ptr < Get(kBlockSize - 1));
       return static_cast<uint32_t>(ptr - Get(0));
     }
 
     uint32_t pos() const { return pos_; }
 
    private:
+    static constexpr size_t kBlockSize =
+        sizeof(void*) == 8
+            ? static_cast<size_t>(4ull * 1024ull * 1024ull * 1024ull) /* 4GB */
+            : 32ull * 1024ull * 1024ull /* 32MB */;
+
     base::PagedMemory mem_;
     uint32_t pos_ = 0;
-    size_t size_;
   };
 
   friend class Iterator;
 
   // Number of bytes to reserve for size and null terminator.
-  // This is the upper limit on metadata size: 5 bytes for max uint32,
-  // plus 1 byte for null terminator. The actual size may be lower.
-  static constexpr uint8_t kMaxMetadataSize = 6;
+  static constexpr uint8_t kMetadataSize = 3;
 
   // Inserts the string with the given hash into the pool
   Id InsertString(base::StringView, uint64_t hash);
 
   // |ptr| should point to the start of the string metadata (i.e. the first byte
   // of the size).
-  Id PtrToId(const uint8_t* ptr) const {
+  Id PtrToId(uint8_t* ptr) const {
     // For a 64 bit architecture, the id is the offset of the pointer inside
     // the one and only 4GB block.
     if (sizeof(void*) == 8) {
       PERFETTO_DCHECK(blocks_.size() == 1);
-      return Id(blocks_.back().OffsetOf(ptr));
+      return blocks_.back().OffsetOf(ptr);
     }
 
     // On 32 bit architectures, the size of the pointer is 32-bit so we simply
     // use the pointer itself as the id.
     // Double cast needed because, on 64 archs, the compiler complains that we
     // are losing information.
-    return Id(static_cast<uint32_t>(reinterpret_cast<uintptr_t>(ptr)));
+    return static_cast<Id>(reinterpret_cast<uintptr_t>(ptr));
   }
 
-  // The returned pointer points to the start of the string metadata (i.e. the
+  // THe returned pointer points to the start of the string metadata (i.e. the
   // first byte of the size).
-  const uint8_t* IdToPtr(Id id) const {
+  uint8_t* IdToPtr(Id id) const {
     // For a 64 bit architecture, the pointer is simply the found by taking
     // the base of the 4GB block and adding the offset given by |id|.
     if (sizeof(void*) == 8) {
       PERFETTO_DCHECK(blocks_.size() == 1);
-      return blocks_.back().Get(id.id);
+      return blocks_.back().Get(id);
     }
     // On a 32 bit architecture, the pointer is the same as the id.
-    return reinterpret_cast<uint8_t*>(id.id);
+    return reinterpret_cast<uint8_t*>(id);
   }
 
   // |ptr| should point to the start of the string metadata (i.e. the first byte
   // of the size).
-  // Returns pointer to the start of the string.
-  static const uint8_t* ReadSize(const uint8_t* ptr, uint32_t* size) {
-    uint64_t value = 0;
-    const uint8_t* str_ptr = protozero::proto_utils::ParseVarInt(
-        ptr, ptr + kMaxMetadataSize, &value);
-    PERFETTO_DCHECK(str_ptr != ptr);
-    PERFETTO_DCHECK(value < std::numeric_limits<uint32_t>::max());
-    *size = static_cast<uint32_t>(value);
-    return str_ptr;
+  static uint16_t GetSize(uint8_t* ptr) {
+    // The size is simply memcpyed into the byte buffer when writing.
+    uint16_t size;
+    memcpy(&size, ptr, sizeof(uint16_t));
+    return size;
   }
 
   // |ptr| should point to the start of the string metadata (i.e. the first byte
   // of the size).
-  static NullTermStringView GetFromPtr(const uint8_t* ptr) {
-    uint32_t size = 0;
-    const uint8_t* str_ptr = ReadSize(ptr, &size);
-    return NullTermStringView(reinterpret_cast<const char*>(str_ptr), size);
+  static NullTermStringView GetFromPtr(uint8_t* ptr) {
+    // With the first two bytes being used for the size, the string starts from
+    // byte 3.
+    return NullTermStringView(reinterpret_cast<char*>(&ptr[2]), GetSize(ptr));
   }
 
   // The actual memory storing the strings.
@@ -227,18 +191,4 @@
 }  // namespace trace_processor
 }  // namespace perfetto
 
-namespace std {
-
-template <>
-struct hash< ::perfetto::trace_processor::StringPool::Id> {
-  using argument_type = ::perfetto::trace_processor::StringPool::Id;
-  using result_type = size_t;
-
-  result_type operator()(const argument_type& r) const {
-    return std::hash<uint32_t>{}(r.id);
-  }
-};
-
-}  // namespace std
-
 #endif  // SRC_TRACE_PROCESSOR_STRING_POOL_H_
diff --git a/src/trace_processor/string_pool_unittest.cc b/src/trace_processor/string_pool_unittest.cc
index 9021f01..6160be4 100644
--- a/src/trace_processor/string_pool_unittest.cc
+++ b/src/trace_processor/string_pool_unittest.cc
@@ -18,7 +18,7 @@
 
 #include <random>
 
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -49,7 +49,7 @@
   StringPool pool;
 
   auto id = pool.InternString(NullTermStringView());
-  ASSERT_EQ(id, 0u);
+  ASSERT_EQ(id, 0);
   ASSERT_EQ(pool.Get(id).c_str(), nullptr);
 }
 
@@ -119,28 +119,7 @@
     }
     string_map.erase(it_pair.first, it_pair.second);
   }
-  ASSERT_EQ(string_map.size(), 0u);
-}
-
-TEST(StringPoolTest, BigString) {
-  constexpr size_t kBigStringSize = 33 * 1024 * 1024;
-  std::unique_ptr<char[]> str1(new char[kBigStringSize + 1]);
-  std::unique_ptr<char[]> str2(new char[kBigStringSize + 1]);
-  for (size_t i = 0; i < kBigStringSize; i++) {
-    str1.get()[i] = 'A' + static_cast<char>(i % 32);
-    str2.get()[i] = 'A' + static_cast<char>((i + 7) % 32);
-  }
-  str1.get()[kBigStringSize] = '\0';
-  str2.get()[kBigStringSize] = '\0';
-
-  StringPool pool;
-  StringPool::Id id1 =
-      pool.InternString(base::StringView(str1.get(), kBigStringSize));
-  StringPool::Id id2 =
-      pool.InternString(base::StringView(str2.get(), kBigStringSize));
-
-  ASSERT_EQ(str1.get(), pool.Get(id1));
-  ASSERT_EQ(str2.get(), pool.Get(id2));
+  ASSERT_EQ(string_map.size(), 0);
 }
 
 }  // namespace
diff --git a/src/trace_processor/string_table.cc b/src/trace_processor/string_table.cc
new file mode 100644
index 0000000..91d4985
--- /dev/null
+++ b/src/trace_processor/string_table.cc
@@ -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.
+ */
+
+#include "src/trace_processor/string_table.h"
+
+#include <sqlite3.h>
+#include <string.h>
+
+#include <algorithm>
+#include <bitset>
+#include <numeric>
+
+#include "src/trace_processor/sqlite_utils.h"
+#include "src/trace_processor/trace_storage.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+StringTable::StringTable(sqlite3*, const TraceStorage* storage)
+    : storage_(storage) {}
+
+void StringTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
+  Table::Register<StringTable>(db, storage, "strings");
+}
+
+base::Optional<Table::Schema> StringTable::Init(int, const char* const*) {
+  return Schema(
+      {
+          Table::Column(Column::kStringId, "id", ColumnType::kUint),
+          Table::Column(Column::kString, "str", ColumnType::kString),
+      },
+      {Column::kStringId});
+}
+
+std::unique_ptr<Table::Cursor> StringTable::CreateCursor() {
+  return std::unique_ptr<Table::Cursor>(new Cursor(this));
+}
+
+int StringTable::BestIndex(const QueryConstraints&, BestIndexInfo* info) {
+  info->order_by_consumed = false;  // Delegate sorting to SQLite.
+  info->estimated_cost = static_cast<uint32_t>(storage_->string_count());
+  return SQLITE_OK;
+}
+
+StringTable::Cursor::Cursor(StringTable* table)
+    : Table::Cursor(table), storage_(table->storage_), table_(table) {}
+
+StringTable::Cursor::~Cursor() = default;
+
+int StringTable::Cursor::Filter(const QueryConstraints&, sqlite3_value**) {
+  *this = Cursor(table_);
+  num_rows_ = storage_->string_count();
+  return SQLITE_OK;
+}
+
+int StringTable::Cursor::Next() {
+  row_++;
+  return SQLITE_OK;
+}
+
+int StringTable::Cursor::Eof() {
+  return row_ >= num_rows_;
+}
+
+int StringTable::Cursor::Column(sqlite3_context* context, int col) {
+  StringId string_id = static_cast<StringId>(row_);
+  switch (col) {
+    case Column::kStringId:
+      sqlite3_result_int64(context, static_cast<sqlite3_int64>(row_));
+      break;
+    case Column::kString:
+      sqlite3_result_text(context, storage_->GetString(string_id).c_str(), -1,
+                          sqlite_utils::kSqliteStatic);
+      break;
+  }
+  return SQLITE_OK;
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/string_table.h b/src/trace_processor/string_table.h
new file mode 100644
index 0000000..9746fdf
--- /dev/null
+++ b/src/trace_processor/string_table.h
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_STRING_TABLE_H_
+#define SRC_TRACE_PROCESSOR_STRING_TABLE_H_
+
+#include <limits>
+#include <memory>
+
+#include "src/trace_processor/table.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class QueryConstraints;
+class TraceStorage;
+
+// A virtual table that allows to list and query all the strings in the db.
+class StringTable : public Table {
+ public:
+  enum Column {
+    kStringId = 0,
+    kString = 1,
+  };
+  // Implementation of the SQLite cursor interface.
+  class Cursor : public Table::Cursor {
+   public:
+    Cursor(StringTable*);
+    ~Cursor() override;
+
+    // Implementation of Table::Cursor.
+    int Filter(const QueryConstraints&, sqlite3_value**) override;
+    int Next() override;
+    int Eof() override;
+    int Column(sqlite3_context*, int N) override;
+
+   private:
+    Cursor(Cursor&) = delete;
+    Cursor& operator=(const Cursor&) = delete;
+
+    Cursor(Cursor&&) noexcept = default;
+    Cursor& operator=(Cursor&&) = default;
+
+    size_t row_ = 0;
+    size_t num_rows_ = 0;
+
+    const TraceStorage* storage_ = nullptr;
+    StringTable* table_ = nullptr;
+  };
+
+  StringTable(sqlite3*, const TraceStorage* storage);
+
+  static void RegisterTable(sqlite3* db, const TraceStorage* storage);
+
+  // Table implementation.
+  base::Optional<Table::Schema> Init(int, const char* const*) override;
+  std::unique_ptr<Table::Cursor> CreateCursor() override;
+  int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
+
+ private:
+  const TraceStorage* const storage_;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_STRING_TABLE_H_
diff --git a/src/trace_processor/syscall_tracker.h b/src/trace_processor/syscall_tracker.h
index f367309..eba0fea 100644
--- a/src/trace_processor/syscall_tracker.h
+++ b/src/trace_processor/syscall_tracker.h
@@ -20,11 +20,10 @@
 #include <limits>
 #include <tuple>
 
-#include "perfetto/ext/base/string_view.h"
+#include "perfetto/base/string_view.h"
 #include "src/trace_processor/slice_tracker.h"
 #include "src/trace_processor/trace_processor_context.h"
 #include "src/trace_processor/trace_storage.h"
-#include "src/trace_processor/track_tracker.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -50,19 +49,14 @@
 
   void Enter(int64_t ts, UniqueTid utid, uint32_t syscall_num) {
     StringId name = SyscallNumberToStringId(syscall_num);
-    if (!name.is_null()) {
-      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-      context_->slice_tracker->Begin(ts, track_id, utid, RefType::kRefUtid,
-                                     0 /* cat */, name);
-    }
+    if (name)
+      context_->slice_tracker->Begin(ts, utid, 0 /* cat */, name);
   }
 
   void Exit(int64_t ts, UniqueTid utid, uint32_t syscall_num) {
     StringId name = SyscallNumberToStringId(syscall_num);
-    if (!name.is_null()) {
-      TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
-      context_->slice_tracker->End(ts, track_id, 0 /* cat */, name);
-    }
+    if (name)
+      context_->slice_tracker->End(ts, utid, 0 /* cat */, name);
   }
 
  private:
@@ -82,7 +76,7 @@
   }
 
   // This is table from platform specific syscall number directly to
-  // the relevant StringId (this avoids having to always do two conversions).
+  // the relevent StringId (this avoids having to always do two conversions).
   std::array<StringId, kMaxSyscalls> arch_syscall_to_string_id_{};
   StringId sys_write_string_id_ = std::numeric_limits<StringId>::max();
 };
diff --git a/src/trace_processor/syscall_tracker_unittest.cc b/src/trace_processor/syscall_tracker_unittest.cc
index 70bf075..5d90607 100644
--- a/src/trace_processor/syscall_tracker_unittest.cc
+++ b/src/trace_processor/syscall_tracker_unittest.cc
@@ -17,14 +17,15 @@
 #include "src/trace_processor/syscall_tracker.h"
 
 #include "src/trace_processor/slice_tracker.h"
-#include "test/gtest_and_gmock.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace trace_processor {
 namespace {
 
 using ::testing::_;
-using ::testing::Return;
 using ::testing::SaveArg;
 
 class MockSliceTracker : public SliceTracker {
@@ -32,29 +33,19 @@
   MockSliceTracker(TraceProcessorContext* context) : SliceTracker(context) {}
   virtual ~MockSliceTracker() = default;
 
-  MOCK_METHOD7(Begin,
-               base::Optional<uint32_t>(int64_t timestamp,
-                                        TrackId track_id,
-                                        int64_t ref,
-                                        RefType ref_type,
-                                        StringId cat,
-                                        StringId name,
-                                        SetArgsCallback args_callback));
-  MOCK_METHOD5(End,
-               base::Optional<uint32_t>(int64_t timestamp,
-                                        TrackId track_id,
-                                        StringId cat,
-                                        StringId name,
-                                        SetArgsCallback args_callback));
+  MOCK_METHOD4(
+      Begin,
+      void(int64_t timestamp, UniqueTid utid, StringId cat, StringId name));
+  MOCK_METHOD4(
+      End,
+      void(int64_t timestamp, UniqueTid utid, StringId cat, StringId name));
 };
 
 class SyscallTrackerTest : public ::testing::Test {
  public:
   SyscallTrackerTest() {
-    context.storage.reset(new TraceStorage());
-    track_tracker = new TrackTracker(&context);
-    context.track_tracker.reset(track_tracker);
     slice_tracker = new MockSliceTracker(&context);
+    context.storage.reset(new TraceStorage());
     context.slice_tracker.reset(slice_tracker);
     context.syscall_tracker.reset(new SyscallTracker(&context));
   }
@@ -62,18 +53,15 @@
  protected:
   TraceProcessorContext context;
   MockSliceTracker* slice_tracker;
-  TrackTracker* track_tracker;
 };
 
 TEST_F(SyscallTrackerTest, ReportUnknownSyscalls) {
-  constexpr TrackId track = 0u;
   StringId begin_name = 0;
   StringId end_name = 0;
-  EXPECT_CALL(*slice_tracker,
-              Begin(100, track, 42, RefType::kRefUtid, kNullStringId, _, _))
-      .WillOnce(DoAll(SaveArg<5>(&begin_name), Return(base::nullopt)));
-  EXPECT_CALL(*slice_tracker, End(110, track, kNullStringId, _, _))
-      .WillOnce(DoAll(SaveArg<3>(&end_name), Return(base::nullopt)));
+  EXPECT_CALL(*slice_tracker, Begin(100, 42, 0, _))
+      .WillOnce(SaveArg<3>(&begin_name));
+  EXPECT_CALL(*slice_tracker, End(110, 42, 0, _))
+      .WillOnce(SaveArg<3>(&end_name));
 
   context.syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 57 /*sys_read*/);
   context.syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 57 /*sys_read*/);
@@ -83,22 +71,20 @@
 
 TEST_F(SyscallTrackerTest, IgnoreWriteSyscalls) {
   context.syscall_tracker->SetArchitecture(kAarch64);
-  EXPECT_CALL(*slice_tracker, Begin(_, _, _, _, _, _, _)).Times(0);
-  EXPECT_CALL(*slice_tracker, End(_, _, _, _, _)).Times(0);
+  EXPECT_CALL(*slice_tracker, Begin(_, _, _, _)).Times(0);
+  EXPECT_CALL(*slice_tracker, End(_, _, _, _)).Times(0);
 
   context.syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 64 /*sys_write*/);
   context.syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 64 /*sys_write*/);
 }
 
 TEST_F(SyscallTrackerTest, Aarch64) {
-  constexpr TrackId track = 0u;
   StringId begin_name = 0;
   StringId end_name = 0;
-  EXPECT_CALL(*slice_tracker,
-              Begin(100, track, 42, RefType::kRefUtid, kNullStringId, _, _))
-      .WillOnce(DoAll(SaveArg<5>(&begin_name), Return(base::nullopt)));
-  EXPECT_CALL(*slice_tracker, End(110, track, kNullStringId, _, _))
-      .WillOnce(DoAll(SaveArg<3>(&end_name), Return(base::nullopt)));
+  EXPECT_CALL(*slice_tracker, Begin(100, 42, 0, _))
+      .WillOnce(SaveArg<3>(&begin_name));
+  EXPECT_CALL(*slice_tracker, End(110, 42, 0, _))
+      .WillOnce(SaveArg<3>(&end_name));
 
   context.syscall_tracker->SetArchitecture(kAarch64);
   context.syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 63 /*sys_read*/);
@@ -108,14 +94,12 @@
 }
 
 TEST_F(SyscallTrackerTest, x8664) {
-  constexpr TrackId track = 0u;
   StringId begin_name = 0;
   StringId end_name = 0;
-  EXPECT_CALL(*slice_tracker,
-              Begin(100, track, 42, RefType::kRefUtid, kNullStringId, _, _))
-      .WillOnce(DoAll(SaveArg<5>(&begin_name), Return(base::nullopt)));
-  EXPECT_CALL(*slice_tracker, End(110, track, kNullStringId, _, _))
-      .WillOnce(DoAll(SaveArg<3>(&end_name), Return(base::nullopt)));
+  EXPECT_CALL(*slice_tracker, Begin(100, 42, 0, _))
+      .WillOnce(SaveArg<3>(&begin_name));
+  EXPECT_CALL(*slice_tracker, End(110, 42, 0, _))
+      .WillOnce(SaveArg<3>(&end_name));
 
   context.syscall_tracker->SetArchitecture(kX86_64);
   context.syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 0 /*sys_read*/);
@@ -125,8 +109,8 @@
 }
 
 TEST_F(SyscallTrackerTest, SyscallNumberTooLarge) {
-  EXPECT_CALL(*slice_tracker, Begin(_, _, _, _, _, _, _)).Times(0);
-  EXPECT_CALL(*slice_tracker, End(_, _, _, _, _)).Times(0);
+  EXPECT_CALL(*slice_tracker, Begin(_, _, _, _)).Times(0);
+  EXPECT_CALL(*slice_tracker, End(_, _, _, _)).Times(0);
   context.syscall_tracker->SetArchitecture(kAarch64);
   context.syscall_tracker->Enter(100 /*ts*/, 42 /*utid*/, 9999);
   context.syscall_tracker->Exit(110 /*ts*/, 42 /*utid*/, 9999);
diff --git a/src/trace_processor/table.cc b/src/trace_processor/table.cc
new file mode 100644
index 0000000..1218b5a
--- /dev/null
+++ b/src/trace_processor/table.cc
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ */
+
+#include "src/trace_processor/table.h"
+
+#include <ctype.h>
+#include <string.h>
+#include <algorithm>
+
+#include "perfetto/base/logging.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+namespace {
+
+std::string TypeToString(Table::ColumnType type) {
+  switch (type) {
+    case Table::ColumnType::kString:
+      return "STRING";
+    case Table::ColumnType::kUint:
+      return "UNSIGNED INT";
+    case Table::ColumnType::kLong:
+      return "BIG INT";
+    case Table::ColumnType::kInt:
+      return "INT";
+    case Table::ColumnType::kDouble:
+      return "DOUBLE";
+    case Table::ColumnType::kUnknown:
+      PERFETTO_FATAL("Cannot map unknown column type");
+  }
+  PERFETTO_FATAL("Not reached");  // For gcc
+}
+
+}  // namespace
+
+// static
+bool Table::debug = false;
+
+Table::Table() = default;
+Table::~Table() = default;
+
+int Table::OpenInternal(sqlite3_vtab_cursor** ppCursor) {
+  // Freed in xClose().
+  *ppCursor = static_cast<sqlite3_vtab_cursor*>(CreateCursor().release());
+  return SQLITE_OK;
+}
+
+int Table::BestIndexInternal(sqlite3_index_info* idx) {
+  QueryConstraints query_constraints;
+
+  for (int i = 0; i < idx->nOrderBy; i++) {
+    int column = idx->aOrderBy[i].iColumn;
+    bool desc = idx->aOrderBy[i].desc;
+    query_constraints.AddOrderBy(column, desc);
+  }
+
+  for (int i = 0; i < idx->nConstraint; i++) {
+    const auto& cs = idx->aConstraint[i];
+    if (!cs.usable)
+      continue;
+    query_constraints.AddConstraint(cs.iColumn, cs.op);
+
+    // argvIndex is 1-based so use the current size of the vector.
+    int argv_index = static_cast<int>(query_constraints.constraints().size());
+    idx->aConstraintUsage[i].argvIndex = argv_index;
+  }
+
+  BestIndexInfo info;
+  info.omit.resize(query_constraints.constraints().size());
+
+  int ret = BestIndex(query_constraints, &info);
+
+  if (Table::debug) {
+    PERFETTO_LOG(
+        "[%s::BestIndex] constraints=%s orderByConsumed=%d estimatedCost=%d",
+        name_.c_str(), query_constraints.ToNewSqlite3String().get(),
+        info.order_by_consumed, info.estimated_cost);
+  }
+
+  if (ret != SQLITE_OK)
+    return ret;
+
+  idx->orderByConsumed = info.order_by_consumed;
+  idx->estimatedCost = info.estimated_cost;
+
+  size_t j = 0;
+  for (int i = 0; i < idx->nConstraint; i++) {
+    const auto& cs = idx->aConstraint[i];
+    if (cs.usable)
+      idx->aConstraintUsage[i].omit = info.omit[j++];
+  }
+
+  if (!info.order_by_consumed)
+    query_constraints.ClearOrderBy();
+
+  idx->idxStr = query_constraints.ToNewSqlite3String().release();
+  idx->needToFreeIdxStr = true;
+  idx->idxNum = ++best_index_num_;
+
+  return SQLITE_OK;
+}
+
+int Table::FindFunction(const char*, FindFunctionFn, void**) {
+  return 0;
+}
+
+int Table::Update(int, sqlite3_value**, sqlite3_int64*) {
+  return SQLITE_READONLY;
+}
+
+const QueryConstraints& Table::ParseConstraints(int idxNum,
+                                                const char* idxStr,
+                                                int argc) {
+  bool cache_hit = true;
+  if (idxNum != qc_hash_) {
+    qc_cache_ = QueryConstraints::FromString(idxStr);
+    qc_hash_ = idxNum;
+    cache_hit = false;
+  }
+  if (Table::debug) {
+    PERFETTO_LOG("[%s::ParseConstraints] constraints=%s argc=%d cache_hit=%d",
+                 name_.c_str(), idxStr, argc, cache_hit);
+  }
+  return qc_cache_;
+}
+
+Table::Cursor::Cursor(Table* table) : table_(table) {
+  // This is required to prevent us from leaving this field uninitialised if
+  // we ever move construct the Cursor.
+  pVtab = table;
+}
+Table::Cursor::~Cursor() = default;
+
+int Table::Cursor::RowId(sqlite3_int64*) {
+  return SQLITE_ERROR;
+}
+
+Table::Column::Column(size_t index,
+                      std::string name,
+                      ColumnType type,
+                      bool hidden)
+    : index_(index), name_(name), type_(type), hidden_(hidden) {}
+
+Table::Schema::Schema(std::vector<Column> columns,
+                      std::vector<size_t> primary_keys)
+    : columns_(std::move(columns)), primary_keys_(std::move(primary_keys)) {
+  for (size_t i = 0; i < columns_.size(); i++) {
+    PERFETTO_CHECK(columns_[i].index() == i);
+  }
+  for (auto key : primary_keys_) {
+    PERFETTO_CHECK(key < columns_.size());
+  }
+}
+
+Table::Schema::Schema() = default;
+Table::Schema::Schema(const Schema&) = default;
+Table::Schema& Table::Schema::operator=(const Schema&) = default;
+
+std::string Table::Schema::ToCreateTableStmt() const {
+  std::string stmt = "CREATE TABLE x(";
+  for (size_t i = 0; i < columns_.size(); ++i) {
+    const Column& col = columns_[i];
+    stmt += " " + col.name();
+
+    if (col.type() != ColumnType::kUnknown) {
+      stmt += " " + TypeToString(col.type());
+    } else if (std::find(primary_keys_.begin(), primary_keys_.end(), i) !=
+               primary_keys_.end()) {
+      PERFETTO_FATAL("Unknown type for primary key column %s",
+                     col.name().c_str());
+    }
+    if (col.hidden()) {
+      stmt += " HIDDEN";
+    }
+    stmt += ",";
+  }
+  stmt += " PRIMARY KEY(";
+  for (size_t i = 0; i < primary_keys_.size(); i++) {
+    if (i != 0)
+      stmt += ", ";
+    stmt += columns_[primary_keys_[i]].name();
+  }
+  stmt += ")) WITHOUT ROWID;";
+  return stmt;
+}
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/table.h b/src/trace_processor/table.h
new file mode 100644
index 0000000..58c9d18
--- /dev/null
+++ b/src/trace_processor/table.h
@@ -0,0 +1,333 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_TABLE_H_
+#define SRC_TRACE_PROCESSOR_TABLE_H_
+
+#include <sqlite3.h>
+
+#include <functional>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "perfetto/base/optional.h"
+#include "src/trace_processor/query_constraints.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class TraceStorage;
+
+// Abstract base class representing a SQLite virtual table. Implements the
+// common bookeeping required across all tables and allows subclasses to
+// implement a friendlier API than that required by SQLite.
+class Table : public sqlite3_vtab {
+ public:
+  using Factory =
+      std::function<std::unique_ptr<Table>(sqlite3*, const TraceStorage*)>;
+
+  // Allowed types for columns in a table.
+  enum ColumnType {
+    kString = 1,
+    kUint = 2,
+    kLong = 3,
+    kInt = 4,
+    kDouble = 5,
+    kUnknown = 6,
+  };
+
+  // Describes a column of this table.
+  class Column {
+   public:
+    Column(size_t idx, std::string name, ColumnType type, bool hidden = false);
+
+    size_t index() const { return index_; }
+    const std::string& name() const { return name_; }
+    ColumnType type() const { return type_; }
+    bool hidden() const { return hidden_; }
+
+   private:
+    size_t index_ = 0;
+    std::string name_;
+    ColumnType type_ = ColumnType::kString;
+    bool hidden_ = false;
+  };
+
+  // When set it logs all BestIndex and Filter actions on the console.
+  static bool debug;
+
+  // Public for unique_ptr destructor calls.
+  virtual ~Table();
+
+  // Abstract base class representing an SQLite Cursor. Presents a friendlier
+  // API for subclasses to implement.
+  class Cursor : public sqlite3_vtab_cursor {
+   public:
+    Cursor(Table* table);
+    virtual ~Cursor();
+
+    // Methods to be implemented by derived table classes.
+
+    // Called to intialise the cursor with the constraints of the query.
+    virtual int Filter(const QueryConstraints& qc, sqlite3_value**) = 0;
+
+    // Called to forward the cursor to the next row in the table.
+    virtual int Next() = 0;
+
+    // Called to check if the cursor has reached eof. Column will be called iff
+    // this method returns true.
+    virtual int Eof() = 0;
+
+    // Used to extract the value from the column at index |N|.
+    virtual int Column(sqlite3_context* context, int N) = 0;
+
+    // Optional methods to implement.
+    virtual int RowId(sqlite3_int64*);
+
+   protected:
+    Cursor(Cursor&) = delete;
+    Cursor& operator=(const Cursor&) = delete;
+
+    Cursor(Cursor&&) noexcept = default;
+    Cursor& operator=(Cursor&&) = default;
+
+   private:
+    friend class Table;
+
+    Table* table_ = nullptr;
+  };
+
+  // The schema of the table. Created by subclasses to allow the table class to
+  // do filtering and inform SQLite about the CREATE table statement.
+  class Schema {
+   public:
+    Schema();
+    Schema(std::vector<Column>, std::vector<size_t> primary_keys);
+
+    // This class is explicitly copiable.
+    Schema(const Schema&);
+    Schema& operator=(const Schema& t);
+
+    std::string ToCreateTableStmt() const;
+
+    const std::vector<Column>& columns() const { return columns_; }
+    const std::vector<size_t> primary_keys() { return primary_keys_; }
+
+   private:
+    // The names and types of the columns of the table.
+    std::vector<Column> columns_;
+
+    // The primary keys of the table given by an offset into |columns|.
+    std::vector<size_t> primary_keys_;
+  };
+
+ protected:
+  // Populated by a BestIndex call to allow subclasses to tweak SQLite's
+  // handling of sets of constraints.
+  struct BestIndexInfo {
+    bool order_by_consumed = false;
+    uint32_t estimated_cost = 0;
+    std::vector<bool> omit;
+  };
+
+  struct TableDescriptor {
+    Table::Factory factory;
+    const TraceStorage* storage = nullptr;
+    std::string name;
+    sqlite3_module module = {};
+  };
+
+  Table();
+
+  // Called by derived classes to register themselves with the SQLite db.
+  // |read_write| specifies whether the table can also be written to.
+  // |requires_args| should be true if the table requires arguments in order to
+  // be instantiated.
+  // Note: this function is inlined here because we use the TTable template to
+  // devirtualise the function calls.
+  template <typename TTable>
+  static void Register(sqlite3* db,
+                       const TraceStorage* storage,
+                       const std::string& table_name,
+                       bool read_write = false,
+                       bool requires_args = false) {
+    using TCursor = typename TTable::Cursor;
+
+    std::unique_ptr<TableDescriptor> desc(new TableDescriptor());
+    desc->storage = storage;
+    desc->factory = GetFactory<TTable>();
+    desc->name = table_name;
+    sqlite3_module* module = &desc->module;
+    memset(module, 0, sizeof(*module));
+
+    auto create_fn = [](sqlite3* xdb, void* arg, int argc,
+                        const char* const* argv, sqlite3_vtab** tab, char**) {
+      const TableDescriptor* xdesc = static_cast<const TableDescriptor*>(arg);
+      auto table = xdesc->factory(xdb, xdesc->storage);
+      table->name_ = xdesc->name;
+
+      auto opt_schema = table->Init(argc, argv);
+      if (!opt_schema.has_value()) {
+        PERFETTO_ELOG("Failed to create schema (table %s)",
+                      xdesc->name.c_str());
+        return SQLITE_ERROR;
+      }
+
+      const auto& schema = opt_schema.value();
+      auto create_stmt = schema.ToCreateTableStmt();
+      PERFETTO_DLOG("Create table statement: %s", create_stmt.c_str());
+
+      int res = sqlite3_declare_vtab(xdb, create_stmt.c_str());
+      if (res != SQLITE_OK)
+        return res;
+
+      // Freed in xDisconnect().
+      table->schema_ = std::move(schema);
+      *tab = table.release();
+
+      return SQLITE_OK;
+    };
+    auto destroy_fn = [](sqlite3_vtab* t) {
+      delete static_cast<TTable*>(t);
+      return SQLITE_OK;
+    };
+
+    module->xCreate = create_fn;
+    module->xConnect = create_fn;
+    module->xDisconnect = destroy_fn;
+    module->xDestroy = destroy_fn;
+    module->xOpen = [](sqlite3_vtab* t, sqlite3_vtab_cursor** c) {
+      return static_cast<TTable*>(t)->OpenInternal(c);
+    };
+    module->xClose = [](sqlite3_vtab_cursor* c) {
+      delete static_cast<TCursor*>(c);
+      return SQLITE_OK;
+    };
+    module->xBestIndex = [](sqlite3_vtab* t, sqlite3_index_info* i) {
+      return static_cast<TTable*>(t)->BestIndexInternal(i);
+    };
+    module->xFilter = [](sqlite3_vtab_cursor* c, int i, const char* s, int a,
+                         sqlite3_value** v) {
+      const auto& qc =
+          static_cast<Cursor*>(c)->table_->ParseConstraints(i, s, a);
+      return static_cast<TCursor*>(c)->Filter(qc, v);
+    };
+    module->xNext = [](sqlite3_vtab_cursor* c) {
+      return static_cast<TCursor*>(c)->Next();
+    };
+    module->xEof = [](sqlite3_vtab_cursor* c) {
+      return static_cast<TCursor*>(c)->Eof();
+    };
+    module->xColumn = [](sqlite3_vtab_cursor* c, sqlite3_context* a, int b) {
+      return static_cast<TCursor*>(c)->Column(a, b);
+    };
+    module->xRowid = [](sqlite3_vtab_cursor* c, sqlite3_int64* r) {
+      return static_cast<TCursor*>(c)->RowId(r);
+    };
+    module->xFindFunction =
+        [](sqlite3_vtab* t, int, const char* name,
+           void (**fn)(sqlite3_context*, int, sqlite3_value**), void** args) {
+          return static_cast<TTable*>(t)->FindFunction(name, fn, args);
+        };
+
+    if (read_write) {
+      module->xUpdate = [](sqlite3_vtab* t, int a, sqlite3_value** v,
+                           sqlite3_int64* r) {
+        return static_cast<TTable*>(t)->Update(a, v, r);
+      };
+    }
+
+    int res = sqlite3_create_module_v2(
+        db, table_name.c_str(), module, desc.release(),
+        [](void* arg) { delete static_cast<TableDescriptor*>(arg); });
+    PERFETTO_CHECK(res == SQLITE_OK);
+
+    // Register virtual tables into an internal 'perfetto_tables' table. This is
+    // used for iterating through all the tables during a database export. Note
+    // that virtual tables requiring arguments aren't registered because they
+    // can't be automatically instantiated for exporting.
+    if (!requires_args) {
+      char* insert_sql = sqlite3_mprintf(
+          "INSERT INTO perfetto_tables(name) VALUES('%q')", table_name.c_str());
+      char* error = nullptr;
+      sqlite3_exec(db, insert_sql, 0, 0, &error);
+      sqlite3_free(insert_sql);
+      if (error) {
+        PERFETTO_ELOG("Error registering table: %s", error);
+        sqlite3_free(error);
+      }
+    }
+  }
+
+  // Methods to be implemented by derived table classes.
+  virtual base::Optional<Schema> Init(int argc, const char* const* argv) = 0;
+  virtual std::unique_ptr<Cursor> CreateCursor() = 0;
+  virtual int BestIndex(const QueryConstraints& qc, BestIndexInfo* info) = 0;
+
+  // Optional metods to implement.
+  using FindFunctionFn = void (**)(sqlite3_context*, int, sqlite3_value**);
+  virtual int FindFunction(const char* name, FindFunctionFn fn, void** args);
+
+  // At registration time, the function should also pass true for |read_write|.
+  virtual int Update(int, sqlite3_value**, sqlite3_int64*);
+
+  void SetErrorMessage(char* error) {
+    sqlite3_free(zErrMsg);
+    zErrMsg = error;
+  }
+
+  const Schema& schema() const { return schema_; }
+  const std::string& name() const { return name_; }
+
+ private:
+  template <typename TableType>
+  static Factory GetFactory() {
+    return [](sqlite3* db, const TraceStorage* storage) {
+      return std::unique_ptr<Table>(new TableType(db, storage));
+    };
+  }
+
+  static void RegisterInternal(sqlite3* db,
+                               const TraceStorage*,
+                               const std::string& name,
+                               bool read_write,
+                               bool requires_args,
+                               Factory);
+
+  const QueryConstraints& ParseConstraints(int idxNum,
+                                           const char* idxStr,
+                                           int argc);
+
+  // Overriden functions from sqlite3_vtab.
+  int OpenInternal(sqlite3_vtab_cursor**);
+  int BestIndexInternal(sqlite3_index_info*);
+
+  Table(const Table&) = delete;
+  Table& operator=(const Table&) = delete;
+
+  std::string name_;
+  Schema schema_;
+
+  QueryConstraints qc_cache_;
+  int qc_hash_ = 0;
+  int best_index_num_ = 0;
+};
+
+}  // namespace trace_processor
+}  // namespace perfetto
+
+#endif  // SRC_TRACE_PROCESSOR_TABLE_H_
diff --git a/src/trace_processor/tables/BUILD.gn b/src/trace_processor/tables/BUILD.gn
deleted file mode 100644
index 10f5289..0000000
--- a/src/trace_processor/tables/BUILD.gn
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../../gn/test.gni")
-
-source_set("tables") {
-  sources = [
-    "macros.h",
-    "macros_internal.h",
-    "profiler_tables.h",
-    "slice_tables.h",
-    "track_tables.h",
-  ]
-  deps = [
-    "..:common",
-    "../../../gn:default_deps",
-    "../db:lib",
-  ]
-}
-
-source_set("unittests") {
-  testonly = true
-  sources = [
-    "macros_unittest.cc",
-  ]
-  deps = [
-    ":tables",
-    "../../../gn:default_deps",
-    "../../../gn:gtest_and_gmock",
-  ]
-}
-
-if (enable_perfetto_benchmarks) {
-  source_set("benchmarks") {
-    testonly = true
-    deps = [
-      ":tables",
-      "../../../gn:benchmark",
-      "../../../gn:default_deps",
-    ]
-    sources = [
-      "macros_benchmark.cc",
-    ]
-  }
-}
diff --git a/src/trace_processor/tables/macros.h b/src/trace_processor/tables/macros.h
deleted file mode 100644
index a085066..0000000
--- a/src/trace_processor/tables/macros.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_TABLES_MACROS_H_
-#define SRC_TRACE_PROCESSOR_TABLES_MACROS_H_
-
-#include "src/trace_processor/tables/macros_internal.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Usage of the below macros
-// These macros have two different invocation patterns depending on whether you
-// are defining a root table or a derived table (see below for definitions and
-// examples). If you're not sure which one you need, you probably want a derived
-// table.
-//
-// Root tables
-// Root tables act as the ultimate parent of a heirarcy of tables. All rows of
-// child tables will be some subset of rows in the parent. Real world examples
-// of root tables include EventTable and TrackTable.
-//
-// All root tables implicitly contain an 'id' column which contains the row
-// index for each row in the table.
-//
-// Suppose we want to define EventTable with columns 'ts' and 'arg_set_id'.
-//
-// Then we would invoke the macro as follows:
-// #define PERFETTO_TP_EVENT_TABLE_DEF(NAME, PARENT, C)
-//   NAME(EventTable, "event")
-//   PERFETTO_TP_ROOT_TABLE(PARENT, C)
-//   C(int64_t, ts, Column::kSorted)
-//   C(uint32_t, arg_set_id)
-// PERFETTO_TP_TABLE(PERFETTO_TP_EVENT_TABLE_DEF);
-//
-// Note the call to PERFETTO_TP_ROOT_TABLE; this macro (defined below) should
-// be called by root tables passing the PARENT and C and allows for correct type
-// checking of root tables.
-//
-// Derived tables
-// Suppose we want to derive a table called SliceTable which inherits all
-// columns from EventTable (with EventTable's definition macro being
-// PERFETTO_TP_EVENT_TABLE_DEF) and columns 'dur' and 'depth'.
-//
-// Then, we would invoke the macro as follows:
-// #define PERFETTO_TP_SLICE_TABLE_DEF(NAME, PARENT, C)
-//   NAME(SliceTable, "slice")
-//   PARENT(PERFETTO_TP_EVENT_TABLE_DEF, C)
-//   C(int64_t, dur)
-//   C(uint8_t, depth)
-// PERFETTO_TP_TABLE(PERFETTO_TP_SLICE_TABLE_DEF);
-
-// Macro definition using when defining a new root table.
-//
-// This macro should be called by passing PARENT and C in root tables; this
-// allows for correct type-checking of columns.
-//
-// See the top of the file for how this should be used.
-#define PERFETTO_TP_ROOT_TABLE(PARENT, C) \
-  PARENT(PERFETTO_TP_ROOT_TABLE_PARENT_DEF, C)
-
-// The macro used to define storage backed tables.
-// See the top of the file for how this should be used.
-//
-// This macro takes one argument: the full definition of the table; the
-// definition is a function macro taking three arguments:
-// 1. NAME, a function macro taking two argument: the name of the new class
-//    being defined and the name of the table when exposed to SQLite.
-// 2. PARENT, a function macro taking two arguments: a) the definition of
-//    the parent table if this table
-//    is a root table b) C, the third parameter of the macro definition (see
-//    below). For root tables, PARENT and C are passsed to
-//    PERFETTO_TP_ROOT_TABLE instead of PARENT called directly.
-// 3. C, a function macro taking two or three parameters:
-//      a) the type of a column
-//      b) the name of a column
-//      c) (optional) the flags of the column (see Column::Flag
-//         for details).
-//    This macro should be invoked as many times as there are columns in the
-//    table with the information about them.
-#define PERFETTO_TP_TABLE(DEF)                                   \
-  PERFETTO_TP_TABLE_INTERNAL(                                    \
-      PERFETTO_TP_TABLE_NAME(DEF), PERFETTO_TP_TABLE_CLASS(DEF), \
-      PERFETTO_TP_TABLE_CLASS(PERFETTO_TP_PARENT_DEF(DEF)), DEF)
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_TABLES_MACROS_H_
diff --git a/src/trace_processor/tables/macros_benchmark.cc b/src/trace_processor/tables/macros_benchmark.cc
deleted file mode 100644
index 9eab915..0000000
--- a/src/trace_processor/tables/macros_benchmark.cc
+++ /dev/null
@@ -1,258 +0,0 @@
-// Copyright (C) 2019 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 <random>
-
-#include <benchmark/benchmark.h>
-
-#include "src/trace_processor/tables/macros.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-#define PERFETTO_TP_ROOT_TEST_TABLE(NAME, PARENT, C) \
-  NAME(RootTestTable, "root_table")                  \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)                  \
-  C(uint32_t, root_non_null)                         \
-  C(base::Optional<uint32_t>, root_nullable)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_ROOT_TEST_TABLE);
-
-#define PERFETTO_TP_CHILD_TABLE(NAME, PARENT, C) \
-  NAME(ChildTestTable, "child_table")            \
-  PARENT(PERFETTO_TP_ROOT_TEST_TABLE, C)         \
-  C(uint32_t, child_non_null)                    \
-  C(base::Optional<uint32_t>, child_nullable)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_CHILD_TABLE);
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
-
-using perfetto::trace_processor::ChildTestTable;
-using perfetto::trace_processor::RootTestTable;
-using perfetto::trace_processor::SqlValue;
-using perfetto::trace_processor::StringPool;
-
-static void BM_TableInsert(benchmark::State& state) {
-  StringPool pool;
-  RootTestTable root(&pool, nullptr);
-
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(root.Insert({}));
-  }
-}
-BENCHMARK(BM_TableInsert);
-
-static void BM_TableIteratorChild(benchmark::State& state) {
-  StringPool pool;
-  RootTestTable root(&pool, nullptr);
-  ChildTestTable child(&pool, &root);
-
-  uint32_t size = static_cast<uint32_t>(state.range(0));
-  for (uint32_t i = 0; i < size; ++i) {
-    child.Insert({});
-    root.Insert({});
-  }
-
-  auto it = child.IterateRows();
-  for (auto _ : state) {
-    for (uint32_t i = 0; i < child.GetColumnCount(); ++i) {
-      benchmark::DoNotOptimize(it.Get(i));
-    }
-    it.Next();
-    if (!it)
-      it = child.IterateRows();
-  }
-}
-BENCHMARK(BM_TableIteratorChild)
-    ->RangeMultiplier(8)
-    ->Range(1024, 2 * 1024 * 1024);
-
-static void BM_TableFilterIdColumn(benchmark::State& state) {
-  StringPool pool;
-  RootTestTable root(&pool, nullptr);
-
-  uint32_t size = static_cast<uint32_t>(state.range(0));
-  for (uint32_t i = 0; i < size; ++i)
-    root.Insert({});
-
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(root.Filter({root.id().eq(SqlValue::Long(30))}));
-  }
-}
-BENCHMARK(BM_TableFilterIdColumn)
-    ->RangeMultiplier(8)
-    ->Range(1024, 2 * 1024 * 1024);
-
-static void BM_TableFilterRootNonNullEqMatchMany(benchmark::State& state) {
-  StringPool pool;
-  RootTestTable root(&pool, nullptr);
-
-  uint32_t size = static_cast<uint32_t>(state.range(0));
-  uint32_t partitions = size / 1024;
-
-  constexpr uint32_t kRandomSeed = 42;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-  for (uint32_t i = 0; i < size; ++i) {
-    RootTestTable::Row row(static_cast<uint32_t>(rnd_engine() % partitions));
-    root.Insert(row);
-  }
-
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(
-        root.Filter({root.root_non_null().eq(SqlValue::Long(0))}));
-  }
-}
-BENCHMARK(BM_TableFilterRootNonNullEqMatchMany)
-    ->RangeMultiplier(8)
-    ->Range(1024, 2 * 1024 * 1024);
-
-static void BM_TableFilterRootNullableEqMatchMany(benchmark::State& state) {
-  StringPool pool;
-  RootTestTable root(&pool, nullptr);
-
-  uint32_t size = static_cast<uint32_t>(state.range(0));
-  uint32_t partitions = size / 512;
-
-  constexpr uint32_t kRandomSeed = 42;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-  for (uint32_t i = 0; i < size; ++i) {
-    uint32_t value = rnd_engine() % partitions;
-
-    RootTestTable::Row row;
-    row.root_nullable = value % 2 == 0 ? perfetto::base::nullopt
-                                       : perfetto::base::make_optional(value);
-    root.Insert(row);
-  }
-
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(
-        root.Filter({root.root_nullable().eq(SqlValue::Long(1))}));
-  }
-}
-BENCHMARK(BM_TableFilterRootNullableEqMatchMany)
-    ->RangeMultiplier(8)
-    ->Range(1024, 2 * 1024 * 1024);
-
-static void BM_TableFilterChildNonNullEqMatchMany(benchmark::State& state) {
-  StringPool pool;
-  RootTestTable root(&pool, nullptr);
-  ChildTestTable child(&pool, &root);
-
-  uint32_t size = static_cast<uint32_t>(state.range(0));
-  uint32_t partitions = size / 1024;
-
-  constexpr uint32_t kRandomSeed = 42;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-  for (uint32_t i = 0; i < size; ++i) {
-    ChildTestTable::Row row;
-    row.child_non_null = static_cast<uint32_t>(rnd_engine() % partitions);
-    root.Insert({});
-    child.Insert(row);
-  }
-
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(
-        child.Filter({child.child_non_null().eq(SqlValue::Long(0))}));
-  }
-}
-BENCHMARK(BM_TableFilterChildNonNullEqMatchMany)
-    ->RangeMultiplier(8)
-    ->Range(1024, 2 * 1024 * 1024);
-
-static void BM_TableFilterChildNullableEqMatchMany(benchmark::State& state) {
-  StringPool pool;
-  RootTestTable root(&pool, nullptr);
-  ChildTestTable child(&pool, &root);
-
-  uint32_t size = static_cast<uint32_t>(state.range(0));
-  uint32_t partitions = size / 512;
-
-  constexpr uint32_t kRandomSeed = 42;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-  for (uint32_t i = 0; i < size; ++i) {
-    uint32_t value = rnd_engine() % partitions;
-
-    ChildTestTable::Row row;
-    row.child_nullable = value % 2 == 0 ? perfetto::base::nullopt
-                                        : perfetto::base::make_optional(value);
-    root.Insert({});
-    child.Insert(row);
-  }
-
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(
-        child.Filter({child.child_nullable().eq(SqlValue::Long(1))}));
-  }
-}
-BENCHMARK(BM_TableFilterChildNullableEqMatchMany)
-    ->RangeMultiplier(8)
-    ->Range(1024, 2 * 1024 * 1024);
-
-static void BM_TableFilterChildNonNullEqMatchManyInParent(
-    benchmark::State& state) {
-  StringPool pool;
-  RootTestTable root(&pool, nullptr);
-  ChildTestTable child(&pool, &root);
-
-  uint32_t size = static_cast<uint32_t>(state.range(0));
-  uint32_t partitions = size / 1024;
-
-  constexpr uint32_t kRandomSeed = 42;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-  for (uint32_t i = 0; i < size; ++i) {
-    ChildTestTable::Row row;
-    row.root_non_null = static_cast<uint32_t>(rnd_engine() % partitions);
-    root.Insert({});
-    child.Insert(row);
-  }
-
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(
-        child.Filter({child.root_non_null().eq(SqlValue::Long(0))}));
-  }
-}
-BENCHMARK(BM_TableFilterChildNonNullEqMatchManyInParent)
-    ->RangeMultiplier(8)
-    ->Range(1024, 2 * 1024 * 1024);
-
-static void BM_TableFilterChildNullableEqMatchManyInParent(
-    benchmark::State& state) {
-  StringPool pool;
-  RootTestTable root(&pool, nullptr);
-  ChildTestTable child(&pool, &root);
-
-  uint32_t size = static_cast<uint32_t>(state.range(0));
-  uint32_t partitions = size / 512;
-
-  constexpr uint32_t kRandomSeed = 42;
-  std::minstd_rand0 rnd_engine(kRandomSeed);
-  for (uint32_t i = 0; i < size; ++i) {
-    ChildTestTable::Row row;
-    row.root_nullable = static_cast<uint32_t>(rnd_engine() % partitions);
-    root.Insert({});
-    child.Insert(row);
-  }
-
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(
-        child.Filter({child.root_nullable().eq(SqlValue::Long(1))}));
-  }
-}
-BENCHMARK(BM_TableFilterChildNullableEqMatchManyInParent)
-    ->RangeMultiplier(8)
-    ->Range(1024, 2 * 1024 * 1024);
diff --git a/src/trace_processor/tables/macros_internal.h b/src/trace_processor/tables/macros_internal.h
deleted file mode 100644
index 4059afa..0000000
--- a/src/trace_processor/tables/macros_internal.h
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_TABLES_MACROS_INTERNAL_H_
-#define SRC_TRACE_PROCESSOR_TABLES_MACROS_INTERNAL_H_
-
-#include <type_traits>
-
-#include "src/trace_processor/db/table.h"
-#include "src/trace_processor/db/typed_column.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace macros_internal {
-
-// We define this class to allow the table macro below to compile without
-// needing templates; in reality none of the methods will be called because the
-// pointer to this class will always be null.
-class RootParentTable : public Table {
- public:
-  struct Row {
-   public:
-    Row(std::nullptr_t) {}
-
-    const char* type() const { return type_; }
-
-   protected:
-    const char* type_ = nullptr;
-  };
-  uint32_t Insert(const Row&) { PERFETTO_FATAL("Should not be called"); }
-};
-
-// The parent class for all macro generated tables.
-// This class is used to extract common code from the macro tables to reduce
-// code size.
-class MacroTable : public Table {
- public:
-  MacroTable(const char* name, StringPool* pool, Table* parent)
-      : Table(pool, parent), name_(name), parent_(parent) {
-    row_maps_.emplace_back();
-    if (!parent) {
-      columns_.emplace_back(
-          Column::IdColumn(this, static_cast<uint32_t>(columns_.size()),
-                           static_cast<uint32_t>(row_maps_.size()) - 1));
-      columns_.emplace_back(
-          Column("type", &type_, Column::kNoFlag, this,
-                 static_cast<uint32_t>(columns_.size()),
-                 static_cast<uint32_t>(row_maps_.size()) - 1));
-    }
-  }
-
-  const char* table_name() const { return name_; }
-
- protected:
-  void UpdateRowMapsAfterParentInsert() {
-    if (parent_ != nullptr) {
-      // If there is a parent table, add the last inserted row in each of the
-      // parent row maps to the corresponding row map in the child.
-      for (uint32_t i = 0; i < parent_->row_maps().size(); ++i) {
-        const RowMap& parent_rm = parent_->row_maps()[i];
-        row_maps_[i].Insert(parent_rm.Get(parent_rm.size() - 1));
-      }
-    }
-    // Also add the index of the new row to the identity row map and increment
-    // the size.
-    row_maps_.back().Insert(size_++);
-  }
-
-  // Stores the most specific "derived" type of this row in the table.
-  //
-  // For example, suppose a row is inserted into the gpu_slice table. This will
-  // also cause a row to be inserted into the slice table. For users querying
-  // the slice table, they will want to know the "real" type of this slice (i.e.
-  // they will want to see that the type is gpu_slice). This sparse vector
-  // stores precisely the real type.
-  //
-  // Only relevant for parentless tables. Will be empty and unreferenced by
-  // tables with parents.
-  SparseVector<StringPool::Id> type_;
-
- private:
-  const char* name_ = nullptr;
-  Table* parent_ = nullptr;
-};
-
-}  // namespace macros_internal
-
-// Basic helper macros.
-#define PERFETTO_TP_NOOP(...)
-
-// Gets the class name from a table definition.
-#define PERFETTO_TP_EXTRACT_TABLE_CLASS(class_name, ...) class_name
-#define PERFETTO_TP_TABLE_CLASS(DEF) \
-  DEF(PERFETTO_TP_EXTRACT_TABLE_CLASS, PERFETTO_TP_NOOP, PERFETTO_TP_NOOP)
-
-// Gets the table name from the table definition.
-#define PERFETTO_TP_EXTRACT_TABLE_NAME(_, table_name) table_name
-#define PERFETTO_TP_TABLE_NAME(DEF) \
-  DEF(PERFETTO_TP_EXTRACT_TABLE_NAME, PERFETTO_TP_NOOP, PERFETTO_TP_NOOP)
-
-// Gets the parent definition from a table definition.
-#define PERFETTO_TP_EXTRACT_PARENT_DEF(PARENT_DEF, _) PARENT_DEF
-#define PERFETTO_TP_PARENT_DEF(DEF) \
-  DEF(PERFETTO_TP_NOOP, PERFETTO_TP_EXTRACT_PARENT_DEF, PERFETTO_TP_NOOP)
-
-// Invokes FN on each column in the definition of the table. We define a
-// recursive macro as we need to walk up the hierarchy until we hit the root.
-// Currently, we hardcode 5 levels but this can be increased as necessary.
-#define PERFETTO_TP_ALL_COLUMNS_0(DEF, arg) \
-  static_assert(false, "Macro recursion depth exceeded");
-#define PERFETTO_TP_ALL_COLUMNS_1(DEF, arg) \
-  DEF(PERFETTO_TP_NOOP, PERFETTO_TP_ALL_COLUMNS_0, arg)
-#define PERFETTO_TP_ALL_COLUMNS_2(DEF, arg) \
-  DEF(PERFETTO_TP_NOOP, PERFETTO_TP_ALL_COLUMNS_1, arg)
-#define PERFETTO_TP_ALL_COLUMNS_3(DEF, arg) \
-  DEF(PERFETTO_TP_NOOP, PERFETTO_TP_ALL_COLUMNS_2, arg)
-#define PERFETTO_TP_ALL_COLUMNS_4(DEF, arg) \
-  DEF(PERFETTO_TP_NOOP, PERFETTO_TP_ALL_COLUMNS_3, arg)
-#define PERFETTO_TP_ALL_COLUMNS(DEF, arg) \
-  DEF(PERFETTO_TP_NOOP, PERFETTO_TP_ALL_COLUMNS_4, arg)
-
-// Invokes FN on each column in the table definition.
-#define PERFETTO_TP_TABLE_COLUMNS(DEF, FN) \
-  DEF(PERFETTO_TP_NOOP, PERFETTO_TP_NOOP, FN)
-
-// Invokes FN on each column in every ancestor of the table.
-#define PERFETTO_TP_PARENT_COLUMNS(DEF, FN) \
-  PERFETTO_TP_ALL_COLUMNS(PERFETTO_TP_PARENT_DEF(DEF), FN)
-
-// Basic macros for extracting column info from a schema.
-#define PERFETTO_TP_NAME_COMMA(type, name, ...) name,
-#define PERFETTO_TP_TYPE_NAME_COMMA(type, name, ...) type name,
-
-// Constructor parameters of Table::Row.
-// We name this name_c to avoid a clash with the field names of
-// Table::Row.
-#define PERFETTO_TP_ROW_CONSTRUCTOR(type, name, ...) type name##_c = {},
-
-// Constructor parameters for parent of Row.
-#define PERFETTO_TP_PARENT_ROW_CONSTRUCTOR(type, name, ...) name##_c,
-
-// Initializes the members of Table::Row.
-#define PERFETTO_TP_ROW_INITIALIZER(type, name, ...) name = name##_c;
-
-// Defines the variable in Table::Row.
-#define PERFETTO_TP_ROW_DEFINITION(type, name, ...) type name = {};
-
-// Used to generate an equality implementation on Table::Row.
-#define PERFETTO_TP_ROW_EQUALS(type, name, ...) other.name == name&&
-
-// Defines the parent row field in Insert.
-#define PERFETTO_TP_PARENT_ROW_INSERT(type, name, ...) row.name,
-
-// Defines the member variable in the Table.
-#define PERFETTO_TP_TABLE_MEMBER(type, name, ...) \
-  SparseVector<TypedColumn<type>::StoredType> name##_;
-
-// Constructs the column in the Table constructor when flags are specified.
-#define PERFETTO_TP_TABLE_CONSTRUCTOR_COLUMN_FLAGS(type, name, flags)          \
-  columns_.emplace_back(                                                       \
-      #name, &name##_,                                                         \
-      static_cast<uint32_t>(flags) | TypedColumn<type>::default_flags(), this, \
-      columns_.size(), row_maps_.size() - 1);
-
-// Constructs the column in the Table constructor when no flags are specified.
-#define PERFETTO_TP_TABLE_CONSTRUCTOR_COLUMN_NO_FLAGS(type, name)            \
-  columns_.emplace_back(#name, &name##_, TypedColumn<type>::default_flags(), \
-                        this, columns_.size(), row_maps_.size() - 1);
-
-// Chooses between the flag and no-flag variant based on the whether there
-// are two or three arguments.
-#define PERFETTO_TP_TABLE_CONSTRUCTOR_COLUMN_CHOOSER(type, name, maybe_flags, \
-                                                     fn, ...)                 \
-  fn
-
-// Invokes the chosen column constructor by passing the given args.
-#define PERFETTO_TP_TABLE_CONSTRUCTOR_COLUMN(...)              \
-  PERFETTO_TP_TABLE_CONSTRUCTOR_COLUMN_CHOOSER(                \
-      __VA_ARGS__, PERFETTO_TP_TABLE_CONSTRUCTOR_COLUMN_FLAGS, \
-      PERFETTO_TP_TABLE_CONSTRUCTOR_COLUMN_NO_FLAGS)           \
-  (__VA_ARGS__)
-
-// Inserts the value into the corresponding column
-#define PERFETTO_TP_COLUMN_APPEND(type, name, ...) \
-  mutable_##name()->Append(std::move(row.name));
-
-// Defines the accessors for a column.
-#define PERFETTO_TP_TABLE_COL_ACCESSOR(type, name, ...)       \
-  const TypedColumn<type>& name() const {                     \
-    return static_cast<const TypedColumn<type>&>(             \
-        columns_[static_cast<uint32_t>(ColumnIndex::name)]);  \
-  }                                                           \
-                                                              \
-  TypedColumn<type>* mutable_##name() {                       \
-    return static_cast<TypedColumn<type>*>(                   \
-        &columns_[static_cast<uint32_t>(ColumnIndex::name)]); \
-  }
-
-// Definition used as the parent of root tables.
-#define PERFETTO_TP_ROOT_TABLE_PARENT_DEF(NAME, PARENT, C) \
-  NAME(macros_internal::RootParentTable, "root")
-
-// For more general documentation, see PERFETTO_TP_TABLE in macros.h.
-#define PERFETTO_TP_TABLE_INTERNAL(table_name, class_name, parent_class_name, \
-                                   DEF)                                       \
-  class class_name : public macros_internal::MacroTable {                     \
-   public:                                                                    \
-    struct Row : parent_class_name::Row {                                     \
-      /*                                                                      \
-       * Expands to Row(col_type1 col1_c, base::Optional<col_type2> col2_c,   \
-       * ...)                                                                 \
-       */                                                                     \
-      Row(PERFETTO_TP_ALL_COLUMNS(DEF, PERFETTO_TP_ROW_CONSTRUCTOR)           \
-              std::nullptr_t = nullptr)                                       \
-          : parent_class_name::Row(PERFETTO_TP_PARENT_COLUMNS(                \
-                DEF,                                                          \
-                PERFETTO_TP_PARENT_ROW_CONSTRUCTOR) nullptr) {                \
-        type_ = table_name;                                                   \
-                                                                              \
-        /* Expands to                                                         \
-         * col1 = col1_c;                                                     \
-         * col2 = col2_c;                                                     \
-         * ...                                                                \
-         */                                                                   \
-        PERFETTO_TP_TABLE_COLUMNS(DEF, PERFETTO_TP_ROW_INITIALIZER)           \
-      }                                                                       \
-                                                                              \
-      bool operator==(const class_name::Row& other) const {                   \
-        return PERFETTO_TP_TABLE_COLUMNS(DEF, PERFETTO_TP_ROW_EQUALS) true;   \
-      }                                                                       \
-                                                                              \
-      /* Expands to                                                           \
-       * col_type1 col1 = {};                                                 \
-       * base::Optional<col_type2> col2 = {};                                 \
-       * ...                                                                  \
-       */                                                                     \
-      PERFETTO_TP_TABLE_COLUMNS(DEF, PERFETTO_TP_ROW_DEFINITION)              \
-    };                                                                        \
-                                                                              \
-    class_name(StringPool* pool, parent_class_name* parent)                   \
-        : macros_internal::MacroTable(table_name, pool, parent),              \
-          parent_(parent) {                                                   \
-      /* Expands to                                                           \
-       * columns_.emplace_back("col1", col1_, Column::kNoFlag, this,          \
-       *                        columns_.size(), row_maps_.size() - 1);       \
-       * columns_.emplace_back("col2", col2_, Column::kNoFlag, this,          \
-       *                       columns_.size(), row_maps_.size() - 1);        \
-       * ...                                                                  \
-       */                                                                     \
-      PERFETTO_TP_TABLE_COLUMNS(DEF, PERFETTO_TP_TABLE_CONSTRUCTOR_COLUMN);   \
-    }                                                                         \
-                                                                              \
-    uint32_t Insert(const Row& row) {                                         \
-      uint32_t id;                                                            \
-      if (parent_ == nullptr) {                                               \
-        id = size();                                                          \
-        type_.Append(string_pool_->InternString(row.type()));                 \
-      } else {                                                                \
-        id = parent_->Insert(row);                                            \
-      }                                                                       \
-      UpdateRowMapsAfterParentInsert();                                       \
-                                                                              \
-      /* Expands to                                                           \
-       * col1_.Append(row.col1);                                              \
-       * col2_.Append(row.col2);                                              \
-       * ...                                                                  \
-       */                                                                     \
-      PERFETTO_TP_TABLE_COLUMNS(DEF, PERFETTO_TP_COLUMN_APPEND);              \
-      return id;                                                              \
-    }                                                                         \
-                                                                              \
-    const Column& id() const {                                                \
-      return columns_[static_cast<uint32_t>(ColumnIndex::id)];                \
-    }                                                                         \
-                                                                              \
-    const TypedColumn<StringPool::Id>& type() const {                         \
-      return static_cast<const TypedColumn<StringPool::Id>&>(                 \
-          columns_[static_cast<uint32_t>(ColumnIndex::type)]);                \
-    }                                                                         \
-                                                                              \
-    /* Expands to                                                             \
-     * const TypedColumn<col1_type>& col1() { return col1_; }                 \
-     * TypedColumn<col1_type>* mutable_col1() { return &col1_; }              \
-     * const TypedColumn<col2_type>& col2() { return col2_; }                 \
-     * TypedColumn<col2_type>* mutable_col2() { return &col2_; }              \
-     * ...                                                                    \
-     */                                                                       \
-    PERFETTO_TP_ALL_COLUMNS(DEF, PERFETTO_TP_TABLE_COL_ACCESSOR)              \
-                                                                              \
-   private:                                                                   \
-    enum class ColumnIndex : uint32_t {                                       \
-      id,                                                                     \
-      type, /* Expands to col1, col2, ... */                                  \
-      PERFETTO_TP_ALL_COLUMNS(DEF, PERFETTO_TP_NAME_COMMA) kNumCols           \
-    };                                                                        \
-                                                                              \
-    parent_class_name* parent_;                                               \
-                                                                              \
-    /* Expands to                                                             \
-     * SparseVector<col1_type> col1_;                                         \
-     * SparseVector<col2_type> col2_;                                         \
-     * ...                                                                    \
-     */                                                                       \
-    PERFETTO_TP_TABLE_COLUMNS(DEF, PERFETTO_TP_TABLE_MEMBER)                  \
-  }
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_TABLES_MACROS_INTERNAL_H_
diff --git a/src/trace_processor/tables/macros_unittest.cc b/src/trace_processor/tables/macros_unittest.cc
deleted file mode 100644
index c270aea..0000000
--- a/src/trace_processor/tables/macros_unittest.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/tables/macros.h"
-
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-#define PERFETTO_TP_TEST_EVENT_TABLE_DEF(NAME, PARENT, C) \
-  NAME(TestEventTable, "event")                           \
-  PARENT(PERFETTO_TP_ROOT_TABLE_PARENT_DEF, C)            \
-  C(int64_t, ts)                                          \
-  C(int64_t, arg_set_id)
-PERFETTO_TP_TABLE(PERFETTO_TP_TEST_EVENT_TABLE_DEF);
-
-#define PERFETTO_TP_TEST_SLICE_TABLE_DEF(NAME, PARENT, C) \
-  NAME(TestSliceTable, "slice")                           \
-  PARENT(PERFETTO_TP_TEST_EVENT_TABLE_DEF, C)             \
-  C(base::Optional<int64_t>, dur)                         \
-  C(int64_t, depth)
-PERFETTO_TP_TABLE(PERFETTO_TP_TEST_SLICE_TABLE_DEF);
-
-#define PERFETTO_TP_TEST_CPU_SLICE_TABLE_DEF(NAME, PARENT, C) \
-  NAME(TestCpuSliceTable, "cpu_slice")                        \
-  PARENT(PERFETTO_TP_TEST_SLICE_TABLE_DEF, C)                 \
-  C(int64_t, cpu)                                             \
-  C(int64_t, priority)                                        \
-  C(StringPool::Id, end_state)
-PERFETTO_TP_TABLE(PERFETTO_TP_TEST_CPU_SLICE_TABLE_DEF);
-
-TEST(TableMacrosUnittest, Name) {
-  StringPool pool;
-  TestEventTable event(&pool, nullptr);
-  TestSliceTable slice(&pool, &event);
-  TestCpuSliceTable cpu_slice(&pool, &slice);
-
-  ASSERT_EQ(event.table_name(), "event");
-  ASSERT_EQ(slice.table_name(), "slice");
-  ASSERT_EQ(cpu_slice.table_name(), "cpu_slice");
-}
-
-TEST(TableMacrosUnittest, InsertParent) {
-  StringPool pool;
-  TestEventTable event(&pool, nullptr);
-  TestSliceTable slice(&pool, &event);
-
-  uint32_t id = event.Insert(TestEventTable::Row(100, 0));
-  ASSERT_EQ(id, 0u);
-  ASSERT_EQ(event.type().GetString(0), "event");
-  ASSERT_EQ(event.ts()[0], 100);
-  ASSERT_EQ(event.arg_set_id()[0], 0);
-
-  id = slice.Insert(TestSliceTable::Row(200, 123, 10, 0));
-  ASSERT_EQ(id, 1u);
-
-  ASSERT_EQ(event.type().GetString(1), "slice");
-  ASSERT_EQ(event.ts()[1], 200);
-  ASSERT_EQ(event.arg_set_id()[1], 123);
-  ASSERT_EQ(slice.type().GetString(0), "slice");
-  ASSERT_EQ(slice.ts()[0], 200);
-  ASSERT_EQ(slice.arg_set_id()[0], 123);
-  ASSERT_EQ(slice.dur()[0], 10);
-  ASSERT_EQ(slice.depth()[0], 0);
-
-  id = slice.Insert(TestSliceTable::Row(210, 456, base::nullopt, 0));
-  ASSERT_EQ(id, 2u);
-
-  ASSERT_EQ(event.type().GetString(2), "slice");
-  ASSERT_EQ(event.ts()[2], 210);
-  ASSERT_EQ(event.arg_set_id()[2], 456);
-  ASSERT_EQ(slice.type().GetString(1), "slice");
-  ASSERT_EQ(slice.ts()[1], 210);
-  ASSERT_EQ(slice.arg_set_id()[1], 456);
-  ASSERT_EQ(slice.dur()[1], base::nullopt);
-  ASSERT_EQ(slice.depth()[1], 0);
-}
-
-TEST(TableMacrosUnittest, InsertChild) {
-  StringPool pool;
-  TestEventTable event(&pool, nullptr);
-  TestSliceTable slice(&pool, &event);
-  TestCpuSliceTable cpu_slice(&pool, &slice);
-
-  event.Insert(TestEventTable::Row(100, 0));
-  slice.Insert(TestSliceTable::Row(200, 123, 10, 0));
-
-  auto reason = pool.InternString("R");
-  uint32_t id =
-      cpu_slice.Insert(TestCpuSliceTable::Row(205, 456, 5, 1, 4, 1024, reason));
-  ASSERT_EQ(id, 2u);
-  ASSERT_EQ(event.type().GetString(2), "cpu_slice");
-  ASSERT_EQ(event.ts()[2], 205);
-  ASSERT_EQ(event.arg_set_id()[2], 456);
-
-  ASSERT_EQ(slice.type().GetString(1), "cpu_slice");
-  ASSERT_EQ(slice.ts()[1], 205);
-  ASSERT_EQ(slice.arg_set_id()[1], 456);
-  ASSERT_EQ(slice.dur()[1], 5);
-  ASSERT_EQ(slice.depth()[1], 1);
-
-  ASSERT_EQ(cpu_slice.type().GetString(0), "cpu_slice");
-  ASSERT_EQ(cpu_slice.ts()[0], 205);
-  ASSERT_EQ(cpu_slice.arg_set_id()[0], 456);
-  ASSERT_EQ(cpu_slice.dur()[0], 5);
-  ASSERT_EQ(cpu_slice.depth()[0], 1);
-  ASSERT_EQ(cpu_slice.cpu()[0], 4);
-  ASSERT_EQ(cpu_slice.priority()[0], 1024);
-  ASSERT_EQ(cpu_slice.end_state()[0], reason);
-  ASSERT_EQ(cpu_slice.end_state().GetString(0), "R");
-}
-
-}  // namespace
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/tables/profiler_tables.h b/src/trace_processor/tables/profiler_tables.h
deleted file mode 100644
index 84ebd76..0000000
--- a/src/trace_processor/tables/profiler_tables.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_TABLES_PROFILER_TABLES_H_
-#define SRC_TRACE_PROCESSOR_TABLES_PROFILER_TABLES_H_
-
-#include "src/trace_processor/tables/macros.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace tables {
-
-#define PERFETTO_TP_STACK_PROFILE_CALLSITE_DEF(NAME, PARENT, C) \
-  NAME(StackProfileCallsiteTable, "stack_profile_callsite")     \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)                             \
-  C(int64_t, depth)                                             \
-  C(int64_t, parent_id)                                         \
-  C(int64_t, frame_id)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_STACK_PROFILE_CALLSITE_DEF);
-
-#define PERFETTO_TP_SYMBOL_DEF(NAME, PARENT, C) \
-  NAME(SymbolTable, "stack_profile_symbol")     \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)             \
-  C(uint32_t, symbol_set_id)                    \
-  C(StringPool::Id, name)                       \
-  C(StringPool::Id, source_file)                \
-  C(uint32_t, line_number)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_SYMBOL_DEF);
-
-#define PERFETTO_TP_HEAP_GRAPH_OBJECT_DEF(NAME, PARENT, C) \
-  NAME(HeapGraphObjectTable, "heap_graph_object")          \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)                        \
-  C(int64_t, upid)                                         \
-  C(int64_t, graph_sample_ts)                              \
-  C(int64_t, object_id)                                    \
-  C(int64_t, self_size)                                    \
-  C(int64_t, retained_size)                                \
-  C(int64_t, unique_retained_size)                         \
-  C(int64_t, reference_set_id)                             \
-  C(int32_t, reachable)                                    \
-  C(StringPool::Id, type_name)                             \
-  C(base::Optional<StringPool::Id>, root_type)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_HEAP_GRAPH_OBJECT_DEF);
-
-#define PERFETTO_TP_HEAP_GRAPH_REFERENCE_DEF(NAME, PARENT, C) \
-  NAME(HeapGraphReferenceTable, "heap_graph_reference")       \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)                           \
-  C(int64_t, reference_set_id)                                \
-  C(int64_t, owner_id)                                        \
-  C(int64_t, owned_id)                                        \
-  C(StringPool::Id, field_name)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_HEAP_GRAPH_REFERENCE_DEF);
-
-#define PERFETTO_TP_VULKAN_MEMORY_ALLOCATIONS_DEF(NAME, PARENT, C) \
-  NAME(VulkanMemoryAllocationsTable, "vulkan_memory_allocations")  \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)                                \
-  C(StringPool::Id, source)                                        \
-  C(StringPool::Id, operation)                                     \
-  C(int64_t, timestamp)                                            \
-  C(base::Optional<uint32_t>, upid)                                \
-  C(base::Optional<int64_t>, device)                               \
-  C(base::Optional<int64_t>, device_memory)                        \
-  C(base::Optional<uint32_t>, heap)                                \
-  C(base::Optional<StringPool::Id>, function_name)                 \
-  C(base::Optional<int64_t>, object_handle)                        \
-  C(base::Optional<int64_t>, memory_address)                       \
-  C(base::Optional<int64_t>, memory_size)                          \
-  C(base::Optional<uint32_t>, arg_set_id)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_VULKAN_MEMORY_ALLOCATIONS_DEF);
-
-}  // namespace tables
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_TABLES_PROFILER_TABLES_H_
diff --git a/src/trace_processor/tables/slice_tables.h b/src/trace_processor/tables/slice_tables.h
deleted file mode 100644
index 06ca534..0000000
--- a/src/trace_processor/tables/slice_tables.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_TABLES_SLICE_TABLES_H_
-#define SRC_TRACE_PROCESSOR_TABLES_SLICE_TABLES_H_
-
-#include "src/trace_processor/tables/macros.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace tables {
-
-#define PERFETTO_TP_GPU_SLICES_DEF(NAME, PARENT, C) \
-  NAME(GpuSliceTable, "internal_gpu_slice")         \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)                 \
-  C(uint32_t, slice_id, Column::kSorted)            \
-  C(base::Optional<int64_t>, context_id)            \
-  C(base::Optional<int64_t>, render_target)         \
-  C(base::Optional<uint32_t>, frame_id)             \
-  C(base::Optional<uint32_t>, submission_id)        \
-  C(base::Optional<uint32_t>, hw_queue_id)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_GPU_SLICES_DEF);
-
-}  // namespace tables
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_TABLES_SLICE_TABLES_H_
diff --git a/src/trace_processor/tables/track_tables.h b/src/trace_processor/tables/track_tables.h
deleted file mode 100644
index 403b520..0000000
--- a/src/trace_processor/tables/track_tables.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_TABLES_TRACK_TABLES_H_
-#define SRC_TRACE_PROCESSOR_TABLES_TRACK_TABLES_H_
-
-#include "src/trace_processor/string_pool.h"
-#include "src/trace_processor/tables/macros.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace tables {
-
-#define PERFETTO_TP_TRACK_TABLE_DEF(NAME, PARENT, C) \
-  NAME(TrackTable, "track")                          \
-  PERFETTO_TP_ROOT_TABLE(PARENT, C)                  \
-  C(StringPool::Id, name)                            \
-  C(base::Optional<uint32_t>, source_arg_set_id)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_TRACK_TABLE_DEF);
-
-#define PERFETTO_TP_PROCESS_TRACK_TABLE_DEF(NAME, PARENT, C) \
-  NAME(ProcessTrackTable, "process_track")                   \
-  PARENT(PERFETTO_TP_TRACK_TABLE_DEF, C)                     \
-  C(uint32_t, upid)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_PROCESS_TRACK_TABLE_DEF);
-
-#define PERFETTO_TP_THREAD_TRACK_TABLE_DEF(NAME, PARENT, C) \
-  NAME(ThreadTrackTable, "thread_track")                    \
-  PARENT(PERFETTO_TP_TRACK_TABLE_DEF, C)                    \
-  C(uint32_t, utid)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_THREAD_TRACK_TABLE_DEF);
-
-#define PERFETTO_TP_GPU_TRACK_DEF(NAME, PARENT, C) \
-  NAME(GpuTrackTable, "gpu_track")                 \
-  PARENT(PERFETTO_TP_TRACK_TABLE_DEF, C)           \
-  C(StringPool::Id, scope)                         \
-  C(base::Optional<int64_t>, context_id)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_GPU_TRACK_DEF);
-
-#define PERFETTO_TP_COUNTER_TRACK_DEF(NAME, PARENT, C) \
-  NAME(CounterTrackTable, "counter_track")             \
-  PARENT(PERFETTO_TP_TRACK_TABLE_DEF, C)               \
-  C(int64_t, ref)                                      \
-  C(StringPool::Id, ref_type)                          \
-  C(StringPool::Id, unit)                              \
-  C(StringPool::Id, description)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_COUNTER_TRACK_DEF);
-
-#define PERFETTO_TP_THREAD_COUNTER_TRACK_DEF(NAME, PARENT, C) \
-  NAME(ThreadCounterTrackTable, "thread_counter_track")       \
-  PARENT(PERFETTO_TP_COUNTER_TRACK_DEF, C)                    \
-  C(uint32_t, utid)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_THREAD_COUNTER_TRACK_DEF);
-
-#define PERFETTO_TP_PROCESS_COUNTER_TRACK_DEF(NAME, PARENT, C) \
-  NAME(ProcessCounterTrackTable, "process_counter_track")      \
-  PARENT(PERFETTO_TP_COUNTER_TRACK_DEF, C)                     \
-  C(uint32_t, upid)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_PROCESS_COUNTER_TRACK_DEF);
-
-#define PERFETTO_TP_CPU_COUNTER_TRACK_DEF(NAME, PARENT, C) \
-  NAME(CpuCounterTrackTable, "cpu_counter_track")          \
-  PARENT(PERFETTO_TP_COUNTER_TRACK_DEF, C)                 \
-  C(uint32_t, cpu)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_CPU_COUNTER_TRACK_DEF);
-
-#define PERFETTO_TP_IRQ_COUNTER_TRACK_DEF(NAME, PARENT, C) \
-  NAME(IrqCounterTrackTable, "irq_counter_track")          \
-  PARENT(PERFETTO_TP_COUNTER_TRACK_DEF, C)                 \
-  C(int32_t, irq)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_IRQ_COUNTER_TRACK_DEF);
-
-#define PERFETTO_TP_SOFTIRQ_COUNTER_TRACK_DEF(NAME, PARENT, C) \
-  NAME(SoftirqCounterTrackTable, "softirq_counter_track")      \
-  PARENT(PERFETTO_TP_COUNTER_TRACK_DEF, C)                     \
-  C(int32_t, softirq)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_SOFTIRQ_COUNTER_TRACK_DEF);
-
-#define PERFETTO_TP_GPU_COUNTER_TRACK_DEF(NAME, PARENT, C) \
-  NAME(GpuCounterTrackTable, "gpu_counter_track")          \
-  PARENT(PERFETTO_TP_COUNTER_TRACK_DEF, C)                 \
-  C(uint32_t, gpu_id)
-
-PERFETTO_TP_TABLE(PERFETTO_TP_GPU_COUNTER_TRACK_DEF);
-
-}  // namespace tables
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_TABLES_TRACK_TABLES_H_
diff --git a/src/trace_processor/thread_table.cc b/src/trace_processor/thread_table.cc
index ba339e8..e66f565 100644
--- a/src/trace_processor/thread_table.cc
+++ b/src/trace_processor/thread_table.cc
@@ -17,8 +17,8 @@
 #include "src/trace_processor/thread_table.h"
 
 #include "perfetto/base/logging.h"
-#include "src/trace_processor/sqlite/query_constraints.h"
-#include "src/trace_processor/sqlite/sqlite_utils.h"
+#include "src/trace_processor/query_constraints.h"
+#include "src/trace_processor/sqlite_utils.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -33,26 +33,23 @@
     : storage_(storage) {}
 
 void ThreadTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
-  SqliteTable::Register<ThreadTable>(db, storage, "thread");
+  Table::Register<ThreadTable>(db, storage, "thread");
 }
 
-util::Status ThreadTable::Init(int, const char* const*, Schema* schema) {
-  *schema = Schema(
+base::Optional<Table::Schema> ThreadTable::Init(int, const char* const*) {
+  return Schema(
       {
-          SqliteTable::Column(Column::kUtid, "utid", SqlValue::Type::kLong),
-          SqliteTable::Column(Column::kUpid, "upid", SqlValue::Type::kLong),
-          SqliteTable::Column(Column::kName, "name", SqlValue::Type::kString),
-          SqliteTable::Column(Column::kTid, "tid", SqlValue::Type::kLong),
-          SqliteTable::Column(Column::kStartTs, "start_ts",
-                              SqlValue::Type::kLong),
-          SqliteTable::Column(Column::kEndTs, "end_ts", SqlValue::Type::kLong),
+          Table::Column(Column::kUtid, "utid", ColumnType::kInt),
+          Table::Column(Column::kUpid, "upid", ColumnType::kInt),
+          Table::Column(Column::kName, "name", ColumnType::kString),
+          Table::Column(Column::kTid, "tid", ColumnType::kInt),
+          Table::Column(Column::kStartTs, "start_ts", ColumnType::kLong),
       },
       {Column::kUtid});
-  return util::OkStatus();
 }
 
-std::unique_ptr<SqliteTable::Cursor> ThreadTable::CreateCursor() {
-  return std::unique_ptr<SqliteTable::Cursor>(new Cursor(this));
+std::unique_ptr<Table::Cursor> ThreadTable::CreateCursor() {
+  return std::unique_ptr<Table::Cursor>(new Cursor(this));
 }
 
 int ThreadTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
@@ -70,47 +67,44 @@
 }
 
 ThreadTable::Cursor::Cursor(ThreadTable* table)
-    : SqliteTable::Cursor(table), storage_(table->storage_), table_(table) {}
+    : Table::Cursor(table), storage_(table->storage_), table_(table) {}
 
 int ThreadTable::Cursor::Filter(const QueryConstraints& qc,
                                 sqlite3_value** argv) {
   *this = Cursor(table_);
 
-  min_ = 0;
-  max_ = static_cast<uint32_t>(storage_->thread_count());
-  desc_ = false;
-
+  min = 0;
+  max = static_cast<uint32_t>(storage_->thread_count()) - 1;
+  desc = false;
+  current = min;
   for (size_t j = 0; j < qc.constraints().size(); j++) {
     const auto& cs = qc.constraints()[j];
     if (cs.iColumn == Column::kUtid) {
       UniqueTid constraint_utid =
           static_cast<UniqueTid>(sqlite3_value_int(argv[j]));
       // Filter the range of utids that we are interested in, based on the
-      // constraints in the query. Everything between min and max (exclusive)
+      // constraints in the query. Everything between min and max (inclusive)
       // will be returned.
       if (IsOpEq(cs.op)) {
-        min_ = constraint_utid;
-        max_ = constraint_utid + 1;
+        min = constraint_utid;
+        max = constraint_utid;
       } else if (IsOpGe(cs.op) || IsOpGt(cs.op)) {
-        min_ = IsOpGt(cs.op) ? constraint_utid + 1 : constraint_utid;
+        min = IsOpGt(cs.op) ? constraint_utid + 1 : constraint_utid;
       } else if (IsOpLe(cs.op) || IsOpLt(cs.op)) {
-        max_ = IsOpLt(cs.op) ? constraint_utid : constraint_utid + 1;
+        max = IsOpLt(cs.op) ? constraint_utid - 1 : constraint_utid;
       }
     }
   }
-
   for (const auto& ob : qc.order_by()) {
     if (ob.iColumn == Column::kUtid) {
-      desc_ = ob.desc;
+      desc = ob.desc;
+      current = desc ? max : min;
     }
   }
-  index_ = 0;
-
   return SQLITE_OK;
 }
 
 int ThreadTable::Cursor::Column(sqlite3_context* context, int N) {
-  uint32_t current = desc_ ? max_ - index_ - 1 : min_ + index_;
   const auto& thread = storage_->GetThread(current);
   switch (N) {
     case Column::kUtid: {
@@ -142,14 +136,6 @@
       }
       break;
     }
-    case Column::kEndTs: {
-      if (thread.end_ns != 0) {
-        sqlite3_result_int64(context, thread.end_ns);
-      } else {
-        sqlite3_result_null(context);
-      }
-      break;
-    }
     default: {
       PERFETTO_FATAL("Unknown column %d", N);
       break;
@@ -159,12 +145,16 @@
 }
 
 int ThreadTable::Cursor::Next() {
-  ++index_;
+  if (desc) {
+    --current;
+  } else {
+    ++current;
+  }
   return SQLITE_OK;
 }
 
 int ThreadTable::Cursor::Eof() {
-  return index_ >= (max_ - min_);
+  return desc ? current < min : current > max;
 }
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/thread_table.h b/src/trace_processor/thread_table.h
index 43484d1..d8ab0b7 100644
--- a/src/trace_processor/thread_table.h
+++ b/src/trace_processor/thread_table.h
@@ -20,7 +20,7 @@
 #include <limits>
 #include <memory>
 
-#include "src/trace_processor/sqlite/sqlite_table.h"
+#include "src/trace_processor/table.h"
 #include "src/trace_processor/trace_storage.h"
 
 namespace perfetto {
@@ -28,17 +28,10 @@
 
 // The implementation of the SQLite table containing each unique process with
 // the metadata for those processes.
-class ThreadTable : public SqliteTable {
+class ThreadTable : public Table {
  public:
-  enum Column {
-    kUtid = 0,
-    kUpid = 1,
-    kName = 2,
-    kTid = 3,
-    kStartTs = 4,
-    kEndTs = 5,
-  };
-  class Cursor : public SqliteTable::Cursor {
+  enum Column { kUtid = 0, kUpid = 1, kName = 2, kTid = 3, kStartTs = 4 };
+  class Cursor : public Table::Cursor {
    public:
     Cursor(ThreadTable* table);
 
@@ -55,10 +48,10 @@
     Cursor(Cursor&&) noexcept = default;
     Cursor& operator=(Cursor&&) = default;
 
-    UniqueTid min_ = 0;
-    UniqueTid max_ = 0;
-    uint32_t index_ = 0;
-    bool desc_ = false;
+    UniqueTid min;
+    UniqueTid max;
+    UniqueTid current;
+    bool desc;
 
     const TraceStorage* storage_ = nullptr;
     ThreadTable* table_ = nullptr;
@@ -69,8 +62,8 @@
   ThreadTable(sqlite3*, const TraceStorage*);
 
   // Table implementation.
-  util::Status Init(int, const char* const*, SqliteTable::Schema*) override;
-  std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
+  base::Optional<Table::Schema> Init(int, const char* const*) override;
+  std::unique_ptr<Table::Cursor> CreateCursor() override;
   int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
 
  private:
diff --git a/src/trace_processor/thread_table_unittest.cc b/src/trace_processor/thread_table_unittest.cc
index 6d5427c..7b30c83 100644
--- a/src/trace_processor/thread_table_unittest.cc
+++ b/src/trace_processor/thread_table_unittest.cc
@@ -18,12 +18,13 @@
 
 #include "src/trace_processor/args_tracker.h"
 #include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
 #include "src/trace_processor/process_table.h"
 #include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/sqlite/scoped_db.h"
+#include "src/trace_processor/scoped_db.h"
 #include "src/trace_processor/trace_processor_context.h"
-#include "test/gtest_and_gmock.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -33,7 +34,6 @@
  public:
   ThreadTableUnittest() {
     sqlite3* db = nullptr;
-    PERFETTO_CHECK(sqlite3_initialize() == SQLITE_OK);
     PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
     db_.reset(db);
 
@@ -41,7 +41,6 @@
     context_.args_tracker.reset(new ArgsTracker(&context_));
     context_.process_tracker.reset(new ProcessTracker(&context_));
     context_.event_tracker.reset(new EventTracker(&context_));
-    context_.sched_tracker.reset(new SchedEventTracker(&context_));
 
     ThreadTable::RegisterTable(db_.get(), context_.storage.get());
     ProcessTable::RegisterTable(db_.get(), context_.storage.get());
@@ -59,6 +58,8 @@
     return reinterpret_cast<const char*>(sqlite3_column_text(*stmt_, colId));
   }
 
+  ~ThreadTableUnittest() override { context_.storage->ResetStorage(); }
+
  protected:
   TraceProcessorContext context_;
   ScopedDb db_;
@@ -73,14 +74,14 @@
   static const char kThreadName2[] = "thread2";
   int32_t prio = 1024;
 
-  context_.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1,
+  context_.event_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1,
                                           kThreadName2, prio, prev_state,
                                           /*tid=*/4, kThreadName1, prio);
-  context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
+  context_.event_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
                                           kThreadName1, prio, prev_state,
                                           /*tid=*/1, kThreadName2, prio);
 
-  context_.process_tracker->SetProcessMetadata(2, base::nullopt, "test");
+  context_.process_tracker->UpdateProcess(2, base::nullopt, "test");
   context_.process_tracker->UpdateThread(4 /*tid*/, 2 /*pid*/);
   PrepareValidStatement("SELECT utid, upid, tid, name FROM thread where tid=4");
 
@@ -101,17 +102,17 @@
   static const char kThreadName2[] = "thread2";
   int32_t prio = 1024;
 
-  context_.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1,
+  context_.event_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1,
                                           kThreadName2, prio, prev_state,
                                           /*tid=*/4, kThreadName1, prio);
-  context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
+  context_.event_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
                                           kThreadName1, prio, prev_state,
                                           /*tid=*/1, kThreadName2, prio);
-  context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 2, /*tid=*/1,
+  context_.event_tracker->PushSchedSwitch(cpu, timestamp + 2, /*tid=*/1,
                                           kThreadName2, prio, prev_state,
                                           /*tid=*/4, kThreadName1, prio);
 
-  context_.process_tracker->SetProcessMetadata(2, base::nullopt, "test");
+  context_.process_tracker->UpdateProcess(2, base::nullopt, "test");
   context_.process_tracker->UpdateThread(4 /*tid*/, 2 /*pid*/);
   context_.process_tracker->UpdateThread(1 /*tid*/, 2 /*pid*/);
   PrepareValidStatement(
@@ -134,17 +135,17 @@
   static const char kThreadName2[] = "thread2";
   int32_t prio = 1024;
 
-  context_.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1,
+  context_.event_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1,
                                           kThreadName2, prio, prev_state,
                                           /*tid=*/4, kThreadName1, prio);
-  context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
+  context_.event_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
                                           kThreadName1, prio, prev_state,
                                           /*tid=*/1, kThreadName2, prio);
 
   // Also create a process for which we haven't seen any thread.
-  context_.process_tracker->SetProcessMetadata(7, base::nullopt, "pid7");
+  context_.process_tracker->UpdateProcess(7, base::nullopt, "pid7");
 
-  context_.process_tracker->SetProcessMetadata(2, base::nullopt, "pid2");
+  context_.process_tracker->UpdateProcess(2, base::nullopt, "pid2");
   context_.process_tracker->UpdateThread(/*tid=*/4, /*pid=*/2);
 
   PrepareValidStatement(
diff --git a/src/trace_processor/timestamped_trace_piece.h b/src/trace_processor/timestamped_trace_piece.h
deleted file mode 100644
index 83b4932..0000000
--- a/src/trace_processor/timestamped_trace_piece.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_TIMESTAMPED_TRACE_PIECE_H_
-#define SRC_TRACE_PROCESSOR_TIMESTAMPED_TRACE_PIECE_H_
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/trace_processor/basic_types.h"
-#include "src/trace_processor/importers/fuchsia/fuchsia_provider_view.h"
-#include "src/trace_processor/importers/proto/packet_sequence_state.h"
-#include "src/trace_processor/trace_blob_view.h"
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/trace_storage.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON_IMPORT)
-#include <json/value.h>
-#else   // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON_IMPORT)
-// Json traces are only supported in some build configurations (standalone, UI).
-namespace Json {
-class Value {};
-}  // namespace Json
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON_IMPORT)
-
-namespace perfetto {
-namespace trace_processor {
-
-struct InlineSchedSwitch {
-  int64_t prev_state;
-  int32_t next_pid;
-  int32_t next_prio;
-  StringId next_comm;
-};
-
-struct InlineSchedWaking {
-  int32_t pid;
-  int32_t target_cpu;
-  int32_t prio;
-  StringId comm;
-};
-
-// Discriminated union of events that are cannot be easily read from the
-// mapped trace.
-struct InlineEvent {
-  enum class Type { kInvalid = 0, kSchedSwitch, kSchedWaking };
-
-  static InlineEvent SchedSwitch(InlineSchedSwitch content) {
-    InlineEvent evt;
-    evt.type = Type::kSchedSwitch;
-    evt.sched_switch = content;
-    return evt;
-  }
-
-  static InlineEvent SchedWaking(InlineSchedWaking content) {
-    InlineEvent evt;
-    evt.type = Type::kSchedWaking;
-    evt.sched_waking = content;
-    return evt;
-  }
-
-  Type type = Type::kInvalid;
-  union {
-    InlineSchedSwitch sched_switch;
-    InlineSchedWaking sched_waking;
-  };
-};
-
-// A TimestampedTracePiece is (usually a reference to) a piece of a trace that
-// is sorted by TraceSorter.
-struct TimestampedTracePiece {
-  TimestampedTracePiece(int64_t ts,
-                        uint64_t idx,
-                        TraceBlobView tbv,
-                        PacketSequenceState* sequence_state)
-      : TimestampedTracePiece(ts,
-                              /*thread_ts=*/0,
-                              /*thread_instructions=*/0,
-                              idx,
-                              std::move(tbv),
-                              /*value=*/nullptr,
-                              /*fpv=*/nullptr,
-                              /*sequence_state=*/sequence_state,
-                              InlineEvent{}) {}
-
-  TimestampedTracePiece(int64_t ts, uint64_t idx, TraceBlobView tbv)
-      : TimestampedTracePiece(ts,
-                              /*thread_ts=*/0,
-                              /*thread_instructions=*/0,
-                              idx,
-                              std::move(tbv),
-                              /*value=*/nullptr,
-                              /*fpv=*/nullptr,
-                              /*sequence_state=*/nullptr,
-                              InlineEvent{}) {}
-
-  TimestampedTracePiece(int64_t ts,
-                        uint64_t idx,
-                        std::unique_ptr<Json::Value> value)
-      : TimestampedTracePiece(ts,
-                              /*thread_ts=*/0,
-                              /*thread_instructions=*/0,
-                              idx,
-                              // TODO(dproy): Stop requiring TraceBlobView in
-                              // TimestampedTracePiece.
-                              TraceBlobView(nullptr, 0, 0),
-                              std::move(value),
-                              /*fpv=*/nullptr,
-                              /*sequence_state=*/nullptr,
-                              InlineEvent{}) {}
-
-  TimestampedTracePiece(int64_t ts,
-                        uint64_t idx,
-                        TraceBlobView tbv,
-                        std::unique_ptr<FuchsiaProviderView> fpv)
-      : TimestampedTracePiece(ts,
-                              /*thread_ts=*/0,
-                              /*thread_instructions=*/0,
-                              idx,
-                              std::move(tbv),
-                              /*value=*/nullptr,
-                              std::move(fpv),
-                              /*sequence_state=*/nullptr,
-                              InlineEvent{}) {}
-
-  TimestampedTracePiece(int64_t ts,
-                        int64_t thread_ts,
-                        int64_t thread_instructions,
-                        uint64_t idx,
-                        TraceBlobView tbv,
-                        PacketSequenceState* sequence_state)
-      : TimestampedTracePiece(ts,
-                              thread_ts,
-                              thread_instructions,
-                              idx,
-                              std::move(tbv),
-                              /*value=*/nullptr,
-                              /*fpv=*/nullptr,
-                              sequence_state,
-                              InlineEvent{}) {}
-
-  // TODO(rsavitski): each "empty" TraceBlobView created by this constructor
-  // still allocates ref-counting structures for the nonexistent memory.
-  // It's not a significant overhead, but consider making the class have a
-  // legitimate empty state.
-  TimestampedTracePiece(int64_t ts, uint64_t idx, InlineEvent inline_evt)
-      : TimestampedTracePiece(ts,
-                              /*thread_ts=*/0,
-                              /*thread_instructions=*/0,
-                              idx,
-                              TraceBlobView(nullptr, 0, 0),
-                              /*value=*/nullptr,
-                              /*fpv=*/nullptr,
-                              /*sequence_state=*/nullptr,
-                              inline_evt) {}
-
-  TimestampedTracePiece(int64_t ts,
-                        int64_t thread_ts,
-                        int64_t thread_instructions,
-                        uint64_t idx,
-                        TraceBlobView tbv,
-                        std::unique_ptr<Json::Value> value,
-                        std::unique_ptr<FuchsiaProviderView> fpv,
-                        PacketSequenceState* sequence_state,
-                        InlineEvent inline_evt)
-      : json_value(std::move(value)),
-        fuchsia_provider_view(std::move(fpv)),
-        packet_sequence_state(sequence_state),
-        packet_sequence_state_generation(
-            sequence_state ? sequence_state->current_generation() : 0),
-        timestamp(ts),
-        thread_timestamp(thread_ts),
-        thread_instruction_count(thread_instructions),
-        packet_idx_(idx),
-        blob_view(std::move(tbv)),
-        inline_event(inline_evt) {}
-
-  TimestampedTracePiece(TimestampedTracePiece&&) noexcept = default;
-  TimestampedTracePiece& operator=(TimestampedTracePiece&&) = default;
-
-  // For std::lower_bound().
-  static inline bool Compare(const TimestampedTracePiece& x, int64_t ts) {
-    return x.timestamp < ts;
-  }
-
-  // For std::sort().
-  inline bool operator<(const TimestampedTracePiece& o) const {
-    return timestamp < o.timestamp ||
-           (timestamp == o.timestamp && packet_idx_ < o.packet_idx_);
-  }
-
-  std::unique_ptr<Json::Value> json_value;
-  std::unique_ptr<FuchsiaProviderView> fuchsia_provider_view;
-  PacketSequenceState* packet_sequence_state;
-  size_t packet_sequence_state_generation;
-
-  int64_t timestamp;
-  int64_t thread_timestamp;
-  int64_t thread_instruction_count;
-  uint64_t packet_idx_;
-  TraceBlobView blob_view;
-  InlineEvent inline_event;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_TIMESTAMPED_TRACE_PIECE_H_
diff --git a/src/trace_processor/trace_database_integrationtest.cc b/src/trace_processor/trace_database_integrationtest.cc
index f845dbb..8fc2579 100644
--- a/src/trace_processor/trace_database_integrationtest.cc
+++ b/src/trace_processor/trace_database_integrationtest.cc
@@ -14,61 +14,52 @@
  * limitations under the License.
  */
 
-#include <algorithm>
 #include <map>
 #include <random>
 #include <string>
 
+#include "gtest/gtest.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/base/scoped_file.h"
 #include "perfetto/trace_processor/trace_processor.h"
 #include "src/base/test/utils.h"
-#include "src/trace_processor/importers/json/json_trace_parser.h"
-#include "test/gtest_and_gmock.h"
+#include "src/trace_processor/json_trace_parser.h"
 
 namespace perfetto {
 namespace trace_processor {
 namespace {
 
-constexpr size_t kMaxChunkSize = 4 * 1024 * 1024;
-
 class TraceProcessorIntegrationTest : public ::testing::Test {
  public:
   TraceProcessorIntegrationTest()
       : processor_(TraceProcessor::CreateInstance(Config())) {}
 
  protected:
-  util::Status LoadTrace(const char* name, size_t min_chunk_size = 512) {
-    EXPECT_LE(min_chunk_size, kMaxChunkSize);
-    base::ScopedFstream f(fopen(
-        base::GetTestDataPath(std::string("test/data/") + name).c_str(), "rb"));
+  bool LoadTrace(const char* name, int min_chunk_size = 1) {
+    base::ScopedFstream f(fopen(base::GetTestDataPath(name).c_str(), "rb"));
     std::minstd_rand0 rnd_engine(0);
-    std::uniform_int_distribution<size_t> dist(min_chunk_size, kMaxChunkSize);
+    std::uniform_int_distribution<> dist(min_chunk_size, 1024);
     while (!feof(*f)) {
-      size_t chunk_size = dist(rnd_engine);
+      size_t chunk_size = static_cast<size_t>(dist(rnd_engine));
       std::unique_ptr<uint8_t[]> buf(new uint8_t[chunk_size]);
       auto rsize = fread(reinterpret_cast<char*>(buf.get()), 1, chunk_size, *f);
-      auto status = processor_->Parse(std::move(buf), rsize);
-      if (!status.ok())
-        return status;
+      if (!processor_->Parse(std::move(buf), rsize))
+        return false;
     }
     processor_->NotifyEndOfFile();
-    return util::OkStatus();
+    return true;
   }
 
   TraceProcessor::Iterator Query(const std::string& query) {
     return processor_->ExecuteQuery(query.c_str());
   }
 
-  size_t RestoreInitialTables() { return processor_->RestoreInitialTables(); }
-
  private:
   std::unique_ptr<TraceProcessor> processor_;
 };
 
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
 TEST_F(TraceProcessorIntegrationTest, AndroidSchedAndPs) {
-  ASSERT_TRUE(LoadTrace("android_sched_and_ps.pb").ok());
+  ASSERT_TRUE(LoadTrace("android_sched_and_ps.pb"));
   auto it = Query(
       "select count(*), max(ts) - min(ts) from sched "
       "where dur != 0 and utid != 0");
@@ -79,38 +70,9 @@
   ASSERT_EQ(it.Get(1).long_value, 19684308497);
   ASSERT_FALSE(it.Next());
 }
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
 
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-TEST_F(TraceProcessorIntegrationTest, TraceBounds) {
-  ASSERT_TRUE(LoadTrace("android_sched_and_ps.pb").ok());
-  auto it = Query("select start_ts, end_ts from trace_bounds");
-  ASSERT_TRUE(it.Next());
-  ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
-  ASSERT_EQ(it.Get(0).long_value, 81473009948313);
-  ASSERT_EQ(it.Get(1).type, SqlValue::kLong);
-  ASSERT_EQ(it.Get(1).long_value, 81492700784311);
-  ASSERT_FALSE(it.Next());
-}
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-
-TEST_F(TraceProcessorIntegrationTest, Hash) {
-  auto it = Query("select HASH()");
-  ASSERT_TRUE(it.Next());
-  ASSERT_EQ(it.Get(0).long_value, static_cast<int64_t>(0xcbf29ce484222325));
-
-  it = Query("select HASH('test')");
-  ASSERT_TRUE(it.Next());
-  ASSERT_EQ(it.Get(0).long_value, static_cast<int64_t>(0xf9e6e6ef197c2b25));
-
-  it = Query("select HASH('test', 1)");
-  ASSERT_TRUE(it.Next());
-  ASSERT_EQ(it.Get(0).long_value, static_cast<int64_t>(0xa9cb070fdc15f7a4));
-}
-
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON_IMPORT)
 TEST_F(TraceProcessorIntegrationTest, Sfgate) {
-  ASSERT_TRUE(LoadTrace("sfgate.json", strlen("{\"traceEvents\":[")).ok());
+  ASSERT_TRUE(LoadTrace("sfgate.json", strlen("{\"traceEvents\":[")));
   auto it =
       Query("select count(*), max(ts) - min(ts) from slices where utid != 0");
   ASSERT_TRUE(it.Next());
@@ -122,8 +84,7 @@
 }
 
 TEST_F(TraceProcessorIntegrationTest, UnsortedTrace) {
-  ASSERT_TRUE(
-      LoadTrace("unsorted_trace.json", strlen("{\"traceEvents\":[")).ok());
+  ASSERT_TRUE(LoadTrace("unsorted_trace.json", strlen("{\"traceEvents\":[")));
   auto it = Query("select ts, depth from slices order by ts");
   ASSERT_TRUE(it.Next());
   ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
@@ -138,75 +99,20 @@
   ASSERT_FALSE(it.Next());
 }
 
+TEST_F(TraceProcessorIntegrationTest, TraceBounds) {
+  ASSERT_TRUE(LoadTrace("android_sched_and_ps.pb"));
+  auto it = Query("select start_ts, end_ts from trace_bounds");
+  ASSERT_TRUE(it.Next());
+  ASSERT_EQ(it.Get(0).type, SqlValue::kLong);
+  ASSERT_EQ(it.Get(0).long_value, 81473009948313);
+  ASSERT_EQ(it.Get(1).type, SqlValue::kLong);
+  ASSERT_EQ(it.Get(1).long_value, 81492700784311);
+  ASSERT_FALSE(it.Next());
+}
+
 // TODO(hjd): Add trace to test_data.
 TEST_F(TraceProcessorIntegrationTest, DISABLED_AndroidBuildTrace) {
-  ASSERT_TRUE(LoadTrace("android_build_trace.json", strlen("[\n{")).ok());
-}
-
-TEST_F(TraceProcessorIntegrationTest, DISABLED_Clusterfuzz14357) {
-  ASSERT_FALSE(LoadTrace("clusterfuzz_14357", 4096).ok());
-}
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_JSON_IMPORT)
-
-TEST_F(TraceProcessorIntegrationTest, Clusterfuzz14730) {
-  ASSERT_TRUE(LoadTrace("clusterfuzz_14730", 4096).ok());
-}
-
-TEST_F(TraceProcessorIntegrationTest, Clusterfuzz14753) {
-  ASSERT_TRUE(LoadTrace("clusterfuzz_14753", 4096).ok());
-}
-
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FUCHSIA)
-TEST_F(TraceProcessorIntegrationTest, Clusterfuzz14762) {
-  ASSERT_TRUE(LoadTrace("clusterfuzz_14762", 4096 * 1024).ok());
-  auto it = Query("select sum(value) from stats where severity = 'error';");
-  ASSERT_TRUE(it.Next());
-  ASSERT_GT(it.Get(0).long_value, 0);
-}
-
-TEST_F(TraceProcessorIntegrationTest, Clusterfuzz14767) {
-  ASSERT_TRUE(LoadTrace("clusterfuzz_14767", 4096 * 1024).ok());
-  auto it = Query("select sum(value) from stats where severity = 'error';");
-  ASSERT_TRUE(it.Next());
-  ASSERT_GT(it.Get(0).long_value, 0);
-}
-
-TEST_F(TraceProcessorIntegrationTest, Clusterfuzz14799) {
-  ASSERT_TRUE(LoadTrace("clusterfuzz_14799", 4096 * 1024).ok());
-  auto it = Query("select sum(value) from stats where severity = 'error';");
-  ASSERT_TRUE(it.Next());
-  ASSERT_GT(it.Get(0).long_value, 0);
-}
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FUCHSIA)
-
-TEST_F(TraceProcessorIntegrationTest, Clusterfuzz15252) {
-  ASSERT_TRUE(LoadTrace("clusterfuzz_15252", 4096).ok());
-}
-
-TEST_F(TraceProcessorIntegrationTest, Clusterfuzz17805) {
-  ASSERT_TRUE(LoadTrace("clusterfuzz_17805", 4096).ok());
-}
-
-TEST_F(TraceProcessorIntegrationTest, RestoreInitialTables) {
-  ASSERT_TRUE(LoadTrace("android_sched_and_ps.pb").ok());
-
-  for (int repeat = 0; repeat < 3; repeat++) {
-    ASSERT_EQ(RestoreInitialTables(), 0u);
-
-    auto it = Query("CREATE TABLE user1(unused text);");
-    it.Next();
-    ASSERT_TRUE(it.Status().ok());
-
-    it = Query("CREATE TEMPORARY TABLE user2(unused text);");
-    it.Next();
-    ASSERT_TRUE(it.Status().ok());
-
-    it = Query("CREATE VIEW user3 AS SELECT * FROM stats;");
-    it.Next();
-    ASSERT_TRUE(it.Status().ok());
-
-    ASSERT_EQ(RestoreInitialTables(), 3u);
-  }
+  ASSERT_TRUE(LoadTrace("android_build_trace.json", strlen("[\n{")));
 }
 
 }  // namespace
diff --git a/src/trace_processor/trace_parser.h b/src/trace_processor/trace_parser.h
index fa3b4ef..63c2ce1 100644
--- a/src/trace_processor/trace_parser.h
+++ b/src/trace_processor/trace_parser.h
@@ -19,7 +19,7 @@
 
 #include <stdint.h>
 
-#include "src/trace_processor/timestamped_trace_piece.h"
+#include "src/trace_processor/trace_sorter.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -28,10 +28,11 @@
  public:
   virtual ~TraceParser();
 
-  virtual void ParseTracePacket(int64_t timestamp, TimestampedTracePiece) = 0;
+  virtual void ParseTracePacket(int64_t timestamp,
+                                TraceSorter::TimestampedTracePiece) = 0;
   virtual void ParseFtracePacket(uint32_t cpu,
                                  int64_t timestamp,
-                                 TimestampedTracePiece) = 0;
+                                 TraceSorter::TimestampedTracePiece) = 0;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/trace_parsing_fuzzer.cc b/src/trace_processor/trace_parsing_fuzzer.cc
index c15d716..19ef03d 100644
--- a/src/trace_processor/trace_parsing_fuzzer.cc
+++ b/src/trace_processor/trace_parsing_fuzzer.cc
@@ -15,7 +15,9 @@
  */
 
 #include "perfetto/base/logging.h"
-#include "perfetto/trace_processor/trace_processor_storage.h"
+#include "perfetto/trace_processor/trace_processor.h"
+
+#include "perfetto/trace_processor/raw_query.pb.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -23,12 +25,11 @@
 void FuzzTraceProcessor(const uint8_t* data, size_t size);
 
 void FuzzTraceProcessor(const uint8_t* data, size_t size) {
-  std::unique_ptr<TraceProcessorStorage> processor =
-      TraceProcessorStorage::CreateInstance(Config());
+  std::unique_ptr<TraceProcessor> processor =
+      TraceProcessor::CreateInstance(Config());
   std::unique_ptr<uint8_t[]> buf(new uint8_t[size]);
   memcpy(buf.get(), data, size);
-  util::Status status = processor->Parse(std::move(buf), size);
-  if (!status.ok())
+  if (!processor->Parse(std::move(buf), size))
     return;
   processor->NotifyEndOfFile();
 }
diff --git a/src/trace_processor/trace_processor.cc b/src/trace_processor/trace_processor.cc
index 0a4942a..80e3b4d 100644
--- a/src/trace_processor/trace_processor.cc
+++ b/src/trace_processor/trace_processor.cc
@@ -15,8 +15,7 @@
  */
 
 #include "perfetto/trace_processor/trace_processor.h"
-
-#include "src/trace_processor/sqlite/sqlite_table.h"
+#include "src/trace_processor/table.h"
 #include "src/trace_processor/trace_processor_impl.h"
 
 namespace perfetto {
@@ -55,16 +54,15 @@
   return iterator_->ColumnCount();
 }
 
-util::Status TraceProcessor::Iterator::Status() {
-  return iterator_->Status();
+base::Optional<std::string> TraceProcessor::Iterator::GetLastError() {
+  return iterator_->GetLastError();
 }
 
 // static
 void EnableSQLiteVtableDebugging() {
   // This level of indirection is required to avoid clients to depend on table.h
   // which in turn requires sqlite headers.
-  SqliteTable::debug = true;
+  Table::debug = true;
 }
-
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/trace_processor_context.cc b/src/trace_processor/trace_processor_context.cc
index 6576e6d..5483dae 100644
--- a/src/trace_processor/trace_processor_context.cc
+++ b/src/trace_processor/trace_processor_context.cc
@@ -17,29 +17,16 @@
 #include "src/trace_processor/trace_processor_context.h"
 
 #include "src/trace_processor/args_tracker.h"
-#include "src/trace_processor/binder_tracker.h"
 #include "src/trace_processor/chunked_trace_reader.h"
 #include "src/trace_processor/clock_tracker.h"
 #include "src/trace_processor/event_tracker.h"
 #include "src/trace_processor/heap_profile_tracker.h"
-#include "src/trace_processor/importers/ftrace/ftrace_module.h"
-#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
-#include "src/trace_processor/importers/json/json_trace_parser.h"
-#include "src/trace_processor/importers/proto/android_probes_module.h"
-#include "src/trace_processor/importers/proto/graphics_event_module.h"
-#include "src/trace_processor/importers/proto/heap_graph_module.h"
-#include "src/trace_processor/importers/proto/heap_graph_tracker.h"
-#include "src/trace_processor/importers/proto/proto_trace_parser.h"
-#include "src/trace_processor/importers/proto/system_probes_module.h"
-#include "src/trace_processor/importers/proto/track_event_module.h"
-#include "src/trace_processor/importers/systrace/systrace_parser.h"
+#include "src/trace_processor/json_trace_parser.h"
 #include "src/trace_processor/process_tracker.h"
+#include "src/trace_processor/proto_trace_parser.h"
 #include "src/trace_processor/slice_tracker.h"
-#include "src/trace_processor/stack_profile_tracker.h"
 #include "src/trace_processor/syscall_tracker.h"
 #include "src/trace_processor/trace_sorter.h"
-#include "src/trace_processor/track_tracker.h"
-#include "src/trace_processor/vulkan_memory_tracker.h"
 
 namespace perfetto {
 namespace trace_processor {
diff --git a/src/trace_processor/trace_processor_context.h b/src/trace_processor/trace_processor_context.h
index a591654..5a4f815 100644
--- a/src/trace_processor/trace_processor_context.h
+++ b/src/trace_processor/trace_processor_context.h
@@ -19,69 +19,37 @@
 
 #include <memory>
 
-#include "perfetto/trace_processor/basic_types.h"
-#include "src/trace_processor/importers/proto/proto_importer_module.h"
-
 namespace perfetto {
 namespace trace_processor {
 
-class AndroidProbesModule;
 class ArgsTracker;
-class BinderTracker;
 class ChunkedTraceReader;
 class ClockTracker;
 class EventTracker;
-class FtraceModule;
-class GraphicsEventModule;
-class HeapGraphModule;
-class HeapGraphTracker;
-class HeapProfileTracker;
 class ProcessTracker;
-class SchedEventTracker;
 class SliceTracker;
 class SyscallTracker;
-class SystemProbesModule;
-class SystraceParser;
 class TraceParser;
-class TraceSorter;
 class TraceStorage;
-class TrackEventModule;
-class TrackTracker;
-class VulkanMemoryTracker;
+class TraceSorter;
+class HeapProfileTracker;
 
 class TraceProcessorContext {
  public:
   TraceProcessorContext();
   ~TraceProcessorContext();
 
-  Config config;
-
-  std::unique_ptr<TraceStorage> storage;
-  std::unique_ptr<TrackTracker> track_tracker;
   std::unique_ptr<ArgsTracker> args_tracker;
   std::unique_ptr<SliceTracker> slice_tracker;
   std::unique_ptr<ProcessTracker> process_tracker;
   std::unique_ptr<SyscallTracker> syscall_tracker;
   std::unique_ptr<EventTracker> event_tracker;
-  std::unique_ptr<SchedEventTracker> sched_tracker;
   std::unique_ptr<ClockTracker> clock_tracker;
+  std::unique_ptr<TraceStorage> storage;
   std::unique_ptr<TraceParser> parser;
   std::unique_ptr<TraceSorter> sorter;
   std::unique_ptr<ChunkedTraceReader> chunk_reader;
   std::unique_ptr<HeapProfileTracker> heap_profile_tracker;
-  std::unique_ptr<SystraceParser> systrace_parser;
-  std::unique_ptr<HeapGraphTracker> heap_graph_tracker;
-  std::unique_ptr<VulkanMemoryTracker> vulkan_memory_tracker;
-  std::unique_ptr<BinderTracker> binder_tracker;
-
-  std::unique_ptr<ProtoImporterModule<FtraceModule>> ftrace_module;
-  std::unique_ptr<ProtoImporterModule<TrackEventModule>> track_event_module;
-  std::unique_ptr<ProtoImporterModule<SystemProbesModule>> system_probes_module;
-  std::unique_ptr<ProtoImporterModule<AndroidProbesModule>>
-      android_probes_module;
-  std::unique_ptr<ProtoImporterModule<HeapGraphModule>> heap_graph_module;
-  std::unique_ptr<ProtoImporterModule<GraphicsEventModule>>
-      graphics_event_module;
 };
 
 }  // namespace trace_processor
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index bbbe087..4313b2d 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -18,60 +18,71 @@
 
 #include <inttypes.h>
 #include <algorithm>
+#include <functional>
 
 #include "perfetto/base/logging.h"
+#include "perfetto/base/string_utils.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/ext/base/string_utils.h"
+#include "perfetto/protozero/scattered_heap_buffer.h"
 #include "src/trace_processor/android_logs_table.h"
 #include "src/trace_processor/args_table.h"
+#include "src/trace_processor/args_tracker.h"
+#include "src/trace_processor/clock_tracker.h"
+#include "src/trace_processor/counter_definitions_table.h"
 #include "src/trace_processor/counter_values_table.h"
-#include "src/trace_processor/cpu_profile_stack_sample_table.h"
-#include "src/trace_processor/heap_profile_allocation_table.h"
+#include "src/trace_processor/event_tracker.h"
+#include "src/trace_processor/fuchsia_trace_parser.h"
+#include "src/trace_processor/fuchsia_trace_tokenizer.h"
+#include "src/trace_processor/heap_profile_tracker.h"
 #include "src/trace_processor/instants_table.h"
-#include "src/trace_processor/metadata_table.h"
+#include "src/trace_processor/metrics/metrics.h"
 #include "src/trace_processor/process_table.h"
+#include "src/trace_processor/process_tracker.h"
+#include "src/trace_processor/proto_trace_parser.h"
+#include "src/trace_processor/proto_trace_tokenizer.h"
 #include "src/trace_processor/raw_table.h"
 #include "src/trace_processor/sched_slice_table.h"
 #include "src/trace_processor/slice_table.h"
+#include "src/trace_processor/slice_tracker.h"
 #include "src/trace_processor/span_join_operator_table.h"
 #include "src/trace_processor/sql_stats_table.h"
-#include "src/trace_processor/sqlite/db_sqlite_table.h"
-#include "src/trace_processor/sqlite/sqlite3_str_split.h"
-#include "src/trace_processor/sqlite/sqlite_table.h"
-#include "src/trace_processor/stack_profile_frame_table.h"
-#include "src/trace_processor/stack_profile_mapping_table.h"
+#include "src/trace_processor/sqlite3_str_split.h"
 #include "src/trace_processor/stats_table.h"
+#include "src/trace_processor/string_table.h"
+#include "src/trace_processor/syscall_tracker.h"
+#include "src/trace_processor/table.h"
 #include "src/trace_processor/thread_table.h"
+#include "src/trace_processor/trace_blob_view.h"
+#include "src/trace_processor/trace_sorter.h"
 #include "src/trace_processor/window_operator_table.h"
 
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
-#include "src/trace_processor/metrics/descriptors.h"
-#include "src/trace_processor/metrics/metrics.descriptor.h"
-#include "src/trace_processor/metrics/metrics.h"
-#include "src/trace_processor/metrics/sql_metrics.h"
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
+#include "perfetto/metrics/android/mem_metric.pbzero.h"
+#include "perfetto/metrics/metrics.pbzero.h"
 
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
-#include "src/trace_processor/export_json.h"
+// JSON parsing is only supported in the standalone build.
+#if PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD)
+#include "src/trace_processor/json_trace_parser.h"
+#include "src/trace_processor/json_trace_tokenizer.h"
 #endif
 
-// In Android and Chromium tree builds, we don't have the percentile module.
+// In Android tree builds, we don't have the percentile module.
 // Just don't include it.
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_PERCENTILE)
+#if !PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
 // defined in sqlite_src/ext/misc/percentile.c
 extern "C" int sqlite3_percentile_init(sqlite3* db,
                                        char** error,
                                        const sqlite3_api_routines* api);
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_PERCENTILE)
+#endif
 
 namespace perfetto {
 namespace trace_processor {
 namespace {
 
-const char kAllTablesQuery[] =
-    "SELECT tbl_name, type FROM (SELECT * FROM sqlite_master UNION ALL SELECT "
-    "* FROM sqlite_temp_master)";
+std::string RemoveWhitespace(const std::string& input) {
+  std::string str(input);
+  str.erase(std::remove_if(str.begin(), str.end(), ::isspace), str.end());
+  return str;
+}
 
 void InitializeSqlite(sqlite3* db) {
   char* error = nullptr;
@@ -82,7 +93,7 @@
   sqlite3_str_split_init(db);
 // In Android tree builds, we don't have the percentile module.
 // Just don't include it.
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_PERCENTILE)
+#if !PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
   sqlite3_percentile_init(db, &error, nullptr);
   if (error) {
     PERFETTO_ELOG("Error initializing: %s", error);
@@ -135,36 +146,9 @@
 void CreateBuiltinViews(sqlite3* db) {
   char* error = nullptr;
   sqlite3_exec(db,
-               "CREATE VIEW counter_definitions AS "
-               "SELECT "
-               "  *, "
-               "  id AS counter_id "
-               "FROM counter_track",
-               0, 0, &error);
-  if (error) {
-    PERFETTO_ELOG("Error initializing: %s", error);
-    sqlite3_free(error);
-  }
-
-  sqlite3_exec(db,
-               "CREATE VIEW counter_values AS "
-               "SELECT "
-               "  *, "
-               "  track_id as counter_id "
-               "FROM counter",
-               0, 0, &error);
-  if (error) {
-    PERFETTO_ELOG("Error initializing: %s", error);
-    sqlite3_free(error);
-  }
-
-  sqlite3_exec(db,
                "CREATE VIEW counters AS "
-               "SELECT * "
-               "FROM counter_values v "
-               "INNER JOIN counter_track t "
-               "ON v.track_id = t.id "
-               "ORDER BY ts;",
+               "SELECT * FROM counter_values "
+               "INNER JOIN counter_definitions USING(counter_id);",
                0, 0, &error);
   if (error) {
     PERFETTO_ELOG("Error initializing: %s", error);
@@ -175,7 +159,6 @@
                "CREATE VIEW slice AS "
                "SELECT "
                "  *, "
-               "  category AS cat, "
                "  CASE ref_type "
                "    WHEN 'utid' THEN ref "
                "    ELSE NULL "
@@ -187,17 +170,6 @@
     sqlite3_free(error);
   }
 
-  sqlite3_exec(db,
-               "CREATE VIEW gpu_slice AS "
-               "SELECT "
-               "* "
-               "FROM internal_gpu_slice join internal_slice using(slice_id);",
-               0, 0, &error);
-  if (error) {
-    PERFETTO_ELOG("Error initializing: %s", error);
-    sqlite3_free(error);
-  }
-
   // Legacy view for "slice" table with a deprecated table name.
   // TODO(eseckler): Remove this view when all users have switched to "slice".
   sqlite3_exec(db,
@@ -210,137 +182,65 @@
   }
 }
 
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
-void ExportJson(sqlite3_context* ctx, int /*argc*/, sqlite3_value** argv) {
-  TraceStorage* storage = static_cast<TraceStorage*>(sqlite3_user_data(ctx));
-  FILE* output;
-  if (sqlite3_value_type(argv[0]) == SQLITE_INTEGER) {
-    // Assume input is an FD.
-    output = fdopen(sqlite3_value_int(argv[0]), "w");
-    if (!output) {
-      sqlite3_result_error(ctx, "Couldn't open output file from given FD", -1);
-      return;
-    }
-  } else {
-    const char* filename =
-        reinterpret_cast<const char*>(sqlite3_value_text(argv[0]));
-    output = fopen(filename, "w");
-    if (!output) {
-      sqlite3_result_error(ctx, "Couldn't open output file", -1);
-      return;
-    }
-  }
-
-  util::Status result = json::ExportJson(storage, output);
-  if (!result.ok()) {
-    sqlite3_result_error(ctx, result.message().c_str(), -1);
-    return;
-  }
-}
-
-void CreateJsonExportFunction(TraceStorage* ts, sqlite3* db) {
-  auto ret = sqlite3_create_function_v2(db, "EXPORT_JSON", 1, SQLITE_UTF8, ts,
-                                        ExportJson, nullptr, nullptr,
+void CreateMetricsFunctions(TraceProcessorImpl* tp, sqlite3* db) {
+  auto ret = sqlite3_create_function_v2(db, "RUN_METRIC", -1, SQLITE_UTF8, tp,
+                                        metrics::RunMetric, nullptr, nullptr,
                                         sqlite_utils::kSqliteStatic);
   if (ret) {
-    PERFETTO_ELOG("Error initializing EXPORT_JSON");
-  }
-}
-#endif
-
-void Hash(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
-  base::Hash hash;
-  for (int i = 0; i < argc; ++i) {
-    sqlite3_value* value = argv[i];
-    switch (sqlite3_value_type(value)) {
-      case SQLITE_INTEGER:
-        hash.Update(sqlite3_value_int64(value));
-        break;
-      case SQLITE_TEXT: {
-        const char* ptr =
-            reinterpret_cast<const char*>(sqlite3_value_text(value));
-        hash.Update(ptr, strlen(ptr));
-        break;
-      }
-      default:
-        sqlite3_result_error(ctx, "Unsupported type of arg passed to HASH", -1);
-        return;
-    }
-  }
-  sqlite3_result_int64(ctx, static_cast<int64_t>(hash.digest()));
-}
-
-void CreateHashFunction(sqlite3* db) {
-  auto ret = sqlite3_create_function_v2(
-      db, "HASH", -1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr, &Hash,
-      nullptr, nullptr, nullptr);
-  if (ret) {
-    PERFETTO_ELOG("Error initializing HASH");
+    PERFETTO_ELOG("Error initializing RUN_METRIC");
   }
 }
 
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
-void SetupMetrics(TraceProcessor* tp,
-                  sqlite3* db,
-                  std::vector<metrics::SqlMetricFile>* sql_metrics) {
-  tp->ExtendMetricsProto(kMetricsDescriptor.data(), kMetricsDescriptor.size());
-
-  for (const auto& file_to_sql : metrics::sql_metrics::kFileToSql) {
-    tp->RegisterMetric(file_to_sql.path, file_to_sql.sql);
-  }
-
-  {
-    std::unique_ptr<metrics::RunMetricContext> ctx(
-        new metrics::RunMetricContext());
-    ctx->tp = tp;
-    ctx->metrics = sql_metrics;
-    auto ret = sqlite3_create_function_v2(
-        db, "RUN_METRIC", -1, SQLITE_UTF8, ctx.release(), metrics::RunMetric,
-        nullptr, nullptr,
-        [](void* ptr) { delete static_cast<metrics::RunMetricContext*>(ptr); });
-    if (ret)
-      PERFETTO_ELOG("Error initializing RUN_METRIC");
-  }
-
-  {
-    auto ret = sqlite3_create_function_v2(
-        db, "RepeatedField", 1, SQLITE_UTF8, nullptr, nullptr,
-        metrics::RepeatedFieldStep, metrics::RepeatedFieldFinal, nullptr);
-    if (ret)
-      PERFETTO_ELOG("Error initializing RepeatedField");
-  }
-}
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
+// Fuchsia traces have a magic number as documented here:
+// https://fuchsia.googlesource.com/fuchsia/+/HEAD/docs/development/tracing/trace-format/README.md#magic-number-record-trace-info-type-0
+constexpr uint64_t kFuchsiaMagicNumber = 0x0016547846040010;
 
 }  // namespace
 
-TraceProcessorImpl::TraceProcessorImpl(const Config& cfg)
-    : TraceProcessorStorageImpl(cfg) {
+TraceType GuessTraceType(const uint8_t* data, size_t size) {
+  if (size == 0)
+    return kUnknownTraceType;
+  std::string start(reinterpret_cast<const char*>(data),
+                    std::min<size_t>(size, 20));
+  std::string start_minus_white_space = RemoveWhitespace(start);
+  if (base::StartsWith(start_minus_white_space, "{\"traceEvents\":["))
+    return kJsonTraceType;
+  if (base::StartsWith(start_minus_white_space, "[{"))
+    return kJsonTraceType;
+  if (size >= 8) {
+    uint64_t first_word = *reinterpret_cast<const uint64_t*>(data);
+    if (first_word == kFuchsiaMagicNumber)
+      return kFuchsiaTraceType;
+  }
+  return ProtoTraceTokenizer::GuessProtoTraceType(data, size);
+}
+
+TraceProcessorImpl::TraceProcessorImpl(const Config& cfg) : cfg_(cfg) {
   sqlite3* db = nullptr;
-  PERFETTO_CHECK(sqlite3_initialize() == SQLITE_OK);
   PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
   InitializeSqlite(db);
   CreateBuiltinTables(db);
   CreateBuiltinViews(db);
+  CreateMetricsFunctions(this, db);
   db_.reset(std::move(db));
 
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
-  CreateJsonExportFunction(this->context_.storage.get(), db);
-#endif
-  CreateHashFunction(db);
-
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
-  SetupMetrics(this, *db_, &sql_metrics_);
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
+  context_.storage.reset(new TraceStorage());
+  context_.args_tracker.reset(new ArgsTracker(&context_));
+  context_.slice_tracker.reset(new SliceTracker(&context_));
+  context_.event_tracker.reset(new EventTracker(&context_));
+  context_.process_tracker.reset(new ProcessTracker(&context_));
+  context_.syscall_tracker.reset(new SyscallTracker(&context_));
+  context_.clock_tracker.reset(new ClockTracker(&context_));
+  context_.heap_profile_tracker.reset(new HeapProfileTracker(&context_));
 
   ArgsTable::RegisterTable(*db_, context_.storage.get());
   ProcessTable::RegisterTable(*db_, context_.storage.get());
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
   SchedSliceTable::RegisterTable(*db_, context_.storage.get());
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
   SliceTable::RegisterTable(*db_, context_.storage.get());
   SqlStatsTable::RegisterTable(*db_, context_.storage.get());
+  StringTable::RegisterTable(*db_, context_.storage.get());
   ThreadTable::RegisterTable(*db_, context_.storage.get());
+  CounterDefinitionsTable::RegisterTable(*db_, context_.storage.get());
   CounterValuesTable::RegisterTable(*db_, context_.storage.get());
   SpanJoinOperatorTable::RegisterTable(*db_, context_.storage.get());
   WindowOperatorTable::RegisterTable(*db_, context_.storage.get());
@@ -348,59 +248,6 @@
   StatsTable::RegisterTable(*db_, context_.storage.get());
   AndroidLogsTable::RegisterTable(*db_, context_.storage.get());
   RawTable::RegisterTable(*db_, context_.storage.get());
-  HeapProfileAllocationTable::RegisterTable(*db_, context_.storage.get());
-  CpuProfileStackSampleTable::RegisterTable(*db_, context_.storage.get());
-  StackProfileFrameTable::RegisterTable(*db_, context_.storage.get());
-  StackProfileMappingTable::RegisterTable(*db_, context_.storage.get());
-  MetadataTable::RegisterTable(*db_, context_.storage.get());
-
-  // New style db-backed tables.
-  const TraceStorage* storage = context_.storage.get();
-
-  DbSqliteTable::RegisterTable(*db_, &storage->track_table(),
-                               storage->track_table().table_name());
-  DbSqliteTable::RegisterTable(*db_, &storage->thread_track_table(),
-                               storage->thread_track_table().table_name());
-  DbSqliteTable::RegisterTable(*db_, &storage->process_track_table(),
-                               storage->process_track_table().table_name());
-  DbSqliteTable::RegisterTable(*db_, &storage->gpu_slice_table(),
-                               storage->gpu_slice_table().table_name());
-  DbSqliteTable::RegisterTable(*db_, &storage->gpu_track_table(),
-                               storage->gpu_track_table().table_name());
-
-  DbSqliteTable::RegisterTable(*db_, &storage->counter_track_table(),
-                               storage->counter_track_table().table_name());
-  DbSqliteTable::RegisterTable(
-      *db_, &storage->process_counter_track_table(),
-      storage->process_counter_track_table().table_name());
-  DbSqliteTable::RegisterTable(
-      *db_, &storage->thread_counter_track_table(),
-      storage->thread_counter_track_table().table_name());
-  DbSqliteTable::RegisterTable(*db_, &storage->cpu_counter_track_table(),
-                               storage->cpu_counter_track_table().table_name());
-  DbSqliteTable::RegisterTable(*db_, &storage->irq_counter_track_table(),
-                               storage->irq_counter_track_table().table_name());
-  DbSqliteTable::RegisterTable(
-      *db_, &storage->softirq_counter_track_table(),
-      storage->softirq_counter_track_table().table_name());
-  DbSqliteTable::RegisterTable(*db_, &storage->gpu_counter_track_table(),
-                               storage->gpu_counter_track_table().table_name());
-
-  DbSqliteTable::RegisterTable(*db_, &storage->heap_graph_object_table(),
-                               storage->heap_graph_object_table().table_name());
-  DbSqliteTable::RegisterTable(
-      *db_, &storage->heap_graph_reference_table(),
-      storage->heap_graph_reference_table().table_name());
-
-  DbSqliteTable::RegisterTable(*db_, &storage->symbol_table(),
-                               storage->symbol_table().table_name());
-  DbSqliteTable::RegisterTable(
-      *db_, &storage->stack_profile_callsite_table(),
-      storage->stack_profile_callsite_table().table_name());
-
-  DbSqliteTable::RegisterTable(
-      *db_, &storage->vulkan_memory_allocations_table(),
-      storage->vulkan_memory_allocations_table().table_name());
 }
 
 TraceProcessorImpl::~TraceProcessorImpl() {
@@ -408,65 +255,70 @@
     it->Reset();
 }
 
-util::Status TraceProcessorImpl::Parse(std::unique_ptr<uint8_t[]> data,
-                                       size_t size) {
-  bytes_parsed_ += size;
-  return TraceProcessorStorageImpl::Parse(std::move(data), size);
-}
+bool TraceProcessorImpl::Parse(std::unique_ptr<uint8_t[]> data, size_t size) {
+  if (size == 0)
+    return true;
+  if (unrecoverable_parse_error_)
+    return false;
 
-std::string TraceProcessorImpl::GetCurrentTraceName() {
-  if (current_trace_name_.empty())
-    return "";
-  auto size = " (" + std::to_string(bytes_parsed_ / 1024 / 1024) + " MB)";
-  return current_trace_name_ + size;
-}
+  // If this is the first Parse() call, guess the trace type and create the
+  // appropriate parser.
+  if (!context_.chunk_reader) {
+    TraceType trace_type;
+    {
+      auto scoped_trace = context_.storage->TraceExecutionTimeIntoStats(
+          stats::guess_trace_type_duration_ns);
+      trace_type = GuessTraceType(data.get(), size);
+    }
+    int64_t window_size_ns = static_cast<int64_t>(cfg_.window_size_ns);
+    switch (trace_type) {
+      case kJsonTraceType:
+        PERFETTO_DLOG("Legacy JSON trace detected");
+#if PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD)
+        context_.chunk_reader.reset(new JsonTraceTokenizer(&context_));
+        // JSON traces have no guarantees about the order of events in them.
+        window_size_ns = std::numeric_limits<int64_t>::max();
+        context_.sorter.reset(new TraceSorter(&context_, window_size_ns));
+        context_.parser.reset(new JsonTraceParser(&context_));
+#else
+        PERFETTO_FATAL("JSON traces only supported in standalone mode.");
+#endif
+        break;
+      case kProtoWithTrackEventsTraceType:
+      case kProtoTraceType:
+        if (trace_type == kProtoWithTrackEventsTraceType) {
+          // TrackEvents can be ordered arbitrarily due to out-of-order absolute
+          // timestamps and cross-packet-sequence events (e.g. async events).
+          window_size_ns = std::numeric_limits<int64_t>::max();
+        }
+        context_.chunk_reader.reset(new ProtoTraceTokenizer(&context_));
+        context_.sorter.reset(new TraceSorter(&context_, window_size_ns));
+        context_.parser.reset(new ProtoTraceParser(&context_));
+        break;
+      case kFuchsiaTraceType:
+        context_.chunk_reader.reset(new FuchsiaTraceTokenizer(&context_));
+        context_.sorter.reset(new TraceSorter(&context_, window_size_ns));
+        context_.parser.reset(new FuchsiaTraceParser(&context_));
+        break;
+      case kUnknownTraceType:
+        return false;
+    }
+  }
 
-void TraceProcessorImpl::SetCurrentTraceName(const std::string& name) {
-  current_trace_name_ = name;
+  auto scoped_trace = context_.storage->TraceExecutionTimeIntoStats(
+      stats::parse_trace_duration_ns);
+  bool res = context_.chunk_reader->Parse(std::move(data), size);
+  unrecoverable_parse_error_ |= !res;
+  return res;
 }
 
 void TraceProcessorImpl::NotifyEndOfFile() {
-  if (current_trace_name_.empty())
-    current_trace_name_ = "Unnamed trace";
+  if (unrecoverable_parse_error_ || !context_.chunk_reader)
+    return;
 
-  TraceProcessorStorageImpl::NotifyEndOfFile();
-
+  context_.sorter->ExtractEventsForced();
+  context_.event_tracker->FlushPendingEvents();
   BuildBoundsTable(*db_, context_.storage->GetTraceTimestampBoundsNs());
-
-  // Create a snapshot of all tables and views created so far. This is so later
-  // we can drop all extra tables created by the UI and reset to the original
-  // state (see RestoreInitialTables).
-  initial_tables_.clear();
-  auto it = ExecuteQuery(kAllTablesQuery);
-  while (it.Next()) {
-    auto value = it.Get(0);
-    PERFETTO_CHECK(value.type == SqlValue::Type::kString);
-    initial_tables_.push_back(value.string_value);
-  }
-}
-
-size_t TraceProcessorImpl::RestoreInitialTables() {
-  std::vector<std::pair<std::string, std::string>> deletion_list;
-  std::string msg = "Resetting DB to initial state, deleting table/views:";
-  for (auto it = ExecuteQuery(kAllTablesQuery); it.Next();) {
-    std::string name(it.Get(0).string_value);
-    std::string type(it.Get(1).string_value);
-    if (std::find(initial_tables_.begin(), initial_tables_.end(), name) ==
-        initial_tables_.end()) {
-      msg += " " + name;
-      deletion_list.push_back(std::make_pair(type, name));
-    }
-  }
-
-  PERFETTO_LOG("%s", msg.c_str());
-  for (const auto& tn : deletion_list) {
-    std::string query = "DROP " + tn.first + " " + tn.second;
-    auto it = ExecuteQuery(query);
-    while (it.Next()) {
-    }
-    PERFETTO_CHECK(it.Status().ok());
-  }
-  return deletion_list.size();
 }
 
 TraceProcessor::Iterator TraceProcessorImpl::ExecuteQuery(
@@ -475,10 +327,10 @@
   sqlite3_stmt* raw_stmt;
   int err = sqlite3_prepare_v2(*db_, sql.c_str(), static_cast<int>(sql.size()),
                                &raw_stmt, nullptr);
-  util::Status status;
+  base::Optional<std::string> error;
   uint32_t col_count = 0;
   if (err != SQLITE_OK) {
-    status = util::ErrStatus("%s", sqlite3_errmsg(*db_));
+    error = sqlite3_errmsg(*db_);
   } else {
     col_count = static_cast<uint32_t>(sqlite3_column_count(raw_stmt));
   }
@@ -489,7 +341,7 @@
                                                               t_start.count());
 
   std::unique_ptr<IteratorImpl> impl(new IteratorImpl(
-      this, *db_, ScopedStmt(raw_stmt), col_count, status, sql_stats_row));
+      this, *db_, ScopedStmt(raw_stmt), col_count, error, sql_stats_row));
   iterators_.emplace_back(impl.get());
   return TraceProcessor::Iterator(std::move(impl));
 }
@@ -501,99 +353,23 @@
   sqlite3_interrupt(db_.get());
 }
 
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
-util::Status TraceProcessorImpl::RegisterMetric(const std::string& path,
-                                                const std::string& sql) {
-  std::string stripped_sql;
-  for (base::StringSplitter sp(sql, '\n'); sp.Next();) {
-    if (strncmp(sp.cur_token(), "--", 2) != 0) {
-      stripped_sql.append(sp.cur_token());
-      stripped_sql.push_back('\n');
-    }
-  }
-
-  // Check if the metric with the given path already exists and if it does, just
-  // update the SQL associated with it.
-  auto it = std::find_if(
-      sql_metrics_.begin(), sql_metrics_.end(),
-      [&path](const metrics::SqlMetricFile& m) { return m.path == path; });
-  if (it != sql_metrics_.end()) {
-    it->sql = stripped_sql;
-    return util::OkStatus();
-  }
-
-  auto sep_idx = path.rfind("/");
-  std::string basename =
-      sep_idx == std::string::npos ? path : path.substr(sep_idx + 1);
-
-  auto sql_idx = basename.rfind(".sql");
-  if (sql_idx == std::string::npos) {
-    return util::ErrStatus("Unable to find .sql extension for metric");
-  }
-  auto no_ext_name = basename.substr(0, sql_idx);
-
-  metrics::SqlMetricFile metric;
-  metric.path = path;
-  metric.proto_field_name = no_ext_name;
-  metric.output_table_name = no_ext_name + "_output";
-  metric.sql = stripped_sql;
-  sql_metrics_.emplace_back(metric);
-  return util::OkStatus();
-}
-
-util::Status TraceProcessorImpl::ExtendMetricsProto(const uint8_t* data,
-                                                    size_t size) {
-  util::Status status = pool_.AddFromFileDescriptorSet(data, size);
-  if (!status.ok())
-    return status;
-
-  for (const auto& desc : pool_.descriptors()) {
-    // Convert the full name (e.g. .perfetto.protos.TraceMetrics.SubMetric)
-    // into a function name of the form (TraceMetrics_SubMetric).
-    auto fn_name = desc.full_name().substr(desc.package_name().size() + 1);
-    std::replace(fn_name.begin(), fn_name.end(), '.', '_');
-
-    std::unique_ptr<metrics::BuildProtoContext> ctx(
-        new metrics::BuildProtoContext());
-    ctx->tp = this;
-    ctx->pool = &pool_;
-    ctx->desc = &desc;
-
-    auto ret = sqlite3_create_function_v2(
-        *db_, fn_name.c_str(), -1, SQLITE_UTF8, ctx.release(),
-        metrics::BuildProto, nullptr, nullptr, [](void* ptr) {
-          delete static_cast<metrics::BuildProtoContext*>(ptr);
-        });
-    if (ret != SQLITE_OK)
-      return util::ErrStatus("%s", sqlite3_errmsg(*db_));
-  }
-  return util::OkStatus();
-}
-
-util::Status TraceProcessorImpl::ComputeMetric(
+int TraceProcessorImpl::ComputeMetric(
     const std::vector<std::string>& metric_names,
     std::vector<uint8_t>* metrics_proto) {
-  auto opt_idx = pool_.FindDescriptorIdx(".perfetto.protos.TraceMetrics");
-  if (!opt_idx.has_value())
-    return util::Status("Root metrics proto descriptor not found");
-
-  const auto& root_descriptor = pool_.descriptors()[opt_idx.value()];
-  return metrics::ComputeMetrics(this, metric_names, sql_metrics_,
-                                 root_descriptor, metrics_proto);
+  return metrics::ComputeMetrics(this, metric_names, metrics_proto);
 }
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
 
 TraceProcessor::IteratorImpl::IteratorImpl(TraceProcessorImpl* trace_processor,
                                            sqlite3* db,
                                            ScopedStmt stmt,
                                            uint32_t column_count,
-                                           util::Status status,
+                                           base::Optional<std::string> error,
                                            uint32_t sql_stats_row)
     : trace_processor_(trace_processor),
       db_(db),
       stmt_(std::move(stmt)),
       column_count_(column_count),
-      status_(status),
+      error_(error),
       sql_stats_row_(sql_stats_row) {}
 
 TraceProcessor::IteratorImpl::~IteratorImpl() {
@@ -610,8 +386,7 @@
 }
 
 void TraceProcessor::IteratorImpl::Reset() {
-  *this = IteratorImpl(nullptr, nullptr, ScopedStmt(), 0,
-                       util::ErrStatus("Trace processor was deleted"), 0);
+  *this = IteratorImpl(nullptr, nullptr, ScopedStmt(), 0, base::nullopt, 0);
 }
 
 void TraceProcessor::IteratorImpl::RecordFirstNextInSqlStats() {
diff --git a/src/trace_processor/trace_processor_impl.h b/src/trace_processor/trace_processor_impl.h
index 3149225..4dd4856 100644
--- a/src/trace_processor/trace_processor_impl.h
+++ b/src/trace_processor/trace_processor_impl.h
@@ -18,71 +18,58 @@
 #define SRC_TRACE_PROCESSOR_TRACE_PROCESSOR_IMPL_H_
 
 #include <sqlite3.h>
-
 #include <atomic>
 #include <functional>
-#include <string>
+#include <memory>
 #include <vector>
 
-#include "perfetto/ext/base/string_view.h"
+#include "perfetto/base/string_view.h"
 #include "perfetto/trace_processor/basic_types.h"
-#include "perfetto/trace_processor/status.h"
 #include "perfetto/trace_processor/trace_processor.h"
-#include "src/trace_processor/sqlite/scoped_db.h"
-#include "src/trace_processor/trace_processor_storage_impl.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
-#include "src/trace_processor/metrics/descriptors.h"
-#include "src/trace_processor/metrics/metrics.h"
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
+#include "src/trace_processor/scoped_db.h"
+#include "src/trace_processor/trace_processor_context.h"
 
 namespace perfetto {
+
 namespace trace_processor {
 
+enum TraceType {
+  kUnknownTraceType,
+  kProtoTraceType,
+  kProtoWithTrackEventsTraceType,
+  kJsonTraceType,
+  kFuchsiaTraceType,
+};
+
+TraceType GuessTraceType(const uint8_t* data, size_t size);
+
 // Coordinates the loading of traces from an arbitrary source and allows
 // execution of SQL queries on the events in these traces.
-class TraceProcessorImpl : public TraceProcessor,
-                           public TraceProcessorStorageImpl {
+class TraceProcessorImpl : public TraceProcessor {
  public:
   explicit TraceProcessorImpl(const Config&);
 
   ~TraceProcessorImpl() override;
 
-  // TraceProcessorStorage implementation:
-  util::Status Parse(std::unique_ptr<uint8_t[]>, size_t) override;
+  bool Parse(std::unique_ptr<uint8_t[]>, size_t) override;
+
   void NotifyEndOfFile() override;
 
-  // TraceProcessor implementation:
   Iterator ExecuteQuery(const std::string& sql,
                         int64_t time_queued = 0) override;
 
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
-  util::Status RegisterMetric(const std::string& path,
-                              const std::string& sql) override;
-
-  util::Status ExtendMetricsProto(const uint8_t* data, size_t size) override;
-
-  util::Status ComputeMetric(const std::vector<std::string>& metric_names,
-                             std::vector<uint8_t>* metrics) override;
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
+  int ComputeMetric(const std::vector<std::string>& metric_names,
+                    std::vector<uint8_t>* metrics) override;
 
   void InterruptQuery() override;
 
-  size_t RestoreInitialTables() override;
-
-  std::string GetCurrentTraceName() override;
-  void SetCurrentTraceName(const std::string&) override;
-
  private:
   // Needed for iterators to be able to delete themselves from the vector.
   friend class IteratorImpl;
 
-  ScopedDb db_;
-
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
-  metrics::DescriptorPool pool_;
-  std::vector<metrics::SqlMetricFile> sql_metrics_;
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_METRICS)
+  ScopedDb db_;  // Keep first.
+  TraceProcessorContext context_;
+  bool unrecoverable_parse_error_ = false;
 
   std::vector<IteratorImpl*> iterators_;
 
@@ -90,13 +77,7 @@
   // to prevent single-flow compiler optimizations in ExecuteQuery().
   std::atomic<bool> query_interrupted_{false};
 
-  // Keeps track of the tables created by the ingestion process. This is used
-  // by RestoreInitialTables() to delete all the tables/view that have been
-  // created after that point.
-  std::vector<std::string> initial_tables_;
-
-  std::string current_trace_name_;
-  uint64_t bytes_parsed_ = 0;
+  const Config cfg_;
 };
 
 // The pointer implementation of TraceProcessor::Iterator.
@@ -106,7 +87,7 @@
                sqlite3* db,
                ScopedStmt,
                uint32_t column_count,
-               util::Status,
+               base::Optional<std::string> error,
                uint32_t sql_stats_row);
   ~IteratorImpl();
 
@@ -125,12 +106,12 @@
       called_next_ = true;
     }
 
-    if (!status_.ok())
+    if (PERFETTO_UNLIKELY(error_.has_value()))
       return false;
 
     int ret = sqlite3_step(*stmt_);
     if (PERFETTO_UNLIKELY(ret != SQLITE_ROW && ret != SQLITE_DONE)) {
-      status_ = util::ErrStatus("%s", sqlite3_errmsg(db_));
+      error_ = base::Optional<std::string>(sqlite3_errmsg(db_));
       return false;
     }
     return ret == SQLITE_ROW;
@@ -154,12 +135,6 @@
         value.type = SqlValue::kDouble;
         value.double_value = sqlite3_column_double(*stmt_, column);
         break;
-      case SQLITE_BLOB:
-        value.type = SqlValue::kBytes;
-        value.bytes_value = sqlite3_column_blob(*stmt_, column);
-        value.bytes_count =
-            static_cast<size_t>(sqlite3_column_bytes(*stmt_, column));
-        break;
       case SQLITE_NULL:
         value.type = SqlValue::kNull;
         break;
@@ -173,7 +148,7 @@
 
   uint32_t ColumnCount() { return column_count_; }
 
-  util::Status Status() { return status_; }
+  base::Optional<std::string> GetLastError() { return error_; }
 
   // Methods called by TraceProcessorImpl.
   void Reset();
@@ -185,7 +160,7 @@
   sqlite3* db_ = nullptr;
   ScopedStmt stmt_;
   uint32_t column_count_ = 0;
-  util::Status status_;
+  base::Optional<std::string> error_;
 
   uint32_t sql_stats_row_ = 0;
   bool called_next_ = false;
diff --git a/src/trace_processor/trace_processor_impl_unittest.cc b/src/trace_processor/trace_processor_impl_unittest.cc
new file mode 100644
index 0000000..629314f
--- /dev/null
+++ b/src/trace_processor/trace_processor_impl_unittest.cc
@@ -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.
+ */
+
+#include "src/trace_processor/trace_processor_impl.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+TEST(TraceProcessorImplTest, GuessTraceType_Empty) {
+  const uint8_t prefix[] = "";
+  EXPECT_EQ(kUnknownTraceType, GuessTraceType(prefix, 0));
+}
+
+TEST(TraceProcessorImplTest, GuessTraceType_Json) {
+  const uint8_t prefix[] = "{\"traceEvents\":[";
+  EXPECT_EQ(kJsonTraceType, GuessTraceType(prefix, sizeof(prefix)));
+}
+
+TEST(TraceProcessorImplTest, GuessTraceType_JsonWithSpaces) {
+  const uint8_t prefix[] = "\n{ \"traceEvents\": [";
+  EXPECT_EQ(kJsonTraceType, GuessTraceType(prefix, sizeof(prefix)));
+}
+
+TEST(TraceProcessorImplTest, GuessTraceType_JsonMissingTraceEvents) {
+  const uint8_t prefix[] = "[{";
+  EXPECT_EQ(kJsonTraceType, GuessTraceType(prefix, sizeof(prefix)));
+}
+
+TEST(TraceProcessorImplTest, GuessTraceType_Proto) {
+  const uint8_t prefix[] = {0x0a, 0x00};  // An empty TracePacket.
+  EXPECT_EQ(kProtoTraceType, GuessTraceType(prefix, sizeof(prefix)));
+}
+
+TEST(TraceProcessorImplTest, GuessTraceType_Fuchsia) {
+  const uint8_t prefix[] = {0x10, 0x00, 0x04, 0x46, 0x78, 0x54, 0x16, 0x00};
+  EXPECT_EQ(kFuchsiaTraceType, GuessTraceType(prefix, sizeof(prefix)));
+}
+
+}  // namespace
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/trace_processor_shell.cc b/src/trace_processor/trace_processor_shell.cc
index f7a2877..093c853 100644
--- a/src/trace_processor/trace_processor_shell.cc
+++ b/src/trace_processor/trace_processor_shell.cc
@@ -14,34 +14,23 @@
  * limitations under the License.
  */
 
+#include <aio.h>
 #include <fcntl.h>
 #include <inttypes.h>
 #include <stdio.h>
 #include <sys/stat.h>
+#include <unistd.h>
 
 #include <functional>
 #include <iostream>
 #include <vector>
 
-#include <google/protobuf/compiler/parser.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/text_format.h>
-
 #include "perfetto/base/build_config.h"
 #include "perfetto/base/logging.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/string_splitter.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/trace_processor/read_trace.h"
 #include "perfetto/trace_processor/trace_processor.h"
-#include "src/trace_processor/metrics/metrics.descriptor.h"
-#include "src/trace_processor/proto_to_json.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_HTTPD)
-#include "src/trace_processor/rpc/httpd.h"
-#endif
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
@@ -51,13 +40,10 @@
 #define PERFETTO_HAS_SIGNAL_H() 0
 #endif
 
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_LINENOISE)
+#if PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD)
 #include <linenoise.h>
 #include <pwd.h>
 #include <sys/types.h>
-#endif
-
-#if PERFETTO_BUILDFLAG(PERFETTO_VERSION_GEN)
 #include "perfetto_version.gen.h"
 #else
 #define PERFETTO_GET_GIT_REVISION() "unknown"
@@ -67,20 +53,13 @@
 #include <signal.h>
 #endif
 
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-#define ftruncate _chsize
-#else
-#include <dirent.h>
-#include <getopt.h>
-#endif
-
 namespace perfetto {
 namespace trace_processor {
 
 namespace {
 TraceProcessor* g_tp;
 
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_LINENOISE)
+#if PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD)
 
 bool EnsureDir(const std::string& path) {
   return mkdir(path.c_str(), 0755) != -1 || errno == EEXIST;
@@ -158,12 +137,12 @@
   return line;
 }
 
-#endif  // PERFETTO_TP_LINENOISE
+#endif
 
 bool PrintStats() {
   auto it = g_tp->ExecuteQuery(
       "SELECT name, idx, source, value from stats "
-      "where severity IN ('error', 'data_loss') and value > 0");
+      "where severity = 'error' and value > 0");
 
   bool first = true;
   for (uint32_t rows = 0; it.Next(); rows++) {
@@ -196,18 +175,14 @@
         case SqlValue::Type::kString:
           fprintf(stderr, "%-40.40s", value.string_value);
           break;
-        case SqlValue::Type::kBytes:
-          printf("%-40.40s", "<raw bytes>");
-          break;
       }
       fprintf(stderr, " ");
     }
     fprintf(stderr, "\n");
   }
 
-  util::Status status = it.Status();
-  if (!status.ok()) {
-    PERFETTO_ELOG("Error while iterating stats %s", status.c_message());
+  if (base::Optional<std::string> opt_error = it.GetLastError()) {
+    PERFETTO_ELOG("Error while iterating stats %s", opt_error->c_str());
     return false;
   }
   return true;
@@ -230,10 +205,8 @@
   auto attach_it = g_tp->ExecuteQuery(attach_sql);
   bool attach_has_more = attach_it.Next();
   PERFETTO_DCHECK(!attach_has_more);
-
-  util::Status status = attach_it.Status();
-  if (!status.ok()) {
-    PERFETTO_ELOG("SQLite error: %s", status.c_message());
+  if (base::Optional<std::string> opt_error = attach_it.GetLastError()) {
+    PERFETTO_ELOG("SQLite error: %s", opt_error->c_str());
     return 1;
   }
 
@@ -249,139 +222,39 @@
     auto export_it = g_tp->ExecuteQuery(export_sql);
     bool export_has_more = export_it.Next();
     PERFETTO_DCHECK(!export_has_more);
-
-    status = export_it.Status();
-    if (!status.ok()) {
-      PERFETTO_ELOG("SQLite error: %s", status.c_message());
+    if (base::Optional<std::string> opt_error = export_it.GetLastError()) {
+      PERFETTO_ELOG("SQLite error: %s", opt_error->c_str());
       return 1;
     }
   }
-  status = tables_it.Status();
-  if (!status.ok()) {
-    PERFETTO_ELOG("SQLite error: %s", status.c_message());
+  if (base::Optional<std::string> opt_error = tables_it.GetLastError()) {
+    PERFETTO_ELOG("SQLite error: %s", opt_error->c_str());
     return 1;
   }
 
   auto detach_it = g_tp->ExecuteQuery("DETACH DATABASE perfetto_export");
   bool detach_has_more = attach_it.Next();
   PERFETTO_DCHECK(!detach_has_more);
-  status = detach_it.Status();
-  if (!status.ok()) {
-    PERFETTO_ELOG("SQLite error: %s", status.c_message());
+  if (base::Optional<std::string> opt_error = detach_it.GetLastError()) {
+    PERFETTO_ELOG("SQLite error: %s", opt_error->c_str());
     return 1;
   }
   return 0;
 }
 
-class ErrorPrinter : public google::protobuf::io::ErrorCollector {
-  void AddError(int line, int col, const std::string& msg) override {
-    PERFETTO_ELOG("%d:%d: %s", line, col, msg.c_str());
-  }
-
-  void AddWarning(int line, int col, const std::string& msg) override {
-    PERFETTO_ILOG("%d:%d: %s", line, col, msg.c_str());
-  }
-};
-
-util::Status RegisterMetric(const std::string& register_metric) {
-  std::string sql;
-  base::ReadFile(register_metric, &sql);
-
-  std::string path = "shell/";
-  auto slash_idx = register_metric.rfind('/');
-  path += slash_idx == std::string::npos
-              ? register_metric
-              : register_metric.substr(slash_idx + 1);
-
-  return g_tp->RegisterMetric(path, sql);
-}
-
-util::Status ExtendMetricsProto(const std::string& extend_metrics_proto,
-                                google::protobuf::DescriptorPool* pool) {
-  google::protobuf::FileDescriptorSet desc_set;
-
-  base::ScopedFile file(base::OpenFile(extend_metrics_proto, O_RDONLY));
-  if (file.get() == -1) {
-    return util::ErrStatus("Failed to open proto file %s",
-                           extend_metrics_proto.c_str());
-  }
-
-  google::protobuf::io::FileInputStream stream(file.get());
-  ErrorPrinter printer;
-  google::protobuf::io::Tokenizer tokenizer(&stream, &printer);
-
-  auto* proto = desc_set.add_file();
-  google::protobuf::compiler::Parser parser;
-  parser.Parse(&tokenizer, proto);
-
-  auto basename_idx = extend_metrics_proto.rfind('/');
-  auto basename = basename_idx == std::string::npos
-                      ? extend_metrics_proto
-                      : extend_metrics_proto.substr(basename_idx + 1);
-  proto->set_name(basename);
-  pool->BuildFile(*proto);
-
-  std::vector<uint8_t> metric_proto;
-  metric_proto.resize(static_cast<size_t>(desc_set.ByteSize()));
-  desc_set.SerializeToArray(metric_proto.data(),
-                            static_cast<int>(metric_proto.size()));
-
-  return g_tp->ExtendMetricsProto(metric_proto.data(), metric_proto.size());
-}
-
-enum OutputFormat {
-  kBinaryProto,
-  kTextProto,
-  kJson,
-  kNone,
-};
-
-int RunMetrics(const std::vector<std::string>& metric_names,
-               OutputFormat format,
-               const google::protobuf::DescriptorPool& pool) {
+int RunMetrics(const std::vector<std::string>& metric_names) {
   std::vector<uint8_t> metric_result;
-  util::Status status = g_tp->ComputeMetric(metric_names, &metric_result);
-  if (!status.ok()) {
-    PERFETTO_ELOG("Error when computing metrics: %s", status.c_message());
+  int res = g_tp->ComputeMetric(metric_names, &metric_result);
+  if (res) {
+    PERFETTO_ELOG("Error when computing metrics");
     return 1;
   }
-  if (format == OutputFormat::kNone) {
-    return 0;
-  }
-  if (format == OutputFormat::kBinaryProto) {
-    fwrite(metric_result.data(), sizeof(uint8_t), metric_result.size(), stdout);
-    return 0;
-  }
-
-  google::protobuf::DynamicMessageFactory factory(&pool);
-  auto* descriptor = pool.FindMessageTypeByName("perfetto.protos.TraceMetrics");
-  std::unique_ptr<google::protobuf::Message> metrics(
-      factory.GetPrototype(descriptor)->New());
-  metrics->ParseFromArray(metric_result.data(),
-                          static_cast<int>(metric_result.size()));
-
-  switch (format) {
-    case OutputFormat::kTextProto: {
-      std::string out;
-      google::protobuf::TextFormat::PrintToString(*metrics, &out);
-      fwrite(out.c_str(), sizeof(char), out.size(), stdout);
-      break;
-    }
-    case OutputFormat::kJson: {
-      auto out = proto_to_json::MessageToJson(*metrics) + "\n";
-      fwrite(out.c_str(), sizeof(char), out.size(), stdout);
-      break;
-    }
-    case OutputFormat::kBinaryProto:
-    case OutputFormat::kNone:
-      PERFETTO_FATAL("Unsupported output format.");
-  }
+  fwrite(metric_result.data(), sizeof(uint8_t), metric_result.size(), stdout);
   return 0;
 }
 
 void PrintQueryResultInteractively(TraceProcessor::Iterator* it,
-                                   base::TimeNanos t_start,
-                                   uint32_t column_width) {
+                                   base::TimeNanos t_start) {
   base::TimeNanos t_end = t_start;
   for (uint32_t rows = 0; it->Next(); rows++) {
     if (rows % 32 == 0) {
@@ -397,14 +270,11 @@
         t_end = base::GetWallTimeNs();
       }
       for (uint32_t i = 0; i < it->ColumnCount(); i++)
-        printf("%-*.*s ", column_width, column_width,
-               it->GetColumName(i).c_str());
+        printf("%20s ", it->GetColumName(i).c_str());
       printf("\n");
 
-      std::string divider(column_width, '-');
-      for (uint32_t i = 0; i < it->ColumnCount(); i++) {
-        printf("%-*s ", column_width, divider.c_str());
-      }
+      for (uint32_t i = 0; i < it->ColumnCount(); i++)
+        printf("%20s ", "--------------------");
       printf("\n");
     }
 
@@ -412,19 +282,16 @@
       auto value = it->Get(c);
       switch (value.type) {
         case SqlValue::Type::kNull:
-          printf("%-*s", column_width, "[NULL]");
+          printf("%-20.20s", "[NULL]");
           break;
         case SqlValue::Type::kDouble:
-          printf("%*f", column_width, value.double_value);
+          printf("%20f", value.double_value);
           break;
         case SqlValue::Type::kLong:
-          printf("%*" PRIi64, column_width, value.long_value);
+          printf("%20" PRIi64, value.long_value);
           break;
         case SqlValue::Type::kString:
-          printf("%-*.*s", column_width, column_width, value.string_value);
-          break;
-        case SqlValue::Type::kBytes:
-          printf("%-*s", column_width, "<raw bytes>");
+          printf("%-20.20s", value.string_value);
           break;
       }
       printf(" ");
@@ -432,9 +299,8 @@
     printf("\n");
   }
 
-  util::Status status = it->Status();
-  if (!status.ok()) {
-    PERFETTO_ELOG("SQLite error: %s", status.c_message());
+  if (base::Optional<std::string> opt_error = it->GetLastError()) {
+    PERFETTO_ELOG("SQLite error: %s", opt_error->c_str());
   }
   printf("\nQuery executed in %.3f ms\n\n", (t_end - t_start).count() / 1E6);
 }
@@ -444,11 +310,10 @@
       "Available commands:\n"
       ".quit, .q    Exit the shell.\n"
       ".help        This text.\n"
-      ".dump FILE   Export the trace as a sqlite database.\n"
-      ".reset       Destroys all tables/view created by the user.\n");
+      ".dump FILE   Export the trace as a sqlite database.\n");
 }
 
-int StartInteractiveShell(uint32_t column_width) {
+int StartInteractiveShell() {
   SetupLineEditor();
 
   for (;;) {
@@ -468,8 +333,6 @@
       } else if (strcmp(command, "dump") == 0 && strlen(arg)) {
         if (ExportTraceToDatabase(arg) != 0)
           PERFETTO_ELOG("Database export failed");
-      } else if (strcmp(command, "reset") == 0) {
-        g_tp->RestoreInitialTables();
       } else {
         PrintShellUsage();
       }
@@ -478,14 +341,14 @@
 
     base::TimeNanos t_start = base::GetWallTimeNs();
     auto it = g_tp->ExecuteQuery(line);
-    PrintQueryResultInteractively(&it, t_start, column_width);
+    PrintQueryResultInteractively(&it, t_start);
 
     FreeLine(line);
   }
   return 0;
 }
 
-util::Status PrintQueryResultAsCsv(TraceProcessor::Iterator* it, FILE* output) {
+void PrintQueryResultAsCsv(TraceProcessor::Iterator* it, FILE* output) {
   for (uint32_t c = 0; c < it->ColumnCount(); c++) {
     if (c > 0)
       fprintf(output, ",");
@@ -512,30 +375,10 @@
         case SqlValue::Type::kString:
           fprintf(output, "\"%s\"", value.string_value);
           break;
-        case SqlValue::Type::kBytes:
-          fprintf(output, "\"%s\"", "<raw bytes>");
-          break;
       }
     }
     fprintf(output, "\n");
   }
-  return it->Status();
-}
-
-bool IsBlankLine(char* buffer) {
-  size_t buf_size = strlen(buffer);
-  for (size_t i = 0; i < buf_size; ++i) {
-    // We can index into buffer[i+1], because strlen does not include the
-    // trailing \0, so even if \r is the last character, this is not out
-    // of bound.
-    if (buffer[i] == '\r') {
-      if (buffer[i + 1] != '\n')
-        return false;
-    } else if (buffer[i] != ' ' && buffer[i] != '\t' && buffer[i] != '\n') {
-      return false;
-    }
-  }
-  return true;
 }
 
 bool LoadQueries(FILE* input, std::vector<std::string>* output) {
@@ -543,7 +386,7 @@
   while (!feof(input) && !ferror(input)) {
     std::string sql_query;
     while (fgets(buffer, sizeof(buffer), input)) {
-      if (IsBlankLine(buffer))
+      if (strncmp(buffer, "\n", sizeof(buffer)) == 0)
         break;
       sql_query.append(buffer);
     }
@@ -579,9 +422,8 @@
     PERFETTO_ILOG("Executing query: %s", sql_query.c_str());
 
     auto it = g_tp->ExecuteQuery(sql_query);
-    util::Status status = it.Status();
-    if (!status.ok()) {
-      PERFETTO_ELOG("SQLite error: %s", status.c_message());
+    if (base::Optional<std::string> opt_error = it.GetLastError()) {
+      PERFETTO_ELOG("SQLite error: %s", opt_error->c_str());
       is_query_error = true;
       break;
     }
@@ -598,335 +440,147 @@
       is_query_error = true;
       break;
     }
-    status = PrintQueryResultAsCsv(&it, output);
+    PrintQueryResultAsCsv(&it, output);
     has_output = true;
-
-    if (!status.ok()) {
-      PERFETTO_ELOG("SQLite error: %s", status.c_message());
-      is_query_error = true;
-    }
   }
   return !is_query_error;
 }
 
-int MaybePrintPerfFile(const std::string& perf_file_path,
-                       base::TimeNanos t_load,
-                       base::TimeNanos t_run) {
-  if (perf_file_path.empty())
-    return 0;
-
-  char buf[128];
-  int count = snprintf(buf, sizeof(buf), "%" PRId64 ",%" PRId64,
-                       static_cast<int64_t>(t_load.count()),
-                       static_cast<int64_t>(t_run.count()));
-  if (count < 0) {
-    PERFETTO_ELOG("Failed to write perf data");
-    return 1;
-  }
-
-  auto fd(base::OpenFile(perf_file_path, O_WRONLY | O_CREAT | O_TRUNC, 0666));
-  if (!fd) {
-    PERFETTO_ELOG("Failed to open perf file");
-    return 1;
-  }
-  base::WriteAll(fd.get(), buf, static_cast<size_t>(count));
-  return 0;
-}
-
-struct CommandLineOptions {
-  std::string perf_file_path;
-  std::string query_file_path;
-  std::string sqlite_file_path;
-  std::string metric_names;
-  std::string metric_output;
-  std::string metric_extra;
-  std::string trace_file_path;
-  bool launch_shell = false;
-  bool enable_httpd = false;
-  bool wide = false;
-  bool force_full_sort = false;
-};
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 void PrintUsage(char** argv) {
   PERFETTO_ELOG(
       "Interactive trace processor shell.\n"
-      "Usage: %s [-q query_file] trace_file.pb",
+      "Usage: %s [OPTIONS] trace_file.pb\n\n"
+      "Options:\n"
+      " -d                   Enable virtual table debugging.\n"
+      " -s FILE              Read and execute contents of file before "
+      "launching an interactive shell.\n"
+      " -q FILE              Read and execute an SQL query from a file.\n"
+      " -e FILE              Export the trace into a SQLite database.\n"
+      " --run-metrics x,y,z   Runs a comma separated list of metrics and "
+      "prints the result as a TraceMetrics proto to stdout.\n",
       argv[0]);
 }
 
-CommandLineOptions ParseCommandLineOptions(int argc, char** argv) {
-  CommandLineOptions command_line_options;
-
-  if (argc == 2) {
-    command_line_options.trace_file_path = argv[1];
-    command_line_options.launch_shell = true;
-  } else if (argc == 4) {
-    if (strcmp(argv[1], "-q") != 0) {
-      PrintUsage(argv);
-      exit(1);
-    }
-    command_line_options.query_file_path = argv[2];
-    command_line_options.trace_file_path = argv[3];
-  } else {
+int TraceProcessorMain(int argc, char** argv) {
+  if (argc < 2) {
     PrintUsage(argv);
-    exit(1);
+    return 1;
   }
-
-  return command_line_options;
-}
-
-util::Status RegisterExtraMetrics(const std::string&, const std::string&) {
-  return util::ErrStatus("RegisterExtraMetrics not implemented on Windows");
-}
-
-#else  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-
-void PrintUsage(char** argv) {
-  PERFETTO_ELOG(R"(
-Interactive trace processor shell.
-Usage: %s [OPTIONS] trace_file.pb
-
-Options:
- -h, --help                           Prints this guide.
- -v, --version                        Prints the version of trace processor.
- -d, --debug                          Enable virtual table debugging.
- -W, --wide                           Prints interactive output with double
-                                      column width.
- -p, --perf-file FILE                 Writes the time taken to ingest the trace
-                                      and execute the queries to the given file.
-                                      Only valid with -q or --run-metrics and
-                                      the file will only be written if the
-                                      execution is successful.
- -q, --query-file FILE                Read and execute an SQL query from a file.
-                                      If used with --run-metrics, the query is
-                                      executed after the selected metrics and
-                                      the metrics output is suppressed.
- -D, --httpd                          Enables the HTTP RPC server.
- -i, --interactive                    Starts interactive mode even after a query
-                                      file is specified with -q or
-                                      --run-metrics.
- -e, --export FILE                    Export the trace into a SQLite database.
- --run-metrics x,y,z                  Runs a comma separated list of metrics and
-                                      prints the result as a TraceMetrics proto
-                                      to stdout. The specified can either be
-                                      in-built metrics or SQL/proto files of
-                                      extension metrics.
- --metrics-output=[binary|text|json]  Allows the output of --run-metrics to be
-                                      specified in either proto binary, proto
-                                      text format or JSON format (default: proto
-                                      text).
- --extra-metrics PATH                 Registers all SQL files at the given path
-                                      to the trace processor and extends the
-                                      builtin metrics proto with
-                                      $PATH/metrics-ext.proto.
- --full-sort                          Forces the trace processor into performing
-                                      a full sort ignoring any windowing
-                                      logic.)",
-                argv[0]);
-}
-
-CommandLineOptions ParseCommandLineOptions(int argc, char** argv) {
-  CommandLineOptions command_line_options;
-  enum LongOption {
-    OPT_RUN_METRICS = 1000,
-    OPT_METRICS_OUTPUT,
-    OPT_EXTRA_METRICS,
-    OPT_FORCE_FULL_SORT,
-  };
-
-  static const struct option long_options[] = {
-      {"help", no_argument, nullptr, 'h'},
-      {"version", no_argument, nullptr, 'v'},
-      {"wide", no_argument, nullptr, 'W'},
-      {"httpd", no_argument, nullptr, 'D'},
-      {"interactive", no_argument, nullptr, 'i'},
-      {"debug", no_argument, nullptr, 'd'},
-      {"perf-file", required_argument, nullptr, 'p'},
-      {"query-file", required_argument, nullptr, 'q'},
-      {"export", required_argument, nullptr, 'e'},
-      {"run-metrics", required_argument, nullptr, OPT_RUN_METRICS},
-      {"metrics-output", required_argument, nullptr, OPT_METRICS_OUTPUT},
-      {"extra-metrics", required_argument, nullptr, OPT_EXTRA_METRICS},
-      {"full-sort", no_argument, nullptr, OPT_FORCE_FULL_SORT},
-      {nullptr, 0, nullptr, 0}};
-
-  bool explicit_interactive = false;
-  int option_index = 0;
-  for (;;) {
-    int option =
-        getopt_long(argc, argv, "hvWiDdp:q:e:", long_options, &option_index);
-
-    if (option == -1)
-      break;  // EOF.
-
-    if (option == 'v') {
+  const char* trace_file_path = nullptr;
+  const char* query_file_path = nullptr;
+  const char* sqlite_file_path = nullptr;
+  const char* metric_names = nullptr;
+  bool launch_shell = true;
+  for (int i = 1; i < argc; i++) {
+    if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) {
       printf("%s\n", PERFETTO_GET_GIT_REVISION());
       exit(0);
     }
-
-    if (option == 'i') {
-      explicit_interactive = true;
-      continue;
-    }
-
-    if (option == 'D') {
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_HTTPD)
-      command_line_options.enable_httpd = true;
-#else
-      PERFETTO_FATAL("HTTP RPC module not supported in this build");
-#endif
-      continue;
-    }
-
-    if (option == 'W') {
-      command_line_options.wide = true;
-      continue;
-    }
-
-    if (option == 'd') {
+    if (strcmp(argv[i], "-d") == 0) {
       EnableSQLiteVtableDebugging();
       continue;
     }
-
-    if (option == 'p') {
-      command_line_options.perf_file_path = optarg;
+    if (strcmp(argv[i], "-q") == 0 || strcmp(argv[i], "-s") == 0) {
+      launch_shell = strcmp(argv[i], "-s") == 0;
+      if (++i == argc) {
+        PrintUsage(argv);
+        return 1;
+      }
+      query_file_path = argv[i];
       continue;
-    }
-
-    if (option == 'q') {
-      command_line_options.query_file_path = optarg;
+    } else if (strcmp(argv[i], "-e") == 0) {
+      if (++i == argc) {
+        PrintUsage(argv);
+        return 1;
+      }
+      sqlite_file_path = argv[i];
       continue;
-    }
-
-    if (option == 'e') {
-      command_line_options.sqlite_file_path = optarg;
+    } else if (strcmp(argv[i], "--run-metrics") == 0) {
+      if (++i == argc) {
+        PrintUsage(argv);
+        return 1;
+      }
+      metric_names = argv[i];
       continue;
+    } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
+      PrintUsage(argv);
+      return 0;
+    } else if (argv[i][0] == '-') {
+      PERFETTO_ELOG("Unknown option: %s", argv[i]);
+      return 1;
     }
+    trace_file_path = argv[i];
+  }
 
-    if (option == OPT_RUN_METRICS) {
-      command_line_options.metric_names = optarg;
-      continue;
-    }
-
-    if (option == OPT_METRICS_OUTPUT) {
-      command_line_options.metric_output = optarg;
-      continue;
-    }
-
-    if (option == OPT_EXTRA_METRICS) {
-      command_line_options.metric_extra = optarg;
-      continue;
-    }
-
-    if (option == OPT_FORCE_FULL_SORT) {
-      command_line_options.force_full_sort = true;
-      continue;
-    }
-
+  if (trace_file_path == nullptr) {
     PrintUsage(argv);
-    exit(option == 'h' ? 0 : 1);
+    return 1;
   }
 
-  command_line_options.launch_shell =
-      explicit_interactive || (command_line_options.metric_names.empty() &&
-                               command_line_options.query_file_path.empty());
-
-  // Only allow non-interactive queries to emit perf data.
-  if (!command_line_options.perf_file_path.empty() &&
-      command_line_options.launch_shell) {
-    PrintUsage(argv);
-    exit(1);
-  }
-
-  // The only case where we allow omitting the trace file path is when running
-  // in --http mode. In all other cases, the last argument must be the trace
-  // file.
-  if (optind == argc - 1 && argv[optind]) {
-    command_line_options.trace_file_path = argv[optind];
-  } else if (!command_line_options.enable_httpd) {
-    PrintUsage(argv);
-    exit(1);
-  }
-  return command_line_options;
-}
-
-util::Status RegisterExtraMetric(const std::string& parent_path,
-                                 const std::string& path) {
-  // Silently ignore any non-SQL files.
-  if (path.find(".sql") == std::string::npos)
-    return util::OkStatus();
-
-  std::string sql;
-  base::ReadFile(parent_path + "/" + path, &sql);
-  return g_tp->RegisterMetric(path, sql);
-}
-
-util::Status RegisterExtraMetrics(const std::string& path,
-                                  const std::string& group) {
-  std::string full_path = path + "/" + group;
-  DIR* dir = opendir(full_path.c_str());
-  if (dir == nullptr) {
-    return util::ErrStatus(
-        "Failed to open directory %s to register extra metrics",
-        full_path.c_str());
-  }
-
-  for (auto* dirent = readdir(dir); dirent != nullptr; dirent = readdir(dir)) {
-    util::Status status = util::OkStatus();
-    if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0)
-      continue;
-
-    if (dirent->d_type == DT_DIR) {
-      status = RegisterExtraMetrics(path, group + dirent->d_name + "/");
-    } else if (dirent->d_type == DT_REG) {
-      status = RegisterExtraMetric(path, group + dirent->d_name);
-    }
-    if (!status.ok())
-      return status;
-  }
-  return util::OkStatus();
-}
-
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-
-int TraceProcessorMain(int argc, char** argv) {
-  CommandLineOptions options = ParseCommandLineOptions(argc, argv);
-
   // Load the trace file into the trace processor.
   Config config;
-  config.force_full_sort = options.force_full_sort;
-
   std::unique_ptr<TraceProcessor> tp = TraceProcessor::CreateInstance(config);
-  g_tp = tp.get();
-
-  base::TimeNanos t_load{};
-  if (!options.trace_file_path.empty()) {
-    auto t_load_start = base::GetWallTimeNs();
-    double size_mb = 0;
-    util::Status read_status =
-        ReadTrace(tp.get(), options.trace_file_path.c_str(),
-                  [&size_mb](size_t parsed_size) {
-                    size_mb = parsed_size / 1E6;
-                    fprintf(stderr, "\rLoading trace: %.2f MB\r", size_mb);
-                  });
-    if (!read_status.ok()) {
-      PERFETTO_ELOG("Could not read trace file (path: %s): %s",
-                    options.trace_file_path.c_str(), read_status.c_message());
-      return 1;
-    }
-    t_load = base::GetWallTimeNs() - t_load_start;
-    double t_load_s = t_load.count() / 1E9;
-    PERFETTO_ILOG("Trace loaded: %.2f MB (%.1f MB/s)", size_mb,
-                  size_mb / t_load_s);
-  }  // if (!trace_file_path.empty())
-
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_HTTPD)
-  if (options.enable_httpd) {
-    RunHttpRPCServer(std::move(tp));
-    return 0;
+  base::ScopedFile fd(base::OpenFile(trace_file_path, O_RDONLY));
+  if (!fd) {
+    PERFETTO_ELOG("Could not open trace file (path: %s)", trace_file_path);
+    return 1;
   }
+
+  // Load the trace in chunks using async IO. We create a simple pipeline where,
+  // at each iteration, we parse the current chunk and asynchronously start
+  // reading the next chunk.
+
+  // 1MB chunk size seems the best tradeoff on a MacBook Pro 2013 - i7 2.8 GHz.
+  constexpr size_t kChunkSize = 1024 * 1024;
+  struct aiocb cb {};
+  cb.aio_nbytes = kChunkSize;
+  cb.aio_fildes = *fd;
+
+  std::unique_ptr<uint8_t[]> aio_buf(new uint8_t[kChunkSize]);
+#if defined(MEMORY_SANITIZER)
+  // Just initialize the memory to make the memory sanitizer happy as it
+  // cannot track aio calls below.
+  memset(aio_buf.get(), 0, kChunkSize);
 #endif
+  cb.aio_buf = aio_buf.get();
+
+  PERFETTO_CHECK(aio_read(&cb) == 0);
+  struct aiocb* aio_list[1] = {&cb};
+
+  uint64_t file_size = 0;
+  auto t_load_start = base::GetWallTimeMs();
+  for (int i = 0;; i++) {
+    if (i % 128 == 0)
+      fprintf(stderr, "\rLoading trace: %.2f MB\r", file_size / 1E6);
+
+    // Block waiting for the pending read to complete.
+    PERFETTO_CHECK(aio_suspend(aio_list, 1, nullptr) == 0);
+    auto rsize = aio_return(&cb);
+    if (rsize <= 0)
+      break;
+    file_size += static_cast<uint64_t>(rsize);
+
+    // Take ownership of the completed buffer and enqueue a new async read
+    // with a fresh buffer.
+    std::unique_ptr<uint8_t[]> buf(std::move(aio_buf));
+    aio_buf.reset(new uint8_t[kChunkSize]);
+#if defined(MEMORY_SANITIZER)
+    // Just initialize the memory to make the memory sanitizer happy as it
+    // cannot track aio calls below.
+    memset(aio_buf.get(), 0, kChunkSize);
+#endif
+    cb.aio_buf = aio_buf.get();
+    cb.aio_offset += rsize;
+    PERFETTO_CHECK(aio_read(&cb) == 0);
+
+    // Parse the completed buffer while the async read is in-flight.
+    tp->Parse(std::move(buf), static_cast<size_t>(rsize));
+  }
+  tp->NotifyEndOfFile();
+  double t_load = (base::GetWallTimeMs() - t_load_start).count() / 1E3;
+  double size_mb = file_size / 1E6;
+  PERFETTO_ILOG("Trace loaded: %.2f MB (%.1f MB/s)", size_mb, size_mb / t_load);
+  g_tp = tp.get();
 
 #if PERFETTO_HAS_SIGNAL_H()
   signal(SIGINT, [](int) { g_tp->InterruptQuery(); });
@@ -937,100 +591,22 @@
     return 1;
   }
 
-  auto t_run_start = base::GetWallTimeNs();
-
-  // Descriptor pool used for printing output as textproto.
-  google::protobuf::DescriptorPool pool;
-  google::protobuf::FileDescriptorSet root_desc_set;
-  root_desc_set.ParseFromArray(kMetricsDescriptor.data(),
-                               kMetricsDescriptor.size());
-  for (const auto& desc : root_desc_set.file()) {
-    pool.BuildFile(desc);
-  }
-
-  if (!options.metric_extra.empty()) {
-    util::Status status = RegisterExtraMetrics(options.metric_extra, "");
-    if (!status.ok()) {
-      PERFETTO_ELOG("Failed to register extra metrics: %s", status.c_message());
-      return 1;
-    }
-
-    auto ext_proto = options.metric_extra + "/metrics-ext.proto";
-    // Check if the file exists
-    base::ScopedFile file(base::OpenFile(ext_proto, O_RDONLY));
-    if (file.get() != -1) {
-      status = ExtendMetricsProto(ext_proto, &pool);
-      if (!status.ok()) {
-        PERFETTO_ELOG("Failed to extend metrics proto: %s", status.c_message());
-        return 1;
-      }
-    }
-  }
-
-  if (!options.metric_names.empty()) {
+  // First, see if we have some metrics to run. If we do, just run them and
+  // return.
+  if (metric_names) {
     std::vector<std::string> metrics;
-    for (base::StringSplitter ss(options.metric_names, ','); ss.Next();) {
+    for (base::StringSplitter ss(metric_names, ','); ss.Next();) {
       metrics.emplace_back(ss.cur_token());
     }
-
-    // For all metrics which are files, register them and extend the metrics
-    // proto.
-    for (size_t i = 0; i < metrics.size(); ++i) {
-      const std::string& metric_or_path = metrics[i];
-
-      // If there is no extension, we assume it is a builtin metric.
-      auto ext_idx = metric_or_path.rfind(".");
-      if (ext_idx == std::string::npos)
-        continue;
-
-      std::string no_ext_name = metric_or_path.substr(0, ext_idx);
-      util::Status status = RegisterMetric(no_ext_name + ".sql");
-      if (!status.ok()) {
-        PERFETTO_ELOG("Unable to register metric %s: %s",
-                      metric_or_path.c_str(), status.c_message());
-        return 1;
-      }
-
-      status = ExtendMetricsProto(no_ext_name + ".proto", &pool);
-      if (!status.ok()) {
-        PERFETTO_ELOG("Unable to extend metrics proto %s: %s",
-                      metric_or_path.c_str(), status.c_message());
-        return 1;
-      }
-
-      auto slash_idx = no_ext_name.rfind('/');
-      std::string basename = slash_idx == std::string::npos
-                                 ? no_ext_name
-                                 : no_ext_name.substr(slash_idx + 1);
-      metrics[i] = basename;
-    }
-
-    OutputFormat format;
-    if (!options.query_file_path.empty()) {
-      format = OutputFormat::kNone;
-    } else if (options.metric_output == "binary") {
-      format = OutputFormat::kBinaryProto;
-    } else if (options.metric_output == "json") {
-      format = OutputFormat::kJson;
-    } else {
-      format = OutputFormat::kTextProto;
-    }
-    int ret = RunMetrics(std::move(metrics), format, pool);
-    if (!ret) {
-      auto t_query = base::GetWallTimeNs() - t_run_start;
-      ret = MaybePrintPerfFile(options.perf_file_path, t_load, t_query);
-    }
-    if (ret)
-      return ret;
+    return RunMetrics(std::move(metrics));
   }
 
   // If we were given a query file, load contents
   std::vector<std::string> queries;
-  if (!options.query_file_path.empty()) {
-    base::ScopedFstream file(fopen(options.query_file_path.c_str(), "r"));
+  if (query_file_path) {
+    base::ScopedFstream file(fopen(query_file_path, "r"));
     if (!file) {
-      PERFETTO_ELOG("Could not open query file (path: %s)",
-                    options.query_file_path.c_str());
+      PERFETTO_ELOG("Could not open query file (path: %s)", query_file_path);
       return 1;
     }
     if (!LoadQueries(file.get(), &queries)) {
@@ -1042,16 +618,18 @@
     return 1;
   }
 
-  if (!options.sqlite_file_path.empty()) {
-    return ExportTraceToDatabase(options.sqlite_file_path);
+  // After this we can dump the database and exit if needed.
+  if (sqlite_file_path) {
+    return ExportTraceToDatabase(sqlite_file_path);
   }
 
-  if (!options.launch_shell) {
-    auto t_query = base::GetWallTimeNs() - t_run_start;
-    return MaybePrintPerfFile(options.perf_file_path, t_load, t_query);
+  // If we ran an automated query, exit.
+  if (!launch_shell) {
+    return 0;
   }
 
-  return StartInteractiveShell(options.wide ? 40 : 20);
+  // Otherwise start an interactive shell.
+  return StartInteractiveShell();
 }
 
 }  // namespace
diff --git a/src/trace_processor/trace_processor_storage.cc b/src/trace_processor/trace_processor_storage.cc
deleted file mode 100644
index f72c2a6..0000000
--- a/src/trace_processor/trace_processor_storage.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/trace_processor/trace_processor_storage.h"
-
-#include "src/trace_processor/trace_processor_storage_impl.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// static
-std::unique_ptr<TraceProcessorStorage> TraceProcessorStorage::CreateInstance(
-    const Config& config) {
-  return std::unique_ptr<TraceProcessorStorage>(
-      new TraceProcessorStorageImpl(config));
-}
-
-TraceProcessorStorage::~TraceProcessorStorage() = default;
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/trace_processor_storage_impl.cc b/src/trace_processor/trace_processor_storage_impl.cc
deleted file mode 100644
index cc86e0b..0000000
--- a/src/trace_processor/trace_processor_storage_impl.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/trace_processor_storage_impl.h"
-
-#include "perfetto/base/logging.h"
-#include "src/trace_processor/args_tracker.h"
-#include "src/trace_processor/binder_tracker.h"
-#include "src/trace_processor/clock_tracker.h"
-#include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/forwarding_trace_parser.h"
-#include "src/trace_processor/heap_profile_tracker.h"
-#include "src/trace_processor/importers/ftrace/ftrace_module.h"
-#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
-#include "src/trace_processor/importers/proto/android_probes_module.h"
-#include "src/trace_processor/importers/proto/graphics_event_module.h"
-#include "src/trace_processor/importers/proto/heap_graph_module.h"
-#include "src/trace_processor/importers/proto/heap_graph_tracker.h"
-#include "src/trace_processor/importers/proto/proto_importer_module.h"
-#include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
-#include "src/trace_processor/importers/proto/system_probes_module.h"
-#include "src/trace_processor/importers/proto/track_event_module.h"
-#include "src/trace_processor/importers/systrace/systrace_parser.h"
-#include "src/trace_processor/importers/systrace/systrace_trace_parser.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/slice_tracker.h"
-#include "src/trace_processor/stack_profile_tracker.h"
-#include "src/trace_processor/syscall_tracker.h"
-#include "src/trace_processor/trace_blob_view.h"
-#include "src/trace_processor/trace_sorter.h"
-#include "src/trace_processor/track_tracker.h"
-#include "src/trace_processor/vulkan_memory_tracker.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-TraceProcessorStorageImpl::TraceProcessorStorageImpl(const Config& cfg) {
-  context_.config = cfg;
-  context_.storage.reset(new TraceStorage());
-  context_.track_tracker.reset(new TrackTracker(&context_));
-  context_.args_tracker.reset(new ArgsTracker(&context_));
-  context_.slice_tracker.reset(new SliceTracker(&context_));
-  context_.event_tracker.reset(new EventTracker(&context_));
-  context_.process_tracker.reset(new ProcessTracker(&context_));
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_SYSCALLS)
-  context_.syscall_tracker.reset(new SyscallTracker(&context_));
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_SYSCALLS)
-  context_.clock_tracker.reset(new ClockTracker(&context_));
-  context_.heap_profile_tracker.reset(new HeapProfileTracker(&context_));
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-  context_.sched_tracker.reset(new SchedEventTracker(&context_));
-  context_.systrace_parser.reset(new SystraceParser(&context_));
-  context_.binder_tracker.reset(new BinderTracker(&context_));
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_GRAPHICS)
-  context_.vulkan_memory_tracker.reset(new VulkanMemoryTracker(&context_));
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_GRAPHICS)
-  context_.ftrace_module.reset(
-      new ProtoImporterModule<FtraceModule>(&context_));
-  context_.track_event_module.reset(
-      new ProtoImporterModule<TrackEventModule>(&context_));
-  context_.system_probes_module.reset(
-      new ProtoImporterModule<SystemProbesModule>(&context_));
-  context_.android_probes_module.reset(
-      new ProtoImporterModule<AndroidProbesModule>(&context_));
-  context_.heap_graph_module.reset(
-      new ProtoImporterModule<HeapGraphModule>(&context_));
-  context_.graphics_event_module.reset(
-      new ProtoImporterModule<GraphicsEventModule>(&context_));
-}
-
-TraceProcessorStorageImpl::~TraceProcessorStorageImpl() {}
-
-util::Status TraceProcessorStorageImpl::Parse(std::unique_ptr<uint8_t[]> data,
-                                              size_t size) {
-  if (size == 0)
-    return util::OkStatus();
-  if (unrecoverable_parse_error_)
-    return util::ErrStatus(
-        "Failed unrecoverably while parsing in a previous Parse call");
-  if (!context_.chunk_reader)
-    context_.chunk_reader.reset(new ForwardingTraceParser(&context_));
-
-  auto scoped_trace = context_.storage->TraceExecutionTimeIntoStats(
-      stats::parse_trace_duration_ns);
-  util::Status status = context_.chunk_reader->Parse(std::move(data), size);
-  unrecoverable_parse_error_ |= !status.ok();
-  return status;
-}
-
-void TraceProcessorStorageImpl::NotifyEndOfFile() {
-  if (unrecoverable_parse_error_ || !context_.chunk_reader)
-    return;
-
-  if (context_.sorter)
-    context_.sorter->ExtractEventsForced();
-#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-  context_.sched_tracker->FlushPendingEvents();
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
-  context_.event_tracker->FlushPendingEvents();
-  context_.slice_tracker->FlushPendingSlices();
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/trace_processor_storage_impl.h b/src/trace_processor/trace_processor_storage_impl.h
deleted file mode 100644
index 41f1273..0000000
--- a/src/trace_processor/trace_processor_storage_impl.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_TRACE_PROCESSOR_STORAGE_IMPL_H_
-#define SRC_TRACE_PROCESSOR_TRACE_PROCESSOR_STORAGE_IMPL_H_
-
-#include <memory>
-
-#include "perfetto/trace_processor/basic_types.h"
-#include "perfetto/trace_processor/status.h"
-#include "perfetto/trace_processor/trace_processor_storage.h"
-#include "src/trace_processor/trace_processor_context.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorStorageImpl : public TraceProcessorStorage {
- public:
-  explicit TraceProcessorStorageImpl(const Config&);
-  ~TraceProcessorStorageImpl() override;
-
-  util::Status Parse(std::unique_ptr<uint8_t[]>, size_t) override;
-  void NotifyEndOfFile() override;
-
-  TraceProcessorContext* context() { return &context_; }
-
- protected:
-  TraceProcessorContext context_;
-  bool unrecoverable_parse_error_ = false;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_TRACE_PROCESSOR_STORAGE_IMPL_H_
diff --git a/src/trace_processor/trace_sorter.cc b/src/trace_processor/trace_sorter.cc
index 49cd78e..b5428d9 100644
--- a/src/trace_processor/trace_sorter.cc
+++ b/src/trace_processor/trace_sorter.cc
@@ -17,8 +17,7 @@
 #include <algorithm>
 #include <utility>
 
-#include "perfetto/ext/base/utils.h"
-#include "src/trace_processor/importers/proto/proto_trace_parser.h"
+#include "src/trace_processor/proto_trace_parser.h"
 #include "src/trace_processor/trace_sorter.h"
 
 namespace perfetto {
@@ -40,7 +39,7 @@
   // smaller than max_ts_.
   PERFETTO_DCHECK(sort_min_ts_ < max_ts_);
 
-  // We know that all events between [0, sort_start_idx_] are sorted. Within
+  // We know that all events between [0, sort_start_idx_] are sorted. Witin
   // this range, perform a bound search and find the iterator for the min
   // timestamp that broke the monotonicity. Re-sort from there to the end.
   auto sort_end = events_.begin() + static_cast<ssize_t>(sort_start_idx_);
@@ -77,7 +76,6 @@
 // time in a profiler.
 void TraceSorter::SortAndExtractEventsBeyondWindow(int64_t window_size_ns) {
   DCHECK_ftrace_batch_cpu(kNoBatch);
-
   constexpr int64_t kTsMax = std::numeric_limits<int64_t>::max();
   const bool was_empty = global_min_ts_ == kTsMax && global_max_ts_ == 0;
   int64_t extract_end_ts = global_max_ts_ - window_size_ns;
diff --git a/src/trace_processor/trace_sorter.h b/src/trace_processor/trace_sorter.h
index 82f5acd..4178f3d 100644
--- a/src/trace_processor/trace_sorter.h
+++ b/src/trace_processor/trace_sorter.h
@@ -19,23 +19,26 @@
 
 #include <vector>
 
-#include "perfetto/ext/base/circular_queue.h"
+#include "perfetto/base/circular_queue.h"
 #include "perfetto/trace_processor/basic_types.h"
-#include "src/trace_processor/timestamped_trace_piece.h"
+#include "src/trace_processor/fuchsia_provider_view.h"
+#include "src/trace_processor/proto_incremental_state.h"
 #include "src/trace_processor/trace_blob_view.h"
 #include "src/trace_processor/trace_processor_context.h"
 #include "src/trace_processor/trace_storage.h"
 
+#if PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD)
+#include <json/value.h>
+#else
+// Json traces are only supported in standalone build.
 namespace Json {
-class Value;
+class Value {};
 }  // namespace Json
+#endif
 
 namespace perfetto {
 namespace trace_processor {
 
-class FuchsiaProviderView;
-class PacketSequenceState;
-
 // This class takes care of sorting events parsed from the trace stream in
 // arbitrary order and pushing them to the next pipeline stages (parsing) in
 // order. In order to support streaming use-cases, sorting happens within a
@@ -65,15 +68,102 @@
 // from there to the end.
 class TraceSorter {
  public:
+  struct TimestampedTracePiece {
+    TimestampedTracePiece(int64_t ts, uint64_t idx, TraceBlobView tbv)
+        : TimestampedTracePiece(ts,
+                                /*thread_ts=*/0,
+                                idx,
+                                std::move(tbv),
+                                /*value=*/nullptr,
+                                /*fpv=*/nullptr,
+                                /*sequence_state=*/nullptr) {}
+
+    TimestampedTracePiece(int64_t ts,
+                          uint64_t idx,
+                          std::unique_ptr<Json::Value> value)
+        : TimestampedTracePiece(ts,
+                                /*thread_ts=*/0,
+                                idx,
+                                // TODO(dproy): Stop requiring TraceBlobView in
+                                // TimestampedTracePiece.
+                                TraceBlobView(nullptr, 0, 0),
+                                std::move(value),
+                                /*fpv=*/nullptr,
+                                /*sequence_state=*/nullptr) {}
+
+    TimestampedTracePiece(int64_t ts,
+                          uint64_t idx,
+                          TraceBlobView tbv,
+                          std::unique_ptr<FuchsiaProviderView> fpv)
+        : TimestampedTracePiece(ts,
+                                /*thread_ts=*/0,
+                                idx,
+                                std::move(tbv),
+                                /*value=*/nullptr,
+                                std::move(fpv),
+                                /*sequence_state=*/nullptr) {}
+
+    TimestampedTracePiece(
+        int64_t ts,
+        int64_t thread_ts,
+        uint64_t idx,
+        TraceBlobView tbv,
+        ProtoIncrementalState::PacketSequenceState* sequence_state)
+        : TimestampedTracePiece(ts,
+                                thread_ts,
+                                idx,
+                                std::move(tbv),
+                                /*value=*/nullptr,
+                                /*fpv=*/nullptr,
+                                sequence_state) {}
+
+    TimestampedTracePiece(
+        int64_t ts,
+        int64_t thread_ts,
+        uint64_t idx,
+        TraceBlobView tbv,
+        std::unique_ptr<Json::Value> value,
+        std::unique_ptr<FuchsiaProviderView> fpv,
+        ProtoIncrementalState::PacketSequenceState* sequence_state)
+        : json_value(std::move(value)),
+          fuchsia_provider_view(std::move(fpv)),
+          packet_sequence_state(sequence_state),
+          timestamp(ts),
+          thread_timestamp(thread_ts),
+          packet_idx_(idx),
+          blob_view(std::move(tbv)) {}
+
+    TimestampedTracePiece(TimestampedTracePiece&&) noexcept = default;
+    TimestampedTracePiece& operator=(TimestampedTracePiece&&) = default;
+
+    // For std::lower_bound().
+    static inline bool Compare(const TimestampedTracePiece& x, int64_t ts) {
+      return x.timestamp < ts;
+    }
+
+    // For std::sort().
+    inline bool operator<(const TimestampedTracePiece& o) const {
+      return timestamp < o.timestamp ||
+             (timestamp == o.timestamp && packet_idx_ < o.packet_idx_);
+    }
+
+    std::unique_ptr<Json::Value> json_value;
+    std::unique_ptr<FuchsiaProviderView> fuchsia_provider_view;
+    ProtoIncrementalState::PacketSequenceState* packet_sequence_state;
+
+    int64_t timestamp;
+    int64_t thread_timestamp;
+    uint64_t packet_idx_;
+    TraceBlobView blob_view;
+  };
+
   TraceSorter(TraceProcessorContext*, int64_t window_size_ns);
 
-  inline void PushTracePacket(int64_t timestamp,
-                              PacketSequenceState* state,
-                              TraceBlobView packet) {
+  inline void PushTracePacket(int64_t timestamp, TraceBlobView packet) {
     DCHECK_ftrace_batch_cpu(kNoBatch);
     auto* queue = GetQueue(0);
-    queue->Append(TimestampedTracePiece(timestamp, packet_idx_++,
-                                        std::move(packet), state));
+    queue->Append(
+        TimestampedTracePiece(timestamp, packet_idx_++, std::move(packet)));
     MaybeExtractEvents(queue);
   }
 
@@ -109,29 +199,13 @@
     // for a bundle are pushed.
   }
 
-  // As with |PushFtraceEvent|, doesn't immediately sort the affected queues.
-  // TODO(rsavitski): if a trace has a mix of normal & "compact" events (being
-  // pushed through this function), the ftrace batches will no longer be fully
-  // sorted by timestamp. In such situations, we will have to sort at the end of
-  // the batch. We can do better as both sub-sequences are sorted however.
-  // Consider adding extra queues, or pushing them in a merge-sort fashion
-  // instead.
-  inline void PushInlineFtraceEvent(uint32_t cpu,
-                                    int64_t timestamp,
-                                    InlineEvent inline_event) {
-    set_ftrace_batch_cpu_for_DCHECK(cpu);
-    GetQueue(cpu + 1)->Append(
-        TimestampedTracePiece(timestamp, packet_idx_++, inline_event));
-  }
-
-  inline void PushTrackEventPacket(int64_t timestamp,
-                                   int64_t thread_time,
-                                   int64_t thread_instruction_count,
-                                   PacketSequenceState* state,
-                                   TraceBlobView packet) {
+  inline void PushTrackEventPacket(
+      int64_t timestamp,
+      int64_t thread_time,
+      ProtoIncrementalState::PacketSequenceState* state,
+      TraceBlobView packet) {
     auto* queue = GetQueue(0);
-    queue->Append(TimestampedTracePiece(timestamp, thread_time,
-                                        thread_instruction_count, packet_idx_++,
+    queue->Append(TimestampedTracePiece(timestamp, thread_time, packet_idx_++,
                                         std::move(packet), state));
     MaybeExtractEvents(queue);
   }
@@ -147,25 +221,10 @@
     SortAndExtractEventsBeyondWindow(/*window_size_ns=*/0);
   }
 
-  // Sets the window size to be the size specified (which should be lower than
-  // any previous window size specified) and flushes any data beyond
-  // this window size.
-  // It is undefined to call this function with a window size greater than than
-  // the current size.
-  void SetWindowSizeNs(int64_t window_size_ns) {
-    PERFETTO_DCHECK(window_size_ns <= window_size_ns_);
-
-    PERFETTO_DLOG("Setting window size to be %" PRId64 " ns", window_size_ns);
+  void set_window_ns_for_testing(int64_t window_size_ns) {
     window_size_ns_ = window_size_ns;
-
-    // Fast path: if, globally, we are within the window size, then just exit.
-    if (global_max_ts_ - global_min_ts_ < window_size_ns)
-      return;
-    SortAndExtractEventsBeyondWindow(window_size_ns_);
   }
 
-  int64_t max_timestamp() const { return global_max_ts_; }
-
  private:
   static constexpr uint32_t kNoBatch = std::numeric_limits<uint32_t>::max();
 
@@ -221,9 +280,9 @@
     global_max_ts_ = std::max(global_max_ts_, queue->max_ts_);
     global_min_ts_ = std::min(global_min_ts_, queue->min_ts_);
 
-    // Fast path: if, globally, we are within the window size, then just exit.
     if (global_max_ts_ - global_min_ts_ < window_size_ns_)
       return;
+
     SortAndExtractEventsBeyondWindow(window_size_ns_);
   }
 
diff --git a/src/trace_processor/trace_sorter_unittest.cc b/src/trace_processor/trace_sorter_unittest.cc
index fa0a34a..8183db9 100644
--- a/src/trace_processor/trace_sorter_unittest.cc
+++ b/src/trace_processor/trace_sorter_unittest.cc
@@ -13,17 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "src/trace_processor/importers/proto/proto_trace_parser.h"
+#include "src/trace_processor/proto_trace_parser.h"
 
 #include <map>
 #include <random>
 #include <vector>
 
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
 #include "perfetto/trace_processor/basic_types.h"
-#include "src/trace_processor/timestamped_trace_piece.h"
 #include "src/trace_processor/trace_processor_context.h"
 #include "src/trace_processor/trace_sorter.h"
-#include "test/gtest_and_gmock.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -32,7 +33,6 @@
 using ::testing::_;
 using ::testing::InSequence;
 using ::testing::Invoke;
-using ::testing::MockFunction;
 using ::testing::NiceMock;
 
 class MockTraceParser : public ProtoTraceParser {
@@ -47,7 +47,7 @@
 
   void ParseFtracePacket(uint32_t cpu,
                          int64_t timestamp,
-                         TimestampedTracePiece ttp) override {
+                         TraceSorter::TimestampedTracePiece ttp) override {
     TraceBlobView& tbv = ttp.blob_view;
     MOCK_ParseFtracePacket(cpu, timestamp, tbv.data(), tbv.length());
   }
@@ -55,7 +55,8 @@
   MOCK_METHOD3(MOCK_ParseTracePacket,
                void(int64_t ts, const uint8_t* data, size_t length));
 
-  void ParseTracePacket(int64_t ts, TimestampedTracePiece ttp) override {
+  void ParseTracePacket(int64_t ts,
+                        TraceSorter::TimestampedTracePiece ttp) override {
     TraceBlobView& tbv = ttp.blob_view;
     MOCK_ParseTracePacket(ts, tbv.data(), tbv.length());
   }
@@ -74,8 +75,7 @@
       : test_buffer_(std::unique_ptr<uint8_t[]>(new uint8_t[8]), 0, 8) {
     storage_ = new NiceMock<MockTraceStorage>();
     context_.storage.reset(storage_);
-    context_.sorter.reset(new TraceSorter(
-        &context_, std::numeric_limits<int64_t>::max() /*window_size*/));
+    context_.sorter.reset(new TraceSorter(&context_, 0 /*window_size*/));
     parser_ = new MockTraceParser(&context_);
     context_.parser.reset(parser_);
   }
@@ -99,7 +99,7 @@
 TEST_F(TraceSorterTest, TestTracePacket) {
   TraceBlobView view = test_buffer_.slice(0, 1);
   EXPECT_CALL(*parser_, MOCK_ParseTracePacket(1000, view.data(), 1));
-  context_.sorter->PushTracePacket(1000, nullptr, std::move(view));
+  context_.sorter->PushTracePacket(1000, std::move(view));
   context_.sorter->FinalizeFtraceEventBatch(1000);
   context_.sorter->ExtractEventsForced();
 }
@@ -117,12 +117,12 @@
   EXPECT_CALL(*parser_, MOCK_ParseTracePacket(1100, view_3.data(), 3));
   EXPECT_CALL(*parser_, MOCK_ParseFtracePacket(2, 1200, view_4.data(), 4));
 
-  context_.sorter->SetWindowSizeNs(200);
+  context_.sorter->set_window_ns_for_testing(200);
   context_.sorter->PushFtraceEvent(2 /*cpu*/, 1200 /*timestamp*/,
                                    std::move(view_4));
   context_.sorter->FinalizeFtraceEventBatch(2);
-  context_.sorter->PushTracePacket(1001, nullptr, std::move(view_2));
-  context_.sorter->PushTracePacket(1100, nullptr, std::move(view_3));
+  context_.sorter->PushTracePacket(1001, std::move(view_2));
+  context_.sorter->PushTracePacket(1100, std::move(view_3));
   context_.sorter->PushFtraceEvent(0 /*cpu*/, 1000 /*timestamp*/,
                                    std::move(view_1));
 
@@ -130,52 +130,6 @@
   context_.sorter->ExtractEventsForced();
 }
 
-TEST_F(TraceSorterTest, SetWindowSize) {
-  TraceBlobView view_1 = test_buffer_.slice(0, 1);
-  TraceBlobView view_2 = test_buffer_.slice(0, 2);
-  TraceBlobView view_3 = test_buffer_.slice(0, 3);
-  TraceBlobView view_4 = test_buffer_.slice(0, 4);
-
-  MockFunction<void(std::string check_point_name)> check;
-
-  {
-    InSequence s;
-
-    EXPECT_CALL(*parser_, MOCK_ParseFtracePacket(0, 1000, view_1.data(), 1));
-    EXPECT_CALL(*parser_, MOCK_ParseTracePacket(1001, view_2.data(), 2));
-    EXPECT_CALL(check, Call("1"));
-    EXPECT_CALL(*parser_, MOCK_ParseTracePacket(1100, view_3.data(), 3));
-    EXPECT_CALL(check, Call("2"));
-    EXPECT_CALL(*parser_, MOCK_ParseFtracePacket(2, 1200, view_4.data(), 4));
-  }
-
-  context_.sorter->SetWindowSizeNs(200);
-  context_.sorter->PushFtraceEvent(2 /*cpu*/, 1200 /*timestamp*/,
-                                   std::move(view_4));
-  context_.sorter->FinalizeFtraceEventBatch(2);
-  context_.sorter->PushTracePacket(1001, nullptr, std::move(view_2));
-  context_.sorter->PushTracePacket(1100, nullptr, std::move(view_3));
-
-  context_.sorter->PushFtraceEvent(0 /*cpu*/, 1000 /*timestamp*/,
-                                   std::move(view_1));
-  context_.sorter->FinalizeFtraceEventBatch(0);
-
-  // At this point, we should just flush the 1000 and 1001 packets.
-  context_.sorter->SetWindowSizeNs(101);
-
-  // Inform the mock about where we are.
-  check.Call("1");
-
-  // Now we should flush the 1100 packet.
-  context_.sorter->SetWindowSizeNs(99);
-
-  // Inform the mock about where we are.
-  check.Call("2");
-
-  // Now we should flush the 1200 packet.
-  context_.sorter->ExtractEventsForced();
-}
-
 // Simulates a random stream of ftrace events happening on random CPUs.
 // Tests that the output of the TraceSorter matches the timestamp order
 // (% events happening at the same time on different CPUs).
diff --git a/src/trace_processor/trace_storage.cc b/src/trace_processor/trace_storage.cc
index 1b9f256..a0892b4 100644
--- a/src/trace_processor/trace_storage.cc
+++ b/src/trace_processor/trace_storage.cc
@@ -20,7 +20,7 @@
 #include <algorithm>
 #include <limits>
 
-#include "perfetto/ext/base/no_destructor.h"
+#include "perfetto/base/no_destructor.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -41,15 +41,13 @@
 }
 
 std::vector<const char*> CreateRefTypeStringMap() {
-  std::vector<const char*> map(static_cast<size_t>(RefType::kRefMax));
-  map[static_cast<size_t>(RefType::kRefNoRef)] = nullptr;
-  map[static_cast<size_t>(RefType::kRefUtid)] = "utid";
-  map[static_cast<size_t>(RefType::kRefCpuId)] = "cpu";
-  map[static_cast<size_t>(RefType::kRefGpuId)] = "gpu";
-  map[static_cast<size_t>(RefType::kRefIrq)] = "irq";
-  map[static_cast<size_t>(RefType::kRefSoftIrq)] = "softirq";
-  map[static_cast<size_t>(RefType::kRefUpid)] = "upid";
-  map[static_cast<size_t>(RefType::kRefTrack)] = "track";
+  std::vector<const char*> map(RefType::kRefMax);
+  map[RefType::kRefNoRef] = nullptr;
+  map[RefType::kRefUtid] = "utid";
+  map[RefType::kRefCpuId] = "cpu";
+  map[RefType::kRefIrq] = "irq";
+  map[RefType::kRefSoftIrq] = "softirq";
+  map[RefType::kRefUpid] = "upid";
   return map;
 }
 
@@ -69,6 +67,10 @@
 
 TraceStorage::~TraceStorage() {}
 
+void TraceStorage::ResetStorage() {
+  *this = TraceStorage();
+}
+
 uint32_t TraceStorage::SqlStats::RecordQueryBegin(const std::string& query,
                                                   int64_t time_queued,
                                                   int64_t time_started) {
@@ -122,18 +124,10 @@
                     nestable_slices_.start_ns().end(), &start_ns, &end_ns);
   MaybeUpdateMinMax(android_log_.timestamps().begin(),
                     android_log_.timestamps().end(), &start_ns, &end_ns);
-  MaybeUpdateMinMax(raw_events_.timestamps().begin(),
-                    raw_events_.timestamps().end(), &start_ns, &end_ns);
-  MaybeUpdateMinMax(heap_profile_allocations_.timestamps().begin(),
-                    heap_profile_allocations_.timestamps().end(), &start_ns,
-                    &end_ns);
 
   if (start_ns == std::numeric_limits<int64_t>::max()) {
     return std::make_pair(0, 0);
   }
-  if (start_ns == end_ns) {
-    end_ns += 1;
-  }
   return std::make_pair(start_ns, end_ns);
 }
 
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index 7243b42..36f8164 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -25,20 +25,15 @@
 #include <utility>
 #include <vector>
 
+#include "perfetto/base/hash.h"
 #include "perfetto/base/logging.h"
+#include "perfetto/base/optional.h"
+#include "perfetto/base/string_view.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/hash.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/utils.h"
 #include "src/trace_processor/ftrace_utils.h"
-#include "src/trace_processor/metadata.h"
 #include "src/trace_processor/stats.h"
 #include "src/trace_processor/string_pool.h"
-#include "src/trace_processor/tables/profiler_tables.h"
-#include "src/trace_processor/tables/slice_tables.h"
-#include "src/trace_processor/tables/track_tables.h"
-#include "src/trace_processor/variadic.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -54,7 +49,6 @@
 
 // StringId is an offset into |string_pool_|.
 using StringId = StringPool::Id;
-static const StringId kNullStringId = StringId(0);
 
 // Identifiers for all the tables in the database.
 enum TableId : uint8_t {
@@ -64,10 +58,6 @@
   kRawEvents = 2,
   kInstants = 3,
   kSched = 4,
-  kNestableSlices = 5,
-  kMetadataTable = 6,
-  kTrack = 7,
-  kVulkanMemoryAllocation = 8,
 };
 
 // The top 8 bits are set to the TableId and the bottom 32 to the row of the
@@ -78,21 +68,13 @@
 using ArgSetId = uint32_t;
 static const ArgSetId kInvalidArgSetId = 0;
 
-using TrackId = uint32_t;
-
-// TODO(lalitm): this is a temporary hack while migrating the counters table and
-// will be removed when the migration is complete.
-static const TrackId kInvalidTrackId = std::numeric_limits<TrackId>::max();
-
-enum class RefType {
+enum RefType {
   kRefNoRef = 0,
   kRefUtid = 1,
   kRefCpuId = 2,
   kRefIrq = 3,
   kRefSoftIrq = 4,
   kRefUpid = 5,
-  kRefGpuId = 6,
-  kRefTrack = 7,
   kRefMax
 };
 
@@ -111,17 +93,15 @@
   struct Process {
     explicit Process(uint32_t p) : pid(p) {}
     int64_t start_ns = 0;
-    int64_t end_ns = 0;
     StringId name_id = 0;
     uint32_t pid = 0;
-    base::Optional<UniquePid> parent_upid;
+    base::Optional<UniquePid> pupid;
   };
 
   // Information about a unique thread seen in a trace.
   struct Thread {
     explicit Thread(uint32_t t) : tid(t) {}
     int64_t start_ns = 0;
-    int64_t end_ns = 0;
     StringId name_id = 0;
     base::Optional<UniquePid> upid;
     uint32_t tid = 0;
@@ -130,6 +110,39 @@
   // Generic key value storage which can be referenced by other tables.
   class Args {
    public:
+    // Variadic type representing the possible values for the args table.
+    struct Variadic {
+      enum Type { kInt, kString, kReal };
+
+      static Variadic Integer(int64_t int_value) {
+        Variadic variadic;
+        variadic.type = Type::kInt;
+        variadic.int_value = int_value;
+        return variadic;
+      }
+
+      static Variadic String(StringId string_id) {
+        Variadic variadic;
+        variadic.type = Type::kString;
+        variadic.string_value = string_id;
+        return variadic;
+      }
+
+      static Variadic Real(double real_value) {
+        Variadic variadic;
+        variadic.type = Type::kReal;
+        variadic.real_value = real_value;
+        return variadic;
+      }
+
+      Type type;
+      union {
+        int64_t int_value;
+        StringId string_value;
+        double real_value;
+      };
+    };
+
     struct Arg {
       StringId flat_key = 0;
       StringId key = 0;
@@ -148,24 +161,12 @@
           case Variadic::Type::kInt:
             hash.Update(arg.value.int_value);
             break;
-          case Variadic::Type::kUint:
-            hash.Update(arg.value.uint_value);
-            break;
           case Variadic::Type::kString:
             hash.Update(arg.value.string_value);
             break;
           case Variadic::Type::kReal:
             hash.Update(arg.value.real_value);
             break;
-          case Variadic::Type::kPointer:
-            hash.Update(arg.value.pointer_value);
-            break;
-          case Variadic::Type::kBool:
-            hash.Update(arg.value.bool_value);
-            break;
-          case Variadic::Type::kJson:
-            hash.Update(arg.value.json_value);
-            break;
         }
         return hash.digest();
       }
@@ -217,47 +218,6 @@
     std::unordered_map<ArgSetHash, uint32_t> arg_row_for_hash_;
   };
 
-  class Tracks {
-   public:
-    inline uint32_t AddTrack(StringId name) {
-      names_.emplace_back(name);
-      return track_count() - 1;
-    }
-
-    uint32_t track_count() const {
-      return static_cast<uint32_t>(names_.size());
-    }
-
-    const std::deque<StringId>& names() const { return names_; }
-
-   private:
-    std::deque<StringId> names_;
-  };
-
-  class GpuContexts {
-   public:
-    inline void AddGpuContext(uint64_t context_id,
-                              UniquePid upid,
-                              uint32_t priority) {
-      context_ids_.emplace_back(context_id);
-      upids_.emplace_back(upid);
-      priorities_.emplace_back(priority);
-    }
-
-    uint32_t gpu_context_count() const {
-      return static_cast<uint32_t>(context_ids_.size());
-    }
-
-    const std::deque<uint64_t>& context_ids() const { return context_ids_; }
-    const std::deque<UniquePid>& upids() const { return upids_; }
-    const std::deque<uint32_t>& priorities() const { return priorities_; }
-
-   private:
-    std::deque<uint64_t> context_ids_;
-    std::deque<UniquePid> upids_;
-    std::deque<uint32_t> priorities_;
-  };
-
   class Slices {
    public:
     inline size_t AddSlice(uint32_t cpu,
@@ -323,233 +283,142 @@
 
   class NestableSlices {
    public:
-    inline uint32_t AddSlice(int64_t start_ns,
-                             int64_t duration_ns,
-                             TrackId track_id,
-                             int64_t ref,
-                             RefType type,
-                             StringId category,
-                             StringId name,
-                             uint8_t depth,
-                             int64_t stack_id,
-                             int64_t parent_stack_id) {
+    inline size_t AddSlice(int64_t start_ns,
+                           int64_t duration_ns,
+                           int64_t ref,
+                           RefType type,
+                           StringId cat,
+                           StringId name,
+                           uint8_t depth,
+                           int64_t stack_id,
+                           int64_t parent_stack_id) {
       start_ns_.emplace_back(start_ns);
       durations_.emplace_back(duration_ns);
-      track_id_.emplace_back(track_id);
       refs_.emplace_back(ref);
       types_.emplace_back(type);
-      categories_.emplace_back(category);
+      cats_.emplace_back(cat);
       names_.emplace_back(name);
       depths_.emplace_back(depth);
       stack_ids_.emplace_back(stack_id);
       parent_stack_ids_.emplace_back(parent_stack_id);
-      arg_set_ids_.emplace_back(kInvalidArgSetId);
       return slice_count() - 1;
     }
 
-    void set_duration(uint32_t index, int64_t duration_ns) {
+    void set_duration(size_t index, int64_t duration_ns) {
       durations_[index] = duration_ns;
     }
 
-    void set_stack_id(uint32_t index, int64_t stack_id) {
+    void set_stack_id(size_t index, int64_t stack_id) {
       stack_ids_[index] = stack_id;
     }
 
-    void set_arg_set_id(uint32_t index, ArgSetId id) {
-      arg_set_ids_[index] = id;
-    }
-
-    uint32_t slice_count() const {
-      return static_cast<uint32_t>(start_ns_.size());
-    }
-
+    size_t slice_count() const { return start_ns_.size(); }
     const std::deque<int64_t>& start_ns() const { return start_ns_; }
     const std::deque<int64_t>& durations() const { return durations_; }
-    const std::deque<TrackId>& track_id() const { return track_id_; }
     const std::deque<int64_t>& refs() const { return refs_; }
     const std::deque<RefType>& types() const { return types_; }
-    const std::deque<StringId>& categories() const { return categories_; }
+    const std::deque<StringId>& cats() const { return cats_; }
     const std::deque<StringId>& names() const { return names_; }
     const std::deque<uint8_t>& depths() const { return depths_; }
     const std::deque<int64_t>& stack_ids() const { return stack_ids_; }
     const std::deque<int64_t>& parent_stack_ids() const {
       return parent_stack_ids_;
     }
-    const std::deque<ArgSetId>& arg_set_ids() const { return arg_set_ids_; }
 
    private:
     std::deque<int64_t> start_ns_;
     std::deque<int64_t> durations_;
-    std::deque<TrackId> track_id_;
     std::deque<int64_t> refs_;
     std::deque<RefType> types_;
-    std::deque<StringId> categories_;
+    std::deque<StringId> cats_;
     std::deque<StringId> names_;
     std::deque<uint8_t> depths_;
     std::deque<int64_t> stack_ids_;
     std::deque<int64_t> parent_stack_ids_;
-    std::deque<ArgSetId> arg_set_ids_;
   };
 
-  class ThreadSlices {
+  class CounterDefinitions {
    public:
-    inline uint32_t AddThreadSlice(uint32_t slice_id,
-                                   int64_t thread_timestamp_ns,
-                                   int64_t thread_duration_ns,
-                                   int64_t thread_instruction_count,
-                                   int64_t thread_instruction_delta) {
-      slice_ids_.emplace_back(slice_id);
-      thread_timestamp_ns_.emplace_back(thread_timestamp_ns);
-      thread_duration_ns_.emplace_back(thread_duration_ns);
-      thread_instruction_counts_.emplace_back(thread_instruction_count);
-      thread_instruction_deltas_.emplace_back(thread_instruction_delta);
-      return slice_count() - 1;
+    using Id = uint32_t;
+    static constexpr Id kInvalidId = std::numeric_limits<Id>::max();
+
+    inline Id AddCounterDefinition(StringId name_id,
+                                   int64_t ref,
+                                   RefType type) {
+      base::Hash hash;
+      hash.Update(name_id);
+      hash.Update(ref);
+      hash.Update(type);
+
+      // TODO(lalitm): this is a perf bottleneck and likely we can do something
+      // quite a bit better here.
+      uint64_t digest = hash.digest();
+      auto it = hash_to_row_idx_.find(digest);
+      if (it != hash_to_row_idx_.end())
+        return it->second;
+
+      name_ids_.emplace_back(name_id);
+      refs_.emplace_back(ref);
+      types_.emplace_back(type);
+      hash_to_row_idx_.emplace(digest, size() - 1);
+      return size() - 1;
     }
 
-    uint32_t slice_count() const {
-      return static_cast<uint32_t>(slice_ids_.size());
-    }
+    uint32_t size() const { return static_cast<uint32_t>(name_ids_.size()); }
 
-    const std::deque<uint32_t>& slice_ids() const { return slice_ids_; }
-    const std::deque<int64_t>& thread_timestamp_ns() const {
-      return thread_timestamp_ns_;
-    }
-    const std::deque<int64_t>& thread_duration_ns() const {
-      return thread_duration_ns_;
-    }
-    const std::deque<int64_t>& thread_instruction_counts() const {
-      return thread_instruction_counts_;
-    }
-    const std::deque<int64_t>& thread_instruction_deltas() const {
-      return thread_instruction_deltas_;
-    }
+    const std::deque<StringId>& name_ids() const { return name_ids_; }
 
-    base::Optional<uint32_t> FindRowForSliceId(uint32_t slice_id) const {
-      auto it =
-          std::lower_bound(slice_ids().begin(), slice_ids().end(), slice_id);
-      if (it != slice_ids().end() && *it == slice_id) {
-        return static_cast<uint32_t>(std::distance(slice_ids().begin(), it));
-      }
-      return base::nullopt;
-    }
+    const std::deque<int64_t>& refs() const { return refs_; }
 
-    void UpdateThreadDeltasForSliceId(uint32_t slice_id,
-                                      int64_t end_thread_timestamp_ns,
-                                      int64_t end_thread_instruction_count) {
-      uint32_t row = *FindRowForSliceId(slice_id);
-      int64_t begin_ns = thread_timestamp_ns_[row];
-      thread_duration_ns_[row] = end_thread_timestamp_ns - begin_ns;
-      int64_t begin_ticount = thread_instruction_counts_[row];
-      thread_instruction_deltas_[row] =
-          end_thread_instruction_count - begin_ticount;
-    }
+    const std::deque<RefType>& types() const { return types_; }
 
    private:
-    std::deque<uint32_t> slice_ids_;
-    std::deque<int64_t> thread_timestamp_ns_;
-    std::deque<int64_t> thread_duration_ns_;
-    std::deque<int64_t> thread_instruction_counts_;
-    std::deque<int64_t> thread_instruction_deltas_;
-  };
+    std::deque<StringId> name_ids_;
+    std::deque<int64_t> refs_;
+    std::deque<RefType> types_;
 
-  class VirtualTrackSlices {
-   public:
-    inline uint32_t AddVirtualTrackSlice(uint32_t slice_id,
-                                         int64_t thread_timestamp_ns,
-                                         int64_t thread_duration_ns,
-                                         int64_t thread_instruction_count,
-                                         int64_t thread_instruction_delta) {
-      slice_ids_.emplace_back(slice_id);
-      thread_timestamp_ns_.emplace_back(thread_timestamp_ns);
-      thread_duration_ns_.emplace_back(thread_duration_ns);
-      thread_instruction_counts_.emplace_back(thread_instruction_count);
-      thread_instruction_deltas_.emplace_back(thread_instruction_delta);
-      return slice_count() - 1;
-    }
-
-    uint32_t slice_count() const {
-      return static_cast<uint32_t>(slice_ids_.size());
-    }
-
-    const std::deque<uint32_t>& slice_ids() const { return slice_ids_; }
-    const std::deque<int64_t>& thread_timestamp_ns() const {
-      return thread_timestamp_ns_;
-    }
-    const std::deque<int64_t>& thread_duration_ns() const {
-      return thread_duration_ns_;
-    }
-    const std::deque<int64_t>& thread_instruction_counts() const {
-      return thread_instruction_counts_;
-    }
-    const std::deque<int64_t>& thread_instruction_deltas() const {
-      return thread_instruction_deltas_;
-    }
-
-    base::Optional<uint32_t> FindRowForSliceId(uint32_t slice_id) const {
-      auto it =
-          std::lower_bound(slice_ids().begin(), slice_ids().end(), slice_id);
-      if (it != slice_ids().end() && *it == slice_id) {
-        return static_cast<uint32_t>(std::distance(slice_ids().begin(), it));
-      }
-      return base::nullopt;
-    }
-
-    void UpdateThreadDeltasForSliceId(uint32_t slice_id,
-                                      int64_t end_thread_timestamp_ns,
-                                      int64_t end_thread_instruction_count) {
-      uint32_t row = *FindRowForSliceId(slice_id);
-      int64_t begin_ns = thread_timestamp_ns_[row];
-      thread_duration_ns_[row] = end_thread_timestamp_ns - begin_ns;
-      int64_t begin_ticount = thread_instruction_counts_[row];
-      thread_instruction_deltas_[row] =
-          end_thread_instruction_count - begin_ticount;
-    }
-
-   private:
-    std::deque<uint32_t> slice_ids_;
-    std::deque<int64_t> thread_timestamp_ns_;
-    std::deque<int64_t> thread_duration_ns_;
-    std::deque<int64_t> thread_instruction_counts_;
-    std::deque<int64_t> thread_instruction_deltas_;
+    std::unordered_map<uint64_t, uint32_t> hash_to_row_idx_;
   };
 
   class CounterValues {
    public:
-    inline uint32_t AddCounterValue(TrackId track_id,
+    inline uint32_t AddCounterValue(CounterDefinitions::Id counter_id,
                                     int64_t timestamp,
                                     double value) {
-      track_id_.emplace_back(track_id);
+      counter_ids_.emplace_back(counter_id);
       timestamps_.emplace_back(timestamp);
       values_.emplace_back(value);
       arg_set_ids_.emplace_back(kInvalidArgSetId);
 
-      if (track_id != kInvalidTrackId) {
-        if (track_id >= rows_for_track_id_.size()) {
-          rows_for_track_id_.resize(track_id + 1);
+      if (counter_id != CounterDefinitions::kInvalidId) {
+        if (counter_id >= rows_for_counter_id_.size()) {
+          rows_for_counter_id_.resize(counter_id + 1);
         }
-        rows_for_track_id_[track_id].emplace_back(size() - 1);
+        rows_for_counter_id_[counter_id].emplace_back(size() - 1);
       }
       return size() - 1;
     }
 
-    void set_track_id(uint32_t index, TrackId track_id) {
-      PERFETTO_DCHECK(track_id_[index] == kInvalidTrackId);
+    void set_counter_id(uint32_t index, CounterDefinitions::Id counter_id) {
+      PERFETTO_DCHECK(counter_ids_[index] == CounterDefinitions::kInvalidId);
 
-      track_id_[index] = track_id;
-      if (track_id >= rows_for_track_id_.size()) {
-        rows_for_track_id_.resize(track_id + 1);
+      counter_ids_[index] = counter_id;
+      if (counter_id >= rows_for_counter_id_.size()) {
+        rows_for_counter_id_.resize(counter_id + 1);
       }
 
-      auto* new_rows = &rows_for_track_id_[track_id];
+      auto* new_rows = &rows_for_counter_id_[counter_id];
       new_rows->insert(
           std::upper_bound(new_rows->begin(), new_rows->end(), index), index);
     }
 
     void set_arg_set_id(uint32_t row, ArgSetId id) { arg_set_ids_[row] = id; }
 
-    uint32_t size() const { return static_cast<uint32_t>(track_id_.size()); }
+    uint32_t size() const { return static_cast<uint32_t>(counter_ids_.size()); }
 
-    const std::deque<TrackId>& track_ids() const { return track_id_; }
+    const std::deque<CounterDefinitions::Id>& counter_ids() const {
+      return counter_ids_;
+    }
 
     const std::deque<int64_t>& timestamps() const { return timestamps_; }
 
@@ -557,18 +426,19 @@
 
     const std::deque<ArgSetId>& arg_set_ids() const { return arg_set_ids_; }
 
-    const std::deque<std::vector<uint32_t>>& rows_for_track_id() const {
-      return rows_for_track_id_;
+    const std::deque<std::vector<uint32_t>>& rows_for_counter_id() const {
+      return rows_for_counter_id_;
     }
 
    private:
-    std::deque<TrackId> track_id_;
+    std::deque<CounterDefinitions::Id> counter_ids_;
     std::deque<int64_t> timestamps_;
     std::deque<double> values_;
     std::deque<ArgSetId> arg_set_ids_;
 
-    // Indexed by track_id and contains the row numbers corresponding to it.
-    std::deque<std::vector<uint32_t>> rows_for_track_id_;
+    // Indexed by counter_id value and contains the row numbers corresponding to
+    // it.
+    std::deque<std::vector<uint32_t>> rows_for_counter_id_;
   };
 
   class SqlStats {
@@ -716,57 +586,7 @@
   };
   using StatsMap = std::array<Stats, stats::kNumKeys>;
 
-  class Metadata {
-   public:
-    const std::deque<metadata::KeyIDs>& keys() const { return keys_; }
-    const std::deque<Variadic>& values() const { return values_; }
-
-    RowId SetScalarMetadata(metadata::KeyIDs key, Variadic value) {
-      PERFETTO_DCHECK(key < metadata::kNumKeys);
-      PERFETTO_DCHECK(metadata::kKeyTypes[key] == metadata::kSingle);
-      PERFETTO_DCHECK(value.type == metadata::kValueTypes[key]);
-
-      // Already set - on release builds, overwrite the previous value.
-      auto it = scalar_indices.find(key);
-      if (it != scalar_indices.end()) {
-        PERFETTO_DFATAL("Setting a scalar metadata entry more than once.");
-        uint32_t index = static_cast<uint32_t>(it->second);
-        values_[index] = value;
-        return TraceStorage::CreateRowId(kMetadataTable, index);
-      }
-      // First time setting this key.
-      keys_.push_back(key);
-      values_.push_back(value);
-      uint32_t index = static_cast<uint32_t>(keys_.size() - 1);
-      scalar_indices[key] = index;
-      return TraceStorage::CreateRowId(kMetadataTable, index);
-    }
-
-    RowId AppendMetadata(metadata::KeyIDs key, Variadic value) {
-      PERFETTO_DCHECK(key < metadata::kNumKeys);
-      PERFETTO_DCHECK(metadata::kKeyTypes[key] == metadata::kMulti);
-      PERFETTO_DCHECK(value.type == metadata::kValueTypes[key]);
-
-      keys_.push_back(key);
-      values_.push_back(value);
-      uint32_t index = static_cast<uint32_t>(keys_.size() - 1);
-      return TraceStorage::CreateRowId(kMetadataTable, index);
-    }
-
-    void OverwriteMetadata(uint32_t index, Variadic value) {
-      PERFETTO_DCHECK(index < values_.size());
-      values_[index] = value;
-    }
-
-   private:
-    std::deque<metadata::KeyIDs> keys_;
-    std::deque<Variadic> values_;
-    // Extraneous state to track locations of entries that should have at most
-    // one row. Used only to maintain uniqueness during insertions.
-    std::map<metadata::KeyIDs, uint32_t> scalar_indices;
-  };
-
-  class StackProfileFrames {
+  class HeapProfileFrames {
    public:
     struct Row {
       StringId name_id;
@@ -779,97 +599,84 @@
       }
     };
 
-    uint32_t size() const { return static_cast<uint32_t>(names_.size()); }
-
-    uint32_t Insert(const Row& row) {
+    int64_t Insert(const Row& row) {
       names_.emplace_back(row.name_id);
       mappings_.emplace_back(row.mapping_row);
       rel_pcs_.emplace_back(row.rel_pc);
-      symbol_set_ids_.emplace_back(0);
-      size_t row_number = names_.size() - 1;
-      index_[std::make_pair(row.mapping_row, row.rel_pc)].emplace_back(
-          row_number);
-      return static_cast<uint32_t>(row_number);
-    }
-
-    std::vector<int64_t> FindFrameRow(size_t mapping_row,
-                                      uint64_t rel_pc) const {
-      auto it = index_.find(std::make_pair(mapping_row, rel_pc));
-      if (it == index_.end())
-        return {};
-      return it->second;
-    }
-
-    void SetSymbolSetId(size_t row_idx, uint32_t symbol_set_id) {
-      PERFETTO_CHECK(row_idx < symbol_set_ids_.size());
-      symbol_set_ids_[row_idx] = symbol_set_id;
+      return static_cast<int64_t>(names_.size()) - 1;
     }
 
     const std::deque<StringId>& names() const { return names_; }
     const std::deque<int64_t>& mappings() const { return mappings_; }
     const std::deque<int64_t>& rel_pcs() const { return rel_pcs_; }
-    const std::deque<uint32_t>& symbol_set_ids() const {
-      return symbol_set_ids_;
-    }
 
    private:
     std::deque<StringId> names_;
     std::deque<int64_t> mappings_;
     std::deque<int64_t> rel_pcs_;
-    std::deque<uint32_t> symbol_set_ids_;
-
-    std::map<std::pair<size_t /* mapping row */, uint64_t /* rel_pc */>,
-             std::vector<int64_t>>
-        index_;
   };
 
-  class StackProfileMappings {
+  class HeapProfileCallsites {
+   public:
+    struct Row {
+      int64_t depth;
+      int64_t parent_id;
+      int64_t frame_row;
+
+      bool operator==(const Row& other) const {
+        return std::tie(depth, parent_id, frame_row) ==
+               std::tie(other.depth, other.parent_id, other.frame_row);
+      }
+    };
+
+    int64_t Insert(const Row& row) {
+      frame_depths_.emplace_back(row.depth);
+      parent_callsite_ids_.emplace_back(row.parent_id);
+      frame_ids_.emplace_back(row.frame_row);
+      return static_cast<int64_t>(frame_depths_.size()) - 1;
+    }
+
+    const std::deque<int64_t>& frame_depths() const { return frame_depths_; }
+    const std::deque<int64_t>& parent_callsite_ids() const {
+      return parent_callsite_ids_;
+    }
+    const std::deque<int64_t>& frame_ids() const { return frame_ids_; }
+
+   private:
+    std::deque<int64_t> frame_depths_;
+    std::deque<int64_t> parent_callsite_ids_;
+    std::deque<int64_t> frame_ids_;
+  };
+
+  class HeapProfileMappings {
    public:
     struct Row {
       StringId build_id;
-      int64_t exact_offset;
-      int64_t start_offset;
+      int64_t offset;
       int64_t start;
       int64_t end;
       int64_t load_bias;
       StringId name_id;
 
       bool operator==(const Row& other) const {
-        return std::tie(build_id, exact_offset, start_offset, start, end,
-                        load_bias, name_id) ==
-               std::tie(other.build_id, other.exact_offset, other.start_offset,
-                        other.start, other.end, other.load_bias, other.name_id);
+        return std::tie(build_id, offset, start, end, load_bias, name_id) ==
+               std::tie(other.build_id, other.offset, other.start, other.end,
+                        other.load_bias, other.name_id);
       }
     };
 
-    uint32_t size() const { return static_cast<uint32_t>(names_.size()); }
-
-    uint32_t Insert(const Row& row) {
+    int64_t Insert(const Row& row) {
       build_ids_.emplace_back(row.build_id);
-      exact_offsets_.emplace_back(row.exact_offset);
-      start_offsets_.emplace_back(row.start_offset);
+      offsets_.emplace_back(row.offset);
       starts_.emplace_back(row.start);
       ends_.emplace_back(row.end);
       load_biases_.emplace_back(row.load_bias);
       names_.emplace_back(row.name_id);
-
-      size_t row_number = build_ids_.size() - 1;
-      index_[std::make_pair(row.name_id, row.build_id)].emplace_back(
-          row_number);
-      return static_cast<uint32_t>(row_number);
-    }
-
-    std::vector<int64_t> FindMappingRow(StringId name,
-                                        StringId build_id) const {
-      auto it = index_.find(std::make_pair(name, build_id));
-      if (it == index_.end())
-        return {};
-      return it->second;
+      return static_cast<int64_t>(build_ids_.size()) - 1;
     }
 
     const std::deque<StringId>& build_ids() const { return build_ids_; }
-    const std::deque<int64_t>& exact_offsets() const { return exact_offsets_; }
-    const std::deque<int64_t>& start_offsets() const { return start_offsets_; }
+    const std::deque<int64_t>& offsets() const { return offsets_; }
     const std::deque<int64_t>& starts() const { return starts_; }
     const std::deque<int64_t>& ends() const { return ends_; }
     const std::deque<int64_t>& load_biases() const { return load_biases_; }
@@ -877,77 +684,46 @@
 
    private:
     std::deque<StringId> build_ids_;
-    std::deque<int64_t> exact_offsets_;
-    std::deque<int64_t> start_offsets_;
+    std::deque<int64_t> offsets_;
     std::deque<int64_t> starts_;
     std::deque<int64_t> ends_;
     std::deque<int64_t> load_biases_;
     std::deque<StringId> names_;
-
-    std::map<std::pair<StringId /* name */, StringId /* build id */>,
-             std::vector<int64_t>>
-        index_;
   };
 
   class HeapProfileAllocations {
    public:
     struct Row {
       int64_t timestamp;
-      UniquePid upid;
+      int64_t pid;
       int64_t callsite_id;
       int64_t count;
       int64_t size;
     };
 
-    uint32_t size() const { return static_cast<uint32_t>(timestamps_.size()); }
-
     void Insert(const Row& row) {
       timestamps_.emplace_back(row.timestamp);
-      upids_.emplace_back(row.upid);
+      pids_.emplace_back(row.pid);
       callsite_ids_.emplace_back(row.callsite_id);
       counts_.emplace_back(row.count);
       sizes_.emplace_back(row.size);
     }
 
     const std::deque<int64_t>& timestamps() const { return timestamps_; }
-    const std::deque<UniquePid>& upids() const { return upids_; }
+    const std::deque<int64_t>& pids() const { return pids_; }
     const std::deque<int64_t>& callsite_ids() const { return callsite_ids_; }
     const std::deque<int64_t>& counts() const { return counts_; }
     const std::deque<int64_t>& sizes() const { return sizes_; }
 
    private:
     std::deque<int64_t> timestamps_;
-    std::deque<UniquePid> upids_;
+    std::deque<int64_t> pids_;
     std::deque<int64_t> callsite_ids_;
     std::deque<int64_t> counts_;
     std::deque<int64_t> sizes_;
   };
 
-  class CpuProfileStackSamples {
-   public:
-    struct Row {
-      int64_t timestamp;
-      int64_t callsite_id;
-      UniqueTid utid;
-    };
-
-    uint32_t size() const { return static_cast<uint32_t>(timestamps_.size()); }
-
-    void Insert(const Row& row) {
-      timestamps_.emplace_back(row.timestamp);
-      callsite_ids_.emplace_back(row.callsite_id);
-      utids_.emplace_back(row.utid);
-    }
-
-    const std::deque<int64_t>& timestamps() const { return timestamps_; }
-    const std::deque<int64_t>& callsite_ids() const { return callsite_ids_; }
-    const std::deque<UniqueTid>& utids() const { return utids_; }
-
-   private:
-    std::deque<int64_t> timestamps_;
-    std::deque<int64_t> callsite_ids_;
-    std::deque<UniqueTid> utids_;
-  };
+  void ResetStorage();
 
   UniqueTid AddEmptyThread(uint32_t tid) {
     unique_threads_.emplace_back(tid);
@@ -1004,24 +780,6 @@
     stats_[key].indexed_values[index] = value;
   }
 
-  // Example usage:
-  // SetMetadata(metadata::benchmark_name,
-  //             Variadic::String(storage->InternString("foo"));
-  // Returns the RowId of the new entry.
-  // Virtual for testing.
-  virtual RowId SetMetadata(metadata::KeyIDs key, Variadic value) {
-    return metadata_.SetScalarMetadata(key, value);
-  }
-
-  // Example usage:
-  // AppendMetadata(metadata::benchmark_story_tags,
-  //                Variadic::String(storage->InternString("bar"));
-  // Returns the RowId of the new entry.
-  // Virtual for testing.
-  virtual RowId AppendMetadata(metadata::KeyIDs key, Variadic value) {
-    return metadata_.AppendMetadata(key, value);
-  }
-
   class ScopedStatsTracer {
    public:
     ScopedStatsTracer(TraceStorage* storage, size_t key)
@@ -1062,8 +820,7 @@
   }
 
   // Reading methods.
-  // Virtual for testing.
-  virtual NullTermStringView GetString(StringId id) const {
+  NullTermStringView GetString(StringId id) const {
     return string_pool_.Get(id);
   }
 
@@ -1072,8 +829,7 @@
     return unique_processes_[upid];
   }
 
-  // Virtual for testing.
-  virtual const Thread& GetThread(UniqueTid utid) const {
+  const Thread& GetThread(UniqueTid utid) const {
     // Allow utid == 0 for idle thread retrieval.
     PERFETTO_DCHECK(utid < unique_threads_.size());
     return unique_threads_[utid];
@@ -1090,93 +846,19 @@
     return std::make_pair(table_id, row);
   }
 
-  const tables::TrackTable& track_table() const { return track_table_; }
-  tables::TrackTable* mutable_track_table() { return &track_table_; }
-
-  const tables::ProcessTrackTable& process_track_table() const {
-    return process_track_table_;
-  }
-  tables::ProcessTrackTable* mutable_process_track_table() {
-    return &process_track_table_;
-  }
-
-  const tables::ThreadTrackTable& thread_track_table() const {
-    return thread_track_table_;
-  }
-  tables::ThreadTrackTable* mutable_thread_track_table() {
-    return &thread_track_table_;
-  }
-
-  const tables::CounterTrackTable& counter_track_table() const {
-    return counter_track_table_;
-  }
-  tables::CounterTrackTable* mutable_counter_track_table() {
-    return &counter_track_table_;
-  }
-
-  const tables::ThreadCounterTrackTable& thread_counter_track_table() const {
-    return thread_counter_track_table_;
-  }
-  tables::ThreadCounterTrackTable* mutable_thread_counter_track_table() {
-    return &thread_counter_track_table_;
-  }
-
-  const tables::ProcessCounterTrackTable& process_counter_track_table() const {
-    return process_counter_track_table_;
-  }
-  tables::ProcessCounterTrackTable* mutable_process_counter_track_table() {
-    return &process_counter_track_table_;
-  }
-
-  const tables::CpuCounterTrackTable& cpu_counter_track_table() const {
-    return cpu_counter_track_table_;
-  }
-  tables::CpuCounterTrackTable* mutable_cpu_counter_track_table() {
-    return &cpu_counter_track_table_;
-  }
-
-  const tables::IrqCounterTrackTable& irq_counter_track_table() const {
-    return irq_counter_track_table_;
-  }
-  tables::IrqCounterTrackTable* mutable_irq_counter_track_table() {
-    return &irq_counter_track_table_;
-  }
-
-  const tables::SoftirqCounterTrackTable& softirq_counter_track_table() const {
-    return softirq_counter_track_table_;
-  }
-  tables::SoftirqCounterTrackTable* mutable_softirq_counter_track_table() {
-    return &softirq_counter_track_table_;
-  }
-
-  const tables::GpuCounterTrackTable& gpu_counter_track_table() const {
-    return gpu_counter_track_table_;
-  }
-  tables::GpuCounterTrackTable* mutable_gpu_counter_track_table() {
-    return &gpu_counter_track_table_;
-  }
-
   const Slices& slices() const { return slices_; }
   Slices* mutable_slices() { return &slices_; }
 
   const NestableSlices& nestable_slices() const { return nestable_slices_; }
   NestableSlices* mutable_nestable_slices() { return &nestable_slices_; }
 
-  const ThreadSlices& thread_slices() const { return thread_slices_; }
-  ThreadSlices* mutable_thread_slices() { return &thread_slices_; }
-
-  const VirtualTrackSlices& virtual_track_slices() const {
-    return virtual_track_slices_;
+  const CounterDefinitions& counter_definitions() const {
+    return counter_definitions_;
   }
-  VirtualTrackSlices* mutable_virtual_track_slices() {
-    return &virtual_track_slices_;
+  CounterDefinitions* mutable_counter_definitions() {
+    return &counter_definitions_;
   }
 
-  const tables::GpuSliceTable& gpu_slice_table() const {
-    return gpu_slice_table_;
-  }
-  tables::GpuSliceTable* mutable_gpu_slice_table() { return &gpu_slice_table_; }
-
   const CounterValues& counter_values() const { return counter_values_; }
   CounterValues* mutable_counter_values() { return &counter_values_; }
 
@@ -1191,35 +873,31 @@
 
   const StatsMap& stats() const { return stats_; }
 
-  const Metadata& metadata() const { return metadata_; }
-  Metadata* mutable_metadata() { return &metadata_; }
-
   const Args& args() const { return args_; }
   Args* mutable_args() { return &args_; }
 
   const RawEvents& raw_events() const { return raw_events_; }
   RawEvents* mutable_raw_events() { return &raw_events_; }
 
-  const StackProfileMappings& stack_profile_mappings() const {
-    return stack_profile_mappings_;
+  const HeapProfileMappings& heap_profile_mappings() const {
+    return heap_profile_mappings_;
   }
-  StackProfileMappings* mutable_stack_profile_mappings() {
-    return &stack_profile_mappings_;
+  HeapProfileMappings* mutable_heap_profile_mappings() {
+    return &heap_profile_mappings_;
   }
 
-  const StackProfileFrames& stack_profile_frames() const {
-    return stack_profile_frames_;
+  const HeapProfileFrames& heap_profile_frames() const {
+    return heap_profile_frames_;
   }
-  StackProfileFrames* mutable_stack_profile_frames() {
-    return &stack_profile_frames_;
+  HeapProfileFrames* mutable_heap_profile_frames() {
+    return &heap_profile_frames_;
   }
 
-  const tables::StackProfileCallsiteTable& stack_profile_callsite_table()
-      const {
-    return stack_profile_callsite_table_;
+  const HeapProfileCallsites& heap_profile_callsites() const {
+    return heap_profile_callsites_;
   }
-  tables::StackProfileCallsiteTable* mutable_stack_profile_callsite_table() {
-    return &stack_profile_callsite_table_;
+  HeapProfileCallsites* mutable_heap_profile_callsites() {
+    return &heap_profile_callsites_;
   }
 
   const HeapProfileAllocations& heap_profile_allocations() const {
@@ -1228,55 +906,14 @@
   HeapProfileAllocations* mutable_heap_profile_allocations() {
     return &heap_profile_allocations_;
   }
-  const CpuProfileStackSamples& cpu_profile_stack_samples() const {
-    return cpu_profile_stack_samples_;
-  }
-  CpuProfileStackSamples* mutable_cpu_profile_stack_samples() {
-    return &cpu_profile_stack_samples_;
-  }
-
-  const tables::SymbolTable& symbol_table() const { return symbol_table_; }
-
-  tables::SymbolTable* mutable_symbol_table() { return &symbol_table_; }
-
-  const tables::HeapGraphObjectTable& heap_graph_object_table() const {
-    return heap_graph_object_table_;
-  }
-
-  tables::HeapGraphObjectTable* mutable_heap_graph_object_table() {
-    return &heap_graph_object_table_;
-  }
-
-  const tables::HeapGraphReferenceTable& heap_graph_reference_table() const {
-    return heap_graph_reference_table_;
-  }
-
-  tables::HeapGraphReferenceTable* mutable_heap_graph_reference_table() {
-    return &heap_graph_reference_table_;
-  }
-
-  const tables::GpuTrackTable& gpu_track_table() const {
-    return gpu_track_table_;
-  }
-  tables::GpuTrackTable* mutable_gpu_track_table() { return &gpu_track_table_; }
-
-  const tables::VulkanMemoryAllocationsTable& vulkan_memory_allocations_table()
-      const {
-    return vulkan_memory_allocations_table_;
-  }
-
-  tables::VulkanMemoryAllocationsTable*
-  mutable_vulkan_memory_allocations_table() {
-    return &vulkan_memory_allocations_table_;
-  }
 
   const StringPool& string_pool() const { return string_pool_; }
 
-  // |unique_processes_| always contains at least 1 element because the 0th ID
+  // |unique_processes_| always contains at least 1 element becuase the 0th ID
   // is reserved to indicate an invalid process.
   size_t process_count() const { return unique_processes_.size(); }
 
-  // |unique_threads_| always contains at least 1 element because the 0th ID
+  // |unique_threads_| always contains at least 1 element becuase the 0th ID
   // is reserved to indicate an invalid thread.
   size_t thread_count() const { return unique_threads_.size(); }
 
@@ -1295,50 +932,21 @@
   TraceStorage(const TraceStorage&) = delete;
   TraceStorage& operator=(const TraceStorage&) = delete;
 
-  TraceStorage(TraceStorage&&) = delete;
-  TraceStorage& operator=(TraceStorage&&) = delete;
-
-  // One entry for each unique string in the trace.
-  StringPool string_pool_;
+  TraceStorage(TraceStorage&&) = default;
+  TraceStorage& operator=(TraceStorage&&) = default;
 
   // Stats about parsing the trace.
   StatsMap stats_{};
 
-  // Extra data extracted from the trace. Includes:
-  // * metadata from chrome and benchmarking infrastructure
-  // * descriptions of android packages
-  Metadata metadata_{};
-
-  // Metadata for tracks.
-  tables::TrackTable track_table_{&string_pool_, nullptr};
-  tables::GpuTrackTable gpu_track_table_{&string_pool_, &track_table_};
-  tables::ProcessTrackTable process_track_table_{&string_pool_, &track_table_};
-  tables::ThreadTrackTable thread_track_table_{&string_pool_, &track_table_};
-
-  // Track tables for counter events.
-  tables::CounterTrackTable counter_track_table_{&string_pool_, &track_table_};
-  tables::ThreadCounterTrackTable thread_counter_track_table_{
-      &string_pool_, &counter_track_table_};
-  tables::ProcessCounterTrackTable process_counter_track_table_{
-      &string_pool_, &counter_track_table_};
-  tables::CpuCounterTrackTable cpu_counter_track_table_{&string_pool_,
-                                                        &counter_track_table_};
-  tables::IrqCounterTrackTable irq_counter_track_table_{&string_pool_,
-                                                        &counter_track_table_};
-  tables::SoftirqCounterTrackTable softirq_counter_track_table_{
-      &string_pool_, &counter_track_table_};
-  tables::GpuCounterTrackTable gpu_counter_track_table_{&string_pool_,
-                                                        &counter_track_table_};
-
-  // Metadata for gpu tracks.
-  GpuContexts gpu_contexts_;
-
   // One entry for each CPU in the trace.
   Slices slices_;
 
   // Args for all other tables.
   Args args_;
 
+  // One entry for each unique string in the trace.
+  StringPool string_pool_;
+
   // One entry for each UniquePid, with UniquePid as the index.
   // Never hold on to pointers to Process, as vector resize will
   // invalidate them.
@@ -1350,16 +958,8 @@
   // Slices coming from userspace events (e.g. Chromium TRACE_EVENT macros).
   NestableSlices nestable_slices_;
 
-  // Additional attributes for threads slices (sub-type of NestableSlices).
-  ThreadSlices thread_slices_;
-
-  // Additional attributes for virtual track slices (sub-type of
-  // NestableSlices).
-  VirtualTrackSlices virtual_track_slices_;
-
-  // Additional attributes for gpu track slices (sub-type of
-  // NestableSlices).
-  tables::GpuSliceTable gpu_slice_table_{&string_pool_, nullptr};
+  // The type of counters in the trace. Can be thought of the the "metadata".
+  CounterDefinitions counter_definitions_;
 
   // The values from the Counter events from the trace. This includes CPU
   // frequency events as well systrace trace_marker counter events.
@@ -1379,21 +979,10 @@
   RawEvents raw_events_;
   AndroidLogs android_log_;
 
-  StackProfileMappings stack_profile_mappings_;
-  StackProfileFrames stack_profile_frames_;
-  tables::StackProfileCallsiteTable stack_profile_callsite_table_{&string_pool_,
-                                                                  nullptr};
+  HeapProfileMappings heap_profile_mappings_;
+  HeapProfileFrames heap_profile_frames_;
+  HeapProfileCallsites heap_profile_callsites_;
   HeapProfileAllocations heap_profile_allocations_;
-  CpuProfileStackSamples cpu_profile_stack_samples_;
-
-  // Symbol tables (mappings from frames to symbol names)
-  tables::SymbolTable symbol_table_{&string_pool_, nullptr};
-  tables::HeapGraphObjectTable heap_graph_object_table_{&string_pool_, nullptr};
-  tables::HeapGraphReferenceTable heap_graph_reference_table_{&string_pool_,
-                                                              nullptr};
-
-  tables::VulkanMemoryAllocationsTable vulkan_memory_allocations_table_{
-      &string_pool_, nullptr};
 };
 
 }  // namespace trace_processor
@@ -1402,10 +991,9 @@
 namespace std {
 
 template <>
-struct hash<
-    ::perfetto::trace_processor::TraceStorage::StackProfileFrames::Row> {
+struct hash<::perfetto::trace_processor::TraceStorage::HeapProfileFrames::Row> {
   using argument_type =
-      ::perfetto::trace_processor::TraceStorage::StackProfileFrames::Row;
+      ::perfetto::trace_processor::TraceStorage::HeapProfileFrames::Row;
   using result_type = size_t;
 
   result_type operator()(const argument_type& r) const {
@@ -1416,30 +1004,28 @@
 
 template <>
 struct hash<
-    ::perfetto::trace_processor::tables::StackProfileCallsiteTable::Row> {
+    ::perfetto::trace_processor::TraceStorage::HeapProfileCallsites::Row> {
   using argument_type =
-      ::perfetto::trace_processor::tables::StackProfileCallsiteTable::Row;
+      ::perfetto::trace_processor::TraceStorage::HeapProfileCallsites::Row;
   using result_type = size_t;
 
   result_type operator()(const argument_type& r) const {
     return std::hash<int64_t>{}(r.depth) ^ std::hash<int64_t>{}(r.parent_id) ^
-           std::hash<int64_t>{}(r.frame_id);
+           std::hash<int64_t>{}(r.frame_row);
   }
 };
 
 template <>
 struct hash<
-    ::perfetto::trace_processor::TraceStorage::StackProfileMappings::Row> {
+    ::perfetto::trace_processor::TraceStorage::HeapProfileMappings::Row> {
   using argument_type =
-      ::perfetto::trace_processor::TraceStorage::StackProfileMappings::Row;
+      ::perfetto::trace_processor::TraceStorage::HeapProfileMappings::Row;
   using result_type = size_t;
 
   result_type operator()(const argument_type& r) const {
     return std::hash<::perfetto::trace_processor::StringId>{}(r.build_id) ^
-           std::hash<int64_t>{}(r.exact_offset) ^
-           std::hash<int64_t>{}(r.start_offset) ^
-           std::hash<int64_t>{}(r.start) ^ std::hash<int64_t>{}(r.end) ^
-           std::hash<int64_t>{}(r.load_bias) ^
+           std::hash<int64_t>{}(r.offset) ^ std::hash<int64_t>{}(r.start) ^
+           std::hash<int64_t>{}(r.end) ^ std::hash<int64_t>{}(r.load_bias) ^
            std::hash<::perfetto::trace_processor::StringId>{}(r.name_id);
   }
 };
diff --git a/src/trace_processor/track_tracker.cc b/src/trace_processor/track_tracker.cc
deleted file mode 100644
index 5cc9746..0000000
--- a/src/trace_processor/track_tracker.cc
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/track_tracker.h"
-
-#include "src/trace_processor/args_tracker.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// static
-constexpr TrackId TrackTracker::kDefaultDescriptorTrackUuid;
-
-TrackTracker::TrackTracker(TraceProcessorContext* context)
-    : source_key_(context->storage->InternString("source")),
-      source_id_key_(context->storage->InternString("source_id")),
-      source_id_is_process_scoped_key_(
-          context->storage->InternString("source_id_is_process_scoped")),
-      source_scope_key_(context->storage->InternString("source_scope")),
-      fuchsia_source_(context->storage->InternString("fuchsia")),
-      chrome_source_(context->storage->InternString("chrome")),
-      android_source_(context->storage->InternString("android")),
-      descriptor_source_(context->storage->InternString("descriptor")),
-      default_descriptor_track_name_(
-          context->storage->InternString("Default Track")),
-      context_(context) {}
-
-TrackId TrackTracker::InternThreadTrack(UniqueTid utid) {
-  auto it = thread_tracks_.find(utid);
-  if (it != thread_tracks_.end())
-    return it->second;
-
-  tables::ThreadTrackTable::Row row;
-  row.utid = utid;
-  auto id = context_->storage->mutable_thread_track_table()->Insert(row);
-  thread_tracks_[utid] = id;
-  return id;
-}
-
-TrackId TrackTracker::InternFuchsiaAsyncTrack(StringId name,
-                                              int64_t correlation_id) {
-  auto it = fuchsia_async_tracks_.find(correlation_id);
-  if (it != fuchsia_async_tracks_.end())
-    return it->second;
-
-  tables::TrackTable::Row row(name);
-  auto id = context_->storage->mutable_track_table()->Insert(row);
-  fuchsia_async_tracks_[correlation_id] = id;
-
-  RowId row_id = TraceStorage::CreateRowId(TableId::kTrack, id);
-  context_->args_tracker->AddArg(row_id, source_key_, source_key_,
-                                 Variadic::String(fuchsia_source_));
-  context_->args_tracker->AddArg(row_id, source_id_key_, source_id_key_,
-                                 Variadic::Integer(correlation_id));
-  return id;
-}
-
-TrackId TrackTracker::InternGpuTrack(const tables::GpuTrackTable::Row& row) {
-  GpuTrackTuple tuple{row.name.id, row.scope, row.context_id.value_or(0)};
-
-  auto it = gpu_tracks_.find(tuple);
-  if (it != gpu_tracks_.end())
-    return it->second;
-
-  auto id = context_->storage->mutable_gpu_track_table()->Insert(row);
-  gpu_tracks_[tuple] = id;
-  return id;
-}
-
-TrackId TrackTracker::InternLegacyChromeAsyncTrack(
-    StringId name,
-    uint32_t upid,
-    int64_t source_id,
-    bool source_id_is_process_scoped,
-    StringId source_scope) {
-  ChromeTrackTuple tuple;
-  if (source_id_is_process_scoped)
-    tuple.upid = upid;
-  tuple.source_id = source_id;
-  tuple.source_scope = source_scope;
-
-  auto it = chrome_tracks_.find(tuple);
-  if (it != chrome_tracks_.end())
-    return it->second;
-
-  // Legacy async tracks are always drawn in the context of a process, even if
-  // the ID's scope is global.
-  tables::ProcessTrackTable::Row track(name);
-  track.upid = upid;
-  TrackId id = context_->storage->mutable_process_track_table()->Insert(track);
-  chrome_tracks_[tuple] = id;
-
-  RowId row_id = TraceStorage::CreateRowId(TableId::kTrack, id);
-  context_->args_tracker->AddArg(row_id, source_key_, source_key_,
-                                 Variadic::String(chrome_source_));
-  context_->args_tracker->AddArg(row_id, source_id_key_, source_id_key_,
-                                 Variadic::Integer(source_id));
-  context_->args_tracker->AddArg(
-      row_id, source_id_is_process_scoped_key_,
-      source_id_is_process_scoped_key_,
-      Variadic::Boolean(source_id_is_process_scoped));
-  context_->args_tracker->AddArg(row_id, source_scope_key_, source_scope_key_,
-                                 Variadic::String(source_scope));
-  return id;
-}
-
-TrackId TrackTracker::InternAndroidAsyncTrack(StringId name,
-                                              UniquePid upid,
-                                              int64_t cookie) {
-  AndroidAsyncTrackTuple tuple{upid, cookie, name};
-
-  auto it = android_async_tracks_.find(tuple);
-  if (it != android_async_tracks_.end())
-    return it->second;
-
-  tables::ProcessTrackTable::Row row(name);
-  row.upid = upid;
-  auto id = context_->storage->mutable_process_track_table()->Insert(row);
-  android_async_tracks_[tuple] = id;
-
-  RowId row_id = TraceStorage::CreateRowId(TableId::kTrack, id);
-  context_->args_tracker->AddArg(row_id, source_key_, source_key_,
-                                 Variadic::String(android_source_));
-  context_->args_tracker->AddArg(row_id, source_id_key_, source_id_key_,
-                                 Variadic::Integer(cookie));
-  return id;
-}
-
-TrackId TrackTracker::InternLegacyChromeProcessInstantTrack(UniquePid upid) {
-  auto it = chrome_process_instant_tracks_.find(upid);
-  if (it != chrome_process_instant_tracks_.end())
-    return it->second;
-
-  tables::ProcessTrackTable::Row row;
-  row.upid = upid;
-  auto id = context_->storage->mutable_process_track_table()->Insert(row);
-  chrome_process_instant_tracks_[upid] = id;
-
-  RowId row_id = TraceStorage::CreateRowId(TableId::kTrack, id);
-  context_->args_tracker->AddArg(row_id, source_key_, source_key_,
-                                 Variadic::String(chrome_source_));
-  return id;
-}
-
-TrackId TrackTracker::GetOrCreateLegacyChromeGlobalInstantTrack() {
-  if (!chrome_global_instant_track_id_) {
-    chrome_global_instant_track_id_ =
-        context_->storage->mutable_track_table()->Insert({});
-
-    RowId row_id = TraceStorage::CreateRowId(TableId::kTrack,
-                                             *chrome_global_instant_track_id_);
-    context_->args_tracker->AddArg(row_id, source_key_, source_key_,
-                                   Variadic::String(chrome_source_));
-  }
-  return *chrome_global_instant_track_id_;
-}
-
-TrackId TrackTracker::UpdateDescriptorTrack(uint64_t uuid,
-                                            StringId name,
-                                            base::Optional<UniquePid> upid,
-                                            base::Optional<UniqueTid> utid) {
-  auto it = descriptor_tracks_.find(uuid);
-  if (it != descriptor_tracks_.end()) {
-    // Update existing track for |uuid|.
-    TrackId track_id = it->second;
-    if (name != kNullStringId) {
-      context_->storage->mutable_track_table()->mutable_name()->Set(track_id,
-                                                                    name);
-    }
-
-#if PERFETTO_DLOG_IS_ON()
-    if (upid) {
-      // Verify that upid didn't change.
-      auto process_track_row =
-          context_->storage->process_track_table().id().IndexOf(
-              SqlValue::Long(track_id));
-      if (!process_track_row) {
-        PERFETTO_DLOG("Can't update non-scoped track with uuid %" PRIu64
-                      " to a scoped track.",
-                      uuid);
-      } else {
-        auto old_upid =
-            context_->storage->process_track_table().upid()[*process_track_row];
-        if (old_upid != upid) {
-          PERFETTO_DLOG("Ignoring upid change for track with uuid %" PRIu64
-                        " from %" PRIu32 " to %" PRIu32 ".",
-                        uuid, old_upid, *upid);
-        }
-      }
-    }
-
-    if (utid) {
-      // Verify that utid didn't change.
-      auto thread_track_row =
-          context_->storage->thread_track_table().id().IndexOf(
-              SqlValue::Long(track_id));
-      if (!thread_track_row) {
-        PERFETTO_DLOG("Can't update non-thread track with uuid %" PRIu64
-                      " to a thread track.",
-                      uuid);
-      } else {
-        auto old_utid =
-            context_->storage->thread_track_table().utid()[*thread_track_row];
-        if (old_utid != utid) {
-          PERFETTO_DLOG("Ignoring utid change for track with uuid %" PRIu64
-                        " from %" PRIu32 " to %" PRIu32 ".",
-                        uuid, old_utid, *utid);
-        }
-      }
-    }
-#endif  // PERFETTO_DLOG_IS_ON()
-
-    return track_id;
-  }
-
-  TrackId track_id;
-
-  if (utid) {
-    // Update existing track for the thread if we have previously created one
-    // in GetOrCreateDescriptorTrackForThread().
-    auto utid_it = descriptor_tracks_by_utid_.find(*utid);
-    if (utid_it != descriptor_tracks_by_utid_.end()) {
-      TrackId candidate_track_id = utid_it->second;
-      // Only update this track if it hasn't been associated with a different
-      // UUID already.
-      auto descriptor_it = std::find_if(
-          descriptor_tracks_.begin(), descriptor_tracks_.end(),
-          [candidate_track_id](const std::pair<uint64_t, TrackId>& entry) {
-            return entry.second == candidate_track_id;
-          });
-      if (descriptor_it == descriptor_tracks_.end()) {
-        descriptor_tracks_[uuid] = candidate_track_id;
-
-        RowId row_id =
-            TraceStorage::CreateRowId(TableId::kTrack, candidate_track_id);
-        context_->args_tracker->AddArg(
-            row_id, source_id_key_, source_id_key_,
-            Variadic::Integer(static_cast<int64_t>(uuid)));
-
-        return candidate_track_id;
-      }
-    }
-
-    // New thread track.
-    tables::ThreadTrackTable::Row row(name);
-    row.utid = *utid;
-    track_id = context_->storage->mutable_thread_track_table()->Insert(row);
-    if (descriptor_tracks_by_utid_.find(*utid) ==
-        descriptor_tracks_by_utid_.end()) {
-      descriptor_tracks_by_utid_[*utid] = track_id;
-    }
-  } else if (upid) {
-    // New process-scoped async track.
-    tables::ProcessTrackTable::Row track(name);
-    track.upid = *upid;
-    track_id = context_->storage->mutable_process_track_table()->Insert(track);
-  } else {
-    // New global async track.
-    tables::TrackTable::Row track(name);
-    track_id = context_->storage->mutable_track_table()->Insert(track);
-  }
-
-  descriptor_tracks_[uuid] = track_id;
-
-  RowId row_id = TraceStorage::CreateRowId(TableId::kTrack, track_id);
-  context_->args_tracker->AddArg(row_id, source_key_, source_key_,
-                                 Variadic::String(descriptor_source_));
-  context_->args_tracker->AddArg(row_id, source_id_key_, source_id_key_,
-                                 Variadic::Integer(static_cast<int64_t>(uuid)));
-
-  return track_id;
-}
-
-base::Optional<TrackId> TrackTracker::GetDescriptorTrack(uint64_t uuid) const {
-  auto it = descriptor_tracks_.find(uuid);
-  if (it == descriptor_tracks_.end())
-    return base::nullopt;
-  return it->second;
-}
-
-TrackId TrackTracker::GetOrCreateDescriptorTrackForThread(UniqueTid utid) {
-  auto it = descriptor_tracks_by_utid_.find(utid);
-  if (it != descriptor_tracks_by_utid_.end()) {
-    return it->second;
-  }
-  // TODO(eseckler): How should this track receive its name?
-  tables::ThreadTrackTable::Row row(/*name=*/kNullStringId);
-  row.utid = utid;
-  TrackId track_id =
-      context_->storage->mutable_thread_track_table()->Insert(row);
-  descriptor_tracks_by_utid_[utid] = track_id;
-
-  RowId row_id = TraceStorage::CreateRowId(TableId::kTrack, track_id);
-  context_->args_tracker->AddArg(row_id, source_key_, source_key_,
-                                 Variadic::String(descriptor_source_));
-  return track_id;
-}
-
-TrackId TrackTracker::GetOrCreateDefaultDescriptorTrack() {
-  base::Optional<TrackId> opt_track_id =
-      GetDescriptorTrack(kDefaultDescriptorTrackUuid);
-  if (opt_track_id)
-    return *opt_track_id;
-
-  return UpdateDescriptorTrack(kDefaultDescriptorTrackUuid,
-                               default_descriptor_track_name_);
-}
-
-TrackId TrackTracker::InternGlobalCounterTrack(StringId name) {
-  auto it = global_counter_tracks_by_name_.find(name);
-  if (it != global_counter_tracks_by_name_.end()) {
-    return it->second;
-  }
-
-  tables::CounterTrackTable::Row row(name);
-  TrackId track = context_->storage->mutable_counter_track_table()->Insert(row);
-  global_counter_tracks_by_name_[name] = track;
-  return track;
-}
-
-TrackId TrackTracker::InternCpuCounterTrack(StringId name, uint32_t cpu) {
-  auto it = cpu_counter_tracks_.find(std::make_pair(name, cpu));
-  if (it != cpu_counter_tracks_.end()) {
-    return it->second;
-  }
-
-  tables::CpuCounterTrackTable::Row row(name);
-  row.cpu = cpu;
-  row.ref = cpu;
-  row.ref_type = context_->storage->InternString(
-      GetRefTypeStringMap()[static_cast<size_t>(RefType::kRefCpuId)]);
-
-  TrackId track =
-      context_->storage->mutable_cpu_counter_track_table()->Insert(row);
-  cpu_counter_tracks_[std::make_pair(name, cpu)] = track;
-  return track;
-}
-
-TrackId TrackTracker::InternThreadCounterTrack(StringId name, UniqueTid utid) {
-  auto it = utid_counter_tracks_.find(std::make_pair(name, utid));
-  if (it != utid_counter_tracks_.end()) {
-    return it->second;
-  }
-
-  tables::ThreadCounterTrackTable::Row row(name);
-  row.utid = utid;
-  row.ref = utid;
-  row.ref_type = context_->storage->InternString(
-      GetRefTypeStringMap()[static_cast<size_t>(RefType::kRefUtid)]);
-
-  TrackId track =
-      context_->storage->mutable_thread_counter_track_table()->Insert(row);
-  utid_counter_tracks_[std::make_pair(name, utid)] = track;
-  return track;
-}
-
-TrackId TrackTracker::InternProcessCounterTrack(StringId name, UniquePid upid) {
-  auto it = upid_counter_tracks_.find(std::make_pair(name, upid));
-  if (it != upid_counter_tracks_.end()) {
-    return it->second;
-  }
-
-  tables::ProcessCounterTrackTable::Row row(name);
-  row.upid = upid;
-  row.ref = upid;
-  row.ref_type = context_->storage->InternString(
-      GetRefTypeStringMap()[static_cast<size_t>(RefType::kRefUpid)]);
-
-  TrackId track =
-      context_->storage->mutable_process_counter_track_table()->Insert(row);
-  upid_counter_tracks_[std::make_pair(name, upid)] = track;
-  return track;
-}
-
-TrackId TrackTracker::InternIrqCounterTrack(StringId name, int32_t irq) {
-  auto it = irq_counter_tracks_.find(std::make_pair(name, irq));
-  if (it != irq_counter_tracks_.end()) {
-    return it->second;
-  }
-
-  tables::IrqCounterTrackTable::Row row(name);
-  row.irq = irq;
-  row.ref = irq;
-  row.ref_type = context_->storage->InternString(
-      GetRefTypeStringMap()[static_cast<size_t>(RefType::kRefIrq)]);
-
-  TrackId track =
-      context_->storage->mutable_irq_counter_track_table()->Insert(row);
-  irq_counter_tracks_[std::make_pair(name, irq)] = track;
-  return track;
-}
-
-TrackId TrackTracker::InternSoftirqCounterTrack(StringId name,
-                                                int32_t softirq) {
-  auto it = softirq_counter_tracks_.find(std::make_pair(name, softirq));
-  if (it != softirq_counter_tracks_.end()) {
-    return it->second;
-  }
-
-  tables::SoftirqCounterTrackTable::Row row(name);
-  row.softirq = softirq;
-  row.ref = softirq;
-  row.ref_type = context_->storage->InternString(
-      GetRefTypeStringMap()[static_cast<size_t>(RefType::kRefSoftIrq)]);
-
-  TrackId track =
-      context_->storage->mutable_softirq_counter_track_table()->Insert(row);
-  softirq_counter_tracks_[std::make_pair(name, softirq)] = track;
-  return track;
-}
-
-TrackId TrackTracker::InternGpuCounterTrack(StringId name, uint32_t gpu_id) {
-  auto it = gpu_counter_tracks_.find(std::make_pair(name, gpu_id));
-  if (it != gpu_counter_tracks_.end()) {
-    return it->second;
-  }
-  TrackId track = CreateGpuCounterTrack(name, gpu_id);
-  gpu_counter_tracks_[std::make_pair(name, gpu_id)] = track;
-  return track;
-}
-
-TrackId TrackTracker::CreateGpuCounterTrack(StringId name,
-                                            uint32_t gpu_id,
-                                            StringId description,
-                                            StringId unit) {
-  tables::GpuCounterTrackTable::Row row(name);
-  row.gpu_id = gpu_id;
-  row.description = description;
-  row.unit = unit;
-  row.ref = gpu_id;
-  row.ref_type = context_->storage->InternString(
-      GetRefTypeStringMap()[static_cast<size_t>(RefType::kRefGpuId)]);
-
-  return context_->storage->mutable_gpu_counter_track_table()->Insert(row);
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/track_tracker.h b/src/trace_processor/track_tracker.h
deleted file mode 100644
index 8ef379a..0000000
--- a/src/trace_processor/track_tracker.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_TRACK_TRACKER_H_
-#define SRC_TRACE_PROCESSOR_TRACK_TRACKER_H_
-
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Tracks and stores tracks based on track types, ids and scopes.
-class TrackTracker {
- public:
-  explicit TrackTracker(TraceProcessorContext*);
-
-  // Interns a thread track into the storage.
-  TrackId InternThreadTrack(UniqueTid utid);
-
-  // Interns a Fuchsia async track into the storage.
-  TrackId InternFuchsiaAsyncTrack(StringId name, int64_t correlation_id);
-
-  // Interns a given GPU track into the storage.
-  TrackId InternGpuTrack(const tables::GpuTrackTable::Row& row);
-
-  // Interns a legacy Chrome async event track into the storage.
-  TrackId InternLegacyChromeAsyncTrack(StringId name,
-                                       uint32_t upid,
-                                       int64_t source_id,
-                                       bool source_id_is_process_scoped,
-                                       StringId source_scope);
-
-  // Interns a Android async track into the storage.
-  TrackId InternAndroidAsyncTrack(StringId name,
-                                  UniquePid upid,
-                                  int64_t cookie);
-
-  // Interns a track for legacy Chrome process-scoped instant events into the
-  // storage.
-  TrackId InternLegacyChromeProcessInstantTrack(UniquePid upid);
-
-  // Lazily creates the track for legacy Chrome global instant events.
-  TrackId GetOrCreateLegacyChromeGlobalInstantTrack();
-
-  // Create or update the track for the TrackDescriptor with the given |uuid|.
-  // Optionally, associate the track with a process or thread.
-  TrackId UpdateDescriptorTrack(uint64_t uuid,
-                                StringId name,
-                                base::Optional<UniquePid> upid = base::nullopt,
-                                base::Optional<UniqueTid> utid = base::nullopt);
-
-  // Returns the ID of the track for the TrackDescriptor with the given |uuid|.
-  // Returns nullopt if no TrackDescriptor with this |uuid| has been parsed yet.
-  base::Optional<TrackId> GetDescriptorTrack(uint64_t uuid) const;
-
-  // Returns the ID of the TrackDescriptor track associated with the given utid.
-  // If the trace contained multiple tracks associated with the utid, the first
-  // created track is returned. Creates a new track if no such track exists.
-  TrackId GetOrCreateDescriptorTrackForThread(UniqueTid utid);
-
-  // Returns the ID of the implicit trace-global default TrackDescriptor track.
-  TrackId GetOrCreateDefaultDescriptorTrack();
-
-  // Interns a global counter track into the storage.
-  TrackId InternGlobalCounterTrack(StringId name);
-
-  // Interns a counter track associated with a cpu into the storage.
-  TrackId InternCpuCounterTrack(StringId name, uint32_t cpu);
-
-  // Interns a counter track associated with a thread into the storage.
-  TrackId InternThreadCounterTrack(StringId name, UniqueTid utid);
-
-  // Interns a counter track associated with a process into the storage.
-  TrackId InternProcessCounterTrack(StringId name, UniquePid upid);
-
-  // Interns a counter track associated with an irq into the storage.
-  TrackId InternIrqCounterTrack(StringId name, int32_t irq);
-
-  // Interns a counter track associated with an softirq into the storage.
-  TrackId InternSoftirqCounterTrack(StringId name, int32_t softirq);
-
-  // Interns a counter track associated with a GPU into the storage.
-  TrackId InternGpuCounterTrack(StringId name, uint32_t gpu_id);
-
-  // Creates a counter track associated with a GPU into the storage.
-  TrackId CreateGpuCounterTrack(StringId name,
-                                uint32_t gpu_id,
-                                StringId description = 0,
-                                StringId unit = 0);
-
- private:
-  struct GpuTrackTuple {
-    StringId track_name;
-    StringId scope;
-    int64_t context_id;
-
-    friend bool operator<(const GpuTrackTuple& l, const GpuTrackTuple& r) {
-      return std::tie(l.track_name, l.scope, l.context_id)
-          < std::tie(r.track_name, r.scope, r.context_id);
-    }
-  };
-  struct ChromeTrackTuple {
-    base::Optional<int64_t> upid;
-    int64_t source_id = 0;
-    StringId source_scope = 0;
-
-    friend bool operator<(const ChromeTrackTuple& l,
-                          const ChromeTrackTuple& r) {
-      return std::tie(l.source_id, l.upid, l.source_scope) <
-             std::tie(r.source_id, r.upid, r.source_scope);
-    }
-  };
-  struct AndroidAsyncTrackTuple {
-    UniquePid upid;
-    int64_t cookie;
-    StringId name;
-
-    friend bool operator<(const AndroidAsyncTrackTuple& l,
-                          const AndroidAsyncTrackTuple& r) {
-      return std::tie(l.upid, l.cookie, l.name) <
-             std::tie(r.upid, r.cookie, r.name);
-    }
-  };
-
-  static constexpr TrackId kDefaultDescriptorTrackUuid = 0u;
-
-  std::map<UniqueTid /* utid */, TrackId> thread_tracks_;
-  std::map<int64_t /* correlation_id */, TrackId> fuchsia_async_tracks_;
-  std::map<GpuTrackTuple, TrackId> gpu_tracks_;
-  std::map<ChromeTrackTuple, TrackId> chrome_tracks_;
-  std::map<AndroidAsyncTrackTuple, TrackId> android_async_tracks_;
-  std::map<UniquePid, TrackId> chrome_process_instant_tracks_;
-  base::Optional<TrackId> chrome_global_instant_track_id_;
-  std::map<uint64_t /* uuid */, TrackId> descriptor_tracks_;
-  std::map<UniqueTid, TrackId> descriptor_tracks_by_utid_;
-
-  std::map<StringId, TrackId> global_counter_tracks_by_name_;
-  std::map<std::pair<StringId, uint32_t>, TrackId> cpu_counter_tracks_;
-  std::map<std::pair<StringId, UniqueTid>, TrackId> utid_counter_tracks_;
-  std::map<std::pair<StringId, UniquePid>, TrackId> upid_counter_tracks_;
-  std::map<std::pair<StringId, int32_t>, TrackId> irq_counter_tracks_;
-  std::map<std::pair<StringId, int32_t>, TrackId> softirq_counter_tracks_;
-  std::map<std::pair<StringId, uint32_t>, TrackId> gpu_counter_tracks_;
-
-  const StringId source_key_ = 0;
-  const StringId source_id_key_ = 0;
-  const StringId source_id_is_process_scoped_key_ = 0;
-  const StringId source_scope_key_ = 0;
-
-  const StringId fuchsia_source_ = 0;
-  const StringId chrome_source_ = 0;
-  const StringId android_source_ = 0;
-  const StringId descriptor_source_ = 0;
-
-  const StringId default_descriptor_track_name_ = 0;
-
-  TraceProcessorContext* const context_;
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_TRACK_TRACKER_H_
diff --git a/src/trace_processor/variadic.h b/src/trace_processor/variadic.h
deleted file mode 100644
index 6df011e..0000000
--- a/src/trace_processor/variadic.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_VARIADIC_H_
-#define SRC_TRACE_PROCESSOR_VARIADIC_H_
-
-#include "src/trace_processor/string_pool.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// Variadic type representing value of different possible types.
-struct Variadic {
-  enum Type { kInt, kUint, kString, kReal, kPointer, kBool, kJson };
-
-  static Variadic Integer(int64_t int_value) {
-    Variadic variadic;
-    variadic.type = Type::kInt;
-    variadic.int_value = int_value;
-    return variadic;
-  }
-
-  // BEWARE: Unsigned 64-bit integers will be handled as signed integers by
-  // SQLite for built-in SQL operators. This variadic type is used to
-  // distinguish between int64 and uint64 for correct JSON export of TrackEvent
-  // arguments.
-  static Variadic UnsignedInteger(uint64_t uint_value) {
-    Variadic variadic;
-    variadic.type = Type::kUint;
-    variadic.uint_value = uint_value;
-    return variadic;
-  }
-
-  static Variadic String(StringPool::Id string_id) {
-    Variadic variadic;
-    variadic.type = Type::kString;
-    variadic.string_value = string_id;
-    return variadic;
-  }
-
-  static Variadic Real(double real_value) {
-    Variadic variadic;
-    variadic.type = Type::kReal;
-    variadic.real_value = real_value;
-    return variadic;
-  }
-
-  // This variadic type is used to distinguish between integers and pointer
-  // values for correct JSON export of TrackEvent arguments.
-  static Variadic Pointer(uint64_t pointer_value) {
-    Variadic variadic;
-    variadic.type = Type::kPointer;
-    variadic.pointer_value = pointer_value;
-    return variadic;
-  }
-
-  static Variadic Boolean(bool bool_value) {
-    Variadic variadic;
-    variadic.type = Type::kBool;
-    variadic.bool_value = bool_value;
-    return variadic;
-  }
-
-  // This variadic type is used to distinguish between regular string and JSON
-  // string values for correct JSON export of TrackEvent arguments.
-  static Variadic Json(StringPool::Id json_value) {
-    Variadic variadic;
-    variadic.type = Type::kJson;
-    variadic.json_value = json_value;
-    return variadic;
-  }
-
-  // Used in tests.
-  bool operator==(const Variadic& other) const {
-    if (type == other.type) {
-      switch (type) {
-        case kInt:
-          return int_value == other.int_value;
-        case kUint:
-          return uint_value == other.uint_value;
-        case kString:
-          return string_value == other.string_value;
-        case kReal:
-          return std::equal_to<double>()(real_value, other.real_value);
-        case kPointer:
-          return pointer_value == other.pointer_value;
-        case kBool:
-          return bool_value == other.bool_value;
-        case kJson:
-          return json_value == other.json_value;
-      }
-    }
-    return false;
-  }
-
-  Type type;
-  union {
-    int64_t int_value;
-    uint64_t uint_value;
-    StringPool::Id string_value;
-    double real_value;
-    uint64_t pointer_value;
-    bool bool_value;
-    StringPool::Id json_value;
-  };
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_VARIADIC_H_
diff --git a/src/trace_processor/vulkan_memory_tracker.cc b/src/trace_processor/vulkan_memory_tracker.cc
deleted file mode 100644
index ed5db0a..0000000
--- a/src/trace_processor/vulkan_memory_tracker.cc
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/trace_processor/vulkan_memory_tracker.h"
-
-#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/trace_processor_context.h"
-
-#include "perfetto/base/logging.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-VulkanMemoryTracker::VulkanMemoryTracker(TraceProcessorContext* context)
-    : context_(context) {
-  SetupSourceAndTypeInternedStrings();
-}
-
-void VulkanMemoryTracker::SetupSourceAndTypeInternedStrings() {
-  // It seems a good idea to have the source and type of the event coded as
-  // a string id inside the Perfetto db instead of having the enum value
-  // stored. However, it seems that Perfetto only allows protobufs which are
-  // optimized for LITE_RUNTIME (removing the line results in link errors).
-  // Apparently, there is also a minimal implementation of protobuf descriptor
-  // in the code base, but it does not have the reflection to retrieve the name
-  // of the enum. More investigation is required to resolve this.
-
-  // TODO (zakerinasab): Fix and uncomment the following code to avoid
-  // hardcoding the interned strings for the source and type of memory events.
-  // const protos::pbzero::EnumDescriptor* source_descriptor =
-  //     protos::pbzero::VulkanMemoryEvent::Source_descriptor();
-  // for (int i = 0; i < source_descriptor->value_count(); i++) {
-  //   auto source_enum = source_descriptor->value(i);
-  //   auto source_str = source_enum->name();
-  //   auto str_id = context_->storage->InternString(
-  //       base::StringView(source_str.c_str(), source_str.length()));
-  //   source_string_map_.emplace(source_enum->number(), str_id);
-  // }
-
-  // const protos::pbzero::EnumDescriptor* type_descriptor =
-  //     protos::pbzero::VulkanMemoryEvent::Type_descriptor();
-  // for (int i = 0; i < type_descriptor->value_count(); i++) {
-  //   auto type_enum = type_descriptor->value(i);
-  //   auto type_str = type_enum->name();
-  //   auto str_id = context_->storage->InternString(
-  //       base::StringView(type_str.c_str(), type_str.length()));
-  //   type_string_map_.emplace(type_enum->number(), str_id);
-  // }
-
-  std::unordered_map<int, std::string> event_sources({
-      {0, "UNKNOWN_SOURCE"},
-      {1, "DEVICE"},
-      {2, "HOST"},
-      {3, "GPU_DEVICE_MEMORY"},
-      {4, "GPU_BUFFER"},
-      {5, "GPU_IMAGE"},
-  });
-  for (const auto& source : event_sources) {
-    source_string_map_.emplace(
-        source.first, context_->storage->InternString(base::StringView(
-                          source.second.c_str(), source.second.length())));
-  }
-
-  std::unordered_map<int, std::string> event_types({
-      {0, "UNKNOWN_TYPE"},
-      {1, "CREATE"},
-      {2, "DESTROY"},
-      {3, "BIND"},
-      {4, "DESTROY_BOUND"},
-      {5, "ANNOTATIONS"},
-  });
-  for (const auto& type : event_types) {
-    type_string_map_.emplace(type.first,
-                             context_->storage->InternString(base::StringView(
-                                 type.second.c_str(), type.second.length())));
-  }
-}
-
-StringId VulkanMemoryTracker::FindSourceString(
-    SourceStringId source) {
-  StringId res = kNullStringId;
-  auto it = source_string_map_.find(source);
-  if (it == source_string_map_.end()) {
-    context_->storage->IncrementStats(
-        stats::vulkan_allocations_invalid_string_id);
-    return res;
-  }
-  res = it->second;
-  return res;
-}
-
-StringId VulkanMemoryTracker::FindTypeString(
-    SourceStringId type) {
-  StringId res = kNullStringId;
-  auto it = type_string_map_.find(type);
-  if (it == type_string_map_.end()) {
-    context_->storage->IncrementStats(
-        stats::vulkan_allocations_invalid_string_id);
-    return res;
-  }
-  res = it->second;
-  return res;
-}
-
-}  // namespace trace_processor
-}  // namespace perfetto
diff --git a/src/trace_processor/vulkan_memory_tracker.h b/src/trace_processor/vulkan_memory_tracker.h
deleted file mode 100644
index 7f40595..0000000
--- a/src/trace_processor/vulkan_memory_tracker.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACE_PROCESSOR_VULKAN_MEMORY_TRACKER_H_
-#define SRC_TRACE_PROCESSOR_VULKAN_MEMORY_TRACKER_H_
-
-#include <deque>
-
-#include "src/trace_processor/importers/proto/proto_incremental_state.h"
-#include "src/trace_processor/trace_storage.h"
-
-#include "protos/perfetto/trace/gpu/vulkan_memory_event.pbzero.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class TraceProcessorContext;
-
-class VulkanMemoryTracker {
- public:
-  using SourceStringId = uint64_t;
-
-  explicit VulkanMemoryTracker(TraceProcessorContext* context);
-  ~VulkanMemoryTracker() = default;
-
-  template <int32_t FieldId>
-  StringId GetInternedString(PacketSequenceState* state,
-                             size_t generation,
-                             uint64_t iid) {
-    auto* decoder =
-        state->LookupInternedMessage<FieldId, protos::pbzero::InternedString>(
-            generation, iid);
-    if (!decoder)
-      return kNullStringId;
-    return context_->storage->InternString(
-        base::StringView(reinterpret_cast<const char*>(decoder->str().data),
-                         decoder->str().size));
-  }
-
-  StringId FindSourceString(SourceStringId);
-  StringId FindTypeString(SourceStringId);
-
- private:
-  TraceProcessorContext* const context_;
-
-  std::unordered_map<SourceStringId, StringId> source_string_map_;
-  std::unordered_map<SourceStringId, StringId> type_string_map_;
-
-  void SetupSourceAndTypeInternedStrings();
-};
-
-}  // namespace trace_processor
-}  // namespace perfetto
-
-#endif  // SRC_TRACE_PROCESSOR_VULKAN_MEMORY_TRACKER_H_
diff --git a/src/trace_processor/wasm_bridge.cc b/src/trace_processor/wasm_bridge.cc
new file mode 100644
index 0000000..e05a79b
--- /dev/null
+++ b/src/trace_processor/wasm_bridge.cc
@@ -0,0 +1,194 @@
+/*
+ * 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.
+ */
+
+#include <emscripten/emscripten.h>
+#include <map>
+#include <string>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/trace_processor/trace_processor.h"
+
+#include "perfetto/trace_processor/raw_query.pb.h"
+#include "perfetto/trace_processor/sched.pb.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+using RequestID = uint32_t;
+
+// Reply(): replies to a RPC method invocation.
+// Called asynchronously (i.e. in a separate task) by the C++ code inside the
+// trace processor to return data for a RPC method call.
+// The function is generic and thankfully we need just one for all methods
+// because the output is always a protobuf buffer.
+// Args:
+//  RequestID: the ID passed by the embedder when invoking the RPC method (e.g.,
+//             the first argument passed to sched_getSchedEvents()).
+using ReplyFunction = void (*)(RequestID,
+                               bool success,
+                               const char* /*proto_reply_data*/,
+                               uint32_t /*len*/);
+
+namespace {
+TraceProcessor* g_trace_processor;
+ReplyFunction g_reply;
+}  // namespace
+// +---------------------------------------------------------------------------+
+// | Exported functions called by the JS/TS running in the worker.             |
+// +---------------------------------------------------------------------------+
+extern "C" {
+
+void EMSCRIPTEN_KEEPALIVE Initialize(ReplyFunction);
+void Initialize(ReplyFunction reply_function) {
+  PERFETTO_ILOG("Initializing WASM bridge");
+  Config config;
+  g_trace_processor = TraceProcessor::CreateInstance(config).release();
+  g_reply = reply_function;
+}
+
+void EMSCRIPTEN_KEEPALIVE trace_processor_parse(RequestID,
+                                                const uint8_t*,
+                                                uint32_t);
+void trace_processor_parse(RequestID id, const uint8_t* data, size_t size) {
+  // TODO(primiano): This copy is extremely unfortunate. Ideally there should be
+  // a way to take the Blob coming from JS (either from FileReader or from th
+  // fetch() stream) and move into WASM.
+  // See https://github.com/WebAssembly/design/issues/1162.
+  std::unique_ptr<uint8_t[]> buf(new uint8_t[size]);
+  memcpy(buf.get(), data, size);
+  g_trace_processor->Parse(std::move(buf), size);
+  g_reply(id, true, "", 0);
+}
+
+// We keep the same signature as other methods even though we don't take input
+// arguments for simplicity.
+void EMSCRIPTEN_KEEPALIVE trace_processor_notifyEof(RequestID,
+                                                    const uint8_t*,
+                                                    uint32_t);
+void trace_processor_notifyEof(RequestID id, const uint8_t*, uint32_t size) {
+  PERFETTO_DCHECK(!size);
+  g_trace_processor->NotifyEndOfFile();
+  g_reply(id, true, "", 0);
+}
+
+void EMSCRIPTEN_KEEPALIVE trace_processor_rawQuery(RequestID,
+                                                   const uint8_t*,
+                                                   int);
+void trace_processor_rawQuery(RequestID id,
+                              const uint8_t* query_data,
+                              int len) {
+  protos::RawQueryArgs query;
+  bool parsed = query.ParseFromArray(query_data, len);
+  if (!parsed) {
+    std::string err = "Failed to parse input request";
+    g_reply(id, false, err.data(), err.size());
+    return;
+  }
+
+  using ColumnDesc = protos::RawQueryResult::ColumnDesc;
+  protos::RawQueryResult result;
+  auto it = g_trace_processor->ExecuteQuery(query.sql_query().c_str());
+  for (uint32_t col = 0; col < it.ColumnCount(); ++col) {
+    // Setup the descriptors.
+    auto* descriptor = result.add_column_descriptors();
+    descriptor->set_name(it.GetColumName(col));
+    descriptor->set_type(ColumnDesc::UNKNOWN);
+
+    // Add an empty column.
+    result.add_columns();
+  }
+
+  for (uint32_t rows = 0; it.Next(); ++rows) {
+    for (uint32_t col = 0; col < it.ColumnCount(); ++col) {
+      auto* column = result.mutable_columns(static_cast<int>(col));
+      auto* desc = result.mutable_column_descriptors(static_cast<int>(col));
+
+      using SqlValue = trace_processor::SqlValue;
+      auto cell = it.Get(col);
+      if (desc->type() == ColumnDesc::UNKNOWN) {
+        switch (cell.type) {
+          case SqlValue::Type::kLong:
+            desc->set_type(ColumnDesc::LONG);
+            break;
+          case SqlValue::Type::kString:
+            desc->set_type(ColumnDesc::STRING);
+            break;
+          case SqlValue::Type::kDouble:
+            desc->set_type(ColumnDesc::DOUBLE);
+            break;
+          case SqlValue::Type::kNull:
+            break;
+        }
+      }
+
+      // If either the column type is null or we still don't know the type,
+      // just add null values to all the columns.
+      if (cell.type == SqlValue::Type::kNull ||
+          desc->type() == ColumnDesc::UNKNOWN) {
+        column->add_long_values(0);
+        column->add_string_values("[NULL]");
+        column->add_double_values(0);
+        column->add_is_nulls(true);
+        continue;
+      }
+
+      // Cast the sqlite value to the type of the column.
+      switch (desc->type()) {
+        case ColumnDesc::LONG:
+          PERFETTO_CHECK(cell.type == SqlValue::Type::kLong ||
+                         cell.type == SqlValue::Type::kDouble);
+          if (cell.type == SqlValue::Type::kLong) {
+            column->add_long_values(cell.long_value);
+          } else /* if (cell.type == SqlValue::Type::kDouble) */ {
+            column->add_long_values(static_cast<int64_t>(cell.double_value));
+          }
+          column->add_is_nulls(false);
+          break;
+        case ColumnDesc::STRING: {
+          PERFETTO_CHECK(cell.type == SqlValue::Type::kString);
+          column->add_string_values(cell.string_value);
+          column->add_is_nulls(false);
+          break;
+        }
+        case ColumnDesc::DOUBLE:
+          PERFETTO_CHECK(cell.type == SqlValue::Type::kLong ||
+                         cell.type == SqlValue::Type::kDouble);
+          if (cell.type == SqlValue::Type::kLong) {
+            column->add_double_values(static_cast<double>(cell.long_value));
+          } else /* if (cell.type == SqlValue::Type::kDouble) */ {
+            column->add_double_values(cell.double_value);
+          }
+          column->add_is_nulls(false);
+          break;
+        case ColumnDesc::UNKNOWN:
+          PERFETTO_FATAL("Handled in if statement above.");
+      }
+    }
+    result.set_num_records(rows + 1);
+  }
+  if (auto opt_error = it.GetLastError()) {
+    result.set_error(*opt_error);
+  }
+
+  std::string encoded;
+  result.SerializeToString(&encoded);
+  g_reply(id, true, encoded.data(), static_cast<uint32_t>(encoded.size()));
+}
+
+}  // extern "C"
+
+}  // namespace trace_processor
+}  // namespace perfetto
diff --git a/src/trace_processor/window_operator_table.cc b/src/trace_processor/window_operator_table.cc
index 727b32a..2d22422 100644
--- a/src/trace_processor/window_operator_table.cc
+++ b/src/trace_processor/window_operator_table.cc
@@ -16,7 +16,7 @@
 
 #include "src/trace_processor/window_operator_table.h"
 
-#include "src/trace_processor/sqlite/sqlite_utils.h"
+#include "src/trace_processor/sqlite_utils.h"
 
 namespace perfetto {
 namespace trace_processor {
@@ -29,45 +29,42 @@
 
 void WindowOperatorTable::RegisterTable(sqlite3* db,
                                         const TraceStorage* storage) {
-  SqliteTable::Register<WindowOperatorTable>(db, storage, "window", true);
+  Table::Register<WindowOperatorTable>(db, storage, "window", true);
 }
 
-util::Status WindowOperatorTable::Init(int,
-                                       const char* const*,
-                                       Schema* schema) {
+base::Optional<Table::Schema> WindowOperatorTable::Init(int,
+                                                        const char* const*) {
   const bool kHidden = true;
-  *schema = Schema(
+  return Schema(
       {
           // These are the operator columns:
-          SqliteTable::Column(Column::kRowId, "rowid", SqlValue::Type::kLong,
-                              kHidden),
-          SqliteTable::Column(Column::kQuantum, "quantum",
-                              SqlValue::Type::kLong, kHidden),
-          SqliteTable::Column(Column::kWindowStart, "window_start",
-                              SqlValue::Type::kLong, kHidden),
-          SqliteTable::Column(Column::kWindowDur, "window_dur",
-                              SqlValue::Type::kLong, kHidden),
+          Table::Column(Column::kRowId, "rowid", ColumnType::kLong, kHidden),
+          Table::Column(Column::kQuantum, "quantum", ColumnType::kLong,
+                        kHidden),
+          Table::Column(Column::kWindowStart, "window_start", ColumnType::kLong,
+                        kHidden),
+          Table::Column(Column::kWindowDur, "window_dur", ColumnType::kLong,
+                        kHidden),
           // These are the ouput columns:
-          SqliteTable::Column(Column::kTs, "ts", SqlValue::Type::kLong),
-          SqliteTable::Column(Column::kDuration, "dur", SqlValue::Type::kLong),
-          SqliteTable::Column(Column::kQuantumTs, "quantum_ts",
-                              SqlValue::Type::kLong),
+          Table::Column(Column::kTs, "ts", ColumnType::kLong),
+          Table::Column(Column::kDuration, "dur", ColumnType::kLong),
+          Table::Column(Column::kQuantumTs, "quantum_ts", ColumnType::kLong),
       },
       {Column::kRowId});
-  return util::OkStatus();
 }
 
-std::unique_ptr<SqliteTable::Cursor> WindowOperatorTable::CreateCursor() {
-  return std::unique_ptr<SqliteTable::Cursor>(new Cursor(this));
+std::unique_ptr<Table::Cursor> WindowOperatorTable::CreateCursor() {
+  return std::unique_ptr<Table::Cursor>(new Cursor(this));
 }
 
 int WindowOperatorTable::BestIndex(const QueryConstraints& qc,
                                    BestIndexInfo* info) {
   // Remove ordering on timestamp if it is the only ordering as we are already
   // sorted on TS. This makes span joining significantly faster.
-  const auto& ob = qc.order_by();
-  info->prune_order_by =
-      ob.size() == 1 && ob[0].iColumn == Column::kTs && !ob[0].desc;
+  if (qc.order_by().size() == 1 && qc.order_by()[0].iColumn == Column::kTs &&
+      !qc.order_by()[0].desc) {
+    info->order_by_consumed = true;
+  }
   return SQLITE_OK;
 }
 
@@ -96,7 +93,7 @@
 }
 
 WindowOperatorTable::Cursor::Cursor(WindowOperatorTable* table)
-    : SqliteTable::Cursor(table), table_(table) {}
+    : Table::Cursor(table), table_(table) {}
 
 int WindowOperatorTable::Cursor::Filter(const QueryConstraints& qc,
                                         sqlite3_value** argv) {
diff --git a/src/trace_processor/window_operator_table.h b/src/trace_processor/window_operator_table.h
index 5959174..fc8f102 100644
--- a/src/trace_processor/window_operator_table.h
+++ b/src/trace_processor/window_operator_table.h
@@ -20,14 +20,14 @@
 #include <limits>
 #include <memory>
 
-#include "src/trace_processor/sqlite/sqlite_table.h"
+#include "src/trace_processor/table.h"
 
 namespace perfetto {
 namespace trace_processor {
 
 class TraceStorage;
 
-class WindowOperatorTable : public SqliteTable {
+class WindowOperatorTable : public Table {
  public:
   enum Column {
     kRowId = 0,
@@ -38,11 +38,11 @@
     kDuration = 5,
     kQuantumTs = 6
   };
-  class Cursor : public SqliteTable::Cursor {
+  class Cursor : public Table::Cursor {
    public:
     Cursor(WindowOperatorTable*);
 
-    // Implementation of SqliteTable::Cursor.
+    // Implementation of Table::Cursor.
     int Filter(const QueryConstraints& qc, sqlite3_value**) override;
     int Next() override;
     int Eof() override;
@@ -75,8 +75,8 @@
   WindowOperatorTable(sqlite3*, const TraceStorage*);
 
   // Table implementation.
-  util::Status Init(int, const char* const*, Schema* schema) override;
-  std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
+  base::Optional<Table::Schema> Init(int, const char* const*) override;
+  std::unique_ptr<Table::Cursor> CreateCursor() override;
   int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
   int Update(int, sqlite3_value**, sqlite3_int64*) override;
 
diff --git a/src/traced/probes/BUILD.gn b/src/traced/probes/BUILD.gn
index 7001f7c..adc0124 100644
--- a/src/traced/probes/BUILD.gn
+++ b/src/traced/probes/BUILD.gn
@@ -12,26 +12,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../gn/test.gni")
-
-# The unprivileged daemon that is allowed to access tracefs (for ftrace).
-# Registers as a Producer on the traced daemon.
-executable("traced_probes") {
-  deps = [
-    "../../../:libperfetto",
-    "../../../gn:default_deps",
-    "../../../include/perfetto/ext/traced",
-  ]
-  sources = [
-    "main.cc",
-  ]
-}
-
-# Contains all the implementation but not the main() entry point. This target
-# is shared both by the executable and tests.
 source_set("probes") {
   public_deps = [
-    "../../../include/perfetto/ext/traced",
+    "../../../include/perfetto/traced",
   ]
   deps = [
     ":probes_src",
@@ -50,15 +33,13 @@
   deps = [
     ":data_source",
     "../../../gn:default_deps",
-    "../../../include/perfetto/ext/traced",
-    "../../../protos/perfetto/config/ftrace:cpp",
+    "../../../include/perfetto/traced",
     "../../../protos/perfetto/trace/ps:zero",
     "../../base",
     "../../tracing:ipc",
     "../../tracing:tracing",
     "android_log",
     "filesystem",
-    "metatrace",
     "packages_list",
     "power",
     "ps",
@@ -83,12 +64,12 @@
   ]
 }
 
-perfetto_unittest_source_set("unittests") {
+source_set("unittests") {
   testonly = true
   deps = [
     ":probes_src",
     "../../../gn:default_deps",
-    "../../../gn:gtest_and_gmock",
+    "../../../gn:gtest_deps",
     "../../tracing:test_support",
     "android_log:unittests",
     "filesystem:unittests",
diff --git a/src/traced/probes/android_log/BUILD.gn b/src/traced/probes/android_log/BUILD.gn
index eac5fd3..cbd9148 100644
--- a/src/traced/probes/android_log/BUILD.gn
+++ b/src/traced/probes/android_log/BUILD.gn
@@ -12,8 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../../gn/test.gni")
-
 source_set("android_log") {
   public_deps = [
     "../../../tracing",
@@ -21,9 +19,8 @@
   deps = [
     "..:data_source",
     "../../../../gn:default_deps",
-    "../../../../include/perfetto/ext/traced",
+    "../../../../include/perfetto/traced",
     "../../../../protos/perfetto/common:zero",
-    "../../../../protos/perfetto/config/android:zero",
     "../../../../protos/perfetto/trace/android:zero",
     "../../../base",
   ]
@@ -33,14 +30,13 @@
   ]
 }
 
-perfetto_unittest_source_set("unittests") {
+source_set("unittests") {
   testonly = true
   deps = [
     ":android_log",
     "../../../../gn:default_deps",
-    "../../../../gn:gtest_and_gmock",
-    "../../../../protos/perfetto/common:zero",
-    "../../../../protos/perfetto/config/android:zero",
+    "../../../../gn:gtest_deps",
+    "../../../../protos/perfetto/trace:lite",
     "../../../../src/base:test_support",
     "../../../../src/tracing:test_support",
   ]
diff --git a/src/traced/probes/android_log/android_log_data_source.cc b/src/traced/probes/android_log/android_log_data_source.cc
index c49bec6..5fad9af 100644
--- a/src/traced/probes/android_log/android_log_data_source.cc
+++ b/src/traced/probes/android_log/android_log_data_source.cc
@@ -16,31 +16,25 @@
 
 #include "src/traced/probes/android_log/android_log_data_source.h"
 
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/logging.h"
+#include "perfetto/base/optional.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/string_splitter.h"
 #include "perfetto/base/task_runner.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/ext/base/unix_socket.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
+#include "perfetto/base/unix_socket.h"
 #include "perfetto/tracing/core/data_source_config.h"
+#include "perfetto/tracing/core/trace_packet.h"
+#include "perfetto/tracing/core/trace_writer.h"
 
-#include "protos/perfetto/common/android_log_constants.pbzero.h"
-#include "protos/perfetto/config/android/android_log_config.pbzero.h"
-#include "protos/perfetto/trace/android/android_log.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/android/android_log.pbzero.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
 
 namespace {
 
-using protos::pbzero::AndroidLogConfig;
-using protos::pbzero::AndroidLogId;
-
 constexpr size_t kBufSize = base::kPageSize;
 const char kLogTagsPath[] = "/system/etc/event-log-tags";
 const char kLogdrSocket[] = "/dev/socket/logdr";
@@ -93,21 +87,18 @@
       task_runner_(task_runner),
       writer_(std::move(writer)),
       weak_factory_(this) {
-  AndroidLogConfig::Decoder cfg(ds_config.android_log_config_raw());
-
+  const auto& cfg = ds_config.android_log_config();
   std::vector<uint32_t> log_ids;
-  for (auto id = cfg.log_ids(); id; ++id)
-    log_ids.push_back(static_cast<uint32_t>(*id));
-
+  for (uint32_t id : cfg.log_ids())
+    log_ids.push_back(id);
   if (log_ids.empty()) {
     // If no log id is specified, add the most popular ones.
-    log_ids.push_back(AndroidLogId::LID_DEFAULT);
-    log_ids.push_back(AndroidLogId::LID_EVENTS);
-    log_ids.push_back(AndroidLogId::LID_SYSTEM);
-    log_ids.push_back(AndroidLogId::LID_CRASH);
-    log_ids.push_back(AndroidLogId::LID_KERNEL);
+    log_ids.push_back(AndroidLogConfig::AndroidLogId::LID_DEFAULT);
+    log_ids.push_back(AndroidLogConfig::AndroidLogId::LID_EVENTS);
+    log_ids.push_back(AndroidLogConfig::AndroidLogId::LID_SYSTEM);
+    log_ids.push_back(AndroidLogConfig::AndroidLogId::LID_CRASH);
+    log_ids.push_back(AndroidLogConfig::AndroidLogId::LID_KERNEL);
   }
-
   // Build the command string that will be sent to the logdr socket on Start(),
   // which looks like "stream lids=1,2,3,4" (lids == log buffer id(s)).
   mode_ = "stream tail=1 lids";
@@ -123,8 +114,7 @@
   // This is to avoid copying strings of tags for the only sake of checking for
   // their existence in the set.
   std::vector<std::pair<size_t, size_t>> tag_boundaries;
-  for (auto it = cfg.filter_tags(); it; ++it) {
-    base::StringView tag(*it);
+  for (const std::string& tag : cfg.filter_tags()) {
     const size_t begin = filter_tags_strbuf_.size();
     filter_tags_strbuf_.insert(filter_tags_strbuf_.end(), tag.begin(),
                                tag.end());
@@ -148,8 +138,7 @@
 }
 
 base::UnixSocketRaw AndroidLogDataSource::ConnectLogdrSocket() {
-  auto socket = base::UnixSocketRaw::CreateMayFail(base::SockFamily::kUnix,
-                                                   base::SockType::kSeqPacket);
+  auto socket = base::UnixSocketRaw::CreateMayFail(base::SockType::kSeqPacket);
   if (!socket || !socket.Connect(kLogdrSocket)) {
     PERFETTO_PLOG("Failed to connect to %s", kLogdrSocket);
     return base::UnixSocketRaw();
@@ -265,7 +254,7 @@
 
     protos::pbzero::AndroidLogPacket::LogEvent* evt = nullptr;
 
-    if (entry.lid == AndroidLogId::LID_EVENTS) {
+    if (entry.lid == AndroidLogConfig::AndroidLogId::LID_EVENTS) {
       // Entries in the EVENTS buffer are special, they are binary encoded.
       // See https://developer.android.com/reference/android/util/EventLog.
       if (!ParseBinaryEvent(buf, end, log_packet, &evt)) {
diff --git a/src/traced/probes/android_log/android_log_data_source.h b/src/traced/probes/android_log/android_log_data_source.h
index 171e543..3a19e19 100644
--- a/src/traced/probes/android_log/android_log_data_source.h
+++ b/src/traced/probes/android_log/android_log_data_source.h
@@ -21,11 +21,11 @@
 #include <unordered_set>
 #include <vector>
 
-#include "perfetto/ext/base/paged_memory.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/ext/base/unix_socket.h"
-#include "perfetto/ext/base/weak_ptr.h"
+#include "perfetto/base/paged_memory.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/string_view.h"
+#include "perfetto/base/unix_socket.h"
+#include "perfetto/base/weak_ptr.h"
 #include "src/traced/probes/probes_data_source.h"
 
 namespace perfetto {
diff --git a/src/traced/probes/android_log/android_log_data_source_unittest.cc b/src/traced/probes/android_log/android_log_data_source_unittest.cc
index 1c90204..09bf81a 100644
--- a/src/traced/probes/android_log/android_log_data_source_unittest.cc
+++ b/src/traced/probes/android_log/android_log_data_source_unittest.cc
@@ -16,16 +16,16 @@
 
 #include "src/traced/probes/android_log/android_log_data_source.h"
 
-#include "perfetto/protozero/scattered_heap_buffer.h"
 #include "perfetto/tracing/core/data_source_config.h"
-#include "protos/perfetto/common/android_log_constants.pbzero.h"
-#include "protos/perfetto/config/android/android_log_config.pbzero.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/tracing/core/trace_writer_for_testing.h"
-#include "test/gtest_and_gmock.h"
 
-using ::perfetto::protos::pbzero::AndroidLogConfig;
-using ::perfetto::protos::pbzero::AndroidLogId;
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "perfetto/trace/trace_packet.pb.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
+
 using ::testing::Invoke;
 using ::testing::Return;
 
@@ -62,8 +62,8 @@
     base::UnixSocketRaw recv_sock;
     // In theory this should be a kSeqPacket. We use kDgram here so that the
     // test can run also on MacOS (which doesn't support SOCK_SEQPACKET).
-    std::tie(send_sock, recv_sock) = base::UnixSocketRaw::CreatePair(
-        base::SockFamily::kUnix, base::SockType::kDgram);
+    const auto kSockType = base::SockType::kDgram;
+    std::tie(send_sock, recv_sock) = base::UnixSocketRaw::CreatePair(kSockType);
     ASSERT_TRUE(send_sock);
     ASSERT_TRUE(recv_sock);
 
@@ -180,18 +180,18 @@
   auto* fmt = data_source_->GetEventFormat(42);
   ASSERT_NE(fmt, nullptr);
   ASSERT_EQ(fmt->name, "answer");
-  ASSERT_EQ(fmt->fields.size(), 1u);
+  ASSERT_EQ(fmt->fields.size(), 1);
   ASSERT_EQ(fmt->fields[0], "to life the universe etc");
 
   fmt = data_source_->GetEventFormat(314);
   ASSERT_NE(fmt, nullptr);
   ASSERT_EQ(fmt->name, "pi");
-  ASSERT_EQ(fmt->fields.size(), 0u);
+  ASSERT_EQ(fmt->fields.size(), 0);
 
   fmt = data_source_->GetEventFormat(1005);
   ASSERT_NE(fmt, nullptr);
   ASSERT_EQ(fmt->name, "tag_def");
-  ASSERT_EQ(fmt->fields.size(), 3u);
+  ASSERT_EQ(fmt->fields.size(), 3);
   ASSERT_EQ(fmt->fields[0], "tag");
   ASSERT_EQ(fmt->fields[1], "name");
   ASSERT_EQ(fmt->fields[2], "format");
@@ -199,7 +199,7 @@
   fmt = data_source_->GetEventFormat(1937006964);
   ASSERT_NE(fmt, nullptr);
   ASSERT_EQ(fmt->name, "stats_log");
-  ASSERT_EQ(fmt->fields.size(), 2u);
+  ASSERT_EQ(fmt->fields.size(), 2);
   ASSERT_EQ(fmt->fields[0], "atom_id");
   ASSERT_EQ(fmt->fields[1], "data");
 }
@@ -210,23 +210,21 @@
   EXPECT_CALL(*data_source_, ReadEventLogDefinitions()).WillOnce(Return(""));
   StartAndSimulateLogd(kValidTextEvents);
 
-  // Read back the data that would have been written into the trace. One packet
-  // with the events, one with stats.
-  auto packets = writer_raw_->GetAllTracePackets();
-  ASSERT_TRUE(packets.size() == 2);
-  auto event_packet = packets[0];
-  auto stats_packet = packets[1];
-  EXPECT_TRUE(stats_packet.android_log().has_stats());
+  // Read back the data that would have been written into the trace.
 
-  EXPECT_EQ(event_packet.android_log().events_size(), 3);
-  const auto& decoded = event_packet.android_log().events();
+  auto packet = writer_raw_->ParseProto();
+  ASSERT_TRUE(packet);
+  ASSERT_TRUE(packet->has_android_log());
+  EXPECT_EQ(packet->android_log().events_size(), 3);
+
+  const auto& decoded = packet->android_log().events();
 
   EXPECT_EQ(decoded.Get(0).log_id(), protos::AndroidLogId::LID_SYSTEM);
   EXPECT_EQ(decoded.Get(0).pid(), 7546);
   EXPECT_EQ(decoded.Get(0).tid(), 8991);
   EXPECT_EQ(decoded.Get(0).uid(), 1000);
   EXPECT_EQ(decoded.Get(0).prio(), protos::AndroidLogPriority::PRIO_INFO);
-  EXPECT_EQ(decoded.Get(0).timestamp(), 1546125239679172326ULL);
+  EXPECT_EQ(decoded.Get(0).timestamp(), 1546125239679172326LL);
   EXPECT_EQ(decoded.Get(0).tag(), "ActivityManager");
   EXPECT_EQ(
       decoded.Get(0).message(),
@@ -237,7 +235,7 @@
   EXPECT_EQ(decoded.Get(1).tid(), 7570);
   EXPECT_EQ(decoded.Get(1).uid(), 1000);
   EXPECT_EQ(decoded.Get(1).prio(), protos::AndroidLogPriority::PRIO_WARN);
-  EXPECT_EQ(decoded.Get(1).timestamp(), 1546125239683537170ULL);
+  EXPECT_EQ(decoded.Get(1).timestamp(), 1546125239683537170LL);
   EXPECT_EQ(decoded.Get(1).tag(), "libprocessgroup");
   EXPECT_EQ(decoded.Get(1).message(),
             "kill(-11660, 9) failed: No such process");
@@ -247,54 +245,47 @@
   EXPECT_EQ(decoded.Get(2).tid(), 7415);
   EXPECT_EQ(decoded.Get(2).uid(), 0);
   EXPECT_EQ(decoded.Get(2).prio(), protos::AndroidLogPriority::PRIO_INFO);
-  EXPECT_EQ(decoded.Get(2).timestamp(), 1546125239719458684ULL);
+  EXPECT_EQ(decoded.Get(2).timestamp(), 1546125239719458684LL);
   EXPECT_EQ(decoded.Get(2).tag(), "Zygote");
   EXPECT_EQ(decoded.Get(2).message(), "Process 11660 exited due to signal (9)");
 }
 
 TEST_F(AndroidLogDataSourceTest, TextEventsWithTagFiltering) {
   DataSourceConfig cfg;
-  protozero::HeapBuffered<AndroidLogConfig> acfg;
-  acfg->add_filter_tags("Zygote");
-  acfg->add_filter_tags("ActivityManager");
-  acfg->add_filter_tags("Unmatched");
-  acfg->add_filter_tags("libprocessgroupZZ");
-  cfg.set_android_log_config_raw(acfg.SerializeAsString());
+  *cfg.mutable_android_log_config()->add_filter_tags() = "Zygote";
+  *cfg.mutable_android_log_config()->add_filter_tags() = "ActivityManager";
+  *cfg.mutable_android_log_config()->add_filter_tags() = "Unmatched";
+  *cfg.mutable_android_log_config()->add_filter_tags() = "libprocessgroupZZ";
 
   CreateInstance(cfg);
   EXPECT_CALL(*data_source_, ReadEventLogDefinitions()).WillOnce(Return(""));
   StartAndSimulateLogd(kValidTextEvents);
 
-  auto packets = writer_raw_->GetAllTracePackets();
-  ASSERT_TRUE(packets.size() == 2);
-  auto event_packet = packets[0];
-  auto stats_packet = packets[1];
-  EXPECT_TRUE(stats_packet.android_log().has_stats());
+  auto packet = writer_raw_->ParseProto();
+  ASSERT_TRUE(packet);
+  ASSERT_TRUE(packet->has_android_log());
+  EXPECT_EQ(packet->android_log().events_size(), 2);
 
-  EXPECT_EQ(event_packet.android_log().events_size(), 2);
-  const auto& decoded = event_packet.android_log().events();
+  const auto& decoded = packet->android_log().events();
   EXPECT_EQ(decoded.Get(0).tag(), "ActivityManager");
   EXPECT_EQ(decoded.Get(1).tag(), "Zygote");
 }
 
 TEST_F(AndroidLogDataSourceTest, TextEventsWithPrioFiltering) {
   DataSourceConfig cfg;
-  protozero::HeapBuffered<AndroidLogConfig> acfg;
-  acfg->set_min_prio(protos::pbzero::AndroidLogPriority::PRIO_WARN);
-  cfg.set_android_log_config_raw(acfg.SerializeAsString());
+  cfg.mutable_android_log_config()->set_min_prio(
+      AndroidLogConfig::AndroidLogPriority::PRIO_WARN);
 
   CreateInstance(cfg);
   EXPECT_CALL(*data_source_, ReadEventLogDefinitions()).WillOnce(Return(""));
   StartAndSimulateLogd(kValidTextEvents);
 
-  auto packets = writer_raw_->GetAllTracePackets();
-  ASSERT_TRUE(packets.size() == 2);
-  auto event_packet = packets[0];
-  auto stats_packet = packets[1];
-  EXPECT_TRUE(stats_packet.android_log().has_stats());
+  auto packet = writer_raw_->ParseProto();
+  ASSERT_TRUE(packet);
+  ASSERT_TRUE(packet->has_android_log());
+  EXPECT_EQ(packet->android_log().events_size(), 1);
 
-  EXPECT_EQ(event_packet.android_log().events_size(), 1);
-  const auto& decoded = event_packet.android_log().events();
+  const auto& decoded = packet->android_log().events();
   EXPECT_EQ(decoded.Get(0).tag(), "libprocessgroup");
 }
 
@@ -309,22 +300,20 @@
   EXPECT_CALL(*data_source_, ReadEventLogDefinitions()).WillOnce(Return(kDefs));
   StartAndSimulateLogd(kValidBinaryEvents);
 
-  // Read back the data that would have been written into the trace. One packet
-  // with the events, one with stats.
-  auto packets = writer_raw_->GetAllTracePackets();
-  ASSERT_TRUE(packets.size() == 2);
-  auto event_packet = packets[0];
-  auto stats_packet = packets[1];
-  EXPECT_TRUE(stats_packet.android_log().has_stats());
+  // Read back the data that would have been written into the trace.
 
-  EXPECT_EQ(event_packet.android_log().events_size(), 3);
-  const auto& decoded = event_packet.android_log().events();
+  auto packet = writer_raw_->ParseProto();
+  ASSERT_TRUE(packet);
+  ASSERT_TRUE(packet->has_android_log());
+  EXPECT_EQ(packet->android_log().events_size(), 3);
+
+  const auto& decoded = packet->android_log().events();
 
   EXPECT_EQ(decoded.Get(0).log_id(), protos::AndroidLogId::LID_EVENTS);
   EXPECT_EQ(decoded.Get(0).pid(), 29981);
   EXPECT_EQ(decoded.Get(0).tid(), 30962);
   EXPECT_EQ(decoded.Get(0).uid(), 1000);
-  EXPECT_EQ(decoded.Get(0).timestamp(), 1546165328914257883ULL);
+  EXPECT_EQ(decoded.Get(0).timestamp(), 1546165328914257883LL);
   EXPECT_EQ(decoded.Get(0).tag(), "am_kill");
   ASSERT_EQ(decoded.Get(0).args_size(), 5);
   EXPECT_EQ(decoded.Get(0).args(0).name(), "User");
@@ -342,7 +331,7 @@
   EXPECT_EQ(decoded.Get(1).pid(), 29981);
   EXPECT_EQ(decoded.Get(1).tid(), 30962);
   EXPECT_EQ(decoded.Get(1).uid(), 1000);
-  EXPECT_EQ(decoded.Get(1).timestamp(), 1546165328946231844ULL);
+  EXPECT_EQ(decoded.Get(1).timestamp(), 1546165328946231844LL);
   EXPECT_EQ(decoded.Get(1).tag(), "am_uid_stopped");
   ASSERT_EQ(decoded.Get(1).args_size(), 1);
   EXPECT_EQ(decoded.Get(1).args(0).name(), "UID");
@@ -352,7 +341,7 @@
   EXPECT_EQ(decoded.Get(2).pid(), 29981);
   EXPECT_EQ(decoded.Get(2).tid(), 29998);
   EXPECT_EQ(decoded.Get(2).uid(), 1000);
-  EXPECT_EQ(decoded.Get(2).timestamp(), 1546165328960813044ULL);
+  EXPECT_EQ(decoded.Get(2).timestamp(), 1546165328960813044LL);
   EXPECT_EQ(decoded.Get(2).tag(), "am_pss");
   ASSERT_EQ(decoded.Get(2).args_size(), 10);
   EXPECT_EQ(decoded.Get(2).args(0).name(), "Pid");
@@ -380,10 +369,8 @@
 
 TEST_F(AndroidLogDataSourceTest, BinaryEventsWithTagFiltering) {
   DataSourceConfig cfg;
-  protozero::HeapBuffered<AndroidLogConfig> acfg;
-  acfg->add_filter_tags("not mached");
-  acfg->add_filter_tags("am_uid_stopped");
-  cfg.set_android_log_config_raw(acfg.SerializeAsString());
+  *cfg.mutable_android_log_config()->add_filter_tags() = "not mached";
+  *cfg.mutable_android_log_config()->add_filter_tags() = "am_uid_stopped";
   CreateInstance(cfg);
   static const char kDefs[] = R"(
 30023 am_kill (User|1|5),(PID|1|5),(Process Name|3),(OomAdj|1|5),(Reason|3)
@@ -393,17 +380,15 @@
   EXPECT_CALL(*data_source_, ReadEventLogDefinitions()).WillOnce(Return(kDefs));
   StartAndSimulateLogd(kValidBinaryEvents);
 
-  // Read back the data that would have been written into the trace. One packet
-  // with the events, one with stats.
-  auto packets = writer_raw_->GetAllTracePackets();
-  ASSERT_TRUE(packets.size() == 2);
-  auto event_packet = packets[0];
-  auto stats_packet = packets[1];
-  EXPECT_TRUE(stats_packet.android_log().has_stats());
+  // Read back the data that would have been written into the trace.
 
-  EXPECT_EQ(event_packet.android_log().events_size(), 1);
-  const auto& decoded = event_packet.android_log().events();
-  EXPECT_EQ(decoded.Get(0).timestamp(), 1546165328946231844ULL);
+  auto packet = writer_raw_->ParseProto();
+  ASSERT_TRUE(packet);
+  ASSERT_TRUE(packet->has_android_log());
+  EXPECT_EQ(packet->android_log().events_size(), 1);
+
+  const auto& decoded = packet->android_log().events();
+  EXPECT_EQ(decoded.Get(0).timestamp(), 1546165328946231844LL);
   EXPECT_EQ(decoded.Get(0).tag(), "am_uid_stopped");
 }
 
diff --git a/src/traced/probes/filesystem/BUILD.gn b/src/traced/probes/filesystem/BUILD.gn
index d3aeba5..45415e0 100644
--- a/src/traced/probes/filesystem/BUILD.gn
+++ b/src/traced/probes/filesystem/BUILD.gn
@@ -12,8 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../../gn/test.gni")
-
 source_set("filesystem") {
   public_deps = [
     "../../../../protos/perfetto/trace/filesystem:zero",
@@ -22,8 +20,7 @@
   deps = [
     "..:data_source",
     "../../../../gn:default_deps",
-    "../../../../include/perfetto/ext/traced",
-    "../../../../protos/perfetto/config/inode_file:zero",
+    "../../../../include/perfetto/traced",
     "../../../base",
   ]
   sources = [
@@ -42,14 +39,12 @@
   ]
 }
 
-perfetto_unittest_source_set("unittests") {
+source_set("unittests") {
   testonly = true
   deps = [
     ":filesystem",
     "../../../../gn:default_deps",
-    "../../../../gn:gtest_and_gmock",
-    "../../../../include/perfetto/protozero",
-    "../../../../protos/perfetto/config/inode_file:zero",
+    "../../../../gn:gtest_deps",
     "../../../../src/base:test_support",
   ]
   sources = [
diff --git a/src/traced/probes/filesystem/file_scanner.cc b/src/traced/probes/filesystem/file_scanner.cc
index 17dd253..c71bbdf 100644
--- a/src/traced/probes/filesystem/file_scanner.cc
+++ b/src/traced/probes/filesystem/file_scanner.cc
@@ -21,7 +21,6 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include "protos/perfetto/trace/filesystem/inode_file_map.pbzero.h"
 #include "src/traced/probes/filesystem/inode_file_data_source.h"
 
 namespace perfetto {
diff --git a/src/traced/probes/filesystem/file_scanner.h b/src/traced/probes/filesystem/file_scanner.h
index aee07db..7e8f909 100644
--- a/src/traced/probes/filesystem/file_scanner.h
+++ b/src/traced/probes/filesystem/file_scanner.h
@@ -20,10 +20,10 @@
 #include <string>
 #include <vector>
 
+#include "perfetto/base/scoped_file.h"
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/traced/data_source_types.h"
+#include "perfetto/base/weak_ptr.h"
+#include "perfetto/traced/data_source_types.h"
 
 namespace perfetto {
 
@@ -34,7 +34,7 @@
     virtual bool OnInodeFound(BlockDeviceID,
                               Inode,
                               const std::string&,
-                              InodeFileMap_Entry_Type) = 0;
+                              protos::pbzero::InodeFileMap_Entry_Type) = 0;
     virtual void OnInodeScanDone() = 0;
     virtual ~Delegate();
   };
diff --git a/src/traced/probes/filesystem/file_scanner_unittest.cc b/src/traced/probes/filesystem/file_scanner_unittest.cc
index 5b77009..29776b0 100644
--- a/src/traced/probes/filesystem/file_scanner_unittest.cc
+++ b/src/traced/probes/filesystem/file_scanner_unittest.cc
@@ -16,15 +16,15 @@
 
 #include "src/traced/probes/filesystem/file_scanner.h"
 
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
 #include <sys/stat.h>
 #include <memory>
 #include <string>
 
 #include "perfetto/base/logging.h"
-#include "protos/perfetto/trace/filesystem/inode_file_map.pbzero.h"
 #include "src/base/test/test_task_runner.h"
-#include "src/base/test/utils.h"
-#include "test/gtest_and_gmock.h"
 
 namespace perfetto {
 namespace {
@@ -35,25 +35,28 @@
 
 class TestDelegate : public FileScanner::Delegate {
  public:
-  TestDelegate(std::function<bool(BlockDeviceID,
-                                  Inode,
-                                  const std::string&,
-                                  InodeFileMap_Entry_Type)> callback,
-               std::function<void()> done_callback)
+  TestDelegate(
+      std::function<bool(BlockDeviceID,
+                         Inode,
+                         const std::string&,
+                         protos::pbzero::InodeFileMap_Entry_Type)> callback,
+      std::function<void()> done_callback)
       : callback_(std::move(callback)),
         done_callback_(std::move(done_callback)) {}
   bool OnInodeFound(BlockDeviceID block_device_id,
                     Inode inode,
                     const std::string& path,
-                    InodeFileMap_Entry_Type type) override {
+                    protos::pbzero::InodeFileMap_Entry_Type type) override {
     return callback_(block_device_id, inode, path, type);
   }
 
   void OnInodeScanDone() { return done_callback_(); }
 
  private:
-  std::function<
-      bool(BlockDeviceID, Inode, const std::string&, InodeFileMap_Entry_Type)>
+  std::function<bool(BlockDeviceID,
+                     Inode,
+                     const std::string&,
+                     protos::pbzero::InodeFileMap_Entry_Type)>
       callback_;
   std::function<void()> done_callback_;
 };
@@ -62,7 +65,7 @@
   FileEntry(BlockDeviceID block_device_id,
             Inode inode,
             std::string path,
-            InodeFileMap_Entry_Type type)
+            protos::pbzero::InodeFileMap_Entry_Type type)
       : block_device_id_(block_device_id),
         inode_(inode),
         path_(std::move(path)),
@@ -77,7 +80,7 @@
   BlockDeviceID block_device_id_;
   Inode inode_;
   std::string path_;
-  InodeFileMap_Entry_Type type_;
+  protos::pbzero::InodeFileMap_Entry_Type type_;
 };
 
 struct stat CheckStat(const std::string& path) {
@@ -86,7 +89,8 @@
   return buf;
 }
 
-FileEntry StatFileEntry(const std::string& path, InodeFileMap_Entry_Type type) {
+FileEntry StatFileEntry(const std::string& path,
+                        protos::pbzero::InodeFileMap_Entry_Type type) {
   struct stat buf = CheckStat(path);
   return FileEntry(buf.st_dev, buf.st_ino, path, type);
 }
@@ -96,15 +100,13 @@
   bool done = false;
   TestDelegate delegate(
       [&seen](BlockDeviceID, Inode, const std::string&,
-              InodeFileMap_Entry_Type) {
+              protos::pbzero::InodeFileMap_Entry_Type) {
         ++seen;
         return false;
       },
       [&done] { done = true; });
 
-  FileScanner fs(
-      {base::GetTestDataPath("src/traced/probes/filesystem/testdata")},
-      &delegate);
+  FileScanner fs({"src/traced/probes/filesystem/testdata"}, &delegate);
   fs.Scan();
 
   EXPECT_EQ(seen, 1u);
@@ -116,15 +118,13 @@
   base::TestTaskRunner task_runner;
   TestDelegate delegate(
       [&seen](BlockDeviceID, Inode, const std::string&,
-              InodeFileMap_Entry_Type) {
+              protos::pbzero::InodeFileMap_Entry_Type) {
         ++seen;
         return false;
       },
       task_runner.CreateCheckpoint("done"));
 
-  FileScanner fs(
-      {base::GetTestDataPath("src/traced/probes/filesystem/testdata")},
-      &delegate, 1, 1);
+  FileScanner fs({"src/traced/probes/filesystem/testdata"}, &delegate, 1, 1);
   fs.Scan(&task_runner);
 
   task_runner.RunUntilCheckpoint("done");
@@ -136,30 +136,25 @@
   std::vector<FileEntry> file_entries;
   TestDelegate delegate(
       [&file_entries](BlockDeviceID block_device_id, Inode inode,
-                      const std::string& path, InodeFileMap_Entry_Type type) {
+                      const std::string& path,
+                      protos::pbzero::InodeFileMap_Entry_Type type) {
         file_entries.emplace_back(block_device_id, inode, path, type);
         return true;
       },
       [] {});
 
-  FileScanner fs(
-      {base::GetTestDataPath("src/traced/probes/filesystem/testdata")},
-      &delegate);
+  FileScanner fs({"src/traced/probes/filesystem/testdata"}, &delegate);
   fs.Scan();
 
   EXPECT_THAT(
       file_entries,
       UnorderedElementsAre(
-          Eq(StatFileEntry(
-              base::GetTestDataPath(
-                  "src/traced/probes/filesystem/testdata/dir1/file1"),
-              protos::pbzero::InodeFileMap_Entry_Type_FILE)),
-          Eq(StatFileEntry(base::GetTestDataPath(
-                               "src/traced/probes/filesystem/testdata/file2"),
+          Eq(StatFileEntry("src/traced/probes/filesystem/testdata/dir1/file1",
+                           protos::pbzero::InodeFileMap_Entry_Type_FILE)),
+          Eq(StatFileEntry("src/traced/probes/filesystem/testdata/file2",
                            protos::pbzero::InodeFileMap_Entry_Type_FILE)),
           Eq(StatFileEntry(
-              base::GetTestDataPath(
-                  "src/traced/probes/filesystem/testdata/dir1"),
+              "src/traced/probes/filesystem/testdata/dir1",
               protos::pbzero::InodeFileMap_Entry_Type_DIRECTORY))));
 }
 
@@ -168,15 +163,14 @@
   std::vector<FileEntry> file_entries;
   TestDelegate delegate(
       [&file_entries](BlockDeviceID block_device_id, Inode inode,
-                      const std::string& path, InodeFileMap_Entry_Type type) {
+                      const std::string& path,
+                      protos::pbzero::InodeFileMap_Entry_Type type) {
         file_entries.emplace_back(block_device_id, inode, path, type);
         return true;
       },
       task_runner.CreateCheckpoint("done"));
 
-  FileScanner fs(
-      {base::GetTestDataPath("src/traced/probes/filesystem/testdata")},
-      &delegate, 1, 1);
+  FileScanner fs({"src/traced/probes/filesystem/testdata"}, &delegate, 1, 1);
   fs.Scan(&task_runner);
 
   task_runner.RunUntilCheckpoint("done");
@@ -184,16 +178,12 @@
   EXPECT_THAT(
       file_entries,
       UnorderedElementsAre(
-          Eq(StatFileEntry(
-              base::GetTestDataPath(
-                  "src/traced/probes/filesystem/testdata/dir1/file1"),
-              protos::pbzero::InodeFileMap_Entry_Type_FILE)),
-          Eq(StatFileEntry(base::GetTestDataPath(
-                               "src/traced/probes/filesystem/testdata/file2"),
+          Eq(StatFileEntry("src/traced/probes/filesystem/testdata/dir1/file1",
+                           protos::pbzero::InodeFileMap_Entry_Type_FILE)),
+          Eq(StatFileEntry("src/traced/probes/filesystem/testdata/file2",
                            protos::pbzero::InodeFileMap_Entry_Type_FILE)),
           Eq(StatFileEntry(
-              base::GetTestDataPath(
-                  "src/traced/probes/filesystem/testdata/dir1"),
+              "src/traced/probes/filesystem/testdata/dir1",
               protos::pbzero::InodeFileMap_Entry_Type_DIRECTORY))));
 }
 
diff --git a/src/traced/probes/filesystem/fs_mount.cc b/src/traced/probes/filesystem/fs_mount.cc
index 7564490..da2030e 100644
--- a/src/traced/probes/filesystem/fs_mount.cc
+++ b/src/traced/probes/filesystem/fs_mount.cc
@@ -21,9 +21,9 @@
 #include <fstream>
 #include <sstream>
 
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/string_splitter.h"
+#include "perfetto/base/string_splitter.h"
 
 namespace perfetto {
 
diff --git a/src/traced/probes/filesystem/fs_mount.h b/src/traced/probes/filesystem/fs_mount.h
index b66a467..2086a80 100644
--- a/src/traced/probes/filesystem/fs_mount.h
+++ b/src/traced/probes/filesystem/fs_mount.h
@@ -21,7 +21,7 @@
 #include <map>
 #include <string>
 #include <vector>
-#include "perfetto/ext/traced/data_source_types.h"
+#include "perfetto/traced/data_source_types.h"
 
 namespace perfetto {
 
diff --git a/src/traced/probes/filesystem/fs_mount_unittest.cc b/src/traced/probes/filesystem/fs_mount_unittest.cc
index 6a516db..6c6b489 100644
--- a/src/traced/probes/filesystem/fs_mount_unittest.cc
+++ b/src/traced/probes/filesystem/fs_mount_unittest.cc
@@ -21,12 +21,13 @@
 #include <stdlib.h>
 #include <sys/stat.h>
 
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 #include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/ext/base/utils.h"
-#include "test/gtest_and_gmock.h"
+#include "perfetto/base/file_utils.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/temp_file.h"
+#include "perfetto/base/utils.h"
 
 namespace perfetto {
 namespace {
@@ -53,7 +54,7 @@
 
   base::TempFile tmp_file = base::TempFile::Create();
   ASSERT_EQ(base::WriteAll(tmp_file.fd(), kMounts, sizeof(kMounts)),
-            static_cast<ssize_t>(sizeof(kMounts)));
+            sizeof(kMounts));
   std::multimap<BlockDeviceID, std::string> mounts =
       ParseMounts(tmp_file.path().c_str());
   struct stat dev_stat = {}, root_stat = {};
diff --git a/src/traced/probes/filesystem/inode_file_data_source.cc b/src/traced/probes/filesystem/inode_file_data_source.cc
index aae5bed..02eed04 100644
--- a/src/traced/probes/filesystem/inode_file_data_source.cc
+++ b/src/traced/probes/filesystem/inode_file_data_source.cc
@@ -24,13 +24,11 @@
 #include <unordered_map>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/tracing/core/trace_packet.h"
+#include "perfetto/tracing/core/trace_writer.h"
 
-#include "protos/perfetto/config/inode_file/inode_file_config.pbzero.h"
-#include "protos/perfetto/trace/filesystem/inode_file_map.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 #include "src/traced/probes/filesystem/file_scanner.h"
 
 namespace perfetto {
@@ -55,6 +53,16 @@
   return result;
 }
 
+std::map<std::string, std::vector<std::string>> BuildMountpointMapping(
+    const DataSourceConfig& source_config) {
+  std::map<std::string, std::vector<std::string>> m;
+  for (const auto& map_entry :
+       source_config.inode_file_config().mount_point_mapping())
+    m.emplace(map_entry.mountpoint(), map_entry.scan_roots());
+
+  return m;
+}
+
 class StaticMapDelegate : public FileScanner::Delegate {
  public:
   StaticMapDelegate(
@@ -66,7 +74,7 @@
   bool OnInodeFound(BlockDeviceID block_device_id,
                     Inode inode_number,
                     const std::string& path,
-                    InodeFileMap_Entry_Type type) {
+                    protos::pbzero::InodeFileMap_Entry_Type type) {
     std::unordered_map<Inode, InodeMapValue>& inode_map =
         (*map_)[block_device_id];
     inode_map[inode_number].SetType(type);
@@ -96,14 +104,13 @@
                                          const InodeMapValue& inode_map_value) {
   auto* entry = destination->add_entries();
   entry->set_inode_number(inode_number);
-  entry->set_type(static_cast<protos::pbzero::InodeFileMap_Entry_Type>(
-      inode_map_value.type()));
+  entry->set_type(inode_map_value.type());
   for (const auto& path : inode_map_value.paths())
     entry->add_paths(path.c_str());
 }
 
 InodeFileDataSource::InodeFileDataSource(
-    DataSourceConfig ds_config,
+    DataSourceConfig source_config,
     base::TaskRunner* task_runner,
     TracingSessionID session_id,
     std::map<BlockDeviceID, std::unordered_map<Inode, InodeMapValue>>*
@@ -111,28 +118,16 @@
     LRUInodeCache* cache,
     std::unique_ptr<TraceWriter> writer)
     : ProbesDataSource(session_id, kTypeId),
+      source_config_(std::move(source_config)),
+      scan_mount_points_(
+          source_config_.inode_file_config().scan_mount_points().cbegin(),
+          source_config_.inode_file_config().scan_mount_points().cend()),
+      mount_point_mapping_(BuildMountpointMapping(source_config_)),
       task_runner_(task_runner),
       static_file_map_(static_file_map),
       cache_(cache),
       writer_(std::move(writer)),
-      weak_factory_(this) {
-  using protos::pbzero::InodeFileConfig;
-  InodeFileConfig::Decoder cfg(ds_config.inode_file_config_raw());
-  for (auto mp = cfg.scan_mount_points(); mp; ++mp)
-    scan_mount_points_.insert((*mp).ToStdString());
-  for (auto mpm = cfg.mount_point_mapping(); mpm; ++mpm) {
-    InodeFileConfig::MountPointMappingEntry::Decoder entry(*mpm);
-    std::vector<std::string> scan_roots;
-    for (auto scan_root = entry.scan_roots(); scan_root; ++scan_root)
-      scan_roots.push_back((*scan_root).ToStdString());
-    std::string mountpoint = entry.mountpoint().ToStdString();
-    mount_point_mapping_.emplace(mountpoint, std::move(scan_roots));
-  }
-  scan_interval_ms_ = OrDefault(cfg.scan_interval_ms(), kScanIntervalMs);
-  scan_delay_ms_ = OrDefault(cfg.scan_delay_ms(), kScanDelayMs);
-  scan_batch_size_ = OrDefault(cfg.scan_batch_size(), kScanBatchSize);
-  do_not_scan_ = cfg.do_not_scan();
-}
+      weak_factory_(this) {}
 
 InodeFileDataSource::~InodeFileDataSource() = default;
 
@@ -219,7 +214,7 @@
     AddInodesFromStaticMap(block_device_id, &inode_numbers);
     AddInodesFromLRUCache(block_device_id, &inode_numbers);
 
-    if (do_not_scan_)
+    if (source_config_.inode_file_config().do_not_scan())
       inode_numbers.clear();
 
     // If we defined mount points we want to scan in the config,
@@ -256,7 +251,7 @@
               }
               weak_this.get()->FindMissingInodes();
             },
-            scan_delay_ms_);
+            GetScanDelayMs());
       }
     }
   }
@@ -294,10 +289,11 @@
   it->second.erase(inode_number);
 }
 
-bool InodeFileDataSource::OnInodeFound(BlockDeviceID block_device_id,
-                                       Inode inode_number,
-                                       const std::string& path,
-                                       InodeFileMap_Entry_Type type) {
+bool InodeFileDataSource::OnInodeFound(
+    BlockDeviceID block_device_id,
+    Inode inode_number,
+    const std::string& path,
+    protos::pbzero::InodeFileMap_Entry_Type type) {
   auto it = missing_inodes_.find(block_device_id);
   if (it == missing_inodes_.end())
     return true;
@@ -360,7 +356,7 @@
           }
           weak_this->FindMissingInodes();
         },
-        scan_delay_ms_);
+        GetScanDelayMs());
   }
 }
 
@@ -392,11 +388,26 @@
   auto weak_this = GetWeakPtr();
   PERFETTO_DLOG("Starting scan of %s", DbgFmt(roots).c_str());
   file_scanner_ = std::unique_ptr<FileScanner>(new FileScanner(
-      std::move(roots), this, scan_interval_ms_, scan_batch_size_));
+      std::move(roots), this, GetScanIntervalMs(), GetScanBatchSize()));
 
   file_scanner_->Scan(task_runner_);
 }
 
+uint32_t InodeFileDataSource::GetScanIntervalMs() const {
+  return OrDefault(source_config_.inode_file_config().scan_interval_ms(),
+                   kScanIntervalMs);
+}
+
+uint32_t InodeFileDataSource::GetScanDelayMs() const {
+  return OrDefault(source_config_.inode_file_config().scan_delay_ms(),
+                   kScanDelayMs);
+}
+
+uint32_t InodeFileDataSource::GetScanBatchSize() const {
+  return OrDefault(source_config_.inode_file_config().scan_batch_size(),
+                   kScanBatchSize);
+}
+
 base::WeakPtr<InodeFileDataSource> InodeFileDataSource::GetWeakPtr() const {
   return weak_factory_.GetWeakPtr();
 }
diff --git a/src/traced/probes/filesystem/inode_file_data_source.h b/src/traced/probes/filesystem/inode_file_data_source.h
index 529fe2c..2afdeed 100644
--- a/src/traced/probes/filesystem/inode_file_data_source.h
+++ b/src/traced/probes/filesystem/inode_file_data_source.h
@@ -26,17 +26,17 @@
 #include <unordered_map>
 
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/traced/data_source_types.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
+#include "perfetto/base/weak_ptr.h"
+#include "perfetto/traced/data_source_types.h"
+#include "perfetto/tracing/core/basic_types.h"
 #include "perfetto/tracing/core/data_source_config.h"
+#include "perfetto/tracing/core/trace_writer.h"
 #include "src/traced/probes/filesystem/file_scanner.h"
 #include "src/traced/probes/filesystem/fs_mount.h"
 #include "src/traced/probes/filesystem/lru_inode_cache.h"
 #include "src/traced/probes/probes_data_source.h"
 
-#include "protos/perfetto/trace/filesystem/inode_file_map.pbzero.h"
+#include "perfetto/trace/filesystem/inode_file_map.pbzero.h"
 
 namespace perfetto {
 
@@ -99,7 +99,7 @@
   bool OnInodeFound(BlockDeviceID block_device_id,
                     Inode inode_number,
                     const std::string& path,
-                    InodeFileMap_Entry_Type type) override;
+                    protos::pbzero::InodeFileMap_Entry_Type type) override;
   void OnInodeScanDone() override;
 
   void AddRootsForBlockDevice(BlockDeviceID block_device_id,
@@ -107,6 +107,11 @@
   void RemoveFromNextMissingInodes(BlockDeviceID block_device_id,
                                    Inode inode_number);
 
+  uint32_t GetScanIntervalMs() const;
+  uint32_t GetScanDelayMs() const;
+  uint32_t GetScanBatchSize() const;
+
+  const DataSourceConfig source_config_;
   std::set<std::string> scan_mount_points_;
   std::map<std::string, std::vector<std::string>> mount_point_mapping_;
 
@@ -123,10 +128,6 @@
   InodeFileMap* current_file_map_;
   bool has_current_trace_packet_ = false;
   bool scan_running_ = false;
-  bool do_not_scan_ = false;
-  uint32_t scan_interval_ms_ = 0;
-  uint32_t scan_delay_ms_ = 0;
-  uint32_t scan_batch_size_ = 0;
   std::unique_ptr<FileScanner> file_scanner_;
   base::WeakPtrFactory<InodeFileDataSource> weak_factory_;  // Keep last.
 };
diff --git a/src/traced/probes/filesystem/inode_file_data_source_unittest.cc b/src/traced/probes/filesystem/inode_file_data_source_unittest.cc
index edd208b..deb943d 100644
--- a/src/traced/probes/filesystem/inode_file_data_source_unittest.cc
+++ b/src/traced/probes/filesystem/inode_file_data_source_unittest.cc
@@ -16,16 +16,13 @@
 
 #include "src/traced/probes/filesystem/inode_file_data_source.h"
 
-#include "perfetto/protozero/scattered_heap_buffer.h"
+#include "perfetto/trace/filesystem/inode_file_map.pbzero.h"
 #include "src/base/test/test_task_runner.h"
-#include "src/base/test/utils.h"
 #include "src/traced/probes/filesystem/lru_inode_cache.h"
 #include "src/tracing/core/null_trace_writer.h"
 
-#include "test/gtest_and_gmock.h"
-
-#include "protos/perfetto/config/inode_file/inode_file_config.pbzero.h"
-#include "protos/perfetto/trace/filesystem/inode_file_map.pbzero.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace {
@@ -53,13 +50,8 @@
                             cache,
                             std::move(writer)) {
     struct stat buf;
-    PERFETTO_CHECK(
-        lstat(base::GetTestDataPath("src/traced/probes/filesystem/testdata")
-                  .c_str(),
-              &buf) != -1);
-    mount_points_.emplace(
-        buf.st_dev,
-        base::GetTestDataPath("src/traced/probes/filesystem/testdata"));
+    PERFETTO_CHECK(lstat("src/traced/probes/filesystem/testdata", &buf) != -1);
+    mount_points_.emplace(buf.st_dev, "src/traced/probes/filesystem/testdata");
   }
 
   MOCK_METHOD3(FillInodeEntry,
@@ -86,30 +78,25 @@
 };
 
 TEST_F(InodeFileDataSourceTest, TestFileSystemScan) {
-  DataSourceConfig ds_config;
-  protozero::HeapBuffered<protos::pbzero::InodeFileConfig> inode_cfg;
-  inode_cfg->set_scan_interval_ms(1);
-  inode_cfg->set_scan_delay_ms(1);
-  ds_config.set_inode_file_config_raw(inode_cfg.SerializeAsString());
-  auto data_source = GetInodeFileDataSource(ds_config);
+  DataSourceConfig config;
+  config.mutable_inode_file_config()->set_scan_interval_ms(1);
+  config.mutable_inode_file_config()->set_scan_delay_ms(1);
+  auto data_source = GetInodeFileDataSource(config);
 
   struct stat buf;
-  PERFETTO_CHECK(
-      lstat(base::GetTestDataPath("src/traced/probes/filesystem/testdata/file2")
-                .c_str(),
-            &buf) != -1);
+  PERFETTO_CHECK(lstat("src/traced/probes/filesystem/testdata/file2", &buf) !=
+                 -1);
 
   auto done = task_runner_.CreateCheckpoint("done");
-  InodeMapValue value(
-      protos::pbzero::InodeFileMap_Entry_Type_FILE,
-      {base::GetTestDataPath("src/traced/probes/filesystem/testdata/file2")});
+  InodeMapValue value(protos::pbzero::InodeFileMap_Entry_Type_FILE,
+                      {"src/traced/probes/filesystem/testdata/file2"});
   EXPECT_CALL(*data_source, FillInodeEntry(_, buf.st_ino, Eq(value)))
       .WillOnce(InvokeWithoutArgs(done));
 
   data_source->OnInodes({{buf.st_ino, buf.st_dev}});
   task_runner_.RunUntilCheckpoint("done");
 
-  // Expect that the found inode is added in the LRU cache.
+  // Expect that the found inode is added the the LRU cache.
   EXPECT_THAT(cache_.Get(std::make_pair(buf.st_dev, buf.st_ino)),
               Pointee(Eq(value)));
 }
@@ -117,19 +104,15 @@
 TEST_F(InodeFileDataSourceTest, TestStaticMap) {
   DataSourceConfig config;
   auto data_source = GetInodeFileDataSource(config);
-  CreateStaticDeviceToInodeMap(
-      base::GetTestDataPath("src/traced/probes/filesystem/testdata"),
-      &static_file_map_);
+  CreateStaticDeviceToInodeMap("src/traced/probes/filesystem/testdata",
+                               &static_file_map_);
 
   struct stat buf;
-  PERFETTO_CHECK(
-      lstat(base::GetTestDataPath("src/traced/probes/filesystem/testdata/file2")
-                .c_str(),
-            &buf) != -1);
+  PERFETTO_CHECK(lstat("src/traced/probes/filesystem/testdata/file2", &buf) !=
+                 -1);
 
-  InodeMapValue value(
-      protos::pbzero::InodeFileMap_Entry_Type_FILE,
-      {base::GetTestDataPath("src/traced/probes/filesystem/testdata/file2")});
+  InodeMapValue value(protos::pbzero::InodeFileMap_Entry_Type_FILE,
+                      {"src/traced/probes/filesystem/testdata/file2"});
   EXPECT_CALL(*data_source, FillInodeEntry(_, buf.st_ino, Eq(value)));
 
   data_source->OnInodes({{buf.st_ino, buf.st_dev}});
@@ -140,19 +123,15 @@
 TEST_F(InodeFileDataSourceTest, TestCache) {
   DataSourceConfig config;
   auto data_source = GetInodeFileDataSource(config);
-  CreateStaticDeviceToInodeMap(
-      base::GetTestDataPath("src/traced/probes/filesystem/testdata"),
-      &static_file_map_);
+  CreateStaticDeviceToInodeMap("src/traced/probes/filesystem/testdata",
+                               &static_file_map_);
 
   struct stat buf;
-  PERFETTO_CHECK(
-      lstat(base::GetTestDataPath("src/traced/probes/filesystem/testdata/file2")
-                .c_str(),
-            &buf) != -1);
+  PERFETTO_CHECK(lstat("src/traced/probes/filesystem/testdata/file2", &buf) !=
+                 -1);
 
-  InodeMapValue value(
-      protos::pbzero::InodeFileMap_Entry_Type_FILE,
-      {base::GetTestDataPath("src/traced/probes/filesystem/testdata/file2")});
+  InodeMapValue value(protos::pbzero::InodeFileMap_Entry_Type_FILE,
+                      {"src/traced/probes/filesystem/testdata/file2"});
   cache_.Insert(std::make_pair(buf.st_dev, buf.st_ino), value);
 
   EXPECT_CALL(*data_source, FillInodeEntry(_, buf.st_ino, Eq(value)));
diff --git a/src/traced/probes/filesystem/lru_inode_cache.h b/src/traced/probes/filesystem/lru_inode_cache.h
index 629d387..0b36109 100644
--- a/src/traced/probes/filesystem/lru_inode_cache.h
+++ b/src/traced/probes/filesystem/lru_inode_cache.h
@@ -22,7 +22,7 @@
 #include <string>
 #include <tuple>
 
-#include "perfetto/ext/traced/data_source_types.h"
+#include "perfetto/traced/data_source_types.h"
 
 namespace perfetto {
 
diff --git a/src/traced/probes/filesystem/lru_inode_cache_unittest.cc b/src/traced/probes/filesystem/lru_inode_cache_unittest.cc
index 86aed74..aafdc97 100644
--- a/src/traced/probes/filesystem/lru_inode_cache_unittest.cc
+++ b/src/traced/probes/filesystem/lru_inode_cache_unittest.cc
@@ -16,12 +16,12 @@
 
 #include "src/traced/probes/filesystem/lru_inode_cache.h"
 
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
 #include <string>
 #include <tuple>
 
-#include "protos/perfetto/trace/filesystem/inode_file_map.pbzero.h"
-#include "test/gtest_and_gmock.h"
-
 namespace perfetto {
 
 namespace {
diff --git a/src/traced/probes/filesystem/prefix_finder.cc b/src/traced/probes/filesystem/prefix_finder.cc
index b22532e..360880a 100644
--- a/src/traced/probes/filesystem/prefix_finder.cc
+++ b/src/traced/probes/filesystem/prefix_finder.cc
@@ -16,7 +16,7 @@
 
 #include "src/traced/probes/filesystem/prefix_finder.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_splitter.h"
+#include "perfetto/base/string_splitter.h"
 
 namespace perfetto {
 
diff --git a/src/traced/probes/filesystem/prefix_finder.h b/src/traced/probes/filesystem/prefix_finder.h
index 3d84ed1..f788dea 100644
--- a/src/traced/probes/filesystem/prefix_finder.h
+++ b/src/traced/probes/filesystem/prefix_finder.h
@@ -25,7 +25,7 @@
 #include <vector>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/lookup_set.h"
+#include "perfetto/base/lookup_set.h"
 
 namespace perfetto {
 
@@ -57,7 +57,7 @@
     Node& operator=(const Node&) = delete;
 
     // Return string representation of prefix, e.g. /foo/bar.
-    // Does not include a trailing /.
+    // Does not enclude a trailing /.
     std::string ToString() const;
 
    private:
diff --git a/src/traced/probes/filesystem/prefix_finder_unittest.cc b/src/traced/probes/filesystem/prefix_finder_unittest.cc
index a40ab6f..b9972c5 100644
--- a/src/traced/probes/filesystem/prefix_finder_unittest.cc
+++ b/src/traced/probes/filesystem/prefix_finder_unittest.cc
@@ -21,11 +21,12 @@
 #include <stdlib.h>
 #include <sys/stat.h>
 
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 #include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/ext/base/utils.h"
-#include "test/gtest_and_gmock.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/temp_file.h"
+#include "perfetto/base/utils.h"
 
 namespace perfetto {
 namespace {
diff --git a/src/traced/probes/filesystem/range_tree.h b/src/traced/probes/filesystem/range_tree.h
index 9821ea7..b28695a 100644
--- a/src/traced/probes/filesystem/range_tree.h
+++ b/src/traced/probes/filesystem/range_tree.h
@@ -20,7 +20,7 @@
 
 #include <stdio.h>
 
-#include "perfetto/ext/base/small_set.h"
+#include "perfetto/base/small_set.h"
 #include "src/traced/probes/filesystem/inode_file_data_source.h"
 #include "src/traced/probes/filesystem/prefix_finder.h"
 
diff --git a/src/traced/probes/filesystem/range_tree_unittest.cc b/src/traced/probes/filesystem/range_tree_unittest.cc
index ce26a36..288647a 100644
--- a/src/traced/probes/filesystem/range_tree_unittest.cc
+++ b/src/traced/probes/filesystem/range_tree_unittest.cc
@@ -22,11 +22,12 @@
 #include <stdlib.h>
 #include <sys/stat.h>
 
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 #include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/ext/base/utils.h"
-#include "test/gtest_and_gmock.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/temp_file.h"
+#include "perfetto/base/utils.h"
 
 namespace perfetto {
 namespace {
diff --git a/src/traced/probes/ftrace/BUILD.gn b/src/traced/probes/ftrace/BUILD.gn
index ddac4e8..5ddf80c 100644
--- a/src/traced/probes/ftrace/BUILD.gn
+++ b/src/traced/probes/ftrace/BUILD.gn
@@ -12,13 +12,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../../gn/fuzzer.gni")
 import("../../../../gn/perfetto.gni")
 import("../../../../gn/proto_library.gni")
-import("../../../../gn/test.gni")
+import("../../../../gn/fuzzer.gni")
+import("../../../../gn/protozero_library.gni")
 
 # For use_libfuzzer.
-if (perfetto_root_path == "//") {
+if (perfetto_build_standalone || perfetto_build_with_android) {
   import("//gn/standalone/sanitizers/vars.gni")
 } else {
   import("//build/config/sanitizers/sanitizers.gni")
@@ -29,7 +29,6 @@
   deps = [
     ":ftrace",
     "../../../../gn:default_deps",
-    "../../../base:test_support",
     "../../../protozero",
   ]
   public_deps = [
@@ -42,7 +41,7 @@
   ]
 }
 
-perfetto_unittest_source_set("unittests") {
+source_set("unittests") {
   testonly = true
   deps = [
     ":format_parser",
@@ -51,7 +50,7 @@
     ":test_messages_zero",
     ":test_support",
     "../../../../gn:default_deps",
-    "../../../../gn:gtest_and_gmock",
+    "../../../../gn:gtest_deps",
     "../../../../protos/perfetto/trace/ftrace:lite",
     "../../../base:test_support",
     "../../../tracing:test_support",
@@ -65,19 +64,25 @@
     "ftrace_config_unittest.cc",
     "ftrace_controller_unittest.cc",
     "ftrace_procfs_unittest.cc",
+    "page_pool_unittest.cc",
     "proto_translation_table_unittest.cc",
   ]
 }
 
-perfetto_proto_library("test_messages_@TYPE@") {
-  proto_generators = [
-    "lite",
-    "zero",
-  ]
-  sources = [
-    "test/test_messages.proto",
-  ]
-  proto_path = perfetto_root_path
+ftrace_reader_test_proto_sources = [ "test/test_messages.proto" ]
+
+protozero_library("test_messages_zero") {
+  sources = ftrace_reader_test_proto_sources
+  proto_in_dir = perfetto_root_path
+  proto_out_dir = perfetto_root_path
+  generator_plugin_options = "wrapper_namespace=pbzero"
+}
+
+proto_library("test_messages_lite") {
+  generate_python = false
+  sources = ftrace_reader_test_proto_sources
+  proto_in_dir = perfetto_root_path
+  proto_out_dir = perfetto_root_path
 }
 
 # These tests require access to a real ftrace implementation and must
@@ -88,7 +93,7 @@
     ":ftrace",
     ":test_support",
     "../../../../gn:default_deps",
-    "../../../../gn:gtest_and_gmock",
+    "../../../../gn:gtest_deps",
     "../../../../protos/perfetto/trace/ftrace:lite",
     "../../../base",
     "../../../tracing",
@@ -107,9 +112,8 @@
     ":format_parser",
     "..:data_source",
     "../../../../gn:default_deps",
-    "../../../../include/perfetto/ext/traced",
-    "../../../../protos/perfetto/config/ftrace:cpp",
-    "../../../../protos/perfetto/config/ftrace:lite",
+    "../../../../include/perfetto/traced",
+    "../../../android_internal:headers",
     "../../../android_internal:lazy_library_loader",
     "../../../base",
     "../../../protozero",
@@ -119,8 +123,6 @@
     "atrace_hal_wrapper.h",
     "atrace_wrapper.cc",
     "atrace_wrapper.h",
-    "compact_sched.cc",
-    "compact_sched.h",
     "cpu_reader.cc",
     "cpu_reader.h",
     "cpu_stats_parser.cc",
@@ -129,10 +131,10 @@
     "event_info.h",
     "event_info_constants.cc",
     "event_info_constants.h",
+    "ftrace_config.cc",
+    "ftrace_config.h",
     "ftrace_config_muxer.cc",
     "ftrace_config_muxer.h",
-    "ftrace_config_utils.cc",
-    "ftrace_config_utils.h",
     "ftrace_controller.cc",
     "ftrace_controller.h",
     "ftrace_data_source.cc",
@@ -143,6 +145,8 @@
     "ftrace_procfs.h",
     "ftrace_stats.cc",
     "ftrace_stats.h",
+    "page_pool.cc",
+    "page_pool.h",
     "proto_translation_table.cc",
     "proto_translation_table.h",
   ]
@@ -159,14 +163,14 @@
   ]
 }
 
-if (enable_perfetto_benchmarks) {
+if (perfetto_build_standalone) {
   source_set("benchmarks") {
     testonly = true
     deps = [
       ":ftrace",
       ":test_support",
-      "../../../../gn:benchmark",
       "../../../../gn:default_deps",
+      "//buildtools:benchmark",
     ]
     sources = [
       "cpu_reader_benchmark.cc",
diff --git a/src/traced/probes/ftrace/atrace_hal_wrapper.h b/src/traced/probes/ftrace/atrace_hal_wrapper.h
index db215ae..883388b 100644
--- a/src/traced/probes/ftrace/atrace_hal_wrapper.h
+++ b/src/traced/probes/ftrace/atrace_hal_wrapper.h
@@ -21,7 +21,7 @@
 #include <string>
 #include <vector>
 
-#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/base/scoped_file.h"
 
 namespace perfetto {
 
diff --git a/src/traced/probes/ftrace/atrace_wrapper.cc b/src/traced/probes/ftrace/atrace_wrapper.cc
index 76e7b7a..2acdbe4 100644
--- a/src/traced/probes/ftrace/atrace_wrapper.cc
+++ b/src/traced/probes/ftrace/atrace_wrapper.cc
@@ -26,9 +26,8 @@
 #include <unistd.h>
 
 #include "perfetto/base/logging.h"
+#include "perfetto/base/pipe.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/pipe.h"
-#include "perfetto/ext/base/utils.h"
 
 namespace perfetto {
 
@@ -131,7 +130,7 @@
     // Wait for the value of the timeout.
     auto ret = poll(fds, kFdCount, timeout_ms);
     if (ret == 0 || (ret < 0 && errno == EINTR)) {
-      // Either timeout occurred in poll (in which case continue so that this
+      // Either timeout occured in poll (in which case continue so that this
       // will be picked up by our own timeout logic) or we received an EINTR and
       // we should try again.
       continue;
diff --git a/src/traced/probes/ftrace/compact_sched.cc b/src/traced/probes/ftrace/compact_sched.cc
deleted file mode 100644
index 7ca8526..0000000
--- a/src/traced/probes/ftrace/compact_sched.cc
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/traced/probes/ftrace/compact_sched.h"
-
-#include <stdint.h>
-
-#include "perfetto/ext/base/optional.h"
-#include "protos/perfetto/config/ftrace/ftrace_config.gen.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/sched.pbzero.h"
-#include "src/traced/probes/ftrace/event_info_constants.h"
-
-namespace perfetto {
-
-namespace {
-
-// Pre-parse the format of sched_switch, checking if our simplifying
-// assumptions about possible widths/signedness hold, and record the subset
-// of the format that will be used during parsing.
-base::Optional<CompactSchedSwitchFormat> ValidateSchedSwitchFormat(
-    const Event& event) {
-  using protos::pbzero::SchedSwitchFtraceEvent;
-
-  CompactSchedSwitchFormat switch_format;
-  switch_format.event_id = event.ftrace_event_id;
-  switch_format.size = event.size;
-
-  bool prev_state_valid = false;
-  bool next_pid_valid = false;
-  bool next_prio_valid = false;
-  bool next_comm_valid = false;
-  for (const auto& field : event.fields) {
-    switch (field.proto_field_id) {
-      case SchedSwitchFtraceEvent::kPrevStateFieldNumber:
-        switch_format.prev_state_offset = field.ftrace_offset;
-        switch_format.prev_state_type = field.ftrace_type;
-
-        // kernel type: long
-        prev_state_valid = (field.ftrace_type == kFtraceInt32 ||
-                            field.ftrace_type == kFtraceInt64);
-        break;
-
-      case SchedSwitchFtraceEvent::kNextPidFieldNumber:
-        switch_format.next_pid_offset = field.ftrace_offset;
-        switch_format.next_pid_type = field.ftrace_type;
-
-        // kernel type: pid_t
-        next_pid_valid = (field.ftrace_type == kFtracePid32);
-        break;
-
-      case SchedSwitchFtraceEvent::kNextPrioFieldNumber:
-        switch_format.next_prio_offset = field.ftrace_offset;
-        switch_format.next_prio_type = field.ftrace_type;
-
-        // kernel type: int
-        next_prio_valid = (field.ftrace_type == kFtraceInt32);
-        break;
-
-      case SchedSwitchFtraceEvent::kNextCommFieldNumber:
-        switch_format.next_comm_offset = field.ftrace_offset;
-
-        next_comm_valid =
-            (field.ftrace_type == kFtraceFixedCString &&
-             field.ftrace_size == CommInterner::kExpectedCommLength);
-        break;
-      default:
-        break;
-    }
-  }
-
-  if (!prev_state_valid || !next_pid_valid || !next_prio_valid ||
-      !next_comm_valid) {
-    return base::nullopt;
-  }
-  return base::make_optional(switch_format);
-}
-
-// Pre-parse the format of sched_waking, checking if our simplifying
-// assumptions about possible widths/signedness hold, and record the subset
-// of the format that will be used during parsing.
-base::Optional<CompactSchedWakingFormat> ValidateSchedWakingFormat(
-    const Event& event) {
-  using protos::pbzero::SchedWakingFtraceEvent;
-
-  CompactSchedWakingFormat waking_format;
-  waking_format.event_id = event.ftrace_event_id;
-  waking_format.size = event.size;
-
-  bool pid_valid = false;
-  bool target_cpu_valid = false;
-  bool prio_valid = false;
-  bool comm_valid = false;
-  for (const auto& field : event.fields) {
-    switch (field.proto_field_id) {
-      case SchedWakingFtraceEvent::kPidFieldNumber:
-        waking_format.pid_offset = field.ftrace_offset;
-        waking_format.pid_type = field.ftrace_type;
-
-        // kernel type: pid_t
-        pid_valid = (field.ftrace_type == kFtracePid32);
-        break;
-
-      case SchedWakingFtraceEvent::kTargetCpuFieldNumber:
-        waking_format.target_cpu_offset = field.ftrace_offset;
-        waking_format.target_cpu_type = field.ftrace_type;
-
-        // kernel type: int
-        target_cpu_valid = (field.ftrace_type == kFtraceInt32);
-        break;
-
-      case SchedWakingFtraceEvent::kPrioFieldNumber:
-        waking_format.prio_offset = field.ftrace_offset;
-        waking_format.prio_type = field.ftrace_type;
-
-        // kernel type: int
-        prio_valid = (field.ftrace_type == kFtraceInt32);
-        break;
-
-      case SchedWakingFtraceEvent::kCommFieldNumber:
-        waking_format.comm_offset = field.ftrace_offset;
-
-        comm_valid = (field.ftrace_type == kFtraceFixedCString &&
-                      field.ftrace_size == CommInterner::kExpectedCommLength);
-        break;
-      default:
-        break;
-    }
-  }
-
-  if (!pid_valid || !target_cpu_valid || !prio_valid || !comm_valid) {
-    return base::nullopt;
-  }
-  return base::make_optional(waking_format);
-}
-
-}  // namespace
-
-// TODO(rsavitski): could avoid looping over all events if the caller did the
-// work to remember the relevant events (translation table construction already
-// loops over them).
-CompactSchedEventFormat ValidateFormatForCompactSched(
-    const std::vector<Event>& events) {
-  using protos::pbzero::FtraceEvent;
-
-  base::Optional<CompactSchedSwitchFormat> switch_format;
-  base::Optional<CompactSchedWakingFormat> waking_format;
-  for (const Event& event : events) {
-    if (event.proto_field_id == FtraceEvent::kSchedSwitchFieldNumber) {
-      switch_format = ValidateSchedSwitchFormat(event);
-    }
-    if (event.proto_field_id == FtraceEvent::kSchedWakingFieldNumber) {
-      waking_format = ValidateSchedWakingFormat(event);
-    }
-  }
-
-  if (switch_format.has_value() && waking_format.has_value()) {
-    return CompactSchedEventFormat{/*format_valid=*/true, switch_format.value(),
-                                   waking_format.value()};
-  } else {
-    PERFETTO_ELOG("Unexpected sched_switch or sched_waking format.");
-    return CompactSchedEventFormat{/*format_valid=*/false,
-                                   CompactSchedSwitchFormat{},
-                                   CompactSchedWakingFormat{}};
-  }
-}
-
-CompactSchedEventFormat InvalidCompactSchedEventFormatForTesting() {
-  return CompactSchedEventFormat{/*format_valid=*/false,
-                                 CompactSchedSwitchFormat{},
-                                 CompactSchedWakingFormat{}};
-}
-
-// TODO(rsavitski): find the correct place in the trace for, and method of,
-// reporting rejection of compact_sched due to compile-time assumptions not
-// holding at runtime.
-CompactSchedConfig CreateCompactSchedConfig(
-    const FtraceConfig& request,
-    const CompactSchedEventFormat& compact_format) {
-  if (!request.compact_sched().enabled())
-    return CompactSchedConfig{/*enabled=*/false};
-
-  if (!compact_format.format_valid)
-    return CompactSchedConfig{/*enabled=*/false};
-
-  return CompactSchedConfig{/*enabled=*/true};
-}
-
-CompactSchedConfig EnabledCompactSchedConfigForTesting() {
-  return CompactSchedConfig{/*enabled=*/true};
-}
-
-CompactSchedConfig DisabledCompactSchedConfigForTesting() {
-  return CompactSchedConfig{/*enabled=*/false};
-}
-
-// Sanity check size of stack-allocated bundle state.
-static_assert(sizeof(CompactSchedBuffer) <= 1 << 18,
-              "CompactSchedBuffer's on-stack size excessively large.");
-
-void CompactSchedSwitchBuffer::Write(
-    protos::pbzero::FtraceEventBundle::CompactSched* compact_out) const {
-  compact_out->set_switch_timestamp(timestamp_);
-  compact_out->set_switch_next_pid(next_pid_);
-  compact_out->set_switch_prev_state(prev_state_);
-  compact_out->set_switch_next_prio(next_prio_);
-  compact_out->set_switch_next_comm_index(next_comm_index_);
-}
-
-void CompactSchedSwitchBuffer::Reset() {
-  last_timestamp_ = 0;
-  timestamp_.Reset();
-  next_pid_.Reset();
-  prev_state_.Reset();
-  next_prio_.Reset();
-  next_comm_index_.Reset();
-}
-
-void CompactSchedWakingBuffer::Write(
-    protos::pbzero::FtraceEventBundle::CompactSched* compact_out) const {
-  compact_out->set_waking_timestamp(timestamp_);
-  compact_out->set_waking_pid(pid_);
-  compact_out->set_waking_target_cpu(target_cpu_);
-  compact_out->set_waking_prio(prio_);
-  compact_out->set_waking_comm_index(comm_index_);
-}
-
-void CompactSchedWakingBuffer::Reset() {
-  last_timestamp_ = 0;
-  timestamp_.Reset();
-  pid_.Reset();
-  target_cpu_.Reset();
-  prio_.Reset();
-  comm_index_.Reset();
-}
-
-void CommInterner::Write(
-    protos::pbzero::FtraceEventBundle::CompactSched* compact_out) const {
-  for (size_t i = 0; i < interned_comms_size_; i++) {
-    compact_out->add_intern_table(interned_comms_[i].data(),
-                                  interned_comms_[i].size());
-  }
-}
-
-void CommInterner::Reset() {
-  intern_buf_write_pos_ = 0;
-  interned_comms_size_ = 0;
-}
-
-void CompactSchedBuffer::WriteAndReset(
-    protos::pbzero::FtraceEventBundle* bundle) {
-  if (switch_.size() > 0 || waking_.size() > 0) {
-    auto* compact_out = bundle->set_compact_sched();
-
-    PERFETTO_DCHECK(interner_.interned_comms_size() > 0);
-    interner_.Write(compact_out);
-
-    if (switch_.size() > 0)
-      switch_.Write(compact_out);
-
-    if (waking_.size() > 0)
-      waking_.Write(compact_out);
-  }
-
-  interner_.Reset();
-  switch_.Reset();
-  waking_.Reset();
-}
-
-}  // namespace perfetto
diff --git a/src/traced/probes/ftrace/compact_sched.h b/src/traced/probes/ftrace/compact_sched.h
deleted file mode 100644
index 657d651..0000000
--- a/src/traced/probes/ftrace/compact_sched.h
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACED_PROBES_FTRACE_COMPACT_SCHED_H_
-#define SRC_TRACED_PROBES_FTRACE_COMPACT_SCHED_H_
-
-#include <stdint.h>
-
-#include "perfetto/ext/base/string_view.h"
-#include "perfetto/protozero/packed_repeated_fields.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-#include "src/traced/probes/ftrace/event_info_constants.h"
-
-namespace perfetto {
-
-class FtraceConfig;
-
-// The subset of the sched_switch event's format that is used when parsing and
-// encoding into the compact format.
-struct CompactSchedSwitchFormat {
-  uint32_t event_id;
-  uint16_t size;
-
-  uint16_t next_pid_offset;
-  FtraceFieldType next_pid_type;
-  uint16_t next_prio_offset;
-  FtraceFieldType next_prio_type;
-  uint16_t prev_state_offset;
-  FtraceFieldType prev_state_type;
-  uint16_t next_comm_offset;
-};
-
-// The subset of the sched_waking event's format that is used when parsing and
-// encoding into the compact format.
-struct CompactSchedWakingFormat {
-  uint32_t event_id;
-  uint16_t size;
-
-  uint16_t pid_offset;
-  FtraceFieldType pid_type;
-  uint16_t target_cpu_offset;
-  FtraceFieldType target_cpu_type;
-  uint16_t prio_offset;
-  FtraceFieldType prio_type;
-  uint16_t comm_offset;
-};
-
-// Pre-parsed format of a subset of scheduling events, for use during ftrace
-// parsing if compact encoding is enabled. Holds a flag, |format_valid| to
-// state whether the compile-time assumptions about the format held at runtime.
-// If they didn't, we cannot use the compact encoding.
-struct CompactSchedEventFormat {
-  // If false, the rest of the struct is considered invalid.
-  const bool format_valid;
-
-  const CompactSchedSwitchFormat sched_switch;
-  const CompactSchedWakingFormat sched_waking;
-};
-
-CompactSchedEventFormat ValidateFormatForCompactSched(
-    const std::vector<Event>& events);
-
-CompactSchedEventFormat InvalidCompactSchedEventFormatForTesting();
-
-// Compact encoding configuration used at ftrace reading & parsing time.
-struct CompactSchedConfig {
-  CompactSchedConfig(bool _enabled) : enabled(_enabled) {}
-
-  // If true, and sched_switch and/or sched_waking events are enabled, encode
-  // them in a compact format instead of the normal form.
-  const bool enabled = false;
-};
-
-CompactSchedConfig CreateCompactSchedConfig(
-    const FtraceConfig& request,
-    const CompactSchedEventFormat& compact_format);
-
-CompactSchedConfig EnabledCompactSchedConfigForTesting();
-CompactSchedConfig DisabledCompactSchedConfigForTesting();
-
-// Collects fields of sched_switch events, allowing them to be written out
-// in a compact encoding.
-class CompactSchedSwitchBuffer {
- public:
-  protozero::PackedVarInt& timestamp() { return timestamp_; }
-  protozero::PackedVarInt& prev_state() { return prev_state_; }
-  protozero::PackedVarInt& next_pid() { return next_pid_; }
-  protozero::PackedVarInt& next_prio() { return next_prio_; }
-  protozero::PackedVarInt& next_comm_index() { return next_comm_index_; }
-
-  size_t size() const {
-    // Caller should fill all per-field buffers at the same rate.
-    return timestamp_.size();
-  }
-
-  inline void AppendTimestamp(uint64_t timestamp) {
-    timestamp_.Append(timestamp - last_timestamp_);
-    last_timestamp_ = timestamp;
-  }
-
-  void Write(
-      protos::pbzero::FtraceEventBundle::CompactSched* compact_out) const;
-  void Reset();
-
- private:
-  // First timestamp in a bundle is absolute. The rest are all delta-encoded,
-  // each relative to the preceding sched_switch timestamp.
-  uint64_t last_timestamp_ = 0;
-
-  protozero::PackedVarInt timestamp_;
-  protozero::PackedVarInt prev_state_;
-  protozero::PackedVarInt next_pid_;
-  protozero::PackedVarInt next_prio_;
-  // Interning indices of the next_comm values. See |CommInterner|.
-  protozero::PackedVarInt next_comm_index_;
-};
-
-// As |CompactSchedSwitchBuffer|, but for sched_waking events.
-class CompactSchedWakingBuffer {
- public:
-  protozero::PackedVarInt& pid() { return pid_; }
-  protozero::PackedVarInt& target_cpu() { return target_cpu_; }
-  protozero::PackedVarInt& prio() { return prio_; }
-  protozero::PackedVarInt& comm_index() { return comm_index_; }
-
-  size_t size() const {
-    // Caller should fill all per-field buffers at the same rate.
-    return timestamp_.size();
-  }
-
-  inline void AppendTimestamp(uint64_t timestamp) {
-    timestamp_.Append(timestamp - last_timestamp_);
-    last_timestamp_ = timestamp;
-  }
-
-  void Write(
-      protos::pbzero::FtraceEventBundle::CompactSched* compact_out) const;
-  void Reset();
-
- private:
-  uint64_t last_timestamp_ = 0;
-
-  protozero::PackedVarInt timestamp_;
-  protozero::PackedVarInt pid_;
-  protozero::PackedVarInt target_cpu_;
-  protozero::PackedVarInt prio_;
-  // Interning indices of the comm values. See |CommInterner|.
-  protozero::PackedVarInt comm_index_;
-};
-
-class CommInterner {
- public:
-  static constexpr size_t kExpectedCommLength = 16;
-
-  size_t InternComm(const char* ptr) {
-    // Linearly scan existing string views, ftrace reader will
-    // make sure this set doesn't grow too large.
-    base::StringView transient_view(ptr);
-    for (size_t i = 0; i < interned_comms_size_; i++) {
-      if (transient_view == interned_comms_[i]) {
-        return i;
-      }
-    }
-
-    // Unique comm, intern it. Null byte is not copied over.
-    char* start = intern_buf_ + intern_buf_write_pos_;
-    size_t size = transient_view.size();
-    memcpy(start, ptr, size);
-    intern_buf_write_pos_ += size;
-
-    size_t idx = interned_comms_size_;
-    base::StringView safe_view(start, size);
-    interned_comms_[interned_comms_size_++] = safe_view;
-
-    PERFETTO_DCHECK(intern_buf_write_pos_ <= sizeof(intern_buf_));
-    PERFETTO_DCHECK(interned_comms_size_ < kMaxElements);
-    return idx;
-  }
-
-  size_t interned_comms_size() const { return interned_comms_size_; }
-
-  void Write(
-      protos::pbzero::FtraceEventBundle::CompactSched* compact_out) const;
-  void Reset();
-
- private:
-  // TODO(rsavitski): Consider making the storage dynamically-expandable instead
-  // to not rely on sizing the buffer for the worst case.
-  static constexpr size_t kMaxElements = 4096;
-
-  char intern_buf_[kMaxElements * (kExpectedCommLength - 1)];
-  size_t intern_buf_write_pos_ = 0;
-
-  // Views into unique interned comm strings. Even if every event carries a
-  // unique comm, the ftrace reader is expected to flush the compact buffer way
-  // before this reaches capacity. This is since the cost of processing each
-  // event grows with every unique interned comm (as the interning needs to
-  // search all existing internings).
-  std::array<base::StringView, kMaxElements> interned_comms_;
-  uint32_t interned_comms_size_ = 0;
-};
-
-// Mutable state for buffering parts of scheduling events, that can later be
-// written out in a compact format with |WriteAndReset|. Used by the ftrace
-// reader.
-class CompactSchedBuffer {
- public:
-  CompactSchedSwitchBuffer& sched_switch() { return switch_; }
-  CompactSchedWakingBuffer& sched_waking() { return waking_; }
-  CommInterner& interner() { return interner_; }
-
-  // Writes out the currently buffered events, and starts the next batch
-  // internally.
-  void WriteAndReset(protos::pbzero::FtraceEventBundle* bundle);
-
- private:
-  CommInterner interner_;
-  CompactSchedSwitchBuffer switch_;
-  CompactSchedWakingBuffer waking_;
-};
-
-}  // namespace perfetto
-
-#endif  // SRC_TRACED_PROBES_FTRACE_COMPACT_SCHED_H_
diff --git a/src/traced/probes/ftrace/cpu_reader.cc b/src/traced/probes/ftrace/cpu_reader.cc
index 8299001..436edfb 100644
--- a/src/traced/probes/ftrace/cpu_reader.cc
+++ b/src/traced/probes/ftrace/cpu_reader.cc
@@ -16,34 +16,32 @@
 
 #include "src/traced/probes/ftrace/cpu_reader.h"
 
-#include <dirent.h>
 #include <signal.h>
 
+#include <dirent.h>
+#include <map>
+#include <queue>
+#include <string>
 #include <utility>
 
 #include "perfetto/base/build_config.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/metatrace.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-#include "protos/perfetto/trace/ftrace/generic.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-#include "src/traced/probes/ftrace/ftrace_config_muxer.h"
+#include "perfetto/base/metatrace.h"
+#include "perfetto/base/optional.h"
+#include "perfetto/base/utils.h"
 #include "src/traced/probes/ftrace/ftrace_controller.h"
 #include "src/traced/probes/ftrace/ftrace_data_source.h"
+#include "src/traced/probes/ftrace/ftrace_thread_sync.h"
 #include "src/traced/probes/ftrace/proto_translation_table.h"
 
-namespace perfetto {
-namespace {
+#include "perfetto/trace/ftrace/ftrace_event.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
+#include "perfetto/trace/ftrace/generic.pbzero.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
-// If the compact_sched buffer accumulates more unique strings, the reader will
-// flush it to reset the interning state (and make it cheap again).
-// This is not an exact cap, since we check only at tracing page boundaries.
-// TODO(rsavitski): consider making part of compact_sched config.
-constexpr size_t kCompactSchedInternerThreshold = 64;
+namespace perfetto {
+
+namespace {
 
 // For further documentation of these constants see the kernel source:
 // linux/include/linux/ring_buffer.h
@@ -54,6 +52,12 @@
 constexpr uint32_t kTypeTimeExtend = 30;
 constexpr uint32_t kTypeTimeStamp = 31;
 
+struct PageHeader {
+  uint64_t timestamp;
+  uint64_t size;
+  uint64_t overwrite;
+};
+
 struct EventHeader {
   uint32_t type_or_length : 5;
   uint32_t time_delta : 27;
@@ -105,285 +109,30 @@
   return true;
 }
 
-template <typename T>
-T ReadValue(const uint8_t* ptr) {
-  T t;
-  memcpy(&t, reinterpret_cast<const void*>(ptr), sizeof(T));
-  return t;
-}
-
-// Reads a signed ftrace value as an int64_t, sign extending if necessary.
-static int64_t ReadSignedFtraceValue(const uint8_t* ptr,
-                                     FtraceFieldType ftrace_type) {
-  if (ftrace_type == kFtraceInt32) {
-    int32_t value;
-    memcpy(&value, reinterpret_cast<const void*>(ptr), sizeof(value));
-    return int64_t(value);
-  }
-  if (ftrace_type == kFtraceInt64) {
-    int64_t value;
-    memcpy(&value, reinterpret_cast<const void*>(ptr), sizeof(value));
-    return value;
-  }
-  PERFETTO_FATAL("unexpected ftrace type");
-}
-
 bool SetBlocking(int fd, bool is_blocking) {
   int flags = fcntl(fd, F_GETFL, 0);
   flags = (is_blocking) ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
   return fcntl(fd, F_SETFL, flags) == 0;
 }
 
-}  // namespace
-
-using protos::pbzero::GenericFtraceEvent;
-
-CpuReader::CpuReader(size_t cpu,
-                     const ProtoTranslationTable* table,
-                     base::ScopedFile trace_fd)
-    : cpu_(cpu), table_(table), trace_fd_(std::move(trace_fd)) {
-  PERFETTO_CHECK(trace_fd_);
-  PERFETTO_CHECK(SetBlocking(*trace_fd_, false));
-}
-
-CpuReader::~CpuReader() = default;
-
-size_t CpuReader::ReadCycle(
-    uint8_t* parsing_buf,
-    size_t parsing_buf_size_pages,
-    size_t max_pages,
-    const std::set<FtraceDataSource*>& started_data_sources) {
-  PERFETTO_DCHECK(max_pages > 0 && parsing_buf_size_pages > 0);
-  metatrace::ScopedEvent evt(metatrace::TAG_FTRACE,
-                             metatrace::FTRACE_CPU_READ_CYCLE);
-
-  // Work in batches to keep cache locality, and limit memory usage.
-  size_t batch_pages = std::min(parsing_buf_size_pages, max_pages);
-  size_t total_pages_read = 0;
-  for (bool is_first_batch = true;; is_first_batch = false) {
-    size_t pages_read = ReadAndProcessBatch(
-        parsing_buf, batch_pages, is_first_batch, started_data_sources);
-
-    PERFETTO_DCHECK(pages_read <= batch_pages);
-    total_pages_read += pages_read;
-
-    // Check whether we've caught up to the writer, or possibly giving up on
-    // this attempt due to some error.
-    if (pages_read != batch_pages)
-      break;
-    // Check if we've hit the limit of work for this cycle.
-    if (total_pages_read >= max_pages)
-      break;
-  }
-  PERFETTO_METATRACE_COUNTER(TAG_FTRACE, FTRACE_PAGES_DRAINED,
-                             total_pages_read);
-  return total_pages_read;
-}
-
-// metatrace note: mark the reading phase as FTRACE_CPU_READ_BATCH, but let the
-// parsing time be implied (by the difference between the caller's span, and
-// this reading span). Makes it easier to estimate the read/parse ratio when
-// looking at the trace in the UI.
-size_t CpuReader::ReadAndProcessBatch(
-    uint8_t* parsing_buf,
-    size_t max_pages,
-    bool first_batch_in_cycle,
-    const std::set<FtraceDataSource*>& started_data_sources) {
-  size_t pages_read = 0;
-  {
-    metatrace::ScopedEvent evt(metatrace::TAG_FTRACE,
-                               metatrace::FTRACE_CPU_READ_BATCH);
-    for (; pages_read < max_pages;) {
-      uint8_t* curr_page = parsing_buf + (pages_read * base::kPageSize);
-      ssize_t res =
-          PERFETTO_EINTR(read(*trace_fd_, curr_page, base::kPageSize));
-      if (res < 0) {
-        // Expected errors:
-        // EAGAIN: no data (since we're in non-blocking mode).
-        // ENONMEM, EBUSY: temporary ftrace failures (they happen).
-        if (errno != EAGAIN && errno != ENOMEM && errno != EBUSY)
-          PERFETTO_PLOG("Unexpected error on raw ftrace read");
-        break;  // stop reading regardless of errno
-      }
-
-      // As long as all of our reads are for a single page, the kernel should
-      // return exactly a well-formed raw ftrace page (if not in the steady
-      // state of reading out fully-written pages, the kernel will construct
-      // pages as necessary, copying over events and zero-filling at the end).
-      // A sub-page read() is therefore not expected in practice (unless
-      // there's a concurrent reader requesting less than a page?). Crash if
-      // encountering this situation. Kernel source pointer: see usage of
-      // |info->read| within |tracing_buffers_read|.
-      if (res == 0) {
-        // Very rare, but possible. Stop for now, should recover.
-        PERFETTO_DLOG("[cpu%zu]: 0-sized read from ftrace pipe.", cpu_);
-        break;
-      }
-      PERFETTO_CHECK(res == static_cast<ssize_t>(base::kPageSize));
-
-      pages_read += 1;
-
-      // Compare the amount of ftrace data read against an empirical threshold
-      // to make an educated guess on whether we should read more. To figure
-      // out the amount of ftrace data, we need to parse the page header (since
-      // the read always returns a page, zero-filled at the end). If we read
-      // fewer bytes than the threshold, it means that we caught up with the
-      // write pointer and we started consuming ftrace events in real-time.
-      // This cannot be just 4096 because it needs to account for
-      // fragmentation, i.e. for the fact that the last trace event didn't fit
-      // in the current page and hence the current page was terminated
-      // prematurely.
-      static constexpr size_t kRoughlyAPage = base::kPageSize - 512;
-      const uint8_t* scratch_ptr = curr_page;
-      base::Optional<PageHeader> hdr =
-          ParsePageHeader(&scratch_ptr, table_->page_header_size_len());
-      PERFETTO_DCHECK(hdr && hdr->size > 0 && hdr->size <= base::kPageSize);
-      if (!hdr.has_value()) {
-        PERFETTO_ELOG("[cpu%zu]: can't parse page header", cpu_);
-        break;
-      }
-      // Note that the first read after starting the read cycle being small is
-      // normal. It means that we're given the remainder of events from a
-      // page that we've partially consumed during the last read of the previous
-      // cycle (having caught up to the writer).
-      if (hdr->size < kRoughlyAPage &&
-          !(first_batch_in_cycle && pages_read == 1)) {
-        break;
-      }
-    }
-  }  // end of metatrace::FTRACE_CPU_READ_BATCH
-
-  // Parse the pages and write to the trace for all relevant data
-  // sources.
-  if (pages_read == 0)
-    return pages_read;
-
-  for (FtraceDataSource* data_source : started_data_sources) {
-    bool success = ProcessPagesForDataSource(
-        data_source->trace_writer(), data_source->mutable_metadata(), cpu_,
-        data_source->parsing_config(), parsing_buf, pages_read, table_);
-    PERFETTO_CHECK(success);
-  }
-
-  return pages_read;
-}
-
-// static
-bool CpuReader::ProcessPagesForDataSource(
-    TraceWriter* trace_writer,
-    FtraceMetadata* metadata,
-    size_t cpu,
-    const FtraceDataSourceConfig* ds_config,
-    const uint8_t* parsing_buf,
-    const size_t pages_read,
-    const ProtoTranslationTable* table) {
-  // Begin an FtraceEventBundle, and allocate the buffer for compact scheduler
-  // events (which will be unused if the compact option isn't enabled).
-  CompactSchedBuffer compact_sched;
-  auto packet = trace_writer->NewTracePacket();
-  auto* bundle = packet->set_ftrace_events();
-
-  bool compact_sched_enabled = ds_config->compact_sched.enabled;
-
-  // Note: The fastpath in proto_trace_parser.cc speculates on the fact
-  // that the cpu field is the first field of the proto message. If this
-  // changes, change proto_trace_parser.cc accordingly.
-  bundle->set_cpu(static_cast<uint32_t>(cpu));
-
-  for (size_t i = 0; i < pages_read; i++) {
-    const uint8_t* curr_page = parsing_buf + (i * base::kPageSize);
-    const uint8_t* curr_page_end = curr_page + base::kPageSize;
-    const uint8_t* parse_pos = curr_page;
-    base::Optional<PageHeader> page_header =
-        ParsePageHeader(&parse_pos, table->page_header_size_len());
-
-    if (!page_header.has_value() || page_header->size == 0 ||
-        parse_pos >= curr_page_end ||
-        parse_pos + page_header->size > curr_page_end) {
-      PERFETTO_DFATAL("invalid page header");
-      return false;
-    }
-
-    // Start a new bundle if either:
-    // * The page we're about to read indicates that there was a kernel ring
-    //   buffer overrun since our last read from that per-cpu buffer. We have
-    //   a single |lost_events| field per bundle, so start a new packet.
-    // * The compact_sched buffer is holding more unique interned strings than
-    //   a threshold. We need to flush the compact buffer to make the
-    //   interning lookups cheap again.
-    bool interner_past_threshold =
-        compact_sched_enabled &&
-        compact_sched.interner().interned_comms_size() >
-            kCompactSchedInternerThreshold;
-    if (page_header->lost_events || interner_past_threshold) {
-      if (compact_sched_enabled)
-        compact_sched.WriteAndReset(bundle);
-      packet->Finalize();
-
-      packet = trace_writer->NewTracePacket();
-      bundle = packet->set_ftrace_events();
-      bundle->set_cpu(static_cast<uint32_t>(cpu));
-      if (page_header->lost_events)
-        bundle->set_lost_events(true);
-    }
-
-    size_t evt_size =
-        ParsePagePayload(parse_pos, &page_header.value(), table, ds_config,
-                         &compact_sched, bundle, metadata);
-
-    // TODO(b/140866160): compare against header->size once padding size
-    // off-by-4 is fixed.
-    PERFETTO_DCHECK(evt_size > 0);
-  }
-
-  if (compact_sched_enabled)
-    compact_sched.WriteAndReset(bundle);
-
-  return true;
-}
-
-// A page header consists of:
-// * timestamp: 8 bytes
-// * commit: 8 bytes on 64 bit, 4 bytes on 32 bit kernels
-//
-// The kernel reports this at /sys/kernel/debug/tracing/events/header_page.
-//
-// |commit|'s bottom bits represent the length of the payload following this
-// header. The top bits have been repurposed as a bitset of flags pertaining to
-// data loss. We look only at the "there has been some data lost" flag
-// (RB_MISSED_EVENTS), and ignore the relatively tricky "appended the precise
-// lost events count past the end of the valid data, as there was room to do so"
-// flag (RB_MISSED_STORED).
-//
-// static
-base::Optional<CpuReader::PageHeader> CpuReader::ParsePageHeader(
-    const uint8_t** ptr,
-    uint16_t page_header_size_len) {
-  // Mask for the data length portion of the |commit| field. Note that the
-  // kernel implementation never explicitly defines the boundary (beyond using
-  // bits 30 and 31 as flags), but 27 bits are mentioned as sufficient in the
-  // original commit message, and is the constant used by trace-cmd.
-  constexpr static uint64_t kDataSizeMask = (1ull << 27) - 1;
-  // If set, indicates that the relevant cpu has lost events since the last read
-  // (clearing the bit internally).
-  constexpr static uint64_t kMissedEventsFlag = (1ull << 31);
-
+base::Optional<PageHeader> ParsePageHeader(const uint8_t** ptr,
+                                           uint16_t page_header_size_len) {
   const uint8_t* end_of_page = *ptr + base::kPageSize;
   PageHeader page_header;
   if (!CpuReader::ReadAndAdvance<uint64_t>(ptr, end_of_page,
                                            &page_header.timestamp))
     return base::nullopt;
 
-  uint32_t size_and_flags;
+  uint32_t overwrite_and_size;
 
   // On little endian, we can just read a uint32_t and reject the rest of the
   // number later.
   if (!CpuReader::ReadAndAdvance<uint32_t>(
-          ptr, end_of_page, base::AssumeLittleEndian(&size_and_flags)))
+          ptr, end_of_page, base::AssumeLittleEndian(&overwrite_and_size)))
     return base::nullopt;
 
-  page_header.size = size_and_flags & kDataSizeMask;
-  page_header.lost_events = bool(size_and_flags & kMissedEventsFlag);
+  page_header.size = (overwrite_and_size & 0x000000000000ffffull) >> 0;
+  page_header.overwrite = (overwrite_and_size & 0x00000000ff000000ull) >> 24;
   PERFETTO_DCHECK(page_header.size <= base::kPageSize);
 
   // Reject rest of the number, if applicable. On 32-bit, size_bytes - 4 will
@@ -395,19 +144,315 @@
   return base::make_optional(page_header);
 }
 
-// A raw ftrace buffer page consists of a header followed by a sequence of
-// binary ftrace events. See |ParsePageHeader| for the format of the earlier.
-//
+}  // namespace
+
+using protos::pbzero::GenericFtraceEvent;
+
+CpuReader::CpuReader(const ProtoTranslationTable* table,
+                     FtraceThreadSync* thread_sync,
+                     size_t cpu,
+                     int generation,
+                     base::ScopedFile fd)
+    : table_(table),
+      thread_sync_(thread_sync),
+      cpu_(cpu),
+      trace_fd_(std::move(fd)) {
+  // Make reads from the raw pipe blocking so that splice() can sleep.
+  PERFETTO_CHECK(trace_fd_);
+  PERFETTO_CHECK(SetBlocking(*trace_fd_, true));
+
+  // We need a non-default SIGPIPE handler to make it so that the blocking
+  // splice() is woken up when the ~CpuReader() dtor destroys the pipes.
+  // Just masking out the signal would cause an implicit syscall restart and
+  // hence make the join() in the dtor unreliable.
+  struct sigaction current_act = {};
+  PERFETTO_CHECK(sigaction(SIGPIPE, nullptr, &current_act) == 0);
+#pragma GCC diagnostic push
+#if defined(__clang__)
+#pragma GCC diagnostic ignored "-Wdisabled-macro-expansion"
+#endif
+  if (current_act.sa_handler == SIG_DFL || current_act.sa_handler == SIG_IGN) {
+    struct sigaction act = {};
+    act.sa_sigaction = [](int, siginfo_t*, void*) {};
+    PERFETTO_CHECK(sigaction(SIGPIPE, &act, nullptr) == 0);
+  }
+#pragma GCC diagnostic pop
+
+  worker_thread_ = std::thread(std::bind(&RunWorkerThread, cpu_, generation,
+                                         *trace_fd_, &pool_, thread_sync_,
+                                         table->page_header_size_len()));
+}
+
+CpuReader::~CpuReader() {
+// FtraceController (who owns this) is supposed to issue a kStop notification
+// to the thread sync object before destroying the CpuReader.
+#if PERFETTO_DCHECK_IS_ON()
+  {
+    std::lock_guard<std::mutex> lock(thread_sync_->mutex);
+    PERFETTO_DCHECK(thread_sync_->cmd == FtraceThreadSync::kQuit);
+  }
+#endif
+
+  // The kernel's splice implementation for the trace pipe doesn't generate a
+  // SIGPIPE if the output pipe is closed (b/73807072). Instead, the call to
+  // close() on the pipe hangs forever. To work around this, we first close the
+  // trace fd (which prevents another splice from starting), raise SIGPIPE and
+  // wait for the worker to exit (i.e., to guarantee no splice is in progress)
+  // and only then close the staging pipe.
+  trace_fd_.reset();
+  InterruptWorkerThreadWithSignal();
+  worker_thread_.join();
+}
+
+void CpuReader::InterruptWorkerThreadWithSignal() {
+  pthread_kill(worker_thread_.native_handle(), SIGPIPE);
+}
+
+// The worker thread reads data from the ftrace trace_pipe_raw and moves it to
+// the page |pool| allowing the main thread to read and decode that.
+// See //docs/ftrace.md for the design of the ftrace worker scheduler.
+// static
+void CpuReader::RunWorkerThread(size_t cpu,
+                                int generation,
+                                int trace_fd,
+                                PagePool* pool,
+                                FtraceThreadSync* thread_sync,
+                                uint16_t header_size_len) {
+// Before attempting any changes to this function, think twice. The kernel
+// ftrace pipe code is full of caveats and bugs. This code carefully works
+// around those bugs. See b/120188810 and b/119805587 for the full narrative.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+  char thread_name[16];
+  snprintf(thread_name, sizeof(thread_name), "traced_probes%zu", cpu);
+  pthread_setname_np(pthread_self(), thread_name);
+
+  // When using splice() the target fd needs to be an actual pipe. This pipe is
+  // used only within this thread and is mainly for synchronization purposes.
+  // A blocking splice() is the only way to block and wait for a new page of
+  // ftrace data.
+  base::Pipe sync_pipe = base::Pipe::Create(base::Pipe::kBothNonBlock);
+
+  enum ReadMode { kRead, kSplice };
+  enum Block { kBlock, kNonBlock };
+  constexpr auto kPageSize = base::kPageSize;
+
+  // This lambda function reads the ftrace raw pipe using either read() or
+  // splice(), either in blocking or non-blocking mode.
+  // Returns the number of ftrace bytes read, or -1 in case of failure.
+  auto read_ftrace_pipe = [&sync_pipe, trace_fd, pool, cpu, header_size_len](
+                              ReadMode mode, Block block) -> int {
+    static const char* const kModesStr[] = {"read-nonblock", "read-block",
+                                            "splice-nonblock", "splice-block"};
+    const char* mode_str = kModesStr[(mode == kSplice) * 2 + (block == kBlock)];
+    PERFETTO_METATRACE(mode_str, cpu);
+    uint8_t* pool_page = pool->BeginWrite();
+    PERFETTO_DCHECK(pool_page);
+
+    ssize_t res;
+    int err = 0;
+    if (mode == kSplice) {
+      uint32_t flg = SPLICE_F_MOVE | ((block == kNonBlock) * SPLICE_F_NONBLOCK);
+      res = splice(trace_fd, nullptr, *sync_pipe.wr, nullptr, kPageSize, flg);
+      err = errno;
+      if (res > 0) {
+        // If the splice() succeeded, read back from the other end of our own
+        // pipe and copy the data into the pool.
+        ssize_t rdres = read(*sync_pipe.rd, pool_page, kPageSize);
+        PERFETTO_DCHECK(rdres == res);
+      }
+    } else {
+      if (block == kNonBlock)
+        SetBlocking(trace_fd, false);
+      res = read(trace_fd, pool_page, kPageSize);
+      err = errno;
+      if (res > 0) {
+        // Need to copy the ptr, ParsePageHeader() advances the passed ptr arg.
+        const uint8_t* ptr = pool_page;
+
+        // The caller of this function wants to have a sufficient approximation
+        // of how many bytes of ftrace data have been read. Unfortunately the
+        // return value of read() is a lie. The problem is that the ftrace
+        // read() implementation, for good reasons, always reconstructs a whole
+        // ftrace page, copying the events over and zero-filling at the end.
+        // This is nice, because we always get a valid ftrace header, but also
+        // causes read to always returns 4096. The only way to have a good
+        // indication of how many bytes of ftrace data have been read is to
+        // parse the ftrace header.
+        // Note: |header_size_len| is *not* an indication on how many bytes are
+        // available form |ptr|. It's just an independent piece of information
+        // that needs to be passed to ParsePageHeader() (a static function) in
+        // order to work.
+        base::Optional<PageHeader> hdr = ParsePageHeader(&ptr, header_size_len);
+        PERFETTO_DCHECK(hdr && hdr->size > 0 && hdr->size <= base::kPageSize);
+        res = hdr.has_value() ? static_cast<int>(hdr->size) : -1;
+      }
+      if (block == kNonBlock)
+        SetBlocking(trace_fd, true);
+    }
+
+    if (res > 0) {
+      // splice() should return full pages, read can return < a page.
+      PERFETTO_DCHECK(res == base::kPageSize || mode == kRead);
+      pool->EndWrite();
+      return static_cast<int>(res);
+    }
+
+    // It is fine to leave the BeginWrite() unpaired in the error case.
+
+    if (res && err != EAGAIN && err != ENOMEM && err != EBUSY && err != EINTR &&
+        err != EBADF) {
+      // EAGAIN: no data when in non-blocking mode.
+      // ENONMEM, EBUSY: temporary ftrace failures (they happen).
+      // EINTR: signal interruption, likely from main thread to issue a new cmd.
+      // EBADF: the main thread has closed the fd (happens during dtor).
+      PERFETTO_PLOG("Unexpected %s() err", mode == kRead ? "read" : "splice");
+    }
+    return -1;
+  };
+
+  uint64_t last_cmd_id = 0;
+  ReadMode cur_mode = kSplice;
+  for (bool run_loop = true; run_loop;) {
+    FtraceThreadSync::Cmd cmd;
+    // Wait for a new command from the main thread issued by FtraceController.
+    // The FtraceController issues also a signal() after every new command. This
+    // is not necessary for the condition variable itself, but it's necessary to
+    // unblock us if we are in a blocking read() or splice().
+    // Commands are tagged with an ID, every new command has a new |cmd_id|, so
+    // we can distinguish spurious wakeups from actual cmd requests.
+    {
+      PERFETTO_METATRACE("wait cmd", cpu);
+      std::unique_lock<std::mutex> lock(thread_sync->mutex);
+      while (thread_sync->cmd_id == last_cmd_id)
+        thread_sync->cond.wait(lock);
+      cmd = thread_sync->cmd;
+      last_cmd_id = thread_sync->cmd_id;
+    }
+
+    // An empirical threshold (bytes read/spliced from the raw pipe) to make an
+    // educated guess on whether we should read/splice more. If we read fewer
+    // bytes it means that we caught up with the write pointer and we started
+    // consuming ftrace events in real-time. This cannot be just 4096 because
+    // it needs to account for fragmentation, i.e. for the fact that the last
+    // trace event didn't fit in the current page and hence the current page
+    // was terminated prematurely.
+    constexpr int kRoughlyAPage = 4096 - 512;
+
+    switch (cmd) {
+      case FtraceThreadSync::kQuit:
+        run_loop = false;
+        break;
+
+      case FtraceThreadSync::kRun: {
+        PERFETTO_METATRACE(cur_mode == kRead ? "read" : "splice", cpu);
+
+        // Do a blocking read/splice. This can fail for a variety of reasons:
+        // - FtraceController interrupts us with a signal for a new cmd
+        //   (e.g. it wants us to quit or do a flush).
+        // - A temporary read/splice() failure occurred (it has been observed
+        //   to happen if the system is under high load).
+        // In all these cases the most useful thing we can do is skip the
+        // current cycle and try again later.
+        if (read_ftrace_pipe(cur_mode, kBlock) <= 0)
+          break;  // Wait for next command.
+
+        // If we are in read mode (because of a previous flush) check if the
+        // in-kernel read cursor is page-aligned again. If a non-blocking splice
+        // succeeds, it means that we can safely switch back to splice mode
+        // (See b/120188810).
+        if (cur_mode == kRead && read_ftrace_pipe(kSplice, kNonBlock) > 0)
+          cur_mode = kSplice;
+
+        // Do as many non-blocking read/splice as we can.
+        while (read_ftrace_pipe(cur_mode, kNonBlock) > kRoughlyAPage) {
+        }
+        pool->CommitWrittenPages();
+        FtraceController::OnCpuReaderRead(cpu, generation, thread_sync);
+        break;
+      }
+
+      case FtraceThreadSync::kFlush: {
+        PERFETTO_METATRACE("flush", cpu);
+        cur_mode = kRead;
+        while (read_ftrace_pipe(cur_mode, kNonBlock) > kRoughlyAPage) {
+        }
+        pool->CommitWrittenPages();
+        FtraceController::OnCpuReaderFlush(cpu, generation, thread_sync);
+        break;
+      }
+    }  // switch(cmd)
+  }    // for(run_loop)
+  PERFETTO_DPLOG("Terminating CPUReader thread for CPU %zd.", cpu);
+#else
+  base::ignore_result(cpu);
+  base::ignore_result(generation);
+  base::ignore_result(trace_fd);
+  base::ignore_result(pool);
+  base::ignore_result(thread_sync);
+  base::ignore_result(header_size_len);
+  PERFETTO_ELOG("Supported only on Linux/Android");
+#endif
+}
+
+// Invoked on the main thread by FtraceController, |drain_rate_ms| after the
+// first CPU wakes up from the blocking read()/splice().
+void CpuReader::Drain(const std::set<FtraceDataSource*>& data_sources) {
+  PERFETTO_DCHECK_THREAD(thread_checker_);
+  PERFETTO_METATRACE("Drain(" + std::to_string(cpu_) + ")",
+                     base::MetaTrace::kMainThreadCpu);
+
+  auto page_blocks = pool_.BeginRead();
+  for (const auto& page_block : page_blocks) {
+    for (size_t i = 0; i < page_block.size(); i++) {
+      const uint8_t* page = page_block.At(i);
+
+      for (FtraceDataSource* data_source : data_sources) {
+        auto packet = data_source->trace_writer()->NewTracePacket();
+        auto* bundle = packet->set_ftrace_events();
+        auto* metadata = data_source->mutable_metadata();
+        auto* filter = data_source->event_filter();
+
+        // Note: The fastpath in proto_trace_parser.cc speculates on the fact
+        // that the cpu field is the first field of the proto message. If this
+        // changes, change proto_trace_parser.cc accordingly.
+        bundle->set_cpu(static_cast<uint32_t>(cpu_));
+
+        size_t evt_size = ParsePage(page, filter, bundle, table_, metadata);
+        PERFETTO_DCHECK(evt_size);
+        bundle->set_overwrite_count(metadata->overwrite_count);
+      }
+    }
+  }
+  pool_.EndRead(std::move(page_blocks));
+}
+
+// The structure of a raw trace buffer page is as follows:
+// First a page header:
+//   8 bytes of timestamp
+//   8 bytes of page length TODO(hjd): other fields also defined here?
+// // TODO(hjd): Document rest of format.
+// Some information about the layout of the page header is available in user
+// space at: /sys/kernel/debug/tracing/events/header_event
 // This method is deliberately static so it can be tested independently.
-size_t CpuReader::ParsePagePayload(const uint8_t* start_of_payload,
-                                   const PageHeader* page_header,
-                                   const ProtoTranslationTable* table,
-                                   const FtraceDataSourceConfig* ds_config,
-                                   CompactSchedBuffer* compact_sched_buffer,
-                                   FtraceEventBundle* bundle,
-                                   FtraceMetadata* metadata) {
-  const uint8_t* ptr = start_of_payload;
+size_t CpuReader::ParsePage(const uint8_t* ptr,
+                            const EventFilter* filter,
+                            FtraceEventBundle* bundle,
+                            const ProtoTranslationTable* table,
+                            FtraceMetadata* metadata) {
+  const uint8_t* const start_of_page = ptr;
+  const uint8_t* const end_of_page = ptr + base::kPageSize;
+
+  auto page_header = ParsePageHeader(&ptr, table->page_header_size_len());
+  if (!page_header.has_value())
+    return 0;
+
+  // ParsePageHeader advances |ptr| to point past the end of the header.
+
+  metadata->overwrite_count = static_cast<uint32_t>(page_header->overwrite);
   const uint8_t* const end = ptr + page_header->size;
+  if (end > end_of_page)
+    return 0;
 
   uint64_t timestamp = page_header->timestamp;
 
@@ -477,42 +522,11 @@
         uint16_t ftrace_event_id;
         if (!ReadAndAdvance<uint16_t>(&ptr, end, &ftrace_event_id))
           return 0;
-
-        if (ds_config->event_filter.IsEventEnabled(ftrace_event_id)) {
-          // Special-cased handling of some scheduler events when compact format
-          // is enabled.
-          bool compact_sched_enabled = ds_config->compact_sched.enabled;
-          const CompactSchedSwitchFormat& sched_switch_format =
-              table->compact_sched_format().sched_switch;
-          const CompactSchedWakingFormat& sched_waking_format =
-              table->compact_sched_format().sched_waking;
-
-          // compact sched_switch
-          if (compact_sched_enabled &&
-              ftrace_event_id == sched_switch_format.event_id) {
-            if (event_size < sched_switch_format.size)
-              return 0;
-
-            ParseSchedSwitchCompact(start, timestamp, &sched_switch_format,
-                                    compact_sched_buffer, metadata);
-
-            // compact sched_waking
-          } else if (compact_sched_enabled &&
-                     ftrace_event_id == sched_waking_format.event_id) {
-            if (event_size < sched_waking_format.size)
-              return 0;
-
-            ParseSchedWakingCompact(start, timestamp, &sched_waking_format,
-                                    compact_sched_buffer, metadata);
-
-          } else {
-            // Common case: parse all other types of enabled events.
-            protos::pbzero::FtraceEvent* event = bundle->add_event();
-            event->set_timestamp(timestamp);
-            if (!ParseEvent(ftrace_event_id, start, next, table, event,
-                            metadata))
-              return 0;
-          }
+        if (filter->IsEventEnabled(ftrace_event_id)) {
+          protos::pbzero::FtraceEvent* event = bundle->add_event();
+          event->set_timestamp(timestamp);
+          if (!ParseEvent(ftrace_event_id, start, next, table, event, metadata))
+            return 0;
         }
 
         // Jump to next event.
@@ -520,7 +534,7 @@
       }
     }
   }
-  return static_cast<size_t>(ptr - start_of_payload);
+  return static_cast<size_t>(ptr - start_of_page);
 }
 
 // |start| is the start of the current event.
@@ -552,8 +566,7 @@
       message->BeginNestedMessage<protozero::Message>(info.proto_field_id);
 
   // Parse generic event.
-  if (PERFETTO_UNLIKELY(info.proto_field_id ==
-                        protos::pbzero::FtraceEvent::kGenericFieldNumber)) {
+  if (info.proto_field_id == protos::pbzero::FtraceEvent::kGenericFieldNumber) {
     nested->AppendString(GenericFtraceEvent::kEventNameFieldNumber, info.name);
     for (const Field& field : info.fields) {
       auto generic_field = nested->BeginNestedMessage<protozero::Message>(
@@ -665,67 +678,8 @@
     case kDevId64ToUint64:
       ReadDevId<uint64_t>(field_start, field_id, message, metadata);
       return true;
-    case kInvalidTranslationStrategy:
-      break;
   }
-  PERFETTO_FATAL("Unexpected translation strategy");
-}
-
-// Parse a sched_switch event according to pre-validated format, and buffer the
-// individual fields in the current compact batch. See the code populating
-// |CompactSchedSwitchFormat| for the assumptions made around the format, which
-// this code is closely tied to.
-// static
-void CpuReader::ParseSchedSwitchCompact(const uint8_t* start,
-                                        uint64_t timestamp,
-                                        const CompactSchedSwitchFormat* format,
-                                        CompactSchedBuffer* compact_buf,
-                                        FtraceMetadata* metadata) {
-  compact_buf->sched_switch().AppendTimestamp(timestamp);
-
-  int32_t next_pid = ReadValue<int32_t>(start + format->next_pid_offset);
-  compact_buf->sched_switch().next_pid().Append(next_pid);
-  metadata->AddPid(next_pid);
-
-  int32_t next_prio = ReadValue<int32_t>(start + format->next_prio_offset);
-  compact_buf->sched_switch().next_prio().Append(next_prio);
-
-  // Varint encoding of int32 and int64 is the same, so treat the value as
-  // int64 after reading.
-  int64_t prev_state = ReadSignedFtraceValue(start + format->prev_state_offset,
-                                             format->prev_state_type);
-  compact_buf->sched_switch().prev_state().Append(prev_state);
-
-  // next_comm
-  const char* comm_ptr =
-      reinterpret_cast<const char*>(start + format->next_comm_offset);
-  size_t iid = compact_buf->interner().InternComm(comm_ptr);
-  compact_buf->sched_switch().next_comm_index().Append(iid);
-}
-
-// static
-void CpuReader::ParseSchedWakingCompact(const uint8_t* start,
-                                        uint64_t timestamp,
-                                        const CompactSchedWakingFormat* format,
-                                        CompactSchedBuffer* compact_buf,
-                                        FtraceMetadata* metadata) {
-  compact_buf->sched_waking().AppendTimestamp(timestamp);
-
-  int32_t pid = ReadValue<int32_t>(start + format->pid_offset);
-  compact_buf->sched_waking().pid().Append(pid);
-  metadata->AddPid(pid);
-
-  int32_t target_cpu = ReadValue<int32_t>(start + format->target_cpu_offset);
-  compact_buf->sched_waking().target_cpu().Append(target_cpu);
-
-  int32_t prio = ReadValue<int32_t>(start + format->prio_offset);
-  compact_buf->sched_waking().prio().Append(prio);
-
-  // comm
-  const char* comm_ptr =
-      reinterpret_cast<const char*>(start + format->comm_offset);
-  size_t iid = compact_buf->interner().InternComm(comm_ptr);
-  compact_buf->sched_waking().comm_index().Append(iid);
+  PERFETTO_FATAL("Not reached");  // For gcc
 }
 
 }  // namespace perfetto
diff --git a/src/traced/probes/ftrace/cpu_reader.h b/src/traced/probes/ftrace/cpu_reader.h
index f329044..9e73020 100644
--- a/src/traced/probes/ftrace/cpu_reader.h
+++ b/src/traced/probes/ftrace/cpu_reader.h
@@ -26,24 +26,24 @@
 #include <set>
 #include <thread>
 
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/paged_memory.h"
-#include "perfetto/ext/base/pipe.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/thread_checker.h"
-#include "perfetto/ext/traced/data_source_types.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
+#include "perfetto/base/gtest_prod_util.h"
+#include "perfetto/base/paged_memory.h"
+#include "perfetto/base/pipe.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/thread_checker.h"
 #include "perfetto/protozero/message.h"
 #include "perfetto/protozero/message_handle.h"
-#include "src/traced/probes/ftrace/compact_sched.h"
+#include "perfetto/traced/data_source_types.h"
+#include "src/traced/probes/ftrace/ftrace_config.h"
 #include "src/traced/probes/ftrace/ftrace_metadata.h"
+#include "src/traced/probes/ftrace/page_pool.h"
 #include "src/traced/probes/ftrace/proto_translation_table.h"
 
 namespace perfetto {
 
 class FtraceDataSource;
+struct FtraceThreadSync;
 class ProtoTranslationTable;
-struct FtraceDataSourceConfig;
 
 namespace protos {
 namespace pbzero {
@@ -51,29 +51,24 @@
 }  // namespace pbzero
 }  // namespace protos
 
-// Reads raw ftrace data for a cpu, parses it, and writes it into the perfetto
-// tracing buffers.
+
+// Reads raw ftrace data for a cpu and writes that into the perfetto userspace
+// buffer.
 class CpuReader {
  public:
   using FtraceEventBundle = protos::pbzero::FtraceEventBundle;
 
-  struct PageHeader {
-    uint64_t timestamp;
-    uint64_t size;
-    bool lost_events;
-  };
-
-  CpuReader(size_t cpu,
-            const ProtoTranslationTable* table,
-            base::ScopedFile trace_fd);
+  CpuReader(const ProtoTranslationTable*,
+            FtraceThreadSync*,
+            size_t cpu,
+            int generation,
+            base::ScopedFile fd);
   ~CpuReader();
 
-  // Reads and parses all ftrace data for this cpu (in batches), until we catch
-  // up to the writer, or hit |max_pages|. Returns number of pages read.
-  size_t ReadCycle(uint8_t* parsing_buf,
-                   size_t parsing_buf_size_pages,
-                   size_t max_pages,
-                   const std::set<FtraceDataSource*>& started_data_sources);
+  // Drains all available data into the buffer of the passed data sources.
+  void Drain(const std::set<FtraceDataSource*>&);
+
+  void InterruptWorkerThreadWithSignal();
 
   template <typename T>
   static bool ReadAndAdvance(const uint8_t** ptr, const uint8_t* end, T* out) {
@@ -152,26 +147,17 @@
         ((min & 0xffffff00ULL) << 12) | ((min & 0xffULL)));
   }
 
-  // Returns a parsed representation of the given raw ftrace page's header.
-  static base::Optional<CpuReader::PageHeader> ParsePageHeader(
-      const uint8_t** ptr,
-      uint16_t page_header_size_len);
-
-  // Parse the payload of a raw ftrace page, and write the events as protos
-  // into the provided bundle (and/or compact buffer).
+  // Parse a raw ftrace page beginning at ptr and write the events a protos
+  // into the provided bundle respecting the given event filter.
   // |table| contains the mix of compile time (e.g. proto field ids) and
   // run time (e.g. field offset and size) information necessary to do this.
   // The table is initialized once at start time by the ftrace controller
   // which passes it to the CpuReader which passes it here.
-  // The caller is responsible for validating that the page_header->size stays
-  // within the current page.
-  static size_t ParsePagePayload(const uint8_t* start_of_payload,
-                                 const PageHeader* page_header,
-                                 const ProtoTranslationTable* table,
-                                 const FtraceDataSourceConfig* ds_config,
-                                 CompactSchedBuffer* compact_sched_buffer,
-                                 FtraceEventBundle* bundle,
-                                 FtraceMetadata* metadata);
+  static size_t ParsePage(const uint8_t* ptr,
+                          const EventFilter*,
+                          protos::pbzero::FtraceEventBundle*,
+                          const ProtoTranslationTable* table,
+                          FtraceMetadata*);
 
   // Parse a single raw ftrace event beginning at |start| and ending at |end|
   // and write it into the provided bundle as a proto.
@@ -193,53 +179,27 @@
                          protozero::Message* message,
                          FtraceMetadata* metadata);
 
-  // Parse a sched_switch event according to pre-validated format, and buffer
-  // the individual fields in the given compact encoding batch.
-  static void ParseSchedSwitchCompact(const uint8_t* start,
-                                      uint64_t timestamp,
-                                      const CompactSchedSwitchFormat* format,
-                                      CompactSchedBuffer* compact_buf,
-                                      FtraceMetadata* metadata);
-
-  // Parse a sched_waking event according to pre-validated format, and buffer
-  // the individual fields in the given compact encoding batch.
-  static void ParseSchedWakingCompact(const uint8_t* start,
-                                      uint64_t timestamp,
-                                      const CompactSchedWakingFormat* format,
-                                      CompactSchedBuffer* compact_buf,
-                                      FtraceMetadata* metadata);
-
-  // Parses & encodes the given range of contiguous tracing pages. Called by
-  // |ReadAndProcessBatch| for each active data source.
-  //
-  // public and static for testing
-  static bool ProcessPagesForDataSource(TraceWriter* trace_writer,
-                                        FtraceMetadata* metadata,
-                                        size_t cpu,
-                                        const FtraceDataSourceConfig* ds_config,
-                                        const uint8_t* parsing_buf,
-                                        const size_t pages_read,
-                                        const ProtoTranslationTable* table);
-
  private:
+  static void RunWorkerThread(size_t cpu,
+                              int generation,
+                              int trace_fd,
+                              PagePool*,
+                              FtraceThreadSync*,
+                              uint16_t header_size_len);
+
   CpuReader(const CpuReader&) = delete;
   CpuReader& operator=(const CpuReader&) = delete;
 
-  // Reads at most |max_pages| of ftrace data, parses it, and writes it
-  // into |started_data_sources|. Returns number of pages read.
-  // See comment on ftrace_controller.cc:kMaxParsingWorkingSetPages for
-  // rationale behind the batching.
-  size_t ReadAndProcessBatch(
-      uint8_t* parsing_buf,
-      size_t max_pages,
-      bool first_batch_in_cycle,
-      const std::set<FtraceDataSource*>& started_data_sources);
-
-  const size_t cpu_;
   const ProtoTranslationTable* const table_;
+  FtraceThreadSync* const thread_sync_;
+  const size_t cpu_;
+  PagePool pool_;
   base::ScopedFile trace_fd_;
+  std::thread worker_thread_;
+  PERFETTO_THREAD_CHECKER(thread_checker_)
 };
 
+
 }  // namespace perfetto
 
 #endif  // SRC_TRACED_PROBES_FTRACE_CPU_READER_H_
diff --git a/src/traced/probes/ftrace/cpu_reader_benchmark.cc b/src/traced/probes/ftrace/cpu_reader_benchmark.cc
index 58b4e20..363f66d 100644
--- a/src/traced/probes/ftrace/cpu_reader_benchmark.cc
+++ b/src/traced/probes/ftrace/cpu_reader_benchmark.cc
@@ -12,16 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <benchmark/benchmark.h>
+#include "benchmark/benchmark.h"
 
-#include "perfetto/ext/base/utils.h"
+#include "src/traced/probes/ftrace/cpu_reader.h"
+#include "src/traced/probes/ftrace/proto_translation_table.h"
+
+#include "perfetto/base/utils.h"
 #include "perfetto/protozero/scattered_stream_null_delegate.h"
 #include "perfetto/protozero/scattered_stream_writer.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-#include "src/traced/probes/ftrace/cpu_reader.h"
-#include "src/traced/probes/ftrace/ftrace_config_muxer.h"
-#include "src/traced/probes/ftrace/proto_translation_table.h"
-#include "src/traced/probes/ftrace/test/cpu_reader_support.h"
+
+#include "perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
+#include "test/cpu_reader_support.h"
 
 namespace {
 
@@ -38,7 +39,7 @@
 00000070: 6561 6400 6572 0000 7002 0000 6100 0000  ead.er..p...a...
 00000080: 0100 0000 0000 0000 4a69 7420 7468 7265  ........Jit thre
 00000090: 6164 2070 6f6f 6c00 140d 0000 8100 0000  ad pool.........
-000000a0: 50c2 0910 2f00 0103 140d 0000 4a69 7420  P.../.......Jit
+000000a0: 50c2 0910 2f00 0103 140d 0000 4a69 7420  P.../.......Jit 
 000000b0: 7468 7265 6164 2070 6f6f 6c00 140d 0000  thread pool.....
 000000c0: 8100 0000 0100 0000 0000 0000 7377 6170  ............swap
 000000d0: 7065 722f 3000 0000 0000 0000 0000 0000  per/0...........
@@ -289,22 +290,18 @@
 
 }  // namespace
 
-using perfetto::CompactSchedBuffer;
-using perfetto::CpuReader;
-using perfetto::DisabledCompactSchedConfigForTesting;
-using perfetto::EventFilter;
 using perfetto::ExamplePage;
-using perfetto::FtraceDataSourceConfig;
-using perfetto::FtraceMetadata;
-using perfetto::GetTable;
-using perfetto::GroupAndName;
-using perfetto::PageFromXxd;
+using perfetto::EventFilter;
 using perfetto::ProtoTranslationTable;
-using perfetto::protos::pbzero::FtraceEventBundle;
-using protozero::ScatteredStreamWriter;
 using protozero::ScatteredStreamWriterNullDelegate;
+using protozero::ScatteredStreamWriter;
+using perfetto::GetTable;
+using perfetto::PageFromXxd;
+using perfetto::protos::pbzero::FtraceEventBundle;
+using perfetto::CpuReader;
+using perfetto::FtraceMetadata;
+using perfetto::GroupAndName;
 
-// Benchmark for the core logic of the ftrace binary format decoding.
 static void BM_ParsePageFullOfSchedSwitch(benchmark::State& state) {
   const ExamplePage* test_case = &g_full_page_sched_switch;
 
@@ -315,27 +312,14 @@
   ProtoTranslationTable* table = GetTable(test_case->name);
   auto page = PageFromXxd(test_case->data);
 
-  FtraceDataSourceConfig ds_config{EventFilter{},
-                                   DisabledCompactSchedConfigForTesting()};
-  ds_config.event_filter.AddEnabledEvent(
+  EventFilter filter;
+  filter.AddEnabledEvent(
       table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
 
   FtraceMetadata metadata{};
   while (state.KeepRunning()) {
     writer.Reset(&stream);
-
-    CompactSchedBuffer compact_buffer;
-    const uint8_t* parse_pos = page.get();
-    perfetto::base::Optional<CpuReader::PageHeader> page_header =
-        CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
-
-    if (!page_header.has_value())
-      return;
-
-    CpuReader::ParsePagePayload(parse_pos, &page_header.value(), table,
-                                &ds_config, &compact_buffer, &writer,
-                                &metadata);
-
+    CpuReader::ParsePage(page.get(), &filter, &writer, table, &metadata);
     metadata.Clear();
   }
 }
diff --git a/src/traced/probes/ftrace/cpu_reader_fuzzer.cc b/src/traced/probes/ftrace/cpu_reader_fuzzer.cc
index 61d5b80..0f79442 100644
--- a/src/traced/probes/ftrace/cpu_reader_fuzzer.cc
+++ b/src/traced/probes/ftrace/cpu_reader_fuzzer.cc
@@ -20,14 +20,12 @@
 #include <algorithm>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/utils.h"
 #include "perfetto/protozero/scattered_stream_null_delegate.h"
 #include "perfetto/protozero/scattered_stream_writer.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
 #include "src/traced/probes/ftrace/cpu_reader.h"
-#include "src/traced/probes/ftrace/ftrace_config_muxer.h"
-#include "src/traced/probes/ftrace/test/cpu_reader_support.h"
-#include "src/tracing/core/null_trace_writer.h"
+#include "test/cpu_reader_support.h"
 
 namespace perfetto {
 namespace {
@@ -40,8 +38,11 @@
 
 void FuzzCpuReaderParsePage(const uint8_t* data, size_t size);
 
-// TODO(rsavitski): make the fuzzer generate multi-page payloads.
-void FuzzCpuReaderProcessPagesForDataSource(const uint8_t* data, size_t size) {
+void FuzzCpuReaderParsePage(const uint8_t* data, size_t size) {
+  protozero::ScatteredStreamWriterNullDelegate delegate(base::kPageSize);
+  protozero::ScatteredStreamWriter stream(&delegate);
+  FtraceEventBundle writer;
+
   ProtoTranslationTable* table = GetTable("synthetic");
   if (!table) {
     PERFETTO_FATAL(
@@ -51,18 +52,15 @@
   memset(g_page, 0, base::kPageSize);
   memcpy(g_page, data, std::min(base::kPageSize, size));
 
-  FtraceMetadata metadata{};
-  FtraceDataSourceConfig ds_config{EventFilter{},
-                                   DisabledCompactSchedConfigForTesting()};
-  ds_config.event_filter.AddEnabledEvent(
+  EventFilter filter;
+  filter.AddEnabledEvent(
       table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
-  ds_config.event_filter.AddEnabledEvent(
+  filter.AddEnabledEvent(
       table->EventToFtraceId(GroupAndName("ftrace", "print")));
 
-  NullTraceWriter null_writer;
-  CpuReader::ProcessPagesForDataSource(&null_writer, &metadata, /*cpu=*/0,
-                                       &ds_config, g_page, /*pages_read=*/1,
-                                       table);
+  writer.Reset(&stream);
+  FtraceMetadata metadata{};
+  CpuReader::ParsePage(g_page, &filter, &writer, table, &metadata);
 }
 
 }  // namespace perfetto
@@ -70,6 +68,6 @@
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  perfetto::FuzzCpuReaderProcessPagesForDataSource(data, size);
+  perfetto::FuzzCpuReaderParsePage(data, size);
   return 0;
 }
diff --git a/src/traced/probes/ftrace/cpu_reader_unittest.cc b/src/traced/probes/ftrace/cpu_reader_unittest.cc
index f8b58cf..0631ecb 100644
--- a/src/traced/probes/ftrace/cpu_reader_unittest.cc
+++ b/src/traced/probes/ftrace/cpu_reader_unittest.cc
@@ -16,41 +16,41 @@
 
 #include "src/traced/probes/ftrace/cpu_reader.h"
 
-#include <string.h>
 #include <sys/stat.h>
 
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "src/traced/probes/ftrace/event_info.h"
+#include "src/traced/probes/ftrace/proto_translation_table.h"
+
 #include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/utils.h"
 #include "perfetto/protozero/proto_utils.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
 #include "perfetto/protozero/scattered_stream_writer.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event.pb.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pb.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-#include "src/traced/probes/ftrace/event_info.h"
-#include "src/traced/probes/ftrace/ftrace_config_muxer.h"
+
+#include "perfetto/trace/ftrace/ftrace_event.pb.h"
+#include "perfetto/trace/ftrace/ftrace_event.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace_event_bundle.pb.h"
+#include "perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
 #include "src/traced/probes/ftrace/ftrace_procfs.h"
-#include "src/traced/probes/ftrace/proto_translation_table.h"
 #include "src/traced/probes/ftrace/test/cpu_reader_support.h"
 #include "src/traced/probes/ftrace/test/test_messages.pb.h"
 #include "src/traced/probes/ftrace/test/test_messages.pbzero.h"
-#include "src/tracing/core/trace_writer_for_testing.h"
-#include "test/gtest_and_gmock.h"
 
-using protozero::proto_utils::ProtoSchemaType;
-using testing::_;
-using testing::AnyNumber;
-using testing::Contains;
 using testing::Each;
 using testing::ElementsAre;
 using testing::ElementsAreArray;
 using testing::EndsWith;
 using testing::Eq;
-using testing::NiceMock;
 using testing::Pair;
-using testing::Return;
 using testing::StartsWith;
+using testing::Contains;
+using testing::_;
+using testing::Return;
+using testing::AnyNumber;
+using testing::NiceMock;
+using protozero::proto_utils::ProtoSchemaType;
 
 namespace perfetto {
 
@@ -118,10 +118,8 @@
   std::unique_ptr<ProtoT> ParseProto() {
     auto bundle = std::unique_ptr<ProtoT>(new ProtoT());
     std::vector<uint8_t> buffer = delegate_.StitchSlices();
-    if (!bundle->ParseFromArray(buffer.data(),
-                                static_cast<int>(buffer.size()))) {
+    if (!bundle->ParseFromArray(buffer.data(), static_cast<int>(buffer.size())))
       return nullptr;
-    }
     return bundle;
   }
 
@@ -306,43 +304,6 @@
   EXPECT_EQ(actual, expected);
 }
 
-TEST(ParsePageHeaderTest, WithOverrun) {
-  std::string text = R"(
-    00000000: 3ef3 db77 67a2 0100 f00f 0080 ffff ffff
-    )";
-  auto page = PageFromXxd(text);
-
-  // parse as if we're on a 32 bit kernel (4 byte "commit" field)
-  {
-    const uint8_t* ptr = page.get();
-    auto ret = CpuReader::ParsePageHeader(&ptr, 4u);
-    ASSERT_TRUE(ret.has_value());
-    CpuReader::PageHeader parsed = ret.value();
-
-    ASSERT_EQ(parsed.timestamp, 0x0001A26777DBF33Eull);  // first 8 bytes
-    ASSERT_EQ(parsed.size, 0x0ff0u);                     // 4080
-    ASSERT_TRUE(parsed.lost_events);
-
-    // pointer advanced past the header (8+4 bytes)
-    ASSERT_EQ(ptr, page.get() + 12);
-  }
-
-  // parse as if we're on a 64 bit kernel (8 byte "commit" field)
-  {
-    const uint8_t* ptr = page.get();
-    auto ret = CpuReader::ParsePageHeader(&ptr, 8u);
-    ASSERT_TRUE(ret.has_value());
-    CpuReader::PageHeader parsed = ret.value();
-
-    ASSERT_EQ(parsed.timestamp, 0x0001A26777DBF33Eull);  // first 8 bytes
-    ASSERT_EQ(parsed.size, 0x0ff0u);                     // 4080
-    ASSERT_TRUE(parsed.lost_events);
-
-    // pointer advanced past the header (8+8 bytes)
-    ASSERT_EQ(ptr, page.get() + 16);
-  }
-}
-
 // clang-format off
 // # tracer: nop
 // #
@@ -375,32 +336,18 @@
   ProtoTranslationTable* table = GetTable(test_case->name);
   auto page = PageFromXxd(test_case->data);
 
-  FtraceDataSourceConfig ds_config{EventFilter{},
-                                   DisabledCompactSchedConfigForTesting()};
-  ds_config.event_filter.AddEnabledEvent(
+  EventFilter filter;
+  filter.AddEnabledEvent(
       table->EventToFtraceId(GroupAndName("ftrace", "print")));
 
   FtraceMetadata metadata{};
-  CompactSchedBuffer compact_buffer;
-  const uint8_t* parse_pos = page.get();
-  base::Optional<CpuReader::PageHeader> page_header =
-      CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
-
-  const uint8_t* page_end = page.get() + base::kPageSize;
-  ASSERT_TRUE(page_header.has_value());
-  EXPECT_EQ(44ul, page_header->size);
-  EXPECT_FALSE(page_header->lost_events);
-  EXPECT_TRUE(parse_pos < page_end);
-  EXPECT_TRUE(parse_pos + page_header->size < page_end);
-
-  size_t evt_bytes = CpuReader::ParsePagePayload(
-      parse_pos, &page_header.value(), table, &ds_config, &compact_buffer,
-      bundle_provider.writer(), &metadata);
-
-  EXPECT_EQ(evt_bytes, 44ul);
+  size_t bytes = CpuReader::ParsePage(
+      page.get(), &filter, bundle_provider.writer(), table, &metadata);
+  EXPECT_EQ(bytes, 60ul);
 
   auto bundle = bundle_provider.ParseProto();
   ASSERT_TRUE(bundle);
+  EXPECT_EQ(metadata.overwrite_count, 0ul);
   ASSERT_EQ(bundle->event().size(), 1);
   const protos::FtraceEvent& event = bundle->event().Get(0);
   EXPECT_EQ(event.pid(), 28712ul);
@@ -504,26 +451,13 @@
   ProtoTranslationTable* table = GetTable(test_case->name);
   auto page = PageFromXxd(test_case->data);
 
-  FtraceDataSourceConfig ds_config{EventFilter{},
-                                   DisabledCompactSchedConfigForTesting()};
-  ds_config.event_filter.AddEnabledEvent(
+  EventFilter filter;
+  filter.AddEnabledEvent(
       table->EventToFtraceId(GroupAndName("ftrace", "print")));
 
   FtraceMetadata metadata{};
-  CompactSchedBuffer compact_buffer;
-  const uint8_t* parse_pos = page.get();
-  base::Optional<CpuReader::PageHeader> page_header =
-      CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
-
-  const uint8_t* page_end = page.get() + base::kPageSize;
-  ASSERT_TRUE(page_header.has_value());
-  EXPECT_FALSE(page_header->lost_events);
-  EXPECT_TRUE(parse_pos < page_end);
-  EXPECT_TRUE(parse_pos + page_header->size < page_end);
-
-  CpuReader::ParsePagePayload(parse_pos, &page_header.value(), table,
-                              &ds_config, &compact_buffer,
-                              bundle_provider.writer(), &metadata);
+  CpuReader::ParsePage(page.get(), &filter, bundle_provider.writer(), table,
+                       &metadata);
 
   auto bundle = bundle_provider.ParseProto();
   ASSERT_TRUE(bundle);
@@ -554,31 +488,17 @@
   ProtoTranslationTable* table = GetTable(test_case->name);
   auto page = PageFromXxd(test_case->data);
 
-  FtraceDataSourceConfig ds_config{EventFilter{},
-                                   DisabledCompactSchedConfigForTesting()};
-  ds_config.event_filter.AddEnabledEvent(
+  EventFilter filter;
+  filter.AddEnabledEvent(
       table->EventToFtraceId(GroupAndName("ftrace", "print")));
 
   FtraceMetadata metadata{};
-  CompactSchedBuffer compact_buffer;
-  const uint8_t* parse_pos = page.get();
-  base::Optional<CpuReader::PageHeader> page_header =
-      CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
-
-  const uint8_t* page_end = page.get() + base::kPageSize;
-  ASSERT_TRUE(page_header.has_value());
-  EXPECT_FALSE(page_header->lost_events);
-  EXPECT_TRUE(parse_pos < page_end);
-  EXPECT_TRUE(parse_pos + page_header->size < page_end);
-
-  size_t evt_bytes = CpuReader::ParsePagePayload(
-      parse_pos, &page_header.value(), table, &ds_config, &compact_buffer,
-      bundle_provider.writer(), &metadata);
-
-  ASSERT_EQ(0u, evt_bytes);
+  ASSERT_FALSE(CpuReader::ParsePage(
+      page.get(), &filter, bundle_provider.writer(), table, &metadata));
 
   auto bundle = bundle_provider.ParseProto();
   ASSERT_TRUE(bundle);
+  EXPECT_EQ(metadata.overwrite_count, 0ul);
   ASSERT_EQ(bundle->event().size(), 1);
   // Although one field is malformed we still see data for the rest
   // since we write the fields as we parse them for speed.
@@ -595,26 +515,15 @@
   ProtoTranslationTable* table = GetTable(test_case->name);
   auto page = PageFromXxd(test_case->data);
 
-  FtraceDataSourceConfig ds_config{EventFilter{},
-                                   DisabledCompactSchedConfigForTesting()};
+  EventFilter filter;
 
   FtraceMetadata metadata{};
-  CompactSchedBuffer compact_buffer;
-  const uint8_t* parse_pos = page.get();
-  base::Optional<CpuReader::PageHeader> page_header =
-      CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
-
-  ASSERT_TRUE(page_header.has_value());
-  EXPECT_FALSE(page_header->lost_events);
-
-  size_t evt_bytes = CpuReader::ParsePagePayload(
-      parse_pos, &page_header.value(), table, &ds_config, &compact_buffer,
-      bundle_provider.writer(), &metadata);
-
-  EXPECT_LT(0u, evt_bytes);
+  ASSERT_TRUE(CpuReader::ParsePage(page.get(), &filter,
+                                   bundle_provider.writer(), table, &metadata));
 
   auto bundle = bundle_provider.ParseProto();
   ASSERT_TRUE(bundle);
+  EXPECT_EQ(metadata.overwrite_count, 0ul);
   ASSERT_EQ(bundle->event().size(), 0);
 }
 
@@ -659,31 +568,17 @@
   ProtoTranslationTable* table = GetTable(test_case->name);
   auto page = PageFromXxd(test_case->data);
 
-  FtraceDataSourceConfig ds_config{EventFilter{},
-                                   DisabledCompactSchedConfigForTesting()};
-  ds_config.event_filter.AddEnabledEvent(
+  EventFilter filter;
+  filter.AddEnabledEvent(
       table->EventToFtraceId(GroupAndName("ftrace", "print")));
 
   FtraceMetadata metadata{};
-  CompactSchedBuffer compact_buffer;
-  const uint8_t* parse_pos = page.get();
-  base::Optional<CpuReader::PageHeader> page_header =
-      CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
-
-  const uint8_t* page_end = page.get() + base::kPageSize;
-  ASSERT_TRUE(page_header.has_value());
-  EXPECT_FALSE(page_header->lost_events);
-  EXPECT_TRUE(parse_pos < page_end);
-  EXPECT_TRUE(parse_pos + page_header->size < page_end);
-
-  size_t evt_bytes = CpuReader::ParsePagePayload(
-      parse_pos, &page_header.value(), table, &ds_config, &compact_buffer,
-      bundle_provider.writer(), &metadata);
-
-  EXPECT_LT(0u, evt_bytes);
+  ASSERT_TRUE(CpuReader::ParsePage(page.get(), &filter,
+                                   bundle_provider.writer(), table, &metadata));
 
   auto bundle = bundle_provider.ParseProto();
   ASSERT_TRUE(bundle);
+  EXPECT_EQ(metadata.overwrite_count, 0ul);
   ASSERT_EQ(bundle->event().size(), 3);
 
   {
@@ -769,31 +664,17 @@
   ProtoTranslationTable* table = GetTable(test_case->name);
   auto page = PageFromXxd(test_case->data);
 
-  FtraceDataSourceConfig ds_config{EventFilter{},
-                                   DisabledCompactSchedConfigForTesting()};
-  ds_config.event_filter.AddEnabledEvent(
+  EventFilter filter;
+  filter.AddEnabledEvent(
       table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
 
   FtraceMetadata metadata{};
-  CompactSchedBuffer compact_buffer;
-  const uint8_t* parse_pos = page.get();
-  base::Optional<CpuReader::PageHeader> page_header =
-      CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
-
-  const uint8_t* page_end = page.get() + base::kPageSize;
-  ASSERT_TRUE(page_header.has_value());
-  EXPECT_FALSE(page_header->lost_events);
-  EXPECT_TRUE(parse_pos < page_end);
-  EXPECT_TRUE(parse_pos + page_header->size < page_end);
-
-  size_t evt_bytes = CpuReader::ParsePagePayload(
-      parse_pos, &page_header.value(), table, &ds_config, &compact_buffer,
-      bundle_provider.writer(), &metadata);
-
-  EXPECT_LT(0u, evt_bytes);
+  ASSERT_TRUE(CpuReader::ParsePage(page.get(), &filter,
+                                   bundle_provider.writer(), table, &metadata));
 
   auto bundle = bundle_provider.ParseProto();
   ASSERT_TRUE(bundle);
+  EXPECT_EQ(metadata.overwrite_count, 0ul);
   ASSERT_EQ(bundle->event().size(), 6);
 
   {
@@ -809,73 +690,6 @@
   }
 }
 
-TEST(CpuReaderTest, ParseSixSchedSwitchCompactFormat) {
-  const ExamplePage* test_case = &g_six_sched_switch;
-
-  BundleProvider bundle_provider(base::kPageSize);
-  ProtoTranslationTable* table = GetTable(test_case->name);
-  auto page = PageFromXxd(test_case->data);
-
-  FtraceDataSourceConfig ds_config{EventFilter{},
-                                   EnabledCompactSchedConfigForTesting()};
-  ds_config.event_filter.AddEnabledEvent(
-      table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
-
-  FtraceMetadata metadata{};
-  CompactSchedBuffer compact_buffer;
-  const uint8_t* parse_pos = page.get();
-  base::Optional<CpuReader::PageHeader> page_header =
-      CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
-
-  const uint8_t* page_end = page.get() + base::kPageSize;
-  ASSERT_TRUE(page_header.has_value());
-  EXPECT_FALSE(page_header->lost_events);
-  EXPECT_TRUE(parse_pos < page_end);
-  EXPECT_TRUE(parse_pos + page_header->size < page_end);
-
-  size_t evt_bytes = CpuReader::ParsePagePayload(
-      parse_pos, &page_header.value(), table, &ds_config, &compact_buffer,
-      bundle_provider.writer(), &metadata);
-
-  EXPECT_LT(0u, evt_bytes);
-
-  // Nothing written into the proto yet:
-  auto bundle = bundle_provider.ParseProto();
-  ASSERT_TRUE(bundle);
-  EXPECT_EQ(0, bundle->event().size());
-  EXPECT_FALSE(bundle->has_compact_sched());
-
-  // Instead, sched switch fields were buffered:
-  EXPECT_LT(0u, compact_buffer.sched_switch().size());
-  EXPECT_LT(0u, compact_buffer.interner().interned_comms_size());
-
-  // Write the buffer out & check the serialized format:
-  compact_buffer.WriteAndReset(bundle_provider.writer());
-  bundle_provider.writer()->Finalize();
-  bundle = bundle_provider.ParseProto();
-  ASSERT_TRUE(bundle);
-
-  const auto& compact_sched = bundle->compact_sched();
-
-  EXPECT_EQ(6, compact_sched.switch_timestamp().size());
-  EXPECT_EQ(6, compact_sched.switch_prev_state().size());
-  EXPECT_EQ(6, compact_sched.switch_next_pid().size());
-  EXPECT_EQ(6, compact_sched.switch_next_prio().size());
-  // 4 unique interned next_comm strings:
-  EXPECT_EQ(4, compact_sched.intern_table().size());
-  EXPECT_EQ(6, compact_sched.switch_next_comm_index().size());
-
-  // First event exactly as expected (absolute timestamp):
-  EXPECT_TRUE(
-      WithinOneMicrosecond(compact_sched.switch_timestamp(0), 1045157, 722134));
-  EXPECT_EQ(1, compact_sched.switch_prev_state(0));
-  EXPECT_EQ(3733, compact_sched.switch_next_pid(0));
-  EXPECT_EQ(120, compact_sched.switch_next_prio(0));
-  std::string next_comm = compact_sched.intern_table(
-      static_cast<int>(compact_sched.switch_next_comm_index(0)));
-  EXPECT_EQ("sleep", next_comm);
-}
-
 TEST_F(CpuReaderTableTest, ParseAllFields) {
   using FakeEventProvider =
       ProtoProvider<pbzero::FakeFtraceEvent, FakeFtraceEvent>;
@@ -1023,8 +837,7 @@
 
   ProtoTranslationTable table(
       &ftrace_, events, std::move(common_fields),
-      ProtoTranslationTable::DefaultPageHeaderSpecForTesting(),
-      InvalidCompactSchedEventFormatForTesting());
+      ProtoTranslationTable::DefaultPageHeaderSpecForTesting());
 
   FakeEventProvider provider(base::kPageSize);
 
@@ -1116,73 +929,6 @@
   EXPECT_THAT(metadata.pids, Contains(9999));
 }
 
-// Page with a single sched_switch, no data loss.
-static char g_switch_page[] =
-    R"(
-    00000000: 2b16 c3be 90b6 0300 4c00 0000 0000 0000  ................
-    00000010: 1e00 0000 0000 0000 1000 0000 2f00 0103  ................
-    00000020: 0300 0000 6b73 6f66 7469 7271 642f 3000  ................
-    00000030: 0000 0000 0300 0000 7800 0000 0100 0000  ................
-    00000040: 0000 0000 736c 6565 7000 722f 3000 0000  ................
-    00000050: 0000 0000 950e 0000 7800 0000 0000 0000  ................
-    )";
-
-// Page with a single sched_switch, header has data loss flag set.
-static char g_switch_page_lost_events[] =
-    R"(
-    00000000: 2b16 c3be 90b6 0300 4c00 0080 ffff ffff  ................
-    00000010: 1e00 0000 0000 0000 1000 0000 2f00 0103  ................
-    00000020: 0300 0000 6b73 6f66 7469 7271 642f 3000  ................
-    00000030: 0000 0000 0300 0000 7800 0000 0100 0000  ................
-    00000040: 0000 0000 736c 6565 7000 722f 3000 0000  ................
-    00000050: 0000 0000 950e 0000 7800 0000 0000 0000  ................
-    )";
-
-TEST(CpuReaderTest, NewPacketOnLostEvents) {
-  auto page_ok = PageFromXxd(g_switch_page);
-  auto page_loss = PageFromXxd(g_switch_page_lost_events);
-
-  std::vector<const void*> test_page_order = {
-      page_ok.get(),   page_ok.get(), page_ok.get(), page_loss.get(),
-      page_loss.get(), page_ok.get(), page_ok.get(), page_ok.get()};
-
-  // Prepare a buffer with 8 contiguous pages, with the above contents.
-  static constexpr size_t kTestPages = 8;
-  uint8_t buf[base::kPageSize * kTestPages] = {};
-  for (size_t i = 0; i < kTestPages; i++) {
-    void* dest = buf + (i * base::kPageSize);
-    memcpy(dest, static_cast<const void*>(test_page_order[i]), base::kPageSize);
-  }
-
-  BundleProvider bundle_provider(base::kPageSize);
-  ProtoTranslationTable* table = GetTable("synthetic");
-  FtraceMetadata metadata{};
-  FtraceDataSourceConfig ds_config{EventFilter{},
-                                   DisabledCompactSchedConfigForTesting()};
-  ds_config.event_filter.AddEnabledEvent(
-      table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
-
-  TraceWriterForTesting trace_writer;
-  CpuReader::ProcessPagesForDataSource(&trace_writer, &metadata, /*cpu=*/1,
-                                       &ds_config, buf, kTestPages, table);
-
-  // Each packet should contain the parsed contents of a contiguous run of pages
-  // without data loss.
-  // So we should get three packets (each page has 1 event):
-  //   [3 events] [1 event] [4 events].
-  std::vector<protos::TracePacket> packets = trace_writer.GetAllTracePackets();
-
-  ASSERT_EQ(3u, packets.size());
-  EXPECT_FALSE(packets[0].ftrace_events().lost_events());
-  EXPECT_EQ(3, packets[0].ftrace_events().event().size());
-
-  EXPECT_TRUE(packets[1].ftrace_events().lost_events());
-  EXPECT_EQ(1, packets[1].ftrace_events().event().size());
-
-  EXPECT_TRUE(packets[2].ftrace_events().lost_events());
-  EXPECT_EQ(4, packets[2].ftrace_events().event().size());
-}
-
 TEST(CpuReaderTest, TranslateBlockDeviceIDToUserspace) {
   const uint32_t kKernelBlockDeviceId = 271581216;
   const BlockDeviceID kUserspaceBlockDeviceId = 66336;
@@ -1615,31 +1361,17 @@
   ProtoTranslationTable* table = GetTable(test_case->name);
   auto page = PageFromXxd(test_case->data);
 
-  FtraceDataSourceConfig ds_config{EventFilter{},
-                                   DisabledCompactSchedConfigForTesting()};
-  ds_config.event_filter.AddEnabledEvent(
+  EventFilter filter;
+  filter.AddEnabledEvent(
       table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
 
   FtraceMetadata metadata{};
-  CompactSchedBuffer compact_buffer;
-  const uint8_t* parse_pos = page.get();
-  base::Optional<CpuReader::PageHeader> page_header =
-      CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
-
-  const uint8_t* page_end = page.get() + base::kPageSize;
-  ASSERT_TRUE(page_header.has_value());
-  EXPECT_FALSE(page_header->lost_events);
-  EXPECT_TRUE(parse_pos < page_end);
-  EXPECT_TRUE(parse_pos + page_header->size < page_end);
-
-  size_t evt_bytes = CpuReader::ParsePagePayload(
-      parse_pos, &page_header.value(), table, &ds_config, &compact_buffer,
-      bundle_provider.writer(), &metadata);
-
-  EXPECT_LT(0u, evt_bytes);
+  ASSERT_TRUE(CpuReader::ParsePage(page.get(), &filter,
+                                   bundle_provider.writer(), table, &metadata));
 
   auto bundle = bundle_provider.ParseProto();
   ASSERT_TRUE(bundle);
+  EXPECT_EQ(metadata.overwrite_count, 0ul);
   EXPECT_EQ(bundle->event().size(), 59);
 }
 
@@ -2060,31 +1792,17 @@
   ProtoTranslationTable* table = GetTable(test_case->name);
   auto page = PageFromXxd(test_case->data);
 
-  FtraceDataSourceConfig ds_config{EventFilter{},
-                                   DisabledCompactSchedConfigForTesting()};
-  ds_config.event_filter.AddEnabledEvent(
+  EventFilter filter;
+  filter.AddEnabledEvent(
       table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
 
   FtraceMetadata metadata{};
-  CompactSchedBuffer compact_buffer;
-  const uint8_t* parse_pos = page.get();
-  base::Optional<CpuReader::PageHeader> page_header =
-      CpuReader::ParsePageHeader(&parse_pos, table->page_header_size_len());
-
-  const uint8_t* page_end = page.get() + base::kPageSize;
-  ASSERT_TRUE(page_header.has_value());
-  EXPECT_TRUE(page_header->lost_events);  // data loss
-  EXPECT_TRUE(parse_pos < page_end);
-  EXPECT_TRUE(parse_pos + page_header->size < page_end);
-
-  size_t evt_bytes = CpuReader::ParsePagePayload(
-      parse_pos, &page_header.value(), table, &ds_config, &compact_buffer,
-      bundle_provider.writer(), &metadata);
-
-  EXPECT_LT(0u, evt_bytes);
+  ASSERT_TRUE(CpuReader::ParsePage(page.get(), &filter,
+                                   bundle_provider.writer(), table, &metadata));
 
   auto bundle = bundle_provider.ParseProto();
   ASSERT_TRUE(bundle);
+  EXPECT_EQ(metadata.overwrite_count, 192ul);
 }
 
 }  // namespace perfetto
diff --git a/src/traced/probes/ftrace/cpu_stats_parser.cc b/src/traced/probes/ftrace/cpu_stats_parser.cc
index 65745ca..8048ee1 100644
--- a/src/traced/probes/ftrace/cpu_stats_parser.cc
+++ b/src/traced/probes/ftrace/cpu_stats_parser.cc
@@ -16,8 +16,8 @@
 
 #include "src/traced/probes/ftrace/cpu_stats_parser.h"
 
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/ext/base/string_utils.h"
+#include "perfetto/base/string_splitter.h"
+#include "perfetto/base/string_utils.h"
 #include "src/traced/probes/ftrace/ftrace_controller.h"
 #include "src/traced/probes/ftrace/ftrace_procfs.h"
 #include "src/traced/probes/ftrace/ftrace_stats.h"
diff --git a/src/traced/probes/ftrace/cpu_stats_parser_unittest.cc b/src/traced/probes/ftrace/cpu_stats_parser_unittest.cc
index f10b335..f016f19 100644
--- a/src/traced/probes/ftrace/cpu_stats_parser_unittest.cc
+++ b/src/traced/probes/ftrace/cpu_stats_parser_unittest.cc
@@ -1,8 +1,10 @@
 #include "src/traced/probes/ftrace/cpu_stats_parser.h"
 
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
 #include "src/traced/probes/ftrace/ftrace_controller.h"
 #include "src/traced/probes/ftrace/ftrace_stats.h"
-#include "test/gtest_and_gmock.h"
 
 namespace perfetto {
 namespace {
@@ -21,14 +23,14 @@
   FtraceCpuStats stats{};
   EXPECT_TRUE(DumpCpuStats(text, &stats));
 
-  EXPECT_EQ(stats.entries, 1u);
-  EXPECT_EQ(stats.overrun, 2u);
-  EXPECT_EQ(stats.commit_overrun, 3u);
-  EXPECT_EQ(stats.bytes_read, 4u);
-  EXPECT_DOUBLE_EQ(stats.oldest_event_ts, 5123.0);
-  EXPECT_DOUBLE_EQ(stats.now_ts, 6123.123);
-  EXPECT_EQ(stats.dropped_events, 7u);
-  EXPECT_EQ(stats.read_events, 8u);
+  EXPECT_EQ(stats.entries, 1);
+  EXPECT_EQ(stats.overrun, 2);
+  EXPECT_EQ(stats.commit_overrun, 3);
+  EXPECT_EQ(stats.bytes_read, 4);
+  EXPECT_EQ(stats.oldest_event_ts, 5123.000);
+  EXPECT_EQ(stats.now_ts, 6123.123);
+  EXPECT_EQ(stats.dropped_events, 7);
+  EXPECT_EQ(stats.read_events, 8);
 }
 
 }  // namespace
diff --git a/src/traced/probes/ftrace/event_info.cc b/src/traced/probes/ftrace/event_info.cc
index b4b108b..657a459 100644
--- a/src/traced/probes/ftrace/event_info.cc
+++ b/src/traced/probes/ftrace/event_info.cc
@@ -10,6140 +10,4036 @@
 using protozero::proto_utils::ProtoSchemaType;
 
 std::vector<Event> GetStaticEventInfo() {
-  static constexpr uint16_t kUnsetOffset = 0;
-  static constexpr uint16_t kUnsetSize = 0;
-  static constexpr uint16_t kUnsetFtraceId = 0;
-  return {
-      {"binder_transaction",
-       "binder",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "debug_id", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "target_node", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "to_proc", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "to_thread", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "reply", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "code", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       50,
-       kUnsetSize},
-      {"binder_transaction_received",
-       "binder",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "debug_id", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       51,
-       kUnsetSize},
-      {"binder_set_priority",
-       "binder",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "proc", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "thread", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "old_prio", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "new_prio", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "desired_prio", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       52,
-       kUnsetSize},
-      {"binder_lock",
-       "binder",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "tag", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       53,
-       kUnsetSize},
-      {"binder_locked",
-       "binder",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "tag", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       54,
-       kUnsetSize},
-      {"binder_unlock",
-       "binder",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "tag", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       55,
-       kUnsetSize},
-      {"binder_transaction_alloc_buf",
-       "binder",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "data_size", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "debug_id", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "offsets_size", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       323,
-       kUnsetSize},
-      {"block_rq_issue",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sector", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_sector", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bytes", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rwbs", 5, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 6, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cmd", 7, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       45,
-       kUnsetSize},
-      {"block_bio_backmerge",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sector", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_sector", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rwbs", 4, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 5, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       115,
-       kUnsetSize},
-      {"block_bio_bounce",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sector", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_sector", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rwbs", 4, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 5, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       116,
-       kUnsetSize},
-      {"block_bio_complete",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sector", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_sector", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "error", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rwbs", 5, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       117,
-       kUnsetSize},
-      {"block_bio_frontmerge",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sector", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_sector", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rwbs", 4, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 5, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       118,
-       kUnsetSize},
-      {"block_bio_queue",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sector", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_sector", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rwbs", 4, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 5, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       119,
-       kUnsetSize},
-      {"block_bio_remap",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sector", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_sector", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "old_dev", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "old_sector", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rwbs", 6, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       120,
-       kUnsetSize},
-      {"block_dirty_buffer",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sector", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "size", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       121,
-       kUnsetSize},
-      {"block_getrq",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sector", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_sector", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rwbs", 4, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 5, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       122,
-       kUnsetSize},
-      {"block_plug",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       123,
-       kUnsetSize},
-      {"block_rq_abort",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sector", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_sector", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "errors", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rwbs", 5, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cmd", 6, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       124,
-       kUnsetSize},
-      {"block_rq_complete",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sector", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_sector", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "errors", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rwbs", 5, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cmd", 6, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       125,
-       kUnsetSize},
-      {"block_rq_insert",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sector", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_sector", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bytes", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rwbs", 5, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 6, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cmd", 7, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       126,
-       kUnsetSize},
-      {"block_rq_remap",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sector", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_sector", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "old_dev", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "old_sector", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_bios", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rwbs", 7, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       128,
-       kUnsetSize},
-      {"block_rq_requeue",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sector", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_sector", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "errors", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rwbs", 5, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cmd", 6, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       129,
-       kUnsetSize},
-      {"block_sleeprq",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sector", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_sector", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rwbs", 4, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 5, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       130,
-       kUnsetSize},
-      {"block_split",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sector", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "new_sector", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rwbs", 4, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 5, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       131,
-       kUnsetSize},
-      {"block_touch_buffer",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sector", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "size", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       132,
-       kUnsetSize},
-      {"block_unplug",
-       "block",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_rq", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 2, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       133,
-       kUnsetSize},
-      {"cgroup_attach_task",
-       "cgroup",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dst_root", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dst_id", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 4, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cname", 5, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       67,
-       kUnsetSize},
-      {"cgroup_mkdir",
-       "cgroup",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "root", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "id", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cname", 3, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       68,
-       kUnsetSize},
-      {"cgroup_remount",
-       "cgroup",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "root", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ss_mask", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 3, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       69,
-       kUnsetSize},
-      {"cgroup_rmdir",
-       "cgroup",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "root", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "id", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cname", 3, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       70,
-       kUnsetSize},
-      {"cgroup_transfer_tasks",
-       "cgroup",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dst_root", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dst_id", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 4, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cname", 5, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       71,
-       kUnsetSize},
-      {"cgroup_destroy_root",
-       "cgroup",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "root", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ss_mask", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 3, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       72,
-       kUnsetSize},
-      {"cgroup_release",
-       "cgroup",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "root", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "id", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cname", 3, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       73,
-       kUnsetSize},
-      {"cgroup_rename",
-       "cgroup",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "root", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "id", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cname", 3, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       74,
-       kUnsetSize},
-      {"cgroup_setup_root",
-       "cgroup",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "root", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ss_mask", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 3, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       75,
-       kUnsetSize},
-      {"clk_enable",
-       "clk",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       320,
-       kUnsetSize},
-      {"clk_disable",
-       "clk",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       321,
-       kUnsetSize},
-      {"clk_set_rate",
-       "clk",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rate", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       322,
-       kUnsetSize},
-      {"mm_compaction_begin",
-       "compaction",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "zone_start", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "migrate_pfn", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "free_pfn", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "zone_end", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sync", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       99,
-       kUnsetSize},
-      {"mm_compaction_defer_compaction",
-       "compaction",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nid", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "idx", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "considered", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "defer_shift", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order_failed", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       100,
-       kUnsetSize},
-      {"mm_compaction_deferred",
-       "compaction",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nid", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "idx", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "considered", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "defer_shift", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order_failed", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       101,
-       kUnsetSize},
-      {"mm_compaction_defer_reset",
-       "compaction",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nid", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "idx", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "considered", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "defer_shift", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order_failed", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       102,
-       kUnsetSize},
-      {"mm_compaction_end",
-       "compaction",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "zone_start", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "migrate_pfn", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "free_pfn", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "zone_end", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sync", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "status", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       103,
-       kUnsetSize},
-      {"mm_compaction_finished",
-       "compaction",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nid", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "idx", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       104,
-       kUnsetSize},
-      {"mm_compaction_isolate_freepages",
-       "compaction",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "start_pfn", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "end_pfn", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_scanned", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_taken", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       105,
-       kUnsetSize},
-      {"mm_compaction_isolate_migratepages",
-       "compaction",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "start_pfn", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "end_pfn", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_scanned", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_taken", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       106,
-       kUnsetSize},
-      {"mm_compaction_kcompactd_sleep",
-       "compaction",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nid", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       107,
-       kUnsetSize},
-      {"mm_compaction_kcompactd_wake",
-       "compaction",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nid", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "classzone_idx", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       108,
-       kUnsetSize},
-      {"mm_compaction_migratepages",
-       "compaction",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_migrated", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_failed", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       109,
-       kUnsetSize},
-      {"mm_compaction_suitable",
-       "compaction",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nid", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "idx", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       110,
-       kUnsetSize},
-      {"mm_compaction_try_to_compact_pages",
-       "compaction",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "gfp_mask", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       111,
-       kUnsetSize},
-      {"mm_compaction_wakeup_kcompactd",
-       "compaction",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nid", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "classzone_idx", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       112,
-       kUnsetSize},
-      {"ext4_da_write_begin",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pos", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       41,
-       kUnsetSize},
-      {"ext4_da_write_end",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pos", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "copied", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       42,
-       kUnsetSize},
-      {"ext4_sync_file_enter",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "parent", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "datasync", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       43,
-       kUnsetSize},
-      {"ext4_sync_file_exit",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       44,
-       kUnsetSize},
-      {"ext4_alloc_da_blocks",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "data_blocks", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "meta_blocks", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       134,
-       kUnsetSize},
-      {"ext4_allocate_blocks",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "block", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "logical", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lleft", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lright", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "goal", 8, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pleft", 9, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pright", 10, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 11, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       135,
-       kUnsetSize},
-      {"ext4_allocate_inode",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dir", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       136,
-       kUnsetSize},
-      {"ext4_begin_ordered_truncate",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "new_size", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       137,
-       kUnsetSize},
-      {"ext4_collapse_range",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "offset", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       138,
-       kUnsetSize},
-      {"ext4_da_release_space",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "i_blocks", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "freed_blocks", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "reserved_data_blocks", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "reserved_meta_blocks", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "allocated_meta_blocks", 7, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 8, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       139,
-       kUnsetSize},
-      {"ext4_da_reserve_space",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "i_blocks", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "reserved_data_blocks", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "reserved_meta_blocks", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "md_needed", 7, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       140,
-       kUnsetSize},
-      {"ext4_da_update_reserve_space",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "i_blocks", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "used_blocks", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "reserved_data_blocks", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "reserved_meta_blocks", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "allocated_meta_blocks", 7, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "quota_claim", 8, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 9, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       141,
-       kUnsetSize},
-      {"ext4_da_write_pages",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "first_page", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_to_write", 4, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sync_mode", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "b_blocknr", 6, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "b_size", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "b_state", 8, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "io_done", 9, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pages_written", 10, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       142,
-       kUnsetSize},
-      {"ext4_da_write_pages_extent",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       143,
-       kUnsetSize},
-      {"ext4_direct_IO_enter",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pos", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rw", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       144,
-       kUnsetSize},
-      {"ext4_direct_IO_exit",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pos", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rw", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       145,
-       kUnsetSize},
-      {"ext4_discard_blocks",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "blk", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "count", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       146,
-       kUnsetSize},
-      {"ext4_discard_preallocations",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       147,
-       kUnsetSize},
-      {"ext4_drop_inode",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "drop", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       148,
-       kUnsetSize},
-      {"ext4_es_cache_extent",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pblk", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "status", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       149,
-       kUnsetSize},
-      {"ext4_es_find_delayed_extent_range_enter",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       150,
-       kUnsetSize},
-      {"ext4_es_find_delayed_extent_range_exit",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pblk", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "status", 6, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       151,
-       kUnsetSize},
-      {"ext4_es_insert_extent",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pblk", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "status", 6, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       152,
-       kUnsetSize},
-      {"ext4_es_lookup_extent_enter",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       153,
-       kUnsetSize},
-      {"ext4_es_lookup_extent_exit",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pblk", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "status", 6, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "found", 7, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       154,
-       kUnsetSize},
-      {"ext4_es_remove_extent",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       155,
-       kUnsetSize},
-      {"ext4_es_shrink",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_shrunk", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "scan_time", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_skipped", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "retried", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       156,
-       kUnsetSize},
-      {"ext4_es_shrink_count",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_to_scan", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cache_cnt", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       157,
-       kUnsetSize},
-      {"ext4_es_shrink_scan_enter",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_to_scan", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cache_cnt", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       158,
-       kUnsetSize},
-      {"ext4_es_shrink_scan_exit",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_shrunk", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cache_cnt", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       159,
-       kUnsetSize},
-      {"ext4_evict_inode",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nlink", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       160,
-       kUnsetSize},
-      {"ext4_ext_convert_to_initialized_enter",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "m_lblk", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "m_len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "u_lblk", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "u_len", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "u_pblk", 7, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       161,
-       kUnsetSize},
-      {"ext4_ext_convert_to_initialized_fastpath",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "m_lblk", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "m_len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "u_lblk", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "u_len", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "u_pblk", 7, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "i_lblk", 8, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "i_len", 9, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "i_pblk", 10, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       162,
-       kUnsetSize},
-      {"ext4_ext_handle_unwritten_extents",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pblk", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "allocated", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "newblk", 8, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       163,
-       kUnsetSize},
-      {"ext4_ext_in_cache",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       164,
-       kUnsetSize},
-      {"ext4_ext_load_extent",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pblk", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       165,
-       kUnsetSize},
-      {"ext4_ext_map_blocks_enter",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       166,
-       kUnsetSize},
-      {"ext4_ext_map_blocks_exit",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pblk", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mflags", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 8, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       167,
-       kUnsetSize},
-      {"ext4_ext_put_in_cache",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "start", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       168,
-       kUnsetSize},
-      {"ext4_ext_remove_space",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "start", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "end", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "depth", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       169,
-       kUnsetSize},
-      {"ext4_ext_remove_space_done",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "start", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "end", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "depth", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "partial", 6, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "eh_entries", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       170,
-       kUnsetSize},
-      {"ext4_ext_rm_idx",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pblk", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       171,
-       kUnsetSize},
-      {"ext4_ext_rm_leaf",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "partial", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "start", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ee_lblk", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ee_pblk", 6, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ee_len", 7, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       172,
-       kUnsetSize},
-      {"ext4_ext_show_extent",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pblk", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       173,
-       kUnsetSize},
-      {"ext4_fallocate_enter",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "offset", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pos", 6, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       174,
-       kUnsetSize},
-      {"ext4_fallocate_exit",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pos", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "blocks", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       175,
-       kUnsetSize},
-      {"ext4_find_delalloc_range",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "from", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "to", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "reverse", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "found", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "found_blk", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       176,
-       kUnsetSize},
-      {"ext4_forget",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "block", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "is_metadata", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       177,
-       kUnsetSize},
-      {"ext4_free_blocks",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "block", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "count", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       178,
-       kUnsetSize},
-      {"ext4_free_inode",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "uid", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "gid", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "blocks", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       179,
-       kUnsetSize},
-      {"ext4_get_implied_cluster_alloc_exit",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pblk", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       180,
-       kUnsetSize},
-      {"ext4_get_reserved_cluster_alloc",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       181,
-       kUnsetSize},
-      {"ext4_ind_map_blocks_enter",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       182,
-       kUnsetSize},
-      {"ext4_ind_map_blocks_exit",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pblk", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lblk", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mflags", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 8, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       183,
-       kUnsetSize},
-      {"ext4_insert_range",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "offset", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       184,
-       kUnsetSize},
-      {"ext4_invalidatepage",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "index", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "offset", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "length", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       185,
-       kUnsetSize},
-      {"ext4_journal_start",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ip", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "blocks", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rsv_blocks", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nblocks", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       186,
-       kUnsetSize},
-      {"ext4_journal_start_reserved",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ip", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "blocks", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       187,
-       kUnsetSize},
-      {"ext4_journalled_invalidatepage",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "index", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "offset", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "length", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       188,
-       kUnsetSize},
-      {"ext4_journalled_write_end",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pos", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "copied", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       189,
-       kUnsetSize},
-      {"ext4_load_inode",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       190,
-       kUnsetSize},
-      {"ext4_load_inode_bitmap",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "group", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       191,
-       kUnsetSize},
-      {"ext4_mark_inode_dirty",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ip", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       192,
-       kUnsetSize},
-      {"ext4_mb_bitmap_load",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "group", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       193,
-       kUnsetSize},
-      {"ext4_mb_buddy_bitmap_load",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "group", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       194,
-       kUnsetSize},
-      {"ext4_mb_discard_preallocations",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "needed", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       195,
-       kUnsetSize},
-      {"ext4_mb_new_group_pa",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pa_pstart", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pa_lstart", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pa_len", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       196,
-       kUnsetSize},
-      {"ext4_mb_new_inode_pa",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pa_pstart", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pa_lstart", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pa_len", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       197,
-       kUnsetSize},
-      {"ext4_mb_release_group_pa",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pa_pstart", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pa_len", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       198,
-       kUnsetSize},
-      {"ext4_mb_release_inode_pa",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "block", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "count", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       199,
-       kUnsetSize},
-      {"ext4_mballoc_alloc",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "orig_logical", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "orig_start", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "orig_group", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "orig_len", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "goal_logical", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "goal_start", 8, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "goal_group", 9, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "goal_len", 10, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "result_logical", 11, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "result_start", 12, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "result_group", 13, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "result_len", 14, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "found", 15, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "groups", 16, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "buddy", 17, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 18, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "tail", 19, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cr", 20, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       200,
-       kUnsetSize},
-      {"ext4_mballoc_discard",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "result_start", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "result_group", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "result_len", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       201,
-       kUnsetSize},
-      {"ext4_mballoc_free",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "result_start", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "result_group", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "result_len", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       202,
-       kUnsetSize},
-      {"ext4_mballoc_prealloc",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "orig_logical", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "orig_start", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "orig_group", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "orig_len", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "result_logical", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "result_start", 8, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "result_group", 9, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "result_len", 10, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       203,
-       kUnsetSize},
-      {"ext4_other_inode_update_time",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "orig_ino", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "uid", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "gid", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       204,
-       kUnsetSize},
-      {"ext4_punch_hole",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "offset", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       205,
-       kUnsetSize},
-      {"ext4_read_block_bitmap_load",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "group", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       206,
-       kUnsetSize},
-      {"ext4_readpage",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "index", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       207,
-       kUnsetSize},
-      {"ext4_releasepage",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "index", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       208,
-       kUnsetSize},
-      {"ext4_remove_blocks",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "from", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "to", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "partial", 5, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ee_pblk", 6, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ee_lblk", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ee_len", 8, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       209,
-       kUnsetSize},
-      {"ext4_request_blocks",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "logical", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lleft", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lright", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "goal", 7, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pleft", 8, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pright", 9, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 10, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       210,
-       kUnsetSize},
-      {"ext4_request_inode",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dir", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       211,
-       kUnsetSize},
-      {"ext4_sync_fs",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "wait", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       212,
-       kUnsetSize},
-      {"ext4_trim_all_free",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev_major", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev_minor", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "group", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "start", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       213,
-       kUnsetSize},
-      {"ext4_trim_extent",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev_major", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev_minor", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "group", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "start", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       214,
-       kUnsetSize},
-      {"ext4_truncate_enter",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "blocks", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       215,
-       kUnsetSize},
-      {"ext4_truncate_exit",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "blocks", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       216,
-       kUnsetSize},
-      {"ext4_unlink_enter",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "parent", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "size", 4, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       217,
-       kUnsetSize},
-      {"ext4_unlink_exit",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       218,
-       kUnsetSize},
-      {"ext4_write_begin",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pos", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       219,
-       kUnsetSize},
-      {"ext4_write_end",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pos", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "copied", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       230,
-       kUnsetSize},
-      {"ext4_writepage",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "index", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       231,
-       kUnsetSize},
-      {"ext4_writepages",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_to_write", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pages_skipped", 4, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "range_start", 5, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "range_end", 6, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "writeback_index", 7, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sync_mode", 8, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "for_kupdate", 9, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "range_cyclic", 10, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       232,
-       kUnsetSize},
-      {"ext4_writepages_result",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pages_written", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pages_skipped", 5, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "writeback_index", 6, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sync_mode", 7, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       233,
-       kUnsetSize},
-      {"ext4_zero_range",
-       "ext4",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "offset", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       234,
-       kUnsetSize},
-      {"f2fs_do_submit_bio",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "btype", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sync", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sector", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "size", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       243,
-       kUnsetSize},
-      {"f2fs_evict_inode",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pino", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "size", 5, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nlink", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "blocks", 7, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "advise", 8, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       244,
-       kUnsetSize},
-      {"f2fs_fallocate",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "offset", 4, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 5, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "size", 6, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "blocks", 7, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 8, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       245,
-       kUnsetSize},
-      {"f2fs_get_data_block",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "iblock", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bh_start", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bh_size", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       246,
-       kUnsetSize},
-      {"f2fs_get_victim",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "type", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "gc_type", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "alloc_mode", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "gc_mode", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "victim", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ofs_unit", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pre_victim", 8, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "prefree", 9, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "free", 10, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       247,
-       kUnsetSize},
-      {"f2fs_iget",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pino", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "size", 5, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nlink", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "blocks", 7, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "advise", 8, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       248,
-       kUnsetSize},
-      {"f2fs_iget_exit",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       249,
-       kUnsetSize},
-      {"f2fs_new_inode",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       250,
-       kUnsetSize},
-      {"f2fs_readpage",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "index", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "blkaddr", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "type", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       251,
-       kUnsetSize},
-      {"f2fs_reserve_new_block",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nid", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ofs_in_node", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       252,
-       kUnsetSize},
-      {"f2fs_set_page_dirty",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "type", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dir", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "index", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dirty", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       253,
-       kUnsetSize},
-      {"f2fs_submit_write_page",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "type", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "index", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "block", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       254,
-       kUnsetSize},
-      {"f2fs_sync_file_enter",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pino", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "size", 5, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nlink", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "blocks", 7, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "advise", 8, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       255,
-       kUnsetSize},
-      {"f2fs_sync_file_exit",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "need_cp", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "datasync", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       256,
-       kUnsetSize},
-      {"f2fs_sync_fs",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dirty", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "wait", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       257,
-       kUnsetSize},
-      {"f2fs_truncate",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pino", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "size", 5, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nlink", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "blocks", 7, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "advise", 8, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       258,
-       kUnsetSize},
-      {"f2fs_truncate_blocks_enter",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "size", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "blocks", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "from", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       259,
-       kUnsetSize},
-      {"f2fs_truncate_blocks_exit",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       260,
-       kUnsetSize},
-      {"f2fs_truncate_data_blocks_range",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nid", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ofs", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "free", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       261,
-       kUnsetSize},
-      {"f2fs_truncate_inode_blocks_enter",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "size", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "blocks", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "from", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       262,
-       kUnsetSize},
-      {"f2fs_truncate_inode_blocks_exit",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       263,
-       kUnsetSize},
-      {"f2fs_truncate_node",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nid", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "blk_addr", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       264,
-       kUnsetSize},
-      {"f2fs_truncate_nodes_enter",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nid", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "blk_addr", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       265,
-       kUnsetSize},
-      {"f2fs_truncate_nodes_exit",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       266,
-       kUnsetSize},
-      {"f2fs_truncate_partial_nodes",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nid", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "depth", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "err", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       267,
-       kUnsetSize},
-      {"f2fs_unlink_enter",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "size", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "blocks", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 5, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       268,
-       kUnsetSize},
-      {"f2fs_unlink_exit",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       269,
-       kUnsetSize},
-      {"f2fs_vm_page_mkwrite",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "type", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dir", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "index", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dirty", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       270,
-       kUnsetSize},
-      {"f2fs_write_begin",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pos", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       271,
-       kUnsetSize},
-      {"f2fs_write_checkpoint",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "is_umount", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "msg", 3, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       272,
-       kUnsetSize},
-      {"f2fs_write_end",
-       "f2fs",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dev", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pos", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "copied", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       273,
-       kUnsetSize},
-      {"fence_init",
-       "fence",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "context", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "driver", 2, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "seqno", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "timeline", 4, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       316,
-       kUnsetSize},
-      {"fence_destroy",
-       "fence",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "context", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "driver", 2, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "seqno", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "timeline", 4, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       317,
-       kUnsetSize},
-      {"fence_enable_signal",
-       "fence",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "context", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "driver", 2, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "seqno", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "timeline", 4, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       318,
-       kUnsetSize},
-      {"fence_signaled",
-       "fence",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "context", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "driver", 2, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "seqno", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "timeline", 4, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       319,
-       kUnsetSize},
-      {"mm_filemap_add_to_page_cache",
-       "filemap",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pfn", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "i_ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "index", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "s_dev", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "page", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       97,
-       kUnsetSize},
-      {"mm_filemap_delete_from_page_cache",
-       "filemap",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pfn", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "i_ino", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "index", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "s_dev", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "page", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       98,
-       kUnsetSize},
-      {"print",
-       "ftrace",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ip", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "buf", 2, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       3,
-       kUnsetSize},
-      {"i2c_read",
-       "i2c",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "adapter_nr", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "msg_nr", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "addr", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       27,
-       kUnsetSize},
-      {"i2c_write",
-       "i2c",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "adapter_nr", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "msg_nr", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "addr", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "buf", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       28,
-       kUnsetSize},
-      {"i2c_result",
-       "i2c",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "adapter_nr", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_msgs", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       29,
-       kUnsetSize},
-      {"i2c_reply",
-       "i2c",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "adapter_nr", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "msg_nr", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "addr", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "buf", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       30,
-       kUnsetSize},
-      {"smbus_read",
-       "i2c",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "adapter_nr", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "addr", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "command", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "protocol", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       31,
-       kUnsetSize},
-      {"smbus_write",
-       "i2c",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "adapter_nr", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "addr", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "command", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "protocol", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       32,
-       kUnsetSize},
-      {"smbus_result",
-       "i2c",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "adapter_nr", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "addr", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "read_write", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "command", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "res", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "protocol", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       33,
-       kUnsetSize},
-      {"smbus_reply",
-       "i2c",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "adapter_nr", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "addr", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "command", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "protocol", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       34,
-       kUnsetSize},
-      {"ipi_entry",
-       "ipi",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "reason", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       21,
-       kUnsetSize},
-      {"ipi_exit",
-       "ipi",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "reason", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       22,
-       kUnsetSize},
-      {"ipi_raise",
-       "ipi",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "target_cpus", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "reason", 2, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       23,
-       kUnsetSize},
-      {"softirq_entry",
-       "irq",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "vec", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       24,
-       kUnsetSize},
-      {"softirq_exit",
-       "irq",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "vec", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       25,
-       kUnsetSize},
-      {"softirq_raise",
-       "irq",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "vec", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       26,
-       kUnsetSize},
-      {"irq_handler_entry",
-       "irq",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "irq", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 2, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "handler", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       36,
-       kUnsetSize},
-      {"irq_handler_exit",
-       "irq",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "irq", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       37,
-       kUnsetSize},
-      {"alloc_pages_iommu_end",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "gfp_flags", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       274,
-       kUnsetSize},
-      {"alloc_pages_iommu_fail",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "gfp_flags", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       275,
-       kUnsetSize},
-      {"alloc_pages_iommu_start",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "gfp_flags", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       276,
-       kUnsetSize},
-      {"alloc_pages_sys_end",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "gfp_flags", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       277,
-       kUnsetSize},
-      {"alloc_pages_sys_fail",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "gfp_flags", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       278,
-       kUnsetSize},
-      {"alloc_pages_sys_start",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "gfp_flags", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       279,
-       kUnsetSize},
-      {"dma_alloc_contiguous_retry",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "tries", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       280,
-       kUnsetSize},
-      {"iommu_map_range",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "chunk_size", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pa", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "va", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       281,
-       kUnsetSize},
-      {"iommu_sec_ptbl_map_range_end",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "num", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pa", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sec_id", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "va", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       282,
-       kUnsetSize},
-      {"iommu_sec_ptbl_map_range_start",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "num", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pa", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sec_id", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "va", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       283,
-       kUnsetSize},
-      {"ion_alloc_buffer_end",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "client_name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "heap_name", 3, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mask", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       284,
-       kUnsetSize},
-      {"ion_alloc_buffer_fail",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "client_name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "error", 2, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "heap_name", 4, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mask", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       285,
-       kUnsetSize},
-      {"ion_alloc_buffer_fallback",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "client_name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "error", 2, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "heap_name", 4, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mask", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       286,
-       kUnsetSize},
-      {"ion_alloc_buffer_start",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "client_name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "heap_name", 3, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mask", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       287,
-       kUnsetSize},
-      {"ion_cp_alloc_retry",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "tries", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       288,
-       kUnsetSize},
-      {"ion_cp_secure_buffer_end",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "align", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "heap_name", 3, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       289,
-       kUnsetSize},
-      {"ion_cp_secure_buffer_start",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "align", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "heap_name", 3, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       290,
-       kUnsetSize},
-      {"ion_prefetching",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       291,
-       kUnsetSize},
-      {"ion_secure_cma_add_to_pool_end",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "is_prefetch", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pool_total", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       292,
-       kUnsetSize},
-      {"ion_secure_cma_add_to_pool_start",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "is_prefetch", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pool_total", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       293,
-       kUnsetSize},
-      {"ion_secure_cma_allocate_end",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "align", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "heap_name", 3, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       294,
-       kUnsetSize},
-      {"ion_secure_cma_allocate_start",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "align", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "heap_name", 3, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       295,
-       kUnsetSize},
-      {"ion_secure_cma_shrink_pool_end",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "drained_size", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "skipped_size", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       296,
-       kUnsetSize},
-      {"ion_secure_cma_shrink_pool_start",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "drained_size", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "skipped_size", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       297,
-       kUnsetSize},
-      {"kfree",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "call_site", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ptr", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       298,
-       kUnsetSize},
-      {"kmalloc",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bytes_alloc", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bytes_req", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "call_site", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "gfp_flags", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ptr", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       299,
-       kUnsetSize},
-      {"kmalloc_node",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bytes_alloc", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bytes_req", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "call_site", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "gfp_flags", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "node", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ptr", 6, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       300,
-       kUnsetSize},
-      {"kmem_cache_alloc",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bytes_alloc", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bytes_req", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "call_site", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "gfp_flags", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ptr", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       301,
-       kUnsetSize},
-      {"kmem_cache_alloc_node",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bytes_alloc", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bytes_req", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "call_site", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "gfp_flags", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "node", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ptr", 6, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       302,
-       kUnsetSize},
-      {"kmem_cache_free",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "call_site", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ptr", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       303,
-       kUnsetSize},
-      {"migrate_pages_end",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       304,
-       kUnsetSize},
-      {"migrate_pages_start",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       305,
-       kUnsetSize},
-      {"migrate_retry",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "tries", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       306,
-       kUnsetSize},
-      {"mm_page_alloc",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "gfp_flags", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "migratetype", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "page", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pfn", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       307,
-       kUnsetSize},
-      {"mm_page_alloc_extfrag",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "alloc_migratetype", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "alloc_order", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "fallback_migratetype", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "fallback_order", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "page", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "change_ownership", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pfn", 7, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       308,
-       kUnsetSize},
-      {"mm_page_alloc_zone_locked",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "migratetype", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "page", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pfn", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       309,
-       kUnsetSize},
-      {"mm_page_free",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "page", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pfn", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       310,
-       kUnsetSize},
-      {"mm_page_free_batched",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cold", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "page", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pfn", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       311,
-       kUnsetSize},
-      {"mm_page_pcpu_drain",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "migratetype", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "page", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pfn", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       312,
-       kUnsetSize},
-      {"rss_stat",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "member", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "size", 2, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       313,
-       kUnsetSize},
-      {"ion_heap_shrink",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "heap_name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "total_allocated", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       314,
-       kUnsetSize},
-      {"ion_heap_grow",
-       "kmem",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "heap_name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "len", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "total_allocated", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       315,
-       kUnsetSize},
-      {"lowmemory_kill",
-       "lowmemorykiller",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pagecache_size", 3, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pagecache_limit", 4, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "free", 5, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       35,
-       kUnsetSize},
-      {"mdp_cmd_kickoff",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ctl_num", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "kickoff_cnt", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       76,
-       kUnsetSize},
-      {"mdp_commit",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "num", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "play_cnt", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "clk_rate", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "bandwidth", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       77,
-       kUnsetSize},
-      {"mdp_perf_set_ot",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pnum", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "xin_id", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rd_lim", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "is_vbif_rt", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       78,
-       kUnsetSize},
-      {"mdp_sspp_change",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "num", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "play_cnt", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mixer", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "stage", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "format", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "img_w", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "img_h", 8, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "src_x", 9, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "src_y", 10, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "src_w", 11, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "src_h", 12, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dst_x", 13, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dst_y", 14, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dst_w", 15, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dst_h", 16, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       79,
-       kUnsetSize},
-      {"tracing_mark_write",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "trace_name", 2, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "trace_begin", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       80,
-       kUnsetSize},
-      {"mdp_cmd_pingpong_done",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ctl_num", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "intf_num", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pp_num", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "koff_cnt", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       81,
-       kUnsetSize},
-      {"mdp_compare_bw",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "new_ab", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "new_ib", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "new_wb", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "old_ab", 4, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "old_ib", 5, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "old_wb", 6, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "params_changed", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "update_bw", 8, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       82,
-       kUnsetSize},
-      {"mdp_perf_set_panic_luts",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pnum", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "fmt", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mode", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "panic_lut", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "robust_lut", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       83,
-       kUnsetSize},
-      {"mdp_sspp_set",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "num", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "play_cnt", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mixer", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "stage", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flags", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "format", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "img_w", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "img_h", 8, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "src_x", 9, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "src_y", 10, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "src_w", 11, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "src_h", 12, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dst_x", 13, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dst_y", 14, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dst_w", 15, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "dst_h", 16, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       84,
-       kUnsetSize},
-      {"mdp_cmd_readptr_done",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ctl_num", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "koff_cnt", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       85,
-       kUnsetSize},
-      {"mdp_misr_crc",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "block_id", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "vsync_cnt", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "crc", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       86,
-       kUnsetSize},
-      {"mdp_perf_set_qos_luts",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pnum", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "fmt", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "intf", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "rot", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "fl", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "lut", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "linear", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       87,
-       kUnsetSize},
-      {"mdp_trace_counter",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "counter_name", 2, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "value", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       88,
-       kUnsetSize},
-      {"mdp_cmd_release_bw",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ctl_num", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       89,
-       kUnsetSize},
-      {"mdp_mixer_update",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mixer_num", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       90,
-       kUnsetSize},
-      {"mdp_perf_set_wm_levels",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pnum", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "use_space", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "priority_bytes", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "wm0", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "wm1", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "wm2", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mb_cnt", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "mb_size", 8, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       91,
-       kUnsetSize},
-      {"mdp_video_underrun_done",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ctl_num", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "underrun_cnt", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       92,
-       kUnsetSize},
-      {"mdp_cmd_wait_pingpong",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ctl_num", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "kickoff_cnt", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       93,
-       kUnsetSize},
-      {"mdp_perf_prefill_calc",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pnum", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "latency_buf", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ot", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "y_buf", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "y_scaler", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pp_lines", 6, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pp_bytes", 7, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "post_sc", 8, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "fbc_bytes", 9, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "prefill_bytes", 10, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       94,
-       kUnsetSize},
-      {"mdp_perf_update_bus",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "client", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ab_quota", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ib_quota", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       95,
-       kUnsetSize},
-      {"rotator_bw_ao_as_context",
-       "mdss",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "state", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       96,
-       kUnsetSize},
-      {"mm_event_record",
-       "mm_event",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "avg_lat", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "count", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "max_lat", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "type", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       328,
-       kUnsetSize},
-      {"oom_score_adj_update",
-       "oom",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "oom_score_adj", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       326,
-       kUnsetSize},
-      {"cpu_frequency",
-       "power",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "state", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cpu_id", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       11,
-       kUnsetSize},
-      {"cpu_frequency_limits",
-       "power",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "min_freq", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "max_freq", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cpu_id", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       12,
-       kUnsetSize},
-      {"cpu_idle",
-       "power",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "state", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cpu_id", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       13,
-       kUnsetSize},
-      {"clock_enable",
-       "power",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "state", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cpu_id", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       14,
-       kUnsetSize},
-      {"clock_disable",
-       "power",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "state", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cpu_id", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       15,
-       kUnsetSize},
-      {"clock_set_rate",
-       "power",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "state", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cpu_id", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       16,
-       kUnsetSize},
-      {"suspend_resume",
-       "power",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "action", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "val", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "start", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       113,
-       kUnsetSize},
-      {"gpu_frequency",
-       "power",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "gpu_id", 1, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "state", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       332,
-       kUnsetSize},
-      {"sys_enter",
-       "raw_syscalls",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "id", 1, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       329,
-       kUnsetSize},
-      {"sys_exit",
-       "raw_syscalls",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "id", 1, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "ret", 2, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       330,
-       kUnsetSize},
-      {"regulator_disable",
-       "regulator",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       60,
-       kUnsetSize},
-      {"regulator_disable_complete",
-       "regulator",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       61,
-       kUnsetSize},
-      {"regulator_enable",
-       "regulator",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       62,
-       kUnsetSize},
-      {"regulator_enable_complete",
-       "regulator",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       63,
-       kUnsetSize},
-      {"regulator_enable_delay",
-       "regulator",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       64,
-       kUnsetSize},
-      {"regulator_set_voltage",
-       "regulator",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "min", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "max", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       65,
-       kUnsetSize},
-      {"regulator_set_voltage_complete",
-       "regulator",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "val", 2, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       66,
-       kUnsetSize},
-      {"sched_switch",
-       "sched",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "prev_comm", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "prev_pid", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "prev_prio", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "prev_state", 4, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "next_comm", 5, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "next_pid", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "next_prio", 7, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       4,
-       kUnsetSize},
-      {"sched_wakeup",
-       "sched",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "prio", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "success", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "target_cpu", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       17,
-       kUnsetSize},
-      {"sched_blocked_reason",
-       "sched",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "caller", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "io_wait", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       18,
-       kUnsetSize},
-      {"sched_cpu_hotplug",
-       "sched",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "affected_cpu", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "error", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "status", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       19,
-       kUnsetSize},
-      {"sched_waking",
-       "sched",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "prio", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "success", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "target_cpu", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       20,
-       kUnsetSize},
-      {"sched_wakeup_new",
-       "sched",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "prio", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "success", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "target_cpu", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       114,
-       kUnsetSize},
-      {"sched_process_exec",
-       "sched",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "filename", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "old_pid", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       237,
-       kUnsetSize},
-      {"sched_process_exit",
-       "sched",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "tgid", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "prio", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       238,
-       kUnsetSize},
-      {"sched_process_fork",
-       "sched",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "parent_comm", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "parent_pid", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "child_comm", 3, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "child_pid", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       239,
-       kUnsetSize},
-      {"sched_process_free",
-       "sched",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "prio", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       240,
-       kUnsetSize},
-      {"sched_process_hang",
-       "sched",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       241,
-       kUnsetSize},
-      {"sched_process_wait",
-       "sched",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "prio", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       242,
-       kUnsetSize},
-      {"signal_deliver",
-       "signal",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "code", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sa_flags", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sig", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       324,
-       kUnsetSize},
-      {"signal_generate",
-       "signal",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "code", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 2, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "group", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "result", 5, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "sig", 6, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       325,
-       kUnsetSize},
-      {"sync_pt",
-       "sync",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "timeline", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "value", 2, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       38,
-       kUnsetSize},
-      {"sync_timeline",
-       "sync",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "value", 2, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       39,
-       kUnsetSize},
-      {"sync_wait",
-       "sync",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 1, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "status", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "begin", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       40,
-       kUnsetSize},
-      {"0",
-       "systrace",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "flag", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "name", 2, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 3, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "value", 4, ProtoSchemaType::kInt64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       331,
-       kUnsetSize},
-      {"task_newtask",
-       "task",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "comm", 2, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "clone_flags", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "oom_score_adj", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       235,
-       kUnsetSize},
-      {"task_rename",
-       "task",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "pid", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "oldcomm", 2, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "newcomm", 3, ProtoSchemaType::kString,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "oom_score_adj", 4, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       236,
-       kUnsetSize},
-      {"mm_vmscan_direct_reclaim_begin",
-       "vmscan",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "may_writepage", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "gfp_flags", 3, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       46,
-       kUnsetSize},
-      {"mm_vmscan_direct_reclaim_end",
-       "vmscan",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nr_reclaimed", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       47,
-       kUnsetSize},
-      {"mm_vmscan_kswapd_wake",
-       "vmscan",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nid", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "order", 2, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       48,
-       kUnsetSize},
-      {"mm_vmscan_kswapd_sleep",
-       "vmscan",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "nid", 1, ProtoSchemaType::kInt32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       49,
-       kUnsetSize},
-      {"workqueue_activate_work",
-       "workqueue",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "work", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       56,
-       kUnsetSize},
-      {"workqueue_execute_end",
-       "workqueue",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "work", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       57,
-       kUnsetSize},
-      {"workqueue_execute_start",
-       "workqueue",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "work", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "function", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       58,
-       kUnsetSize},
-      {"workqueue_queue_work",
-       "workqueue",
-       {
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "work", 1, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "function", 2, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "workqueue", 3, ProtoSchemaType::kUint64,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "req_cpu", 4, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
-            "cpu", 5, ProtoSchemaType::kUint32,
-            TranslationStrategy::kInvalidTranslationStrategy},
-       },
-       kUnsetFtraceId,
-       59,
-       kUnsetSize},
-  };
+  std::vector<Event> events;
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "binder_transaction";
+    event->group = "binder";
+    event->proto_field_id = 50;
+    event->fields.push_back(MakeField("debug_id", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("target_node", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("to_proc", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("to_thread", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("reply", 5, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("code", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("flags", 7, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "binder_transaction_received";
+    event->group = "binder";
+    event->proto_field_id = 51;
+    event->fields.push_back(MakeField("debug_id", 1, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "binder_set_priority";
+    event->group = "binder";
+    event->proto_field_id = 52;
+    event->fields.push_back(MakeField("proc", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("thread", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("old_prio", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("new_prio", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("desired_prio", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "binder_lock";
+    event->group = "binder";
+    event->proto_field_id = 53;
+    event->fields.push_back(MakeField("tag", 1, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "binder_locked";
+    event->group = "binder";
+    event->proto_field_id = 54;
+    event->fields.push_back(MakeField("tag", 1, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "binder_unlock";
+    event->group = "binder";
+    event->proto_field_id = 55;
+    event->fields.push_back(MakeField("tag", 1, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "binder_transaction_alloc_buf";
+    event->group = "binder";
+    event->proto_field_id = 323;
+    event->fields.push_back(
+        MakeField("data_size", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("debug_id", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("offsets_size", 3, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_rq_issue";
+    event->group = "block";
+    event->proto_field_id = 45;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sector", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_sector", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("bytes", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("rwbs", 5, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("comm", 6, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("cmd", 7, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_bio_backmerge";
+    event->group = "block";
+    event->proto_field_id = 115;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sector", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_sector", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("rwbs", 4, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("comm", 5, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_bio_bounce";
+    event->group = "block";
+    event->proto_field_id = 116;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sector", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_sector", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("rwbs", 4, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("comm", 5, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_bio_complete";
+    event->group = "block";
+    event->proto_field_id = 117;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sector", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_sector", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("error", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("rwbs", 5, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_bio_frontmerge";
+    event->group = "block";
+    event->proto_field_id = 118;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sector", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_sector", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("rwbs", 4, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("comm", 5, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_bio_queue";
+    event->group = "block";
+    event->proto_field_id = 119;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sector", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_sector", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("rwbs", 4, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("comm", 5, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_bio_remap";
+    event->group = "block";
+    event->proto_field_id = 120;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sector", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_sector", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("old_dev", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("old_sector", 5, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("rwbs", 6, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_dirty_buffer";
+    event->group = "block";
+    event->proto_field_id = 121;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sector", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("size", 3, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_getrq";
+    event->group = "block";
+    event->proto_field_id = 122;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sector", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_sector", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("rwbs", 4, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("comm", 5, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_plug";
+    event->group = "block";
+    event->proto_field_id = 123;
+    event->fields.push_back(MakeField("comm", 1, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_rq_abort";
+    event->group = "block";
+    event->proto_field_id = 124;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sector", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_sector", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("errors", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("rwbs", 5, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("cmd", 6, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_rq_complete";
+    event->group = "block";
+    event->proto_field_id = 125;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sector", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_sector", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("errors", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("rwbs", 5, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("cmd", 6, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_rq_insert";
+    event->group = "block";
+    event->proto_field_id = 126;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sector", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_sector", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("bytes", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("rwbs", 5, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("comm", 6, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("cmd", 7, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_rq_remap";
+    event->group = "block";
+    event->proto_field_id = 128;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sector", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_sector", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("old_dev", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("old_sector", 5, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("nr_bios", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("rwbs", 7, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_rq_requeue";
+    event->group = "block";
+    event->proto_field_id = 129;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sector", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_sector", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("errors", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("rwbs", 5, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("cmd", 6, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_sleeprq";
+    event->group = "block";
+    event->proto_field_id = 130;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sector", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_sector", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("rwbs", 4, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("comm", 5, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_split";
+    event->group = "block";
+    event->proto_field_id = 131;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sector", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("new_sector", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("rwbs", 4, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("comm", 5, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_touch_buffer";
+    event->group = "block";
+    event->proto_field_id = 132;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sector", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("size", 3, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "block_unplug";
+    event->group = "block";
+    event->proto_field_id = 133;
+    event->fields.push_back(MakeField("nr_rq", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("comm", 2, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "cgroup_attach_task";
+    event->group = "cgroup";
+    event->proto_field_id = 67;
+    event->fields.push_back(MakeField("dst_root", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("dst_id", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("pid", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("comm", 4, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("cname", 5, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "cgroup_mkdir";
+    event->group = "cgroup";
+    event->proto_field_id = 68;
+    event->fields.push_back(MakeField("root", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("id", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("cname", 3, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "cgroup_remount";
+    event->group = "cgroup";
+    event->proto_field_id = 69;
+    event->fields.push_back(MakeField("root", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("ss_mask", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("name", 3, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "cgroup_rmdir";
+    event->group = "cgroup";
+    event->proto_field_id = 70;
+    event->fields.push_back(MakeField("root", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("id", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("cname", 3, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "cgroup_transfer_tasks";
+    event->group = "cgroup";
+    event->proto_field_id = 71;
+    event->fields.push_back(MakeField("dst_root", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("dst_id", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("pid", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("comm", 4, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("cname", 5, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "cgroup_destroy_root";
+    event->group = "cgroup";
+    event->proto_field_id = 72;
+    event->fields.push_back(MakeField("root", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("ss_mask", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("name", 3, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "cgroup_release";
+    event->group = "cgroup";
+    event->proto_field_id = 73;
+    event->fields.push_back(MakeField("root", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("id", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("cname", 3, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "cgroup_rename";
+    event->group = "cgroup";
+    event->proto_field_id = 74;
+    event->fields.push_back(MakeField("root", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("id", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("cname", 3, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "cgroup_setup_root";
+    event->group = "cgroup";
+    event->proto_field_id = 75;
+    event->fields.push_back(MakeField("root", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("ss_mask", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("name", 3, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "clk_enable";
+    event->group = "clk";
+    event->proto_field_id = 320;
+    event->fields.push_back(MakeField("name", 1, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "clk_disable";
+    event->group = "clk";
+    event->proto_field_id = 321;
+    event->fields.push_back(MakeField("name", 1, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "clk_set_rate";
+    event->group = "clk";
+    event->proto_field_id = 322;
+    event->fields.push_back(MakeField("name", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("rate", 2, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_compaction_begin";
+    event->group = "compaction";
+    event->proto_field_id = 99;
+    event->fields.push_back(
+        MakeField("zone_start", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("migrate_pfn", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("free_pfn", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("zone_end", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sync", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_compaction_defer_compaction";
+    event->group = "compaction";
+    event->proto_field_id = 100;
+    event->fields.push_back(MakeField("nid", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("idx", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("order", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("considered", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("defer_shift", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("order_failed", 6, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_compaction_deferred";
+    event->group = "compaction";
+    event->proto_field_id = 101;
+    event->fields.push_back(MakeField("nid", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("idx", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("order", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("considered", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("defer_shift", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("order_failed", 6, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_compaction_defer_reset";
+    event->group = "compaction";
+    event->proto_field_id = 102;
+    event->fields.push_back(MakeField("nid", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("idx", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("order", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("considered", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("defer_shift", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("order_failed", 6, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_compaction_end";
+    event->group = "compaction";
+    event->proto_field_id = 103;
+    event->fields.push_back(
+        MakeField("zone_start", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("migrate_pfn", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("free_pfn", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("zone_end", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sync", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("status", 6, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_compaction_finished";
+    event->group = "compaction";
+    event->proto_field_id = 104;
+    event->fields.push_back(MakeField("nid", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("idx", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("order", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("ret", 4, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_compaction_isolate_freepages";
+    event->group = "compaction";
+    event->proto_field_id = 105;
+    event->fields.push_back(
+        MakeField("start_pfn", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("end_pfn", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_scanned", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("nr_taken", 4, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_compaction_isolate_migratepages";
+    event->group = "compaction";
+    event->proto_field_id = 106;
+    event->fields.push_back(
+        MakeField("start_pfn", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("end_pfn", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_scanned", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("nr_taken", 4, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_compaction_kcompactd_sleep";
+    event->group = "compaction";
+    event->proto_field_id = 107;
+    event->fields.push_back(MakeField("nid", 1, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_compaction_kcompactd_wake";
+    event->group = "compaction";
+    event->proto_field_id = 108;
+    event->fields.push_back(MakeField("nid", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("order", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("classzone_idx", 3, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_compaction_migratepages";
+    event->group = "compaction";
+    event->proto_field_id = 109;
+    event->fields.push_back(
+        MakeField("nr_migrated", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_failed", 2, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_compaction_suitable";
+    event->group = "compaction";
+    event->proto_field_id = 110;
+    event->fields.push_back(MakeField("nid", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("idx", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("order", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("ret", 4, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_compaction_try_to_compact_pages";
+    event->group = "compaction";
+    event->proto_field_id = 111;
+    event->fields.push_back(MakeField("order", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("gfp_mask", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("mode", 3, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_compaction_wakeup_kcompactd";
+    event->group = "compaction";
+    event->proto_field_id = 112;
+    event->fields.push_back(MakeField("nid", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("order", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("classzone_idx", 3, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_da_write_begin";
+    event->group = "ext4";
+    event->proto_field_id = 41;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pos", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("flags", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_da_write_end";
+    event->group = "ext4";
+    event->proto_field_id = 42;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pos", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("copied", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_sync_file_enter";
+    event->group = "ext4";
+    event->proto_field_id = 43;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("parent", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("datasync", 4, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_sync_file_exit";
+    event->group = "ext4";
+    event->proto_field_id = 44;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ret", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_alloc_da_blocks";
+    event->group = "ext4";
+    event->proto_field_id = 134;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("data_blocks", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("meta_blocks", 4, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_allocate_blocks";
+    event->group = "ext4";
+    event->proto_field_id = 135;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("block", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("logical", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("lleft", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("lright", 7, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("goal", 8, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pleft", 9, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pright", 10, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("flags", 11, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_allocate_inode";
+    event->group = "ext4";
+    event->proto_field_id = 136;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("dir", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("mode", 4, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_begin_ordered_truncate";
+    event->group = "ext4";
+    event->proto_field_id = 137;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("new_size", 3, ProtoSchemaType::kInt64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_collapse_range";
+    event->group = "ext4";
+    event->proto_field_id = 138;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("offset", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kInt64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_da_release_space";
+    event->group = "ext4";
+    event->proto_field_id = 139;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("i_blocks", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("freed_blocks", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("reserved_data_blocks", 5, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("reserved_meta_blocks", 6, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("allocated_meta_blocks", 7, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("mode", 8, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_da_reserve_space";
+    event->group = "ext4";
+    event->proto_field_id = 140;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("i_blocks", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("reserved_data_blocks", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("reserved_meta_blocks", 5, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("mode", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("md_needed", 7, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_da_update_reserve_space";
+    event->group = "ext4";
+    event->proto_field_id = 141;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("i_blocks", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("used_blocks", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("reserved_data_blocks", 5, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("reserved_meta_blocks", 6, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("allocated_meta_blocks", 7, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("quota_claim", 8, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("mode", 9, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_da_write_pages";
+    event->group = "ext4";
+    event->proto_field_id = 142;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("first_page", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_to_write", 4, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("sync_mode", 5, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("b_blocknr", 6, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("b_size", 7, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("b_state", 8, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("io_done", 9, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("pages_written", 10, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_da_write_pages_extent";
+    event->group = "ext4";
+    event->proto_field_id = 143;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("lblk", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("flags", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_direct_IO_enter";
+    event->group = "ext4";
+    event->proto_field_id = 144;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pos", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("rw", 5, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_direct_IO_exit";
+    event->group = "ext4";
+    event->proto_field_id = 145;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pos", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("rw", 5, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("ret", 6, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_discard_blocks";
+    event->group = "ext4";
+    event->proto_field_id = 146;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("blk", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("count", 3, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_discard_preallocations";
+    event->group = "ext4";
+    event->proto_field_id = 147;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_drop_inode";
+    event->group = "ext4";
+    event->proto_field_id = 148;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("drop", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_es_cache_extent";
+    event->group = "ext4";
+    event->proto_field_id = 149;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("lblk", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("pblk", 5, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("status", 6, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_es_find_delayed_extent_range_enter";
+    event->group = "ext4";
+    event->proto_field_id = 150;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("lblk", 3, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_es_find_delayed_extent_range_exit";
+    event->group = "ext4";
+    event->proto_field_id = 151;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("lblk", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("pblk", 5, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("status", 6, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_es_insert_extent";
+    event->group = "ext4";
+    event->proto_field_id = 152;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("lblk", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("pblk", 5, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("status", 6, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_es_lookup_extent_enter";
+    event->group = "ext4";
+    event->proto_field_id = 153;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("lblk", 3, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_es_lookup_extent_exit";
+    event->group = "ext4";
+    event->proto_field_id = 154;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("lblk", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("pblk", 5, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("status", 6, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("found", 7, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_es_remove_extent";
+    event->group = "ext4";
+    event->proto_field_id = 155;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("lblk", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kInt64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_es_shrink";
+    event->group = "ext4";
+    event->proto_field_id = 156;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("nr_shrunk", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("scan_time", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_skipped", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("retried", 5, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_es_shrink_count";
+    event->group = "ext4";
+    event->proto_field_id = 157;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_to_scan", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("cache_cnt", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_es_shrink_scan_enter";
+    event->group = "ext4";
+    event->proto_field_id = 158;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_to_scan", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("cache_cnt", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_es_shrink_scan_exit";
+    event->group = "ext4";
+    event->proto_field_id = 159;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("nr_shrunk", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("cache_cnt", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_evict_inode";
+    event->group = "ext4";
+    event->proto_field_id = 160;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("nlink", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_ext_convert_to_initialized_enter";
+    event->group = "ext4";
+    event->proto_field_id = 161;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("m_lblk", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("m_len", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("u_lblk", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("u_len", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("u_pblk", 7, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_ext_convert_to_initialized_fastpath";
+    event->group = "ext4";
+    event->proto_field_id = 162;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("m_lblk", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("m_len", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("u_lblk", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("u_len", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("u_pblk", 7, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("i_lblk", 8, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("i_len", 9, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("i_pblk", 10, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_ext_handle_unwritten_extents";
+    event->group = "ext4";
+    event->proto_field_id = 163;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("flags", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("lblk", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("pblk", 5, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("len", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("allocated", 7, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("newblk", 8, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_ext_in_cache";
+    event->group = "ext4";
+    event->proto_field_id = 164;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("lblk", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("ret", 4, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_ext_load_extent";
+    event->group = "ext4";
+    event->proto_field_id = 165;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pblk", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("lblk", 4, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_ext_map_blocks_enter";
+    event->group = "ext4";
+    event->proto_field_id = 166;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("lblk", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("flags", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_ext_map_blocks_exit";
+    event->group = "ext4";
+    event->proto_field_id = 167;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("flags", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("pblk", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("lblk", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("len", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("mflags", 7, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("ret", 8, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_ext_put_in_cache";
+    event->group = "ext4";
+    event->proto_field_id = 168;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("lblk", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("start", 5, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_ext_remove_space";
+    event->group = "ext4";
+    event->proto_field_id = 169;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("start", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("end", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("depth", 5, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_ext_remove_space_done";
+    event->group = "ext4";
+    event->proto_field_id = 170;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("start", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("end", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("depth", 5, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("partial", 6, ProtoSchemaType::kInt64));
+    event->fields.push_back(
+        MakeField("eh_entries", 7, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_ext_rm_idx";
+    event->group = "ext4";
+    event->proto_field_id = 171;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pblk", 3, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_ext_rm_leaf";
+    event->group = "ext4";
+    event->proto_field_id = 172;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("partial", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("start", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("ee_lblk", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("ee_pblk", 6, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ee_len", 7, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_ext_show_extent";
+    event->group = "ext4";
+    event->proto_field_id = 173;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pblk", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("lblk", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("len", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_fallocate_enter";
+    event->group = "ext4";
+    event->proto_field_id = 174;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("offset", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("mode", 5, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("pos", 6, ProtoSchemaType::kInt64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_fallocate_exit";
+    event->group = "ext4";
+    event->proto_field_id = 175;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pos", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("blocks", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("ret", 5, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_find_delalloc_range";
+    event->group = "ext4";
+    event->proto_field_id = 176;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("from", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("to", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("reverse", 5, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("found", 6, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("found_blk", 7, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_forget";
+    event->group = "ext4";
+    event->proto_field_id = 177;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("block", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("is_metadata", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("mode", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_free_blocks";
+    event->group = "ext4";
+    event->proto_field_id = 178;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("block", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("count", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("flags", 5, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("mode", 6, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_free_inode";
+    event->group = "ext4";
+    event->proto_field_id = 179;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("uid", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("gid", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("blocks", 5, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("mode", 6, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_get_implied_cluster_alloc_exit";
+    event->group = "ext4";
+    event->proto_field_id = 180;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("flags", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("lblk", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("pblk", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("len", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("ret", 6, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_get_reserved_cluster_alloc";
+    event->group = "ext4";
+    event->proto_field_id = 181;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("lblk", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_ind_map_blocks_enter";
+    event->group = "ext4";
+    event->proto_field_id = 182;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("lblk", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("flags", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_ind_map_blocks_exit";
+    event->group = "ext4";
+    event->proto_field_id = 183;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("flags", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("pblk", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("lblk", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("len", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("mflags", 7, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("ret", 8, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_insert_range";
+    event->group = "ext4";
+    event->proto_field_id = 184;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("offset", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kInt64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_invalidatepage";
+    event->group = "ext4";
+    event->proto_field_id = 185;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("index", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("offset", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("length", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_journal_start";
+    event->group = "ext4";
+    event->proto_field_id = 186;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ip", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("blocks", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("rsv_blocks", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("nblocks", 5, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_journal_start_reserved";
+    event->group = "ext4";
+    event->proto_field_id = 187;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ip", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("blocks", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_journalled_invalidatepage";
+    event->group = "ext4";
+    event->proto_field_id = 188;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("index", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("offset", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("length", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_journalled_write_end";
+    event->group = "ext4";
+    event->proto_field_id = 189;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pos", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("copied", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_load_inode";
+    event->group = "ext4";
+    event->proto_field_id = 190;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_load_inode_bitmap";
+    event->group = "ext4";
+    event->proto_field_id = 191;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("group", 2, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_mark_inode_dirty";
+    event->group = "ext4";
+    event->proto_field_id = 192;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ip", 3, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_mb_bitmap_load";
+    event->group = "ext4";
+    event->proto_field_id = 193;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("group", 2, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_mb_buddy_bitmap_load";
+    event->group = "ext4";
+    event->proto_field_id = 194;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("group", 2, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_mb_discard_preallocations";
+    event->group = "ext4";
+    event->proto_field_id = 195;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("needed", 2, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_mb_new_group_pa";
+    event->group = "ext4";
+    event->proto_field_id = 196;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("pa_pstart", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("pa_lstart", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pa_len", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_mb_new_inode_pa";
+    event->group = "ext4";
+    event->proto_field_id = 197;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("pa_pstart", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("pa_lstart", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pa_len", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_mb_release_group_pa";
+    event->group = "ext4";
+    event->proto_field_id = 198;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("pa_pstart", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pa_len", 3, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_mb_release_inode_pa";
+    event->group = "ext4";
+    event->proto_field_id = 199;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("block", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("count", 4, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_mballoc_alloc";
+    event->group = "ext4";
+    event->proto_field_id = 200;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("orig_logical", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("orig_start", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("orig_group", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("orig_len", 6, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("goal_logical", 7, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("goal_start", 8, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("goal_group", 9, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("goal_len", 10, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("result_logical", 11, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("result_start", 12, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("result_group", 13, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("result_len", 14, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("found", 15, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("groups", 16, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("buddy", 17, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("flags", 18, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("tail", 19, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("cr", 20, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_mballoc_discard";
+    event->group = "ext4";
+    event->proto_field_id = 201;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("result_start", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("result_group", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("result_len", 5, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_mballoc_free";
+    event->group = "ext4";
+    event->proto_field_id = 202;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("result_start", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("result_group", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("result_len", 5, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_mballoc_prealloc";
+    event->group = "ext4";
+    event->proto_field_id = 203;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("orig_logical", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("orig_start", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("orig_group", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("orig_len", 6, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("result_logical", 7, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("result_start", 8, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("result_group", 9, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("result_len", 10, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_other_inode_update_time";
+    event->group = "ext4";
+    event->proto_field_id = 204;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("orig_ino", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("uid", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("gid", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("mode", 6, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_punch_hole";
+    event->group = "ext4";
+    event->proto_field_id = 205;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("offset", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("mode", 5, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_read_block_bitmap_load";
+    event->group = "ext4";
+    event->proto_field_id = 206;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("group", 2, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_readpage";
+    event->group = "ext4";
+    event->proto_field_id = 207;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("index", 3, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_releasepage";
+    event->group = "ext4";
+    event->proto_field_id = 208;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("index", 3, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_remove_blocks";
+    event->group = "ext4";
+    event->proto_field_id = 209;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("from", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("to", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("partial", 5, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("ee_pblk", 6, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ee_lblk", 7, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("ee_len", 8, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_request_blocks";
+    event->group = "ext4";
+    event->proto_field_id = 210;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("len", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("logical", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("lleft", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("lright", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("goal", 7, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pleft", 8, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pright", 9, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("flags", 10, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_request_inode";
+    event->group = "ext4";
+    event->proto_field_id = 211;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("dir", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("mode", 3, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_sync_fs";
+    event->group = "ext4";
+    event->proto_field_id = 212;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("wait", 2, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_trim_all_free";
+    event->group = "ext4";
+    event->proto_field_id = 213;
+    event->fields.push_back(MakeField("dev_major", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("dev_minor", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("group", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("start", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("len", 5, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_trim_extent";
+    event->group = "ext4";
+    event->proto_field_id = 214;
+    event->fields.push_back(MakeField("dev_major", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("dev_minor", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("group", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("start", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("len", 5, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_truncate_enter";
+    event->group = "ext4";
+    event->proto_field_id = 215;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("blocks", 3, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_truncate_exit";
+    event->group = "ext4";
+    event->proto_field_id = 216;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("blocks", 3, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_unlink_enter";
+    event->group = "ext4";
+    event->proto_field_id = 217;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("parent", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("size", 4, ProtoSchemaType::kInt64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_unlink_exit";
+    event->group = "ext4";
+    event->proto_field_id = 218;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ret", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_write_begin";
+    event->group = "ext4";
+    event->proto_field_id = 219;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pos", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("flags", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_write_end";
+    event->group = "ext4";
+    event->proto_field_id = 230;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pos", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("copied", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_writepage";
+    event->group = "ext4";
+    event->proto_field_id = 231;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("index", 3, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_writepages";
+    event->group = "ext4";
+    event->proto_field_id = 232;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("nr_to_write", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(
+        MakeField("pages_skipped", 4, ProtoSchemaType::kInt64));
+    event->fields.push_back(
+        MakeField("range_start", 5, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("range_end", 6, ProtoSchemaType::kInt64));
+    event->fields.push_back(
+        MakeField("writeback_index", 7, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sync_mode", 8, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("for_kupdate", 9, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("range_cyclic", 10, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_writepages_result";
+    event->group = "ext4";
+    event->proto_field_id = 233;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ret", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("pages_written", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("pages_skipped", 5, ProtoSchemaType::kInt64));
+    event->fields.push_back(
+        MakeField("writeback_index", 6, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sync_mode", 7, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ext4_zero_range";
+    event->group = "ext4";
+    event->proto_field_id = 234;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("offset", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("mode", 5, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_do_submit_bio";
+    event->group = "f2fs";
+    event->proto_field_id = 243;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("btype", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("sync", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("sector", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("size", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_evict_inode";
+    event->group = "f2fs";
+    event->proto_field_id = 244;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pino", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("mode", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("size", 5, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("nlink", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("blocks", 7, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("advise", 8, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_fallocate";
+    event->group = "f2fs";
+    event->proto_field_id = 245;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("mode", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("offset", 4, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("len", 5, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("size", 6, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("blocks", 7, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ret", 8, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_get_data_block";
+    event->group = "f2fs";
+    event->proto_field_id = 246;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("iblock", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("bh_start", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("bh_size", 5, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ret", 6, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_get_victim";
+    event->group = "f2fs";
+    event->proto_field_id = 247;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("type", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("gc_type", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("alloc_mode", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("gc_mode", 5, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("victim", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("ofs_unit", 7, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("pre_victim", 8, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("prefree", 9, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("free", 10, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_iget";
+    event->group = "f2fs";
+    event->proto_field_id = 248;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pino", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("mode", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("size", 5, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("nlink", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("blocks", 7, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("advise", 8, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_iget_exit";
+    event->group = "f2fs";
+    event->proto_field_id = 249;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ret", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_new_inode";
+    event->group = "f2fs";
+    event->proto_field_id = 250;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ret", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_readpage";
+    event->group = "f2fs";
+    event->proto_field_id = 251;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("index", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("blkaddr", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("type", 5, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_reserve_new_block";
+    event->group = "f2fs";
+    event->proto_field_id = 252;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("nid", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("ofs_in_node", 3, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_set_page_dirty";
+    event->group = "f2fs";
+    event->proto_field_id = 253;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("type", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("dir", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("index", 5, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("dirty", 6, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_submit_write_page";
+    event->group = "f2fs";
+    event->proto_field_id = 254;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("type", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("index", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("block", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_sync_file_enter";
+    event->group = "f2fs";
+    event->proto_field_id = 255;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pino", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("mode", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("size", 5, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("nlink", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("blocks", 7, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("advise", 8, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_sync_file_exit";
+    event->group = "f2fs";
+    event->proto_field_id = 256;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("need_cp", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("datasync", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("ret", 5, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_sync_fs";
+    event->group = "f2fs";
+    event->proto_field_id = 257;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("dirty", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("wait", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_truncate";
+    event->group = "f2fs";
+    event->proto_field_id = 258;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pino", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("mode", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("size", 5, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("nlink", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("blocks", 7, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("advise", 8, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_truncate_blocks_enter";
+    event->group = "f2fs";
+    event->proto_field_id = 259;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("size", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("blocks", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("from", 5, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_truncate_blocks_exit";
+    event->group = "f2fs";
+    event->proto_field_id = 260;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ret", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_truncate_data_blocks_range";
+    event->group = "f2fs";
+    event->proto_field_id = 261;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("nid", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("ofs", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("free", 5, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_truncate_inode_blocks_enter";
+    event->group = "f2fs";
+    event->proto_field_id = 262;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("size", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("blocks", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("from", 5, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_truncate_inode_blocks_exit";
+    event->group = "f2fs";
+    event->proto_field_id = 263;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ret", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_truncate_node";
+    event->group = "f2fs";
+    event->proto_field_id = 264;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("nid", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("blk_addr", 4, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_truncate_nodes_enter";
+    event->group = "f2fs";
+    event->proto_field_id = 265;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("nid", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("blk_addr", 4, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_truncate_nodes_exit";
+    event->group = "f2fs";
+    event->proto_field_id = 266;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ret", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_truncate_partial_nodes";
+    event->group = "f2fs";
+    event->proto_field_id = 267;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("nid", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("depth", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("err", 5, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_unlink_enter";
+    event->group = "f2fs";
+    event->proto_field_id = 268;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("size", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("blocks", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("name", 5, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_unlink_exit";
+    event->group = "f2fs";
+    event->proto_field_id = 269;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ret", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_vm_page_mkwrite";
+    event->group = "f2fs";
+    event->proto_field_id = 270;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("type", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("dir", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("index", 5, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("dirty", 6, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_write_begin";
+    event->group = "f2fs";
+    event->proto_field_id = 271;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pos", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("flags", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_write_checkpoint";
+    event->group = "f2fs";
+    event->proto_field_id = 272;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("is_umount", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("msg", 3, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "f2fs_write_end";
+    event->group = "f2fs";
+    event->proto_field_id = 273;
+    event->fields.push_back(MakeField("dev", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pos", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("copied", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "fence_init";
+    event->group = "fence";
+    event->proto_field_id = 316;
+    event->fields.push_back(MakeField("context", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("driver", 2, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("seqno", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("timeline", 4, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "fence_destroy";
+    event->group = "fence";
+    event->proto_field_id = 317;
+    event->fields.push_back(MakeField("context", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("driver", 2, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("seqno", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("timeline", 4, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "fence_enable_signal";
+    event->group = "fence";
+    event->proto_field_id = 318;
+    event->fields.push_back(MakeField("context", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("driver", 2, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("seqno", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("timeline", 4, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "fence_signaled";
+    event->group = "fence";
+    event->proto_field_id = 319;
+    event->fields.push_back(MakeField("context", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("driver", 2, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("seqno", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("timeline", 4, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_filemap_add_to_page_cache";
+    event->group = "filemap";
+    event->proto_field_id = 97;
+    event->fields.push_back(MakeField("pfn", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("i_ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("index", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("s_dev", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("page", 5, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_filemap_delete_from_page_cache";
+    event->group = "filemap";
+    event->proto_field_id = 98;
+    event->fields.push_back(MakeField("pfn", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("i_ino", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("index", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("s_dev", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("page", 5, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "print";
+    event->group = "ftrace";
+    event->proto_field_id = 3;
+    event->fields.push_back(MakeField("ip", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("buf", 2, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "i2c_read";
+    event->group = "i2c";
+    event->proto_field_id = 27;
+    event->fields.push_back(
+        MakeField("adapter_nr", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("msg_nr", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("addr", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("flags", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("len", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "i2c_write";
+    event->group = "i2c";
+    event->proto_field_id = 28;
+    event->fields.push_back(
+        MakeField("adapter_nr", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("msg_nr", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("addr", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("flags", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("len", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("buf", 6, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "i2c_result";
+    event->group = "i2c";
+    event->proto_field_id = 29;
+    event->fields.push_back(
+        MakeField("adapter_nr", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("nr_msgs", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("ret", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "i2c_reply";
+    event->group = "i2c";
+    event->proto_field_id = 30;
+    event->fields.push_back(
+        MakeField("adapter_nr", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("msg_nr", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("addr", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("flags", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("len", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("buf", 6, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "smbus_read";
+    event->group = "i2c";
+    event->proto_field_id = 31;
+    event->fields.push_back(
+        MakeField("adapter_nr", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("flags", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("addr", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("command", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("protocol", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "smbus_write";
+    event->group = "i2c";
+    event->proto_field_id = 32;
+    event->fields.push_back(
+        MakeField("adapter_nr", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("addr", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("flags", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("command", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("len", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("protocol", 6, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "smbus_result";
+    event->group = "i2c";
+    event->proto_field_id = 33;
+    event->fields.push_back(
+        MakeField("adapter_nr", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("addr", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("flags", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("read_write", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("command", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("res", 6, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("protocol", 7, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "smbus_reply";
+    event->group = "i2c";
+    event->proto_field_id = 34;
+    event->fields.push_back(
+        MakeField("adapter_nr", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("addr", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("flags", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("command", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("len", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("protocol", 6, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ipi_entry";
+    event->group = "ipi";
+    event->proto_field_id = 21;
+    event->fields.push_back(MakeField("reason", 1, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ipi_exit";
+    event->group = "ipi";
+    event->proto_field_id = 22;
+    event->fields.push_back(MakeField("reason", 1, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ipi_raise";
+    event->group = "ipi";
+    event->proto_field_id = 23;
+    event->fields.push_back(
+        MakeField("target_cpus", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("reason", 2, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "softirq_entry";
+    event->group = "irq";
+    event->proto_field_id = 24;
+    event->fields.push_back(MakeField("vec", 1, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "softirq_exit";
+    event->group = "irq";
+    event->proto_field_id = 25;
+    event->fields.push_back(MakeField("vec", 1, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "softirq_raise";
+    event->group = "irq";
+    event->proto_field_id = 26;
+    event->fields.push_back(MakeField("vec", 1, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "irq_handler_entry";
+    event->group = "irq";
+    event->proto_field_id = 36;
+    event->fields.push_back(MakeField("irq", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("name", 2, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("handler", 3, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "irq_handler_exit";
+    event->group = "irq";
+    event->proto_field_id = 37;
+    event->fields.push_back(MakeField("irq", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("ret", 2, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "alloc_pages_iommu_end";
+    event->group = "kmem";
+    event->proto_field_id = 274;
+    event->fields.push_back(
+        MakeField("gfp_flags", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("order", 2, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "alloc_pages_iommu_fail";
+    event->group = "kmem";
+    event->proto_field_id = 275;
+    event->fields.push_back(
+        MakeField("gfp_flags", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("order", 2, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "alloc_pages_iommu_start";
+    event->group = "kmem";
+    event->proto_field_id = 276;
+    event->fields.push_back(
+        MakeField("gfp_flags", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("order", 2, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "alloc_pages_sys_end";
+    event->group = "kmem";
+    event->proto_field_id = 277;
+    event->fields.push_back(
+        MakeField("gfp_flags", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("order", 2, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "alloc_pages_sys_fail";
+    event->group = "kmem";
+    event->proto_field_id = 278;
+    event->fields.push_back(
+        MakeField("gfp_flags", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("order", 2, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "alloc_pages_sys_start";
+    event->group = "kmem";
+    event->proto_field_id = 279;
+    event->fields.push_back(
+        MakeField("gfp_flags", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("order", 2, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "dma_alloc_contiguous_retry";
+    event->group = "kmem";
+    event->proto_field_id = 280;
+    event->fields.push_back(MakeField("tries", 1, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "iommu_map_range";
+    event->group = "kmem";
+    event->proto_field_id = 281;
+    event->fields.push_back(
+        MakeField("chunk_size", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("len", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pa", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("va", 4, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "iommu_sec_ptbl_map_range_end";
+    event->group = "kmem";
+    event->proto_field_id = 282;
+    event->fields.push_back(MakeField("len", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("num", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("pa", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("sec_id", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("va", 5, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "iommu_sec_ptbl_map_range_start";
+    event->group = "kmem";
+    event->proto_field_id = 283;
+    event->fields.push_back(MakeField("len", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("num", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("pa", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("sec_id", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("va", 5, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ion_alloc_buffer_end";
+    event->group = "kmem";
+    event->proto_field_id = 284;
+    event->fields.push_back(
+        MakeField("client_name", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("flags", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("heap_name", 3, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("mask", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ion_alloc_buffer_fail";
+    event->group = "kmem";
+    event->proto_field_id = 285;
+    event->fields.push_back(
+        MakeField("client_name", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("error", 2, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("flags", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("heap_name", 4, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("len", 5, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("mask", 6, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ion_alloc_buffer_fallback";
+    event->group = "kmem";
+    event->proto_field_id = 286;
+    event->fields.push_back(
+        MakeField("client_name", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("error", 2, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("flags", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("heap_name", 4, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("len", 5, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("mask", 6, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ion_alloc_buffer_start";
+    event->group = "kmem";
+    event->proto_field_id = 287;
+    event->fields.push_back(
+        MakeField("client_name", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("flags", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("heap_name", 3, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("mask", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ion_cp_alloc_retry";
+    event->group = "kmem";
+    event->proto_field_id = 288;
+    event->fields.push_back(MakeField("tries", 1, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ion_cp_secure_buffer_end";
+    event->group = "kmem";
+    event->proto_field_id = 289;
+    event->fields.push_back(MakeField("align", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("flags", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("heap_name", 3, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ion_cp_secure_buffer_start";
+    event->group = "kmem";
+    event->proto_field_id = 290;
+    event->fields.push_back(MakeField("align", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("flags", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("heap_name", 3, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ion_prefetching";
+    event->group = "kmem";
+    event->proto_field_id = 291;
+    event->fields.push_back(MakeField("len", 1, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ion_secure_cma_add_to_pool_end";
+    event->group = "kmem";
+    event->proto_field_id = 292;
+    event->fields.push_back(
+        MakeField("is_prefetch", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("len", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("pool_total", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ion_secure_cma_add_to_pool_start";
+    event->group = "kmem";
+    event->proto_field_id = 293;
+    event->fields.push_back(
+        MakeField("is_prefetch", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("len", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("pool_total", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ion_secure_cma_allocate_end";
+    event->group = "kmem";
+    event->proto_field_id = 294;
+    event->fields.push_back(MakeField("align", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("flags", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("heap_name", 3, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ion_secure_cma_allocate_start";
+    event->group = "kmem";
+    event->proto_field_id = 295;
+    event->fields.push_back(MakeField("align", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("flags", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("heap_name", 3, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("len", 4, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ion_secure_cma_shrink_pool_end";
+    event->group = "kmem";
+    event->proto_field_id = 296;
+    event->fields.push_back(
+        MakeField("drained_size", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("skipped_size", 2, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ion_secure_cma_shrink_pool_start";
+    event->group = "kmem";
+    event->proto_field_id = 297;
+    event->fields.push_back(
+        MakeField("drained_size", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("skipped_size", 2, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "kfree";
+    event->group = "kmem";
+    event->proto_field_id = 298;
+    event->fields.push_back(
+        MakeField("call_site", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ptr", 2, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "kmalloc";
+    event->group = "kmem";
+    event->proto_field_id = 299;
+    event->fields.push_back(
+        MakeField("bytes_alloc", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("bytes_req", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("call_site", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("gfp_flags", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("ptr", 5, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "kmalloc_node";
+    event->group = "kmem";
+    event->proto_field_id = 300;
+    event->fields.push_back(
+        MakeField("bytes_alloc", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("bytes_req", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("call_site", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("gfp_flags", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("node", 5, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("ptr", 6, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "kmem_cache_alloc";
+    event->group = "kmem";
+    event->proto_field_id = 301;
+    event->fields.push_back(
+        MakeField("bytes_alloc", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("bytes_req", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("call_site", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("gfp_flags", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("ptr", 5, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "kmem_cache_alloc_node";
+    event->group = "kmem";
+    event->proto_field_id = 302;
+    event->fields.push_back(
+        MakeField("bytes_alloc", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("bytes_req", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("call_site", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("gfp_flags", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("node", 5, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("ptr", 6, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "kmem_cache_free";
+    event->group = "kmem";
+    event->proto_field_id = 303;
+    event->fields.push_back(
+        MakeField("call_site", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ptr", 2, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "migrate_pages_end";
+    event->group = "kmem";
+    event->proto_field_id = 304;
+    event->fields.push_back(MakeField("mode", 1, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "migrate_pages_start";
+    event->group = "kmem";
+    event->proto_field_id = 305;
+    event->fields.push_back(MakeField("mode", 1, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "migrate_retry";
+    event->group = "kmem";
+    event->proto_field_id = 306;
+    event->fields.push_back(MakeField("tries", 1, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_page_alloc";
+    event->group = "kmem";
+    event->proto_field_id = 307;
+    event->fields.push_back(
+        MakeField("gfp_flags", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("migratetype", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("order", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("page", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pfn", 5, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_page_alloc_extfrag";
+    event->group = "kmem";
+    event->proto_field_id = 308;
+    event->fields.push_back(
+        MakeField("alloc_migratetype", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("alloc_order", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("fallback_migratetype", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("fallback_order", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("page", 5, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("change_ownership", 6, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("pfn", 7, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_page_alloc_zone_locked";
+    event->group = "kmem";
+    event->proto_field_id = 309;
+    event->fields.push_back(
+        MakeField("migratetype", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("order", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("page", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pfn", 4, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_page_free";
+    event->group = "kmem";
+    event->proto_field_id = 310;
+    event->fields.push_back(MakeField("order", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("page", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pfn", 3, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_page_free_batched";
+    event->group = "kmem";
+    event->proto_field_id = 311;
+    event->fields.push_back(MakeField("cold", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("page", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pfn", 3, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_page_pcpu_drain";
+    event->group = "kmem";
+    event->proto_field_id = 312;
+    event->fields.push_back(
+        MakeField("migratetype", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("order", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("page", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("pfn", 4, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "rss_stat";
+    event->group = "kmem";
+    event->proto_field_id = 313;
+    event->fields.push_back(MakeField("member", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("size", 2, ProtoSchemaType::kInt64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ion_heap_shrink";
+    event->group = "kmem";
+    event->proto_field_id = 314;
+    event->fields.push_back(
+        MakeField("heap_name", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("len", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("total_allocated", 3, ProtoSchemaType::kInt64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "ion_heap_grow";
+    event->group = "kmem";
+    event->proto_field_id = 315;
+    event->fields.push_back(
+        MakeField("heap_name", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("len", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("total_allocated", 3, ProtoSchemaType::kInt64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "lowmemory_kill";
+    event->group = "lowmemorykiller";
+    event->proto_field_id = 35;
+    event->fields.push_back(MakeField("comm", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("pid", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("pagecache_size", 3, ProtoSchemaType::kInt64));
+    event->fields.push_back(
+        MakeField("pagecache_limit", 4, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("free", 5, ProtoSchemaType::kInt64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_cmd_kickoff";
+    event->group = "mdss";
+    event->proto_field_id = 76;
+    event->fields.push_back(MakeField("ctl_num", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("kickoff_cnt", 2, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_commit";
+    event->group = "mdss";
+    event->proto_field_id = 77;
+    event->fields.push_back(MakeField("num", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("play_cnt", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("clk_rate", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("bandwidth", 4, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_perf_set_ot";
+    event->group = "mdss";
+    event->proto_field_id = 78;
+    event->fields.push_back(MakeField("pnum", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("xin_id", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("rd_lim", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("is_vbif_rt", 4, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_sspp_change";
+    event->group = "mdss";
+    event->proto_field_id = 79;
+    event->fields.push_back(MakeField("num", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("play_cnt", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("mixer", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("stage", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("flags", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("format", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("img_w", 7, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("img_h", 8, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("src_x", 9, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("src_y", 10, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("src_w", 11, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("src_h", 12, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("dst_x", 13, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("dst_y", 14, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("dst_w", 15, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("dst_h", 16, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "tracing_mark_write";
+    event->group = "mdss";
+    event->proto_field_id = 80;
+    event->fields.push_back(MakeField("pid", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("trace_name", 2, ProtoSchemaType::kString));
+    event->fields.push_back(
+        MakeField("trace_begin", 3, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_cmd_pingpong_done";
+    event->group = "mdss";
+    event->proto_field_id = 81;
+    event->fields.push_back(MakeField("ctl_num", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("intf_num", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("pp_num", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("koff_cnt", 4, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_compare_bw";
+    event->group = "mdss";
+    event->proto_field_id = 82;
+    event->fields.push_back(MakeField("new_ab", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("new_ib", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("new_wb", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("old_ab", 4, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("old_ib", 5, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("old_wb", 6, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("params_changed", 7, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("update_bw", 8, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_perf_set_panic_luts";
+    event->group = "mdss";
+    event->proto_field_id = 83;
+    event->fields.push_back(MakeField("pnum", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("fmt", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("mode", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("panic_lut", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("robust_lut", 5, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_sspp_set";
+    event->group = "mdss";
+    event->proto_field_id = 84;
+    event->fields.push_back(MakeField("num", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("play_cnt", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("mixer", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("stage", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("flags", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("format", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("img_w", 7, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("img_h", 8, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("src_x", 9, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("src_y", 10, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("src_w", 11, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("src_h", 12, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("dst_x", 13, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("dst_y", 14, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("dst_w", 15, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("dst_h", 16, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_cmd_readptr_done";
+    event->group = "mdss";
+    event->proto_field_id = 85;
+    event->fields.push_back(MakeField("ctl_num", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("koff_cnt", 2, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_misr_crc";
+    event->group = "mdss";
+    event->proto_field_id = 86;
+    event->fields.push_back(MakeField("block_id", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("vsync_cnt", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("crc", 3, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_perf_set_qos_luts";
+    event->group = "mdss";
+    event->proto_field_id = 87;
+    event->fields.push_back(MakeField("pnum", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("fmt", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("intf", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("rot", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("fl", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("lut", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("linear", 7, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_trace_counter";
+    event->group = "mdss";
+    event->proto_field_id = 88;
+    event->fields.push_back(MakeField("pid", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("counter_name", 2, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("value", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_cmd_release_bw";
+    event->group = "mdss";
+    event->proto_field_id = 89;
+    event->fields.push_back(MakeField("ctl_num", 1, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_mixer_update";
+    event->group = "mdss";
+    event->proto_field_id = 90;
+    event->fields.push_back(
+        MakeField("mixer_num", 1, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_perf_set_wm_levels";
+    event->group = "mdss";
+    event->proto_field_id = 91;
+    event->fields.push_back(MakeField("pnum", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("use_space", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("priority_bytes", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("wm0", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("wm1", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("wm2", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("mb_cnt", 7, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("mb_size", 8, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_video_underrun_done";
+    event->group = "mdss";
+    event->proto_field_id = 92;
+    event->fields.push_back(MakeField("ctl_num", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("underrun_cnt", 2, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_cmd_wait_pingpong";
+    event->group = "mdss";
+    event->proto_field_id = 93;
+    event->fields.push_back(MakeField("ctl_num", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("kickoff_cnt", 2, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_perf_prefill_calc";
+    event->group = "mdss";
+    event->proto_field_id = 94;
+    event->fields.push_back(MakeField("pnum", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("latency_buf", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("ot", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("y_buf", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("y_scaler", 5, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("pp_lines", 6, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("pp_bytes", 7, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("post_sc", 8, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("fbc_bytes", 9, ProtoSchemaType::kUint32));
+    event->fields.push_back(
+        MakeField("prefill_bytes", 10, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mdp_perf_update_bus";
+    event->group = "mdss";
+    event->proto_field_id = 95;
+    event->fields.push_back(MakeField("client", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("ab_quota", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("ib_quota", 3, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "rotator_bw_ao_as_context";
+    event->group = "mdss";
+    event->proto_field_id = 96;
+    event->fields.push_back(MakeField("state", 1, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_event_record";
+    event->group = "mm_event";
+    event->proto_field_id = 328;
+    event->fields.push_back(MakeField("avg_lat", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("count", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("max_lat", 3, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("type", 4, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "oom_score_adj_update";
+    event->group = "oom";
+    event->proto_field_id = 326;
+    event->fields.push_back(MakeField("comm", 1, ProtoSchemaType::kString));
+    event->fields.push_back(
+        MakeField("oom_score_adj", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("pid", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "cpu_frequency";
+    event->group = "power";
+    event->proto_field_id = 11;
+    event->fields.push_back(MakeField("state", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("cpu_id", 2, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "cpu_frequency_limits";
+    event->group = "power";
+    event->proto_field_id = 12;
+    event->fields.push_back(MakeField("min_freq", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("max_freq", 2, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("cpu_id", 3, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "cpu_idle";
+    event->group = "power";
+    event->proto_field_id = 13;
+    event->fields.push_back(MakeField("state", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("cpu_id", 2, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "clock_enable";
+    event->group = "power";
+    event->proto_field_id = 14;
+    event->fields.push_back(MakeField("name", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("state", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("cpu_id", 3, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "clock_disable";
+    event->group = "power";
+    event->proto_field_id = 15;
+    event->fields.push_back(MakeField("name", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("state", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("cpu_id", 3, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "clock_set_rate";
+    event->group = "power";
+    event->proto_field_id = 16;
+    event->fields.push_back(MakeField("name", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("state", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("cpu_id", 3, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "suspend_resume";
+    event->group = "power";
+    event->proto_field_id = 113;
+    event->fields.push_back(MakeField("action", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("val", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("start", 3, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "gpu_frequency";
+    event->group = "power";
+    event->proto_field_id = 332;
+    event->fields.push_back(MakeField("gpu_id", 1, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("state", 2, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "sys_enter";
+    event->group = "raw_syscalls";
+    event->proto_field_id = 329;
+    event->fields.push_back(MakeField("id", 1, ProtoSchemaType::kInt64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "sys_exit";
+    event->group = "raw_syscalls";
+    event->proto_field_id = 330;
+    event->fields.push_back(MakeField("id", 1, ProtoSchemaType::kInt64));
+    event->fields.push_back(MakeField("ret", 2, ProtoSchemaType::kInt64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "regulator_disable";
+    event->group = "regulator";
+    event->proto_field_id = 60;
+    event->fields.push_back(MakeField("name", 1, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "regulator_disable_complete";
+    event->group = "regulator";
+    event->proto_field_id = 61;
+    event->fields.push_back(MakeField("name", 1, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "regulator_enable";
+    event->group = "regulator";
+    event->proto_field_id = 62;
+    event->fields.push_back(MakeField("name", 1, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "regulator_enable_complete";
+    event->group = "regulator";
+    event->proto_field_id = 63;
+    event->fields.push_back(MakeField("name", 1, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "regulator_enable_delay";
+    event->group = "regulator";
+    event->proto_field_id = 64;
+    event->fields.push_back(MakeField("name", 1, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "regulator_set_voltage";
+    event->group = "regulator";
+    event->proto_field_id = 65;
+    event->fields.push_back(MakeField("name", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("min", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("max", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "regulator_set_voltage_complete";
+    event->group = "regulator";
+    event->proto_field_id = 66;
+    event->fields.push_back(MakeField("name", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("val", 2, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "sched_switch";
+    event->group = "sched";
+    event->proto_field_id = 4;
+    event->fields.push_back(
+        MakeField("prev_comm", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("prev_pid", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("prev_prio", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("prev_state", 4, ProtoSchemaType::kInt64));
+    event->fields.push_back(
+        MakeField("next_comm", 5, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("next_pid", 6, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("next_prio", 7, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "sched_wakeup";
+    event->group = "sched";
+    event->proto_field_id = 17;
+    event->fields.push_back(MakeField("comm", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("pid", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("prio", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("success", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("target_cpu", 5, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "sched_blocked_reason";
+    event->group = "sched";
+    event->proto_field_id = 18;
+    event->fields.push_back(MakeField("pid", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("caller", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("io_wait", 3, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "sched_cpu_hotplug";
+    event->group = "sched";
+    event->proto_field_id = 19;
+    event->fields.push_back(
+        MakeField("affected_cpu", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("error", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("status", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "sched_waking";
+    event->group = "sched";
+    event->proto_field_id = 20;
+    event->fields.push_back(MakeField("comm", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("pid", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("prio", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("success", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("target_cpu", 5, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "sched_wakeup_new";
+    event->group = "sched";
+    event->proto_field_id = 114;
+    event->fields.push_back(MakeField("comm", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("pid", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("prio", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("success", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("target_cpu", 5, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "sched_process_exec";
+    event->group = "sched";
+    event->proto_field_id = 237;
+    event->fields.push_back(MakeField("filename", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("pid", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("old_pid", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "sched_process_exit";
+    event->group = "sched";
+    event->proto_field_id = 238;
+    event->fields.push_back(MakeField("comm", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("pid", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("tgid", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("prio", 4, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "sched_process_fork";
+    event->group = "sched";
+    event->proto_field_id = 239;
+    event->fields.push_back(
+        MakeField("parent_comm", 1, ProtoSchemaType::kString));
+    event->fields.push_back(
+        MakeField("parent_pid", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("child_comm", 3, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("child_pid", 4, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "sched_process_free";
+    event->group = "sched";
+    event->proto_field_id = 240;
+    event->fields.push_back(MakeField("comm", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("pid", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("prio", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "sched_process_hang";
+    event->group = "sched";
+    event->proto_field_id = 241;
+    event->fields.push_back(MakeField("comm", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("pid", 2, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "sched_process_wait";
+    event->group = "sched";
+    event->proto_field_id = 242;
+    event->fields.push_back(MakeField("comm", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("pid", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("prio", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "signal_deliver";
+    event->group = "signal";
+    event->proto_field_id = 324;
+    event->fields.push_back(MakeField("code", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("sa_flags", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("sig", 3, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "signal_generate";
+    event->group = "signal";
+    event->proto_field_id = 325;
+    event->fields.push_back(MakeField("code", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("comm", 2, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("group", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("pid", 4, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("result", 5, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("sig", 6, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "sync_pt";
+    event->group = "sync";
+    event->proto_field_id = 38;
+    event->fields.push_back(MakeField("timeline", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("value", 2, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "sync_timeline";
+    event->group = "sync";
+    event->proto_field_id = 39;
+    event->fields.push_back(MakeField("name", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("value", 2, ProtoSchemaType::kString));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "sync_wait";
+    event->group = "sync";
+    event->proto_field_id = 40;
+    event->fields.push_back(MakeField("name", 1, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("status", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("begin", 3, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "0";
+    event->group = "systrace";
+    event->proto_field_id = 331;
+    event->fields.push_back(MakeField("flag", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("name", 2, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("pid", 3, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("value", 4, ProtoSchemaType::kInt64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "task_newtask";
+    event->group = "task";
+    event->proto_field_id = 235;
+    event->fields.push_back(MakeField("pid", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("comm", 2, ProtoSchemaType::kString));
+    event->fields.push_back(
+        MakeField("clone_flags", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("oom_score_adj", 4, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "task_rename";
+    event->group = "task";
+    event->proto_field_id = 236;
+    event->fields.push_back(MakeField("pid", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("oldcomm", 2, ProtoSchemaType::kString));
+    event->fields.push_back(MakeField("newcomm", 3, ProtoSchemaType::kString));
+    event->fields.push_back(
+        MakeField("oom_score_adj", 4, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_vmscan_direct_reclaim_begin";
+    event->group = "vmscan";
+    event->proto_field_id = 46;
+    event->fields.push_back(MakeField("order", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("may_writepage", 2, ProtoSchemaType::kInt32));
+    event->fields.push_back(
+        MakeField("gfp_flags", 3, ProtoSchemaType::kUint32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_vmscan_direct_reclaim_end";
+    event->group = "vmscan";
+    event->proto_field_id = 47;
+    event->fields.push_back(
+        MakeField("nr_reclaimed", 1, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_vmscan_kswapd_wake";
+    event->group = "vmscan";
+    event->proto_field_id = 48;
+    event->fields.push_back(MakeField("nid", 1, ProtoSchemaType::kInt32));
+    event->fields.push_back(MakeField("order", 2, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "mm_vmscan_kswapd_sleep";
+    event->group = "vmscan";
+    event->proto_field_id = 49;
+    event->fields.push_back(MakeField("nid", 1, ProtoSchemaType::kInt32));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "workqueue_activate_work";
+    event->group = "workqueue";
+    event->proto_field_id = 56;
+    event->fields.push_back(MakeField("work", 1, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "workqueue_execute_end";
+    event->group = "workqueue";
+    event->proto_field_id = 57;
+    event->fields.push_back(MakeField("work", 1, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "workqueue_execute_start";
+    event->group = "workqueue";
+    event->proto_field_id = 58;
+    event->fields.push_back(MakeField("work", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("function", 2, ProtoSchemaType::kUint64));
+  }
+
+  {
+    events.emplace_back(Event{});
+    Event* event = &events.back();
+    event->name = "workqueue_queue_work";
+    event->group = "workqueue";
+    event->proto_field_id = 59;
+    event->fields.push_back(MakeField("work", 1, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("function", 2, ProtoSchemaType::kUint64));
+    event->fields.push_back(
+        MakeField("workqueue", 3, ProtoSchemaType::kUint64));
+    event->fields.push_back(MakeField("req_cpu", 4, ProtoSchemaType::kUint32));
+    event->fields.push_back(MakeField("cpu", 5, ProtoSchemaType::kUint32));
+  }
+
+  return events;
 }
 
 }  // namespace perfetto
diff --git a/src/traced/probes/ftrace/event_info_constants.cc b/src/traced/probes/ftrace/event_info_constants.cc
index 5c020d9..f87b5fc 100644
--- a/src/traced/probes/ftrace/event_info_constants.cc
+++ b/src/traced/probes/ftrace/event_info_constants.cc
@@ -19,22 +19,18 @@
 namespace perfetto {
 using protozero::proto_utils::ProtoSchemaType;
 
-namespace {
-Field StaticField(const char* ftrace_name,
-                  uint32_t proto_field_id,
-                  ProtoSchemaType proto_field_type) {
+Field MakeField(const char* name, uint32_t id, ProtoSchemaType type) {
   Field field{};
-  field.ftrace_name = ftrace_name;
-  field.proto_field_id = proto_field_id;
-  field.proto_field_type = proto_field_type;
+  field.ftrace_name = name;
+  field.proto_field_id = id;
+  field.proto_field_type = type;
   return field;
 }
-}  // namespace
 
 std::vector<Field> GetStaticCommonFieldsInfo() {
   std::vector<Field> fields;
 
-  fields.push_back(StaticField("common_pid", 2, ProtoSchemaType::kInt32));
+  fields.push_back(MakeField("common_pid", 2, ProtoSchemaType::kInt32));
 
   return fields;
 }
diff --git a/src/traced/probes/ftrace/event_info_constants.h b/src/traced/probes/ftrace/event_info_constants.h
index 923ee62..ef1e51d 100644
--- a/src/traced/probes/ftrace/event_info_constants.h
+++ b/src/traced/probes/ftrace/event_info_constants.h
@@ -28,8 +28,7 @@
 namespace perfetto {
 
 enum FtraceFieldType {
-  kInvalidFtraceFieldType = 0,
-  kFtraceUint8,
+  kFtraceUint8 = 1,
   kFtraceUint16,
   kFtraceUint32,
   kFtraceUint64,
@@ -54,8 +53,7 @@
 // where there exists a way to convert from the FtraceFieldType
 // into the ProtoFieldType.
 enum TranslationStrategy {
-  kInvalidTranslationStrategy = 0,
-  kUint8ToUint32,
+  kUint8ToUint32 = 1,
   kUint8ToUint64,
   kUint16ToUint32,
   kUint16ToUint64,
@@ -125,13 +123,17 @@
       return "devid64";
     case kFtraceDataLoc:
       return "__data_loc";
-    case kInvalidFtraceFieldType:
-      break;
   }
-  PERFETTO_FATAL("Unexpected ftrace field type.");
+  // For gcc:
+  PERFETTO_FATAL("Not reached");
+  return "";
 }
 
 struct Field {
+  Field() = default;
+  Field(uint16_t offset, uint16_t size)
+      : ftrace_offset(offset), ftrace_size(size) {}
+
   uint16_t ftrace_offset;
   uint16_t ftrace_size;
   FtraceFieldType ftrace_type;
@@ -144,6 +146,10 @@
 };
 
 struct Event {
+  Event() = default;
+  Event(const char* event_name, const char* event_group)
+      : name(event_name), group(event_group) {}
+
   const char* name;
   const char* group;
   std::vector<Field> fields;
@@ -167,6 +173,10 @@
                             protozero::proto_utils::ProtoSchemaType proto,
                             TranslationStrategy* out);
 
+Field MakeField(const char* name,
+                uint32_t id,
+                protozero::proto_utils::ProtoSchemaType type);
+
 }  // namespace perfetto
 
 #endif  // SRC_TRACED_PROBES_FTRACE_EVENT_INFO_CONSTANTS_H_
diff --git a/src/traced/probes/ftrace/event_info_unittest.cc b/src/traced/probes/ftrace/event_info_unittest.cc
index 6c3f9d8..76d3d78 100644
--- a/src/traced/probes/ftrace/event_info_unittest.cc
+++ b/src/traced/probes/ftrace/event_info_unittest.cc
@@ -15,9 +15,9 @@
  */
 
 #include "src/traced/probes/ftrace/event_info.h"
-
 #include "perfetto/protozero/proto_utils.h"
-#include "test/gtest_and_gmock.h"
+
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace {
diff --git a/src/traced/probes/ftrace/format_parser.cc b/src/traced/probes/ftrace/format_parser.cc
index c5ce2c1..6cb1ee3 100644
--- a/src/traced/probes/ftrace/format_parser.cc
+++ b/src/traced/probes/ftrace/format_parser.cc
@@ -25,8 +25,8 @@
 #include <vector>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/string_splitter.h"
+#include "perfetto/base/utils.h"
 
 namespace perfetto {
 namespace {
diff --git a/src/traced/probes/ftrace/format_parser_unittest.cc b/src/traced/probes/ftrace/format_parser_unittest.cc
index 3e92f67..17a8e84 100644
--- a/src/traced/probes/ftrace/format_parser_unittest.cc
+++ b/src/traced/probes/ftrace/format_parser_unittest.cc
@@ -15,7 +15,8 @@
  */
 #include "src/traced/probes/ftrace/format_parser.h"
 
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace {
diff --git a/src/traced/probes/ftrace/ftrace_config.cc b/src/traced/probes/ftrace/ftrace_config.cc
new file mode 100644
index 0000000..365a94e
--- /dev/null
+++ b/src/traced/probes/ftrace/ftrace_config.cc
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+#include "src/traced/probes/ftrace/ftrace_config.h"
+
+#include "perfetto/base/logging.h"
+
+namespace perfetto {
+namespace {
+
+bool IsGoodFtracePunctuation(char c) {
+  return c == '_' || c == '/' || c == '*';
+}
+
+bool IsGoodAtracePunctuation(char c) {
+  return c == '_' || c == '.' || c == '*';
+}
+
+bool IsValidAtraceEventName(const std::string& str) {
+  for (size_t i = 0; i < str.size(); i++) {
+    if (!isalnum(str[i]) && !IsGoodAtracePunctuation(str[i]))
+      return false;
+  }
+  return true;
+}
+
+bool IsValidFtraceEventName(const std::string& str) {
+  int slash_count = 0;
+  for (size_t i = 0; i < str.size(); i++) {
+    if (!isalnum(str[i]) && !IsGoodFtracePunctuation(str[i]))
+      return false;
+    if (str[i] == '/') {
+      slash_count++;
+      // At most one '/' allowed and not at the beginning or end.
+      if (slash_count > 1 || i == 0 || i == str.size() - 1)
+        return false;
+    }
+    if (str[i] == '*' && i != str.size() - 1)
+      return false;
+  }
+  return true;
+}
+
+}  // namespace
+
+FtraceConfig CreateFtraceConfig(std::set<std::string> names) {
+  FtraceConfig config;
+  for (const std::string& name : names)
+    *config.add_ftrace_events() = name;
+  return config;
+}
+
+bool RequiresAtrace(const FtraceConfig& config) {
+  return !config.atrace_categories().empty() || !config.atrace_apps().empty();
+}
+
+bool ValidConfig(const FtraceConfig& config) {
+  for (const std::string& event_name : config.ftrace_events()) {
+    if (!IsValidFtraceEventName(event_name)) {
+      PERFETTO_ELOG("Bad event name '%s'", event_name.c_str());
+      return false;
+    }
+  }
+  for (const std::string& category : config.atrace_categories()) {
+    if (!IsValidAtraceEventName(category)) {
+      PERFETTO_ELOG("Bad category name '%s'", category.c_str());
+      return false;
+    }
+  }
+  for (const std::string& app : config.atrace_apps()) {
+    if (!IsValidAtraceEventName(app)) {
+      PERFETTO_ELOG("Bad app '%s'", app.c_str());
+      return false;
+    }
+  }
+  return true;
+}
+
+}  // namespace perfetto
diff --git a/src/traced/probes/ftrace/ftrace_config.h b/src/traced/probes/ftrace/ftrace_config.h
new file mode 100644
index 0000000..f43ac1f
--- /dev/null
+++ b/src/traced/probes/ftrace/ftrace_config.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_TRACED_PROBES_FTRACE_FTRACE_CONFIG_H_
+#define SRC_TRACED_PROBES_FTRACE_FTRACE_CONFIG_H_
+
+#include <set>
+#include <string>
+
+#include "perfetto/tracing/core/ftrace_config.h"
+
+namespace perfetto {
+
+// 0 is invalid.
+using FtraceConfigId = uint64_t;
+
+// Utility method for the common case where we don't care about atrace events.
+FtraceConfig CreateFtraceConfig(std::set<std::string> names);
+
+// Returns true iff the config has any atrace categories or apps.
+bool RequiresAtrace(const FtraceConfig&);
+
+bool ValidConfig(const FtraceConfig& config);
+
+}  // namespace perfetto
+
+#endif  // SRC_TRACED_PROBES_FTRACE_FTRACE_CONFIG_H_
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer.cc b/src/traced/probes/ftrace/ftrace_config_muxer.cc
index cc97bf2..ee721a7 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer.cc
+++ b/src/traced/probes/ftrace/ftrace_config_muxer.cc
@@ -23,20 +23,18 @@
 
 #include <algorithm>
 
-#include "perfetto/ext/base/utils.h"
-#include "protos/perfetto/trace/ftrace/sched.pbzero.h"
+#include "perfetto/base/utils.h"
 #include "src/traced/probes/ftrace/atrace_wrapper.h"
-#include "src/traced/probes/ftrace/compact_sched.h"
 
 namespace perfetto {
 namespace {
 
-constexpr int kDefaultPerCpuBufferSizeKb = 2 * 1024;  // 2mb
-constexpr int kMaxPerCpuBufferSizeKb = 64 * 1024;     // 64mb
-
 // trace_clocks in preference order.
 constexpr const char* kClocks[] = {"boot", "global", "local"};
 
+constexpr int kDefaultPerCpuBufferSizeKb = 2 * 1024;  // 2mb
+constexpr int kMaxPerCpuBufferSizeKb = 64 * 1024;  // 64mb
+
 void AddEventGroup(const ProtoTranslationTable* table,
                    const std::string& group,
                    std::set<GroupAndName>* to) {
@@ -107,39 +105,7 @@
     for (const std::string& category : request.atrace_categories()) {
       if (category == "gfx") {
         AddEventGroup(table, "mdss", &events);
-        events.insert(GroupAndName("mdss", "rotator_bw_ao_as_context"));
-        events.insert(GroupAndName("mdss", "mdp_trace_counter"));
-        events.insert(GroupAndName("mdss", "tracing_mark_write"));
-        events.insert(GroupAndName("mdss", "mdp_cmd_wait_pingpong"));
-        events.insert(GroupAndName("mdss", "mdp_cmd_kickoff"));
-        events.insert(GroupAndName("mdss", "mdp_cmd_release_bw"));
-        events.insert(GroupAndName("mdss", "mdp_cmd_readptr_done"));
-        events.insert(GroupAndName("mdss", "mdp_cmd_pingpong_done"));
-        events.insert(GroupAndName("mdss", "mdp_misr_crc"));
-        events.insert(GroupAndName("mdss", "mdp_compare_bw"));
-        events.insert(GroupAndName("mdss", "mdp_perf_update_bus"));
-        events.insert(GroupAndName("mdss", "mdp_video_underrun_done"));
-        events.insert(GroupAndName("mdss", "mdp_commit"));
-        events.insert(GroupAndName("mdss", "mdp_mixer_update"));
-        events.insert(GroupAndName("mdss", "mdp_perf_prefill_calc"));
-        events.insert(GroupAndName("mdss", "mdp_perf_set_ot"));
-        events.insert(GroupAndName("mdss", "mdp_perf_set_wm_levels"));
-        events.insert(GroupAndName("mdss", "mdp_perf_set_panic_luts"));
-        events.insert(GroupAndName("mdss", "mdp_perf_set_qos_luts"));
-        events.insert(GroupAndName("mdss", "mdp_sspp_change"));
-        events.insert(GroupAndName("mdss", "mdp_sspp_set"));
-        AddEventGroup(table, "mali_systrace", &events);
         AddEventGroup(table, "sde", &events);
-        events.insert(GroupAndName("sde", "tracing_mark_write"));
-        events.insert(GroupAndName("sde", "sde_perf_update_bus"));
-        events.insert(GroupAndName("sde", "sde_perf_set_qos_luts"));
-        events.insert(GroupAndName("sde", "sde_perf_set_ot"));
-        events.insert(GroupAndName("sde", "sde_perf_set_danger_luts"));
-        events.insert(GroupAndName("sde", "sde_perf_crtc_update"));
-        events.insert(GroupAndName("sde", "sde_perf_calc_crtc"));
-        events.insert(GroupAndName("sde", "sde_evtlog"));
-        events.insert(GroupAndName("sde", "sde_encoder_underrun"));
-        events.insert(GroupAndName("sde", "sde_cmd_release_bw"));
         continue;
       }
 
@@ -156,44 +122,19 @@
         events.insert(GroupAndName("sched", "sched_cpu_hotplug"));
         events.insert(GroupAndName("sched", "sched_pi_setprio"));
         events.insert(GroupAndName("sched", "sched_process_exit"));
+        events.insert(GroupAndName("systrace", "0"));
         AddEventGroup(table, "cgroup", &events);
-        events.insert(GroupAndName("cgroup", "cgroup_transfer_tasks"));
-        events.insert(GroupAndName("cgroup", "cgroup_setup_root"));
-        events.insert(GroupAndName("cgroup", "cgroup_rmdir"));
-        events.insert(GroupAndName("cgroup", "cgroup_rename"));
-        events.insert(GroupAndName("cgroup", "cgroup_remount"));
-        events.insert(GroupAndName("cgroup", "cgroup_release"));
-        events.insert(GroupAndName("cgroup", "cgroup_mkdir"));
-        events.insert(GroupAndName("cgroup", "cgroup_destroy_root"));
-        events.insert(GroupAndName("cgroup", "cgroup_attach_task"));
         events.insert(GroupAndName("oom", "oom_score_adj_update"));
         events.insert(GroupAndName("task", "task_rename"));
         events.insert(GroupAndName("task", "task_newtask"));
-
         AddEventGroup(table, "systrace", &events);
-        events.insert(GroupAndName("systrace", "0"));
-
         AddEventGroup(table, "scm", &events);
-        events.insert(GroupAndName("scm", "scm_call_start"));
-        events.insert(GroupAndName("scm", "scm_call_end"));
         continue;
       }
 
       if (category == "irq") {
         AddEventGroup(table, "irq", &events);
-        events.insert(GroupAndName("irq", "tasklet_hi_exit"));
-        events.insert(GroupAndName("irq", "tasklet_hi_entry"));
-        events.insert(GroupAndName("irq", "tasklet_exit"));
-        events.insert(GroupAndName("irq", "tasklet_entry"));
-        events.insert(GroupAndName("irq", "softirq_raise"));
-        events.insert(GroupAndName("irq", "softirq_exit"));
-        events.insert(GroupAndName("irq", "softirq_entry"));
-        events.insert(GroupAndName("irq", "irq_handler_exit"));
-        events.insert(GroupAndName("irq", "irq_handler_entry"));
         AddEventGroup(table, "ipi", &events);
-        events.insert(GroupAndName("ipi", "ipi_raise"));
-        events.insert(GroupAndName("ipi", "ipi_exit"));
-        events.insert(GroupAndName("ipi", "ipi_entry"));
         continue;
       }
 
@@ -234,15 +175,6 @@
         events.insert(GroupAndName("power", "cpu_frequency_limits"));
         events.insert(GroupAndName("power", "suspend_resume"));
         AddEventGroup(table, "msm_bus", &events);
-        events.insert(GroupAndName("msm_bus", "bus_update_request_end"));
-        events.insert(GroupAndName("msm_bus", "bus_update_request"));
-        events.insert(GroupAndName("msm_bus", "bus_rules_matches"));
-        events.insert(GroupAndName("msm_bus", "bus_max_votes"));
-        events.insert(GroupAndName("msm_bus", "bus_client_status"));
-        events.insert(GroupAndName("msm_bus", "bus_bke_params"));
-        events.insert(GroupAndName("msm_bus", "bus_bimc_config_limiter"));
-        events.insert(GroupAndName("msm_bus", "bus_avail_bw"));
-        events.insert(GroupAndName("msm_bus", "bus_agg_bw"));
         continue;
       }
 
@@ -283,19 +215,8 @@
       if (category == "sync") {
         // linux kernel < 4.9
         AddEventGroup(table, "sync", &events);
-        events.insert(GroupAndName("sync", "sync_pt"));
-        events.insert(GroupAndName("sync", "sync_timeline"));
-        events.insert(GroupAndName("sync", "sync_wait"));
         // linux kernel == 4.9.x
         AddEventGroup(table, "fence", &events);
-        events.insert(GroupAndName("fence", "fence_annotate_wait_on"));
-        events.insert(GroupAndName("fence", "fence_destroy"));
-        events.insert(GroupAndName("fence", "fence_emit"));
-        events.insert(GroupAndName("fence", "fence_enable_signal"));
-        events.insert(GroupAndName("fence", "fence_init"));
-        events.insert(GroupAndName("fence", "fence_signaled"));
-        events.insert(GroupAndName("fence", "fence_wait_end"));
-        events.insert(GroupAndName("fence", "fence_wait_start"));
         // linux kernel > 4.9
         AddEventGroup(table, "dma_fence", &events);
         continue;
@@ -303,10 +224,6 @@
 
       if (category == "workq") {
         AddEventGroup(table, "workqueue", &events);
-        events.insert(GroupAndName("workqueue", "workqueue_queue_work"));
-        events.insert(GroupAndName("workqueue", "workqueue_execute_start"));
-        events.insert(GroupAndName("workqueue", "workqueue_execute_end"));
-        events.insert(GroupAndName("workqueue", "workqueue_activate_work"));
         continue;
       }
 
@@ -316,20 +233,11 @@
         events.insert(GroupAndName("vmscan", "mm_vmscan_kswapd_wake"));
         events.insert(GroupAndName("vmscan", "mm_vmscan_kswapd_sleep"));
         AddEventGroup(table, "lowmemorykiller", &events);
-        events.insert(GroupAndName("lowmemorykiller", "lowmemory_kill"));
         continue;
       }
 
       if (category == "regulators") {
         AddEventGroup(table, "regulator", &events);
-        events.insert(
-            GroupAndName("regulator", "regulator_set_voltage_complete"));
-        events.insert(GroupAndName("regulator", "regulator_set_voltage"));
-        events.insert(GroupAndName("regulator", "regulator_enable_delay"));
-        events.insert(GroupAndName("regulator", "regulator_enable_complete"));
-        events.insert(GroupAndName("regulator", "regulator_enable"));
-        events.insert(GroupAndName("regulator", "regulator_disable_complete"));
-        events.insert(GroupAndName("regulator", "regulator_disable"));
         continue;
       }
 
@@ -350,13 +258,6 @@
 
       if (category == "pagecache") {
         AddEventGroup(table, "filemap", &events);
-        events.insert(
-            GroupAndName("filemap", "mm_filemap_delete_from_page_cache"));
-        events.insert(
-            GroupAndName("filemap", "mm_filemap_delete_from_page_cache"));
-        events.insert(GroupAndName("filemap", "mm_filemap_add_to_page_cache"));
-        events.insert(GroupAndName("filemap", "filemap_set_wb_err"));
-        events.insert(GroupAndName("filemap", "file_check_and_advance_wb_err"));
         continue;
       }
 
@@ -394,15 +295,19 @@
 
 FtraceConfigMuxer::FtraceConfigMuxer(FtraceProcfs* ftrace,
                                      ProtoTranslationTable* table)
-    : ftrace_(ftrace), table_(table), current_state_(), ds_configs_() {}
+    : ftrace_(ftrace),
+      table_(table),
+      current_state_(),
+      filters_(),
+      configs_() {}
 FtraceConfigMuxer::~FtraceConfigMuxer() = default;
 
 FtraceConfigId FtraceConfigMuxer::SetupConfig(const FtraceConfig& request) {
   EventFilter filter;
+  FtraceConfig actual;
   bool is_ftrace_enabled = ftrace_->IsTracingEnabled();
-  if (ds_configs_.empty()) {
+  if (configs_.empty()) {
     PERFETTO_DCHECK(active_configs_.empty());
-
     PERFETTO_DCHECK(!current_state_.tracing_on);
 
     // If someone outside of perfetto is using ftrace give up now.
@@ -431,35 +336,29 @@
                     group_and_name.ToString().c_str());
       continue;
     }
-    // Note: ftrace events are always implicitly enabled (and don't have an
-    // "enable" file). So they aren't tracked by the central event filter (but
-    // still need to be added to the per data source event filter to retain the
-    // events during parsing).
     if (current_state_.ftrace_events.IsEventEnabled(event->ftrace_event_id) ||
         std::string("ftrace") == event->group) {
       filter.AddEnabledEvent(event->ftrace_event_id);
+      *actual.add_ftrace_events() = group_and_name.ToString();
       continue;
     }
     if (ftrace_->EnableEvent(event->group, event->name)) {
       current_state_.ftrace_events.AddEnabledEvent(event->ftrace_event_id);
       filter.AddEnabledEvent(event->ftrace_event_id);
+      *actual.add_ftrace_events() = group_and_name.ToString();
     } else {
       PERFETTO_DPLOG("Failed to enable %s.", group_and_name.ToString().c_str());
     }
   }
 
-  auto compact_sched =
-      CreateCompactSchedConfig(request, table_->compact_sched_format());
-
   FtraceConfigId id = ++last_id_;
-  ds_configs_.emplace(std::piecewise_construct, std::forward_as_tuple(id),
-                      std::forward_as_tuple(std::move(filter), compact_sched));
-
+  configs_.emplace(id, std::move(actual));
+  filters_.emplace(id, std::move(filter));
   return id;
 }
 
 bool FtraceConfigMuxer::ActivateConfig(FtraceConfigId id) {
-  if (!id || ds_configs_.count(id) == 0) {
+  if (!id || configs_.count(id) == 0) {
     PERFETTO_DFATAL("Config not found");
     return false;
   }
@@ -482,11 +381,11 @@
 }
 
 bool FtraceConfigMuxer::RemoveConfig(FtraceConfigId config_id) {
-  if (!config_id || !ds_configs_.erase(config_id))
+  if (!config_id || !filters_.erase(config_id) || !configs_.erase(config_id))
     return false;
   EventFilter expected_ftrace_events;
-  for (const auto& ds_config : ds_configs_) {
-    expected_ftrace_events.EnableEventsFrom(ds_config.second.event_filter);
+  for (const auto& id_filter : filters_) {
+    expected_ftrace_events.EnableEventsFrom(id_filter.second);
   }
 
   // Disable any events that are currently enabled, but are not in any configs
@@ -517,9 +416,8 @@
   // Even if we don't have any other active configs, we might still have idle
   // configs around. Tear down the rest of the ftrace config only if all
   // configs are removed.
-  if (ds_configs_.empty()) {
-    if (ftrace_->SetCpuBufferSizeInPages(1))
-      current_state_.cpu_buffer_size_pages = 1;
+  if (configs_.empty()) {
+    ftrace_->SetCpuBufferSizeInPages(0);
     ftrace_->DisableAllEvents();
     ftrace_->ClearTrace();
     if (current_state_.atrace_on)
@@ -529,11 +427,16 @@
   return true;
 }
 
-const FtraceDataSourceConfig* FtraceConfigMuxer::GetDataSourceConfig(
-    FtraceConfigId id) {
-  if (!ds_configs_.count(id))
+const FtraceConfig* FtraceConfigMuxer::GetConfigForTesting(FtraceConfigId id) {
+  if (!configs_.count(id))
     return nullptr;
-  return &ds_configs_.at(id);
+  return &configs_.at(id);
+}
+
+const EventFilter* FtraceConfigMuxer::GetEventFilter(FtraceConfigId id) {
+  if (!filters_.count(id))
+    return nullptr;
+  return &filters_.at(id);
 }
 
 void FtraceConfigMuxer::SetupClock(const FtraceConfig&) {
@@ -557,10 +460,6 @@
   current_state_.cpu_buffer_size_pages = pages;
 }
 
-size_t FtraceConfigMuxer::GetPerCpuBufferSizePages() {
-  return current_state_.cpu_buffer_size_pages;
-}
-
 void FtraceConfigMuxer::UpdateAtrace(const FtraceConfig& request) {
   PERFETTO_DLOG("Update atrace config...");
 
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer.h b/src/traced/probes/ftrace/ftrace_config_muxer.h
index 416a38b..7c70720 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer.h
+++ b/src/traced/probes/ftrace/ftrace_config_muxer.h
@@ -20,41 +20,27 @@
 #include <map>
 #include <set>
 
-#include "src/traced/probes/ftrace/compact_sched.h"
-#include "src/traced/probes/ftrace/ftrace_config_utils.h"
+#include "src/traced/probes/ftrace/ftrace_config.h"
 #include "src/traced/probes/ftrace/ftrace_controller.h"
 #include "src/traced/probes/ftrace/ftrace_procfs.h"
 #include "src/traced/probes/ftrace/proto_translation_table.h"
 
 namespace perfetto {
 
-// State held by the muxer per data source, used to parse ftrace according to
-// that data source's config.
-struct FtraceDataSourceConfig {
-  FtraceDataSourceConfig(EventFilter _event_filter,
-                         CompactSchedConfig _compact_sched)
-      : event_filter(std::move(_event_filter)), compact_sched(_compact_sched) {}
-
-  // The event filter allows to quickly check if a certain ftrace event with id
-  // x is enabled for this data source.
-  EventFilter event_filter;
-
-  // Configuration of the optional compact encoding of scheduling events.
-  const CompactSchedConfig compact_sched;
-};
-
-// Ftrace is a bunch of globally modifiable persistent state.
+// Ftrace is a bunch of globaly modifiable persistent state.
 // Given a number of FtraceConfig's we need to find the best union of all
-// the settings to make everyone happy while also watching out for anybody
+// the settings to make eveyone happy while also watching out for anybody
 // messing with the ftrace settings at the same time as us.
-//
+
 // Specifically FtraceConfigMuxer takes in a *requested* FtraceConfig
 // (|SetupConfig|), makes a best effort attempt to modify the ftrace
-// debugfs files to honor those settings without interrupting other perfetto
+// debugfs files to honor those settings without interupting other perfetto
 // traces already in progress or other users of ftrace, then returns an
 // FtraceConfigId representing that config or zero on failure.
-//
-// When you are finished with a config you can signal that with |RemoveConfig|.
+
+// To see which settings we actually managed to set you can call |GetConfig|
+// and when you are finished with a config you can signal that with
+// |RemoveConfig|.
 class FtraceConfigMuxer {
  public:
   // The FtraceConfigMuxer and ProtoTranslationTable
@@ -67,9 +53,10 @@
   // config or zero on failure.
   // This is best effort. FtraceConfigMuxer may not be able to adjust the
   // buffer size right now. Events may be missing or there may be extra events
-  // (if you enable an atrace category we try to give you the matching events).
+  // (if you enable an atrace catagory we try to give you the matching events).
   // If someone else is tracing we won't touch atrace (since it resets the
   // buffer).
+  // To see the config you ended up with use |GetConfig|.
   FtraceConfigId SetupConfig(const FtraceConfig& request);
 
   // Activate ftrace for the given config (if not already active).
@@ -79,32 +66,26 @@
   // or already removed.
   bool RemoveConfig(FtraceConfigId);
 
-  const FtraceDataSourceConfig* GetDataSourceConfig(FtraceConfigId id);
-
-  // Returns the current per-cpu buffer size, as configured by this muxer
-  // (without consulting debugfs). Constant for a given tracing session.
-  // Note that if there are multiple concurrent tracing sessions, the first
-  // session's buffer size is used for all of them.
-  size_t GetPerCpuBufferSizePages();
+  const EventFilter* GetEventFilter(FtraceConfigId id);
 
   // public for testing
   void SetupClockForTesting(const FtraceConfig& request) {
     SetupClock(request);
   }
 
+  const FtraceConfig* GetConfigForTesting(FtraceConfigId id);
+
   std::set<GroupAndName> GetFtraceEventsForTesting(
       const FtraceConfig& request,
       const ProtoTranslationTable* table) {
     return GetFtraceEvents(request, table);
   }
 
-  const EventFilter* GetCentralEventFilterForTesting() const {
-    return &current_state_.ftrace_events;
-  }
-
  private:
   struct FtraceState {
     EventFilter ftrace_events;
+    std::set<std::string> atrace_categories;
+    std::set<std::string> atrace_apps;
     bool tracing_on = false;
     bool atrace_on = false;
     size_t cpu_buffer_size_pages = 0;
@@ -133,13 +114,16 @@
 
   FtraceState current_state_;
 
-  // Set of all requested tracing configurations, with the associated derived
-  // data used during parsing. Note that not all of these configurations might
-  // be active. When a config is present but not active, we do setup buffer
-  // sizes and events, but don't enable ftrace (i.e. tracing_on).
-  std::map<FtraceConfigId, FtraceDataSourceConfig> ds_configs_;
+  // There is a filter per config. These filters allow a quick way
+  // to check if a certain ftrace event with id x is enabled.
+  std::map<FtraceConfigId, EventFilter> filters_;
 
-  // Subset of |ds_configs_| that are currently active. At any time ftrace is
+  // Set of all configurations. Note that not all of them might be active.
+  // When a config is present but not active, we do setup buffer sizes and
+  // events, but don't enable ftrace (i.e. tracing_on).
+  std::map<FtraceConfigId, FtraceConfig> configs_;
+
+  // Subset of |configs_| that are currently active. At any time ftrace is
   // enabled iff |active_configs_| is not empty.
   std::set<FtraceConfigId> active_configs_;
 };
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc b/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
index 890e07a..936d02c 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
+++ b/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
@@ -18,11 +18,11 @@
 
 #include <memory>
 
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 #include "src/traced/probes/ftrace/atrace_wrapper.h"
-#include "src/traced/probes/ftrace/compact_sched.h"
 #include "src/traced/probes/ftrace/ftrace_procfs.h"
 #include "src/traced/probes/ftrace/proto_translation_table.h"
-#include "test/gtest_and_gmock.h"
 
 using testing::_;
 using testing::AnyNumber;
@@ -34,6 +34,7 @@
 using testing::NiceMock;
 using testing::Not;
 using testing::Return;
+using testing::UnorderedElementsAre;
 
 namespace perfetto {
 namespace {
@@ -78,13 +79,11 @@
   MockProtoTranslationTable(NiceMock<MockFtraceProcfs>* ftrace_procfs,
                             const std::vector<Event>& events,
                             std::vector<Field> common_fields,
-                            FtracePageHeaderSpec ftrace_page_header_spec,
-                            CompactSchedEventFormat compact_sched_format)
+                            FtracePageHeaderSpec ftrace_page_header_spec)
       : ProtoTranslationTable(ftrace_procfs,
                               events,
                               common_fields,
-                              ftrace_page_header_spec,
-                              compact_sched_format) {}
+                              ftrace_page_header_spec) {}
   MOCK_METHOD1(GetOrCreateEvent, Event*(const GroupAndName& group_and_name));
   MOCK_CONST_METHOD1(GetEvent,
                      const Event*(const GroupAndName& group_and_name));
@@ -98,24 +97,16 @@
     return std::unique_ptr<MockProtoTranslationTable>(
         new MockProtoTranslationTable(
             &table_procfs_, events, std::move(common_fields),
-            ProtoTranslationTable::DefaultPageHeaderSpecForTesting(),
-            InvalidCompactSchedEventFormatForTesting()));
+            ProtoTranslationTable::DefaultPageHeaderSpecForTesting()));
   }
-
-  static constexpr int kFakeSchedSwitchEventId = 1;
-  static constexpr int kCgroupMkdirEventId = 12;
-  static constexpr int kFakePrintEventId = 20;
-
-  std::unique_ptr<ProtoTranslationTable> CreateFakeTable(
-      CompactSchedEventFormat compact_format =
-          InvalidCompactSchedEventFormatForTesting()) {
+  std::unique_ptr<ProtoTranslationTable> CreateFakeTable() {
     std::vector<Field> common_fields;
     std::vector<Event> events;
     {
       Event event;
       event.name = "sched_switch";
       event.group = "sched";
-      event.ftrace_event_id = kFakeSchedSwitchEventId;
+      event.ftrace_event_id = 1;
       events.push_back(event);
     }
 
@@ -139,7 +130,7 @@
       Event event;
       event.name = "cgroup_mkdir";
       event.group = "cgroup";
-      event.ftrace_event_id = kCgroupMkdirEventId;
+      event.ftrace_event_id = 12;
       events.push_back(event);
     }
 
@@ -163,14 +154,13 @@
       Event event;
       event.name = "print";
       event.group = "ftrace";
-      event.ftrace_event_id = kFakePrintEventId;
+      event.ftrace_event_id = 20;
       events.push_back(event);
     }
 
     return std::unique_ptr<ProtoTranslationTable>(new ProtoTranslationTable(
         &table_procfs_, events, std::move(common_fields),
-        ProtoTranslationTable::DefaultPageHeaderSpecForTesting(),
-        compact_format));
+        ProtoTranslationTable::DefaultPageHeaderSpecForTesting()));
   }
 
   NiceMock<MockFtraceProcfs> table_procfs_;
@@ -215,11 +205,10 @@
   EXPECT_CALL(*mock_table, GetEvent(GroupAndName("power", "cpu_frequency")))
       .Times(AnyNumber());
 
-  static constexpr int kExpectedEventId = 77;
   Event event_to_return;
   event_to_return.name = "cpu_frequency";
   event_to_return.group = "power";
-  event_to_return.ftrace_event_id = kExpectedEventId;
+  event_to_return.ftrace_event_id = 1;
   ON_CALL(*mock_table, GetOrCreateEvent(GroupAndName("power", "cpu_frequency")))
       .WillByDefault(Return(&event_to_return));
   EXPECT_CALL(*mock_table,
@@ -227,15 +216,9 @@
 
   FtraceConfigId id = model.SetupConfig(config);
   ASSERT_TRUE(model.ActivateConfig(id));
-
-  const FtraceDataSourceConfig* ds_config = model.GetDataSourceConfig(id);
-  ASSERT_TRUE(ds_config);
-  ASSERT_THAT(ds_config->event_filter.GetEnabledEvents(),
-              ElementsAreArray({kExpectedEventId}));
-
-  const EventFilter* central_filter = model.GetCentralEventFilterForTesting();
-  ASSERT_THAT(central_filter->GetEnabledEvents(),
-              ElementsAreArray({kExpectedEventId}));
+  const FtraceConfig* actual_config = model.GetConfigForTesting(id);
+  EXPECT_TRUE(actual_config);
+  EXPECT_THAT(actual_config->ftrace_events(), Contains("power/cpu_frequency"));
 }
 
 TEST_F(FtraceConfigMuxerTest, AddSameNameEvents) {
@@ -246,34 +229,28 @@
 
   FtraceConfigMuxer model(&ftrace, mock_table.get());
 
-  static constexpr int kEventId1 = 1;
   Event event1;
   event1.name = "foo";
   event1.group = "group_one";
-  event1.ftrace_event_id = kEventId1;
+  event1.ftrace_event_id = 1;
   ON_CALL(*mock_table, GetOrCreateEvent(GroupAndName("group_one", "foo")))
       .WillByDefault(Return(&event1));
   EXPECT_CALL(*mock_table, GetOrCreateEvent(GroupAndName("group_one", "foo")));
 
-  static constexpr int kEventId2 = 2;
   Event event2;
   event2.name = "foo";
   event2.group = "group_two";
-  event2.ftrace_event_id = kEventId2;
+  event2.ftrace_event_id = 2;
   ON_CALL(*mock_table, GetOrCreateEvent(GroupAndName("group_two", "foo")))
       .WillByDefault(Return(&event2));
   EXPECT_CALL(*mock_table, GetOrCreateEvent(GroupAndName("group_two", "foo")));
 
   FtraceConfigId id = model.SetupConfig(config);
   ASSERT_TRUE(model.ActivateConfig(id));
-
-  const FtraceDataSourceConfig* ds_config = model.GetDataSourceConfig(id);
-  ASSERT_THAT(ds_config->event_filter.GetEnabledEvents(),
-              ElementsAreArray({kEventId1, kEventId2}));
-
-  const EventFilter* central_filter = model.GetCentralEventFilterForTesting();
-  ASSERT_THAT(central_filter->GetEnabledEvents(),
-              ElementsAreArray({kEventId1, kEventId2}));
+  const FtraceConfig* actual_config = model.GetConfigForTesting(id);
+  EXPECT_TRUE(actual_config);
+  EXPECT_THAT(actual_config->ftrace_events(), Contains("group_one/foo"));
+  EXPECT_THAT(actual_config->ftrace_events(), Contains("group_two/foo"));
 }
 
 TEST_F(FtraceConfigMuxerTest, AddAllEvents) {
@@ -305,9 +282,9 @@
   EXPECT_CALL(ftrace, GetEventNamesForGroup("events/sched")).Times(1);
 
   // Non-generic event.
-  static constexpr int kSchedSwitchEventId = 1;
-  Event sched_switch = {"sched_switch", "sched", {}, 0, 0, 0};
-  sched_switch.ftrace_event_id = kSchedSwitchEventId;
+  std::map<std::string, const Event*> events;
+  Event sched_switch = {"sched_switch", "sched"};
+  sched_switch.ftrace_event_id = 1;
   ON_CALL(*mock_table, GetOrCreateEvent(GroupAndName("sched", "sched_switch")))
       .WillByDefault(Return(&sched_switch));
   EXPECT_CALL(*mock_table,
@@ -315,11 +292,10 @@
       .Times(AnyNumber());
 
   // Generic event.
-  static constexpr int kGenericEventId = 2;
   Event event_to_return;
   event_to_return.name = "sched_new_event";
   event_to_return.group = "sched";
-  event_to_return.ftrace_event_id = kGenericEventId;
+  event_to_return.ftrace_event_id = 2;
   ON_CALL(*mock_table,
           GetOrCreateEvent(GroupAndName("sched", "sched_new_event")))
       .WillByDefault(Return(&event_to_return));
@@ -330,14 +306,10 @@
   ASSERT_TRUE(id);
   ASSERT_TRUE(model.ActivateConfig(id));
 
-  const FtraceDataSourceConfig* ds_config = model.GetDataSourceConfig(id);
-  ASSERT_TRUE(ds_config);
-  ASSERT_THAT(ds_config->event_filter.GetEnabledEvents(),
-              ElementsAreArray({kSchedSwitchEventId, kGenericEventId}));
-
-  const EventFilter* central_filter = model.GetCentralEventFilterForTesting();
-  ASSERT_THAT(central_filter->GetEnabledEvents(),
-              ElementsAreArray({kSchedSwitchEventId, kGenericEventId}));
+  const FtraceConfig* actual_config = model.GetConfigForTesting(id);
+  EXPECT_THAT(actual_config->ftrace_events(), Contains("sched/sched_switch"));
+  EXPECT_THAT(actual_config->ftrace_events(),
+              Contains("sched/sched_new_event"));
 }
 
 TEST_F(FtraceConfigMuxerTest, TwoWildcardGroups) {
@@ -359,35 +331,28 @@
   EXPECT_CALL(ftrace, GetEventNamesForGroup("events/group_two"))
       .Times(AnyNumber());
 
-  static constexpr int kEventId1 = 1;
   Event event1;
   event1.name = "foo";
   event1.group = "group_one";
-  event1.ftrace_event_id = kEventId1;
+  event1.ftrace_event_id = 1;
   ON_CALL(*mock_table, GetOrCreateEvent(GroupAndName("group_one", "foo")))
       .WillByDefault(Return(&event1));
   EXPECT_CALL(*mock_table, GetOrCreateEvent(GroupAndName("group_one", "foo")));
 
-  static constexpr int kEventId2 = 2;
   Event event2;
   event2.name = "foo";
   event2.group = "group_two";
-  event2.ftrace_event_id = kEventId2;
+  event2.ftrace_event_id = 2;
   ON_CALL(*mock_table, GetOrCreateEvent(GroupAndName("group_two", "foo")))
       .WillByDefault(Return(&event2));
   EXPECT_CALL(*mock_table, GetOrCreateEvent(GroupAndName("group_two", "foo")));
 
   FtraceConfigId id = model.SetupConfig(config);
   ASSERT_TRUE(model.ActivateConfig(id));
-
-  const FtraceDataSourceConfig* ds_config = model.GetDataSourceConfig(id);
-  ASSERT_TRUE(ds_config);
-  ASSERT_THAT(ds_config->event_filter.GetEnabledEvents(),
-              ElementsAreArray({kEventId1, kEventId2}));
-
-  const EventFilter* central_filter = model.GetCentralEventFilterForTesting();
-  ASSERT_THAT(central_filter->GetEnabledEvents(),
-              ElementsAreArray({kEventId1, kEventId2}));
+  const FtraceConfig* actual_config = model.GetConfigForTesting(id);
+  EXPECT_TRUE(actual_config);
+  EXPECT_THAT(actual_config->ftrace_events(), Contains("group_one/foo"));
+  EXPECT_THAT(actual_config->ftrace_events(), Contains("group_two/foo"));
 }
 
 TEST_F(FtraceConfigMuxerTest, TurnFtraceOnOff) {
@@ -410,33 +375,22 @@
   EXPECT_CALL(ftrace, WriteToFile("/root/tracing_on", "1"));
   EXPECT_CALL(ftrace,
               WriteToFile("/root/events/sched/sched_switch/enable", "1"));
-
   FtraceConfigId id = model.SetupConfig(config);
   ASSERT_TRUE(id);
   ASSERT_TRUE(model.ActivateConfig(id));
 
-  const FtraceDataSourceConfig* ds_config = model.GetDataSourceConfig(id);
-  ASSERT_TRUE(ds_config);
-  ASSERT_THAT(
-      ds_config->event_filter.GetEnabledEvents(),
-      ElementsAreArray({FtraceConfigMuxerTest::kFakeSchedSwitchEventId}));
-
-  const EventFilter* central_filter = model.GetCentralEventFilterForTesting();
-  ASSERT_THAT(
-      central_filter->GetEnabledEvents(),
-      ElementsAreArray({FtraceConfigMuxerTest::kFakeSchedSwitchEventId}));
-
-  ASSERT_TRUE(testing::Mock::VerifyAndClearExpectations(&ftrace));
-  EXPECT_CALL(ftrace, NumberOfCpus()).Times(AnyNumber());
+  const FtraceConfig* actual_config = model.GetConfigForTesting(id);
+  EXPECT_TRUE(actual_config);
+  EXPECT_THAT(actual_config->ftrace_events(), Contains("sched/sched_switch"));
+  EXPECT_THAT(actual_config->ftrace_events(), Not(Contains("foo")));
 
   EXPECT_CALL(ftrace, WriteToFile("/root/tracing_on", "0"));
-  EXPECT_CALL(ftrace, WriteToFile("/root/buffer_size_kb", "4"));
+  EXPECT_CALL(ftrace, WriteToFile("/root/buffer_size_kb", "0"));
   EXPECT_CALL(ftrace, WriteToFile("/root/events/enable", "0"));
   EXPECT_CALL(ftrace,
               WriteToFile("/root/events/sched/sched_switch/enable", "0"));
   EXPECT_CALL(ftrace, ClearFile("/root/trace"));
   EXPECT_CALL(ftrace, ClearFile(MatchesRegex("/root/per_cpu/cpu[0-9]/trace")));
-
   ASSERT_TRUE(model.RemoveConfig(id));
 }
 
@@ -473,19 +427,10 @@
   FtraceConfigId id = model.SetupConfig(config);
   ASSERT_TRUE(id);
 
-  // "ftrace" group events are always enabled, and therefore the "print" event
-  // will show up in the per data source event filter (as we want to record it),
-  // but not the central filter (as we're not enabling/disabling it).
-  const FtraceDataSourceConfig* ds_config = model.GetDataSourceConfig(id);
-  ASSERT_TRUE(ds_config);
-  EXPECT_THAT(ds_config->event_filter.GetEnabledEvents(),
-              Contains(FtraceConfigMuxerTest::kFakeSchedSwitchEventId));
-  EXPECT_THAT(ds_config->event_filter.GetEnabledEvents(),
-              Contains(FtraceConfigMuxerTest::kFakePrintEventId));
-
-  const EventFilter* central_filter = model.GetCentralEventFilterForTesting();
-  EXPECT_THAT(central_filter->GetEnabledEvents(),
-              Contains(FtraceConfigMuxerTest::kFakeSchedSwitchEventId));
+  const FtraceConfig* actual_config = model.GetConfigForTesting(id);
+  EXPECT_TRUE(actual_config);
+  EXPECT_THAT(actual_config->ftrace_events(), Contains("sched/sched_switch"));
+  EXPECT_THAT(actual_config->ftrace_events(), Contains("ftrace/print"));
 
   EXPECT_CALL(atrace, RunAtrace(ElementsAreArray(
                           {"atrace", "--async_stop", "--only_userspace"})))
@@ -515,10 +460,9 @@
   FtraceConfigId id = model.SetupConfig(config);
   ASSERT_TRUE(id);
 
-  const FtraceDataSourceConfig* ds_config = model.GetDataSourceConfig(id);
-  ASSERT_TRUE(ds_config);
-  ASSERT_THAT(ds_config->event_filter.GetEnabledEvents(),
-              Contains(FtraceConfigMuxerTest::kFakePrintEventId));
+  const FtraceConfig* actual_config = model.GetConfigForTesting(id);
+  EXPECT_TRUE(actual_config);
+  EXPECT_THAT(actual_config->ftrace_events(), Contains("ftrace/print"));
 
   EXPECT_CALL(atrace, RunAtrace(ElementsAreArray(
                           {"atrace", "--async_stop", "--only_userspace"})))
@@ -630,21 +574,13 @@
   ASSERT_TRUE(id);
   ASSERT_TRUE(model.ActivateConfig(id));
 
-  const FtraceDataSourceConfig* ds_config = model.GetDataSourceConfig(id);
-  ASSERT_TRUE(ds_config);
-  EXPECT_THAT(ds_config->event_filter.GetEnabledEvents(),
-              Contains(FtraceConfigMuxerTest::kFakeSchedSwitchEventId));
-  EXPECT_THAT(ds_config->event_filter.GetEnabledEvents(),
-              Contains(FtraceConfigMuxerTest::kCgroupMkdirEventId));
-
-  const EventFilter* central_filter = model.GetCentralEventFilterForTesting();
-  EXPECT_THAT(central_filter->GetEnabledEvents(),
-              Contains(FtraceConfigMuxerTest::kFakeSchedSwitchEventId));
-  EXPECT_THAT(central_filter->GetEnabledEvents(),
-              Contains(FtraceConfigMuxerTest::kCgroupMkdirEventId));
+  const FtraceConfig* actual_config = model.GetConfigForTesting(id);
+  EXPECT_TRUE(actual_config);
+  EXPECT_THAT(actual_config->ftrace_events(), Contains("sched/sched_switch"));
+  EXPECT_THAT(actual_config->ftrace_events(), Contains("cgroup/cgroup_mkdir"));
 
   EXPECT_CALL(ftrace, WriteToFile("/root/tracing_on", "0"));
-  EXPECT_CALL(ftrace, WriteToFile("/root/buffer_size_kb", "4"));
+  EXPECT_CALL(ftrace, WriteToFile("/root/buffer_size_kb", "0"));
   EXPECT_CALL(ftrace, WriteToFile("/root/events/enable", "0"));
   EXPECT_CALL(ftrace,
               WriteToFile("/root/events/sched/sched_switch/enable", "0"));
@@ -658,64 +594,5 @@
   ASSERT_TRUE(model.RemoveConfig(id));
 }
 
-TEST_F(FtraceConfigMuxerTest, CompactSchedConfig) {
-  // Set scheduling event format as validated. The pre-parsed format itself
-  // doesn't need to be sensible, as the tests won't use it.
-  auto valid_compact_format =
-      CompactSchedEventFormat{/*format_valid=*/true, CompactSchedSwitchFormat{},
-                              CompactSchedWakingFormat{}};
-
-  NiceMock<MockFtraceProcfs> ftrace;
-  table_ = CreateFakeTable(valid_compact_format);
-  FtraceConfigMuxer model(&ftrace, table_.get());
-
-  // First data source - request compact encoding.
-  FtraceConfig config_enabled = CreateFtraceConfig({"sched/sched_switch"});
-  config_enabled.mutable_compact_sched()->set_enabled(true);
-
-  // Second data source - no compact encoding (default).
-  FtraceConfig config_disabled = CreateFtraceConfig({"sched/sched_switch"});
-
-  {
-    FtraceConfigId id = model.SetupConfig(config_enabled);
-    ASSERT_TRUE(id);
-    const FtraceDataSourceConfig* ds_config = model.GetDataSourceConfig(id);
-    ASSERT_TRUE(ds_config);
-    EXPECT_THAT(ds_config->event_filter.GetEnabledEvents(),
-                Contains(FtraceConfigMuxerTest::kFakeSchedSwitchEventId));
-    EXPECT_TRUE(ds_config->compact_sched.enabled);
-  }
-  {
-    FtraceConfigId id = model.SetupConfig(config_disabled);
-    ASSERT_TRUE(id);
-    const FtraceDataSourceConfig* ds_config = model.GetDataSourceConfig(id);
-    ASSERT_TRUE(ds_config);
-    EXPECT_THAT(ds_config->event_filter.GetEnabledEvents(),
-                Contains(FtraceConfigMuxerTest::kFakeSchedSwitchEventId));
-    EXPECT_FALSE(ds_config->compact_sched.enabled);
-  }
-}
-
-TEST_F(FtraceConfigMuxerTest, CompactSchedConfigWithInvalidFormat) {
-  NiceMock<MockFtraceProcfs> ftrace;
-  FtraceConfigMuxer model(&ftrace, table_.get());
-
-  // Request compact encoding.
-  FtraceConfig config = CreateFtraceConfig({"sched/sched_switch"});
-  config.mutable_compact_sched()->set_enabled(true);
-
-  FtraceConfigId id = model.SetupConfig(config);
-  ASSERT_TRUE(id);
-
-  // The translation table says that the scheduling events' format didn't match
-  // compile-time assumptions, so we won't enable compact events even if
-  // requested.
-  const FtraceDataSourceConfig* ds_config = model.GetDataSourceConfig(id);
-  ASSERT_TRUE(ds_config);
-  EXPECT_THAT(ds_config->event_filter.GetEnabledEvents(),
-              Contains(FtraceConfigMuxerTest::kFakeSchedSwitchEventId));
-  EXPECT_FALSE(ds_config->compact_sched.enabled);
-}
-
 }  // namespace
 }  // namespace perfetto
diff --git a/src/traced/probes/ftrace/ftrace_config_unittest.cc b/src/traced/probes/ftrace/ftrace_config_unittest.cc
index 0c22fee..d1a5c0b 100644
--- a/src/traced/probes/ftrace/ftrace_config_unittest.cc
+++ b/src/traced/probes/ftrace/ftrace_config_unittest.cc
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-#include "src/traced/probes/ftrace/ftrace_config_utils.h"
+#include "src/traced/probes/ftrace/ftrace_config.h"
 
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 using testing::Contains;
 
diff --git a/src/traced/probes/ftrace/ftrace_config_utils.cc b/src/traced/probes/ftrace/ftrace_config_utils.cc
deleted file mode 100644
index a655f72..0000000
--- a/src/traced/probes/ftrace/ftrace_config_utils.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.
- */
-
-#include "src/traced/probes/ftrace/ftrace_config_utils.h"
-
-#include "perfetto/base/logging.h"
-
-namespace perfetto {
-namespace {
-
-bool IsGoodFtracePunctuation(char c) {
-  return c == '_' || c == '/' || c == '*';
-}
-
-bool IsGoodAtracePunctuation(char c) {
-  return c == '_' || c == '.' || c == '*';
-}
-
-bool IsValidAtraceEventName(const std::string& str) {
-  for (size_t i = 0; i < str.size(); i++) {
-    if (!isalnum(str[i]) && !IsGoodAtracePunctuation(str[i]))
-      return false;
-  }
-  return true;
-}
-
-bool IsValidFtraceEventName(const std::string& str) {
-  int slash_count = 0;
-  for (size_t i = 0; i < str.size(); i++) {
-    if (!isalnum(str[i]) && !IsGoodFtracePunctuation(str[i]))
-      return false;
-    if (str[i] == '/') {
-      slash_count++;
-      // At most one '/' allowed and not at the beginning or end.
-      if (slash_count > 1 || i == 0 || i == str.size() - 1)
-        return false;
-    }
-    if (str[i] == '*' && i != str.size() - 1)
-      return false;
-  }
-  return true;
-}
-
-}  // namespace
-
-FtraceConfig CreateFtraceConfig(std::set<std::string> names) {
-  FtraceConfig config;
-  for (const std::string& name : names)
-    *config.add_ftrace_events() = name;
-  return config;
-}
-
-bool RequiresAtrace(const FtraceConfig& config) {
-  return !config.atrace_categories().empty() || !config.atrace_apps().empty();
-}
-
-bool ValidConfig(const FtraceConfig& config) {
-  for (const std::string& event_name : config.ftrace_events()) {
-    if (!IsValidFtraceEventName(event_name)) {
-      PERFETTO_ELOG("Bad event name '%s'", event_name.c_str());
-      return false;
-    }
-  }
-  for (const std::string& category : config.atrace_categories()) {
-    if (!IsValidAtraceEventName(category)) {
-      PERFETTO_ELOG("Bad category name '%s'", category.c_str());
-      return false;
-    }
-  }
-  for (const std::string& app : config.atrace_apps()) {
-    if (!IsValidAtraceEventName(app)) {
-      PERFETTO_ELOG("Bad app '%s'", app.c_str());
-      return false;
-    }
-  }
-  return true;
-}
-
-}  // namespace perfetto
diff --git a/src/traced/probes/ftrace/ftrace_config_utils.h b/src/traced/probes/ftrace/ftrace_config_utils.h
deleted file mode 100644
index 8af3c52..0000000
--- a/src/traced/probes/ftrace/ftrace_config_utils.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef SRC_TRACED_PROBES_FTRACE_FTRACE_CONFIG_UTILS_H_
-#define SRC_TRACED_PROBES_FTRACE_FTRACE_CONFIG_UTILS_H_
-
-#include <set>
-#include <string>
-
-#include "protos/perfetto/config/ftrace/ftrace_config.gen.h"
-
-namespace perfetto {
-
-// 0 is invalid.
-using FtraceConfigId = uint64_t;
-
-// Utility method for the common case where we don't care about atrace events.
-FtraceConfig CreateFtraceConfig(std::set<std::string> names);
-
-// Returns true iff the config has any atrace categories or apps.
-bool RequiresAtrace(const FtraceConfig&);
-
-bool ValidConfig(const FtraceConfig& config);
-
-}  // namespace perfetto
-
-#endif  // SRC_TRACED_PROBES_FTRACE_FTRACE_CONFIG_UTILS_H_
diff --git a/src/traced/probes/ftrace/ftrace_controller.cc b/src/traced/probes/ftrace/ftrace_controller.cc
index a66ed05..b1b3793 100644
--- a/src/traced/probes/ftrace/ftrace_controller.cc
+++ b/src/traced/probes/ftrace/ftrace_controller.cc
@@ -29,11 +29,11 @@
 #include <utility>
 
 #include "perfetto/base/build_config.h"
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/logging.h"
+#include "perfetto/base/metatrace.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/metatrace.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
+#include "perfetto/tracing/core/trace_writer.h"
 #include "src/traced/probes/ftrace/cpu_reader.h"
 #include "src/traced/probes/ftrace/cpu_stats_parser.h"
 #include "src/traced/probes/ftrace/event_info.h"
@@ -48,25 +48,10 @@
 namespace {
 
 constexpr int kDefaultDrainPeriodMs = 100;
+constexpr int kControllerFlushTimeoutMs = 500;
 constexpr int kMinDrainPeriodMs = 1;
 constexpr int kMaxDrainPeriodMs = 1000 * 60;
 
-// Read at most this many pages of data per cpu per read task. If we hit this
-// limit on at least one cpu, we stop and repost the read task, letting other
-// tasks get some cpu time before continuing reading.
-constexpr size_t kMaxPagesPerCpuPerReadTick = 256;  // 1 MB per cpu
-
-// When reading and parsing data for a particular cpu, we do it in batches of
-// this many pages. In other words, we'll read up to
-// |kParsingBufferSizePages| into memory, parse them, and then repeat if we
-// still haven't caught up to the writer. A working set of 32 pages is 128k of
-// data, which should fit in a typical L2D cache. Furthermore, the batching
-// limits the memory usage of traced_probes.
-//
-// TODO(rsavitski): consider making buffering & parsing page counts independent,
-// should be a single counter in the cpu_reader, similar to lost_events case.
-constexpr size_t kParsingBufferSizePages = 32;
-
 uint32_t ClampDrainPeriodMs(uint32_t drain_period_ms) {
   if (drain_period_ms == 0) {
     return kDefaultDrainPeriodMs;
@@ -150,12 +135,16 @@
                                    Observer* observer)
     : task_runner_(task_runner),
       observer_(observer),
+      thread_sync_(task_runner),
       ftrace_procfs_(std::move(ftrace_procfs)),
       table_(std::move(table)),
       ftrace_config_muxer_(std::move(model)),
-      weak_factory_(this) {}
+      weak_factory_(this) {
+  thread_sync_.trace_controller_weak = GetWeakPtr();
+}
 
 FtraceController::~FtraceController() {
+  PERFETTO_DCHECK_THREAD(thread_checker_);
   for (const auto* data_source : data_sources_)
     ftrace_config_muxer_->RemoveConfig(data_source->config_id());
   data_sources_.clear();
@@ -167,118 +156,161 @@
   return static_cast<uint64_t>(base::GetWallTimeMs().count());
 }
 
+// The OnCpuReader* methods below are called on the CpuReader worker threads.
+// Lifetime is guaranteed to be valid, because the FtraceController dtor
+// (that happens on the main thread) joins the worker threads.
+
+// static
+void FtraceController::OnCpuReaderRead(size_t cpu,
+                                       int generation,
+                                       FtraceThreadSync* thread_sync) {
+  PERFETTO_METATRACE("OnCpuReaderRead()", cpu);
+
+  {
+    std::lock_guard<std::mutex> lock(thread_sync->mutex);
+    // If this was the first CPU to wake up, schedule a drain for the next
+    // drain interval.
+    bool post_drain_task = thread_sync->cpus_to_drain.none();
+    thread_sync->cpus_to_drain[cpu] = true;
+    if (!post_drain_task)
+      return;
+  }  // lock(thread_sync_.mutex)
+
+  base::WeakPtr<FtraceController> weak_ctl = thread_sync->trace_controller_weak;
+  base::TaskRunner* task_runner = thread_sync->task_runner;
+
+  // The nested PostTask is used because the FtraceController (and hence
+  // GetDrainPeriodMs()) can be called only on the main thread.
+  task_runner->PostTask([weak_ctl, task_runner, generation] {
+
+    if (!weak_ctl)
+      return;
+    uint32_t drain_period_ms = weak_ctl->GetDrainPeriodMs();
+
+    task_runner->PostDelayedTask(
+        [weak_ctl, generation] {
+          if (weak_ctl)
+            weak_ctl->DrainCPUs(generation);
+        },
+        drain_period_ms - (weak_ctl->NowMs() % drain_period_ms));
+
+  });
+}
+
+// static
+void FtraceController::OnCpuReaderFlush(size_t cpu,
+                                        int generation,
+                                        FtraceThreadSync* thread_sync) {
+  // In the case of a flush, we want to drain the data as quickly as possible to
+  // minimize the flush latency, at the cost of more tasks / wakeups (eventually
+  // one task per cpu). Flushes are not supposed to happen too frequently.
+  {
+    std::lock_guard<std::mutex> lock(thread_sync->mutex);
+    thread_sync->cpus_to_drain[cpu] = true;
+    thread_sync->flush_acks[cpu] = true;
+  }  // lock(thread_sync_.mutex)
+
+  base::WeakPtr<FtraceController> weak_ctl = thread_sync->trace_controller_weak;
+  thread_sync->task_runner->PostTask([weak_ctl, generation] {
+    if (weak_ctl)
+      weak_ctl->DrainCPUs(generation);
+  });
+}
+
+void FtraceController::DrainCPUs(int generation) {
+  PERFETTO_DCHECK_THREAD(thread_checker_);
+  PERFETTO_METATRACE("DrainCPUs()", base::MetaTrace::kMainThreadCpu);
+
+  if (generation != generation_)
+    return;
+
+  const size_t num_cpus = ftrace_procfs_->NumberOfCpus();
+  PERFETTO_DCHECK(cpu_readers_.size() == num_cpus);
+  FlushRequestID ack_flush_request_id = 0;
+  std::bitset<base::kMaxCpus> cpus_to_drain;
+  {
+    std::lock_guard<std::mutex> lock(thread_sync_.mutex);
+    std::swap(cpus_to_drain, thread_sync_.cpus_to_drain);
+
+    // Check also if a flush is pending and if all cpus have acked. If that's
+    // the case, ack the overall Flush() request at the end of this function.
+    if (cur_flush_request_id_ && thread_sync_.flush_acks.count() >= num_cpus) {
+      thread_sync_.flush_acks.reset();
+      ack_flush_request_id = cur_flush_request_id_;
+      cur_flush_request_id_ = 0;
+    }
+  }
+
+  for (size_t cpu = 0; cpu < num_cpus; cpu++) {
+    if (!cpus_to_drain[cpu])
+      continue;
+    // This method reads the pipe and converts the raw ftrace data into
+    // protobufs using the |data_source|'s TraceWriter.
+    cpu_readers_[cpu]->Drain(started_data_sources_);
+    OnDrainCpuForTesting(cpu);
+  }
+
+  // If we filled up any SHM pages while draining the data, we will have posted
+  // a task to notify traced about this. Only unblock the readers after this
+  // notification is sent to make it less likely that they steal CPU time away
+  // from traced. Also, don't unblock the readers until all of them have replied
+  // to the flush.
+  if (!cur_flush_request_id_) {
+    base::WeakPtr<FtraceController> weak_this = weak_factory_.GetWeakPtr();
+    task_runner_->PostTask([weak_this] {
+      if (weak_this)
+        weak_this->UnblockReaders();
+    });
+  }
+
+  observer_->OnFtraceDataWrittenIntoDataSourceBuffers();
+
+  if (ack_flush_request_id) {
+    // Flush completed, all CpuReader(s) acked.
+
+    IssueThreadSyncCmd(FtraceThreadSync::kRun);  // Switch back to reading mode.
+
+    // This will call FtraceDataSource::OnFtraceFlushComplete(), which in turn
+    // will flush the userspace buffers and ack the flush to the ProbesProducer
+    // which in turn will ack the flush to the tracing service.
+    NotifyFlushCompleteToStartedDataSources(ack_flush_request_id);
+  }
+}
+
+void FtraceController::UnblockReaders() {
+  PERFETTO_METATRACE("UnblockReaders()", base::MetaTrace::kMainThreadCpu);
+
+  // If a flush or a quit is pending, do nothing.
+  std::unique_lock<std::mutex> lock(thread_sync_.mutex);
+  if (thread_sync_.cmd != FtraceThreadSync::kRun)
+    return;
+
+  // Unblock all waiting readers to start moving more data into their
+  // respective staging pipes.
+  IssueThreadSyncCmd(FtraceThreadSync::kRun, std::move(lock));
+}
+
 void FtraceController::StartIfNeeded() {
   if (started_data_sources_.size() > 1)
     return;
   PERFETTO_DCHECK(!started_data_sources_.empty());
-  PERFETTO_DCHECK(per_cpu_.empty());
+  PERFETTO_DCHECK(cpu_readers_.empty());
+  base::WeakPtr<FtraceController> weak_this = weak_factory_.GetWeakPtr();
 
-  // Lazily allocate the memory used for reading & parsing ftrace.
-  if (!parsing_mem_.IsValid()) {
-    parsing_mem_ =
-        base::PagedMemory::Allocate(base::kPageSize * kParsingBufferSizePages);
+  {
+    std::lock_guard<std::mutex> lock(thread_sync_.mutex);
+    thread_sync_.cpus_to_drain.reset();
+    thread_sync_.cmd = FtraceThreadSync::kRun;
+    thread_sync_.cmd_id++;
   }
 
-  per_cpu_.clear();
-  per_cpu_.reserve(ftrace_procfs_->NumberOfCpus());
-  size_t period_page_quota = ftrace_config_muxer_->GetPerCpuBufferSizePages();
+  generation_++;
+  cpu_readers_.clear();
+  cpu_readers_.reserve(ftrace_procfs_->NumberOfCpus());
   for (size_t cpu = 0; cpu < ftrace_procfs_->NumberOfCpus(); cpu++) {
-    auto reader = std::unique_ptr<CpuReader>(
-        new CpuReader(cpu, table_.get(), ftrace_procfs_->OpenPipeForCpu(cpu)));
-    per_cpu_.emplace_back(std::move(reader), period_page_quota);
-  }
-
-  // Start the repeating read tasks.
-  auto generation = ++generation_;
-  auto drain_period_ms = GetDrainPeriodMs();
-  auto weak_this = weak_factory_.GetWeakPtr();
-  task_runner_->PostDelayedTask(
-      [weak_this, generation] {
-        if (weak_this)
-          weak_this->ReadTick(generation);
-      },
-      drain_period_ms - (NowMs() % drain_period_ms));
-}
-
-// We handle the ftrace buffers in a repeating task (ReadTick). On a given tick,
-// we iterate over all per-cpu buffers, parse their contents, and then write out
-// the serialized packets. This is handled by |CpuReader| instances, which
-// attempt to read from their respective per-cpu buffer fd until they catch up
-// to the head of the buffer, or hit a transient error.
-//
-// The readers work in batches of |kParsingBufferSizePages| pages for cache
-// locality, and to limit memory usage.
-//
-// However, the reading happens on the primary thread, shared with the rest of
-// the service (including ipc). If there is a lot of ftrace data to read, we
-// want to yield to the event loop, re-enqueueing a continuation task at the end
-// of the immediate queue (letting other enqueued tasks to run before
-// continuing). Therefore we introduce |kMaxPagesPerCpuPerReadTick|.
-//
-// There is also a possibility that the ftrace bandwidth is particularly high.
-// We do not want to continue trying to catch up to the event stream (via
-// continuation tasks) without bound, as we want to limit our cpu% usage.  We
-// assume that given a config saying "per-cpu kernel ftrace buffer is N pages,
-// and drain every T milliseconds", we should not read more than N pages per
-// drain period. Therefore we introduce |per_cpu_.period_page_quota|. If the
-// consumer wants to handle a high bandwidth of ftrace events, they should set
-// the config values appropriately.
-void FtraceController::ReadTick(int generation) {
-  metatrace::ScopedEvent evt(metatrace::TAG_FTRACE,
-                             metatrace::FTRACE_READ_TICK);
-  if (started_data_sources_.empty() || generation != generation_) {
-    return;
-  }
-
-  // Read all cpu buffers with remaining per-period quota.
-  bool all_cpus_done = true;
-  uint8_t* parsing_buf = reinterpret_cast<uint8_t*>(parsing_mem_.Get());
-  for (size_t i = 0; i < per_cpu_.size(); i++) {
-    size_t orig_quota = per_cpu_[i].period_page_quota;
-    if (orig_quota == 0)
-      continue;
-
-    size_t max_pages = std::min(orig_quota, kMaxPagesPerCpuPerReadTick);
-    size_t pages_read = per_cpu_[i].reader->ReadCycle(
-        parsing_buf, kParsingBufferSizePages, max_pages, started_data_sources_);
-
-    size_t new_quota = (pages_read >= orig_quota) ? 0 : orig_quota - pages_read;
-    per_cpu_[i].period_page_quota = new_quota;
-
-    // Reader got stopped by the cap on the number of pages (to not do too much
-    // work on the shared thread at once), but can read more in this drain
-    // period. Repost the ReadTick (on the immediate queue) to iterate over all
-    // cpus again. In other words, we will keep reposting work for all cpus as
-    // long as at least one of them hits the read page cap each tick. If all
-    // readers catch up to the event stream (pages_read < max_pages), or exceed
-    // their quota, we will stop for the given period.
-    PERFETTO_DCHECK(pages_read <= max_pages);
-    if (pages_read == max_pages && new_quota > 0)
-      all_cpus_done = false;
-  }
-  observer_->OnFtraceDataWrittenIntoDataSourceBuffers();
-
-  // More work to do in this period.
-  auto weak_this = weak_factory_.GetWeakPtr();
-  if (!all_cpus_done) {
-    PERFETTO_DLOG("Reposting immediate ReadTick as there's more work.");
-    task_runner_->PostTask([weak_this, generation] {
-      if (weak_this)
-        weak_this->ReadTick(generation);
-    });
-  } else {
-    // Done until next drain period.
-    size_t period_page_quota = ftrace_config_muxer_->GetPerCpuBufferSizePages();
-    for (auto& per_cpu : per_cpu_)
-      per_cpu.period_page_quota = period_page_quota;
-
-    auto drain_period_ms = GetDrainPeriodMs();
-    task_runner_->PostDelayedTask(
-        [weak_this, generation] {
-          if (weak_this)
-            weak_this->ReadTick(generation);
-        },
-        drain_period_ms - (NowMs() % drain_period_ms));
+    cpu_readers_.emplace_back(
+        new CpuReader(table_.get(), &thread_sync_, cpu, generation_,
+                      ftrace_procfs_->OpenPipeForCpu(cpu)));
   }
 }
 
@@ -306,24 +338,45 @@
 }
 
 void FtraceController::Flush(FlushRequestID flush_id) {
-  metatrace::ScopedEvent evt(metatrace::TAG_FTRACE,
-                             metatrace::FTRACE_CPU_FLUSH);
+  PERFETTO_DCHECK_THREAD(thread_checker_);
 
-  // Read all cpus in one go, limiting the per-cpu read amount to make sure we
-  // don't get stuck chasing the writer if there's a very high bandwidth of
-  // events.
-  size_t per_cpu_buf_size_pages =
-      ftrace_config_muxer_->GetPerCpuBufferSizePages();
-  uint8_t* parsing_buf = reinterpret_cast<uint8_t*>(parsing_mem_.Get());
-  for (size_t i = 0; i < per_cpu_.size(); i++) {
-    per_cpu_[i].reader->ReadCycle(parsing_buf, kParsingBufferSizePages,
-                                  per_cpu_buf_size_pages,
-                                  started_data_sources_);
+  if (flush_id == cur_flush_request_id_)
+    return;  // Already dealing with this flush request.
+
+  cur_flush_request_id_ = flush_id;
+  {
+    std::unique_lock<std::mutex> lock(thread_sync_.mutex);
+    thread_sync_.flush_acks.reset();
+    IssueThreadSyncCmd(FtraceThreadSync::kFlush, std::move(lock));
   }
-  observer_->OnFtraceDataWrittenIntoDataSourceBuffers();
 
-  for (FtraceDataSource* data_source : started_data_sources_)
-    data_source->OnFtraceFlushComplete(flush_id);
+  base::WeakPtr<FtraceController> weak_this = weak_factory_.GetWeakPtr();
+  task_runner_->PostDelayedTask(
+      [weak_this, flush_id] {
+        if (weak_this)
+          weak_this->OnFlushTimeout(flush_id);
+      },
+      kControllerFlushTimeoutMs);
+}
+
+void FtraceController::OnFlushTimeout(FlushRequestID flush_request_id) {
+  if (flush_request_id != cur_flush_request_id_)
+    return;
+
+  std::string acks;  // For debugging purposes only.
+  {
+    // Unlock the cpu readers and move on.
+    std::unique_lock<std::mutex> lock(thread_sync_.mutex);
+    acks = thread_sync_.flush_acks.to_string();
+    thread_sync_.flush_acks.reset();
+    if (thread_sync_.cmd == FtraceThreadSync::kFlush)
+      IssueThreadSyncCmd(FtraceThreadSync::kRun, std::move(lock));
+  }
+
+  PERFETTO_ELOG("Ftrace flush(%" PRIu64 ") timed out. Acked cpus mask: [%s]",
+                flush_request_id, acks.c_str());
+  cur_flush_request_id_ = 0;
+  NotifyFlushCompleteToStartedDataSources(flush_request_id);
 }
 
 void FtraceController::StopIfNeeded() {
@@ -334,14 +387,15 @@
   // ask for an explicit flush before stopping, unless it needs to perform a
   // non-graceful stop.
 
-  per_cpu_.clear();
+  IssueThreadSyncCmd(FtraceThreadSync::kQuit);
 
-  if (parsing_mem_.IsValid()) {
-    parsing_mem_.AdviseDontNeed(parsing_mem_.Get(), parsing_mem_.size());
-  }
+  // Destroying the CpuReader(s) will join on their worker threads.
+  cpu_readers_.clear();
+  generation_++;
 }
 
 bool FtraceController::AddDataSource(FtraceDataSource* data_source) {
+  PERFETTO_DCHECK_THREAD(thread_checker_);
   if (!ValidConfig(data_source->config()))
     return false;
 
@@ -349,15 +403,15 @@
   if (!config_id)
     return false;
 
-  const FtraceDataSourceConfig* ds_config =
-      ftrace_config_muxer_->GetDataSourceConfig(config_id);
+  const EventFilter* filter = ftrace_config_muxer_->GetEventFilter(config_id);
   auto it_and_inserted = data_sources_.insert(data_source);
   PERFETTO_DCHECK(it_and_inserted.second);
-  data_source->Initialize(config_id, ds_config);
+  data_source->Initialize(config_id, filter);
   return true;
 }
 
 bool FtraceController::StartDataSource(FtraceDataSource* data_source) {
+  PERFETTO_DCHECK_THREAD(thread_checker_);
   PERFETTO_DCHECK(data_sources_.count(data_source) > 0);
 
   FtraceConfigId config_id = data_source->config_id();
@@ -372,6 +426,7 @@
 }
 
 void FtraceController::RemoveDataSource(FtraceDataSource* data_source) {
+  PERFETTO_DCHECK_THREAD(thread_checker_);
   started_data_sources_.erase(data_source);
   size_t removed = data_sources_.erase(data_source);
   if (!removed)
@@ -384,6 +439,43 @@
   DumpAllCpuStats(ftrace_procfs_.get(), stats);
 }
 
+void FtraceController::IssueThreadSyncCmd(
+    FtraceThreadSync::Cmd cmd,
+    std::unique_lock<std::mutex> pass_lock_from_caller) {
+  PERFETTO_DCHECK_THREAD(thread_checker_);
+  {
+    std::unique_lock<std::mutex> lock(std::move(pass_lock_from_caller));
+    if (!lock.owns_lock())
+      lock = std::unique_lock<std::mutex>(thread_sync_.mutex);
+
+    if (thread_sync_.cmd == FtraceThreadSync::kQuit &&
+        cmd != FtraceThreadSync::kQuit) {
+      // If in kQuit state, we should never issue any other commands.
+      return;
+    }
+
+    thread_sync_.cmd = cmd;
+    thread_sync_.cmd_id++;
+  }
+
+  // Send a SIGPIPE to all worker threads to wake them up if they are sitting in
+  // a blocking splice(). If they are not and instead they are sitting in the
+  // cond-variable.wait(), this, together with the one below, will have at best
+  // the same effect of a spurious wakeup, depending on the implementation of
+  // the condition variable.
+  for (const auto& cpu_reader : cpu_readers_)
+    cpu_reader->InterruptWorkerThreadWithSignal();
+
+  thread_sync_.cond.notify_all();
+}
+
+void FtraceController::NotifyFlushCompleteToStartedDataSources(
+    FlushRequestID flush_request_id) {
+  PERFETTO_DCHECK_THREAD(thread_checker_);
+  for (FtraceDataSource* data_source : started_data_sources_)
+    data_source->OnFtraceFlushComplete(flush_request_id);
+}
+
 FtraceController::Observer::~Observer() = default;
 
 }  // namespace perfetto
diff --git a/src/traced/probes/ftrace/ftrace_controller.h b/src/traced/probes/ftrace/ftrace_controller.h
index 0004a91..275b888 100644
--- a/src/traced/probes/ftrace/ftrace_controller.h
+++ b/src/traced/probes/ftrace/ftrace_controller.h
@@ -27,16 +27,17 @@
 #include <set>
 #include <string>
 
+#include "perfetto/base/gtest_prod_util.h"
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/paged_memory.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "src/traced/probes/ftrace/cpu_reader.h"
-#include "src/traced/probes/ftrace/ftrace_config_utils.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/base/weak_ptr.h"
+#include "perfetto/tracing/core/basic_types.h"
+#include "src/traced/probes/ftrace/ftrace_config.h"
+#include "src/traced/probes/ftrace/ftrace_thread_sync.h"
 
 namespace perfetto {
 
+class CpuReader;
 class FtraceConfigMuxer;
 class FtraceDataSource;
 class FtraceProcfs;
@@ -61,6 +62,10 @@
   static std::unique_ptr<FtraceController> Create(base::TaskRunner*, Observer*);
   virtual ~FtraceController();
 
+  // These two methods are called by CpuReader(s) from their worker threads.
+  static void OnCpuReaderRead(size_t cpu, int generation, FtraceThreadSync*);
+  static void OnCpuReaderFlush(size_t cpu, int generation, FtraceThreadSync*);
+
   void DisableAllEvents();
   void WriteTraceMarker(const std::string& s);
   void ClearTrace();
@@ -69,8 +74,9 @@
   bool StartDataSource(FtraceDataSource*);
   void RemoveDataSource(FtraceDataSource*);
 
-  // Force a read of the ftrace buffers. Will call OnFtraceFlushComplete() on
-  // all |started_data_sources_|.
+  // Force a read of the ftrace buffers, including kernel buffer pages that
+  // are not full. Will call OnFtraceFlushComplete() on all
+  // |started_data_sources_| once all workers have flushed (or timed out).
   void Flush(FlushRequestID);
 
   void DumpFtraceStats(FtraceStats*);
@@ -87,24 +93,24 @@
                    base::TaskRunner*,
                    Observer*);
 
+  virtual void OnDrainCpuForTesting(size_t /*cpu*/) {}
+
   // Protected and virtual for testing.
   virtual uint64_t NowMs() const;
 
  private:
   friend class TestFtraceController;
-
-  struct PerCpuState {
-    PerCpuState(std::unique_ptr<CpuReader> _reader, size_t _period_page_quota)
-        : reader(std::move(_reader)), period_page_quota(_period_page_quota) {}
-    std::unique_ptr<CpuReader> reader;
-    size_t period_page_quota = 0;
-  };
+  FRIEND_TEST(FtraceControllerIntegrationTest, EnableDisableEvent);
 
   FtraceController(const FtraceController&) = delete;
   FtraceController& operator=(const FtraceController&) = delete;
 
-  // Periodic task that reads all per-cpu ftrace buffers.
-  void ReadTick(int generation);
+  void OnFlushTimeout(FlushRequestID);
+  void DrainCPUs(int generation);
+  void UnblockReaders();
+  void NotifyFlushCompleteToStartedDataSources(FlushRequestID);
+  void IssueThreadSyncCmd(FtraceThreadSync::Cmd,
+                          std::unique_lock<std::mutex> = {});
 
   uint32_t GetDrainPeriodMs();
 
@@ -113,15 +119,17 @@
 
   base::TaskRunner* const task_runner_;
   Observer* const observer_;
-  base::PagedMemory parsing_mem_;
+  FtraceThreadSync thread_sync_;
   std::unique_ptr<FtraceProcfs> ftrace_procfs_;
   std::unique_ptr<ProtoTranslationTable> table_;
   std::unique_ptr<FtraceConfigMuxer> ftrace_config_muxer_;
   int generation_ = 0;
+  FlushRequestID cur_flush_request_id_ = 0;
   bool atrace_running_ = false;
-  std::vector<PerCpuState> per_cpu_;  // empty if tracing isn't active
+  std::vector<std::unique_ptr<CpuReader>> cpu_readers_;
   std::set<FtraceDataSource*> data_sources_;
   std::set<FtraceDataSource*> started_data_sources_;
+  PERFETTO_THREAD_CHECKER(thread_checker_)
   base::WeakPtrFactory<FtraceController> weak_factory_;  // Keep last.
 };
 
diff --git a/src/traced/probes/ftrace/ftrace_controller_unittest.cc b/src/traced/probes/ftrace/ftrace_controller_unittest.cc
index 6622ee2..e6bdc12 100644
--- a/src/traced/probes/ftrace/ftrace_controller_unittest.cc
+++ b/src/traced/probes/ftrace/ftrace_controller_unittest.cc
@@ -20,32 +20,32 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
-#include "src/traced/probes/ftrace/compact_sched.h"
 #include "src/traced/probes/ftrace/cpu_reader.h"
+#include "src/traced/probes/ftrace/ftrace_config.h"
 #include "src/traced/probes/ftrace/ftrace_config_muxer.h"
-#include "src/traced/probes/ftrace/ftrace_config_utils.h"
 #include "src/traced/probes/ftrace/ftrace_data_source.h"
 #include "src/traced/probes/ftrace/ftrace_procfs.h"
 #include "src/traced/probes/ftrace/proto_translation_table.h"
 #include "src/tracing/core/trace_writer_for_testing.h"
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_stats.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/trace_packet.pb.h"
+
+#include "perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace_stats.pbzero.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
 using testing::_;
 using testing::AnyNumber;
 using testing::ByMove;
-using testing::ElementsAre;
 using testing::Invoke;
-using testing::IsEmpty;
-using testing::MatchesRegex;
-using testing::Mock;
 using testing::NiceMock;
-using testing::Pair;
+using testing::MatchesRegex;
 using testing::Return;
+using testing::IsEmpty;
+using testing::ElementsAre;
+using testing::Pair;
 
 using Table = perfetto::ProtoTranslationTable;
 using FtraceEventBundle = perfetto::protos::pbzero::FtraceEventBundle;
@@ -59,35 +59,72 @@
 
 class MockTaskRunner : public base::TaskRunner {
  public:
+  MockTaskRunner() {
+    ON_CALL(*this, PostTask(_))
+        .WillByDefault(Invoke(this, &MockTaskRunner::OnPostTask));
+    ON_CALL(*this, PostDelayedTask(_, _))
+        .WillByDefault(Invoke(this, &MockTaskRunner::OnPostDelayedTask));
+  }
+
+  void OnPostTask(std::function<void()> task) {
+    std::unique_lock<std::mutex> lock(lock_);
+    EXPECT_FALSE(task_);
+    task_ = std::move(task);
+  }
+
+  void OnPostDelayedTask(std::function<void()> task, int /*delay*/) {
+    std::unique_lock<std::mutex> lock(lock_);
+    EXPECT_FALSE(task_);
+    task_ = std::move(task);
+  }
+
+  void RunLastTask() {
+    auto task = TakeTask();
+    if (task)
+      task();
+  }
+
+  std::function<void()> TakeTask() {
+    std::unique_lock<std::mutex> lock(lock_);
+    auto task(std::move(task_));
+    task_ = std::function<void()>();
+    return task;
+  }
+
   MOCK_METHOD1(PostTask, void(std::function<void()>));
   MOCK_METHOD2(PostDelayedTask, void(std::function<void()>, uint32_t delay_ms));
   MOCK_METHOD2(AddFileDescriptorWatch, void(int fd, std::function<void()>));
   MOCK_METHOD1(RemoveFileDescriptorWatch, void(int fd));
   MOCK_CONST_METHOD0(RunsTasksOnCurrentThread, bool());
+
+ private:
+  std::mutex lock_;
+  std::function<void()> task_;
 };
 
 std::unique_ptr<Table> FakeTable(FtraceProcfs* ftrace) {
   std::vector<Field> common_fields;
   std::vector<Event> events;
+
   {
-    events.push_back(Event{});
-    auto& event = events.back();
+    Event event;
     event.name = "foo";
     event.group = "group";
     event.ftrace_event_id = 1;
+    events.push_back(event);
   }
+
   {
-    events.push_back(Event{});
-    auto& event = events.back();
+    Event event;
     event.name = "bar";
     event.group = "group";
     event.ftrace_event_id = 10;
+    events.push_back(event);
   }
 
   return std::unique_ptr<Table>(
       new Table(ftrace, events, std::move(common_fields),
-                ProtoTranslationTable::DefaultPageHeaderSpecForTesting(),
-                InvalidCompactSchedEventFormatForTesting()));
+                ProtoTranslationTable::DefaultPageHeaderSpecForTesting()));
 }
 
 std::unique_ptr<FtraceConfigMuxer> FakeModel(FtraceProcfs* ftrace,
@@ -178,11 +215,34 @@
         runner_(std::move(runner)),
         procfs_(raw_procfs) {}
 
+  MOCK_METHOD1(OnDrainCpuForTesting, void(size_t cpu));
+
   MockTaskRunner* runner() { return runner_.get(); }
   MockFtraceProcfs* procfs() { return procfs_; }
+
   uint64_t NowMs() const override { return now_ms; }
+
   uint32_t drain_period_ms() { return GetDrainPeriodMs(); }
 
+  std::function<void()> GetDataAvailableCallback(size_t cpu) {
+    int generation = generation_;
+    auto* thread_sync = &thread_sync_;
+    return [cpu, generation, thread_sync] {
+      FtraceController::OnCpuReaderRead(cpu, generation, thread_sync);
+    };
+  }
+
+  void WaitForData(size_t cpu) {
+    for (;;) {
+      {
+        std::unique_lock<std::mutex> lock(thread_sync_.mutex);
+        if (thread_sync_.cpus_to_drain[cpu])
+          return;
+      }
+      usleep(5000);
+    }
+  }
+
   std::unique_ptr<FtraceDataSource> AddFakeDataSource(const FtraceConfig& cfg) {
     std::unique_ptr<FtraceDataSource> data_source(new FtraceDataSource(
         GetWeakPtr(), 0 /* session id */, cfg, nullptr /* trace_writer */));
@@ -206,10 +266,15 @@
 namespace {
 
 std::unique_ptr<TestFtraceController> CreateTestController(
+    bool runner_is_nice_mock,
     bool procfs_is_nice_mock,
     size_t cpu_count = 1) {
-  std::unique_ptr<MockTaskRunner> runner =
-      std::unique_ptr<MockTaskRunner>(new NiceMock<MockTaskRunner>());
+  std::unique_ptr<MockTaskRunner> runner;
+  if (runner_is_nice_mock) {
+    runner = std::unique_ptr<MockTaskRunner>(new NiceMock<MockTaskRunner>());
+  } else {
+    runner = std::unique_ptr<MockTaskRunner>(new MockTaskRunner());
+  }
 
   std::unique_ptr<MockFtraceProcfs> ftrace_procfs;
   if (procfs_is_nice_mock) {
@@ -233,14 +298,16 @@
 }  // namespace
 
 TEST(FtraceControllerTest, NonExistentEventsDontCrash) {
-  auto controller = CreateTestController(true /* nice procfs */);
+  auto controller =
+      CreateTestController(true /* nice runner */, true /* nice procfs */);
 
   FtraceConfig config = CreateFtraceConfig({"not_an_event"});
   EXPECT_TRUE(controller->AddFakeDataSource(config));
 }
 
 TEST(FtraceControllerTest, RejectsBadEventNames) {
-  auto controller = CreateTestController(true /* nice procfs */);
+  auto controller =
+      CreateTestController(true /* nice runner */, true /* nice procfs */);
 
   FtraceConfig config = CreateFtraceConfig({"../try/to/escape"});
   EXPECT_FALSE(controller->AddFakeDataSource(config));
@@ -251,10 +318,8 @@
 }
 
 TEST(FtraceControllerTest, OneSink) {
-  auto controller = CreateTestController(false /* nice procfs */);
-
-  // No read tasks posted as part of adding the data source.
-  EXPECT_CALL(*controller->runner(), PostDelayedTask(_, _)).Times(0);
+  auto controller =
+      CreateTestController(true /* nice runner */, false /* nice procfs */);
 
   FtraceConfig config = CreateFtraceConfig({"group/foo"});
 
@@ -263,20 +328,10 @@
   auto data_source = controller->AddFakeDataSource(config);
   ASSERT_TRUE(data_source);
 
-  // Verify that no read tasks have been posted. And set up expectation that
-  // a single recurring read task will be posted as part of starting the data
-  // source.
-  Mock::VerifyAndClearExpectations(controller->runner());
-  EXPECT_CALL(*controller->runner(), PostDelayedTask(_, _)).Times(1);
-
   EXPECT_CALL(*controller->procfs(), WriteToFile("/root/tracing_on", "1"));
   ASSERT_TRUE(controller->StartDataSource(data_source.get()));
 
-  // Verify single posted read task.
-  Mock::VerifyAndClearExpectations(controller->runner());
-
-  // State clearing on tracing teardown.
-  EXPECT_CALL(*controller->procfs(), WriteToFile("/root/buffer_size_kb", "4"));
+  EXPECT_CALL(*controller->procfs(), WriteToFile("/root/buffer_size_kb", "0"));
   EXPECT_CALL(*controller->procfs(), ClearFile("/root/trace"))
       .WillOnce(Return(true));
   EXPECT_CALL(*controller->procfs(),
@@ -292,39 +347,27 @@
 }
 
 TEST(FtraceControllerTest, MultipleSinks) {
-  auto controller = CreateTestController(false /* nice procfs */);
+  auto controller =
+      CreateTestController(false /* nice runner */, false /* nice procfs */);
 
   FtraceConfig configA = CreateFtraceConfig({"group/foo"});
   FtraceConfig configB = CreateFtraceConfig({"group/foo", "group/bar"});
 
-  // No read tasks posted as part of adding the data sources.
-  EXPECT_CALL(*controller->runner(), PostDelayedTask(_, _)).Times(0);
-
   EXPECT_CALL(*controller->procfs(), WriteToFile("/root/buffer_size_kb", _));
   EXPECT_CALL(*controller->procfs(), WriteToFile(kFooEnablePath, "1"));
   auto data_sourceA = controller->AddFakeDataSource(configA);
   EXPECT_CALL(*controller->procfs(), WriteToFile(kBarEnablePath, "1"));
   auto data_sourceB = controller->AddFakeDataSource(configB);
 
-  // Verify that no read tasks have been posted. And set up expectation that
-  // a single recurring read task will be posted as part of starting the data
-  // sources.
-  Mock::VerifyAndClearExpectations(controller->runner());
-  EXPECT_CALL(*controller->runner(), PostDelayedTask(_, _)).Times(1);
-
   EXPECT_CALL(*controller->procfs(), WriteToFile("/root/tracing_on", "1"));
   ASSERT_TRUE(controller->StartDataSource(data_sourceA.get()));
   ASSERT_TRUE(controller->StartDataSource(data_sourceB.get()));
 
-  // Verify single posted read task.
-  Mock::VerifyAndClearExpectations(controller->runner());
-
   data_sourceA.reset();
 
-  // State clearing on tracing teardown.
   EXPECT_CALL(*controller->procfs(), WriteToFile(kFooEnablePath, "0"));
   EXPECT_CALL(*controller->procfs(), WriteToFile(kBarEnablePath, "0"));
-  EXPECT_CALL(*controller->procfs(), WriteToFile("/root/buffer_size_kb", "4"));
+  EXPECT_CALL(*controller->procfs(), WriteToFile("/root/buffer_size_kb", "0"));
   EXPECT_CALL(*controller->procfs(), WriteToFile("/root/tracing_on", "0"));
   EXPECT_CALL(*controller->procfs(), WriteToFile("/root/events/enable", "0"));
   EXPECT_CALL(*controller->procfs(), ClearFile("/root/trace"));
@@ -334,7 +377,8 @@
 }
 
 TEST(FtraceControllerTest, ControllerMayDieFirst) {
-  auto controller = CreateTestController(false /* nice procfs */);
+  auto controller =
+      CreateTestController(false /* nice runner */, false /* nice procfs */);
 
   FtraceConfig config = CreateFtraceConfig({"group/foo"});
 
@@ -345,7 +389,6 @@
   EXPECT_CALL(*controller->procfs(), WriteToFile("/root/tracing_on", "1"));
   ASSERT_TRUE(controller->StartDataSource(data_source.get()));
 
-  // State clearing on tracing teardown.
   EXPECT_CALL(*controller->procfs(), WriteToFile(kFooEnablePath, "0"));
   EXPECT_CALL(*controller->procfs(), ClearFile("/root/trace"))
       .WillOnce(Return(true));
@@ -353,24 +396,62 @@
               ClearFile(MatchesRegex("/root/per_cpu/cpu[0-9]/trace")))
       .WillRepeatedly(Return(true));
   EXPECT_CALL(*controller->procfs(), WriteToFile("/root/tracing_on", "0"));
-  EXPECT_CALL(*controller->procfs(), WriteToFile("/root/buffer_size_kb", "4"));
+  EXPECT_CALL(*controller->procfs(), WriteToFile("/root/buffer_size_kb", "0"));
   EXPECT_CALL(*controller->procfs(), WriteToFile("/root/events/enable", "0"));
   controller.reset();
   data_source.reset();
 }
 
+TEST(FtraceControllerTest, BackToBackEnableDisable) {
+  auto controller =
+      CreateTestController(false /* nice runner */, false /* nice procfs */);
+
+  // For this test we don't care about calls to WriteToFile/ClearFile.
+  EXPECT_CALL(*controller->procfs(), WriteToFile(_, _)).Times(AnyNumber());
+  EXPECT_CALL(*controller->procfs(), ClearFile(_)).Times(AnyNumber());
+  EXPECT_CALL(*controller->procfs(), ReadOneCharFromFile("/root/tracing_on"))
+      .Times(AnyNumber());
+
+  EXPECT_CALL(*controller->runner(), PostTask(_)).Times(2);
+  EXPECT_CALL(*controller->runner(), PostDelayedTask(_, 100)).Times(2);
+  FtraceConfig config = CreateFtraceConfig({"group/foo"});
+  auto data_source = controller->AddFakeDataSource(config);
+  ASSERT_TRUE(controller->StartDataSource(data_source.get()));
+
+  auto on_data_available = controller->GetDataAvailableCallback(0u);
+  std::thread worker([on_data_available] { on_data_available(); });
+  controller->WaitForData(0u);
+
+  // Disable the first data source and run the delayed task that it generated.
+  // It should be a no-op.
+  data_source.reset();
+  controller->runner()->RunLastTask();
+  controller->runner()->RunLastTask();
+  worker.join();
+
+  // Register another data source and wait for it to generate data.
+  data_source = controller->AddFakeDataSource(config);
+  ASSERT_TRUE(controller->StartDataSource(data_source.get()));
+
+  on_data_available = controller->GetDataAvailableCallback(0u);
+  std::thread worker2([on_data_available] { on_data_available(); });
+  controller->WaitForData(0u);
+
+  // This drain should also be a no-op after the data source is unregistered.
+  data_source.reset();
+  controller->runner()->RunLastTask();
+  controller->runner()->RunLastTask();
+  worker2.join();
+}
+
 TEST(FtraceControllerTest, BufferSize) {
-  auto controller = CreateTestController(false /* nice procfs */);
+  auto controller =
+      CreateTestController(true /* nice runner */, false /* nice procfs */);
 
   // For this test we don't care about most calls to WriteToFile/ClearFile.
   EXPECT_CALL(*controller->procfs(), WriteToFile(_, _)).Times(AnyNumber());
   EXPECT_CALL(*controller->procfs(), ClearFile(_)).Times(AnyNumber());
 
-  // Every time a fake data source is destroyed, the controller will reset the
-  // buffer size to a single page.
-  EXPECT_CALL(*controller->procfs(), WriteToFile("/root/buffer_size_kb", "4"))
-      .Times(AnyNumber());
-
   {
     // No buffer size -> good default.
     EXPECT_CALL(*controller->procfs(),
@@ -402,8 +483,9 @@
   }
 
   {
-    // Your size ends up with less than 1 page per cpu -> 1 page (gmock already
-    // covered by the cleanup expectation above).
+    // Your size ends up with less than 1 page per cpu -> 1 page.
+    EXPECT_CALL(*controller->procfs(),
+                WriteToFile("/root/buffer_size_kb", "4"));
     FtraceConfig config = CreateFtraceConfig({"group/foo"});
     config.set_buffer_size_kb(1);
     auto data_source = controller->AddFakeDataSource(config);
@@ -433,7 +515,8 @@
 }
 
 TEST(FtraceControllerTest, PeriodicDrainConfig) {
-  auto controller = CreateTestController(false /* nice procfs */);
+  auto controller =
+      CreateTestController(true /* nice runner */, false /* nice procfs */);
 
   // For this test we don't care about calls to WriteToFile/ClearFile.
   EXPECT_CALL(*controller->procfs(), WriteToFile(_, _)).Times(AnyNumber());
@@ -475,10 +558,12 @@
   FtraceMetadata metadata;
   metadata.inode_and_device.push_back(std::make_pair(1, 1));
   metadata.pids.push_back(2);
+  metadata.overwrite_count = 3;
   metadata.last_seen_device_id = 100;
   metadata.Clear();
   EXPECT_THAT(metadata.inode_and_device, IsEmpty());
   EXPECT_THAT(metadata.pids, IsEmpty());
+  EXPECT_EQ(0u, metadata.overwrite_count);
   EXPECT_EQ(BlockDeviceID(0), metadata.last_seen_device_id);
 }
 
@@ -534,11 +619,11 @@
     stats.Write(out);
   }
 
-  protos::TracePacket result_packet = writer->GetOnlyTracePacket();
-  auto result = result_packet.ftrace_stats().cpu_stats(0);
-  EXPECT_EQ(result.cpu(), 0u);
-  EXPECT_EQ(result.entries(), 1u);
-  EXPECT_EQ(result.overrun(), 2u);
+  std::unique_ptr<protos::TracePacket> result_packet = writer->ParseProto();
+  auto result = result_packet->ftrace_stats().cpu_stats(0);
+  EXPECT_EQ(result.cpu(), 0);
+  EXPECT_EQ(result.entries(), 1);
+  EXPECT_EQ(result.overrun(), 2);
 }
 
 }  // namespace perfetto
diff --git a/src/traced/probes/ftrace/ftrace_data_source.cc b/src/traced/probes/ftrace/ftrace_data_source.cc
index f576f16..4f9ef3e 100644
--- a/src/traced/probes/ftrace/ftrace_data_source.cc
+++ b/src/traced/probes/ftrace/ftrace_data_source.cc
@@ -19,9 +19,9 @@
 #include "src/traced/probes/ftrace/cpu_reader.h"
 #include "src/traced/probes/ftrace/ftrace_controller.h"
 
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_stats.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace_stats.pbzero.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
 
@@ -43,12 +43,11 @@
     controller_weak_->RemoveDataSource(this);
 };
 
-void FtraceDataSource::Initialize(
-    FtraceConfigId config_id,
-    const FtraceDataSourceConfig* parsing_config) {
+void FtraceDataSource::Initialize(FtraceConfigId config_id,
+                                  const EventFilter* event_filter) {
   PERFETTO_CHECK(config_id);
   config_id_ = config_id;
-  parsing_config_ = parsing_config;
+  event_filter_ = event_filter;
 }
 
 void FtraceDataSource::Start() {
diff --git a/src/traced/probes/ftrace/ftrace_data_source.h b/src/traced/probes/ftrace/ftrace_data_source.h
index 1730616..6cd4f04 100644
--- a/src/traced/probes/ftrace/ftrace_data_source.h
+++ b/src/traced/probes/ftrace/ftrace_data_source.h
@@ -24,22 +24,22 @@
 #include <string>
 #include <utility>
 
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/weak_ptr.h"
 #include "perfetto/protozero/message_handle.h"
-#include "src/traced/probes/ftrace/ftrace_config_utils.h"
+#include "perfetto/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/trace_writer.h"
+#include "src/traced/probes/ftrace/ftrace_config.h"
 #include "src/traced/probes/ftrace/ftrace_metadata.h"
 #include "src/traced/probes/ftrace/ftrace_stats.h"
 #include "src/traced/probes/probes_data_source.h"
 
 namespace perfetto {
 
+class EventFilter;
 class FtraceController;
 class ProcessStatsDataSource;
 class InodeFileDataSource;
-struct FtraceDataSourceConfig;
 
 namespace protos {
 namespace pbzero {
@@ -63,7 +63,7 @@
 
   // Called by FtraceController soon after ProbesProducer creates the data
   // source, to inject ftrace dependencies.
-  void Initialize(FtraceConfigId, const FtraceDataSourceConfig* parsing_config);
+  void Initialize(FtraceConfigId, const EventFilter* event_filter);
 
   // ProbesDataSource implementation.
   void Start() override;
@@ -75,10 +75,7 @@
 
   FtraceConfigId config_id() const { return config_id_; }
   const FtraceConfig& config() const { return config_; }
-  const FtraceDataSourceConfig* parsing_config() const {
-    return parsing_config_;
-  }
-
+  const EventFilter* event_filter() { return event_filter_; }
   FtraceMetadata* mutable_metadata() { return &metadata_; }
   TraceWriter* trace_writer() { return writer_.get(); }
 
@@ -94,14 +91,11 @@
   FtraceStats stats_before_ = {};
   std::map<FlushRequestID, std::function<void()>> pending_flushes_;
 
-  // -- Fields initialized by the Initialize() call:
+  // Initialized by the Initialize() call.
   FtraceConfigId config_id_ = 0;
   std::unique_ptr<TraceWriter> writer_;
   base::WeakPtr<FtraceController> controller_weak_;
-  // Muxer-held state for parsing ftrace according to this data source's
-  // configuration. Not the raw FtraceConfig proto (held by |config_|).
-  const FtraceDataSourceConfig* parsing_config_;
-  // -- End of fields set by Initialize().
+  const EventFilter* event_filter_;
 };
 
 }  // namespace perfetto
diff --git a/src/traced/probes/ftrace/ftrace_metadata.cc b/src/traced/probes/ftrace/ftrace_metadata.cc
index c719a67..3ae8aaa 100644
--- a/src/traced/probes/ftrace/ftrace_metadata.cc
+++ b/src/traced/probes/ftrace/ftrace_metadata.cc
@@ -58,7 +58,7 @@
 }
 
 void FtraceMetadata::AddPid(int32_t pid) {
-  // Speculative optimization against repated pid's while keeping
+  // Speculative optimization aginst repated pid's while keeping
   // faster insertion than a set.
   if (!pids.empty() && pids.back() == pid)
     return;
@@ -81,6 +81,7 @@
   inode_and_device.clear();
   pids.clear();
   rename_pids.clear();
+  overwrite_count = 0;
   FinishEvent();
 }
 
diff --git a/src/traced/probes/ftrace/ftrace_metadata.h b/src/traced/probes/ftrace/ftrace_metadata.h
index ac37def..9d8f98d 100644
--- a/src/traced/probes/ftrace/ftrace_metadata.h
+++ b/src/traced/probes/ftrace/ftrace_metadata.h
@@ -31,11 +31,10 @@
 using BlockDeviceID = decltype(stat::st_dev);
 using Inode = decltype(stat::st_ino);
 
-// Container for tracking miscellaneous information while parsing ftrace events,
-// scoped to an individual data source.
 struct FtraceMetadata {
   FtraceMetadata();
 
+  uint32_t overwrite_count = 0;
   BlockDeviceID last_seen_device_id = 0;
 #if PERFETTO_DCHECK_IS_ON()
   bool seen_device_id = false;
diff --git a/src/traced/probes/ftrace/ftrace_procfs.cc b/src/traced/probes/ftrace/ftrace_procfs.cc
index 060f4cd..47e56e7 100644
--- a/src/traced/probes/ftrace/ftrace_procfs.cc
+++ b/src/traced/probes/ftrace/ftrace_procfs.cc
@@ -25,9 +25,9 @@
 #include <sstream>
 #include <string>
 
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/utils.h"
 
 namespace perfetto {
 
diff --git a/src/traced/probes/ftrace/ftrace_procfs.h b/src/traced/probes/ftrace/ftrace_procfs.h
index cd05adb..2860eae 100644
--- a/src/traced/probes/ftrace/ftrace_procfs.h
+++ b/src/traced/probes/ftrace/ftrace_procfs.h
@@ -21,7 +21,7 @@
 #include <set>
 #include <string>
 
-#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/base/scoped_file.h"
 
 namespace perfetto {
 
@@ -73,7 +73,7 @@
   // Disables tracing, does not clear the buffer.
   bool DisableTracing();
 
-  // Enables/disables tracing, does not clear the buffer.
+  // Enabls/disables tracing, does not clear the buffer.
   bool SetTracingOn(bool enable);
 
   // Returns true iff tracing is enabled.
@@ -88,7 +88,7 @@
   // Get the currently set clock.
   std::string GetClock();
 
-  // Get all the available clocks.
+  // Get all the avaiable clocks.
   std::set<std::string> AvailableClocks();
 
   // Open the raw pipe for |cpu|.
diff --git a/src/traced/probes/ftrace/ftrace_procfs_integrationtest.cc b/src/traced/probes/ftrace/ftrace_procfs_integrationtest.cc
index b8bf269..b63bd98 100644
--- a/src/traced/probes/ftrace/ftrace_procfs_integrationtest.cc
+++ b/src/traced/probes/ftrace/ftrace_procfs_integrationtest.cc
@@ -19,10 +19,11 @@
 #include <sstream>
 #include <string>
 
-#include "perfetto/ext/base/file_utils.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/file_utils.h"
 #include "src/traced/probes/ftrace/ftrace_controller.h"
 #include "src/traced/probes/ftrace/ftrace_procfs.h"
-#include "test/gtest_and_gmock.h"
 
 using testing::HasSubstr;
 using testing::Not;
diff --git a/src/traced/probes/ftrace/ftrace_procfs_unittest.cc b/src/traced/probes/ftrace/ftrace_procfs_unittest.cc
index a8051de..cac3360 100644
--- a/src/traced/probes/ftrace/ftrace_procfs_unittest.cc
+++ b/src/traced/probes/ftrace/ftrace_procfs_unittest.cc
@@ -16,7 +16,8 @@
 
 #include "src/traced/probes/ftrace/ftrace_procfs.h"
 
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 using testing::AnyNumber;
 using testing::IsEmpty;
diff --git a/src/traced/probes/ftrace/ftrace_stats.cc b/src/traced/probes/ftrace/ftrace_stats.cc
index eb3a99f..eff118d 100644
--- a/src/traced/probes/ftrace/ftrace_stats.cc
+++ b/src/traced/probes/ftrace/ftrace_stats.cc
@@ -16,7 +16,7 @@
 
 #include "src/traced/probes/ftrace/ftrace_stats.h"
 
-#include "protos/perfetto/trace/ftrace/ftrace_stats.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace_stats.pbzero.h"
 
 namespace perfetto {
 
diff --git a/src/traced/probes/ftrace/ftrace_thread_sync.h b/src/traced/probes/ftrace/ftrace_thread_sync.h
new file mode 100644
index 0000000..b2c4a9a
--- /dev/null
+++ b/src/traced/probes/ftrace/ftrace_thread_sync.h
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_TRACED_PROBES_FTRACE_FTRACE_THREAD_SYNC_H_
+#define SRC_TRACED_PROBES_FTRACE_FTRACE_THREAD_SYNC_H_
+
+#include <stdint.h>
+
+#include <bitset>
+#include <condition_variable>
+#include <mutex>
+
+#include "perfetto/base/utils.h"
+#include "perfetto/base/weak_ptr.h"
+
+namespace perfetto {
+
+namespace base {
+class TaskRunner;
+}  // namespace base
+
+class FtraceController;
+
+// This struct is accessed both by the FtraceController on the main thread and
+// by the CpuReader(s) on their worker threads. It is used to synchronize
+// handshakes between FtraceController and CpuReader(s). There is only *ONE*
+// instance of this state, owned by the FtraceController and shared with all
+// CpuReader(s).
+struct FtraceThreadSync {
+  explicit FtraceThreadSync(base::TaskRunner* tr) : task_runner(tr) {}
+
+  // These variables are set upon initialization time and never changed. Can
+  // be accessed outside of the |mutex|.
+  base::TaskRunner* const task_runner;  // Where the FtraceController lives.
+  base::WeakPtr<FtraceController> trace_controller_weak;
+
+  // Mutex & condition variable shared by main thread and all per-cpu workers.
+  // All fields below are read and modified holding |mutex|.
+  std::mutex mutex;
+
+  // Used to suspend CpuReader(s) between cycles and to wake them up at the
+  // same time.
+  std::condition_variable cond;
+
+  // |cmd| and |cmd_id| are written only by FtraceController. On each cycle,
+  // FtraceController increases the |cmd_id| monotonic counter and issues the
+  // new command. |cmd_id| is used by the CpuReader(s) to distinguish a new
+  // command from a spurious wakeup.
+  enum Cmd { kRun = 0, kFlush, kQuit };
+  Cmd cmd = kRun;
+  uint64_t cmd_id = 0;
+
+  // This bitmap is cleared by the FtraceController before every kRun command
+  // and is optionally set by OnDataAvailable() if a CpuReader did fetch any
+  // ftrace data during the read cycle.
+  std::bitset<base::kMaxCpus> cpus_to_drain;
+
+  // This bitmap is cleared by the FtraceController before issuing a kFlush
+  // command and set by each CpuReader after they have completed the flush.
+  std::bitset<base::kMaxCpus> flush_acks;
+};
+
+}  // namespace perfetto
+
+#endif  // SRC_TRACED_PROBES_FTRACE_FTRACE_THREAD_SYNC_H_
diff --git a/src/traced/probes/ftrace/page_pool.cc b/src/traced/probes/ftrace/page_pool.cc
new file mode 100644
index 0000000..f66309d
--- /dev/null
+++ b/src/traced/probes/ftrace/page_pool.cc
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#include "src/traced/probes/ftrace/page_pool.h"
+
+#include <array>
+
+namespace perfetto {
+
+namespace {
+constexpr size_t kMaxFreelistBlocks = 128;  // 128 * 32 * 4KB = 16MB.
+}
+
+void PagePool::NewPageBlock() {
+  std::lock_guard<std::mutex> lock(mutex_);
+  if (freelist_.empty()) {
+    write_queue_.emplace_back(PageBlock::Create());
+  } else {
+    write_queue_.emplace_back(std::move(freelist_.back()));
+    freelist_.pop_back();
+  }
+  PERFETTO_DCHECK(write_queue_.back().size() == 0);
+}
+
+void PagePool::EndRead(std::vector<PageBlock> page_blocks) {
+  PERFETTO_DCHECK_THREAD(reader_thread_);
+  for (PageBlock& page_block : page_blocks)
+    page_block.Clear();
+
+  std::lock_guard<std::mutex> lock(mutex_);
+  freelist_.insert(freelist_.end(),
+                   std::make_move_iterator(page_blocks.begin()),
+                   std::make_move_iterator(page_blocks.end()));
+
+  // Even if blocks in the freelist don't waste any resident memory (because
+  // the Clear() call above madvise()s them) let's avoid that in pathological
+  // cases we keep accumulating virtual address space reservations.
+  if (freelist_.size() > kMaxFreelistBlocks)
+    freelist_.erase(freelist_.begin() + kMaxFreelistBlocks, freelist_.end());
+}
+
+}  // namespace perfetto
diff --git a/src/traced/probes/ftrace/page_pool.h b/src/traced/probes/ftrace/page_pool.h
new file mode 100644
index 0000000..e558d85
--- /dev/null
+++ b/src/traced/probes/ftrace/page_pool.h
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_TRACED_PROBES_FTRACE_PAGE_POOL_H_
+#define SRC_TRACED_PROBES_FTRACE_PAGE_POOL_H_
+
+#include <stdint.h>
+
+#include <mutex>
+#include <vector>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/base/optional.h"
+#include "perfetto/base/paged_memory.h"
+#include "perfetto/base/thread_checker.h"
+#include "perfetto/base/utils.h"
+
+namespace perfetto {
+
+// This class is a page pool tailored around the needs of the ftrace CpuReader.
+// It has two responsibilities:
+// 1) A cheap bump-pointer page allocator for the writing side of CpuReader.
+// 2) A thread-safe producer/consumer queue to synchronize the read/write
+//    threads of CpuReader.
+// For context, CpuReader (and hence this class) is used on two threads:
+// (1) A worker thread that writes into the buffer and (2) the main thread which
+// reads all the content in big batches and turn them into protos.
+// There is at most one thread writing and at most one thread reading. In rare
+// circumstances they can be active At the same time.
+// This class is optimized for the following use case:
+// - Most of the times CpuReader wants to write 4096 bytes. In some rare cases
+//   (read() during flush) it wants to write < 4096 bytes.
+// - Even when it writes < 4096 bytes, CpuReader can figure out the size of the
+//   payload from the ftrace header. We don't need extra tracking to tell how
+//   much of each page is used.
+// - Doing a syscall for each page write is overkill. In most occasions
+//   CpuReader writes bursts of several pages in one go.
+// - We can't really predict upfront how big the write bursts will be, hence we
+//   cannot predict the size of the pool, unless we accept a very high bound.
+//   In extreme, yet rare, conditions, CpuReader will read the whole per-cpu
+//   ftrace buffer, while the reader is still reading the previous batch.
+// - Write burst should not be too frequent, so once they are over it's worth
+//   spending some extra cycles to release the memory.
+// - The reader side always wants to read *all* the written pages in one batch.
+//   While this happens though, the write might want to write more.
+//
+// The architecture of this class is as follows. Pages are organized in
+// PageBlock(s). A PageBlock is simply an array of pages and is the elementary
+// unit of memory allocation and frees. Pages within one block are cheaply
+// allocated with a simple bump-pointer allocator.
+//
+//      [      Writer (thread worker)    ] | [    Reader (main thread)   ]
+//                                  ~~~~~~~~~~~~~~~~~~~~~
+//      +---> write queue ------------> ready queue --+
+//      |                                             |
+//      +------------------------------- freelist <---+
+//                                  ~~~~~~~~~~~~~~~~~~~~~
+//                                  ~  mutex protected  ~
+//                                  ~~~~~~~~~~~~~~~~~~~~~
+class PagePool {
+ public:
+  class PageBlock {
+   public:
+    static constexpr size_t kPagesPerBlock = 32;  // 32 * 4KB = 128 KB.
+    static constexpr size_t kBlockSize = kPagesPerBlock * base::kPageSize;
+
+    // This factory method is just that we accidentally create extra blocks
+    // without realizing by triggering the default constructor in containers.
+    static PageBlock Create() { return PageBlock(); }
+
+    PageBlock(PageBlock&&) noexcept = default;
+    PageBlock& operator=(PageBlock&&) = default;
+
+    size_t size() const { return size_; }
+    bool IsFull() const { return size_ >= kPagesPerBlock; }
+
+    // Returns the pointer to the contents of the i-th page in the block.
+    uint8_t* At(size_t i) const {
+      PERFETTO_DCHECK(i < kPagesPerBlock);
+      return reinterpret_cast<uint8_t*>(mem_.Get()) + i * base::kPageSize;
+    }
+
+    uint8_t* CurPage() const { return At(size_); }
+
+    void NextPage() {
+      PERFETTO_DCHECK(!IsFull());
+      size_++;
+    }
+
+    // Releases memory of the block and marks it available for reuse.
+    void Clear() {
+      size_ = 0;
+      mem_.AdviseDontNeed(mem_.Get(), kBlockSize);
+    }
+
+   private:
+    PageBlock(const PageBlock&) = delete;
+    PageBlock& operator=(const PageBlock&) = delete;
+    PageBlock() { mem_ = base::PagedMemory::Allocate(kBlockSize); }
+
+    base::PagedMemory mem_;
+    size_t size_ = 0;
+  };
+
+  PagePool() {
+    PERFETTO_DETACH_FROM_THREAD(writer_thread_);
+    PERFETTO_DETACH_FROM_THREAD(reader_thread_);
+  }
+
+  // Grabs a new page, eventually allocating a whole new PageBlock.
+  // If contents are written to the page, the caller must call EndWrite().
+  // If no data is written, it is okay to leave the BeginWrite() unpaired
+  // (e.g., in case of a non-blocking read returning no data) and call again
+  // BeginWrite() in the future.
+  uint8_t* BeginWrite() {
+    PERFETTO_DCHECK_THREAD(writer_thread_);
+    if (write_queue_.empty() || write_queue_.back().IsFull())
+      NewPageBlock();  // Slowpath. Tries the freelist first, then allocates.
+    return write_queue_.back().CurPage();
+  }
+
+  // Marks the last page as written and bumps the write pointer.
+  void EndWrite() {
+    PERFETTO_DCHECK_THREAD(writer_thread_);
+    PERFETTO_DCHECK(!write_queue_.empty() && !write_queue_.back().IsFull());
+    write_queue_.back().NextPage();
+  }
+
+  // Makes all written pages available to the reader.
+  void CommitWrittenPages() {
+    PERFETTO_DCHECK_THREAD(writer_thread_);
+    std::lock_guard<std::mutex> lock(mutex_);
+    read_queue_.insert(read_queue_.end(),
+                       std::make_move_iterator(write_queue_.begin()),
+                       std::make_move_iterator(write_queue_.end()));
+    write_queue_.clear();
+  }
+
+  // Moves ownership of all the page blocks in the read queue to the caller.
+  // The caller is expected to move them back after reading through EndRead().
+  // PageBlocks will be freed if the caller doesn't call EndRead().
+  std::vector<PageBlock> BeginRead() {
+    PERFETTO_DCHECK_THREAD(reader_thread_);
+    std::lock_guard<std::mutex> lock(mutex_);
+    auto res = std::move(read_queue_);
+    read_queue_.clear();
+    return res;
+  }
+
+  // Returns the page blocks borrowed for read and makes them available for
+  // reuse. This allows the writer to avoid doing syscalls after the initial
+  // writes.
+  void EndRead(std::vector<PageBlock> page_blocks);
+
+  size_t freelist_size_for_testing() const { return freelist_.size(); }
+
+ private:
+  PagePool(const PagePool&) = delete;
+  PagePool& operator=(const PagePool&) = delete;
+  void NewPageBlock();
+
+  PERFETTO_THREAD_CHECKER(writer_thread_)
+  std::vector<PageBlock> write_queue_;  // Accessed exclusively by the writer.
+
+  std::mutex mutex_;  // Protects both the read queue and the freelist.
+
+  PERFETTO_THREAD_CHECKER(reader_thread_)
+  std::vector<PageBlock> read_queue_;  // Accessed by both threads.
+  std::vector<PageBlock> freelist_;    // Accessed by both threads.
+};
+
+}  // namespace perfetto
+
+#endif  // SRC_TRACED_PROBES_FTRACE_PAGE_POOL_H_
diff --git a/src/traced/probes/ftrace/page_pool_unittest.cc b/src/traced/probes/ftrace/page_pool_unittest.cc
new file mode 100644
index 0000000..3e7fbcb
--- /dev/null
+++ b/src/traced/probes/ftrace/page_pool_unittest.cc
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+#include "src/traced/probes/ftrace/page_pool.h"
+
+#include <array>
+#include <mutex>
+#include <random>
+#include <thread>
+#include <vector>
+
+#include "gtest/gtest.h"
+
+namespace perfetto {
+namespace {
+
+TEST(PagePoolTest, SingleThreaded) {
+  PagePool pool;
+  for (int i = 0; i < 2; i++)
+    ASSERT_TRUE(pool.BeginRead().empty());
+
+  for (int repeat = 0; repeat < 3; repeat++) {
+    for (uint32_t seed = 0; seed < 6; seed++) {
+      uint8_t* page = pool.BeginWrite();
+      std::minstd_rand0 rnd_engine(seed);
+      std::generate(page, page + base::kPageSize, rnd_engine);
+      // Deliberately make it so pages 3 is overwritten, so we should see only
+      // pages 0, 1, 2, 4, 5.
+      if (seed != 3)
+        pool.EndWrite();
+    }
+
+    // No write should be visible until the CommitWrittenPages() call.
+    ASSERT_TRUE(pool.BeginRead().empty());
+
+    pool.CommitWrittenPages();
+
+    auto blocks = pool.BeginRead();
+    ASSERT_EQ(blocks.size(), 1);
+    ASSERT_EQ(blocks[0].size(), 5);
+    for (uint32_t i = 0; i < blocks[0].size(); i++) {
+      auto seed = std::array<uint32_t, 5>{{0, 1, 2, 4, 5}}[i];
+      const char* page = reinterpret_cast<const char*>(blocks[0].At(i));
+      char expected[base::kPageSize];
+      std::minstd_rand0 rnd_engine(seed);
+      std::generate(expected, expected + base::kPageSize, rnd_engine);
+      EXPECT_STREQ(page, expected);
+    }
+
+    pool.EndRead(std::move(blocks));
+    ASSERT_EQ(pool.freelist_size_for_testing(), 1);
+  }
+}
+
+TEST(PagePoolTest, MultiThreaded) {
+  PagePool pool;
+
+  // Generate some random content.
+  std::vector<std::string> expected_pages;
+  std::minstd_rand0 rnd_engine(0);
+  for (int i = 0; i < 1000; i++) {
+    expected_pages.emplace_back();
+    std::string& page = expected_pages.back();
+    page.resize(base::kPageSize);
+    std::generate(page.begin(), page.end(), rnd_engine);
+  }
+
+  auto writer_fn = [&pool, &expected_pages] {
+    std::minstd_rand0 rnd(0);
+    for (const std::string& expected_page : expected_pages) {
+      uint8_t* dst = pool.BeginWrite();
+      memcpy(dst, expected_page.data(), base::kPageSize);
+      pool.EndWrite();
+      if (rnd() % 16 == 0)
+        pool.CommitWrittenPages();
+    }
+    pool.CommitWrittenPages();
+  };
+
+  auto reader_fn = [&pool, &expected_pages] {
+    for (size_t page_idx = 0; page_idx < expected_pages.size();) {
+      auto blocks = pool.BeginRead();
+      for (const auto& block : blocks) {
+        for (size_t i = 0; i < block.size(); i++) {
+          const char* page = reinterpret_cast<const char*>(block.At(i));
+          EXPECT_EQ(expected_pages[page_idx],
+                    std::string(page, base::kPageSize));
+          page_idx++;
+        }
+      }
+      pool.EndRead(std::move(blocks));
+    }
+  };
+
+  std::thread writer(writer_fn);
+  std::thread reader(reader_fn);
+  writer.join();
+  reader.join();
+}
+
+}  // namespace
+}  // namespace perfetto
diff --git a/src/traced/probes/ftrace/proto_translation_table.cc b/src/traced/probes/ftrace/proto_translation_table.cc
index 86c61f0..16b87fd 100644
--- a/src/traced/probes/ftrace/proto_translation_table.cc
+++ b/src/traced/probes/ftrace/proto_translation_table.cc
@@ -21,21 +21,21 @@
 
 #include <algorithm>
 
-#include "perfetto/ext/base/string_utils.h"
+#include "perfetto/base/string_utils.h"
 #include "perfetto/protozero/proto_utils.h"
 #include "src/traced/probes/ftrace/event_info.h"
 #include "src/traced/probes/ftrace/ftrace_procfs.h"
 
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-#include "protos/perfetto/trace/ftrace/generic.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace_event.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
+#include "perfetto/trace/ftrace/generic.pbzero.h"
 
 namespace perfetto {
 
 namespace {
 
-using protos::pbzero::GenericFtraceEvent;
 using protozero::proto_utils::ProtoSchemaType;
+using protos::pbzero::GenericFtraceEvent;
 
 ProtoTranslationTable::FtracePageHeaderSpec MakeFtracePageHeaderSpec(
     const std::vector<FtraceEvent::Field>& fields) {
@@ -74,9 +74,8 @@
   if (commit_size < 8 && uname(&sysinfo) == 0) {
     // Arm returns armv# for its machine type. The first (and only currently)
     // arm processor that supports 64bit is the armv8 series.
-    commit_size =
-        strstr(sysinfo.machine, "64") || strstr(sysinfo.machine, "armv8") ? 8
-                                                                          : 4;
+    commit_size = strstr(sysinfo.machine, "64") ||
+                  strstr(sysinfo.machine, "armv8") ? 8 : 4;
   }
 #endif
 
@@ -162,7 +161,7 @@
                      const char* event_name_for_debug) {
   uint16_t fields_end = 0;
 
-  // Loop over each Field in |fields| modifying it with information from the
+  // Loop over each Field in |fields| modifiying it with information from the
   // matching |ftrace_fields| field or removing it.
   auto field = fields->begin();
   while (field != fields->end()) {
@@ -242,8 +241,6 @@
       *proto_type = ProtoSchemaType::kUint64;
       *proto_field_id = GenericFtraceEvent::Field::kUintValueFieldNumber;
       break;
-    case kInvalidFtraceFieldType:
-      PERFETTO_FATAL("Unexpected ftrace field type");
   }
 }
 
@@ -449,13 +446,8 @@
                               }),
                events.end());
 
-  // Pre-parse certain scheduler events, and see if the compile-time assumptions
-  // about their format hold for this kernel.
-  CompactSchedEventFormat compact_sched = ValidateFormatForCompactSched(events);
-
-  auto table = std::unique_ptr<ProtoTranslationTable>(
-      new ProtoTranslationTable(ftrace_procfs, events, std::move(common_fields),
-                                header_spec, compact_sched));
+  auto table = std::unique_ptr<ProtoTranslationTable>(new ProtoTranslationTable(
+      ftrace_procfs, events, std::move(common_fields), header_spec));
   return table;
 }
 
@@ -463,14 +455,12 @@
     const FtraceProcfs* ftrace_procfs,
     const std::vector<Event>& events,
     std::vector<Field> common_fields,
-    FtracePageHeaderSpec ftrace_page_header_spec,
-    CompactSchedEventFormat compact_sched_format)
+    FtracePageHeaderSpec ftrace_page_header_spec)
     : ftrace_procfs_(ftrace_procfs),
       events_(BuildEventsVector(events)),
       largest_id_(events_.size() - 1),
       common_fields_(std::move(common_fields)),
-      ftrace_page_header_spec_(ftrace_page_header_spec),
-      compact_sched_format_(compact_sched_format) {
+      ftrace_page_header_spec_(ftrace_page_header_spec) {
   for (const Event& event : events) {
     group_and_name_to_event_[GroupAndName(event.group, event.name)] =
         &events_.at(event.ftrace_event_id);
diff --git a/src/traced/probes/ftrace/proto_translation_table.h b/src/traced/probes/ftrace/proto_translation_table.h
index f9c5be6..fe4abde 100644
--- a/src/traced/probes/ftrace/proto_translation_table.h
+++ b/src/traced/probes/ftrace/proto_translation_table.h
@@ -25,8 +25,7 @@
 #include <string>
 #include <vector>
 
-#include "perfetto/ext/base/scoped_file.h"
-#include "src/traced/probes/ftrace/compact_sched.h"
+#include "perfetto/base/scoped_file.h"
 #include "src/traced/probes/ftrace/event_info.h"
 #include "src/traced/probes/ftrace/format_parser.h"
 
@@ -92,8 +91,7 @@
   ProtoTranslationTable(const FtraceProcfs* ftrace_procfs,
                         const std::vector<Event>& events,
                         std::vector<Field> common_fields,
-                        FtracePageHeaderSpec ftrace_page_header_spec,
-                        CompactSchedEventFormat compact_sched_format);
+                        FtracePageHeaderSpec ftrace_page_header_spec);
 
   size_t largest_id() const { return largest_id_; }
 
@@ -153,10 +151,6 @@
     return name_to_events_.at(name)[0];
   }
 
-  const CompactSchedEventFormat& compact_sched_format() const {
-    return compact_sched_format_;
-  }
-
  private:
   ProtoTranslationTable(const ProtoTranslationTable&) = delete;
   ProtoTranslationTable& operator=(const ProtoTranslationTable&) = delete;
@@ -176,7 +170,6 @@
   std::vector<Field> common_fields_;
   FtracePageHeaderSpec ftrace_page_header_spec_{};
   std::set<std::string> interned_strings_;
-  CompactSchedEventFormat compact_sched_format_;
 };
 
 // Class for efficient 'is event with id x enabled?' checks.
diff --git a/src/traced/probes/ftrace/proto_translation_table_unittest.cc b/src/traced/probes/ftrace/proto_translation_table_unittest.cc
index 8f54e48..89d6c67 100644
--- a/src/traced/probes/ftrace/proto_translation_table_unittest.cc
+++ b/src/traced/probes/ftrace/proto_translation_table_unittest.cc
@@ -16,14 +16,13 @@
 
 #include "src/traced/probes/ftrace/proto_translation_table.h"
 
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/generic.pbzero.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/trace/ftrace/ftrace_event.pbzero.h"
+#include "perfetto/trace/ftrace/generic.pbzero.h"
 #include "src/base/test/gtest_test_suite.h"
-#include "src/base/test/utils.h"
-#include "src/traced/probes/ftrace/compact_sched.h"
 #include "src/traced/probes/ftrace/event_info.h"
 #include "src/traced/probes/ftrace/ftrace_procfs.h"
-#include "test/gtest_and_gmock.h"
 
 using testing::_;
 using testing::Values;
@@ -53,8 +52,8 @@
 class AllTranslationTableTest : public TestWithParam<const char*> {
  public:
   void SetUp() override {
-    std::string path = base::GetTestDataPath(
-        "src/traced/probes/ftrace/test/data/" + std::string(GetParam()) + "/");
+    std::string path =
+        "src/traced/probes/ftrace/test/data/" + std::string(GetParam()) + "/";
     FtraceProcfs ftrace_procfs(path);
     table_ = ProtoTranslationTable::Create(&ftrace_procfs, GetStaticEventInfo(),
                                            GetStaticCommonFieldsInfo());
@@ -107,8 +106,8 @@
 INSTANTIATE_TEST_SUITE_P(ByDevice, AllTranslationTableTest, ValuesIn(kDevices));
 
 TEST(TranslationTableTest, Seed) {
-  std::string path = base::GetTestDataPath(
-      "src/traced/probes/ftrace/test/data/android_seed_N2F62_3.10.49/");
+  std::string path =
+      "src/traced/probes/ftrace/test/data/android_seed_N2F62_3.10.49/";
   FtraceProcfs ftrace_procfs(path);
   auto table = ProtoTranslationTable::Create(
       &ftrace_procfs, GetStaticEventInfo(), GetStaticCommonFieldsInfo());
@@ -173,6 +172,7 @@
 	field:u32 field_e;	offset:32;	size:4;	signed:0;
 
 print fmt: "some format")"));
+  ;
 
   EXPECT_CALL(ftrace, ReadPageHeaderFormat()).Times(AnyNumber());
   EXPECT_CALL(ftrace, ReadEventFormat(_, _)).Times(AnyNumber());
@@ -259,58 +259,6 @@
 
 INSTANTIATE_TEST_SUITE_P(BySize, TranslationTableCreationTest, Values(4, 8));
 
-TEST(TranslationTableTest, CompactSchedFormatParsingWalleyeData) {
-  std::string path =
-      "src/traced/probes/ftrace/test/data/"
-      "android_walleye_OPM5.171019.017.A1_4.4.88/";
-  FtraceProcfs ftrace_procfs(path);
-  auto table = ProtoTranslationTable::Create(
-      &ftrace_procfs, GetStaticEventInfo(), GetStaticCommonFieldsInfo());
-  PERFETTO_CHECK(table);
-  const CompactSchedEventFormat& format = table->compact_sched_format();
-
-  // Format matches compile-time assumptions.
-  ASSERT_TRUE(format.format_valid);
-
-  // Check exact sched_switch format (note: 64 bit long prev_state).
-  EXPECT_EQ(47u, format.sched_switch.event_id);
-  EXPECT_EQ(64u, format.sched_switch.size);
-  EXPECT_EQ(56u, format.sched_switch.next_pid_offset);
-  EXPECT_EQ(FtraceFieldType::kFtracePid32, format.sched_switch.next_pid_type);
-  EXPECT_EQ(60u, format.sched_switch.next_prio_offset);
-  EXPECT_EQ(FtraceFieldType::kFtraceInt32, format.sched_switch.next_prio_type);
-  EXPECT_EQ(32u, format.sched_switch.prev_state_offset);
-  EXPECT_EQ(FtraceFieldType::kFtraceInt64, format.sched_switch.prev_state_type);
-  EXPECT_EQ(40u, format.sched_switch.next_comm_offset);
-
-  // Check exact sched_waking format.
-  EXPECT_EQ(44u, format.sched_waking.event_id);
-  EXPECT_EQ(40u, format.sched_waking.size);
-  EXPECT_EQ(24u, format.sched_waking.pid_offset);
-  EXPECT_EQ(FtraceFieldType::kFtracePid32, format.sched_waking.pid_type);
-  EXPECT_EQ(36u, format.sched_waking.target_cpu_offset);
-  EXPECT_EQ(FtraceFieldType::kFtraceInt32, format.sched_waking.target_cpu_type);
-  EXPECT_EQ(28u, format.sched_waking.prio_offset);
-  EXPECT_EQ(FtraceFieldType::kFtraceInt32, format.sched_waking.prio_type);
-  EXPECT_EQ(8u, format.sched_waking.comm_offset);
-}
-
-TEST(TranslationTableTest, CompactSchedFormatParsingSeedData) {
-  std::string path =
-      "src/traced/probes/ftrace/test/data/android_seed_N2F62_3.10.49/";
-  FtraceProcfs ftrace_procfs(path);
-  auto table = ProtoTranslationTable::Create(
-      &ftrace_procfs, GetStaticEventInfo(), GetStaticCommonFieldsInfo());
-  PERFETTO_CHECK(table);
-  const CompactSchedEventFormat& format = table->compact_sched_format();
-
-  // We consider the entire format invalid as there's no sched_waking event
-  // available. This is a simplifying assumption. We could instead look at each
-  // event independently (and in this case, sched_switch does match compile-time
-  // assumptions).
-  ASSERT_FALSE(format.format_valid);
-}
-
 TEST(TranslationTableTest, InferFtraceType) {
   FtraceFieldType type;
 
@@ -394,9 +342,7 @@
 
   ProtoTranslationTable table(
       &ftrace, events, std::move(common_fields),
-      ProtoTranslationTable::DefaultPageHeaderSpecForTesting(),
-      InvalidCompactSchedEventFormatForTesting());
-
+      ProtoTranslationTable::DefaultPageHeaderSpecForTesting());
   EXPECT_EQ(table.largest_id(), 100ul);
   EXPECT_EQ(table.EventToFtraceId(GroupAndName("group_one", "foo")), 1ul);
   EXPECT_EQ(table.EventToFtraceId(GroupAndName("group_two", "baz")), 100ul);
@@ -456,9 +402,9 @@
   EXPECT_EQ(table->EventToFtraceId(group_and_name), 42ul);
 
   // Check getters
-  EXPECT_EQ(static_cast<int>(table->GetEventById(42)->proto_field_id),
+  EXPECT_EQ(table->GetEventById(42)->proto_field_id,
             protos::pbzero::FtraceEvent::kGenericFieldNumber);
-  EXPECT_EQ(static_cast<int>(table->GetEvent(group_and_name)->proto_field_id),
+  EXPECT_EQ(table->GetEvent(group_and_name)->proto_field_id,
             protos::pbzero::FtraceEvent::kGenericFieldNumber);
   EXPECT_EQ(table->GetEventsByGroup("group")->front()->name,
             group_and_name.name());
@@ -468,7 +414,7 @@
   // Check string field
   const auto& str_field = fields[0];
   EXPECT_STREQ(str_field.ftrace_name, "field_a");
-  EXPECT_EQ(static_cast<int>(str_field.proto_field_id),
+  EXPECT_EQ(str_field.proto_field_id,
             protos::pbzero::GenericFtraceEvent::Field::kStrValueFieldNumber);
   EXPECT_EQ(str_field.proto_field_type, ProtoSchemaType::kString);
   EXPECT_EQ(str_field.ftrace_type, kFtraceFixedCString);
@@ -478,7 +424,7 @@
   // Check bool field
   const auto& bool_field = fields[1];
   EXPECT_STREQ(bool_field.ftrace_name, "field_b");
-  EXPECT_EQ(static_cast<int>(bool_field.proto_field_id),
+  EXPECT_EQ(bool_field.proto_field_id,
             protos::pbzero::GenericFtraceEvent::Field::kUintValueFieldNumber);
   EXPECT_EQ(bool_field.proto_field_type, ProtoSchemaType::kUint64);
   EXPECT_EQ(bool_field.ftrace_type, kFtraceBool);
@@ -488,7 +434,7 @@
   // Check int field
   const auto& int_field = fields[2];
   EXPECT_STREQ(int_field.ftrace_name, "field_c");
-  EXPECT_EQ(static_cast<int>(int_field.proto_field_id),
+  EXPECT_EQ(int_field.proto_field_id,
             protos::pbzero::GenericFtraceEvent::Field::kIntValueFieldNumber);
   EXPECT_EQ(int_field.proto_field_type, ProtoSchemaType::kInt64);
   EXPECT_EQ(int_field.ftrace_type, kFtraceInt32);
@@ -498,7 +444,7 @@
   // Check uint field
   const auto& uint_field = fields[3];
   EXPECT_STREQ(uint_field.ftrace_name, "field_d");
-  EXPECT_EQ(static_cast<int>(uint_field.proto_field_id),
+  EXPECT_EQ(uint_field.proto_field_id,
             protos::pbzero::GenericFtraceEvent::Field::kUintValueFieldNumber);
   EXPECT_EQ(uint_field.proto_field_type, ProtoSchemaType::kUint64);
   EXPECT_EQ(uint_field.ftrace_type, kFtraceUint32);
diff --git a/src/traced/probes/ftrace/test/cpu_reader_support.cc b/src/traced/probes/ftrace/test/cpu_reader_support.cc
index 020298b..4d1ce03 100644
--- a/src/traced/probes/ftrace/test/cpu_reader_support.cc
+++ b/src/traced/probes/ftrace/test/cpu_reader_support.cc
@@ -16,8 +16,7 @@
 
 #include "src/traced/probes/ftrace/test/cpu_reader_support.h"
 
-#include "perfetto/ext/base/utils.h"
-#include "src/base/test/utils.h"
+#include "perfetto/base/utils.h"
 #include "src/traced/probes/ftrace/ftrace_procfs.h"
 
 #include <string.h>
@@ -30,6 +29,22 @@
 
 std::map<std::string, std::unique_ptr<ProtoTranslationTable>>* g_tables;
 
+std::string GetBinaryDirectory() {
+  std::string buf(512, '\0');
+  ssize_t rd = readlink("/proc/self/exe", &buf[0], buf.size());
+  if (rd < 0) {
+    PERFETTO_ELOG("Failed to readlink(\"/proc/self/exe\"");
+    return "";
+  }
+  buf.resize(static_cast<size_t>(rd));
+  size_t end = buf.rfind('/');
+  if (end == std::string::npos) {
+    PERFETTO_ELOG("Failed to find directory.");
+    return "";
+  }
+  return buf.substr(0, end + 1);
+}
+
 }  // namespace
 
 ProtoTranslationTable* GetTable(const std::string& name) {
@@ -41,7 +56,7 @@
     struct stat st;
     if (lstat(path.c_str(), &st) == -1 && errno == ENOENT) {
       // For OSS fuzz, which does not run in the correct cwd.
-      path = base::GetTestDataPath(path);
+      path = GetBinaryDirectory() + path;
     }
     FtraceProcfs ftrace(path);
     auto table = ProtoTranslationTable::Create(&ftrace, GetStaticEventInfo(),
diff --git a/src/traced/probes/ftrace/test/cpu_reader_support.h b/src/traced/probes/ftrace/test/cpu_reader_support.h
index ab91932..d73ebcc 100644
--- a/src/traced/probes/ftrace/test/cpu_reader_support.h
+++ b/src/traced/probes/ftrace/test/cpu_reader_support.h
@@ -32,7 +32,7 @@
   const char* data;
 };
 
-// Create a ProtoTranslationTable using the fomat files in
+// Create a ProtoTranslationTable uing the fomat files in
 // directory |name|. Caches the table for subsequent lookups.
 ProtoTranslationTable* GetTable(const std::string& name);
 
diff --git a/src/traced/probes/ftrace/test/data/synthetic/available_events b/src/traced/probes/ftrace/test/data/synthetic/available_events
index 28798fa..0a0ea6f 100644
--- a/src/traced/probes/ftrace/test/data/synthetic/available_events
+++ b/src/traced/probes/ftrace/test/data/synthetic/available_events
@@ -1,5 +1,4 @@
 sched:sched_switch
-sched:sched_waking
 kmem:ion_heap_grow
 kmem:ion_heap_shrink
 kmem:rss_stat
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/sched/sched_waking/format b/src/traced/probes/ftrace/test/data/synthetic/events/sched/sched_waking/format
deleted file mode 100644
index 57bd43f..0000000
--- a/src/traced/probes/ftrace/test/data/synthetic/events/sched/sched_waking/format
+++ /dev/null
@@ -1,15 +0,0 @@
-name: sched_waking
-ID: 44
-format:
-	field:unsigned short common_type;	offset:0;	size:2;	signed:0;
-	field:unsigned char common_flags;	offset:2;	size:1;	signed:0;
-	field:unsigned char common_preempt_count;	offset:3;	size:1;	signed:0;
-	field:int common_pid;	offset:4;	size:4;	signed:1;
-
-	field:char comm[16];	offset:8;	size:16;	signed:0;
-	field:pid_t pid;	offset:24;	size:4;	signed:1;
-	field:int prio;	offset:28;	size:4;	signed:1;
-	field:int success;	offset:32;	size:4;	signed:1;
-	field:int target_cpu;	offset:36;	size:4;	signed:1;
-
-print fmt: "comm=%s pid=%d prio=%d target_cpu=%03d", REC->comm, REC->pid, REC->prio, REC->target_cpu
diff --git a/src/traced/probes/ftrace/test/test_proto_gen.py b/src/traced/probes/ftrace/test/test_proto_gen.py
index a7f63e2..104a3a2 100755
--- a/src/traced/probes/ftrace/test/test_proto_gen.py
+++ b/src/traced/probes/ftrace/test/test_proto_gen.py
@@ -19,11 +19,9 @@
 import subprocess
 import tempfile
 
-
 def test_command(*args):
   subprocess.check_call(args, stdout=sys.stdout, stderr=sys.stderr)
 
-
 if __name__ == '__main__':
   if len(sys.argv) != 4:
     print('Usage: test_proto_gen.py to/ftrace_proto_gen to/protoc to/format')
@@ -34,5 +32,8 @@
   tmpdir = tempfile.mkdtemp()
   proto_path = os.path.join(tmpdir, 'format.proto')
   test_command(ftrace_proto_gen_path, format_path, proto_path)
-  test_command(protoc_path, proto_path, '--proto_path=' + tmpdir,
-               '--cpp_out=' + tmpdir)
+  test_command(
+      protoc_path,
+      proto_path,
+      '--proto_path='+tmpdir,
+      '--cpp_out='+tmpdir)
diff --git a/src/traced/probes/main.cc b/src/traced/probes/main.cc
index a91a6b6..71b9d4e 100644
--- a/src/traced/probes/main.cc
+++ b/src/traced/probes/main.cc
@@ -15,7 +15,7 @@
  */
 
 #include <stdio.h>
-#include "perfetto/ext/traced/traced.h"
+#include "perfetto/traced/traced.h"
 
 int main(int argc, char** argv) {
   return perfetto::ProbesMain(argc, argv);
diff --git a/src/traced/probes/metatrace/BUILD.gn b/src/traced/probes/metatrace/BUILD.gn
deleted file mode 100644
index 489b85a..0000000
--- a/src/traced/probes/metatrace/BUILD.gn
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2019 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.
-
-source_set("metatrace") {
-  public_deps = [
-    "../../../tracing",
-  ]
-  deps = [
-    "..:data_source",
-    "../../../../gn:default_deps",
-    "../../../../include/perfetto/ext/traced",
-    "../../../../protos/perfetto/trace/perfetto:zero",
-    "../../../base",
-    "../../../tracing",
-  ]
-  sources = [
-    "metatrace_data_source.cc",
-    "metatrace_data_source.h",
-  ]
-}
diff --git a/src/traced/probes/metatrace/metatrace_data_source.cc b/src/traced/probes/metatrace/metatrace_data_source.cc
deleted file mode 100644
index f87117e..0000000
--- a/src/traced/probes/metatrace/metatrace_data_source.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/traced/probes/metatrace/metatrace_data_source.h"
-
-#include <vector>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/base/task_runner.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "src/tracing/core/metatrace_writer.h"
-
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-namespace perfetto {
-
-// static
-const char* MetatraceDataSource::kDataSourceName =
-    MetatraceWriter::kDataSourceName;
-
-MetatraceDataSource::MetatraceDataSource(base::TaskRunner* task_runner,
-                                         TracingSessionID session_id,
-                                         std::unique_ptr<TraceWriter> writer)
-    : ProbesDataSource(session_id, kTypeId),
-      task_runner_(task_runner),
-      trace_writer_(std::move(writer)) {}
-
-MetatraceDataSource::~MetatraceDataSource() {
-  metatrace_writer_->Disable();
-}
-
-void MetatraceDataSource::Start() {
-  metatrace_writer_.reset(new MetatraceWriter());
-  metatrace_writer_->Enable(task_runner_, std::move(trace_writer_),
-                            metatrace::TAG_ANY);
-}
-
-// This method is also called from StopDataSource with a dummy FlushRequestID
-// (zero), to ensure that the metatrace commits the events recorded during the
-// final flush of the tracing session.
-void MetatraceDataSource::Flush(FlushRequestID,
-                                std::function<void()> callback) {
-  metatrace_writer_->WriteAllAndFlushTraceWriter(std::move(callback));
-}
-
-}  // namespace perfetto
diff --git a/src/traced/probes/metatrace/metatrace_data_source.h b/src/traced/probes/metatrace/metatrace_data_source.h
deleted file mode 100644
index 3bd0d04..0000000
--- a/src/traced/probes/metatrace/metatrace_data_source.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACED_PROBES_METATRACE_METATRACE_DATA_SOURCE_H_
-#define SRC_TRACED_PROBES_METATRACE_METATRACE_DATA_SOURCE_H_
-
-#include <memory>
-
-#include "src/traced/probes/probes_data_source.h"
-
-namespace perfetto {
-
-class MetatraceWriter;
-class TraceWriter;
-
-namespace base {
-class TaskRunner;
-}
-
-class MetatraceDataSource : public ProbesDataSource {
- public:
-  static constexpr int kTypeId = 8;
-  static const char* kDataSourceName;
-
-  MetatraceDataSource(base::TaskRunner*,
-                      TracingSessionID,
-                      std::unique_ptr<TraceWriter> writer);
-
-  ~MetatraceDataSource() override;
-
-  // ProbesDataSource implementation.
-  void Start() override;
-  void Flush(FlushRequestID, std::function<void()> callback) override;
-
- private:
-  base::TaskRunner* const task_runner_;
-  std::unique_ptr<TraceWriter> trace_writer_;
-  std::unique_ptr<MetatraceWriter> metatrace_writer_;
-};
-
-}  // namespace perfetto
-
-#endif  // SRC_TRACED_PROBES_METATRACE_METATRACE_DATA_SOURCE_H_
diff --git a/src/traced/probes/packages_list/BUILD.gn b/src/traced/probes/packages_list/BUILD.gn
index b1092d1..c79eeda 100644
--- a/src/traced/probes/packages_list/BUILD.gn
+++ b/src/traced/probes/packages_list/BUILD.gn
@@ -12,8 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../../gn/test.gni")
-
 source_set("packages_list") {
   public_deps = [
     "../../../tracing",
@@ -21,9 +19,9 @@
   deps = [
     "..:data_source",
     "../../../../gn:default_deps",
-    "../../../../include/perfetto/ext/traced",
+    "../../../../include/perfetto/traced",
     "../../../../protos/perfetto/common:zero",
-    "../../../../protos/perfetto/config/android:zero",
+    "../../../../protos/perfetto/config:zero",
     "../../../../protos/perfetto/trace/android:zero",
     "../../../base",
   ]
@@ -33,12 +31,12 @@
   ]
 }
 
-perfetto_unittest_source_set("unittests") {
+source_set("unittests") {
   testonly = true
   deps = [
     ":packages_list",
     "../../../../gn:default_deps",
-    "../../../../gn:gtest_and_gmock",
+    "../../../../gn:gtest_deps",
     "../../../../protos/perfetto/trace/android:lite",
     "../../../../protos/perfetto/trace/android:zero",
     "../../../../src/base:test_support",
diff --git a/src/traced/probes/packages_list/packages_list_data_source.cc b/src/traced/probes/packages_list/packages_list_data_source.cc
index 730d0f6..0c39d54 100644
--- a/src/traced/probes/packages_list/packages_list_data_source.cc
+++ b/src/traced/probes/packages_list/packages_list_data_source.cc
@@ -16,11 +16,14 @@
 
 #include "src/traced/probes/packages_list/packages_list_data_source.h"
 
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/string_splitter.h"
-
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/string_splitter.h"
+#include "perfetto/config/android/packages_list_config.pbzero.h"
+#include "perfetto/trace/android/packages_list.pbzero.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/tracing/core/data_source_config.h"
+#include "perfetto/tracing/core/packages_list_config.h"
+#include "perfetto/tracing/core/trace_writer.h"
 
 using perfetto::protos::pbzero::PackagesListConfig;
 
@@ -110,9 +113,9 @@
     TracingSessionID session_id,
     std::unique_ptr<TraceWriter> writer)
     : ProbesDataSource(session_id, kTypeId), writer_(std::move(writer)) {
-  PackagesListConfig::Decoder cfg(ds_config.packages_list_config_raw());
-  for (auto name = cfg.package_name_filter(); name; ++name) {
-    package_name_filter_.emplace((*name).ToStdString());
+  for (const auto& name :
+       ds_config.packages_list_config().package_name_filter()) {
+    package_name_filter_.emplace(name);
   }
 }
 
diff --git a/src/traced/probes/packages_list/packages_list_data_source.h b/src/traced/probes/packages_list/packages_list_data_source.h
index 6f0ee9a..871da7d 100644
--- a/src/traced/probes/packages_list/packages_list_data_source.h
+++ b/src/traced/probes/packages_list/packages_list_data_source.h
@@ -21,14 +21,12 @@
 #include <memory>
 #include <set>
 
+#include "perfetto/base/scoped_file.h"
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/scoped_file.h"
-
-#include "perfetto/ext/tracing/core/basic_types.h"
+#include "perfetto/trace/android/packages_list.pbzero.h"
+#include "perfetto/tracing/core/basic_types.h"
 #include "perfetto/tracing/core/data_source_config.h"
-#include "protos/perfetto/config/android/packages_list_config.pbzero.h"
-#include "protos/perfetto/trace/android/packages_list.pbzero.h"
-
+#include "perfetto/tracing/core/packages_list_config.h"
 #include "src/traced/probes/probes_data_source.h"
 
 namespace perfetto {
diff --git a/src/traced/probes/packages_list/packages_list_data_source_unittest.cc b/src/traced/probes/packages_list/packages_list_data_source_unittest.cc
index f2f7675..dc9bc82 100644
--- a/src/traced/probes/packages_list/packages_list_data_source_unittest.cc
+++ b/src/traced/probes/packages_list/packages_list_data_source_unittest.cc
@@ -16,16 +16,16 @@
 
 #include "src/traced/probes/packages_list/packages_list_data_source.h"
 
+#include <gtest/gtest.h>
 #include <stdio.h>
 
 #include <set>
 #include <string>
 
-#include "perfetto/ext/base/pipe.h"
+#include "perfetto/base/pipe.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
-#include "protos/perfetto/trace/android/packages_list.pb.h"
-#include "protos/perfetto/trace/android/packages_list.pbzero.h"
-#include "test/gtest_and_gmock.h"
+#include "perfetto/trace/android/packages_list.pb.h"
+#include "perfetto/trace/android/packages_list.pbzero.h"
 
 namespace perfetto {
 namespace {
diff --git a/src/traced/probes/power/BUILD.gn b/src/traced/probes/power/BUILD.gn
index d3af4a3..358f6b4 100644
--- a/src/traced/probes/power/BUILD.gn
+++ b/src/traced/probes/power/BUILD.gn
@@ -19,8 +19,7 @@
   deps = [
     "..:data_source",
     "../../../../gn:default_deps",
-    "../../../../include/perfetto/ext/traced",
-    "../../../../protos/perfetto/config/power:zero",
+    "../../../../include/perfetto/traced",
     "../../../../protos/perfetto/trace/power:zero",
     "../../../android_internal:lazy_library_loader",
     "../../../base",
diff --git a/src/traced/probes/power/android_power_data_source.cc b/src/traced/probes/power/android_power_data_source.cc
index 98bf2de..9a2c087 100644
--- a/src/traced/probes/power/android_power_data_source.cc
+++ b/src/traced/probes/power/android_power_data_source.cc
@@ -19,21 +19,20 @@
 #include <vector>
 
 #include "perfetto/base/logging.h"
+#include "perfetto/base/optional.h"
+#include "perfetto/base/scoped_file.h"
 #include "perfetto/base/task_runner.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
 #include "perfetto/tracing/core/data_source_config.h"
+#include "perfetto/tracing/core/trace_packet.h"
+#include "perfetto/tracing/core/trace_writer.h"
 #include "src/android_internal/health_hal.h"
 #include "src/android_internal/lazy_library_loader.h"
 #include "src/android_internal/power_stats_hal.h"
 
-#include "protos/perfetto/config/power/android_power_config.pbzero.h"
-#include "protos/perfetto/trace/power/battery_counters.pbzero.h"
-#include "protos/perfetto/trace/power/power_rails.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/power/battery_counters.pbzero.h"
+#include "perfetto/trace/power/power_rails.pbzero.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
 
@@ -90,23 +89,21 @@
     std::unique_ptr<TraceWriter> writer)
     : ProbesDataSource(session_id, kTypeId),
       task_runner_(task_runner),
+      poll_rate_ms_(cfg.android_power_config().battery_poll_ms()),
+      rails_collection_enabled_(
+          cfg.android_power_config().collect_power_rails()),
       rail_descriptors_logged_(false),
       writer_(std::move(writer)),
       weak_factory_(this) {
-  using protos::pbzero::AndroidPowerConfig;
-  AndroidPowerConfig::Decoder pcfg(cfg.android_power_config_raw());
-  poll_rate_ms_ = pcfg.battery_poll_ms();
-  rails_collection_enabled_ = pcfg.collect_power_rails();
-
   if (poll_rate_ms_ < kMinPollRateMs) {
     PERFETTO_ELOG("Battery poll interval of %" PRIu32
                   " ms is too low. Capping to %" PRIu32 " ms",
                   poll_rate_ms_, kMinPollRateMs);
     poll_rate_ms_ = kMinPollRateMs;
   }
-  for (auto counter = pcfg.battery_counters(); counter; ++counter) {
+  for (auto counter : cfg.android_power_config().battery_counters()) {
     auto hal_id = android_internal::BatteryCounter::kUnspecified;
-    switch (*counter) {
+    switch (counter) {
       case AndroidPowerConfig::BATTERY_COUNTER_UNSPECIFIED:
         break;
       case AndroidPowerConfig::BATTERY_COUNTER_CHARGE:
diff --git a/src/traced/probes/power/android_power_data_source.h b/src/traced/probes/power/android_power_data_source.h
index c4efd39..b3b45e8 100644
--- a/src/traced/probes/power/android_power_data_source.h
+++ b/src/traced/probes/power/android_power_data_source.h
@@ -20,8 +20,8 @@
 #include <bitset>
 #include <memory>
 
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/weak_ptr.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/weak_ptr.h"
 #include "perfetto/tracing/core/data_source_config.h"
 #include "src/traced/probes/probes_data_source.h"
 
diff --git a/src/traced/probes/probes.cc b/src/traced/probes/probes.cc
index 70c5d2c..4920138 100644
--- a/src/traced/probes/probes.cc
+++ b/src/traced/probes/probes.cc
@@ -20,12 +20,12 @@
 #include <unistd.h>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/unix_task_runner.h"
-#include "perfetto/ext/traced/traced.h"
-#include "perfetto/ext/tracing/ipc/default_socket.h"
+#include "perfetto/base/unix_task_runner.h"
+#include "perfetto/traced/traced.h"
 
 #include "src/traced/probes/ftrace/ftrace_procfs.h"
 #include "src/traced/probes/probes_producer.h"
+#include "src/tracing/ipc/default_socket.h"
 
 namespace perfetto {
 
diff --git a/src/traced/probes/probes_data_source.h b/src/traced/probes/probes_data_source.h
index ef410c7..7c92ede 100644
--- a/src/traced/probes/probes_data_source.h
+++ b/src/traced/probes/probes_data_source.h
@@ -20,7 +20,7 @@
 #include <functional>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/basic_types.h"
 
 namespace perfetto {
 
diff --git a/src/traced/probes/probes_producer.cc b/src/traced/probes/probes_producer.cc
index 0c3a5de..5d28445 100644
--- a/src/traced/probes/probes_producer.cc
+++ b/src/traced/probes/probes_producer.cc
@@ -24,29 +24,28 @@
 #include <string>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/traced/traced.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/ipc/producer_ipc_client.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/base/weak_ptr.h"
+#include "perfetto/traced/traced.h"
 #include "perfetto/tracing/core/data_source_config.h"
 #include "perfetto/tracing/core/data_source_descriptor.h"
+#include "perfetto/tracing/core/ftrace_config.h"
 #include "perfetto/tracing/core/trace_config.h"
+#include "perfetto/tracing/core/trace_packet.h"
+#include "perfetto/tracing/ipc/producer_ipc_client.h"
 #include "src/traced/probes/android_log/android_log_data_source.h"
 #include "src/traced/probes/filesystem/inode_file_data_source.h"
 #include "src/traced/probes/ftrace/ftrace_data_source.h"
-#include "src/traced/probes/metatrace/metatrace_data_source.h"
 #include "src/traced/probes/packages_list/packages_list_data_source.h"
 #include "src/traced/probes/power/android_power_data_source.h"
 #include "src/traced/probes/probes_data_source.h"
 #include "src/traced/probes/ps/process_stats_data_source.h"
 #include "src/traced/probes/sys_stats/sys_stats_data_source.h"
 
-#include "protos/perfetto/config/ftrace/ftrace_config.gen.h"
-#include "protos/perfetto/trace/filesystem/inode_file_map.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_stats.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/filesystem/inode_file_map.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
+#include "perfetto/trace/ftrace/ftrace_stats.pbzero.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
 namespace {
@@ -130,13 +129,6 @@
     desc.set_name(kPackagesListSourceName);
     endpoint_->RegisterDataSource(desc);
   }
-
-  {
-    DataSourceDescriptor desc;
-    desc.set_name(MetatraceDataSource::kDataSourceName);
-    desc.set_will_notify_on_stop(true);
-    endpoint_->RegisterDataSource(desc);
-  }
 }
 
 void ProbesProducer::OnDisconnect() {
@@ -154,7 +146,7 @@
 void ProbesProducer::Restart() {
   // We lost the connection with the tracing service. At this point we need
   // to reset all the data sources. Trying to handle that manually is going to
-  // be error prone. What we do here is simply destroying the instance and
+  // be error prone. What we do here is simply desroying the instance and
   // recreating it again.
   // TODO(hjd): Add e2e test for this.
 
@@ -191,8 +183,6 @@
     data_source = CreateAndroidLogDataSource(session_id, config);
   } else if (config.name() == kPackagesListSourceName) {
     data_source = CreatePackagesListDataSource(session_id, config);
-  } else if (config.name() == MetatraceDataSource::kDataSourceName) {
-    data_source = CreateMetatraceDataSource(session_id, config);
   }
 
   if (!data_source) {
@@ -251,10 +241,8 @@
 
   PERFETTO_LOG("Ftrace setup (target_buf=%" PRIu32 ")", config.target_buffer());
   const BufferID buffer_id = static_cast<BufferID>(config.target_buffer());
-  FtraceConfig ftrace_config;
-  ftrace_config.ParseRawProto(config.ftrace_config_raw());
   std::unique_ptr<FtraceDataSource> data_source(new FtraceDataSource(
-      ftrace_->GetWeakPtr(), session_id, std::move(ftrace_config),
+      ftrace_->GetWeakPtr(), session_id, config.ftrace_config(),
       endpoint_->CreateTraceWriter(buffer_id)));
   if (!ftrace_->AddDataSource(data_source.get())) {
     PERFETTO_ELOG(
@@ -262,7 +250,7 @@
         "already in use)");
     return nullptr;
   }
-  return std::unique_ptr<ProbesDataSource>(std::move(data_source));
+  return std::move(data_source);
 }
 
 std::unique_ptr<ProbesDataSource> ProbesProducer::CreateInodeFileDataSource(
@@ -322,14 +310,6 @@
                              endpoint_->CreateTraceWriter(buffer_id), config));
 }
 
-std::unique_ptr<ProbesDataSource> ProbesProducer::CreateMetatraceDataSource(
-    TracingSessionID session_id,
-    const DataSourceConfig& config) {
-  auto buffer_id = static_cast<BufferID>(config.target_buffer());
-  return std::unique_ptr<ProbesDataSource>(new MetatraceDataSource(
-      task_runner_, session_id, endpoint_->CreateTraceWriter(buffer_id)));
-}
-
 void ProbesProducer::StopDataSource(DataSourceInstanceID id) {
   PERFETTO_LOG("Producer stop (id=%" PRIu64 ")", id);
   auto it = data_sources_.find(id);
@@ -339,14 +319,6 @@
     return;
   }
   ProbesDataSource* data_source = it->second.get();
-
-  // MetatraceDataSource special case: re-flush and ack the stop (to record the
-  // flushes of other data sources).
-  if (data_source->type_id == MetatraceDataSource::kTypeId) {
-    data_source->Flush(FlushRequestID{0}, [] {});
-    endpoint_->NotifyDataSourceStopped(id);
-  }
-
   TracingSessionID session_id = data_source->tracing_session_id;
   auto range = session_data_sources_.equal_range(session_id);
   for (auto kv = range.first; kv != range.second; kv++) {
@@ -498,7 +470,6 @@
       case SysStatsDataSource::kTypeId:
       case AndroidLogDataSource::kTypeId:
       case PackagesListDataSource::kTypeId:
-      case MetatraceDataSource::kTypeId:
         break;
       default:
         PERFETTO_DFATAL("Invalid data source.");
diff --git a/src/traced/probes/probes_producer.h b/src/traced/probes/probes_producer.h
index 1cdbd28..2184830 100644
--- a/src/traced/probes/probes_producer.h
+++ b/src/traced/probes/probes_producer.h
@@ -22,16 +22,16 @@
 #include <utility>
 
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/watchdog.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/tracing/core/producer.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
+#include "perfetto/base/watchdog.h"
+#include "perfetto/base/weak_ptr.h"
+#include "perfetto/tracing/core/producer.h"
+#include "perfetto/tracing/core/trace_writer.h"
+#include "perfetto/tracing/core/tracing_service.h"
 #include "src/traced/probes/filesystem/inode_file_data_source.h"
 #include "src/traced/probes/ftrace/ftrace_controller.h"
 #include "src/traced/probes/ftrace/ftrace_metadata.h"
 
-#include "protos/perfetto/trace/filesystem/inode_file_map.pbzero.h"
+#include "perfetto/trace/filesystem/inode_file_map.pbzero.h"
 
 namespace perfetto {
 
@@ -84,9 +84,6 @@
   std::unique_ptr<ProbesDataSource> CreatePackagesListDataSource(
       TracingSessionID session_id,
       const DataSourceConfig& config);
-  std::unique_ptr<ProbesDataSource> CreateMetatraceDataSource(
-      TracingSessionID session_id,
-      const DataSourceConfig& config);
 
  private:
   enum State {
diff --git a/src/traced/probes/ps/BUILD.gn b/src/traced/probes/ps/BUILD.gn
index 9918cc3..902d850 100644
--- a/src/traced/probes/ps/BUILD.gn
+++ b/src/traced/probes/ps/BUILD.gn
@@ -12,8 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../../gn/test.gni")
-
 source_set("ps") {
   public_deps = [
     "../../../tracing",
@@ -21,8 +19,7 @@
   deps = [
     "..:data_source",
     "../../../../gn:default_deps",
-    "../../../../include/perfetto/ext/traced",
-    "../../../../protos/perfetto/config/process_stats:zero",
+    "../../../../include/perfetto/traced",
     "../../../../protos/perfetto/trace/ps:zero",
     "../../../base",
   ]
@@ -32,14 +29,13 @@
   ]
 }
 
-perfetto_unittest_source_set("unittests") {
+source_set("unittests") {
   testonly = true
   deps = [
     ":ps",
     "../../../../gn:default_deps",
-    "../../../../gn:gtest_and_gmock",
-    "../../../../protos/perfetto/config/process_stats:zero",
-    "../../../../protos/perfetto/trace/ps:zero",
+    "../../../../gn:gtest_deps",
+    "../../../../protos/perfetto/trace:lite",
     "../../../../src/base:test_support",
     "../../../../src/tracing:test_support",
   ]
diff --git a/src/traced/probes/ps/process_stats_data_source.cc b/src/traced/probes/ps/process_stats_data_source.cc
index 6c9d2da..e994c2d 100644
--- a/src/traced/probes/ps/process_stats_data_source.cc
+++ b/src/traced/probes/ps/process_stats_data_source.cc
@@ -21,18 +21,16 @@
 #include <algorithm>
 #include <utility>
 
+#include "perfetto/base/file_utils.h"
+#include "perfetto/base/metatrace.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/string_splitter.h"
 #include "perfetto/base/task_runner.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/metatrace.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/tracing/core/data_source_config.h"
 
-#include "protos/perfetto/config/process_stats/process_stats_config.pbzero.h"
-#include "protos/perfetto/trace/ps/process_stats.pbzero.h"
-#include "protos/perfetto/trace/ps/process_tree.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/ps/process_stats.pbzero.h"
+#include "perfetto/trace/ps/process_tree.pbzero.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
 // TODO(primiano): the code in this file assumes that PIDs are never recycled
 // and that processes/threads never change names. Neither is always true.
@@ -90,22 +88,20 @@
     base::TaskRunner* task_runner,
     TracingSessionID session_id,
     std::unique_ptr<TraceWriter> writer,
-    const DataSourceConfig& ds_config)
+    const DataSourceConfig& config)
     : ProbesDataSource(session_id, kTypeId),
       task_runner_(task_runner),
       writer_(std::move(writer)),
+      record_thread_names_(config.process_stats_config().record_thread_names()),
+      dump_all_procs_on_start_(
+          config.process_stats_config().scan_all_processes_on_start()),
       weak_factory_(this) {
-  using protos::pbzero::ProcessStatsConfig;
-  ProcessStatsConfig::Decoder cfg(ds_config.process_stats_config_raw());
-  record_thread_names_ = cfg.record_thread_names();
-  dump_all_procs_on_start_ = cfg.scan_all_processes_on_start();
-  enable_on_demand_dumps_ = true;
-  for (auto quirk = cfg.quirks(); quirk; ++quirk) {
-    if (*quirk == ProcessStatsConfig::DISABLE_ON_DEMAND)
-      enable_on_demand_dumps_ = false;
-  }
-
-  poll_period_ms_ = cfg.proc_stats_poll_ms();
+  const auto& ps_config = config.process_stats_config();
+  const auto& quirks = ps_config.quirks();
+  enable_on_demand_dumps_ =
+      (std::find(quirks.begin(), quirks.end(),
+                 ProcessStatsConfig::DISABLE_ON_DEMAND) == quirks.end());
+  poll_period_ms_ = ps_config.proc_stats_poll_ms();
   if (poll_period_ms_ > 0 && poll_period_ms_ < 100) {
     PERFETTO_ILOG("proc_stats_poll_ms %" PRIu32
                   " is less than minimum of 100ms. Increasing to 100ms.",
@@ -114,7 +110,7 @@
   }
 
   if (poll_period_ms_ > 0) {
-    auto proc_stats_ttl_ms = cfg.proc_stats_cache_ttl_ms();
+    auto proc_stats_ttl_ms = ps_config.proc_stats_cache_ttl_ms();
     process_stats_cache_ttl_ticks_ =
         std::max(proc_stats_ttl_ms / poll_period_ms_, 1u);
   }
@@ -138,7 +134,7 @@
 }
 
 void ProcessStatsDataSource::WriteAllProcesses() {
-  PERFETTO_METATRACE_SCOPED(TAG_PROC_POLLERS, PS_WRITE_ALL_PROCESSES);
+  PERFETTO_METATRACE("WriteAllProcesses", 0);
   PERFETTO_DCHECK(!cur_ps_tree_);
 
   CacheProcFsScanStartTimestamp();
@@ -171,23 +167,20 @@
 }
 
 void ProcessStatsDataSource::OnPids(const std::vector<int32_t>& pids) {
-  PERFETTO_METATRACE_SCOPED(TAG_PROC_POLLERS, PS_ON_PIDS);
+  PERFETTO_METATRACE("OnPids", 0);
   if (!enable_on_demand_dumps_)
     return;
   PERFETTO_DCHECK(!cur_ps_tree_);
-  int pids_scanned = 0;
   for (int32_t pid : pids) {
     if (seen_pids_.count(pid) || pid == 0)
       continue;
     WriteProcessOrThread(pid);
-    pids_scanned++;
   }
   FinalizeCurPacket();
-  PERFETTO_METATRACE_COUNTER(TAG_PROC_POLLERS, PS_PIDS_SCANNED, pids_scanned);
 }
 
 void ProcessStatsDataSource::OnRenamePids(const std::vector<int32_t>& pids) {
-  PERFETTO_METATRACE_SCOPED(TAG_PROC_POLLERS, PS_ON_RENAME_PIDS);
+  PERFETTO_METATRACE("OnRenamePids", 0);
   if (!enable_on_demand_dumps_)
     return;
   PERFETTO_DCHECK(!cur_ps_tree_);
@@ -235,8 +228,6 @@
   auto* proc = GetOrCreatePsTree()->add_processes();
   proc->set_pid(pid);
   proc->set_ppid(ToInt(ReadProcStatusEntry(proc_status, "PPid:")));
-  // Uid will have multiple entries, only return first (real uid).
-  proc->set_uid(ToInt(ReadProcStatusEntry(proc_status, "Uid:")));
 
   std::string cmdline = ReadProcPidFile(pid, "cmdline");
   if (!cmdline.empty()) {
@@ -372,7 +363,7 @@
   // proc files over and over. Same for non-whitelist processes (see above).
 
   CacheProcFsScanStartTimestamp();
-  PERFETTO_METATRACE_SCOPED(TAG_PROC_POLLERS, PS_WRITE_ALL_PROCESS_STATS);
+  PERFETTO_METATRACE("WriteAllProcessStats", 0);
   base::ScopedDir proc_dir = OpenProcDir();
   if (!proc_dir)
     return;
diff --git a/src/traced/probes/ps/process_stats_data_source.h b/src/traced/probes/ps/process_stats_data_source.h
index b2fa51c..c0288f1 100644
--- a/src/traced/probes/ps/process_stats_data_source.h
+++ b/src/traced/probes/ps/process_stats_data_source.h
@@ -23,10 +23,11 @@
 #include <unordered_map>
 #include <vector>
 
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/weak_ptr.h"
+#include "perfetto/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/data_source_config.h"
+#include "perfetto/tracing/core/trace_writer.h"
 #include "src/traced/probes/probes_data_source.h"
 
 namespace perfetto {
@@ -43,8 +44,6 @@
 }  // namespace pbzero
 }  // namespace protos
 
-class DataSourceConfig;
-
 class ProcessStatsDataSource : public ProbesDataSource {
  public:
   static constexpr int kTypeId = 3;
diff --git a/src/traced/probes/ps/process_stats_data_source_unittest.cc b/src/traced/probes/ps/process_stats_data_source_unittest.cc
index c7cbd28..0ccd703 100644
--- a/src/traced/probes/ps/process_stats_data_source_unittest.cc
+++ b/src/traced/probes/ps/process_stats_data_source_unittest.cc
@@ -18,17 +18,14 @@
 
 #include <dirent.h>
 
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "perfetto/tracing/core/data_source_config.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/temp_file.h"
+#include "perfetto/trace/trace_packet.pb.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/tracing/core/trace_writer_for_testing.h"
-#include "test/gtest_and_gmock.h"
 
-#include "protos/perfetto/config/process_stats/process_stats_config.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-using ::perfetto::protos::pbzero::ProcessStatsConfig;
 using ::testing::_;
 using ::testing::ElementsAreArray;
 using ::testing::Invoke;
@@ -72,21 +69,19 @@
 TEST_F(ProcessStatsDataSourceTest, WriteOnceProcess) {
   auto data_source = GetProcessStatsDataSource(DataSourceConfig());
   EXPECT_CALL(*data_source, ReadProcPidFile(42, "status"))
-      .WillOnce(Return(
-          "Name: foo\nTgid:\t42\nPid:   42\nPPid:  17\nUid:  43 44 45 56\n"));
+      .WillOnce(Return("Name: foo\nTgid:\t42\nPid:   42\nPPid:  17\n"));
   EXPECT_CALL(*data_source, ReadProcPidFile(42, "cmdline"))
       .WillOnce(Return(std::string("foo\0bar\0baz\0", 12)));
 
   data_source->OnPids({42});
 
   std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets();
-  ASSERT_EQ(trace.size(), 1u);
+  ASSERT_EQ(trace.size(), 1);
   auto ps_tree = trace[0].process_tree();
   ASSERT_EQ(ps_tree.processes_size(), 1);
   auto first_process = ps_tree.processes(0);
   ASSERT_EQ(first_process.pid(), 42);
   ASSERT_EQ(first_process.ppid(), 17);
-  ASSERT_EQ(first_process.uid(), 43);
   ASSERT_THAT(first_process.cmdline(), ElementsAreArray({"foo", "bar", "baz"}));
 }
 
@@ -105,11 +100,9 @@
     };
   };
 
-  DataSourceConfig ds_config;
-  protozero::HeapBuffered<ProcessStatsConfig> cfg;
-  cfg->set_record_thread_names(true);
-  ds_config.set_process_stats_config_raw(cfg.SerializeAsString());
-  auto data_source = GetProcessStatsDataSource(ds_config);
+  DataSourceConfig config;
+  config.mutable_process_stats_config()->set_record_thread_names(true);
+  auto data_source = GetProcessStatsDataSource(config);
   for (int p : {10, 11, 12, 20, 21, 22, 30, 31, 32}) {
     EXPECT_CALL(*data_source, ReadProcPidFile(p, "status"))
         .WillOnce(Invoke([](int32_t pid, const std::string&) {
@@ -132,7 +125,7 @@
 
   // check written contents
   std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets();
-  EXPECT_EQ(trace.size(), 3u);
+  EXPECT_EQ(trace.size(), 3);
 
   // first packet - two unique processes, four threads
   auto ps_tree = trace[0].process_tree();
@@ -169,7 +162,7 @@
 
   {
     std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets();
-    ASSERT_EQ(trace.size(), 1u);
+    ASSERT_EQ(trace.size(), 1);
     auto packet = trace[0];
     // First packet in the trace has no previous state, so the clear marker is
     // emitted.
@@ -192,7 +185,7 @@
 
   {
     std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets();
-    ASSERT_EQ(trace.size(), 1u);
+    ASSERT_EQ(trace.size(), 1);
   }
 
   // Invalidate incremental state, and look up the same pid again, which should
@@ -209,7 +202,7 @@
   {
     // Second packet with new proc information.
     std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets();
-    ASSERT_EQ(trace.size(), 2u);
+    ASSERT_EQ(trace.size(), 2);
     auto packet = trace[1];
     ASSERT_TRUE(packet.incremental_state_cleared());
 
@@ -265,7 +258,7 @@
 
   // check written contents
   std::vector<protos::TracePacket> trace = writer_raw_->GetAllTracePackets();
-  EXPECT_EQ(trace.size(), 3u);
+  EXPECT_EQ(trace.size(), 3);
 
   // first packet - two unique processes
   auto ps_tree = trace[0].process_tree();
@@ -288,12 +281,11 @@
 }
 
 TEST_F(ProcessStatsDataSourceTest, ProcessStats) {
-  DataSourceConfig ds_config;
-  protozero::HeapBuffered<ProcessStatsConfig> cfg;
-  cfg->set_proc_stats_poll_ms(1);
-  cfg->add_quirks(ProcessStatsConfig::DISABLE_ON_DEMAND);
-  ds_config.set_process_stats_config_raw(cfg.SerializeAsString());
-  auto data_source = GetProcessStatsDataSource(ds_config);
+  DataSourceConfig cfg;
+  cfg.mutable_process_stats_config()->set_proc_stats_poll_ms(1);
+  *(cfg.mutable_process_stats_config()->add_quirks()) =
+      perfetto::ProcessStatsConfig::DISABLE_ON_DEMAND;
+  auto data_source = GetProcessStatsDataSource(cfg);
 
   // Populate a fake /proc/ directory.
   auto fake_proc = base::TempDir::Create();
@@ -351,12 +343,9 @@
   iter = 0;
   for (const auto& proc_counters : processes) {
     int32_t pid = proc_counters.pid();
-    ASSERT_EQ(static_cast<int>(proc_counters.vm_size_kb()),
-              pid * 100 + iter * 10 + 1);
-    ASSERT_EQ(static_cast<int>(proc_counters.vm_rss_kb()),
-              pid * 100 + iter * 10 + 2);
-    ASSERT_EQ(static_cast<int>(proc_counters.oom_score_adj()),
-              pid * 100 + iter * 10 + 3);
+    ASSERT_EQ(proc_counters.vm_size_kb(), pid * 100 + iter * 10 + 1);
+    ASSERT_EQ(proc_counters.vm_rss_kb(), pid * 100 + iter * 10 + 2);
+    ASSERT_EQ(proc_counters.oom_score_adj(), pid * 100 + iter * 10 + 3);
     if (pid == kPids[base::ArraySize(kPids) - 1])
       iter++;
   }
@@ -367,13 +356,12 @@
 }
 
 TEST_F(ProcessStatsDataSourceTest, CacheProcessStats) {
-  DataSourceConfig ds_config;
-  protozero::HeapBuffered<ProcessStatsConfig> cfg;
-  cfg->set_proc_stats_poll_ms(105);
-  cfg->set_proc_stats_cache_ttl_ms(220);
-  cfg->add_quirks(ProcessStatsConfig::DISABLE_ON_DEMAND);
-  ds_config.set_process_stats_config_raw(cfg.SerializeAsString());
-  auto data_source = GetProcessStatsDataSource(ds_config);
+  DataSourceConfig cfg;
+  cfg.mutable_process_stats_config()->set_proc_stats_poll_ms(105);
+  cfg.mutable_process_stats_config()->set_proc_stats_cache_ttl_ms(220);
+  *(cfg.mutable_process_stats_config()->add_quirks()) =
+      perfetto::ProcessStatsConfig::DISABLE_ON_DEMAND;
+  auto data_source = GetProcessStatsDataSource(cfg);
 
   // Populate a fake /proc/ directory.
   auto fake_proc = base::TempDir::Create();
@@ -422,12 +410,12 @@
   // a) emissions happen at 0ms, 105ms, 210ms, 315ms
   // b) clear events happen at 220ms, 440ms...
   // Therefore, we should see the emissions at 0ms and 315ms.
-  ASSERT_EQ(processes.size(), 2u);
+  ASSERT_EQ(processes.size(), 2);
   for (const auto& proc_counters : processes) {
     ASSERT_EQ(proc_counters.pid(), kPid);
-    ASSERT_EQ(static_cast<int>(proc_counters.vm_size_kb()), kPid * 100 + 1);
-    ASSERT_EQ(static_cast<int>(proc_counters.vm_rss_kb()), kPid * 100 + 2);
-    ASSERT_EQ(static_cast<int>(proc_counters.oom_score_adj()), kPid * 100);
+    ASSERT_EQ(proc_counters.vm_size_kb(), kPid * 100 + 1);
+    ASSERT_EQ(proc_counters.vm_rss_kb(), kPid * 100 + 2);
+    ASSERT_EQ(proc_counters.oom_score_adj(), kPid * 100);
   }
 
   // Cleanup |fake_proc|. TempDir checks that the directory is empty.
diff --git a/src/traced/probes/sys_stats/BUILD.gn b/src/traced/probes/sys_stats/BUILD.gn
index c7fa58b..16ae4e0 100644
--- a/src/traced/probes/sys_stats/BUILD.gn
+++ b/src/traced/probes/sys_stats/BUILD.gn
@@ -12,8 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../../gn/test.gni")
-
 source_set("sys_stats") {
   public_deps = [
     "../../../tracing",
@@ -21,10 +19,9 @@
   deps = [
     "..:data_source",
     "../../../../gn:default_deps",
-    "../../../../include/perfetto/ext/traced",
-    "../../../../include/perfetto/ext/traced:sys_stats_counters",
-    "../../../../protos/perfetto/common:zero",
-    "../../../../protos/perfetto/config/sys_stats:zero",
+    "../../../../include/perfetto/traced",
+    "../../../../include/perfetto/traced:sys_stats_counters",
+    "../../../../protos/perfetto/config:lite",
     "../../../../protos/perfetto/trace/sys_stats:zero",
     "../../../base",
   ]
@@ -34,16 +31,14 @@
   ]
 }
 
-perfetto_unittest_source_set("unittests") {
+source_set("unittests") {
   testonly = true
   deps = [
     ":sys_stats",
     "../../../../gn:default_deps",
-    "../../../../gn:gtest_and_gmock",
-    "../../../../protos/perfetto/common:zero",
-    "../../../../protos/perfetto/config:zero",
-    "../../../../protos/perfetto/config/sys_stats:zero",
-    "../../../../protos/perfetto/trace/sys_stats:zero",
+    "../../../../gn:gtest_deps",
+    "../../../../protos/perfetto/config:lite",
+    "../../../../protos/perfetto/trace:lite",
     "../../../../src/base:test_support",
     "../../../../src/tracing:test_support",
   ]
diff --git a/src/traced/probes/sys_stats/sys_stats_data_source.cc b/src/traced/probes/sys_stats/sys_stats_data_source.cc
index 132e279..217b196 100644
--- a/src/traced/probes/sys_stats/sys_stats_data_source.cc
+++ b/src/traced/probes/sys_stats/sys_stats_data_source.cc
@@ -21,28 +21,26 @@
 
 #include <algorithm>
 #include <array>
-#include <bitset>
 #include <limits>
 #include <utility>
 
+#include "perfetto/base/file_utils.h"
+#include "perfetto/base/metatrace.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/string_splitter.h"
 #include "perfetto/base/task_runner.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/metatrace.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/traced/sys_stats_counters.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/traced/sys_stats_counters.h"
+#include "perfetto/tracing/core/sys_stats_config.h"
 
-#include "protos/perfetto/common/sys_stats_counters.pbzero.h"
-#include "protos/perfetto/config/sys_stats/sys_stats_config.pbzero.h"
-#include "protos/perfetto/trace/sys_stats/sys_stats.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/common/sys_stats_counters.pb.h"
+#include "perfetto/config/sys_stats/sys_stats_config.pb.h"
+#include "perfetto/trace/sys_stats/sys_stats.pbzero.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
 
-using protos::pbzero::SysStatsConfig;
-
 namespace {
 constexpr size_t kReadBufSize = 1024 * 16;
 
@@ -77,6 +75,8 @@
       task_runner_(task_runner),
       writer_(std::move(writer)),
       weak_factory_(this) {
+  const auto& config = ds_config.sys_stats_config();
+
   ns_per_user_hz_ = 1000000000ull / static_cast<uint64_t>(sysconf(_SC_CLK_TCK));
 
   open_fn = open_fn ? open_fn : OpenReadOnly;
@@ -89,59 +89,33 @@
   // Build a lookup map that allows to quickly translate strings like "MemTotal"
   // into the corresponding enum value, only for the counters enabled in the
   // config.
-
-  using protos::pbzero::SysStatsConfig;
-  SysStatsConfig::Decoder cfg(ds_config.sys_stats_config_raw());
-
-  constexpr size_t kMaxMeminfoEnum = protos::pbzero::MeminfoCounters_MAX;
-  std::bitset<kMaxMeminfoEnum + 1> meminfo_counters_enabled{};
-  if (!cfg.has_meminfo_counters())
-    meminfo_counters_enabled.set();
-  for (auto it = cfg.meminfo_counters(); it; ++it) {
-    uint32_t counter = static_cast<uint32_t>(*it);
-    if (counter > 0 && counter <= kMaxMeminfoEnum) {
-      meminfo_counters_enabled.set(counter);
-    } else {
-      PERFETTO_DFATAL("Meminfo counter out of bounds %u", counter);
+  for (const auto& counter_id : config.meminfo_counters()) {
+    for (size_t i = 0; i < base::ArraySize(kMeminfoKeys); i++) {
+      const auto& k = kMeminfoKeys[i];
+      if (static_cast<int>(k.id) == static_cast<int>(counter_id))
+        meminfo_counters_.emplace(k.str, k.id);
     }
   }
-  for (size_t i = 0; i < base::ArraySize(kMeminfoKeys); i++) {
-    const auto& k = kMeminfoKeys[i];
-    if (meminfo_counters_enabled[static_cast<size_t>(k.id)])
-      meminfo_counters_.emplace(k.str, k.id);
-  }
 
-  constexpr size_t kMaxVmstatEnum = protos::pbzero::VmstatCounters_MAX;
-  std::bitset<kMaxVmstatEnum + 1> vmstat_counters_enabled{};
-  if (!cfg.has_vmstat_counters())
-    vmstat_counters_enabled.set();
-  for (auto it = cfg.vmstat_counters(); it; ++it) {
-    uint32_t counter = static_cast<uint32_t>(*it);
-    if (counter > 0 && counter <= kMaxVmstatEnum) {
-      vmstat_counters_enabled.set(counter);
-    } else {
-      PERFETTO_DFATAL("Vmstat counter out of bounds %u", counter);
+  for (const auto& counter_id : config.vmstat_counters()) {
+    for (size_t i = 0; i < base::ArraySize(kVmstatKeys); i++) {
+      const auto& k = kVmstatKeys[i];
+      if (static_cast<int>(k.id) == static_cast<int>(counter_id))
+        vmstat_counters_.emplace(k.str, k.id);
     }
   }
-  for (size_t i = 0; i < base::ArraySize(kVmstatKeys); i++) {
-    const auto& k = kVmstatKeys[i];
-    if (vmstat_counters_enabled[static_cast<size_t>(k.id)])
-      vmstat_counters_.emplace(k.str, k.id);
-  }
 
-  if (!cfg.has_stat_counters())
-    stat_enabled_fields_ = ~0u;
-  for (auto counter = cfg.stat_counters(); counter; ++counter) {
-    stat_enabled_fields_ |= 1ul << static_cast<uint32_t>(*counter);
+  for (const auto& counter_id : config.stat_counters()) {
+    stat_enabled_fields_ |= 1 << counter_id;
   }
 
   std::array<uint32_t, 3> periods_ms{};
   std::array<uint32_t, 3> ticks{};
   static_assert(periods_ms.size() == ticks.size(), "must have same size");
 
-  periods_ms[0] = ClampTo10Ms(cfg.meminfo_period_ms(), "meminfo_period_ms");
-  periods_ms[1] = ClampTo10Ms(cfg.vmstat_period_ms(), "vmstat_period_ms");
-  periods_ms[2] = ClampTo10Ms(cfg.stat_period_ms(), "stat_period_ms");
+  periods_ms[0] = ClampTo10Ms(config.meminfo_period_ms(), "meminfo_period_ms");
+  periods_ms[1] = ClampTo10Ms(config.vmstat_period_ms(), "vmstat_period_ms");
+  periods_ms[2] = ClampTo10Ms(config.stat_period_ms(), "stat_period_ms");
 
   tick_period_ms_ = 0;
   for (uint32_t ms : periods_ms) {
@@ -185,7 +159,7 @@
 SysStatsDataSource::~SysStatsDataSource() = default;
 
 void SysStatsDataSource::ReadSysStats() {
-  PERFETTO_METATRACE_SCOPED(TAG_PROC_POLLERS, READ_SYS_STATS);
+  PERFETTO_METATRACE("ReadSysStats", 0);
   auto packet = writer_->NewTracePacket();
 
   packet->set_timestamp(static_cast<uint64_t>(base::GetBootTimeNs().count()));
@@ -288,7 +262,7 @@
         auto v = static_cast<uint64_t>(strtoll(words.cur_token(), nullptr, 10));
         if (i == 0) {
           sys_stats->set_num_irq_total(v);
-        } else if (v > 0) {
+        } else {
           auto* irq_stat = sys_stats->add_num_irq();
           irq_stat->set_irq(static_cast<int32_t>(i - 1));
           irq_stat->set_count(v);
diff --git a/src/traced/probes/sys_stats/sys_stats_data_source.h b/src/traced/probes/sys_stats/sys_stats_data_source.h
index ad33071..0fa085c 100644
--- a/src/traced/probes/sys_stats/sys_stats_data_source.h
+++ b/src/traced/probes/sys_stats/sys_stats_data_source.h
@@ -23,12 +23,12 @@
 #include <memory>
 #include <string>
 
-#include "perfetto/ext/base/paged_memory.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
+#include "perfetto/base/paged_memory.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/weak_ptr.h"
+#include "perfetto/tracing/core/basic_types.h"
 #include "perfetto/tracing/core/data_source_config.h"
+#include "perfetto/tracing/core/trace_writer.h"
 #include "src/traced/probes/probes_data_source.h"
 
 namespace perfetto {
diff --git a/src/traced/probes/sys_stats/sys_stats_data_source_unittest.cc b/src/traced/probes/sys_stats/sys_stats_data_source_unittest.cc
index c760f41..763d8d1 100644
--- a/src/traced/probes/sys_stats/sys_stats_data_source_unittest.cc
+++ b/src/traced/probes/sys_stats/sys_stats_data_source_unittest.cc
@@ -16,17 +16,16 @@
 
 #include <unistd.h>
 
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/temp_file.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/traced/probes/sys_stats/sys_stats_data_source.h"
 #include "src/tracing/core/trace_writer_for_testing.h"
-#include "test/gtest_and_gmock.h"
 
-#include "protos/perfetto/common/sys_stats_counters.pbzero.h"
-#include "protos/perfetto/config/data_source_config.pbzero.h"
-#include "protos/perfetto/config/sys_stats/sys_stats_config.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/config/sys_stats/sys_stats_config.pb.h"
+#include "perfetto/trace/trace_packet.pb.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
 using ::testing::_;
 using ::testing::Invoke;
@@ -233,23 +232,25 @@
 };
 
 TEST_F(SysStatsDataSourceTest, Meminfo) {
-  using C = protos::pbzero::MeminfoCounters;
-  DataSourceConfig config;
-  protozero::HeapBuffered<protos::pbzero::SysStatsConfig> sys_cfg;
-  sys_cfg->set_meminfo_period_ms(10);
-  sys_cfg->add_meminfo_counters(C::MEMINFO_MEM_TOTAL);
-  sys_cfg->add_meminfo_counters(C::MEMINFO_MEM_FREE);
-  sys_cfg->add_meminfo_counters(C::MEMINFO_ACTIVE_ANON);
-  sys_cfg->add_meminfo_counters(C::MEMINFO_INACTIVE_FILE);
-  sys_cfg->add_meminfo_counters(C::MEMINFO_CMA_FREE);
-  config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
-  auto data_source = GetSysStatsDataSource(config);
+  using C = protos::MeminfoCounters;
+  protos::DataSourceConfig config;
+  config.mutable_sys_stats_config()->set_meminfo_period_ms(1);
+  config.mutable_sys_stats_config()->add_meminfo_counters(C::MEMINFO_MEM_TOTAL);
+  config.mutable_sys_stats_config()->add_meminfo_counters(C::MEMINFO_MEM_FREE);
+  config.mutable_sys_stats_config()->add_meminfo_counters(
+      C::MEMINFO_ACTIVE_ANON);
+  config.mutable_sys_stats_config()->add_meminfo_counters(
+      C::MEMINFO_INACTIVE_FILE);
+  config.mutable_sys_stats_config()->add_meminfo_counters(C::MEMINFO_CMA_FREE);
+  DataSourceConfig config_obj;
+  config_obj.FromProto(config);
+  auto data_source = GetSysStatsDataSource(config_obj);
 
   WaitTick(data_source.get());
 
-  protos::TracePacket packet = writer_raw_->GetOnlyTracePacket();
-  ASSERT_TRUE(packet.has_sys_stats());
-  const auto& sys_stats = packet.sys_stats();
+  std::unique_ptr<protos::TracePacket> packet = writer_raw_->ParseProto();
+  ASSERT_TRUE(packet->has_sys_stats());
+  const auto& sys_stats = packet->sys_stats();
   EXPECT_EQ(sys_stats.vmstat_size(), 0);
   EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
 
@@ -266,39 +267,24 @@
                                    KV{C::MEMINFO_CMA_FREE, 60}));
 }
 
-TEST_F(SysStatsDataSourceTest, MeminfoAll) {
-  DataSourceConfig config;
-  protozero::HeapBuffered<protos::pbzero::SysStatsConfig> sys_cfg;
-  sys_cfg->set_meminfo_period_ms(10);
-  config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
-  auto data_source = GetSysStatsDataSource(config);
-
-  WaitTick(data_source.get());
-
-  protos::TracePacket packet = writer_raw_->GetOnlyTracePacket();
-  ASSERT_TRUE(packet.has_sys_stats());
-  const auto& sys_stats = packet.sys_stats();
-  EXPECT_EQ(sys_stats.vmstat_size(), 0);
-  EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
-  EXPECT_GE(sys_stats.meminfo_size(), 10);
-}
-
 TEST_F(SysStatsDataSourceTest, Vmstat) {
-  using C = protos::pbzero::VmstatCounters;
-  DataSourceConfig config;
-  protozero::HeapBuffered<protos::pbzero::SysStatsConfig> sys_cfg;
-  sys_cfg->set_vmstat_period_ms(10);
-  sys_cfg->add_vmstat_counters(C::VMSTAT_NR_FREE_PAGES);
-  sys_cfg->add_vmstat_counters(C::VMSTAT_PGACTIVATE);
-  sys_cfg->add_vmstat_counters(C::VMSTAT_PGMIGRATE_FAIL);
-  config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
-  auto data_source = GetSysStatsDataSource(config);
+  using C = protos::VmstatCounters;
+  protos::DataSourceConfig config;
+  config.mutable_sys_stats_config()->set_vmstat_period_ms(1);
+  config.mutable_sys_stats_config()->add_vmstat_counters(
+      C::VMSTAT_NR_FREE_PAGES);
+  config.mutable_sys_stats_config()->add_vmstat_counters(C::VMSTAT_PGACTIVATE);
+  config.mutable_sys_stats_config()->add_vmstat_counters(
+      C::VMSTAT_PGMIGRATE_FAIL);
+  DataSourceConfig config_obj;
+  config_obj.FromProto(config);
+  auto data_source = GetSysStatsDataSource(config_obj);
 
   WaitTick(data_source.get());
 
-  protos::TracePacket packet = writer_raw_->GetOnlyTracePacket();
-  ASSERT_TRUE(packet.has_sys_stats());
-  const auto& sys_stats = packet.sys_stats();
+  std::unique_ptr<protos::TracePacket> packet = writer_raw_->ParseProto();
+  ASSERT_TRUE(packet->has_sys_stats());
+  const auto& sys_stats = packet->sys_stats();
   EXPECT_EQ(sys_stats.meminfo_size(), 0);
   EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
 
@@ -312,35 +298,24 @@
                                         KV{C::VMSTAT_PGMIGRATE_FAIL, 3439}));
 }
 
-TEST_F(SysStatsDataSourceTest, VmstatAll) {
-  DataSourceConfig config;
-  protozero::HeapBuffered<protos::pbzero::SysStatsConfig> sys_cfg;
-  sys_cfg->set_vmstat_period_ms(10);
-  config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
-  auto data_source = GetSysStatsDataSource(config);
-
-  WaitTick(data_source.get());
-
-  protos::TracePacket packet = writer_raw_->GetOnlyTracePacket();
-  ASSERT_TRUE(packet.has_sys_stats());
-  const auto& sys_stats = packet.sys_stats();
-  EXPECT_EQ(sys_stats.meminfo_size(), 0);
-  EXPECT_EQ(sys_stats.cpu_stat_size(), 0);
-  EXPECT_GE(sys_stats.vmstat_size(), 10);
-}
-
 TEST_F(SysStatsDataSourceTest, StatAll) {
-  DataSourceConfig config;
-  protozero::HeapBuffered<protos::pbzero::SysStatsConfig> sys_cfg;
-  sys_cfg->set_stat_period_ms(10);
-  config.set_sys_stats_config_raw(sys_cfg.SerializeAsString());
-  auto data_source = GetSysStatsDataSource(config);
+  using C = protos::SysStatsConfig;
+  protos::DataSourceConfig config;
+  config.mutable_sys_stats_config()->set_stat_period_ms(1);
+  config.mutable_sys_stats_config()->add_stat_counters(C::STAT_CPU_TIMES);
+  config.mutable_sys_stats_config()->add_stat_counters(C::STAT_IRQ_COUNTS);
+  config.mutable_sys_stats_config()->add_stat_counters(C::STAT_SOFTIRQ_COUNTS);
+  config.mutable_sys_stats_config()->add_stat_counters(C::STAT_FORK_COUNT);
+  DataSourceConfig config_obj;
+  config_obj.FromProto(config);
+  auto data_source = GetSysStatsDataSource(config_obj);
 
   WaitTick(data_source.get());
 
-  protos::TracePacket packet = writer_raw_->GetOnlyTracePacket();
-  ASSERT_TRUE(packet.has_sys_stats());
-  const auto& sys_stats = packet.sys_stats();
+  std::unique_ptr<protos::TracePacket> packet = writer_raw_->ParseProto();
+  ASSERT_TRUE(packet);
+  ASSERT_TRUE(packet->has_sys_stats());
+  const auto& sys_stats = packet->sys_stats();
   EXPECT_EQ(sys_stats.meminfo_size(), 0);
   EXPECT_EQ(sys_stats.vmstat_size(), 0);
 
@@ -352,28 +327,26 @@
   EXPECT_EQ(sys_stats.cpu_stat(7).system_mode_ns(), 139874 * 10000000ull);
   EXPECT_EQ(sys_stats.cpu_stat(7).softirq_ns(), 13407 * 10000000ull);
 
-  EXPECT_EQ(sys_stats.num_forks(), 243320u);
+  EXPECT_EQ(sys_stats.num_forks(), 243320);
 
-  EXPECT_EQ(sys_stats.num_irq_total(), 238128517u);
-  ASSERT_EQ(sys_stats.num_irq_size(), 102);
-  EXPECT_EQ(sys_stats.num_irq(0).count(), 63500984u);
-  EXPECT_EQ(sys_stats.num_irq(0).irq(), 3);
-  EXPECT_EQ(sys_stats.num_irq(1).count(), 6253792u);
-  EXPECT_EQ(sys_stats.num_irq(1).irq(), 5);
-  EXPECT_EQ(sys_stats.num_irq(101).count(), 680u);
+  EXPECT_EQ(sys_stats.num_irq_total(), 238128517);
+  ASSERT_EQ(sys_stats.num_irq_size(), 793);
+  EXPECT_EQ(sys_stats.num_irq(0).count(), 0);
+  EXPECT_EQ(sys_stats.num_irq(3).count(), 63500984);
+  EXPECT_EQ(sys_stats.num_irq(790).count(), 680);
 
-  EXPECT_EQ(sys_stats.num_softirq_total(), 84611084u);
+  EXPECT_EQ(sys_stats.num_softirq_total(), 84611084);
   ASSERT_EQ(sys_stats.num_softirq_size(), 10);
-  EXPECT_EQ(sys_stats.num_softirq(0).count(), 10220177u);
-  EXPECT_EQ(sys_stats.num_softirq(9).count(), 16443195u);
+  EXPECT_EQ(sys_stats.num_softirq(0).count(), 10220177);
+  EXPECT_EQ(sys_stats.num_softirq(9).count(), 16443195);
 
-  EXPECT_EQ(sys_stats.num_softirq_total(), 84611084u);
+  EXPECT_EQ(sys_stats.num_softirq_total(), 84611084);
 }
 
 TEST_F(SysStatsDataSourceTest, StatForksOnly) {
   using C = protos::SysStatsConfig;
   protos::DataSourceConfig config;
-  config.mutable_sys_stats_config()->set_stat_period_ms(10);
+  config.mutable_sys_stats_config()->set_stat_period_ms(1);
   config.mutable_sys_stats_config()->add_stat_counters(C::STAT_FORK_COUNT);
   DataSourceConfig config_obj;
   config_obj.FromProto(config);
@@ -381,16 +354,16 @@
 
   WaitTick(data_source.get());
 
-  protos::TracePacket packet = writer_raw_->GetOnlyTracePacket();
-  ASSERT_TRUE(packet.has_sys_stats());
-  const auto& sys_stats = packet.sys_stats();
+  std::unique_ptr<protos::TracePacket> packet = writer_raw_->ParseProto();
+  ASSERT_TRUE(packet->has_sys_stats());
+  const auto& sys_stats = packet->sys_stats();
   EXPECT_EQ(sys_stats.meminfo_size(), 0);
   EXPECT_EQ(sys_stats.vmstat_size(), 0);
   ASSERT_EQ(sys_stats.cpu_stat_size(), 0);
-  EXPECT_EQ(sys_stats.num_forks(), 243320u);
-  EXPECT_EQ(sys_stats.num_irq_total(), 0u);
+  EXPECT_EQ(sys_stats.num_forks(), 243320);
+  EXPECT_EQ(sys_stats.num_irq_total(), 0);
   ASSERT_EQ(sys_stats.num_irq_size(), 0);
-  EXPECT_EQ(sys_stats.num_softirq_total(), 0u);
+  EXPECT_EQ(sys_stats.num_softirq_total(), 0);
   ASSERT_EQ(sys_stats.num_softirq_size(), 0);
 }
 
diff --git a/src/traced/service/BUILD.gn b/src/traced/service/BUILD.gn
index d193ab4..f351f0e 100644
--- a/src/traced/service/BUILD.gn
+++ b/src/traced/service/BUILD.gn
@@ -12,31 +12,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../../gn/test.gni")
-
-# The unprivileged trace daemon that listens for Producer and Consumer
-# connections, handles the coordination of the tracing sessions and owns the
-# log buffers.
-executable("traced") {
-  deps = [
-    # Both traced and traced_probes depend on "libprefetto" instead of directly
-    # on lib. This is to reduce binary size on android builds. All the code is
-    # built into libperfetto and the executables are just tiny shells that call
-    # into the xxx_main() defined in the library.
-    "../../../:libperfetto",
-    "../../../gn:default_deps",
-    "../../../include/perfetto/ext/traced",
-  ]
-  sources = [
-    "main.cc",
-  ]
-}
-
-# Contains all the implementation but not the main() entry point. This target
-# is shared both by the executable and tests.
 source_set("service") {
   public_deps = [
-    "../../../include/perfetto/ext/traced",
+    "../../../include/perfetto/traced",
   ]
   deps = [
     "../../../gn:default_deps",
@@ -45,23 +23,23 @@
     "../../tracing:ipc",
   ]
   sources = [
-    "builtin_producer.cc",
-    "builtin_producer.h",
+    "lazy_producer.cc",
+    "lazy_producer.h",
     "service.cc",
   ]
 }
 
-perfetto_unittest_source_set("unittests") {
+source_set("unittests") {
   testonly = true
   deps = [
     ":service",
     "../../../gn:default_deps",
-    "../../../gn:gtest_and_gmock",
+    "../../../gn:gtest_deps",
     "../../base",
     "../../base:test_support",
     "../../tracing",
   ]
   sources = [
-    "builtin_producer_unittest.cc",
+    "lazy_producer_unittest.cc",
   ]
 }
diff --git a/src/traced/service/builtin_producer.cc b/src/traced/service/builtin_producer.cc
deleted file mode 100644
index 16df2e1..0000000
--- a/src/traced/service/builtin_producer.cc
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/traced/service/builtin_producer.h"
-
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/metatrace.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
-#include "perfetto/tracing/core/data_source_config.h"
-#include "perfetto/tracing/core/data_source_descriptor.h"
-#include "src/tracing/core/metatrace_writer.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-#include <sys/system_properties.h>
-#endif
-
-namespace perfetto {
-
-namespace {
-
-constexpr char kHeapprofdDataSourceName[] = "android.heapprofd";
-constexpr char kJavaHprofDataSourceName[] = "android.java_hprof";
-constexpr char kLazyHeapprofdPropertyName[] = "traced.lazy.heapprofd";
-
-}  // namespace
-
-BuiltinProducer::BuiltinProducer(base::TaskRunner* task_runner,
-                                 uint32_t lazy_stop_delay_ms)
-    : task_runner_(task_runner), weak_factory_(this) {
-  lazy_heapprofd_.stop_delay_ms = lazy_stop_delay_ms;
-}
-
-BuiltinProducer::~BuiltinProducer() {
-  if (!lazy_heapprofd_.instance_ids.empty())
-    SetAndroidProperty(kLazyHeapprofdPropertyName, "0");
-}
-
-void BuiltinProducer::ConnectInProcess(TracingService* svc) {
-  endpoint_ = svc->ConnectProducer(this, geteuid(), "traced",
-                                   /*shm_hint_kb*/ 16, /*in_process*/ true);
-}
-
-void BuiltinProducer::OnConnect() {
-  DataSourceDescriptor metatrace_dsd;
-  metatrace_dsd.set_name(MetatraceWriter::kDataSourceName);
-  metatrace_dsd.set_will_notify_on_stop(true);
-  endpoint_->RegisterDataSource(metatrace_dsd);
-
-  {
-    DataSourceDescriptor lazy_heapprofd_dsd;
-    lazy_heapprofd_dsd.set_name(kHeapprofdDataSourceName);
-    endpoint_->RegisterDataSource(lazy_heapprofd_dsd);
-  }
-
-  {
-    DataSourceDescriptor lazy_java_hprof_dsd;
-    lazy_java_hprof_dsd.set_name(kJavaHprofDataSourceName);
-    endpoint_->RegisterDataSource(lazy_java_hprof_dsd);
-  }
-}
-
-void BuiltinProducer::SetupDataSource(DataSourceInstanceID ds_id,
-                                      const DataSourceConfig& ds_config) {
-  if (ds_config.name() == kHeapprofdDataSourceName ||
-      ds_config.name() == kJavaHprofDataSourceName) {
-    SetAndroidProperty(kLazyHeapprofdPropertyName, "1");
-    lazy_heapprofd_.generation++;
-    lazy_heapprofd_.instance_ids.emplace(ds_id);
-  }
-}
-
-void BuiltinProducer::StartDataSource(DataSourceInstanceID ds_id,
-                                      const DataSourceConfig& ds_config) {
-  // We slightly rely on the fact that since this producer is in-process for
-  // enabling metatrace early (relative to producers that are notified via IPC).
-  if (ds_config.name() == MetatraceWriter::kDataSourceName) {
-    auto writer = endpoint_->CreateTraceWriter(
-        static_cast<BufferID>(ds_config.target_buffer()));
-
-    auto it_and_inserted = metatrace_.writers.emplace(
-        std::piecewise_construct, std::make_tuple(ds_id), std::make_tuple());
-    PERFETTO_DCHECK(it_and_inserted.second);
-    // Note: only the first concurrent writer will actually be active.
-    metatrace_.writers[ds_id].Enable(task_runner_, std::move(writer),
-                                     metatrace::TAG_ANY);
-  }
-}
-
-void BuiltinProducer::StopDataSource(DataSourceInstanceID ds_id) {
-  auto meta_it = metatrace_.writers.find(ds_id);
-  if (meta_it != metatrace_.writers.end()) {
-    // Synchronously re-flush the metatrace writer to record more of the
-    // teardown interactions, then ack the stop.
-    meta_it->second.WriteAllAndFlushTraceWriter([] {});
-    metatrace_.writers.erase(meta_it);
-    endpoint_->NotifyDataSourceStopped(ds_id);
-  }
-
-  auto lazy_it = lazy_heapprofd_.instance_ids.find(ds_id);
-  if (lazy_it != lazy_heapprofd_.instance_ids.end()) {
-    lazy_heapprofd_.instance_ids.erase(lazy_it);
-
-    // if no more sessions - stop heapprofd after a delay
-    if (lazy_heapprofd_.instance_ids.empty()) {
-      uint64_t cur_generation = lazy_heapprofd_.generation;
-      auto weak_this = weak_factory_.GetWeakPtr();
-      task_runner_->PostDelayedTask(
-          [weak_this, cur_generation] {
-            if (!weak_this)
-              return;
-            if (weak_this->lazy_heapprofd_.generation == cur_generation)
-              weak_this->SetAndroidProperty(kLazyHeapprofdPropertyName, "0");
-          },
-          lazy_heapprofd_.stop_delay_ms);
-    }
-  }
-}
-
-void BuiltinProducer::Flush(FlushRequestID flush_id,
-                            const DataSourceInstanceID* ds_ids,
-                            size_t num_ds_ids) {
-  for (size_t i = 0; i < num_ds_ids; i++) {
-    auto meta_it = metatrace_.writers.find(ds_ids[i]);
-    if (meta_it != metatrace_.writers.end()) {
-      meta_it->second.WriteAllAndFlushTraceWriter([] {});
-    }
-    // nothing to be done for lazy heapprofd sources
-  }
-  endpoint_->NotifyFlushComplete(flush_id);
-}
-
-bool BuiltinProducer::SetAndroidProperty(const std::string& name,
-                                         const std::string& value) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  return __system_property_set(name.c_str(), value.c_str()) == 0;
-#else
-  // Allow this to be mocked out for tests on other platforms.
-  base::ignore_result(name);
-  base::ignore_result(value);
-  return true;
-#endif
-}
-
-}  // namespace perfetto
diff --git a/src/traced/service/builtin_producer.h b/src/traced/service/builtin_producer.h
deleted file mode 100644
index 065310b..0000000
--- a/src/traced/service/builtin_producer.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACED_SERVICE_BUILTIN_PRODUCER_H_
-#define SRC_TRACED_SERVICE_BUILTIN_PRODUCER_H_
-
-#include <map>
-#include <set>
-#include <string>
-
-#include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/producer.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
-#include "src/tracing/core/metatrace_writer.h"
-
-namespace perfetto {
-
-// Data sources built into the tracing service daemon (traced):
-// * perfetto metatrace
-// * lazy heapprofd daemon starter (android only)
-class BuiltinProducer : public Producer {
- public:
-  BuiltinProducer(base::TaskRunner* task_runner, uint32_t lazy_stop_delay_ms);
-
-  ~BuiltinProducer() override;
-  void OnConnect() override;
-  void SetupDataSource(DataSourceInstanceID, const DataSourceConfig&) override;
-  void StartDataSource(DataSourceInstanceID, const DataSourceConfig&) override;
-  void Flush(FlushRequestID, const DataSourceInstanceID*, size_t) override;
-  void StopDataSource(DataSourceInstanceID) override;
-
-  // nops:
-  void OnDisconnect() override {}
-  void OnTracingSetup() override {}
-  void ClearIncrementalState(const DataSourceInstanceID*, size_t) override {}
-
-  void ConnectInProcess(TracingService* svc);
-
-  // virtual for testing
-  virtual bool SetAndroidProperty(const std::string& name,
-                                  const std::string& value);
-
- private:
-  struct MetatraceState {
-    // If multiple metatrace sources are enabled concurrently, only the first
-    // one becomes active. But we still want to be responsive to the others'
-    // flushes.
-    std::map<DataSourceInstanceID, MetatraceWriter> writers;
-  };
-
-  struct LazyHeapprofdState {
-    // Track active instances to know when to stop.
-    std::set<DataSourceInstanceID> instance_ids;
-    // Delay between the last heapprofd session stopping, and the lazy system
-    // property being unset (to shut down heapprofd).
-    uint32_t stop_delay_ms;
-    uint64_t generation = 0;
-  };
-
-  base::TaskRunner* const task_runner_;
-  std::unique_ptr<TracingService::ProducerEndpoint> endpoint_;
-
-  MetatraceState metatrace_;
-  LazyHeapprofdState lazy_heapprofd_;
-
-  base::WeakPtrFactory<BuiltinProducer> weak_factory_;  // Keep last.
-};
-
-}  // namespace perfetto
-
-#endif  // SRC_TRACED_SERVICE_BUILTIN_PRODUCER_H_
diff --git a/src/traced/service/builtin_producer_unittest.cc b/src/traced/service/builtin_producer_unittest.cc
deleted file mode 100644
index 80b17fe..0000000
--- a/src/traced/service/builtin_producer_unittest.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.
- */
-
-#include "src/traced/service/builtin_producer.h"
-
-#include "perfetto/tracing/core/data_source_config.h"
-#include "src/base/test/test_task_runner.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace {
-
-constexpr const char kHeapprofdDataSourceName[] = "android.heapprofd";
-constexpr const char kLazyHeapprofdPropertyName[] = "traced.lazy.heapprofd";
-
-using ::testing::_;
-using ::testing::InSequence;
-using ::testing::InvokeWithoutArgs;
-using ::testing::Return;
-
-class MockBuiltinProducer : public BuiltinProducer {
- public:
-  MockBuiltinProducer(base::TaskRunner* task_runner)
-      : BuiltinProducer(task_runner, /*lazy_stop_delay_ms=*/0) {}
-
-  MOCK_METHOD2(SetAndroidProperty,
-               bool(const std::string&, const std::string&));
-};
-
-TEST(BuiltinProducerTest, LazyHeapprofdSimple) {
-  DataSourceConfig cfg;
-  cfg.set_name(kHeapprofdDataSourceName);
-  base::TestTaskRunner task_runner;
-  auto done = task_runner.CreateCheckpoint("done");
-  MockBuiltinProducer p(&task_runner);
-  InSequence s;
-  EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, "1"))
-      .WillOnce(Return(true));
-  EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, "0"))
-      .WillOnce(InvokeWithoutArgs([&done]() {
-        done();
-        return true;
-      }));
-  p.SetupDataSource(1, cfg);
-  p.StopDataSource(1);
-  task_runner.RunUntilCheckpoint("done");
-}
-
-TEST(BuiltinProducerTest, LazyHeapprofdRefCount) {
-  DataSourceConfig cfg;
-  cfg.set_name(kHeapprofdDataSourceName);
-  base::TestTaskRunner task_runner;
-  auto done = task_runner.CreateCheckpoint("done");
-  MockBuiltinProducer p(&task_runner);
-  InSequence s;
-  EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, "1"))
-      .WillRepeatedly(Return(true));
-  p.SetupDataSource(1, cfg);
-  p.SetupDataSource(2, cfg);
-  p.StopDataSource(2);
-  task_runner.RunUntilIdle();
-  EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, "0"))
-      .WillOnce(InvokeWithoutArgs([&done]() {
-        done();
-        return true;
-      }));
-  p.StopDataSource(1);
-  task_runner.RunUntilCheckpoint("done");
-}
-
-TEST(BuiltinProducerTest, LazyHeapprofdNoFlap) {
-  DataSourceConfig cfg;
-  cfg.set_name(kHeapprofdDataSourceName);
-  base::TestTaskRunner task_runner;
-  auto done = task_runner.CreateCheckpoint("done");
-  MockBuiltinProducer p(&task_runner);
-  InSequence s;
-  EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, "1"))
-      .WillRepeatedly(Return(true));
-  p.SetupDataSource(1, cfg);
-  p.StopDataSource(1);
-  p.SetupDataSource(2, cfg);
-  task_runner.RunUntilIdle();
-  p.StopDataSource(2);
-  EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, "0"))
-      .WillOnce(InvokeWithoutArgs([&done]() {
-        done();
-        return true;
-      }));
-  task_runner.RunUntilCheckpoint("done");
-}
-
-}  // namespace
-}  // namespace perfetto
diff --git a/src/traced/service/lazy_producer.cc b/src/traced/service/lazy_producer.cc
new file mode 100644
index 0000000..d63bdd4
--- /dev/null
+++ b/src/traced/service/lazy_producer.cc
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2019 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 "src/traced/service/lazy_producer.h"
+
+#include "perfetto/base/build_config.h"
+
+#include "perfetto/tracing/core/data_source_config.h"
+#include "perfetto/tracing/core/data_source_descriptor.h"
+
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#include <sys/system_properties.h>
+#endif
+
+namespace perfetto {
+
+LazyProducer::LazyProducer(base::TaskRunner* task_runner,
+                           uint32_t delay_ms,
+                           std::string data_source_name,
+                           std::string property_name)
+    : task_runner_(task_runner),
+      delay_ms_(delay_ms),
+      data_source_name_(data_source_name),
+      property_name_(property_name),
+      weak_factory_(this) {}
+
+void LazyProducer::ConnectInProcess(TracingService* svc) {
+  endpoint_ = svc->ConnectProducer(this, geteuid(), "lazy_producer",
+                                   /*shm_hint_kb*/ 16, /*in_process*/ true);
+}
+
+void LazyProducer::OnConnect() {
+  DataSourceDescriptor dsd;
+  dsd.set_name(data_source_name_);
+  endpoint_->RegisterDataSource(dsd);
+}
+
+void LazyProducer::SetupDataSource(DataSourceInstanceID,
+                                   const DataSourceConfig&) {
+  SetAndroidProperty(property_name_, "1");
+  active_sessions_++;
+  generation_++;
+}
+
+void LazyProducer::StopDataSource(DataSourceInstanceID) {
+  if (--active_sessions_)
+    return;
+
+  uint64_t cur_generation = generation_;
+  auto weak_this = weak_factory_.GetWeakPtr();
+  task_runner_->PostDelayedTask(
+      [weak_this, cur_generation] {
+        if (!weak_this)
+          return;
+        if (weak_this->generation_ == cur_generation)
+          weak_this->SetAndroidProperty(weak_this->property_name_, "0");
+      },
+      delay_ms_);
+}
+
+bool LazyProducer::SetAndroidProperty(const std::string& name,
+                                      const std::string& value) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+  return __system_property_set(name.c_str(), value.c_str()) == 0;
+#else
+  // Allow this to be mocked out for tests on other platforms.
+  base::ignore_result(name);
+  base::ignore_result(value);
+  return true;
+#endif
+}
+
+LazyProducer::~LazyProducer() {
+  if (active_sessions_)
+    SetAndroidProperty(property_name_, "0");
+}
+
+}  // namespace perfetto
diff --git a/src/traced/service/lazy_producer.h b/src/traced/service/lazy_producer.h
new file mode 100644
index 0000000..541b5ba
--- /dev/null
+++ b/src/traced/service/lazy_producer.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 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 SRC_TRACED_SERVICE_LAZY_PRODUCER_H_
+#define SRC_TRACED_SERVICE_LAZY_PRODUCER_H_
+
+#include <set>
+#include <string>
+
+#include "perfetto/base/task_runner.h"
+#include "perfetto/base/weak_ptr.h"
+
+#include "perfetto/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/producer.h"
+#include "perfetto/tracing/core/tracing_service.h"
+
+namespace perfetto {
+
+class LazyProducer : public Producer {
+ public:
+  LazyProducer(base::TaskRunner* task_runner,
+               uint32_t delay_ms,
+               std::string data_source_name,
+               std::string property_name);
+
+  ~LazyProducer() override;
+  // No-ops to satisfy the Producer implementation.
+  void OnDisconnect() override {}
+  void OnTracingSetup() override {}
+  void StartDataSource(DataSourceInstanceID, const DataSourceConfig&) override {
+  }
+  void Flush(FlushRequestID flush_id,
+             const DataSourceInstanceID*,
+             size_t) override {
+    endpoint_->NotifyFlushComplete(flush_id);
+  }
+  void ClearIncrementalState(const DataSourceInstanceID* /*data_source_ids*/,
+                             size_t /*num_data_sources*/) override {}
+
+  void OnConnect() override;
+  void SetupDataSource(DataSourceInstanceID, const DataSourceConfig&) override;
+  void StopDataSource(DataSourceInstanceID) override;
+
+  void ConnectInProcess(TracingService* svc);
+  virtual bool SetAndroidProperty(const std::string& name,
+                                  const std::string& value);
+
+ private:
+  base::TaskRunner* task_runner_;
+  uint32_t delay_ms_;
+
+  std::string data_source_name_;
+  std::string property_name_;
+
+  std::unique_ptr<TracingService::ProducerEndpoint> endpoint_;
+  uint64_t active_sessions_ = 0;
+  uint64_t generation_ = 0;
+
+  base::WeakPtrFactory<LazyProducer> weak_factory_;  // Keep last.
+};
+
+}  // namespace perfetto
+
+#endif  // SRC_TRACED_SERVICE_LAZY_PRODUCER_H_
diff --git a/src/traced/service/lazy_producer_unittest.cc b/src/traced/service/lazy_producer_unittest.cc
new file mode 100644
index 0000000..7707a99
--- /dev/null
+++ b/src/traced/service/lazy_producer_unittest.cc
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+#include "src/traced/service/lazy_producer.h"
+
+#include "src/base/test/test_task_runner.h"
+
+#include "perfetto/tracing/core/data_source_config.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace perfetto {
+namespace {
+
+constexpr const char* kDataSourceName = "android.heapprofd";
+constexpr const char* kPropertyName = "persist.heapprofd.enable";
+
+using ::testing::_;
+using ::testing::InSequence;
+using ::testing::Return;
+using ::testing::InvokeWithoutArgs;
+
+class MockLazyProducer : public LazyProducer {
+ public:
+  MockLazyProducer(base::TaskRunner* task_runner)
+      : LazyProducer(task_runner, 0, kDataSourceName, kPropertyName) {}
+
+  MOCK_METHOD2(SetAndroidProperty,
+               bool(const std::string&, const std::string&));
+};
+
+TEST(LazyProducersTest, Simple) {
+  DataSourceConfig cfg;
+  cfg.set_name(kDataSourceName);
+  base::TestTaskRunner task_runner;
+  auto done = task_runner.CreateCheckpoint("done");
+  MockLazyProducer p(&task_runner);
+  InSequence s;
+  EXPECT_CALL(p, SetAndroidProperty(kPropertyName, "1")).WillOnce(Return(true));
+  EXPECT_CALL(p, SetAndroidProperty(kPropertyName, "0"))
+      .WillOnce(InvokeWithoutArgs([&done]() {
+        done();
+        return true;
+      }));
+  p.SetupDataSource(1, cfg);
+  p.StopDataSource(1);
+  task_runner.RunUntilCheckpoint("done");
+}
+
+TEST(LazyProducersTest, RefCount) {
+  DataSourceConfig cfg;
+  cfg.set_name(kDataSourceName);
+  base::TestTaskRunner task_runner;
+  auto done = task_runner.CreateCheckpoint("done");
+  MockLazyProducer p(&task_runner);
+  InSequence s;
+  EXPECT_CALL(p, SetAndroidProperty(kPropertyName, "1"))
+      .WillRepeatedly(Return(true));
+  p.SetupDataSource(1, cfg);
+  p.SetupDataSource(2, cfg);
+  p.StopDataSource(2);
+  task_runner.RunUntilIdle();
+  EXPECT_CALL(p, SetAndroidProperty(kPropertyName, "0"))
+      .WillOnce(InvokeWithoutArgs([&done]() {
+        done();
+        return true;
+      }));
+  p.StopDataSource(1);
+  task_runner.RunUntilCheckpoint("done");
+}
+
+TEST(LazyProducersTest, NoFlap) {
+  DataSourceConfig cfg;
+  cfg.set_name(kDataSourceName);
+  base::TestTaskRunner task_runner;
+  auto done = task_runner.CreateCheckpoint("done");
+  MockLazyProducer p(&task_runner);
+  InSequence s;
+  EXPECT_CALL(p, SetAndroidProperty(kPropertyName, "1"))
+      .WillRepeatedly(Return(true));
+  p.SetupDataSource(1, cfg);
+  p.StopDataSource(1);
+  p.SetupDataSource(2, cfg);
+  task_runner.RunUntilIdle();
+  p.StopDataSource(2);
+  EXPECT_CALL(p, SetAndroidProperty(kPropertyName, "0"))
+      .WillOnce(InvokeWithoutArgs([&done]() {
+        done();
+        return true;
+      }));
+  task_runner.RunUntilCheckpoint("done");
+}
+
+}  // namespace
+}  // namespace perfetto
diff --git a/src/traced/service/main.cc b/src/traced/service/main.cc
index fe81b4b..552ae6b 100644
--- a/src/traced/service/main.cc
+++ b/src/traced/service/main.cc
@@ -15,7 +15,7 @@
  */
 
 #include <stdio.h>
-#include "perfetto/ext/traced/traced.h"
+#include "perfetto/traced/traced.h"
 
 int main(int argc, char** argv) {
   return perfetto::ServiceMain(argc, argv);
diff --git a/src/traced/service/service.cc b/src/traced/service/service.cc
index b28c40b..c52b246 100644
--- a/src/traced/service/service.cc
+++ b/src/traced/service/service.cc
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/base/unix_task_runner.h"
-#include "perfetto/ext/base/watchdog.h"
-#include "perfetto/ext/traced/traced.h"
-#include "perfetto/ext/tracing/ipc/default_socket.h"
-#include "perfetto/ext/tracing/ipc/service_ipc_host.h"
-#include "src/traced/service/builtin_producer.h"
+#include "perfetto/base/unix_task_runner.h"
+#include "perfetto/base/watchdog.h"
+#include "perfetto/traced/traced.h"
+#include "perfetto/tracing/ipc/service_ipc_host.h"
+#include "src/traced/service/lazy_producer.h"
+#include "src/tracing/ipc/default_socket.h"
 
 namespace perfetto {
 
@@ -29,7 +29,7 @@
   svc = ServiceIPCHost::CreateInstance(&task_runner);
 
   // When built as part of the Android tree, the two socket are created and
-  // bound by init and their fd number is passed in two env variables.
+  // bonund by init and their fd number is passed in two env variables.
   // See libcutils' android_get_control_socket().
   const char* env_prod = getenv("ANDROID_SOCKET_traced_producer");
   const char* env_cons = getenv("ANDROID_SOCKET_traced_consumer");
@@ -50,8 +50,9 @@
     return 1;
   }
 
-  BuiltinProducer builtin_producer(&task_runner, /*lazy_stop_delay_ms=*/30000);
-  builtin_producer.ConnectInProcess(svc->service());
+  LazyProducer lazy_heapprofd(&task_runner, /*delay_ms=*/30000,
+                              "android.heapprofd", "traced.lazy.heapprofd");
+  lazy_heapprofd.ConnectInProcess(svc->service());
 
   // Set the CPU limit and start the watchdog running. The memory limit will
   // be set inside the service code as it relies on the size of buffers.
diff --git a/src/tracing/BUILD.gn b/src/tracing/BUILD.gn
index 9c58d68..cd9823d 100644
--- a/src/tracing/BUILD.gn
+++ b/src/tracing/BUILD.gn
@@ -13,116 +13,129 @@
 # limitations under the License.
 
 import("//build_overrides/build.gni")
-import("../../gn/fuzzer.gni")
 import("../../gn/perfetto.gni")
-import("../../gn/test.gni")
 
 # Core tracing library, platform independent, no transport layer.
 source_set("tracing") {
   public_deps = [
-    ":common",
-    "../../include/perfetto/ext/tracing/core",
+    "../../include/perfetto/tracing/core",
     "../../protos/perfetto/common:lite",
     "../../protos/perfetto/trace:minimal_lite",
     "../../protos/perfetto/trace:trusted_lite",
     "../../protos/perfetto/trace:zero",
-    "../../protos/perfetto/trace/interned_data:zero",
-    "../../protos/perfetto/trace/track_event:zero",
   ]
   deps = [
     "../../gn:default_deps",
-    "../../include/perfetto/tracing",
+    "../../gn:gtest_prod_config",
     "../../protos/perfetto/config:lite",
-    "../../protos/perfetto/trace/perfetto:zero",  # For MetatraceWriter.
     "../base",
     "../protozero",
   ]
   sources = [
+    "core/android_log_config.cc",
+    "core/android_power_config.cc",
+    "core/chrome_config.cc",
+    "core/commit_data_request.cc",
+    "core/data_source_config.cc",
+    "core/data_source_descriptor.cc",
+    "core/ftrace_config.cc",
+    "core/heapprofd_config.cc",
     "core/id_allocator.cc",
     "core/id_allocator.h",
-    "core/metatrace_writer.cc",
-    "core/metatrace_writer.h",
+    "core/inode_file_config.cc",
     "core/null_trace_writer.cc",
     "core/null_trace_writer.h",
+    "core/observable_events.cc",
+    "core/packages_list_config.cc",
     "core/packet_stream_validator.cc",
     "core/packet_stream_validator.h",
     "core/patch_list.h",
+    "core/process_stats_config.cc",
     "core/shared_memory_abi.cc",
     "core/shared_memory_arbiter_impl.cc",
     "core/shared_memory_arbiter_impl.h",
     "core/sliced_protobuf_input_stream.cc",
+    "core/sliced_protobuf_input_stream.h",
     "core/startup_trace_writer.cc",
     "core/startup_trace_writer_registry.cc",
+    "core/sys_stats_config.cc",
+    "core/test_config.cc",
     "core/trace_buffer.cc",
     "core/trace_buffer.h",
+    "core/trace_config.cc",
     "core/trace_packet.cc",
+    "core/trace_stats.cc",
     "core/trace_writer_impl.cc",
     "core/trace_writer_impl.h",
     "core/tracing_service_impl.cc",
     "core/tracing_service_impl.h",
+    "core/tracing_service_state.cc",
     "core/virtual_destructors.cc",
   ]
 }
 
-perfetto_unittest_source_set("unittests") {
-  testonly = true
-  deps = [
-    ":test_support",
-    ":tracing",
-    "../../gn:default_deps",
-    "../../gn:gtest_and_gmock",
-    "../../protos/perfetto/config:lite",
-    "../../protos/perfetto/trace:lite",
-    "../../protos/perfetto/trace:zero",
-    "../base",
-    "../base:test_support",
-  ]
-  sources = [
-    "core/id_allocator_unittest.cc",
-    "core/null_trace_writer_unittest.cc",
-    "core/packet_stream_validator_unittest.cc",
-    "core/patch_list_unittest.cc",
-    "core/shared_memory_abi_unittest.cc",
-    "core/sliced_protobuf_input_stream_unittest.cc",
-    "core/trace_buffer_unittest.cc",
-    "core/trace_packet_unittest.cc",
-    "test/aligned_buffer_test.cc",
-    "test/aligned_buffer_test.h",
-    "test/fake_packet.cc",
-    "test/fake_packet.h",
-    "test/test_shared_memory.cc",
-    "test/test_shared_memory.h",
-  ]
-
-  if (enable_perfetto_ipc) {
-    deps += [ ":ipc" ]
-    sources += [
-      "ipc/posix_shared_memory_unittest.cc",
-      "test/tracing_integration_test.cc",
+if (perfetto_build_standalone || perfetto_build_with_android ||
+    build_with_chromium) {
+  source_set("unittests") {
+    testonly = true
+    deps = [
+      ":test_support",
+      ":tracing",
+      "../../gn:default_deps",
+      "../../gn:gtest_deps",
+      "../../protos/perfetto/config:lite",
+      "../../protos/perfetto/trace:lite",
+      "../../protos/perfetto/trace:zero",
+      "../base",
+      "../base:test_support",
     ]
-  }
-
-  # These tests rely on test_task_runner.h which
-  # has no Windows implementation.
-  if (!is_win) {
-    sources += [
-      "core/shared_memory_arbiter_impl_unittest.cc",
-      "core/startup_trace_writer_unittest.cc",
-      "core/trace_writer_impl_unittest.cc",
-      "core/tracing_service_impl_unittest.cc",
-      "test/fake_producer_endpoint.h",
-      "test/mock_consumer.cc",
-      "test/mock_consumer.h",
-      "test/mock_producer.cc",
-      "test/mock_producer.h",
+    sources = [
+      "core/id_allocator_unittest.cc",
+      "core/null_trace_writer_unittest.cc",
+      "core/packet_stream_validator_unittest.cc",
+      "core/patch_list_unittest.cc",
+      "core/shared_memory_abi_unittest.cc",
+      "core/sliced_protobuf_input_stream_unittest.cc",
+      "core/trace_buffer_unittest.cc",
+      "core/trace_packet_unittest.cc",
+      "test/aligned_buffer_test.cc",
+      "test/aligned_buffer_test.h",
+      "test/fake_packet.cc",
+      "test/fake_packet.h",
+      "test/test_shared_memory.cc",
+      "test/test_shared_memory.h",
     ]
+
+    if (perfetto_build_with_ipc_layer) {
+      deps += [ ":ipc" ]
+      sources += [
+        "ipc/posix_shared_memory_unittest.cc",
+        "test/tracing_integration_test.cc",
+      ]
+    }
+
+    # These tests rely on test_task_runner.h which
+    # has no Windows implementation.
+    if (!is_win) {
+      sources += [
+        "core/shared_memory_arbiter_impl_unittest.cc",
+        "core/startup_trace_writer_unittest.cc",
+        "core/trace_writer_impl_unittest.cc",
+        "core/tracing_service_impl_unittest.cc",
+        "test/fake_producer_endpoint.h",
+        "test/mock_consumer.cc",
+        "test/mock_consumer.h",
+        "test/mock_producer.cc",
+        "test/mock_producer.h",
+      ]
+    }
   }
 }
 
 source_set("test_support") {
   testonly = true
   public_deps = [
-    "../../include/perfetto/ext/tracing/core",
+    "../../include/perfetto/tracing/core",
     "../../protos/perfetto/trace:lite",
     "../../protos/perfetto/trace:zero",
     "../protozero",
@@ -136,9 +149,8 @@
 if (perfetto_build_standalone || perfetto_build_with_android) {
   executable("consumer_api_test") {
     deps = [
-      ":consumer_api_deprecated",
+      ":api",
       "../../gn:default_deps",
-      "../../include/perfetto/public",
       "../../protos/perfetto/config:lite",
       "../../protos/perfetto/trace:lite",
       "../base",
@@ -148,16 +160,24 @@
     ]
   }
 
+  source_set("tracing_benchmarks") {
+    testonly = true
+    deps = [
+      "../../gn:default_deps",
+      "//buildtools:benchmark",
+    ]
+    sources = [
+      "test/hello_world_benchmark.cc",
+    ]
+  }
+
   # Imlementation of the public-facing consumer API in libperfetto.so (only for
   # Android builds).
-  # TODO(primiano): remove this. This is a legacy and deprecated API. The only
-  # uses should be moved to the perfetto Client API.
-  source_set("consumer_api_deprecated") {
+  source_set("api") {
     deps = [
       ":ipc",
       ":tracing",
       "../../gn:default_deps",
-      "../../include/perfetto/public",
       "../../protos/perfetto/config:lite",
       "../base",
     ]
@@ -167,18 +187,19 @@
   }
 }
 
-if (enable_perfetto_ipc) {
+if (perfetto_build_with_ipc_layer) {
   # Posix specialization of the tracing library for Linux / Android / Mac.
   # Provides an IPC transport over a UNIX domain socket.
-  source_set("ipc") {
+  static_library("ipc") {
     public_deps = [
-      "../../include/perfetto/ext/tracing/core",
-      "../../include/perfetto/ext/tracing/ipc",
+      "../../include/perfetto/tracing/core",
+      "../../include/perfetto/tracing/ipc",
     ]
     sources = [
       "ipc/consumer/consumer_ipc_client_impl.cc",
       "ipc/consumer/consumer_ipc_client_impl.h",
       "ipc/default_socket.cc",
+      "ipc/default_socket.h",
       "ipc/posix_shared_memory.cc",
       "ipc/posix_shared_memory.h",
       "ipc/producer/producer_ipc_client_impl.cc",
@@ -199,119 +220,3 @@
     ]
   }
 }
-
-# Separate target because the embedder might not want this (e.g. on Windows).
-if (is_linux || is_mac || is_android) {
-  source_set("platform_posix") {
-    deps = [
-      "../../gn:default_deps",
-      "../../include/perfetto/tracing",
-      "../base",
-    ]
-    sources = [
-      "platform_posix.cc",
-    ]
-  }
-}
-
-# Code that both public headers and other non-public sources (e.g.
-# src/tracing/core) need to depend on. It cannot be in the root :tracing target
-# otherwise there would be a cyclic dependency because public itself needs to
-# depend on tracing.
-source_set("common") {
-  deps = [
-    "../../gn:default_deps",
-    "../../include/perfetto/tracing",
-  ]
-  sources = [
-    "trace_writer_base.cc",
-  ]
-}
-
-source_set("client_api") {
-  deps = [
-    ":common",
-    "../../include/perfetto/tracing/core",
-    "../../protos/perfetto/config:lite",
-    "../base",
-    "../tracing",
-  ]
-  public_deps = [
-    "../../gn:default_deps",
-    "../../include/perfetto/tracing",
-  ]
-  sources = [
-    "data_source.cc",
-    "internal/in_process_tracing_backend.cc",
-    "internal/in_process_tracing_backend.h",
-    "internal/tracing_muxer_impl.cc",
-    "internal/tracing_muxer_impl.h",
-    "internal/track_event_internal.cc",
-    "platform.cc",
-    "tracing.cc",
-    "track_event_category_registry.cc",
-    "track_event_context.cc",
-    "virtual_destructors.cc",
-  ]
-
-  if (enable_perfetto_ipc) {
-    deps += [ ":ipc" ]
-    sources += [
-      "internal/system_tracing_backend.cc",
-      "internal/system_tracing_backend.h",
-    ]
-  }
-}
-
-if (enable_perfetto_integration_tests) {
-  source_set("client_api_integrationtests") {
-    testonly = true
-    deps = [
-      ":client_api",
-      ":platform_posix",
-      "../../:libperfetto_client_experimental",
-      "../../gn:default_deps",
-      "../../gn:gtest_and_gmock",
-      "../../include/perfetto/tracing/core",
-      "../../protos/perfetto/trace:lite",
-      "../../protos/perfetto/trace:zero",
-      "../../protos/perfetto/trace/interned_data:zero",
-      "../base",
-      "test:api_test_support",
-    ]
-    sources = [
-      "api_integrationtest.cc",
-      "test/tracing_module.cc",
-      "test/tracing_module.h",
-      "test/tracing_module2.cc",
-      "test/tracing_module_categories.h",
-    ]
-  }
-}
-
-if (enable_perfetto_benchmarks) {
-  source_set("benchmarks") {
-    testonly = true
-    deps = [
-      ":tracing",
-      "../../../../gn:benchmark",
-      "../../../../gn:default_deps",
-      "../../protos/perfetto/trace:zero",
-      "../../protos/perfetto/trace/ftrace:zero",
-      "../protozero",
-    ]
-    sources = [
-      "core/packet_stream_validator_benchmark.cc",
-    ]
-  }
-}
-
-perfetto_fuzzer_test("packet_stream_validator_fuzzer") {
-  sources = [
-    "core/packet_stream_validator_fuzzer.cc",
-  ]
-  deps = [
-    ":tracing",
-    "../../../../gn:default_deps",
-  ]
-}
diff --git a/src/tracing/api_impl/consumer_api.cc b/src/tracing/api_impl/consumer_api.cc
index db7cb7d..286b6b4 100644
--- a/src/tracing/api_impl/consumer_api.cc
+++ b/src/tracing/api_impl/consumer_api.cc
@@ -27,29 +27,29 @@
 #include <unistd.h>
 
 #include <atomic>
-#include <condition_variable>
 #include <memory>
 #include <mutex>
 #include <thread>
 
 #include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/ext/base/thread_checker.h"
-#include "perfetto/ext/base/unix_task_runner.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/tracing/core/consumer.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/ipc/consumer_ipc_client.h"
-#include "perfetto/ext/tracing/ipc/default_socket.h"
+#include "perfetto/base/event.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/temp_file.h"
+#include "perfetto/base/thread_checker.h"
+#include "perfetto/base/unix_task_runner.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/tracing/core/consumer.h"
 #include "perfetto/tracing/core/trace_config.h"
+#include "perfetto/tracing/core/trace_packet.h"
+#include "perfetto/tracing/ipc/consumer_ipc_client.h"
+#include "src/tracing/ipc/default_socket.h"
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
 #include <linux/memfd.h>
 #include <sys/syscall.h>
 #endif
 
-#include "protos/perfetto/config/trace_config.pb.h"
+#include "perfetto/config/trace_config.pb.h"
 
 #define PERFETTO_EXPORTED_API __attribute__((visibility("default")))
 
@@ -350,7 +350,7 @@
   if (it == sessions_.end()) {
     PERFETTO_ELOG("StartTracing(): Invalid tracing session handle");
     return;
-  }
+  };
   TracingSession* session = it->second.get();
   task_runner_->PostTask([session] { session->StartTracing(); });
 }
diff --git a/src/tracing/api_impl/consumer_api_test.cc b/src/tracing/api_impl/consumer_api_test.cc
index ce8883a..035bd65 100644
--- a/src/tracing/api_impl/consumer_api_test.cc
+++ b/src/tracing/api_impl/consumer_api_test.cc
@@ -22,8 +22,8 @@
 #include "perfetto/base/logging.h"
 #include "perfetto/public/consumer_api.h"
 
-#include "protos/perfetto/config/trace_config.pb.h"
-#include "protos/perfetto/trace/trace.pb.h"
+#include "perfetto/config/trace_config.pb.h"
+#include "perfetto/trace/trace.pb.h"
 
 using namespace perfetto::consumer;
 
diff --git a/src/tracing/api_integrationtest.cc b/src/tracing/api_integrationtest.cc
deleted file mode 100644
index dee34a4..0000000
--- a/src/tracing/api_integrationtest.cc
+++ /dev/null
@@ -1,1366 +0,0 @@
-/*
- * Copyright (C) 2019 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 <fcntl.h>
-
-#include <chrono>
-#include <condition_variable>
-#include <functional>
-#include <list>
-#include <mutex>
-#include <vector>
-
-#include "perfetto/tracing.h"
-#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
-#include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/trace.pb.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-#include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
-#include "protos/perfetto/trace/track_event/log_message.pbzero.h"
-#include "protos/perfetto/trace/track_event/source_location.pbzero.h"
-#include "test/gtest_and_gmock.h"
-
-// Deliberately not pulling any non-public perfetto header to spot accidental
-// header public -> non-public dependency while building this file.
-
-// These two are the only headers allowed here, see comments in
-// api_test_support.h.
-#include "src/tracing/test/api_test_support.h"
-#include "src/tracing/test/tracing_module.h"
-
-#include "perfetto/tracing/core/data_source_descriptor.h"
-#include "perfetto/tracing/core/trace_config.h"
-
-// Trace categories used in the tests.
-PERFETTO_DEFINE_CATEGORIES(PERFETTO_CATEGORY(test),
-                           PERFETTO_CATEGORY(foo),
-                           PERFETTO_CATEGORY(bar));
-PERFETTO_TRACK_EVENT_STATIC_STORAGE();
-
-// For testing interning of complex objects.
-using SourceLocation = std::tuple<const char* /* file_name */,
-                                  const char* /* function_name */,
-                                  uint32_t /* line_number */>;
-
-namespace std {
-template <>
-struct hash<SourceLocation> {
-  size_t operator()(const SourceLocation& value) const {
-    auto hasher = hash<size_t>();
-    return hasher(reinterpret_cast<size_t>(get<0>(value))) ^
-           hasher(reinterpret_cast<size_t>(get<1>(value))) ^
-           hasher(get<2>(value));
-  }
-};
-}  // namespace std
-
-namespace {
-
-using ::testing::_;
-using ::testing::ElementsAre;
-using ::testing::HasSubstr;
-using ::testing::Invoke;
-using ::testing::InvokeWithoutArgs;
-using ::testing::NiceMock;
-using ::testing::Not;
-using ::testing::Property;
-using ::testing::StrEq;
-
-// ------------------------------
-// Declarations of helper classes
-// ------------------------------
-static constexpr auto kWaitEventTimeout = std::chrono::seconds(5);
-
-struct WaitableTestEvent {
-  std::mutex mutex_;
-  std::condition_variable cv_;
-  bool notified_ = false;
-
-  bool notified() {
-    std::unique_lock<std::mutex> lock(mutex_);
-    return notified_;
-  }
-
-  void Wait() {
-    std::unique_lock<std::mutex> lock(mutex_);
-    if (!cv_.wait_for(lock, kWaitEventTimeout, [this] { return notified_; })) {
-      fprintf(stderr, "Timed out while waiting for event\n");
-      abort();
-    }
-  }
-
-  void Notify() {
-    std::unique_lock<std::mutex> lock(mutex_);
-    notified_ = true;
-    cv_.notify_one();
-  }
-};
-
-class MockDataSource;
-
-// We can't easily use gmock here because instances of data sources are lazily
-// created by the service and are not owned by the test fixture.
-struct TestDataSourceHandle {
-  WaitableTestEvent on_create;
-  WaitableTestEvent on_setup;
-  WaitableTestEvent on_start;
-  WaitableTestEvent on_stop;
-  MockDataSource* instance;
-  perfetto::DataSourceConfig config;
-  bool handle_stop_asynchronously = false;
-  std::function<void()> on_start_callback;
-  std::function<void()> on_stop_callback;
-  std::function<void()> async_stop_closure;
-};
-
-class MockDataSource : public perfetto::DataSource<MockDataSource> {
- public:
-  void OnSetup(const SetupArgs&) override;
-  void OnStart(const StartArgs&) override;
-  void OnStop(const StopArgs&) override;
-  TestDataSourceHandle* handle_ = nullptr;
-};
-
-class MockDataSource2 : public perfetto::DataSource<MockDataSource2> {
- public:
-  void OnSetup(const SetupArgs&) override {}
-  void OnStart(const StartArgs&) override {}
-  void OnStop(const StopArgs&) override {}
-};
-
-// Used to verify that track event data sources in different namespaces register
-// themselves correctly in the muxer.
-class MockTracingMuxer : public perfetto::internal::TracingMuxer {
- public:
-  struct DataSource {
-    const perfetto::DataSourceDescriptor dsd;
-    perfetto::internal::DataSourceStaticState* static_state;
-  };
-
-  MockTracingMuxer() : TracingMuxer(nullptr), prev_instance_(instance_) {
-    instance_ = this;
-  }
-  ~MockTracingMuxer() override { instance_ = prev_instance_; }
-
-  bool RegisterDataSource(
-      const perfetto::DataSourceDescriptor& dsd,
-      DataSourceFactory,
-      perfetto::internal::DataSourceStaticState* static_state) override {
-    data_sources.emplace_back(DataSource{dsd, static_state});
-    return true;
-  }
-
-  std::unique_ptr<perfetto::TraceWriterBase> CreateTraceWriter(
-      perfetto::internal::DataSourceState*,
-      perfetto::BufferExhaustedPolicy) override {
-    return nullptr;
-  }
-
-  void DestroyStoppedTraceWritersForCurrentThread() override {}
-
-  std::vector<DataSource> data_sources;
-
- private:
-  TracingMuxer* prev_instance_;
-};
-
-struct TestIncrementalState {
-  TestIncrementalState() { constructed = true; }
-  // Note: a virtual destructor is not required for incremental state.
-  ~TestIncrementalState() { destroyed = true; }
-
-  int count = 100;
-  static bool constructed;
-  static bool destroyed;
-};
-
-bool TestIncrementalState::constructed;
-bool TestIncrementalState::destroyed;
-
-struct TestIncrementalDataSourceTraits
-    : public perfetto::DefaultDataSourceTraits {
-  using IncrementalStateType = TestIncrementalState;
-};
-
-class TestIncrementalDataSource
-    : public perfetto::DataSource<TestIncrementalDataSource,
-                                  TestIncrementalDataSourceTraits> {
- public:
-  void OnSetup(const SetupArgs&) override {}
-  void OnStart(const StartArgs&) override {}
-  void OnStop(const StopArgs&) override {}
-};
-
-// A convenience wrapper around TracingSession that allows to do block on
-//
-struct TestTracingSessionHandle {
-  perfetto::TracingSession* get() { return session.get(); }
-  std::unique_ptr<perfetto::TracingSession> session;
-  WaitableTestEvent on_stop;
-};
-
-// -------------------------
-// Declaration of test class
-// -------------------------
-class PerfettoApiTest : public ::testing::Test {
- public:
-  static PerfettoApiTest* instance;
-
-  void SetUp() override {
-    instance = this;
-    // Perfetto can only be initialized once in a process.
-    static bool was_initialized;
-    if (!was_initialized) {
-      perfetto::TracingInitArgs args;
-      args.backends = perfetto::kInProcessBackend;
-      perfetto::Tracing::Initialize(args);
-      was_initialized = true;
-      RegisterDataSource<MockDataSource>("my_data_source");
-      perfetto::TrackEvent::Register();
-    }
-    // Make sure our data source always has a valid handle.
-    data_sources_["my_data_source"];
-  }
-
-  void TearDown() override { instance = nullptr; }
-
-  template <typename DataSourceType>
-  TestDataSourceHandle* RegisterDataSource(std::string name) {
-    EXPECT_EQ(data_sources_.count(name), 0u);
-    TestDataSourceHandle* handle = &data_sources_[name];
-    perfetto::DataSourceDescriptor dsd;
-    dsd.set_name(name);
-    DataSourceType::Register(dsd);
-    return handle;
-  }
-
-  TestTracingSessionHandle* NewTrace(const perfetto::TraceConfig& cfg,
-                                     int fd = -1) {
-    sessions_.emplace_back();
-    TestTracingSessionHandle* handle = &sessions_.back();
-    handle->session =
-        perfetto::Tracing::NewTrace(perfetto::BackendType::kInProcessBackend);
-    handle->session->SetOnStopCallback([handle] { handle->on_stop.Notify(); });
-    handle->session->Setup(cfg, fd);
-    return handle;
-  }
-
-  std::vector<std::string> ReadLogMessagesFromTrace(
-      perfetto::TracingSession* tracing_session) {
-    std::vector<char> raw_trace = tracing_session->ReadTraceBlocking();
-    EXPECT_GE(raw_trace.size(), 0u);
-
-    // Read back the trace, maintaining interning tables as we go.
-    std::vector<std::string> log_messages;
-    std::map<uint64_t, std::string> log_message_bodies;
-    std::map<uint64_t, perfetto::protos::SourceLocation> source_locations;
-    perfetto::protos::Trace parsed_trace;
-    EXPECT_TRUE(
-        parsed_trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
-
-    for (const auto& packet : parsed_trace.packet()) {
-      if (!packet.has_track_event())
-        continue;
-
-      if (packet.has_interned_data()) {
-        const auto& interned_data = packet.interned_data();
-        for (const auto& it : interned_data.log_message_body()) {
-          EXPECT_GE(it.iid(), 1u);
-          EXPECT_EQ(log_message_bodies.find(it.iid()),
-                    log_message_bodies.end());
-          log_message_bodies[it.iid()] = it.body();
-        }
-        for (const auto& it : interned_data.source_locations()) {
-          EXPECT_GE(it.iid(), 1u);
-          EXPECT_EQ(source_locations.find(it.iid()), source_locations.end());
-          source_locations[it.iid()] = it;
-        }
-      }
-      const auto& track_event = packet.track_event();
-      if (track_event.type() != perfetto::protos::TrackEvent::TYPE_SLICE_BEGIN)
-        continue;
-
-      EXPECT_TRUE(track_event.has_log_message());
-      const auto& log = track_event.log_message();
-      if (log.source_location_iid()) {
-        std::stringstream msg;
-        const auto& source_location =
-            source_locations[log.source_location_iid()];
-        msg << source_location.function_name() << "("
-            << source_location.file_name() << ":"
-            << source_location.line_number()
-            << "): " << log_message_bodies[log.body_iid()];
-        log_messages.emplace_back(msg.str());
-      } else {
-        log_messages.emplace_back(log_message_bodies[log.body_iid()]);
-      }
-    }
-    return log_messages;
-  }
-
-  std::map<std::string, TestDataSourceHandle> data_sources_;
-  std::list<TestTracingSessionHandle> sessions_;  // Needs stable pointers.
-};
-
-// ---------------------------------------------
-// Definitions for non-inlineable helper methods
-// ---------------------------------------------
-PerfettoApiTest* PerfettoApiTest::instance;
-
-void MockDataSource::OnSetup(const SetupArgs& args) {
-  EXPECT_EQ(handle_, nullptr);
-  auto it = PerfettoApiTest::instance->data_sources_.find(args.config->name());
-
-  // We should not see an OnSetup for a data source that we didn't register
-  // before via PerfettoApiTest::RegisterDataSource().
-  EXPECT_NE(it, PerfettoApiTest::instance->data_sources_.end());
-  handle_ = &it->second;
-  handle_->config = *args.config;  // Deliberate copy.
-  handle_->on_setup.Notify();
-}
-
-void MockDataSource::OnStart(const StartArgs&) {
-  EXPECT_NE(handle_, nullptr);
-  if (handle_->on_start_callback)
-    handle_->on_start_callback();
-  handle_->on_start.Notify();
-}
-
-void MockDataSource::OnStop(const StopArgs& args) {
-  EXPECT_NE(handle_, nullptr);
-  if (handle_->handle_stop_asynchronously)
-    handle_->async_stop_closure = args.HandleStopAsynchronously();
-  if (handle_->on_stop_callback)
-    handle_->on_stop_callback();
-  handle_->on_stop.Notify();
-}
-
-// -------------
-// Test fixtures
-// -------------
-
-TEST_F(PerfettoApiTest, TrackEventStartStopAndDestroy) {
-  // This test used to cause a use after free as the tracing session got
-  // destroyed. It needed to be run approximately 2000 times to catch it so test
-  // with --gtest_repeat=3000 (less if running under GDB).
-
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("track_event");
-  ds_cfg->set_legacy_config("test");
-  // Create five new trace sessions.
-  std::vector<std::unique_ptr<perfetto::TracingSession>> sessions;
-  for (size_t i = 0; i < 5; ++i) {
-    sessions.push_back(
-        perfetto::Tracing::NewTrace(perfetto::BackendType::kInProcessBackend));
-    sessions[i]->Setup(cfg);
-    sessions[i]->Start();
-    sessions[i]->Stop();
-  }
-}
-
-TEST_F(PerfettoApiTest, TrackEventStartStopAndStopBlocking) {
-  // This test used to cause a deadlock (due to StopBlocking() after the session
-  // already stopped). This usually occurred within 1 or 2 runs of the test so
-  // use --gtest_repeat=10
-
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("track_event");
-  ds_cfg->set_legacy_config("test");
-  // Create five new trace sessions.
-  std::vector<std::unique_ptr<perfetto::TracingSession>> sessions;
-  for (size_t i = 0; i < 5; ++i) {
-    sessions.push_back(
-        perfetto::Tracing::NewTrace(perfetto::BackendType::kInProcessBackend));
-    sessions[i]->Setup(cfg);
-    sessions[i]->Start();
-    sessions[i]->Stop();
-  }
-  for (auto& session : sessions) {
-    session->StopBlocking();
-  }
-}
-
-TEST_F(PerfettoApiTest, TrackEvent) {
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("track_event");
-  ds_cfg->set_legacy_config("test");
-
-  // Create a new trace session.
-  auto* tracing_session = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-
-  // Emit one complete track event.
-  TRACE_EVENT_BEGIN("test", "TestEvent");
-  TRACE_EVENT_END("test");
-  perfetto::TrackEvent::Flush();
-
-  tracing_session->on_stop.Wait();
-  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-  ASSERT_GE(raw_trace.size(), 0u);
-
-  // Read back the trace, maintaining interning tables as we go.
-  perfetto::protos::Trace trace;
-  std::map<uint64_t, std::string> categories;
-  std::map<uint64_t, std::string> event_names;
-  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
-
-  bool incremental_state_was_cleared = false;
-  bool begin_found = false;
-  bool end_found = false;
-  bool process_descriptor_found = false;
-  bool thread_descriptor_found = false;
-  auto now = perfetto::test::GetWallTimeNs();
-  uint32_t sequence_id = 0;
-  int32_t cur_pid = perfetto::test::GetCurrentProcessId();
-  for (const auto& packet : trace.packet()) {
-    if (packet.has_process_descriptor()) {
-      EXPECT_FALSE(process_descriptor_found);
-      const auto& pd = packet.process_descriptor();
-      EXPECT_EQ(cur_pid, pd.pid());
-      process_descriptor_found = true;
-    }
-    if (packet.has_thread_descriptor()) {
-      EXPECT_FALSE(thread_descriptor_found);
-      const auto& td = packet.thread_descriptor();
-      EXPECT_EQ(cur_pid, td.pid());
-      EXPECT_NE(0, td.tid());
-      thread_descriptor_found = true;
-    }
-    if (packet.incremental_state_cleared()) {
-      incremental_state_was_cleared = true;
-      categories.clear();
-      event_names.clear();
-    }
-
-    if (!packet.has_track_event())
-      continue;
-    const auto& track_event = packet.track_event();
-
-    // Make sure we only see track events on one sequence.
-    if (packet.trusted_packet_sequence_id()) {
-      if (!sequence_id)
-        sequence_id = packet.trusted_packet_sequence_id();
-      EXPECT_EQ(sequence_id, packet.trusted_packet_sequence_id());
-    }
-
-    // Update incremental state.
-    if (packet.has_interned_data()) {
-      const auto& interned_data = packet.interned_data();
-      for (const auto& it : interned_data.event_categories()) {
-        EXPECT_EQ(categories.find(it.iid()), categories.end());
-        categories[it.iid()] = it.name();
-      }
-      for (const auto& it : interned_data.event_names()) {
-        EXPECT_EQ(event_names.find(it.iid()), event_names.end());
-        event_names[it.iid()] = it.name();
-      }
-    }
-
-    EXPECT_GT(packet.timestamp(), 0u);
-    EXPECT_LE(packet.timestamp(), now);
-    EXPECT_EQ(track_event.category_iids().size(), 1);
-    EXPECT_GE(track_event.category_iids().Get(0), 1u);
-
-    if (track_event.type() == perfetto::protos::TrackEvent::TYPE_SLICE_BEGIN) {
-      EXPECT_FALSE(begin_found);
-      EXPECT_EQ("test", categories[track_event.category_iids().Get(0)]);
-      EXPECT_EQ("TestEvent", event_names[track_event.name_iid()]);
-      begin_found = true;
-    } else if (track_event.type() ==
-               perfetto::protos::TrackEvent::TYPE_SLICE_END) {
-      EXPECT_FALSE(end_found);
-      EXPECT_EQ(0u, track_event.name_iid());
-      EXPECT_EQ("test", categories[track_event.category_iids().Get(0)]);
-      end_found = true;
-    }
-  }
-  EXPECT_TRUE(incremental_state_was_cleared);
-  EXPECT_TRUE(process_descriptor_found);
-  EXPECT_TRUE(thread_descriptor_found);
-  EXPECT_TRUE(begin_found);
-  EXPECT_TRUE(end_found);
-}
-
-TEST_F(PerfettoApiTest, TrackEventCategories) {
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("track_event");
-  ds_cfg->set_legacy_config("bar");
-
-  // Create a new trace session.
-  auto* tracing_session = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-
-  // Emit some track events.
-  TRACE_EVENT_BEGIN("foo", "NotEnabled");
-  TRACE_EVENT_END("foo");
-  TRACE_EVENT_BEGIN("bar", "Enabled");
-  TRACE_EVENT_END("bar");
-
-  tracing_session->get()->StopBlocking();
-  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-  std::string trace(raw_trace.data(), raw_trace.size());
-  // TODO(skyostil): Come up with a nicer way to verify trace contents.
-  EXPECT_THAT(trace, HasSubstr("Enabled"));
-  EXPECT_THAT(trace, Not(HasSubstr("NotEnabled")));
-}
-
-TEST_F(PerfettoApiTest, TrackEventRegistrationWithModule) {
-  MockTracingMuxer muxer;
-
-  // Each track event namespace registers its own data source.
-  perfetto::TrackEvent::Register();
-  EXPECT_EQ(1u, muxer.data_sources.size());
-
-  tracing_module::InitializeCategories();
-  EXPECT_EQ(2u, muxer.data_sources.size());
-
-  // Both data sources have the same name but distinct static data (i.e.,
-  // individual instance states).
-  EXPECT_EQ("track_event", muxer.data_sources[0].dsd.name());
-  EXPECT_EQ("track_event", muxer.data_sources[1].dsd.name());
-  EXPECT_NE(muxer.data_sources[0].static_state,
-            muxer.data_sources[1].static_state);
-}
-
-TEST_F(PerfettoApiTest, TrackEventSharedIncrementalState) {
-  tracing_module::InitializeCategories();
-
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  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 = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-
-  perfetto::internal::TrackEventIncrementalState* main_state = nullptr;
-  perfetto::TrackEvent::Trace(
-      [&main_state](perfetto::TrackEvent::TraceContext ctx) {
-        main_state = ctx.GetIncrementalState();
-      });
-  perfetto::internal::TrackEventIncrementalState* module_state =
-      tracing_module::GetIncrementalState();
-
-  // Both track event data sources should use the same incremental state (thanks
-  // to sharing TLS).
-  EXPECT_NE(nullptr, main_state);
-  EXPECT_EQ(main_state, module_state);
-  tracing_session->get()->StopBlocking();
-}
-
-TEST_F(PerfettoApiTest, TrackEventCategoriesWithModule) {
-  // Check that categories defined in two different category registries are
-  // enabled and disabled correctly.
-  tracing_module::InitializeCategories();
-
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("track_event");
-
-  // Only the "foo" category is enabled. It also exists both locally and in the
-  // existing module.
-  ds_cfg->set_legacy_config("foo");
-
-  // Create a new trace session.
-  auto* tracing_session = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-
-  // Emit some track events locally and from the test module.
-  TRACE_EVENT_BEGIN("foo", "FooEventFromMain");
-  TRACE_EVENT_END("foo");
-  tracing_module::EmitTrackEvents();
-  tracing_module::EmitTrackEvents2();
-  TRACE_EVENT_BEGIN("bar", "DisabledEventFromMain");
-  TRACE_EVENT_END("bar");
-
-  tracing_session->get()->StopBlocking();
-  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-  std::string trace(raw_trace.data(), raw_trace.size());
-  EXPECT_THAT(trace, HasSubstr("FooEventFromMain"));
-  EXPECT_THAT(trace, Not(HasSubstr("DisabledEventFromMain")));
-  EXPECT_THAT(trace, HasSubstr("FooEventFromModule"));
-  EXPECT_THAT(trace, Not(HasSubstr("DisabledEventFromModule")));
-  EXPECT_THAT(trace, HasSubstr("FooEventFromModule2"));
-  EXPECT_THAT(trace, Not(HasSubstr("DisabledEventFromModule2")));
-
-  perfetto::protos::Trace parsed_trace;
-  ASSERT_TRUE(
-      parsed_trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
-
-  uint32_t sequence_id = 0;
-  for (const auto& packet : parsed_trace.packet()) {
-    if (!packet.has_track_event())
-      continue;
-
-    // Make sure we only see track events on one sequence. This means all track
-    // event modules are sharing the same trace writer (by using the same TLS
-    // index).
-    if (packet.trusted_packet_sequence_id()) {
-      if (!sequence_id)
-        sequence_id = packet.trusted_packet_sequence_id();
-      EXPECT_EQ(sequence_id, packet.trusted_packet_sequence_id());
-    }
-  }
-}
-
-TEST_F(PerfettoApiTest, TrackEventConcurrentSessions) {
-  // Check that categories that are enabled and disabled in two parallel tracing
-  // sessions don't interfere.
-
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("track_event");
-
-  // Session #1 enables the "foo" category.
-  ds_cfg->set_legacy_config("foo");
-  auto* tracing_session = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-
-  // Session #2 enables the "bar" category.
-  ds_cfg->set_legacy_config("bar");
-  auto* tracing_session2 = NewTrace(cfg);
-  tracing_session2->get()->StartBlocking();
-
-  // Emit some track events under both categories.
-  TRACE_EVENT_BEGIN("foo", "Session1_First");
-  TRACE_EVENT_END("foo");
-  TRACE_EVENT_BEGIN("bar", "Session2_First");
-  TRACE_EVENT_END("bar");
-
-  tracing_session->get()->StopBlocking();
-  TRACE_EVENT_BEGIN("foo", "Session1_Second");
-  TRACE_EVENT_END("foo");
-  TRACE_EVENT_BEGIN("bar", "Session2_Second");
-  TRACE_EVENT_END("bar");
-
-  tracing_session2->get()->StopBlocking();
-  TRACE_EVENT_BEGIN("foo", "Session1_Third");
-  TRACE_EVENT_END("foo");
-  TRACE_EVENT_BEGIN("bar", "Session2_Third");
-  TRACE_EVENT_END("bar");
-
-  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-  std::string trace(raw_trace.data(), raw_trace.size());
-  EXPECT_THAT(trace, HasSubstr("Session1_First"));
-  EXPECT_THAT(trace, Not(HasSubstr("Session1_Second")));
-  EXPECT_THAT(trace, Not(HasSubstr("Session1_Third")));
-  EXPECT_THAT(trace, Not(HasSubstr("Session2_First")));
-  EXPECT_THAT(trace, Not(HasSubstr("Session2_Second")));
-  EXPECT_THAT(trace, Not(HasSubstr("Session2_Third")));
-
-  std::vector<char> raw_trace2 = tracing_session2->get()->ReadTraceBlocking();
-  std::string trace2(raw_trace2.data(), raw_trace2.size());
-  EXPECT_THAT(trace2, Not(HasSubstr("Session1_First")));
-  EXPECT_THAT(trace2, Not(HasSubstr("Session1_Second")));
-  EXPECT_THAT(trace2, Not(HasSubstr("Session1_Third")));
-  EXPECT_THAT(trace2, HasSubstr("Session2_First"));
-  EXPECT_THAT(trace2, HasSubstr("Session2_Second"));
-  EXPECT_THAT(trace2, Not(HasSubstr("Session2_Third")));
-}
-
-TEST_F(PerfettoApiTest, TrackEventTypedArgs) {
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("track_event");
-  ds_cfg->set_legacy_config("foo");
-
-  // Create a new trace session.
-  auto* tracing_session = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-
-  auto random_value = random();
-  TRACE_EVENT_BEGIN("foo", "EventWithTypedArg",
-                    [random_value](perfetto::TrackEventContext ctx) {
-                      auto* log = ctx.track_event()->set_log_message();
-                      log->set_source_location_iid(1);
-                      log->set_body_iid(2);
-                      auto* dbg = ctx.track_event()->add_debug_annotations();
-                      dbg->set_name("random");
-                      dbg->set_int_value(random_value);
-                    });
-  TRACE_EVENT_END("foo");
-
-  tracing_session->get()->StopBlocking();
-  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-  std::string trace(raw_trace.data(), raw_trace.size());
-
-  perfetto::protos::Trace parsed_trace;
-  ASSERT_TRUE(
-      parsed_trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
-
-  bool found_args = false;
-  for (const auto& packet : parsed_trace.packet()) {
-    if (!packet.has_track_event())
-      continue;
-    const auto& track_event = packet.track_event();
-    if (track_event.type() != perfetto::protos::TrackEvent::TYPE_SLICE_BEGIN)
-      continue;
-
-    EXPECT_TRUE(track_event.has_log_message());
-    const auto& log = track_event.log_message();
-    EXPECT_EQ(1u, log.source_location_iid());
-    EXPECT_EQ(2u, log.body_iid());
-
-    const auto& dbg = track_event.debug_annotations().Get(0);
-    EXPECT_EQ("random", dbg.name());
-    EXPECT_EQ(random_value, dbg.int_value());
-
-    found_args = true;
-  }
-  EXPECT_TRUE(found_args);
-}
-
-struct InternedLogMessageBody
-    : public perfetto::TrackEventInternedDataIndex<
-          InternedLogMessageBody,
-          perfetto::protos::pbzero::InternedData::kLogMessageBodyFieldNumber,
-          std::string> {
-  static void Add(perfetto::protos::pbzero::InternedData* interned_data,
-                  size_t iid,
-                  const std::string& value) {
-    auto l = interned_data->add_log_message_body();
-    l->set_iid(iid);
-    l->set_body(value.data(), value.size());
-    commit_count++;
-  }
-
-  static int commit_count;
-};
-
-int InternedLogMessageBody::commit_count = 0;
-
-TEST_F(PerfettoApiTest, TrackEventTypedArgsWithInterning) {
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("track_event");
-  ds_cfg->set_legacy_config("foo");
-
-  // Create a new trace session.
-  auto* tracing_session = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-
-  std::stringstream large_message;
-  for (size_t i = 0; i < 512; i++)
-    large_message << i << ". Something wicked this way comes. ";
-
-  size_t body_iid;
-  InternedLogMessageBody::commit_count = 0;
-  TRACE_EVENT_BEGIN(
-      "foo", "EventWithState", [&](perfetto::TrackEventContext ctx) {
-        EXPECT_EQ(0, InternedLogMessageBody::commit_count);
-        body_iid = InternedLogMessageBody::Get(&ctx, "Alas, poor Yorick!");
-        auto log = ctx.track_event()->set_log_message();
-        log->set_body_iid(body_iid);
-        EXPECT_EQ(1, InternedLogMessageBody::commit_count);
-
-        auto body_iid2 =
-            InternedLogMessageBody::Get(&ctx, "Alas, poor Yorick!");
-        EXPECT_EQ(body_iid, body_iid2);
-        EXPECT_EQ(1, InternedLogMessageBody::commit_count);
-      });
-  TRACE_EVENT_END("foo");
-
-  TRACE_EVENT_BEGIN(
-      "foo", "EventWithState", [&](perfetto::TrackEventContext ctx) {
-        // Check that very large amounts of interned data works.
-        auto log = ctx.track_event()->set_log_message();
-        log->set_body_iid(
-            InternedLogMessageBody::Get(&ctx, large_message.str()));
-        EXPECT_EQ(2, InternedLogMessageBody::commit_count);
-      });
-  TRACE_EVENT_END("foo");
-
-  // Make sure interned data persists across trace points.
-  TRACE_EVENT_BEGIN(
-      "foo", "EventWithState", [&](perfetto::TrackEventContext ctx) {
-        auto body_iid2 =
-            InternedLogMessageBody::Get(&ctx, "Alas, poor Yorick!");
-        EXPECT_EQ(body_iid, body_iid2);
-
-        auto body_iid3 =
-            InternedLogMessageBody::Get(&ctx, "I knew him, Horatio");
-        EXPECT_NE(body_iid, body_iid3);
-        auto log = ctx.track_event()->set_log_message();
-        log->set_body_iid(body_iid3);
-        EXPECT_EQ(3, InternedLogMessageBody::commit_count);
-      });
-  TRACE_EVENT_END("foo");
-
-  tracing_session->get()->StopBlocking();
-  auto log_messages = ReadLogMessagesFromTrace(tracing_session->get());
-  EXPECT_THAT(log_messages,
-              ElementsAre("Alas, poor Yorick!", large_message.str(),
-                          "I knew him, Horatio"));
-}
-
-struct InternedLogMessageBodySmall
-    : public perfetto::TrackEventInternedDataIndex<
-          InternedLogMessageBodySmall,
-          perfetto::protos::pbzero::InternedData::kLogMessageBodyFieldNumber,
-          const char*,
-          perfetto::SmallInternedDataTraits> {
-  static void Add(perfetto::protos::pbzero::InternedData* interned_data,
-                  size_t iid,
-                  const char* value) {
-    auto l = interned_data->add_log_message_body();
-    l->set_iid(iid);
-    l->set_body(value);
-  }
-};
-
-TEST_F(PerfettoApiTest, TrackEventTypedArgsWithInterningByValue) {
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("track_event");
-  ds_cfg->set_legacy_config("foo");
-
-  // Create a new trace session.
-  auto* tracing_session = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-
-  size_t body_iid;
-  TRACE_EVENT_BEGIN(
-      "foo", "EventWithState", [&](perfetto::TrackEventContext ctx) {
-        body_iid = InternedLogMessageBodySmall::Get(&ctx, "This above all:");
-        auto log = ctx.track_event()->set_log_message();
-        log->set_body_iid(body_iid);
-
-        auto body_iid2 =
-            InternedLogMessageBodySmall::Get(&ctx, "This above all:");
-        EXPECT_EQ(body_iid, body_iid2);
-
-        auto body_iid3 =
-            InternedLogMessageBodySmall::Get(&ctx, "to thine own self be true");
-        EXPECT_NE(body_iid, body_iid3);
-      });
-  TRACE_EVENT_END("foo");
-
-  tracing_session->get()->StopBlocking();
-  auto log_messages = ReadLogMessagesFromTrace(tracing_session->get());
-  EXPECT_THAT(log_messages, ElementsAre("This above all:"));
-}
-
-struct InternedLogMessageBodyHashed
-    : public perfetto::TrackEventInternedDataIndex<
-          InternedLogMessageBodyHashed,
-          perfetto::protos::pbzero::InternedData::kLogMessageBodyFieldNumber,
-          std::string,
-          perfetto::HashedInternedDataTraits> {
-  static void Add(perfetto::protos::pbzero::InternedData* interned_data,
-                  size_t iid,
-                  const std::string& value) {
-    auto l = interned_data->add_log_message_body();
-    l->set_iid(iid);
-    l->set_body(value.data(), value.size());
-  }
-};
-
-TEST_F(PerfettoApiTest, TrackEventTypedArgsWithInterningByHashing) {
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("track_event");
-  ds_cfg->set_legacy_config("foo");
-
-  // Create a new trace session.
-  auto* tracing_session = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-
-  size_t body_iid;
-  TRACE_EVENT_BEGIN(
-      "foo", "EventWithState", [&](perfetto::TrackEventContext ctx) {
-        // Test using a dynamically created interned value.
-        body_iid = InternedLogMessageBodyHashed::Get(
-            &ctx, std::string("Though this ") + "be madness,");
-        auto log = ctx.track_event()->set_log_message();
-        log->set_body_iid(body_iid);
-
-        auto body_iid2 =
-            InternedLogMessageBodyHashed::Get(&ctx, "Though this be madness,");
-        EXPECT_EQ(body_iid, body_iid2);
-
-        auto body_iid3 =
-            InternedLogMessageBodyHashed::Get(&ctx, "yet there is method in’t");
-        EXPECT_NE(body_iid, body_iid3);
-      });
-  TRACE_EVENT_END("foo");
-
-  tracing_session->get()->StopBlocking();
-  auto log_messages = ReadLogMessagesFromTrace(tracing_session->get());
-  EXPECT_THAT(log_messages, ElementsAre("Though this be madness,"));
-}
-
-struct InternedSourceLocation
-    : public perfetto::TrackEventInternedDataIndex<
-          InternedSourceLocation,
-          perfetto::protos::pbzero::InternedData::kSourceLocationsFieldNumber,
-          SourceLocation> {
-  static void Add(perfetto::protos::pbzero::InternedData* interned_data,
-                  size_t iid,
-                  const SourceLocation& value) {
-    auto l = interned_data->add_source_locations();
-    auto file_name = std::get<0>(value);
-    auto function_name = std::get<1>(value);
-    auto line_number = std::get<2>(value);
-    l->set_iid(iid);
-    l->set_file_name(file_name);
-    l->set_function_name(function_name);
-    l->set_line_number(line_number);
-  }
-};
-
-TEST_F(PerfettoApiTest, TrackEventTypedArgsWithInterningComplexValue) {
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("track_event");
-  ds_cfg->set_legacy_config("foo");
-
-  // Create a new trace session.
-  auto* tracing_session = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-
-  TRACE_EVENT_BEGIN(
-      "foo", "EventWithState", [&](perfetto::TrackEventContext ctx) {
-        const SourceLocation location{"file.cc", "SomeFunction", 123};
-        auto location_iid = InternedSourceLocation::Get(&ctx, location);
-        auto body_iid =
-            InternedLogMessageBody::Get(&ctx, "To be, or not to be");
-        auto log = ctx.track_event()->set_log_message();
-        log->set_source_location_iid(location_iid);
-        log->set_body_iid(body_iid);
-
-        auto location_iid2 = InternedSourceLocation::Get(&ctx, location);
-        EXPECT_EQ(location_iid, location_iid2);
-
-        const SourceLocation location2{"file.cc", "SomeFunction", 456};
-        auto location_iid3 = InternedSourceLocation::Get(&ctx, location2);
-        EXPECT_NE(location_iid, location_iid3);
-      });
-  TRACE_EVENT_END("foo");
-
-  tracing_session->get()->StopBlocking();
-  auto log_messages = ReadLogMessagesFromTrace(tracing_session->get());
-  EXPECT_THAT(log_messages,
-              ElementsAre("SomeFunction(file.cc:123): To be, or not to be"));
-}
-
-TEST_F(PerfettoApiTest, OneDataSourceOneEvent) {
-  auto* data_source = &data_sources_["my_data_source"];
-
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("my_data_source");
-  ds_cfg->set_legacy_config("test config");
-
-  // Create a new trace session.
-  auto* tracing_session = NewTrace(cfg);
-
-  MockDataSource::Trace([](MockDataSource::TraceContext) {
-    FAIL() << "Should not be called because the trace was not started";
-  });
-  MockDataSource::CallIfEnabled([](uint32_t) {
-    FAIL() << "Should not be called because the trace was not started";
-  });
-
-  tracing_session->get()->Start();
-  data_source->on_setup.Wait();
-  EXPECT_EQ(data_source->config.legacy_config(), "test config");
-  data_source->on_start.Wait();
-
-  // Emit one trace event.
-  std::atomic<int> trace_lambda_calls{0};
-  MockDataSource::Trace(
-      [&trace_lambda_calls](MockDataSource::TraceContext ctx) {
-        auto packet = ctx.NewTracePacket();
-        packet->set_timestamp(42);
-        packet->set_for_testing()->set_str("event 1");
-        trace_lambda_calls++;
-        packet->Finalize();
-
-        // The SMB scraping logic will skip the last packet because it cannot
-        // guarantee it's finalized. Create an empty packet so we get the
-        // previous one and this empty one is ignored.
-        packet = ctx.NewTracePacket();
-      });
-
-  uint32_t active_instances = 0;
-  MockDataSource::CallIfEnabled([&active_instances](uint32_t instances) {
-    active_instances = instances;
-  });
-  EXPECT_EQ(1u, active_instances);
-
-  data_source->on_stop.Wait();
-  tracing_session->on_stop.Wait();
-  EXPECT_EQ(trace_lambda_calls, 1);
-
-  MockDataSource::Trace([](MockDataSource::TraceContext) {
-    FAIL() << "Should not be called because the trace is now stopped";
-  });
-  MockDataSource::CallIfEnabled([](uint32_t) {
-    FAIL() << "Should not be called because the trace is now stopped";
-  });
-
-  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-  ASSERT_GE(raw_trace.size(), 0u);
-
-  perfetto::protos::Trace trace;
-  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
-  bool test_packet_found = false;
-  for (const auto& packet : trace.packet()) {
-    if (!packet.has_for_testing())
-      continue;
-    EXPECT_FALSE(test_packet_found);
-    EXPECT_EQ(packet.timestamp(), 42U);
-    EXPECT_EQ(packet.for_testing().str(), "event 1");
-    test_packet_found = true;
-  }
-  EXPECT_TRUE(test_packet_found);
-}
-
-TEST_F(PerfettoApiTest, BlockingStartAndStop) {
-  auto* data_source = &data_sources_["my_data_source"];
-
-  // Register a second data source to get a bit more coverage.
-  perfetto::DataSourceDescriptor dsd;
-  dsd.set_name("my_data_source2");
-  MockDataSource2::Register(dsd);
-
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("my_data_source");
-  ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("my_data_source2");
-
-  // Create a new trace session.
-  auto* tracing_session = NewTrace(cfg);
-
-  tracing_session->get()->StartBlocking();
-  EXPECT_TRUE(data_source->on_setup.notified());
-  EXPECT_TRUE(data_source->on_start.notified());
-
-  tracing_session->get()->StopBlocking();
-  EXPECT_TRUE(data_source->on_stop.notified());
-  EXPECT_TRUE(tracing_session->on_stop.notified());
-}
-
-TEST_F(PerfettoApiTest, BlockingStartAndStopOnEmptySession) {
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("non_existent_data_source");
-
-  // Create a new trace session.
-  auto* tracing_session = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-  tracing_session->get()->StopBlocking();
-  EXPECT_TRUE(tracing_session->on_stop.notified());
-}
-
-TEST_F(PerfettoApiTest, WriteEventsAfterDeferredStop) {
-  auto* data_source = &data_sources_["my_data_source"];
-  data_source->handle_stop_asynchronously = true;
-
-  // Setup the trace config and start the tracing session.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("my_data_source");
-  auto* tracing_session = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-
-  // Stop and wait for the producer to have seen the stop event.
-  WaitableTestEvent consumer_stop_signal;
-  tracing_session->get()->SetOnStopCallback(
-      [&consumer_stop_signal] { consumer_stop_signal.Notify(); });
-  tracing_session->get()->Stop();
-  data_source->on_stop.Wait();
-
-  // At this point tracing should be still allowed because of the
-  // HandleStopAsynchronously() call.
-  bool lambda_called = false;
-
-  // This usleep is here just to prevent that we accidentally pass the test
-  // just by virtue of hitting some race. We should be able to trace up until
-  // 5 seconds after seeing the stop when using the deferred stop mechanism.
-  usleep(250 * 1000);
-
-  MockDataSource::Trace([&lambda_called](MockDataSource::TraceContext ctx) {
-    auto packet = ctx.NewTracePacket();
-    packet->set_for_testing()->set_str("event written after OnStop");
-    packet->Finalize();
-    ctx.Flush();
-    lambda_called = true;
-  });
-  ASSERT_TRUE(lambda_called);
-
-  // Now call the async stop closure. This acks the stop to the service and
-  // disallows further Trace() calls.
-  EXPECT_TRUE(data_source->async_stop_closure);
-  data_source->async_stop_closure();
-
-  // Wait that the stop is propagated to the consumer.
-  consumer_stop_signal.Wait();
-
-  MockDataSource::Trace([](MockDataSource::TraceContext) {
-    FAIL() << "Should not be called after the stop is acked";
-  });
-
-  // Check the contents of the trace.
-  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-  ASSERT_GE(raw_trace.size(), 0u);
-  perfetto::protos::Trace trace;
-  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
-  int test_packet_found = 0;
-  for (const auto& packet : trace.packet()) {
-    if (!packet.has_for_testing())
-      continue;
-    EXPECT_EQ(packet.for_testing().str(), "event written after OnStop");
-    test_packet_found++;
-  }
-  EXPECT_EQ(test_packet_found, 1);
-}
-
-TEST_F(PerfettoApiTest, RepeatedStartAndStop) {
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("my_data_source");
-
-  for (int i = 0; i < 5; i++) {
-    auto* tracing_session = NewTrace(cfg);
-    tracing_session->get()->Start();
-    std::atomic<bool> stop_called{false};
-    tracing_session->get()->SetOnStopCallback(
-        [&stop_called] { stop_called = true; });
-    tracing_session->get()->StopBlocking();
-    EXPECT_TRUE(stop_called);
-  }
-}
-
-TEST_F(PerfettoApiTest, SetupWithFile) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  char temp_file[] = "/data/local/tmp/perfetto-XXXXXXXX";
-#else
-  char temp_file[] = "/tmp/perfetto-XXXXXXXX";
-#endif
-  int fd = mkstemp(temp_file);
-  ASSERT_TRUE(fd >= 0);
-
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("my_data_source");
-  // Write a trace into |fd|.
-  auto* tracing_session = NewTrace(cfg, fd);
-  tracing_session->get()->StartBlocking();
-  tracing_session->get()->StopBlocking();
-  // Check that |fd| didn't get closed.
-  EXPECT_EQ(0, fcntl(fd, F_GETFD, 0));
-  // Check that the trace got written.
-  EXPECT_GT(lseek(fd, 0, SEEK_END), 0);
-  EXPECT_EQ(0, close(fd));
-  // Clean up.
-  EXPECT_EQ(0, unlink(temp_file));
-}
-
-TEST_F(PerfettoApiTest, MultipleRegistrations) {
-  // Attempt to register the same data source again.
-  perfetto::DataSourceDescriptor dsd;
-  dsd.set_name("my_data_source");
-  EXPECT_TRUE(MockDataSource::Register(dsd));
-
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("my_data_source");
-
-  // Create a new trace session.
-  auto* tracing_session = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-
-  // Emit one trace event.
-  std::atomic<int> trace_lambda_calls{0};
-  MockDataSource::Trace([&trace_lambda_calls](MockDataSource::TraceContext) {
-    trace_lambda_calls++;
-  });
-
-  // Make sure the data source got called only once.
-  tracing_session->get()->StopBlocking();
-  EXPECT_EQ(trace_lambda_calls, 1);
-}
-
-TEST_F(PerfettoApiTest, CustomIncrementalState) {
-  perfetto::DataSourceDescriptor dsd;
-  dsd.set_name("incr_data_source");
-  TestIncrementalDataSource::Register(dsd);
-
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(500);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("incr_data_source");
-
-  // Create a new trace session.
-  auto* tracing_session = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-
-  // First emit a no-op trace event that initializes the incremental state as a
-  // side effect.
-  TestIncrementalDataSource::Trace(
-      [](TestIncrementalDataSource::TraceContext) {});
-  EXPECT_TRUE(TestIncrementalState::constructed);
-
-  // Check that the incremental state is carried across trace events.
-  TestIncrementalDataSource::Trace(
-      [](TestIncrementalDataSource::TraceContext ctx) {
-        auto* state = ctx.GetIncrementalState();
-        EXPECT_TRUE(state);
-        EXPECT_EQ(100, state->count);
-        state->count++;
-      });
-
-  TestIncrementalDataSource::Trace(
-      [](TestIncrementalDataSource::TraceContext ctx) {
-        auto* state = ctx.GetIncrementalState();
-        EXPECT_EQ(101, state->count);
-      });
-
-  // Make sure the incremental state gets cleaned up between sessions.
-  tracing_session->get()->StopBlocking();
-  tracing_session = NewTrace(cfg);
-  tracing_session->get()->StartBlocking();
-  TestIncrementalDataSource::Trace(
-      [](TestIncrementalDataSource::TraceContext ctx) {
-        auto* state = ctx.GetIncrementalState();
-        EXPECT_TRUE(TestIncrementalState::destroyed);
-        EXPECT_TRUE(state);
-        EXPECT_EQ(100, state->count);
-      });
-  tracing_session->get()->StopBlocking();
-}
-
-// Regression test for b/139110180. Checks that GetDataSourceLocked() can be
-// called from OnStart() and OnStop() callbacks without deadlocking.
-TEST_F(PerfettoApiTest, GetDataSourceLockedFromCallbacks) {
-  auto* data_source = &data_sources_["my_data_source"];
-
-  // Setup the trace config.
-  perfetto::TraceConfig cfg;
-  cfg.set_duration_ms(1);
-  cfg.add_buffers()->set_size_kb(1024);
-  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
-  ds_cfg->set_name("my_data_source");
-
-  // Create a new trace session.
-  auto* tracing_session = NewTrace(cfg);
-
-  data_source->on_start_callback = [] {
-    MockDataSource::Trace([](MockDataSource::TraceContext ctx) {
-      ctx.NewTracePacket()->set_for_testing()->set_str("on-start");
-      auto ds = ctx.GetDataSourceLocked();
-      ASSERT_TRUE(!!ds);
-      ctx.NewTracePacket()->set_for_testing()->set_str("on-start-locked");
-    });
-  };
-
-  data_source->on_stop_callback = [] {
-    MockDataSource::Trace([](MockDataSource::TraceContext ctx) {
-      ctx.NewTracePacket()->set_for_testing()->set_str("on-stop");
-      auto ds = ctx.GetDataSourceLocked();
-      ASSERT_TRUE(!!ds);
-      ctx.NewTracePacket()->set_for_testing()->set_str("on-stop-locked");
-      ctx.Flush();
-    });
-  };
-
-  tracing_session->get()->Start();
-  data_source->on_stop.Wait();
-  tracing_session->on_stop.Wait();
-
-  std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
-  ASSERT_GE(raw_trace.size(), 0u);
-
-  perfetto::protos::Trace trace;
-  ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
-  int packets_found = 0;
-  for (const auto& packet : trace.packet()) {
-    if (!packet.has_for_testing())
-      continue;
-    packets_found |= packet.for_testing().str() == "on-start" ? 1 : 0;
-    packets_found |= packet.for_testing().str() == "on-start-locked" ? 2 : 0;
-    packets_found |= packet.for_testing().str() == "on-stop" ? 4 : 0;
-    packets_found |= packet.for_testing().str() == "on-stop-locked" ? 8 : 0;
-  }
-  EXPECT_EQ(packets_found, 1 | 2 | 4 | 8);
-}
-
-}  // namespace
-
-PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(MockDataSource);
-PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(MockDataSource2);
-PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(TestIncrementalDataSource,
-                                           TestIncrementalDataSourceTraits);
diff --git a/src/tracing/core/android_log_config.cc b/src/tracing/core/android_log_config.cc
new file mode 100644
index 0000000..2a4fc63
--- /dev/null
+++ b/src/tracing/core/android_log_config.cc
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/android/android_log_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/android_log_config.h"
+
+#include "perfetto/common/android_log_constants.pb.h"
+#include "perfetto/config/android/android_log_config.pb.h"
+
+namespace perfetto {
+
+AndroidLogConfig::AndroidLogConfig() = default;
+AndroidLogConfig::~AndroidLogConfig() = default;
+AndroidLogConfig::AndroidLogConfig(const AndroidLogConfig&) = default;
+AndroidLogConfig& AndroidLogConfig::operator=(const AndroidLogConfig&) =
+    default;
+AndroidLogConfig::AndroidLogConfig(AndroidLogConfig&&) noexcept = default;
+AndroidLogConfig& AndroidLogConfig::operator=(AndroidLogConfig&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool AndroidLogConfig::operator==(const AndroidLogConfig& other) const {
+  return (log_ids_ == other.log_ids_) && (min_prio_ == other.min_prio_) &&
+         (filter_tags_ == other.filter_tags_);
+}
+#pragma GCC diagnostic pop
+
+void AndroidLogConfig::FromProto(
+    const perfetto::protos::AndroidLogConfig& proto) {
+  log_ids_.clear();
+  for (const auto& field : proto.log_ids()) {
+    log_ids_.emplace_back();
+    static_assert(sizeof(log_ids_.back()) == sizeof(proto.log_ids(0)),
+                  "size mismatch");
+    log_ids_.back() = static_cast<decltype(log_ids_)::value_type>(field);
+  }
+
+  static_assert(sizeof(min_prio_) == sizeof(proto.min_prio()), "size mismatch");
+  min_prio_ = static_cast<decltype(min_prio_)>(proto.min_prio());
+
+  filter_tags_.clear();
+  for (const auto& field : proto.filter_tags()) {
+    filter_tags_.emplace_back();
+    static_assert(sizeof(filter_tags_.back()) == sizeof(proto.filter_tags(0)),
+                  "size mismatch");
+    filter_tags_.back() =
+        static_cast<decltype(filter_tags_)::value_type>(field);
+  }
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void AndroidLogConfig::ToProto(
+    perfetto::protos::AndroidLogConfig* proto) const {
+  proto->Clear();
+
+  for (const auto& it : log_ids_) {
+    proto->add_log_ids(static_cast<decltype(proto->log_ids(0))>(it));
+    static_assert(sizeof(it) == sizeof(proto->log_ids(0)), "size mismatch");
+  }
+
+  static_assert(sizeof(min_prio_) == sizeof(proto->min_prio()),
+                "size mismatch");
+  proto->set_min_prio(static_cast<decltype(proto->min_prio())>(min_prio_));
+
+  for (const auto& it : filter_tags_) {
+    proto->add_filter_tags(static_cast<decltype(proto->filter_tags(0))>(it));
+    static_assert(sizeof(it) == sizeof(proto->filter_tags(0)), "size mismatch");
+  }
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+}  // namespace perfetto
diff --git a/src/tracing/core/android_log_constants.cc b/src/tracing/core/android_log_constants.cc
new file mode 100644
index 0000000..b3e85f2
--- /dev/null
+++ b/src/tracing/core/android_log_constants.cc
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/common/android_log_constants.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/android_log_constants.h"
+
+#include "perfetto/common/android_log_constants.pb.h"
+
+namespace perfetto {}  // namespace perfetto
diff --git a/src/tracing/core/android_power_config.cc b/src/tracing/core/android_power_config.cc
new file mode 100644
index 0000000..c9723da
--- /dev/null
+++ b/src/tracing/core/android_power_config.cc
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/power/android_power_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/android_power_config.h"
+
+#include "perfetto/config/power/android_power_config.pb.h"
+
+namespace perfetto {
+
+AndroidPowerConfig::AndroidPowerConfig() = default;
+AndroidPowerConfig::~AndroidPowerConfig() = default;
+AndroidPowerConfig::AndroidPowerConfig(const AndroidPowerConfig&) = default;
+AndroidPowerConfig& AndroidPowerConfig::operator=(const AndroidPowerConfig&) =
+    default;
+AndroidPowerConfig::AndroidPowerConfig(AndroidPowerConfig&&) noexcept = default;
+AndroidPowerConfig& AndroidPowerConfig::operator=(AndroidPowerConfig&&) =
+    default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool AndroidPowerConfig::operator==(const AndroidPowerConfig& other) const {
+  return (battery_poll_ms_ == other.battery_poll_ms_) &&
+         (battery_counters_ == other.battery_counters_) &&
+         (collect_power_rails_ == other.collect_power_rails_);
+}
+#pragma GCC diagnostic pop
+
+void AndroidPowerConfig::FromProto(
+    const perfetto::protos::AndroidPowerConfig& proto) {
+  static_assert(sizeof(battery_poll_ms_) == sizeof(proto.battery_poll_ms()),
+                "size mismatch");
+  battery_poll_ms_ =
+      static_cast<decltype(battery_poll_ms_)>(proto.battery_poll_ms());
+
+  battery_counters_.clear();
+  for (const auto& field : proto.battery_counters()) {
+    battery_counters_.emplace_back();
+    static_assert(
+        sizeof(battery_counters_.back()) == sizeof(proto.battery_counters(0)),
+        "size mismatch");
+    battery_counters_.back() =
+        static_cast<decltype(battery_counters_)::value_type>(field);
+  }
+
+  static_assert(
+      sizeof(collect_power_rails_) == sizeof(proto.collect_power_rails()),
+      "size mismatch");
+  collect_power_rails_ =
+      static_cast<decltype(collect_power_rails_)>(proto.collect_power_rails());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void AndroidPowerConfig::ToProto(
+    perfetto::protos::AndroidPowerConfig* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(battery_poll_ms_) == sizeof(proto->battery_poll_ms()),
+                "size mismatch");
+  proto->set_battery_poll_ms(
+      static_cast<decltype(proto->battery_poll_ms())>(battery_poll_ms_));
+
+  for (const auto& it : battery_counters_) {
+    proto->add_battery_counters(
+        static_cast<decltype(proto->battery_counters(0))>(it));
+    static_assert(sizeof(it) == sizeof(proto->battery_counters(0)),
+                  "size mismatch");
+  }
+
+  static_assert(
+      sizeof(collect_power_rails_) == sizeof(proto->collect_power_rails()),
+      "size mismatch");
+  proto->set_collect_power_rails(
+      static_cast<decltype(proto->collect_power_rails())>(
+          collect_power_rails_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+}  // namespace perfetto
diff --git a/src/tracing/core/chrome_config.cc b/src/tracing/core/chrome_config.cc
new file mode 100644
index 0000000..eb989ed
--- /dev/null
+++ b/src/tracing/core/chrome_config.cc
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/chrome/chrome_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/chrome_config.h"
+
+#include "perfetto/config/chrome/chrome_config.pb.h"
+
+namespace perfetto {
+
+ChromeConfig::ChromeConfig() = default;
+ChromeConfig::~ChromeConfig() = default;
+ChromeConfig::ChromeConfig(const ChromeConfig&) = default;
+ChromeConfig& ChromeConfig::operator=(const ChromeConfig&) = default;
+ChromeConfig::ChromeConfig(ChromeConfig&&) noexcept = default;
+ChromeConfig& ChromeConfig::operator=(ChromeConfig&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool ChromeConfig::operator==(const ChromeConfig& other) const {
+  return (trace_config_ == other.trace_config_) &&
+         (privacy_filtering_enabled_ == other.privacy_filtering_enabled_);
+}
+#pragma GCC diagnostic pop
+
+void ChromeConfig::FromProto(const perfetto::protos::ChromeConfig& proto) {
+  static_assert(sizeof(trace_config_) == sizeof(proto.trace_config()),
+                "size mismatch");
+  trace_config_ = static_cast<decltype(trace_config_)>(proto.trace_config());
+
+  static_assert(sizeof(privacy_filtering_enabled_) ==
+                    sizeof(proto.privacy_filtering_enabled()),
+                "size mismatch");
+  privacy_filtering_enabled_ =
+      static_cast<decltype(privacy_filtering_enabled_)>(
+          proto.privacy_filtering_enabled());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void ChromeConfig::ToProto(perfetto::protos::ChromeConfig* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(trace_config_) == sizeof(proto->trace_config()),
+                "size mismatch");
+  proto->set_trace_config(
+      static_cast<decltype(proto->trace_config())>(trace_config_));
+
+  static_assert(sizeof(privacy_filtering_enabled_) ==
+                    sizeof(proto->privacy_filtering_enabled()),
+                "size mismatch");
+  proto->set_privacy_filtering_enabled(
+      static_cast<decltype(proto->privacy_filtering_enabled())>(
+          privacy_filtering_enabled_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+}  // namespace perfetto
diff --git a/src/tracing/core/commit_data_request.cc b/src/tracing/core/commit_data_request.cc
new file mode 100644
index 0000000..9899585
--- /dev/null
+++ b/src/tracing/core/commit_data_request.cc
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/common/commit_data_request.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/commit_data_request.h"
+
+#include "perfetto/common/commit_data_request.pb.h"
+
+namespace perfetto {
+
+CommitDataRequest::CommitDataRequest() = default;
+CommitDataRequest::~CommitDataRequest() = default;
+CommitDataRequest::CommitDataRequest(const CommitDataRequest&) = default;
+CommitDataRequest& CommitDataRequest::operator=(const CommitDataRequest&) =
+    default;
+CommitDataRequest::CommitDataRequest(CommitDataRequest&&) noexcept = default;
+CommitDataRequest& CommitDataRequest::operator=(CommitDataRequest&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool CommitDataRequest::operator==(const CommitDataRequest& other) const {
+  return (chunks_to_move_ == other.chunks_to_move_) &&
+         (chunks_to_patch_ == other.chunks_to_patch_) &&
+         (flush_request_id_ == other.flush_request_id_);
+}
+#pragma GCC diagnostic pop
+
+void CommitDataRequest::FromProto(
+    const perfetto::protos::CommitDataRequest& proto) {
+  chunks_to_move_.clear();
+  for (const auto& field : proto.chunks_to_move()) {
+    chunks_to_move_.emplace_back();
+    chunks_to_move_.back().FromProto(field);
+  }
+
+  chunks_to_patch_.clear();
+  for (const auto& field : proto.chunks_to_patch()) {
+    chunks_to_patch_.emplace_back();
+    chunks_to_patch_.back().FromProto(field);
+  }
+
+  static_assert(sizeof(flush_request_id_) == sizeof(proto.flush_request_id()),
+                "size mismatch");
+  flush_request_id_ =
+      static_cast<decltype(flush_request_id_)>(proto.flush_request_id());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void CommitDataRequest::ToProto(
+    perfetto::protos::CommitDataRequest* proto) const {
+  proto->Clear();
+
+  for (const auto& it : chunks_to_move_) {
+    auto* entry = proto->add_chunks_to_move();
+    it.ToProto(entry);
+  }
+
+  for (const auto& it : chunks_to_patch_) {
+    auto* entry = proto->add_chunks_to_patch();
+    it.ToProto(entry);
+  }
+
+  static_assert(sizeof(flush_request_id_) == sizeof(proto->flush_request_id()),
+                "size mismatch");
+  proto->set_flush_request_id(
+      static_cast<decltype(proto->flush_request_id())>(flush_request_id_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+CommitDataRequest::ChunksToMove::ChunksToMove() = default;
+CommitDataRequest::ChunksToMove::~ChunksToMove() = default;
+CommitDataRequest::ChunksToMove::ChunksToMove(
+    const CommitDataRequest::ChunksToMove&) = default;
+CommitDataRequest::ChunksToMove& CommitDataRequest::ChunksToMove::operator=(
+    const CommitDataRequest::ChunksToMove&) = default;
+CommitDataRequest::ChunksToMove::ChunksToMove(
+    CommitDataRequest::ChunksToMove&&) noexcept = default;
+CommitDataRequest::ChunksToMove& CommitDataRequest::ChunksToMove::operator=(
+    CommitDataRequest::ChunksToMove&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool CommitDataRequest::ChunksToMove::operator==(
+    const CommitDataRequest::ChunksToMove& other) const {
+  return (page_ == other.page_) && (chunk_ == other.chunk_) &&
+         (target_buffer_ == other.target_buffer_);
+}
+#pragma GCC diagnostic pop
+
+void CommitDataRequest::ChunksToMove::FromProto(
+    const perfetto::protos::CommitDataRequest_ChunksToMove& proto) {
+  static_assert(sizeof(page_) == sizeof(proto.page()), "size mismatch");
+  page_ = static_cast<decltype(page_)>(proto.page());
+
+  static_assert(sizeof(chunk_) == sizeof(proto.chunk()), "size mismatch");
+  chunk_ = static_cast<decltype(chunk_)>(proto.chunk());
+
+  static_assert(sizeof(target_buffer_) == sizeof(proto.target_buffer()),
+                "size mismatch");
+  target_buffer_ = static_cast<decltype(target_buffer_)>(proto.target_buffer());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void CommitDataRequest::ChunksToMove::ToProto(
+    perfetto::protos::CommitDataRequest_ChunksToMove* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(page_) == sizeof(proto->page()), "size mismatch");
+  proto->set_page(static_cast<decltype(proto->page())>(page_));
+
+  static_assert(sizeof(chunk_) == sizeof(proto->chunk()), "size mismatch");
+  proto->set_chunk(static_cast<decltype(proto->chunk())>(chunk_));
+
+  static_assert(sizeof(target_buffer_) == sizeof(proto->target_buffer()),
+                "size mismatch");
+  proto->set_target_buffer(
+      static_cast<decltype(proto->target_buffer())>(target_buffer_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+CommitDataRequest::ChunkToPatch::ChunkToPatch() = default;
+CommitDataRequest::ChunkToPatch::~ChunkToPatch() = default;
+CommitDataRequest::ChunkToPatch::ChunkToPatch(
+    const CommitDataRequest::ChunkToPatch&) = default;
+CommitDataRequest::ChunkToPatch& CommitDataRequest::ChunkToPatch::operator=(
+    const CommitDataRequest::ChunkToPatch&) = default;
+CommitDataRequest::ChunkToPatch::ChunkToPatch(
+    CommitDataRequest::ChunkToPatch&&) noexcept = default;
+CommitDataRequest::ChunkToPatch& CommitDataRequest::ChunkToPatch::operator=(
+    CommitDataRequest::ChunkToPatch&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool CommitDataRequest::ChunkToPatch::operator==(
+    const CommitDataRequest::ChunkToPatch& other) const {
+  return (target_buffer_ == other.target_buffer_) &&
+         (writer_id_ == other.writer_id_) && (chunk_id_ == other.chunk_id_) &&
+         (patches_ == other.patches_) &&
+         (has_more_patches_ == other.has_more_patches_);
+}
+#pragma GCC diagnostic pop
+
+void CommitDataRequest::ChunkToPatch::FromProto(
+    const perfetto::protos::CommitDataRequest_ChunkToPatch& proto) {
+  static_assert(sizeof(target_buffer_) == sizeof(proto.target_buffer()),
+                "size mismatch");
+  target_buffer_ = static_cast<decltype(target_buffer_)>(proto.target_buffer());
+
+  static_assert(sizeof(writer_id_) == sizeof(proto.writer_id()),
+                "size mismatch");
+  writer_id_ = static_cast<decltype(writer_id_)>(proto.writer_id());
+
+  static_assert(sizeof(chunk_id_) == sizeof(proto.chunk_id()), "size mismatch");
+  chunk_id_ = static_cast<decltype(chunk_id_)>(proto.chunk_id());
+
+  patches_.clear();
+  for (const auto& field : proto.patches()) {
+    patches_.emplace_back();
+    patches_.back().FromProto(field);
+  }
+
+  static_assert(sizeof(has_more_patches_) == sizeof(proto.has_more_patches()),
+                "size mismatch");
+  has_more_patches_ =
+      static_cast<decltype(has_more_patches_)>(proto.has_more_patches());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void CommitDataRequest::ChunkToPatch::ToProto(
+    perfetto::protos::CommitDataRequest_ChunkToPatch* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(target_buffer_) == sizeof(proto->target_buffer()),
+                "size mismatch");
+  proto->set_target_buffer(
+      static_cast<decltype(proto->target_buffer())>(target_buffer_));
+
+  static_assert(sizeof(writer_id_) == sizeof(proto->writer_id()),
+                "size mismatch");
+  proto->set_writer_id(static_cast<decltype(proto->writer_id())>(writer_id_));
+
+  static_assert(sizeof(chunk_id_) == sizeof(proto->chunk_id()),
+                "size mismatch");
+  proto->set_chunk_id(static_cast<decltype(proto->chunk_id())>(chunk_id_));
+
+  for (const auto& it : patches_) {
+    auto* entry = proto->add_patches();
+    it.ToProto(entry);
+  }
+
+  static_assert(sizeof(has_more_patches_) == sizeof(proto->has_more_patches()),
+                "size mismatch");
+  proto->set_has_more_patches(
+      static_cast<decltype(proto->has_more_patches())>(has_more_patches_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+CommitDataRequest::ChunkToPatch::Patch::Patch() = default;
+CommitDataRequest::ChunkToPatch::Patch::~Patch() = default;
+CommitDataRequest::ChunkToPatch::Patch::Patch(
+    const CommitDataRequest::ChunkToPatch::Patch&) = default;
+CommitDataRequest::ChunkToPatch::Patch& CommitDataRequest::ChunkToPatch::Patch::
+operator=(const CommitDataRequest::ChunkToPatch::Patch&) = default;
+CommitDataRequest::ChunkToPatch::Patch::Patch(
+    CommitDataRequest::ChunkToPatch::Patch&&) noexcept = default;
+CommitDataRequest::ChunkToPatch::Patch& CommitDataRequest::ChunkToPatch::Patch::
+operator=(CommitDataRequest::ChunkToPatch::Patch&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool CommitDataRequest::ChunkToPatch::Patch::operator==(
+    const CommitDataRequest::ChunkToPatch::Patch& other) const {
+  return (offset_ == other.offset_) && (data_ == other.data_);
+}
+#pragma GCC diagnostic pop
+
+void CommitDataRequest::ChunkToPatch::Patch::FromProto(
+    const perfetto::protos::CommitDataRequest_ChunkToPatch_Patch& proto) {
+  static_assert(sizeof(offset_) == sizeof(proto.offset()), "size mismatch");
+  offset_ = static_cast<decltype(offset_)>(proto.offset());
+
+  static_assert(sizeof(data_) == sizeof(proto.data()), "size mismatch");
+  data_ = static_cast<decltype(data_)>(proto.data());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void CommitDataRequest::ChunkToPatch::Patch::ToProto(
+    perfetto::protos::CommitDataRequest_ChunkToPatch_Patch* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(offset_) == sizeof(proto->offset()), "size mismatch");
+  proto->set_offset(static_cast<decltype(proto->offset())>(offset_));
+
+  static_assert(sizeof(data_) == sizeof(proto->data()), "size mismatch");
+  proto->set_data(static_cast<decltype(proto->data())>(data_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+}  // namespace perfetto
diff --git a/src/tracing/core/data_source_config.cc b/src/tracing/core/data_source_config.cc
new file mode 100644
index 0000000..eaed73a
--- /dev/null
+++ b/src/tracing/core/data_source_config.cc
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/data_source_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/data_source_config.h"
+
+#include "perfetto/config/android/android_log_config.pb.h"
+#include "perfetto/config/android/packages_list_config.pb.h"
+#include "perfetto/config/chrome/chrome_config.pb.h"
+#include "perfetto/config/data_source_config.pb.h"
+#include "perfetto/config/ftrace/ftrace_config.pb.h"
+#include "perfetto/config/inode_file/inode_file_config.pb.h"
+#include "perfetto/config/power/android_power_config.pb.h"
+#include "perfetto/config/process_stats/process_stats_config.pb.h"
+#include "perfetto/config/profiling/heapprofd_config.pb.h"
+#include "perfetto/config/sys_stats/sys_stats_config.pb.h"
+#include "perfetto/config/test_config.pb.h"
+
+namespace perfetto {
+
+DataSourceConfig::DataSourceConfig() = default;
+DataSourceConfig::~DataSourceConfig() = default;
+DataSourceConfig::DataSourceConfig(const DataSourceConfig&) = default;
+DataSourceConfig& DataSourceConfig::operator=(const DataSourceConfig&) =
+    default;
+DataSourceConfig::DataSourceConfig(DataSourceConfig&&) noexcept = default;
+DataSourceConfig& DataSourceConfig::operator=(DataSourceConfig&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool DataSourceConfig::operator==(const DataSourceConfig& other) const {
+  return (name_ == other.name_) && (target_buffer_ == other.target_buffer_) &&
+         (trace_duration_ms_ == other.trace_duration_ms_) &&
+         (enable_extra_guardrails_ == other.enable_extra_guardrails_) &&
+         (tracing_session_id_ == other.tracing_session_id_) &&
+         (ftrace_config_ == other.ftrace_config_) &&
+         (chrome_config_ == other.chrome_config_) &&
+         (inode_file_config_ == other.inode_file_config_) &&
+         (process_stats_config_ == other.process_stats_config_) &&
+         (sys_stats_config_ == other.sys_stats_config_) &&
+         (heapprofd_config_ == other.heapprofd_config_) &&
+         (android_power_config_ == other.android_power_config_) &&
+         (android_log_config_ == other.android_log_config_) &&
+         (packages_list_config_ == other.packages_list_config_) &&
+         (legacy_config_ == other.legacy_config_) &&
+         (for_testing_ == other.for_testing_);
+}
+#pragma GCC diagnostic pop
+
+void DataSourceConfig::FromProto(
+    const perfetto::protos::DataSourceConfig& proto) {
+  static_assert(sizeof(name_) == sizeof(proto.name()), "size mismatch");
+  name_ = static_cast<decltype(name_)>(proto.name());
+
+  static_assert(sizeof(target_buffer_) == sizeof(proto.target_buffer()),
+                "size mismatch");
+  target_buffer_ = static_cast<decltype(target_buffer_)>(proto.target_buffer());
+
+  static_assert(sizeof(trace_duration_ms_) == sizeof(proto.trace_duration_ms()),
+                "size mismatch");
+  trace_duration_ms_ =
+      static_cast<decltype(trace_duration_ms_)>(proto.trace_duration_ms());
+
+  static_assert(sizeof(enable_extra_guardrails_) ==
+                    sizeof(proto.enable_extra_guardrails()),
+                "size mismatch");
+  enable_extra_guardrails_ = static_cast<decltype(enable_extra_guardrails_)>(
+      proto.enable_extra_guardrails());
+
+  static_assert(
+      sizeof(tracing_session_id_) == sizeof(proto.tracing_session_id()),
+      "size mismatch");
+  tracing_session_id_ =
+      static_cast<decltype(tracing_session_id_)>(proto.tracing_session_id());
+
+  ftrace_config_.FromProto(proto.ftrace_config());
+
+  chrome_config_.FromProto(proto.chrome_config());
+
+  inode_file_config_.FromProto(proto.inode_file_config());
+
+  process_stats_config_.FromProto(proto.process_stats_config());
+
+  sys_stats_config_.FromProto(proto.sys_stats_config());
+
+  heapprofd_config_.FromProto(proto.heapprofd_config());
+
+  android_power_config_.FromProto(proto.android_power_config());
+
+  android_log_config_.FromProto(proto.android_log_config());
+
+  packages_list_config_.FromProto(proto.packages_list_config());
+
+  static_assert(sizeof(legacy_config_) == sizeof(proto.legacy_config()),
+                "size mismatch");
+  legacy_config_ = static_cast<decltype(legacy_config_)>(proto.legacy_config());
+
+  for_testing_.FromProto(proto.for_testing());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void DataSourceConfig::ToProto(
+    perfetto::protos::DataSourceConfig* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(name_) == sizeof(proto->name()), "size mismatch");
+  proto->set_name(static_cast<decltype(proto->name())>(name_));
+
+  static_assert(sizeof(target_buffer_) == sizeof(proto->target_buffer()),
+                "size mismatch");
+  proto->set_target_buffer(
+      static_cast<decltype(proto->target_buffer())>(target_buffer_));
+
+  static_assert(
+      sizeof(trace_duration_ms_) == sizeof(proto->trace_duration_ms()),
+      "size mismatch");
+  proto->set_trace_duration_ms(
+      static_cast<decltype(proto->trace_duration_ms())>(trace_duration_ms_));
+
+  static_assert(sizeof(enable_extra_guardrails_) ==
+                    sizeof(proto->enable_extra_guardrails()),
+                "size mismatch");
+  proto->set_enable_extra_guardrails(
+      static_cast<decltype(proto->enable_extra_guardrails())>(
+          enable_extra_guardrails_));
+
+  static_assert(
+      sizeof(tracing_session_id_) == sizeof(proto->tracing_session_id()),
+      "size mismatch");
+  proto->set_tracing_session_id(
+      static_cast<decltype(proto->tracing_session_id())>(tracing_session_id_));
+
+  ftrace_config_.ToProto(proto->mutable_ftrace_config());
+
+  chrome_config_.ToProto(proto->mutable_chrome_config());
+
+  inode_file_config_.ToProto(proto->mutable_inode_file_config());
+
+  process_stats_config_.ToProto(proto->mutable_process_stats_config());
+
+  sys_stats_config_.ToProto(proto->mutable_sys_stats_config());
+
+  heapprofd_config_.ToProto(proto->mutable_heapprofd_config());
+
+  android_power_config_.ToProto(proto->mutable_android_power_config());
+
+  android_log_config_.ToProto(proto->mutable_android_log_config());
+
+  packages_list_config_.ToProto(proto->mutable_packages_list_config());
+
+  static_assert(sizeof(legacy_config_) == sizeof(proto->legacy_config()),
+                "size mismatch");
+  proto->set_legacy_config(
+      static_cast<decltype(proto->legacy_config())>(legacy_config_));
+
+  for_testing_.ToProto(proto->mutable_for_testing());
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+}  // namespace perfetto
diff --git a/src/tracing/core/data_source_descriptor.cc b/src/tracing/core/data_source_descriptor.cc
new file mode 100644
index 0000000..015c590
--- /dev/null
+++ b/src/tracing/core/data_source_descriptor.cc
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/common/data_source_descriptor.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/data_source_descriptor.h"
+
+#include "perfetto/common/data_source_descriptor.pb.h"
+
+namespace perfetto {
+
+DataSourceDescriptor::DataSourceDescriptor() = default;
+DataSourceDescriptor::~DataSourceDescriptor() = default;
+DataSourceDescriptor::DataSourceDescriptor(const DataSourceDescriptor&) =
+    default;
+DataSourceDescriptor& DataSourceDescriptor::operator=(
+    const DataSourceDescriptor&) = default;
+DataSourceDescriptor::DataSourceDescriptor(DataSourceDescriptor&&) noexcept =
+    default;
+DataSourceDescriptor& DataSourceDescriptor::operator=(DataSourceDescriptor&&) =
+    default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool DataSourceDescriptor::operator==(const DataSourceDescriptor& other) const {
+  return (name_ == other.name_) &&
+         (will_notify_on_stop_ == other.will_notify_on_stop_) &&
+         (will_notify_on_start_ == other.will_notify_on_start_) &&
+         (handles_incremental_state_clear_ ==
+          other.handles_incremental_state_clear_);
+}
+#pragma GCC diagnostic pop
+
+void DataSourceDescriptor::FromProto(
+    const perfetto::protos::DataSourceDescriptor& proto) {
+  static_assert(sizeof(name_) == sizeof(proto.name()), "size mismatch");
+  name_ = static_cast<decltype(name_)>(proto.name());
+
+  static_assert(
+      sizeof(will_notify_on_stop_) == sizeof(proto.will_notify_on_stop()),
+      "size mismatch");
+  will_notify_on_stop_ =
+      static_cast<decltype(will_notify_on_stop_)>(proto.will_notify_on_stop());
+
+  static_assert(
+      sizeof(will_notify_on_start_) == sizeof(proto.will_notify_on_start()),
+      "size mismatch");
+  will_notify_on_start_ = static_cast<decltype(will_notify_on_start_)>(
+      proto.will_notify_on_start());
+
+  static_assert(sizeof(handles_incremental_state_clear_) ==
+                    sizeof(proto.handles_incremental_state_clear()),
+                "size mismatch");
+  handles_incremental_state_clear_ =
+      static_cast<decltype(handles_incremental_state_clear_)>(
+          proto.handles_incremental_state_clear());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void DataSourceDescriptor::ToProto(
+    perfetto::protos::DataSourceDescriptor* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(name_) == sizeof(proto->name()), "size mismatch");
+  proto->set_name(static_cast<decltype(proto->name())>(name_));
+
+  static_assert(
+      sizeof(will_notify_on_stop_) == sizeof(proto->will_notify_on_stop()),
+      "size mismatch");
+  proto->set_will_notify_on_stop(
+      static_cast<decltype(proto->will_notify_on_stop())>(
+          will_notify_on_stop_));
+
+  static_assert(
+      sizeof(will_notify_on_start_) == sizeof(proto->will_notify_on_start()),
+      "size mismatch");
+  proto->set_will_notify_on_start(
+      static_cast<decltype(proto->will_notify_on_start())>(
+          will_notify_on_start_));
+
+  static_assert(sizeof(handles_incremental_state_clear_) ==
+                    sizeof(proto->handles_incremental_state_clear()),
+                "size mismatch");
+  proto->set_handles_incremental_state_clear(
+      static_cast<decltype(proto->handles_incremental_state_clear())>(
+          handles_incremental_state_clear_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+}  // namespace perfetto
diff --git a/src/tracing/core/ftrace_config.cc b/src/tracing/core/ftrace_config.cc
new file mode 100644
index 0000000..532f2f3
--- /dev/null
+++ b/src/tracing/core/ftrace_config.cc
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/ftrace/ftrace_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/ftrace_config.h"
+
+#include "perfetto/config/ftrace/ftrace_config.pb.h"
+
+namespace perfetto {
+
+FtraceConfig::FtraceConfig() = default;
+FtraceConfig::~FtraceConfig() = default;
+FtraceConfig::FtraceConfig(const FtraceConfig&) = default;
+FtraceConfig& FtraceConfig::operator=(const FtraceConfig&) = default;
+FtraceConfig::FtraceConfig(FtraceConfig&&) noexcept = default;
+FtraceConfig& FtraceConfig::operator=(FtraceConfig&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool FtraceConfig::operator==(const FtraceConfig& other) const {
+  return (ftrace_events_ == other.ftrace_events_) &&
+         (atrace_categories_ == other.atrace_categories_) &&
+         (atrace_apps_ == other.atrace_apps_) &&
+         (buffer_size_kb_ == other.buffer_size_kb_) &&
+         (drain_period_ms_ == other.drain_period_ms_);
+}
+#pragma GCC diagnostic pop
+
+void FtraceConfig::FromProto(const perfetto::protos::FtraceConfig& proto) {
+  ftrace_events_.clear();
+  for (const auto& field : proto.ftrace_events()) {
+    ftrace_events_.emplace_back();
+    static_assert(
+        sizeof(ftrace_events_.back()) == sizeof(proto.ftrace_events(0)),
+        "size mismatch");
+    ftrace_events_.back() =
+        static_cast<decltype(ftrace_events_)::value_type>(field);
+  }
+
+  atrace_categories_.clear();
+  for (const auto& field : proto.atrace_categories()) {
+    atrace_categories_.emplace_back();
+    static_assert(
+        sizeof(atrace_categories_.back()) == sizeof(proto.atrace_categories(0)),
+        "size mismatch");
+    atrace_categories_.back() =
+        static_cast<decltype(atrace_categories_)::value_type>(field);
+  }
+
+  atrace_apps_.clear();
+  for (const auto& field : proto.atrace_apps()) {
+    atrace_apps_.emplace_back();
+    static_assert(sizeof(atrace_apps_.back()) == sizeof(proto.atrace_apps(0)),
+                  "size mismatch");
+    atrace_apps_.back() =
+        static_cast<decltype(atrace_apps_)::value_type>(field);
+  }
+
+  static_assert(sizeof(buffer_size_kb_) == sizeof(proto.buffer_size_kb()),
+                "size mismatch");
+  buffer_size_kb_ =
+      static_cast<decltype(buffer_size_kb_)>(proto.buffer_size_kb());
+
+  static_assert(sizeof(drain_period_ms_) == sizeof(proto.drain_period_ms()),
+                "size mismatch");
+  drain_period_ms_ =
+      static_cast<decltype(drain_period_ms_)>(proto.drain_period_ms());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void FtraceConfig::ToProto(perfetto::protos::FtraceConfig* proto) const {
+  proto->Clear();
+
+  for (const auto& it : ftrace_events_) {
+    proto->add_ftrace_events(
+        static_cast<decltype(proto->ftrace_events(0))>(it));
+    static_assert(sizeof(it) == sizeof(proto->ftrace_events(0)),
+                  "size mismatch");
+  }
+
+  for (const auto& it : atrace_categories_) {
+    proto->add_atrace_categories(
+        static_cast<decltype(proto->atrace_categories(0))>(it));
+    static_assert(sizeof(it) == sizeof(proto->atrace_categories(0)),
+                  "size mismatch");
+  }
+
+  for (const auto& it : atrace_apps_) {
+    proto->add_atrace_apps(static_cast<decltype(proto->atrace_apps(0))>(it));
+    static_assert(sizeof(it) == sizeof(proto->atrace_apps(0)), "size mismatch");
+  }
+
+  static_assert(sizeof(buffer_size_kb_) == sizeof(proto->buffer_size_kb()),
+                "size mismatch");
+  proto->set_buffer_size_kb(
+      static_cast<decltype(proto->buffer_size_kb())>(buffer_size_kb_));
+
+  static_assert(sizeof(drain_period_ms_) == sizeof(proto->drain_period_ms()),
+                "size mismatch");
+  proto->set_drain_period_ms(
+      static_cast<decltype(proto->drain_period_ms())>(drain_period_ms_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+}  // namespace perfetto
diff --git a/src/tracing/core/heapprofd_config.cc b/src/tracing/core/heapprofd_config.cc
new file mode 100644
index 0000000..ec11d22
--- /dev/null
+++ b/src/tracing/core/heapprofd_config.cc
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/profiling/heapprofd_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/heapprofd_config.h"
+
+#include "perfetto/config/profiling/heapprofd_config.pb.h"
+
+namespace perfetto {
+
+HeapprofdConfig::HeapprofdConfig() = default;
+HeapprofdConfig::~HeapprofdConfig() = default;
+HeapprofdConfig::HeapprofdConfig(const HeapprofdConfig&) = default;
+HeapprofdConfig& HeapprofdConfig::operator=(const HeapprofdConfig&) = default;
+HeapprofdConfig::HeapprofdConfig(HeapprofdConfig&&) noexcept = default;
+HeapprofdConfig& HeapprofdConfig::operator=(HeapprofdConfig&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool HeapprofdConfig::operator==(const HeapprofdConfig& other) const {
+  return (sampling_interval_bytes_ == other.sampling_interval_bytes_) &&
+         (process_cmdline_ == other.process_cmdline_) && (pid_ == other.pid_) &&
+         (all_ == other.all_) &&
+         (skip_symbol_prefix_ == other.skip_symbol_prefix_) &&
+         (continuous_dump_config_ == other.continuous_dump_config_) &&
+         (shmem_size_bytes_ == other.shmem_size_bytes_) &&
+         (block_client_ == other.block_client_);
+}
+#pragma GCC diagnostic pop
+
+void HeapprofdConfig::FromProto(
+    const perfetto::protos::HeapprofdConfig& proto) {
+  static_assert(sizeof(sampling_interval_bytes_) ==
+                    sizeof(proto.sampling_interval_bytes()),
+                "size mismatch");
+  sampling_interval_bytes_ = static_cast<decltype(sampling_interval_bytes_)>(
+      proto.sampling_interval_bytes());
+
+  process_cmdline_.clear();
+  for (const auto& field : proto.process_cmdline()) {
+    process_cmdline_.emplace_back();
+    static_assert(
+        sizeof(process_cmdline_.back()) == sizeof(proto.process_cmdline(0)),
+        "size mismatch");
+    process_cmdline_.back() =
+        static_cast<decltype(process_cmdline_)::value_type>(field);
+  }
+
+  pid_.clear();
+  for (const auto& field : proto.pid()) {
+    pid_.emplace_back();
+    static_assert(sizeof(pid_.back()) == sizeof(proto.pid(0)), "size mismatch");
+    pid_.back() = static_cast<decltype(pid_)::value_type>(field);
+  }
+
+  static_assert(sizeof(all_) == sizeof(proto.all()), "size mismatch");
+  all_ = static_cast<decltype(all_)>(proto.all());
+
+  skip_symbol_prefix_.clear();
+  for (const auto& field : proto.skip_symbol_prefix()) {
+    skip_symbol_prefix_.emplace_back();
+    static_assert(sizeof(skip_symbol_prefix_.back()) ==
+                      sizeof(proto.skip_symbol_prefix(0)),
+                  "size mismatch");
+    skip_symbol_prefix_.back() =
+        static_cast<decltype(skip_symbol_prefix_)::value_type>(field);
+  }
+
+  continuous_dump_config_.FromProto(proto.continuous_dump_config());
+
+  static_assert(sizeof(shmem_size_bytes_) == sizeof(proto.shmem_size_bytes()),
+                "size mismatch");
+  shmem_size_bytes_ =
+      static_cast<decltype(shmem_size_bytes_)>(proto.shmem_size_bytes());
+
+  static_assert(sizeof(block_client_) == sizeof(proto.block_client()),
+                "size mismatch");
+  block_client_ = static_cast<decltype(block_client_)>(proto.block_client());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void HeapprofdConfig::ToProto(perfetto::protos::HeapprofdConfig* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(sampling_interval_bytes_) ==
+                    sizeof(proto->sampling_interval_bytes()),
+                "size mismatch");
+  proto->set_sampling_interval_bytes(
+      static_cast<decltype(proto->sampling_interval_bytes())>(
+          sampling_interval_bytes_));
+
+  for (const auto& it : process_cmdline_) {
+    proto->add_process_cmdline(
+        static_cast<decltype(proto->process_cmdline(0))>(it));
+    static_assert(sizeof(it) == sizeof(proto->process_cmdline(0)),
+                  "size mismatch");
+  }
+
+  for (const auto& it : pid_) {
+    proto->add_pid(static_cast<decltype(proto->pid(0))>(it));
+    static_assert(sizeof(it) == sizeof(proto->pid(0)), "size mismatch");
+  }
+
+  static_assert(sizeof(all_) == sizeof(proto->all()), "size mismatch");
+  proto->set_all(static_cast<decltype(proto->all())>(all_));
+
+  for (const auto& it : skip_symbol_prefix_) {
+    proto->add_skip_symbol_prefix(
+        static_cast<decltype(proto->skip_symbol_prefix(0))>(it));
+    static_assert(sizeof(it) == sizeof(proto->skip_symbol_prefix(0)),
+                  "size mismatch");
+  }
+
+  continuous_dump_config_.ToProto(proto->mutable_continuous_dump_config());
+
+  static_assert(sizeof(shmem_size_bytes_) == sizeof(proto->shmem_size_bytes()),
+                "size mismatch");
+  proto->set_shmem_size_bytes(
+      static_cast<decltype(proto->shmem_size_bytes())>(shmem_size_bytes_));
+
+  static_assert(sizeof(block_client_) == sizeof(proto->block_client()),
+                "size mismatch");
+  proto->set_block_client(
+      static_cast<decltype(proto->block_client())>(block_client_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+HeapprofdConfig::ContinuousDumpConfig::ContinuousDumpConfig() = default;
+HeapprofdConfig::ContinuousDumpConfig::~ContinuousDumpConfig() = default;
+HeapprofdConfig::ContinuousDumpConfig::ContinuousDumpConfig(
+    const HeapprofdConfig::ContinuousDumpConfig&) = default;
+HeapprofdConfig::ContinuousDumpConfig& HeapprofdConfig::ContinuousDumpConfig::
+operator=(const HeapprofdConfig::ContinuousDumpConfig&) = default;
+HeapprofdConfig::ContinuousDumpConfig::ContinuousDumpConfig(
+    HeapprofdConfig::ContinuousDumpConfig&&) noexcept = default;
+HeapprofdConfig::ContinuousDumpConfig& HeapprofdConfig::ContinuousDumpConfig::
+operator=(HeapprofdConfig::ContinuousDumpConfig&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool HeapprofdConfig::ContinuousDumpConfig::operator==(
+    const HeapprofdConfig::ContinuousDumpConfig& other) const {
+  return (dump_phase_ms_ == other.dump_phase_ms_) &&
+         (dump_interval_ms_ == other.dump_interval_ms_);
+}
+#pragma GCC diagnostic pop
+
+void HeapprofdConfig::ContinuousDumpConfig::FromProto(
+    const perfetto::protos::HeapprofdConfig_ContinuousDumpConfig& proto) {
+  static_assert(sizeof(dump_phase_ms_) == sizeof(proto.dump_phase_ms()),
+                "size mismatch");
+  dump_phase_ms_ = static_cast<decltype(dump_phase_ms_)>(proto.dump_phase_ms());
+
+  static_assert(sizeof(dump_interval_ms_) == sizeof(proto.dump_interval_ms()),
+                "size mismatch");
+  dump_interval_ms_ =
+      static_cast<decltype(dump_interval_ms_)>(proto.dump_interval_ms());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void HeapprofdConfig::ContinuousDumpConfig::ToProto(
+    perfetto::protos::HeapprofdConfig_ContinuousDumpConfig* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(dump_phase_ms_) == sizeof(proto->dump_phase_ms()),
+                "size mismatch");
+  proto->set_dump_phase_ms(
+      static_cast<decltype(proto->dump_phase_ms())>(dump_phase_ms_));
+
+  static_assert(sizeof(dump_interval_ms_) == sizeof(proto->dump_interval_ms()),
+                "size mismatch");
+  proto->set_dump_interval_ms(
+      static_cast<decltype(proto->dump_interval_ms())>(dump_interval_ms_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+}  // namespace perfetto
diff --git a/src/tracing/core/id_allocator_unittest.cc b/src/tracing/core/id_allocator_unittest.cc
index 4d557bb..53b8034 100644
--- a/src/tracing/core/id_allocator_unittest.cc
+++ b/src/tracing/core/id_allocator_unittest.cc
@@ -16,7 +16,7 @@
 
 #include "src/tracing/core/id_allocator.h"
 
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace {
diff --git a/src/tracing/core/inode_file_config.cc b/src/tracing/core/inode_file_config.cc
new file mode 100644
index 0000000..44e3439
--- /dev/null
+++ b/src/tracing/core/inode_file_config.cc
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/inode_file/inode_file_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/inode_file_config.h"
+
+#include "perfetto/config/inode_file/inode_file_config.pb.h"
+
+namespace perfetto {
+
+InodeFileConfig::InodeFileConfig() = default;
+InodeFileConfig::~InodeFileConfig() = default;
+InodeFileConfig::InodeFileConfig(const InodeFileConfig&) = default;
+InodeFileConfig& InodeFileConfig::operator=(const InodeFileConfig&) = default;
+InodeFileConfig::InodeFileConfig(InodeFileConfig&&) noexcept = default;
+InodeFileConfig& InodeFileConfig::operator=(InodeFileConfig&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool InodeFileConfig::operator==(const InodeFileConfig& other) const {
+  return (scan_interval_ms_ == other.scan_interval_ms_) &&
+         (scan_delay_ms_ == other.scan_delay_ms_) &&
+         (scan_batch_size_ == other.scan_batch_size_) &&
+         (do_not_scan_ == other.do_not_scan_) &&
+         (scan_mount_points_ == other.scan_mount_points_) &&
+         (mount_point_mapping_ == other.mount_point_mapping_);
+}
+#pragma GCC diagnostic pop
+
+void InodeFileConfig::FromProto(
+    const perfetto::protos::InodeFileConfig& proto) {
+  static_assert(sizeof(scan_interval_ms_) == sizeof(proto.scan_interval_ms()),
+                "size mismatch");
+  scan_interval_ms_ =
+      static_cast<decltype(scan_interval_ms_)>(proto.scan_interval_ms());
+
+  static_assert(sizeof(scan_delay_ms_) == sizeof(proto.scan_delay_ms()),
+                "size mismatch");
+  scan_delay_ms_ = static_cast<decltype(scan_delay_ms_)>(proto.scan_delay_ms());
+
+  static_assert(sizeof(scan_batch_size_) == sizeof(proto.scan_batch_size()),
+                "size mismatch");
+  scan_batch_size_ =
+      static_cast<decltype(scan_batch_size_)>(proto.scan_batch_size());
+
+  static_assert(sizeof(do_not_scan_) == sizeof(proto.do_not_scan()),
+                "size mismatch");
+  do_not_scan_ = static_cast<decltype(do_not_scan_)>(proto.do_not_scan());
+
+  scan_mount_points_.clear();
+  for (const auto& field : proto.scan_mount_points()) {
+    scan_mount_points_.emplace_back();
+    static_assert(
+        sizeof(scan_mount_points_.back()) == sizeof(proto.scan_mount_points(0)),
+        "size mismatch");
+    scan_mount_points_.back() =
+        static_cast<decltype(scan_mount_points_)::value_type>(field);
+  }
+
+  mount_point_mapping_.clear();
+  for (const auto& field : proto.mount_point_mapping()) {
+    mount_point_mapping_.emplace_back();
+    mount_point_mapping_.back().FromProto(field);
+  }
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void InodeFileConfig::ToProto(perfetto::protos::InodeFileConfig* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(scan_interval_ms_) == sizeof(proto->scan_interval_ms()),
+                "size mismatch");
+  proto->set_scan_interval_ms(
+      static_cast<decltype(proto->scan_interval_ms())>(scan_interval_ms_));
+
+  static_assert(sizeof(scan_delay_ms_) == sizeof(proto->scan_delay_ms()),
+                "size mismatch");
+  proto->set_scan_delay_ms(
+      static_cast<decltype(proto->scan_delay_ms())>(scan_delay_ms_));
+
+  static_assert(sizeof(scan_batch_size_) == sizeof(proto->scan_batch_size()),
+                "size mismatch");
+  proto->set_scan_batch_size(
+      static_cast<decltype(proto->scan_batch_size())>(scan_batch_size_));
+
+  static_assert(sizeof(do_not_scan_) == sizeof(proto->do_not_scan()),
+                "size mismatch");
+  proto->set_do_not_scan(
+      static_cast<decltype(proto->do_not_scan())>(do_not_scan_));
+
+  for (const auto& it : scan_mount_points_) {
+    proto->add_scan_mount_points(
+        static_cast<decltype(proto->scan_mount_points(0))>(it));
+    static_assert(sizeof(it) == sizeof(proto->scan_mount_points(0)),
+                  "size mismatch");
+  }
+
+  for (const auto& it : mount_point_mapping_) {
+    auto* entry = proto->add_mount_point_mapping();
+    it.ToProto(entry);
+  }
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+InodeFileConfig::MountPointMappingEntry::MountPointMappingEntry() = default;
+InodeFileConfig::MountPointMappingEntry::~MountPointMappingEntry() = default;
+InodeFileConfig::MountPointMappingEntry::MountPointMappingEntry(
+    const InodeFileConfig::MountPointMappingEntry&) = default;
+InodeFileConfig::MountPointMappingEntry&
+InodeFileConfig::MountPointMappingEntry::operator=(
+    const InodeFileConfig::MountPointMappingEntry&) = default;
+InodeFileConfig::MountPointMappingEntry::MountPointMappingEntry(
+    InodeFileConfig::MountPointMappingEntry&&) noexcept = default;
+InodeFileConfig::MountPointMappingEntry&
+InodeFileConfig::MountPointMappingEntry::operator=(
+    InodeFileConfig::MountPointMappingEntry&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool InodeFileConfig::MountPointMappingEntry::operator==(
+    const InodeFileConfig::MountPointMappingEntry& other) const {
+  return (mountpoint_ == other.mountpoint_) &&
+         (scan_roots_ == other.scan_roots_);
+}
+#pragma GCC diagnostic pop
+
+void InodeFileConfig::MountPointMappingEntry::FromProto(
+    const perfetto::protos::InodeFileConfig_MountPointMappingEntry& proto) {
+  static_assert(sizeof(mountpoint_) == sizeof(proto.mountpoint()),
+                "size mismatch");
+  mountpoint_ = static_cast<decltype(mountpoint_)>(proto.mountpoint());
+
+  scan_roots_.clear();
+  for (const auto& field : proto.scan_roots()) {
+    scan_roots_.emplace_back();
+    static_assert(sizeof(scan_roots_.back()) == sizeof(proto.scan_roots(0)),
+                  "size mismatch");
+    scan_roots_.back() = static_cast<decltype(scan_roots_)::value_type>(field);
+  }
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void InodeFileConfig::MountPointMappingEntry::ToProto(
+    perfetto::protos::InodeFileConfig_MountPointMappingEntry* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(mountpoint_) == sizeof(proto->mountpoint()),
+                "size mismatch");
+  proto->set_mountpoint(
+      static_cast<decltype(proto->mountpoint())>(mountpoint_));
+
+  for (const auto& it : scan_roots_) {
+    proto->add_scan_roots(static_cast<decltype(proto->scan_roots(0))>(it));
+    static_assert(sizeof(it) == sizeof(proto->scan_roots(0)), "size mismatch");
+  }
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+}  // namespace perfetto
diff --git a/src/tracing/core/metatrace_writer.cc b/src/tracing/core/metatrace_writer.cc
deleted file mode 100644
index f6acfa0..0000000
--- a/src/tracing/core/metatrace_writer.cc
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/tracing/core/metatrace_writer.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/base/task_runner.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "perfetto/tracing/core/data_source_descriptor.h"
-
-#include "protos/perfetto/trace/perfetto/perfetto_metatrace.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-namespace perfetto {
-
-// static
-constexpr char MetatraceWriter::kDataSourceName[];
-
-MetatraceWriter::MetatraceWriter() : weak_ptr_factory_(this) {}
-
-MetatraceWriter::~MetatraceWriter() {
-  Disable();
-}
-
-void MetatraceWriter::Enable(base::TaskRunner* task_runner,
-                             std::unique_ptr<TraceWriter> trace_writer,
-                             uint32_t tags) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  if (started_) {
-    PERFETTO_DFATAL_OR_ELOG("Metatrace already started from this instance");
-    return;
-  }
-  task_runner_ = task_runner;
-  trace_writer_ = std::move(trace_writer);
-  auto weak_ptr = weak_ptr_factory_.GetWeakPtr();
-  bool enabled = metatrace::Enable(
-      [weak_ptr] {
-        if (weak_ptr)
-          weak_ptr->WriteAllAvailableEvents();
-      },
-      task_runner, tags);
-  if (!enabled)
-    return;
-  started_ = true;
-}
-
-void MetatraceWriter::Disable() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  if (!started_)
-    return;
-  metatrace::Disable();
-  started_ = false;
-  trace_writer_.reset();
-}
-
-void MetatraceWriter::WriteAllAvailableEvents() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  if (!started_)
-    return;
-  for (auto it = metatrace::RingBuffer::GetReadIterator(); it; ++it) {
-    auto type_and_id = it->type_and_id.load(std::memory_order_acquire);
-    if (type_and_id == 0)
-      break;  // Stop at the first incomplete event.
-
-    auto packet = trace_writer_->NewTracePacket();
-    packet->set_timestamp(it->timestamp_ns());
-    auto* evt = packet->set_perfetto_metatrace();
-    uint16_t type = type_and_id & metatrace::Record::kTypeMask;
-    uint16_t id = type_and_id & ~metatrace::Record::kTypeMask;
-    if (type == metatrace::Record::kTypeCounter) {
-      evt->set_counter_id(id);
-      evt->set_counter_value(it->counter_value);
-    } else {
-      evt->set_event_id(id);
-      evt->set_event_duration_ns(it->duration_ns);
-    }
-
-    evt->set_thread_id(static_cast<uint32_t>(it->thread_id));
-
-    if (metatrace::RingBuffer::has_overruns())
-      evt->set_has_overruns(true);
-  }
-  // The |it| destructor will automatically update the read index position in
-  // the meta-trace ring buffer.
-}
-
-void MetatraceWriter::WriteAllAndFlushTraceWriter(
-    std::function<void()> callback) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  if (!started_)
-    return;
-  WriteAllAvailableEvents();
-  trace_writer_->Flush(std::move(callback));
-}
-
-}  // namespace perfetto
diff --git a/src/tracing/core/metatrace_writer.h b/src/tracing/core/metatrace_writer.h
deleted file mode 100644
index 2c06b24..0000000
--- a/src/tracing/core/metatrace_writer.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACING_CORE_METATRACE_WRITER_H_
-#define SRC_TRACING_CORE_METATRACE_WRITER_H_
-
-#include <functional>
-#include <memory>
-
-#include "perfetto/ext/base/metatrace.h"
-#include "perfetto/ext/base/thread_checker.h"
-#include "perfetto/ext/base/weak_ptr.h"
-
-namespace perfetto {
-
-namespace base {
-class TaskRunner;
-}
-
-class TraceWriter;
-
-// Complements the base::metatrace infrastructure.
-// It hooks a callback to metatrace::Enable() and writes metatrace events into
-// a TraceWriter whenever the metatrace ring buffer is half full.
-// It is safe to create and attempt to start multiple instances of this class,
-// however only the first one will succeed because the metatrace framework
-// doesn't support multiple instances.
-// This class is defined here (instead of directly in src/probes/) so it can
-// be reused by other components (e.g. heapprofd).
-class MetatraceWriter {
- public:
-  static constexpr char kDataSourceName[] = "perfetto.metatrace";
-
-  MetatraceWriter();
-  ~MetatraceWriter();
-
-  MetatraceWriter(const MetatraceWriter&) = delete;
-  MetatraceWriter& operator=(const MetatraceWriter&) = delete;
-  MetatraceWriter(MetatraceWriter&&) = delete;
-  MetatraceWriter& operator=(MetatraceWriter&&) = delete;
-
-  void Enable(base::TaskRunner*, std::unique_ptr<TraceWriter>, uint32_t tags);
-  void Disable();
-  void WriteAllAndFlushTraceWriter(std::function<void()> callback);
-
- private:
-  void WriteAllAvailableEvents();
-
-  bool started_ = false;
-  base::TaskRunner* task_runner_ = nullptr;
-  std::unique_ptr<TraceWriter> trace_writer_;
-  PERFETTO_THREAD_CHECKER(thread_checker_)
-  base::WeakPtrFactory<MetatraceWriter> weak_ptr_factory_;  // Keep last.
-};
-
-}  // namespace perfetto
-
-#endif  // SRC_TRACING_CORE_METATRACE_WRITER_H_
diff --git a/src/tracing/core/null_trace_writer.cc b/src/tracing/core/null_trace_writer.cc
index 40fe9a5..5ca2e71 100644
--- a/src/tracing/core/null_trace_writer.cc
+++ b/src/tracing/core/null_trace_writer.cc
@@ -17,11 +17,11 @@
 #include "src/tracing/core/null_trace_writer.h"
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/utils.h"
 
 #include "perfetto/protozero/message.h"
 
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
 
diff --git a/src/tracing/core/null_trace_writer.h b/src/tracing/core/null_trace_writer.h
index fabbca7..a6a81e2 100644
--- a/src/tracing/core/null_trace_writer.h
+++ b/src/tracing/core/null_trace_writer.h
@@ -17,9 +17,9 @@
 #ifndef SRC_TRACING_CORE_NULL_TRACE_WRITER_H_
 #define SRC_TRACING_CORE_NULL_TRACE_WRITER_H_
 
-#include "perfetto/ext/tracing/core/trace_writer.h"
 #include "perfetto/protozero/message_handle.h"
 #include "perfetto/protozero/scattered_stream_null_delegate.h"
+#include "perfetto/tracing/core/trace_writer.h"
 
 namespace perfetto {
 
diff --git a/src/tracing/core/null_trace_writer_unittest.cc b/src/tracing/core/null_trace_writer_unittest.cc
index 03374da..f2d2f54 100644
--- a/src/tracing/core/null_trace_writer_unittest.cc
+++ b/src/tracing/core/null_trace_writer_unittest.cc
@@ -16,12 +16,13 @@
 
 #include "src/tracing/core/null_trace_writer.h"
 
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/tracing/core/trace_writer.h"
 
-#include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/test_event.pbzero.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
 namespace {
diff --git a/src/tracing/core/observable_events.cc b/src/tracing/core/observable_events.cc
new file mode 100644
index 0000000..9c62124
--- /dev/null
+++ b/src/tracing/core/observable_events.cc
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/common/observable_events.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/observable_events.h"
+
+#include "perfetto/common/observable_events.pb.h"
+
+namespace perfetto {
+
+ObservableEvents::ObservableEvents() = default;
+ObservableEvents::~ObservableEvents() = default;
+ObservableEvents::ObservableEvents(const ObservableEvents&) = default;
+ObservableEvents& ObservableEvents::operator=(const ObservableEvents&) =
+    default;
+ObservableEvents::ObservableEvents(ObservableEvents&&) noexcept = default;
+ObservableEvents& ObservableEvents::operator=(ObservableEvents&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool ObservableEvents::operator==(const ObservableEvents& other) const {
+  return (instance_state_changes_ == other.instance_state_changes_);
+}
+#pragma GCC diagnostic pop
+
+void ObservableEvents::FromProto(
+    const perfetto::protos::ObservableEvents& proto) {
+  instance_state_changes_.clear();
+  for (const auto& field : proto.instance_state_changes()) {
+    instance_state_changes_.emplace_back();
+    instance_state_changes_.back().FromProto(field);
+  }
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void ObservableEvents::ToProto(
+    perfetto::protos::ObservableEvents* proto) const {
+  proto->Clear();
+
+  for (const auto& it : instance_state_changes_) {
+    auto* entry = proto->add_instance_state_changes();
+    it.ToProto(entry);
+  }
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+ObservableEvents::DataSourceInstanceStateChange::
+    DataSourceInstanceStateChange() = default;
+ObservableEvents::DataSourceInstanceStateChange::
+    ~DataSourceInstanceStateChange() = default;
+ObservableEvents::DataSourceInstanceStateChange::DataSourceInstanceStateChange(
+    const ObservableEvents::DataSourceInstanceStateChange&) = default;
+ObservableEvents::DataSourceInstanceStateChange&
+ObservableEvents::DataSourceInstanceStateChange::operator=(
+    const ObservableEvents::DataSourceInstanceStateChange&) = default;
+ObservableEvents::DataSourceInstanceStateChange::DataSourceInstanceStateChange(
+    ObservableEvents::DataSourceInstanceStateChange&&) noexcept = default;
+ObservableEvents::DataSourceInstanceStateChange&
+ObservableEvents::DataSourceInstanceStateChange::operator=(
+    ObservableEvents::DataSourceInstanceStateChange&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool ObservableEvents::DataSourceInstanceStateChange::operator==(
+    const ObservableEvents::DataSourceInstanceStateChange& other) const {
+  return (producer_name_ == other.producer_name_) &&
+         (data_source_name_ == other.data_source_name_) &&
+         (state_ == other.state_);
+}
+#pragma GCC diagnostic pop
+
+void ObservableEvents::DataSourceInstanceStateChange::FromProto(
+    const perfetto::protos::ObservableEvents_DataSourceInstanceStateChange&
+        proto) {
+  static_assert(sizeof(producer_name_) == sizeof(proto.producer_name()),
+                "size mismatch");
+  producer_name_ = static_cast<decltype(producer_name_)>(proto.producer_name());
+
+  static_assert(sizeof(data_source_name_) == sizeof(proto.data_source_name()),
+                "size mismatch");
+  data_source_name_ =
+      static_cast<decltype(data_source_name_)>(proto.data_source_name());
+
+  static_assert(sizeof(state_) == sizeof(proto.state()), "size mismatch");
+  state_ = static_cast<decltype(state_)>(proto.state());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void ObservableEvents::DataSourceInstanceStateChange::ToProto(
+    perfetto::protos::ObservableEvents_DataSourceInstanceStateChange* proto)
+    const {
+  proto->Clear();
+
+  static_assert(sizeof(producer_name_) == sizeof(proto->producer_name()),
+                "size mismatch");
+  proto->set_producer_name(
+      static_cast<decltype(proto->producer_name())>(producer_name_));
+
+  static_assert(sizeof(data_source_name_) == sizeof(proto->data_source_name()),
+                "size mismatch");
+  proto->set_data_source_name(
+      static_cast<decltype(proto->data_source_name())>(data_source_name_));
+
+  static_assert(sizeof(state_) == sizeof(proto->state()), "size mismatch");
+  proto->set_state(static_cast<decltype(proto->state())>(state_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+}  // namespace perfetto
diff --git a/src/tracing/core/packages_list_config.cc b/src/tracing/core/packages_list_config.cc
new file mode 100644
index 0000000..cd2b355
--- /dev/null
+++ b/src/tracing/core/packages_list_config.cc
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/android/packages_list_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/packages_list_config.h"
+
+#include "perfetto/config/android/packages_list_config.pb.h"
+
+namespace perfetto {
+
+PackagesListConfig::PackagesListConfig() = default;
+PackagesListConfig::~PackagesListConfig() = default;
+PackagesListConfig::PackagesListConfig(const PackagesListConfig&) = default;
+PackagesListConfig& PackagesListConfig::operator=(const PackagesListConfig&) =
+    default;
+PackagesListConfig::PackagesListConfig(PackagesListConfig&&) noexcept = default;
+PackagesListConfig& PackagesListConfig::operator=(PackagesListConfig&&) =
+    default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool PackagesListConfig::operator==(const PackagesListConfig& other) const {
+  return (package_name_filter_ == other.package_name_filter_);
+}
+#pragma GCC diagnostic pop
+
+void PackagesListConfig::FromProto(
+    const perfetto::protos::PackagesListConfig& proto) {
+  package_name_filter_.clear();
+  for (const auto& field : proto.package_name_filter()) {
+    package_name_filter_.emplace_back();
+    static_assert(sizeof(package_name_filter_.back()) ==
+                      sizeof(proto.package_name_filter(0)),
+                  "size mismatch");
+    package_name_filter_.back() =
+        static_cast<decltype(package_name_filter_)::value_type>(field);
+  }
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void PackagesListConfig::ToProto(
+    perfetto::protos::PackagesListConfig* proto) const {
+  proto->Clear();
+
+  for (const auto& it : package_name_filter_) {
+    proto->add_package_name_filter(
+        static_cast<decltype(proto->package_name_filter(0))>(it));
+    static_assert(sizeof(it) == sizeof(proto->package_name_filter(0)),
+                  "size mismatch");
+  }
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+}  // namespace perfetto
diff --git a/src/tracing/core/packet_stream_validator.cc b/src/tracing/core/packet_stream_validator.cc
index 3d2d846..4591f22 100644
--- a/src/tracing/core/packet_stream_validator.cc
+++ b/src/tracing/core/packet_stream_validator.cc
@@ -20,171 +20,50 @@
 #include <stddef.h>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
 #include "perfetto/protozero/proto_utils.h"
-
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/trusted_packet.pb.h"
 
 namespace perfetto {
 
-namespace {
-
-using protozero::proto_utils::ProtoWireType;
-
-const uint32_t kReservedFieldIds[] = {
-    protos::pbzero::TracePacket::kTrustedUidFieldNumber,
-    protos::pbzero::TracePacket::kTrustedPacketSequenceIdFieldNumber,
-    protos::pbzero::TracePacket::kTraceConfigFieldNumber,
-    protos::pbzero::TracePacket::kTraceStatsFieldNumber,
-    protos::pbzero::TracePacket::kCompressedPacketsFieldNumber,
-    protos::pbzero::TracePacket::kSynchronizationMarkerFieldNumber,
-};
-
-// This translation unit is quite subtle and perf-sensitive. Remember to check
-// BM_PacketStreamValidator in perfetto_benchmarks when making changes.
-
-// Checks that a packet, spread over several slices, is well-formed and doesn't
-// contain reserved top-level fields.
-// The checking logic is based on a state-machine that skips the fields' payload
-// and operates as follows:
-//              +-------------------------------+ <-------------------------+
-// +----------> | Read field preamble (varint)  | <----------------------+  |
-// |            +-------------------------------+                        |  |
-// |              |              |            |                          |  |
-// |       <Varint>        <Fixed 32/64>     <Length-delimited field>    |  |
-// |          V                  |                      V                |  |
-// |  +------------------+       |               +--------------+        |  |
-// |  | Read field value |       |               | Read length  |        |  |
-// |  | (another varint) |       |               |   (varint)   |        |  |
-// |  +------------------+       |               +--------------+        |  |
-// |           |                 V                      V                |  |
-// +-----------+        +----------------+     +-----------------+       |  |
-//                      | Skip 4/8 Bytes |     | Skip $len Bytes |-------+  |
-//                      +----------------+     +-----------------+          |
-//                               |                                          |
-//                               +------------------------------------------+
-class ProtoFieldParserFSM {
- public:
-  // This method effectively continuously parses varints (either for the field
-  // preamble or the payload or the submessage length) and tells the caller
-  // (the Validate() method) how many bytes to skip until the next field.
-  size_t Push(uint8_t octet) {
-    varint_ |= static_cast<uint64_t>(octet & 0x7F) << varint_shift_;
-    if (octet & 0x80) {
-      varint_shift_ += 7;
-      if (varint_shift_ >= 64)
-        state_ = kInvalidVarInt;
-      return 0;
-    }
-    uint64_t varint = varint_;
-    varint_ = 0;
-    varint_shift_ = 0;
-
-    switch (state_) {
-      case kFieldPreamble: {
-        uint64_t field_type = varint & 7;  // 7 = 0..0111
-        auto field_id = static_cast<uint32_t>(varint >> 3);
-        // Check if the field id is reserved, go into an error state if it is.
-        for (size_t i = 0; i < base::ArraySize(kReservedFieldIds); ++i) {
-          if (field_id == kReservedFieldIds[i]) {
-            state_ = kWroteReservedField;
-            return 0;
-          }
-        }
-        // The field type is legit, now check it's well formed and within
-        // boundaries.
-        if (field_type == static_cast<uint64_t>(ProtoWireType::kVarInt)) {
-          state_ = kVarIntValue;
-        } else if (field_type ==
-                   static_cast<uint64_t>(ProtoWireType::kFixed32)) {
-          return 4;
-        } else if (field_type ==
-                   static_cast<uint64_t>(ProtoWireType::kFixed64)) {
-          return 8;
-        } else if (field_type ==
-                   static_cast<uint64_t>(ProtoWireType::kLengthDelimited)) {
-          state_ = kLenDelimitedLen;
-        } else {
-          state_ = kUnknownFieldType;
-        }
-        return 0;
-      }
-
-      case kVarIntValue: {
-        // Consume the int field payload and go back to the next field.
-        state_ = kFieldPreamble;
-        return 0;
-      }
-
-      case kLenDelimitedLen: {
-        if (varint > protozero::proto_utils::kMaxMessageLength) {
-          state_ = kMessageTooBig;
-          return 0;
-        }
-        state_ = kFieldPreamble;
-        return static_cast<size_t>(varint);
-      }
-
-      case kWroteReservedField:
-      case kUnknownFieldType:
-      case kMessageTooBig:
-      case kInvalidVarInt:
-        // Persistent error states.
-        return 0;
-
-    }          // switch(state_)
-    return 0;  // To keep GCC happy.
-  }
-
-  // Queried at the end of the all payload. A message is well-formed only
-  // if the FSM is back to the state where it should parse the next field and
-  // hasn't started parsing any preamble.
-  bool valid() const { return state_ == kFieldPreamble && varint_shift_ == 0; }
-  int state() const { return static_cast<int>(state_); }
-
- private:
-  enum State {
-    kFieldPreamble = 0,  // Parsing the varint for the field preamble.
-    kVarIntValue,        // Parsing the varint value for the field payload.
-    kLenDelimitedLen,    // Parsing the length of the length-delimited field.
-
-    // Error states:
-    kWroteReservedField,  // Tried to set a reserved field id.
-    kUnknownFieldType,    // Encountered an invalid field type.
-    kMessageTooBig,       // Size of the length delimited message was too big.
-    kInvalidVarInt,       // VarInt larger than 64 bits.
-  };
-
-  State state_ = kFieldPreamble;
-  uint64_t varint_ = 0;
-  uint32_t varint_shift_ = 0;
-};
-
-}  // namespace
-
 // static
 bool PacketStreamValidator::Validate(const Slices& slices) {
-  ProtoFieldParserFSM parser;
-  size_t skip_bytes = 0;
-  for (const Slice& slice : slices) {
-    for (size_t i = 0; i < slice.size;) {
-      const size_t skip_bytes_cur_slice = std::min(skip_bytes, slice.size - i);
-      if (skip_bytes_cur_slice > 0) {
-        i += skip_bytes_cur_slice;
-        skip_bytes -= skip_bytes_cur_slice;
-      } else {
-        uint8_t octet = *(reinterpret_cast<const uint8_t*>(slice.start) + i);
-        skip_bytes = parser.Push(octet);
-        i++;
-      }
-    }
-  }
-  if (skip_bytes == 0 && parser.valid())
-    return true;
+  SlicedProtobufInputStream stream(&slices);
+  size_t size = 0;
+  for (const Slice& slice : slices)
+    size += slice.size;
 
-  PERFETTO_DLOG("Packet validation error (state %d, skip = %zu)",
-                parser.state(), skip_bytes);
-  return false;
+  protos::TrustedPacket packet;
+  if (!packet.ParseFromBoundedZeroCopyStream(&stream, static_cast<int>(size)))
+    return false;
+
+  // Only the service is allowed to fill in these fields:
+
+  if (packet.optional_trusted_uid_case() !=
+      protos::TrustedPacket::OPTIONAL_TRUSTED_UID_NOT_SET) {
+    return false;
+  }
+
+  if (packet.optional_trusted_packet_sequence_id_case() !=
+      protos::TrustedPacket::OPTIONAL_TRUSTED_PACKET_SEQUENCE_ID_NOT_SET) {
+    return false;
+  }
+
+  if (packet.has_trace_config())
+    return false;
+
+  if (packet.has_trace_stats())
+    return false;
+
+  if (!packet.synchronization_marker().empty())
+    return false;
+
+  // We are deliberately not checking for clock_snapshot for the moment. It's
+  // unclear if we want to allow producers to snapshot their clocks. Ideally we
+  // want a security model where producers can only snapshot their own clocks
+  // and not system ones. However, right now, there isn't a compelling need to
+  // be so prescriptive.
+
+  return true;
 }
 
 }  // namespace perfetto
diff --git a/src/tracing/core/packet_stream_validator.h b/src/tracing/core/packet_stream_validator.h
index c52d337..8494f4e 100644
--- a/src/tracing/core/packet_stream_validator.h
+++ b/src/tracing/core/packet_stream_validator.h
@@ -17,7 +17,7 @@
 #ifndef SRC_TRACING_CORE_PACKET_STREAM_VALIDATOR_H_
 #define SRC_TRACING_CORE_PACKET_STREAM_VALIDATOR_H_
 
-#include "perfetto/ext/tracing/core/slice.h"
+#include "src/tracing/core/sliced_protobuf_input_stream.h"
 
 namespace perfetto {
 
diff --git a/src/tracing/core/packet_stream_validator_benchmark.cc b/src/tracing/core/packet_stream_validator_benchmark.cc
deleted file mode 100644
index 9813b61..0000000
--- a/src/tracing/core/packet_stream_validator_benchmark.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// 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.
-
-#include <benchmark/benchmark.h>
-
-#include "src/tracing/core/packet_stream_validator.h"
-
-#include "perfetto/ext/tracing/core/slice.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-#include "protos/perfetto/trace/ftrace/sched.pbzero.h"
-#include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-namespace {
-
-static void BM_PacketStreamValidator(benchmark::State& state) {
-  using namespace perfetto;
-
-  // Create a packet that resembles a ftrace sched bundle. A ftrace page is
-  // 4KB and typically contains ~64 sched events of 64 bytes each.
-  protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
-  auto* bundle = packet->set_ftrace_events();
-  bundle->set_cpu(1);
-  for (size_t events = 0; events < 64; events++) {
-    auto* ftrace_evt = bundle->add_event();
-    ftrace_evt->set_pid(12345);
-    ftrace_evt->set_timestamp(1000ull * 1000 * 1000 * 3600 * 24 * 365);
-    auto* sched_switch = ftrace_evt->set_sched_switch();
-    sched_switch->set_prev_comm("thread_name_1");
-    sched_switch->set_prev_pid(12345);
-    sched_switch->set_prev_state(42);
-    sched_switch->set_next_comm("thread_name_2");
-    sched_switch->set_next_pid(67890);
-  }
-  std::vector<uint8_t> buf = packet.SerializeAsArray();
-
-  // Append 10 packets like the one above, splitting each packet into slices
-  // of 512B each.
-  Slices slices;
-  static constexpr size_t kSliceSize = 512;
-  for (size_t num_packets = 0; num_packets < 10; num_packets++) {
-    for (size_t pos = 0; pos < buf.size(); pos += kSliceSize) {
-      size_t slice_size = std::min(kSliceSize, buf.size() - pos);
-      Slice slice = Slice::Allocate(slice_size);
-      memcpy(slice.own_data(), &buf[pos], slice_size);
-      slices.emplace_back(std::move(slice));
-    }
-  }
-
-  bool res = true;
-  while (state.KeepRunning()) {
-    res &= PacketStreamValidator::Validate(slices);
-  }
-  PERFETTO_CHECK(res);
-}
-
-}  // namespace
-
-BENCHMARK(BM_PacketStreamValidator);
diff --git a/src/tracing/core/packet_stream_validator_fuzzer.cc b/src/tracing/core/packet_stream_validator_fuzzer.cc
deleted file mode 100644
index 54f70b5..0000000
--- a/src/tracing/core/packet_stream_validator_fuzzer.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2019 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 <stddef.h>
-#include <stdint.h>
-
-#include "perfetto/ext/tracing/core/slice.h"
-#include "src/tracing/core/packet_stream_validator.h"
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  perfetto::Slices slices;
-  for (const uint8_t* p = data; p < data + size;) {
-    size_t slice_size = *(p++);
-    size_t size_left = size - static_cast<size_t>(p - data);
-    slice_size = std::min(slice_size, size_left);
-    slices.emplace_back(perfetto::Slice(p, slice_size));
-    p += slice_size;
-  }
-  perfetto::PacketStreamValidator::Validate(slices);
-  return 0;
-}
diff --git a/src/tracing/core/packet_stream_validator_unittest.cc b/src/tracing/core/packet_stream_validator_unittest.cc
index bdb8ffd..03f15f4 100644
--- a/src/tracing/core/packet_stream_validator_unittest.cc
+++ b/src/tracing/core/packet_stream_validator_unittest.cc
@@ -18,8 +18,9 @@
 
 #include <string>
 
-#include "protos/perfetto/trace/trace_packet.pb.h"
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
+
+#include "perfetto/trace/trace_packet.pb.h"
 
 namespace perfetto {
 namespace {
diff --git a/src/tracing/core/patch_list.h b/src/tracing/core/patch_list.h
index f4a1618..c356006 100644
--- a/src/tracing/core/patch_list.h
+++ b/src/tracing/core/patch_list.h
@@ -21,8 +21,8 @@
 #include <forward_list>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/shared_memory_abi.h"
+#include "perfetto/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/shared_memory_abi.h"
 
 namespace perfetto {
 
diff --git a/src/tracing/core/patch_list_unittest.cc b/src/tracing/core/patch_list_unittest.cc
index dee9a1a..99609b2 100644
--- a/src/tracing/core/patch_list_unittest.cc
+++ b/src/tracing/core/patch_list_unittest.cc
@@ -18,7 +18,8 @@
 
 #include <ostream>
 
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 using testing::ElementsAre;
 
diff --git a/src/tracing/core/process_stats_config.cc b/src/tracing/core/process_stats_config.cc
new file mode 100644
index 0000000..7c4f898
--- /dev/null
+++ b/src/tracing/core/process_stats_config.cc
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/process_stats/process_stats_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/process_stats_config.h"
+
+#include "perfetto/config/process_stats/process_stats_config.pb.h"
+
+namespace perfetto {
+
+ProcessStatsConfig::ProcessStatsConfig() = default;
+ProcessStatsConfig::~ProcessStatsConfig() = default;
+ProcessStatsConfig::ProcessStatsConfig(const ProcessStatsConfig&) = default;
+ProcessStatsConfig& ProcessStatsConfig::operator=(const ProcessStatsConfig&) =
+    default;
+ProcessStatsConfig::ProcessStatsConfig(ProcessStatsConfig&&) noexcept = default;
+ProcessStatsConfig& ProcessStatsConfig::operator=(ProcessStatsConfig&&) =
+    default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool ProcessStatsConfig::operator==(const ProcessStatsConfig& other) const {
+  return (quirks_ == other.quirks_) &&
+         (scan_all_processes_on_start_ == other.scan_all_processes_on_start_) &&
+         (record_thread_names_ == other.record_thread_names_) &&
+         (proc_stats_poll_ms_ == other.proc_stats_poll_ms_) &&
+         (proc_stats_cache_ttl_ms_ == other.proc_stats_cache_ttl_ms_);
+}
+#pragma GCC diagnostic pop
+
+void ProcessStatsConfig::FromProto(
+    const perfetto::protos::ProcessStatsConfig& proto) {
+  quirks_.clear();
+  for (const auto& field : proto.quirks()) {
+    quirks_.emplace_back();
+    static_assert(sizeof(quirks_.back()) == sizeof(proto.quirks(0)),
+                  "size mismatch");
+    quirks_.back() = static_cast<decltype(quirks_)::value_type>(field);
+  }
+
+  static_assert(sizeof(scan_all_processes_on_start_) ==
+                    sizeof(proto.scan_all_processes_on_start()),
+                "size mismatch");
+  scan_all_processes_on_start_ =
+      static_cast<decltype(scan_all_processes_on_start_)>(
+          proto.scan_all_processes_on_start());
+
+  static_assert(
+      sizeof(record_thread_names_) == sizeof(proto.record_thread_names()),
+      "size mismatch");
+  record_thread_names_ =
+      static_cast<decltype(record_thread_names_)>(proto.record_thread_names());
+
+  static_assert(
+      sizeof(proc_stats_poll_ms_) == sizeof(proto.proc_stats_poll_ms()),
+      "size mismatch");
+  proc_stats_poll_ms_ =
+      static_cast<decltype(proc_stats_poll_ms_)>(proto.proc_stats_poll_ms());
+
+  static_assert(sizeof(proc_stats_cache_ttl_ms_) ==
+                    sizeof(proto.proc_stats_cache_ttl_ms()),
+                "size mismatch");
+  proc_stats_cache_ttl_ms_ = static_cast<decltype(proc_stats_cache_ttl_ms_)>(
+      proto.proc_stats_cache_ttl_ms());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void ProcessStatsConfig::ToProto(
+    perfetto::protos::ProcessStatsConfig* proto) const {
+  proto->Clear();
+
+  for (const auto& it : quirks_) {
+    proto->add_quirks(static_cast<decltype(proto->quirks(0))>(it));
+    static_assert(sizeof(it) == sizeof(proto->quirks(0)), "size mismatch");
+  }
+
+  static_assert(sizeof(scan_all_processes_on_start_) ==
+                    sizeof(proto->scan_all_processes_on_start()),
+                "size mismatch");
+  proto->set_scan_all_processes_on_start(
+      static_cast<decltype(proto->scan_all_processes_on_start())>(
+          scan_all_processes_on_start_));
+
+  static_assert(
+      sizeof(record_thread_names_) == sizeof(proto->record_thread_names()),
+      "size mismatch");
+  proto->set_record_thread_names(
+      static_cast<decltype(proto->record_thread_names())>(
+          record_thread_names_));
+
+  static_assert(
+      sizeof(proc_stats_poll_ms_) == sizeof(proto->proc_stats_poll_ms()),
+      "size mismatch");
+  proto->set_proc_stats_poll_ms(
+      static_cast<decltype(proto->proc_stats_poll_ms())>(proc_stats_poll_ms_));
+
+  static_assert(sizeof(proc_stats_cache_ttl_ms_) ==
+                    sizeof(proto->proc_stats_cache_ttl_ms()),
+                "size mismatch");
+  proto->set_proc_stats_cache_ttl_ms(
+      static_cast<decltype(proto->proc_stats_cache_ttl_ms())>(
+          proc_stats_cache_ttl_ms_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+}  // namespace perfetto
diff --git a/src/tracing/core/shared_memory_abi.cc b/src/tracing/core/shared_memory_abi.cc
index 75b9713..0b82dfc 100644
--- a/src/tracing/core/shared_memory_abi.cc
+++ b/src/tracing/core/shared_memory_abi.cc
@@ -13,7 +13,7 @@
  * express or implied. See the License for the specific language
  * governing permissions and limitations under the License.
  */
-#include "perfetto/ext/tracing/core/shared_memory_abi.h"
+#include "perfetto/tracing/core/shared_memory_abi.h"
 
 #include "perfetto/base/build_config.h"
 #include "perfetto/base/time.h"
@@ -22,8 +22,8 @@
 #include <sys/mman.h>
 #endif
 
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/tracing/core/basic_types.h"
 
 namespace perfetto {
 
@@ -74,7 +74,6 @@
 constexpr const char* SharedMemoryABI::kChunkStateStr[];
 constexpr const size_t SharedMemoryABI::kInvalidPageIdx;
 constexpr const size_t SharedMemoryABI::kMaxPageSize;
-constexpr const size_t SharedMemoryABI::kPacketSizeDropPacket;
 
 SharedMemoryABI::SharedMemoryABI() = default;
 
diff --git a/src/tracing/core/shared_memory_abi_unittest.cc b/src/tracing/core/shared_memory_abi_unittest.cc
index aed8893..0ce7a02 100644
--- a/src/tracing/core/shared_memory_abi_unittest.cc
+++ b/src/tracing/core/shared_memory_abi_unittest.cc
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/tracing/core/shared_memory_abi.h"
+#include "perfetto/tracing/core/shared_memory_abi.h"
 
-#include "perfetto/ext/tracing/core/basic_types.h"
+#include "gtest/gtest.h"
+#include "perfetto/tracing/core/basic_types.h"
 #include "src/base/test/gtest_test_suite.h"
 #include "src/tracing/test/aligned_buffer_test.h"
-#include "test/gtest_and_gmock.h"
 
 namespace perfetto {
 namespace {
diff --git a/src/tracing/core/shared_memory_arbiter_impl.cc b/src/tracing/core/shared_memory_arbiter_impl.cc
index 6141afb..88a43e6 100644
--- a/src/tracing/core/shared_memory_arbiter_impl.cc
+++ b/src/tracing/core/shared_memory_arbiter_impl.cc
@@ -19,9 +19,9 @@
 #include "perfetto/base/logging.h"
 #include "perfetto/base/task_runner.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/tracing/core/commit_data_request.h"
-#include "perfetto/ext/tracing/core/shared_memory.h"
-#include "perfetto/ext/tracing/core/startup_trace_writer_registry.h"
+#include "perfetto/tracing/core/commit_data_request.h"
+#include "perfetto/tracing/core/shared_memory.h"
+#include "perfetto/tracing/core/startup_trace_writer_registry.h"
 #include "src/tracing/core/null_trace_writer.h"
 #include "src/tracing/core/trace_writer_impl.h"
 
@@ -61,7 +61,6 @@
 
 Chunk SharedMemoryArbiterImpl::GetNewChunk(
     const SharedMemoryABI::ChunkHeader& header,
-    BufferExhaustedPolicy buffer_exhausted_policy,
     size_t size_hint) {
   PERFETTO_DCHECK(size_hint == 0);  // Not implemented yet.
   int stall_count = 0;
@@ -69,30 +68,13 @@
   static const unsigned kMaxStallIntervalUs = 100000;
   static const int kLogAfterNStalls = 3;
   static const int kFlushCommitsAfterEveryNStalls = 2;
-  static const int kAssertAtNStalls = 100;
 
   for (;;) {
     // TODO(primiano): Probably this lock is not really required and this code
     // could be rewritten leveraging only the Try* atomic operations in
     // SharedMemoryABI. But let's not be too adventurous for the moment.
     {
-      std::unique_lock<std::mutex> scoped_lock(lock_);
-
-      // If more than half of the SMB.size() is filled with completed chunks for
-      // which we haven't notified the service yet (i.e. they are still enqueued
-      // in |commit_data_req_|), force a synchronous CommitDataRequest() even if
-      // we acquire a chunk, to reduce the likeliness of stalling the writer.
-      //
-      // We can only do this if we're writing on the same thread that we access
-      // the producer endpoint on, since we cannot notify the producer endpoint
-      // to commit synchronously on a different thread. Attempting to flush
-      // synchronously on another thread will lead to subtle bugs caused by
-      // out-of-order commit requests (crbug.com/919187#c28).
-      bool should_commit_synchronously =
-          buffer_exhausted_policy == BufferExhaustedPolicy::kStall &&
-          commit_data_req_ && bytes_pending_commit_ >= shmem_abi_.size() / 2 &&
-          task_runner_->RunsTasksOnCurrentThread();
-
+      std::lock_guard<std::mutex> scoped_lock(lock_);
       const size_t initial_page_idx = page_idx_;
       for (size_t i = 0; i < shmem_abi_.num_pages(); i++) {
         page_idx_ = (initial_page_idx + i) % shmem_abi_.num_pages();
@@ -125,33 +107,16 @@
             PERFETTO_LOG("Recovered from stall after %d iterations",
                          stall_count);
           }
-
-          if (should_commit_synchronously) {
-            // We can't flush while holding the lock.
-            scoped_lock.unlock();
-            FlushPendingCommitDataRequests();
-            return chunk;
-          } else {
-            return chunk;
-          }
+          return chunk;
         }
       }
-    }  // std::unique_lock<std::mutex>
-
-    if (buffer_exhausted_policy == BufferExhaustedPolicy::kDrop) {
-      PERFETTO_DLOG("Shared memory buffer exhaused, returning invalid Chunk!");
-      return Chunk();
-    }
+    }  // std::lock_guard<std::mutex>
 
     // All chunks are taken (either kBeingWritten by us or kBeingRead by the
-    // Service).
+    // Service). TODO: at this point we should return a bankrupcy chunk, not
+    // crash the process.
     if (stall_count++ == kLogAfterNStalls) {
-      PERFETTO_LOG("Shared memory buffer overrun! Stalling");
-    }
-
-    if (stall_count == kAssertAtNStalls) {
-      PERFETTO_FATAL(
-          "Shared memory buffer max stall count exceeded; possible deadlock");
+      PERFETTO_ELOG("Shared memory buffer overrun! Stalling");
     }
 
     // If the IPC thread itself is stalled because the current process has
@@ -205,6 +170,7 @@
                                                       PatchList* patch_list) {
   // Note: chunk will be invalid if the call came from SendPatches().
   bool should_post_callback = false;
+  bool should_commit_synchronously = false;
   base::WeakPtr<SharedMemoryArbiterImpl> weak_this;
   {
     std::lock_guard<std::mutex> scoped_lock(lock_);
@@ -229,6 +195,22 @@
       ctm->set_page(static_cast<uint32_t>(page_idx));
       ctm->set_chunk(chunk_idx);
       ctm->set_target_buffer(target_buffer);
+
+      // If more than half of the SMB.size() is filled with completed chunks for
+      // which we haven't notified the service yet (i.e. they are still enqueued
+      // in |commit_data_req_|), force a synchronous CommitDataRequest(), to
+      // reduce the likeliness of stalling the writer.
+      //
+      // We can only do this if we're writing on the same thread that we access
+      // the producer endpoint on, since we cannot notify the producer endpoint
+      // to commit synchronously on a different thread. Attempting to flush
+      // synchronously on another thread will lead to subtle bugs caused by
+      // out-of-order commit requests (crbug.com/919187#c28).
+      if (task_runner_->RunsTasksOnCurrentThread() &&
+          bytes_pending_commit_ >= shmem_abi_.size() / 2) {
+        should_commit_synchronously = true;
+        should_post_callback = false;
+      }
     }
 
     // Get the completed patches for previous chunks from the |patch_list|
@@ -266,6 +248,9 @@
         weak_this->FlushPendingCommitDataRequests();
     });
   }
+
+  if (should_commit_synchronously)
+    FlushPendingCommitDataRequests();
 }
 
 // This function is quite subtle. When making changes keep in mind these two
@@ -310,8 +295,7 @@
 }
 
 std::unique_ptr<TraceWriter> SharedMemoryArbiterImpl::CreateTraceWriter(
-    BufferID target_buffer,
-    BufferExhaustedPolicy buffer_exhausted_policy) {
+    BufferID target_buffer) {
   WriterID id;
   {
     std::lock_guard<std::mutex> scoped_lock(lock_);
@@ -325,7 +309,7 @@
       weak_this->producer_endpoint_->RegisterTraceWriter(id, target_buffer);
   });
   return std::unique_ptr<TraceWriter>(
-      new TraceWriterImpl(this, id, target_buffer, buffer_exhausted_policy));
+      new TraceWriterImpl(this, id, target_buffer));
 }
 
 void SharedMemoryArbiterImpl::BindStartupTraceWriterRegistry(
diff --git a/src/tracing/core/shared_memory_arbiter_impl.h b/src/tracing/core/shared_memory_arbiter_impl.h
index be00684..c92b887 100644
--- a/src/tracing/core/shared_memory_arbiter_impl.h
+++ b/src/tracing/core/shared_memory_arbiter_impl.h
@@ -24,11 +24,11 @@
 #include <mutex>
 #include <vector>
 
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/shared_memory_abi.h"
-#include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
-#include "perfetto/ext/tracing/core/startup_trace_writer_registry.h"
+#include "perfetto/base/weak_ptr.h"
+#include "perfetto/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/shared_memory_abi.h"
+#include "perfetto/tracing/core/shared_memory_arbiter.h"
+#include "perfetto/tracing/core/startup_trace_writer_registry.h"
 #include "src/tracing/core/id_allocator.h"
 
 namespace perfetto {
@@ -50,19 +50,26 @@
 // current thread-local chunk.
 class SharedMemoryArbiterImpl : public SharedMemoryArbiter {
  public:
-  // See SharedMemoryArbiter::CreateInstance(). |start|, |size| define the
-  // boundaries of the shared memory buffer.
+  // Args:
+  // |start|,|size|: boundaries of the shared memory buffer.
+  // |page_size|: a multiple of 4KB that defines the granularity of tracing
+  // pages. See tradeoff considerations in shared_memory_abi.h.
+  // |OnPagesCompleteCallback|: a callback that will be posted on the passed
+  // |TaskRunner| when one or more pages are complete (and hence the Producer
+  // should send a CommitData request to the Service).
+  // |TaskRunner|: Task runner for perfetto's main thread, which executes the
+  // OnPagesCompleteCallback and IPC calls to the |ProducerEndpoint|.
   SharedMemoryArbiterImpl(void* start,
                           size_t size,
                           size_t page_size,
                           TracingService::ProducerEndpoint*,
                           base::TaskRunner*);
 
-  // Returns a new Chunk to write tracing data. Depending on the provided
-  // BufferExhaustedPolicy, this may return an invalid chunk if no valid free
-  // chunk could be found in the SMB.
+  // Returns a new Chunk to write tracing data. The call always returns a valid
+  // Chunk. TODO(primiano): right now this blocks if there are no free chunks
+  // in the SMB. In the long term the caller should be allowed to pick a policy
+  // and handle the retry itself asynchronously.
   SharedMemoryABI::Chunk GetNewChunk(const SharedMemoryABI::ChunkHeader&,
-                                     BufferExhaustedPolicy,
                                      size_t size_hint = 0);
 
   // Puts back a Chunk that has been completed and sends a request to the
@@ -97,22 +104,13 @@
   // SharedMemoryArbiter implementation.
   // See include/perfetto/tracing/core/shared_memory_arbiter.h for comments.
   std::unique_ptr<TraceWriter> CreateTraceWriter(
-      BufferID target_buffer,
-      BufferExhaustedPolicy = BufferExhaustedPolicy::kDefault) override;
+      BufferID target_buffer) override;
   void BindStartupTraceWriterRegistry(
       std::unique_ptr<StartupTraceWriterRegistry>,
       BufferID target_buffer) override;
 
   void NotifyFlushComplete(FlushRequestID) override;
 
-  base::TaskRunner* task_runner() const { return task_runner_; }
-  size_t page_size() const { return shmem_abi_.page_size(); }
-  size_t num_pages() const { return shmem_abi_.num_pages(); }
-
-  base::WeakPtr<SharedMemoryArbiterImpl> GetWeakPtr() const {
-    return weak_ptr_factory_.GetWeakPtr();
-  }
-
  private:
   friend class TraceWriterImpl;
   friend class StartupTraceWriterTest;
diff --git a/src/tracing/core/shared_memory_arbiter_impl_unittest.cc b/src/tracing/core/shared_memory_arbiter_impl_unittest.cc
index 91bd5db..90682dc 100644
--- a/src/tracing/core/shared_memory_arbiter_impl_unittest.cc
+++ b/src/tracing/core/shared_memory_arbiter_impl_unittest.cc
@@ -16,18 +16,17 @@
 
 #include "src/tracing/core/shared_memory_arbiter_impl.h"
 
-#include <bitset>
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/commit_data_request.h"
-#include "perfetto/ext/tracing/core/shared_memory_abi.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/commit_data_request.h"
+#include "perfetto/tracing/core/shared_memory_abi.h"
+#include "perfetto/tracing/core/trace_writer.h"
 #include "src/base/test/gtest_test_suite.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/tracing/core/patch_list.h"
 #include "src/tracing/test/aligned_buffer_test.h"
-#include "src/tracing/test/fake_producer_endpoint.h"
-#include "test/gtest_and_gmock.h"
 
 namespace perfetto {
 namespace {
@@ -45,9 +44,7 @@
   void ActivateTriggers(const std::vector<std::string>&) {}
   SharedMemory* shared_memory() const override { return nullptr; }
   size_t shared_buffer_page_size_kb() const override { return 0; }
-  std::unique_ptr<TraceWriter> CreateTraceWriter(
-      BufferID,
-      BufferExhaustedPolicy) override {
+  std::unique_ptr<TraceWriter> CreateTraceWriter(BufferID) override {
     return nullptr;
   }
   SharedMemoryArbiter* GetInProcessShmemArbiter() override { return nullptr; }
@@ -93,7 +90,7 @@
   static constexpr size_t kTotChunks = kNumPages * 14;
   SharedMemoryABI::Chunk chunks[kTotChunks];
   for (size_t i = 0; i < 14 * 2 + 2; i++) {
-    chunks[i] = arbiter_->GetNewChunk({}, BufferExhaustedPolicy::kStall);
+    chunks[i] = arbiter_->GetNewChunk({}, 0 /*size_hint*/);
     ASSERT_TRUE(chunks[i].is_valid());
   }
 
@@ -137,53 +134,23 @@
   task_runner_->RunUntilCheckpoint("on_commit_2");
 }
 
-// Helper for verifying trace writer id allocations.
-class TraceWriterIdChecker : public FakeProducerEndpoint {
- public:
-  TraceWriterIdChecker(std::function<void()> checkpoint)
-      : checkpoint_(std::move(checkpoint)) {}
-
-  void RegisterTraceWriter(uint32_t id, uint32_t) override {
-    EXPECT_GT(id, 0u);
-    EXPECT_LE(id, kMaxWriterID);
-    if (id > 0 && id <= kMaxWriterID) {
-      registered_ids_.set(id - 1);
-    }
-  }
-
-  void UnregisterTraceWriter(uint32_t id) override {
-    if (++unregister_calls_ == kMaxWriterID)
-      checkpoint_();
-
-    EXPECT_GT(id, 0u);
-    EXPECT_LE(id, kMaxWriterID);
-    if (id > 0 && id <= kMaxWriterID) {
-      unregistered_ids_.set(id - 1);
-    }
-  }
-
-  // bit N corresponds to id N+1
-  std::bitset<kMaxWriterID> registered_ids_;
-  std::bitset<kMaxWriterID> unregistered_ids_;
-
-  int unregister_calls_ = 0;
-
- private:
-  std::function<void()> checkpoint_;
-};
-
 // Check that we can actually create up to kMaxWriterID TraceWriter(s).
 TEST_P(SharedMemoryArbiterImplTest, WriterIDsAllocation) {
   auto checkpoint = task_runner_->CreateCheckpoint("last_unregistered");
-
-  TraceWriterIdChecker id_checking_endpoint(checkpoint);
-  arbiter_.reset(new SharedMemoryArbiterImpl(buf(), buf_size(), page_size(),
-                                             &id_checking_endpoint,
-                                             task_runner_.get()));
+  int num_unregistered = 0;
   {
     std::map<WriterID, std::unique_ptr<TraceWriter>> writers;
-
     for (size_t i = 0; i < kMaxWriterID; i++) {
+      EXPECT_CALL(mock_producer_endpoint_,
+                  RegisterTraceWriter(static_cast<uint32_t>(i + 1), 0));
+      EXPECT_CALL(mock_producer_endpoint_,
+                  UnregisterTraceWriter(static_cast<uint32_t>(i + 1)))
+          .WillOnce(Invoke([checkpoint, &num_unregistered](uint32_t) {
+            num_unregistered++;
+            if (num_unregistered == kMaxWriterID)
+              checkpoint();
+          }));
+
       std::unique_ptr<TraceWriter> writer = arbiter_->CreateTraceWriter(0);
       ASSERT_TRUE(writer);
       WriterID writer_id = writer->writer_id();
@@ -195,47 +162,8 @@
     ASSERT_EQ(arbiter_->CreateTraceWriter(0)->writer_id(), 0);
   }
 
-  // This should run the Register/UnregisterTraceWriter tasks enqueued by the
-  // memory arbiter.
+  // This should run the Register/UnregisterTraceWriter calls expected above.
   task_runner_->RunUntilCheckpoint("last_unregistered", 15000);
-
-  EXPECT_TRUE(id_checking_endpoint.registered_ids_.all());
-  EXPECT_TRUE(id_checking_endpoint.unregistered_ids_.all());
-}
-
-// Verify that getting a new chunk doesn't stall when kDrop policy is chosen.
-TEST_P(SharedMemoryArbiterImplTest, BufferExhaustedPolicyDrop) {
-  // Grab all chunks in the SMB.
-  SharedMemoryArbiterImpl::set_default_layout_for_testing(
-      SharedMemoryABI::PageLayout::kPageDiv1);
-  static constexpr size_t kTotChunks = kNumPages;
-  SharedMemoryABI::Chunk chunks[kTotChunks];
-  for (size_t i = 0; i < kTotChunks; i++) {
-    chunks[i] = arbiter_->GetNewChunk({}, BufferExhaustedPolicy::kDrop);
-    ASSERT_TRUE(chunks[i].is_valid());
-  }
-
-  // SMB is exhausted, thus GetNewChunk() should return an invalid chunk. In
-  // kStall mode, this would stall.
-  SharedMemoryABI::Chunk invalid_chunk =
-      arbiter_->GetNewChunk({}, BufferExhaustedPolicy::kDrop);
-  ASSERT_FALSE(invalid_chunk.is_valid());
-
-  // Returning the chunk is not enough to be able to reacquire it.
-  PatchList ignored;
-  arbiter_->ReturnCompletedChunk(std::move(chunks[0]), 0, &ignored);
-
-  invalid_chunk = arbiter_->GetNewChunk({}, BufferExhaustedPolicy::kDrop);
-  ASSERT_FALSE(invalid_chunk.is_valid());
-
-  // After releasing the chunk as free, we can reacquire it.
-  chunks[0] =
-      arbiter_->shmem_abi_for_testing()->TryAcquireChunkForReading(0, 0);
-  ASSERT_TRUE(chunks[0].is_valid());
-  arbiter_->shmem_abi_for_testing()->ReleaseChunkAsFree(std::move(chunks[0]));
-
-  chunks[0] = arbiter_->GetNewChunk({}, BufferExhaustedPolicy::kDrop);
-  ASSERT_TRUE(chunks[0].is_valid());
 }
 
 // TODO(primiano): add multi-threaded tests.
diff --git a/src/tracing/core/sliced_protobuf_input_stream.cc b/src/tracing/core/sliced_protobuf_input_stream.cc
index 3301e63..65b0bb1 100644
--- a/src/tracing/core/sliced_protobuf_input_stream.cc
+++ b/src/tracing/core/sliced_protobuf_input_stream.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/tracing/core/sliced_protobuf_input_stream.h"
+#include "src/tracing/core/sliced_protobuf_input_stream.h"
 
 #include <algorithm>
 
@@ -86,17 +86,17 @@
   return true;
 }
 
-SlicedProtobufInputStream::int64 SlicedProtobufInputStream::ByteCount() const {
+google::protobuf::int64 SlicedProtobufInputStream::ByteCount() const {
   PERFETTO_DCHECK(Validate());
-  int64_t count = 0;
+  google::protobuf::int64 count = 0;
   for (auto it = slices_->begin(); it != slices_->end(); it++) {
     if (it == cur_slice_) {
-      count += static_cast<int64_t>(pos_in_cur_slice_);
+      count += static_cast<google::protobuf::int64>(pos_in_cur_slice_);
       break;
     }
-    count += static_cast<int64_t>(it->size);
+    count += static_cast<google::protobuf::int64>(it->size);
   }
-  return static_cast<SlicedProtobufInputStream::int64>(count);
+  return count;
 }
 
 bool SlicedProtobufInputStream::Validate() const {
diff --git a/src/tracing/core/sliced_protobuf_input_stream.h b/src/tracing/core/sliced_protobuf_input_stream.h
new file mode 100644
index 0000000..71c7e60
--- /dev/null
+++ b/src/tracing/core/sliced_protobuf_input_stream.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2017 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 SRC_TRACING_CORE_SLICED_PROTOBUF_INPUT_STREAM_H_
+#define SRC_TRACING_CORE_SLICED_PROTOBUF_INPUT_STREAM_H_
+
+#include "perfetto/tracing/core/slice.h"
+
+#include <stdint.h>
+
+#include "google/protobuf/io/zero_copy_stream.h"
+
+namespace perfetto {
+
+// Wraps a sequence of Slice(s) in a protobuf ZeroCopyInputStream that can be
+// passed to protobuf::Message::ParseFromZeroCopyStream().
+class SlicedProtobufInputStream
+    : public google::protobuf::io::ZeroCopyInputStream {
+ public:
+  explicit SlicedProtobufInputStream(const Slices*);
+  ~SlicedProtobufInputStream() override;
+
+  // ZeroCopyInputStream implementation. See zero_copy_stream.h for the API
+  // contract of the methods below.
+  bool Next(const void** data, int* size) override;
+  void BackUp(int count) override;
+  bool Skip(int count) override;
+  google::protobuf::int64 ByteCount() const override;
+
+ private:
+  bool Validate() const;
+
+  const Slices* const slices_;
+  Slices::const_iterator cur_slice_;
+  size_t pos_in_cur_slice_ = 0;
+};
+
+}  // namespace perfetto
+
+#endif  // SRC_TRACING_CORE_SLICED_PROTOBUF_INPUT_STREAM_H_
diff --git a/src/tracing/core/sliced_protobuf_input_stream_unittest.cc b/src/tracing/core/sliced_protobuf_input_stream_unittest.cc
index fc0c075..076afc1 100644
--- a/src/tracing/core/sliced_protobuf_input_stream_unittest.cc
+++ b/src/tracing/core/sliced_protobuf_input_stream_unittest.cc
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/tracing/core/sliced_protobuf_input_stream.h"
+#include "src/tracing/core/sliced_protobuf_input_stream.h"
 
-#include "perfetto/ext/base/utils.h"
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/utils.h"
 
 namespace perfetto {
 namespace {
diff --git a/src/tracing/core/startup_trace_writer.cc b/src/tracing/core/startup_trace_writer.cc
index 26b8605..989a28a 100644
--- a/src/tracing/core/startup_trace_writer.cc
+++ b/src/tracing/core/startup_trace_writer.cc
@@ -14,34 +14,28 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/tracing/core/startup_trace_writer.h"
+#include "perfetto/tracing/core/startup_trace_writer.h"
 
 #include <numeric>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/metatrace.h"
-#include "perfetto/ext/tracing/core/startup_trace_writer_registry.h"
 #include "perfetto/protozero/proto_utils.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-#include "src/tracing/core/null_trace_writer.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/tracing/core/shared_memory_abi.h"
+#include "perfetto/tracing/core/startup_trace_writer_registry.h"
 #include "src/tracing/core/patch_list.h"
 #include "src/tracing/core/shared_memory_arbiter_impl.h"
 
-using PageHeader = perfetto::SharedMemoryABI::PageHeader;
 using ChunkHeader = perfetto::SharedMemoryABI::ChunkHeader;
 
 namespace perfetto {
 
 namespace {
 
-static constexpr ChunkID kFirstChunkId = 0;
-
 SharedMemoryABI::Chunk NewChunk(SharedMemoryArbiterImpl* arbiter,
                                 WriterID writer_id,
                                 ChunkID chunk_id,
-                                bool fragmenting_packet,
-                                BufferExhaustedPolicy buffer_exhausted_policy) {
+                                bool fragmenting_packet) {
   ChunkHeader::Packets packets = {};
   if (fragmenting_packet) {
     packets.count = 1;
@@ -56,15 +50,13 @@
   header.chunk_id.store(chunk_id, std::memory_order_relaxed);
   header.packets.store(packets, std::memory_order_relaxed);
 
-  return arbiter->GetNewChunk(header, buffer_exhausted_policy);
+  return arbiter->GetNewChunk(header);
 }
 
 class LocalBufferReader {
  public:
-  LocalBufferReader(std::unique_ptr<protozero::ScatteredHeapBuffer> buffer)
-      : buffer_(std::move(buffer)),
-        buffer_slices_(buffer_->slices()),
-        cur_slice_(buffer_slices_.begin()) {}
+  LocalBufferReader(protozero::ScatteredHeapBuffer* buffer)
+      : buffer_slices_(buffer->slices()), cur_slice_(buffer_slices_.begin()) {}
 
   size_t ReadBytes(SharedMemoryABI::Chunk* target_chunk,
                    size_t num_bytes,
@@ -117,7 +109,6 @@
   }
 
  private:
-  std::unique_ptr<protozero::ScatteredHeapBuffer> buffer_;
   const std::vector<protozero::ScatteredHeapBuffer::Slice>& buffer_slices_;
 
   // Iterator pointing to slice in |buffer_slices_| that we're currently reading
@@ -127,241 +118,14 @@
   size_t cur_slice_offset_ = 0;
 };
 
-// Helper class that takes ownership of a LocalBufferReader its buffer and
-// commits the buffer's data into the assigned SMB in batches. After writing
-// each batch of data, it waits for the service to acknowledge the batch's
-// commit before continuing with the remaining data.
-class LocalBufferCommitter {
- public:
-  LocalBufferCommitter(std::unique_ptr<LocalBufferReader> local_buffer_reader,
-                       std::unique_ptr<std::vector<uint32_t>> packet_sizes,
-                       base::WeakPtr<SharedMemoryArbiterImpl> arbiter,
-                       WriterID writer_id,
-                       BufferID target_buffer,
-                       size_t chunks_per_batch,
-                       BufferExhaustedPolicy buffer_exhausted_policy,
-                       SharedMemoryABI::Chunk first_chunk)
-      : local_buffer_reader_(std::move(local_buffer_reader)),
-        packet_sizes_(std::move(packet_sizes)),
-        arbiter_(arbiter),
-        // TODO(eseckler): This assumes a fixed page layout of one chunk per
-        // page. If we ever end up supporting dynamic page layouts, we'd have to
-        // make sure that the arbiter gives us full-page chunks.
-        max_payload_size_(arbiter->page_size() - sizeof(PageHeader) -
-                          sizeof(ChunkHeader)),
-        writer_id_(writer_id),
-        target_buffer_(target_buffer),
-        chunks_per_batch_(chunks_per_batch),
-        buffer_exhausted_policy_(buffer_exhausted_policy),
-        cur_chunk_(std::move(first_chunk)) {
-    PERFETTO_DCHECK(cur_chunk_.is_valid());
-    PERFETTO_DCHECK(!packet_sizes_->empty());
-    remaining_packet_size_ = (*packet_sizes_)[packet_idx_];
-  }
-
-  static void CommitRemainingDataInBatches(
-      std::unique_ptr<LocalBufferCommitter> committer) {
-    // Give up and destroy the committer if the arbiter went away.
-    if (!committer->arbiter_)
-      return;
-
-    committer->CommitNextBatch();
-    if (committer->HasMoreDataToCommit()) {
-      // Flush the commit request to the service and wait for its response
-      // before continuing with the next batch.
-      std::shared_ptr<std::unique_ptr<LocalBufferCommitter>> committer_shared(
-          new std::unique_ptr<LocalBufferCommitter>(std::move(committer)));
-
-      (*committer_shared)
-          ->arbiter_->FlushPendingCommitDataRequests([committer_shared]() {
-            std::unique_ptr<LocalBufferCommitter> owned_committer(
-                committer_shared->release());
-            CommitRemainingDataInBatches(std::move(owned_committer));
-          });
-      return;
-    }
-
-    // We should have read all data from the local buffer.
-    PERFETTO_DCHECK(committer->local_buffer_reader_->DidReadAllData());
-    // Last chunk should have completed the last packet.
-    PERFETTO_DCHECK(!committer->fragmenting_packet_);
-
-    committer->arbiter_->FlushPendingCommitDataRequests();
-  }
-
-  size_t GetTotalNumChunksRequired() {
-    // We will write at least one chunk.
-    size_t num_chunks = 1;
-
-    size_t cur_payload_size = 0;
-    uint16_t cur_num_packets = 0;
-    for (size_t packet_idx = 0; packet_idx < packet_sizes_->size();
-         packet_idx++) {
-      uint32_t remaining_packet_size = (*packet_sizes_)[packet_idx];
-      ++cur_num_packets;
-      do {
-        uint32_t fragment_size = static_cast<uint32_t>(
-            std::min(static_cast<size_t>(remaining_packet_size),
-                     max_payload_size_ - cur_payload_size -
-                         SharedMemoryABI::kPacketHeaderSize));
-        cur_payload_size += SharedMemoryABI::kPacketHeaderSize;
-        cur_payload_size += fragment_size;
-        remaining_packet_size -= fragment_size;
-
-        // We need another chunk if we've filled its payload (i.e., cannot fit
-        // another packet's header) or reached the maximum number of packets.
-        bool next_chunk =
-            cur_payload_size >=
-                max_payload_size_ - SharedMemoryABI::kPacketHeaderSize ||
-            cur_num_packets == ChunkHeader::Packets::kMaxCount;
-
-        if (next_chunk) {
-          num_chunks++;
-          bool is_fragmenting = remaining_packet_size > 0;
-          cur_num_packets = is_fragmenting ? 1 : 0;
-          cur_payload_size = 0;
-        }
-      } while (remaining_packet_size > 0);
-    }
-
-    return num_chunks;
-  }
-
- private:
-  bool HasMoreDataToCommit() const {
-    PERFETTO_DCHECK(packet_idx_ <= packet_sizes_->size());
-    return packet_idx_ < packet_sizes_->size() || remaining_packet_size_ != 0;
-  }
-
-  // Reads (part of) the remaining data from |local_buffer_reader_| and writes
-  // the next batch of chunks into the SMB.
-  void CommitNextBatch() {
-    PERFETTO_METATRACE_SCOPED(TAG_TRACE_WRITER,
-                              TRACE_WRITER_COMMIT_STARTUP_WRITER_BATCH);
-    for (size_t num_chunks = 0;
-         (!chunks_per_batch_ || num_chunks < chunks_per_batch_) &&
-         HasMoreDataToCommit();
-         num_chunks++) {
-      if (!CommitNextChunk()) {
-        // We ran out of SMB space. Send the current batch early and retry later
-        // with the next batch.
-        break;
-      }
-    }
-  }
-
-  bool CommitNextChunk() {
-    PERFETTO_DCHECK(HasMoreDataToCommit());
-
-    // First chunk is acquired before LocalBufferCommitter is created, so we may
-    // already have a valid chunk.
-    if (!cur_chunk_.is_valid()) {
-      cur_chunk_ = NewChunk(arbiter_.get(), writer_id_, next_chunk_id_,
-                            fragmenting_packet_, buffer_exhausted_policy_);
-
-      if (!cur_chunk_.is_valid())
-        return false;
-
-      next_chunk_id_++;
-    }
-
-    // See comment at initialization of |max_payload_size_|.
-    PERFETTO_CHECK(max_payload_size_ == cur_chunk_.payload_size());
-
-    // Iterate over remaining packets, starting at |packet_idx_|. Write as much
-    // data as possible into |chunk| while not exceeding the chunk's payload
-    // size and the maximum number of packets per chunk.
-    size_t cur_payload_size = 0;
-    uint16_t cur_num_packets = 0;
-    PatchList empty_patch_list;
-    PERFETTO_DCHECK(packet_idx_ < packet_sizes_->size());
-    PERFETTO_DCHECK((*packet_sizes_)[packet_idx_] >= remaining_packet_size_ &&
-                    (remaining_packet_size_ || !(*packet_sizes_)[packet_idx_]));
-    while (HasMoreDataToCommit()) {
-      ++cur_num_packets;
-
-      // The packet may not fit completely into the chunk.
-      uint32_t fragment_size = static_cast<uint32_t>(
-          std::min(static_cast<size_t>(remaining_packet_size_),
-                   max_payload_size_ - cur_payload_size -
-                       SharedMemoryABI::kPacketHeaderSize));
-
-      // Write packet header, i.e. the fragment size.
-      protozero::proto_utils::WriteRedundantVarInt(
-          fragment_size, cur_chunk_.payload_begin() + cur_payload_size);
-      cur_payload_size += SharedMemoryABI::kPacketHeaderSize;
-
-      // Copy packet content into the chunk.
-      size_t bytes_read = local_buffer_reader_->ReadBytes(
-          &cur_chunk_, fragment_size, cur_payload_size);
-      PERFETTO_DCHECK(bytes_read == fragment_size);
-
-      cur_payload_size += fragment_size;
-      remaining_packet_size_ -= fragment_size;
-
-      fragmenting_packet_ = remaining_packet_size_ > 0;
-      if (!fragmenting_packet_) {
-        ++packet_idx_;
-        if (packet_idx_ < packet_sizes_->size()) {
-          remaining_packet_size_ = (*packet_sizes_)[packet_idx_];
-        }
-      }
-
-      // We should return the current chunk if we've filled its payload, reached
-      // the maximum number of packets, or wrote everything we wanted to.
-      bool return_chunk =
-          cur_payload_size >=
-              max_payload_size_ - SharedMemoryABI::kPacketHeaderSize ||
-          cur_num_packets == ChunkHeader::Packets::kMaxCount ||
-          !HasMoreDataToCommit();
-
-      if (return_chunk)
-        break;
-    }
-
-    auto new_packet_count = cur_chunk_.IncreasePacketCountTo(cur_num_packets);
-    PERFETTO_DCHECK(new_packet_count == cur_num_packets);
-
-    if (fragmenting_packet_) {
-      PERFETTO_DCHECK(cur_payload_size == max_payload_size_);
-      cur_chunk_.SetFlag(ChunkHeader::kLastPacketContinuesOnNextChunk);
-    }
-
-    arbiter_->ReturnCompletedChunk(std::move(cur_chunk_), target_buffer_,
-                                   &empty_patch_list);
-    return true;
-  }
-
-  std::unique_ptr<LocalBufferReader> local_buffer_reader_;
-  std::unique_ptr<std::vector<uint32_t>> packet_sizes_;
-  base::WeakPtr<SharedMemoryArbiterImpl> arbiter_;
-  const size_t max_payload_size_;
-  const WriterID writer_id_;
-  const BufferID target_buffer_;
-  const size_t chunks_per_batch_;
-  BufferExhaustedPolicy buffer_exhausted_policy_;
-  SharedMemoryABI::Chunk cur_chunk_;
-  // We receive the first chunk in the constructor, thus the next chunk will be
-  // the second one.
-  ChunkID next_chunk_id_ = kFirstChunkId + 1;
-  size_t packet_idx_ = 0;
-  uint32_t remaining_packet_size_ = 0;
-  bool fragmenting_packet_ = false;
-};
-
 }  // namespace
 
 StartupTraceWriter::StartupTraceWriter(
-    std::shared_ptr<StartupTraceWriterRegistryHandle> registry_handle,
-    BufferExhaustedPolicy buffer_exhausted_policy,
-    size_t max_buffer_size_bytes)
+    std::shared_ptr<StartupTraceWriterRegistryHandle> registry_handle)
     : registry_handle_(std::move(registry_handle)),
-      buffer_exhausted_policy_(buffer_exhausted_policy),
-      max_buffer_size_bytes_(max_buffer_size_bytes),
       memory_buffer_(new protozero::ScatteredHeapBuffer()),
       memory_stream_writer_(
-          new protozero::ScatteredStreamWriter(memory_buffer_.get())),
-      packet_sizes_(new std::vector<uint32_t>()) {
+          new protozero::ScatteredStreamWriter(memory_buffer_.get())) {
   memory_buffer_->set_writer(memory_stream_writer_.get());
   PERFETTO_DETACH_FROM_THREAD(writer_thread_checker_);
 }
@@ -371,34 +135,18 @@
     : was_bound_(true), trace_writer_(std::move(trace_writer)) {}
 
 StartupTraceWriter::~StartupTraceWriter() {
-  // Should have been returned to the registry before destruction.
-  PERFETTO_DCHECK(!registry_handle_);
-}
-
-// static
-void StartupTraceWriter::ReturnToRegistry(
-    std::unique_ptr<StartupTraceWriter> writer) {
-  auto registry_handle = std::move(writer->registry_handle_);
-  if (registry_handle) {
-    // May destroy |writer|.
-    registry_handle->ReturnWriterToRegistry(std::move(writer));
-  }
+  if (registry_handle_)
+    registry_handle_->OnWriterDestroyed(this);
 }
 
 bool StartupTraceWriter::BindToArbiter(SharedMemoryArbiterImpl* arbiter,
-                                       BufferID target_buffer,
-                                       size_t chunks_per_batch) {
-  // LocalBufferCommitter requires a WeakPtr to the arbiter, and thus needs to
-  // execute on the arbiter's task runner.
-  PERFETTO_DCHECK(arbiter->task_runner()->RunsTasksOnCurrentThread());
-
+                                       BufferID target_buffer) {
   // Create and destroy trace writer without holding lock, since this will post
   // a task and task posting may trigger a trace event, which would cause a
   // deadlock. This may create a few more trace writers than necessary in cases
   // where a concurrent write is in progress (other than causing some
   // computational overhead, this is not problematic).
-  auto trace_writer =
-      arbiter->CreateTraceWriter(target_buffer, buffer_exhausted_policy_);
+  auto trace_writer = arbiter->CreateTraceWriter(target_buffer);
 
   {
     std::lock_guard<std::mutex> lock(lock_);
@@ -416,33 +164,16 @@
       cur_packet_.reset();
     }
 
-    // Successfully bind if we don't have any data or no valid trace writer.
-    if (packet_sizes_->empty() || !trace_writer->writer_id()) {
-      trace_writer_ = std::move(trace_writer);
-      memory_buffer_.reset();
-      packet_sizes_.reset();
-      memory_stream_writer_.reset();
-      return true;
-    }
-
-    // We need to ensure that we commit at least one chunk now, otherwise the
-    // service might receive and erroneously start reading from a future chunk
-    // committed by the underlying trace writer. Thus, we attempt to acquire the
-    // first chunk and bail out if we fail (we'll retry later).
-    SharedMemoryABI::Chunk first_chunk =
-        NewChunk(arbiter, trace_writer->writer_id(), kFirstChunkId,
-                 /*fragmenting_packet=*/false, buffer_exhausted_policy_);
-    if (!first_chunk.is_valid())
-      return false;
-
     trace_writer_ = std::move(trace_writer);
     ChunkID next_chunk_id = CommitLocalBufferChunks(
-        arbiter, trace_writer_->writer_id(), target_buffer, chunks_per_batch,
-        std::move(first_chunk));
+        arbiter, trace_writer_->writer_id(), target_buffer);
 
     // The real TraceWriter should start writing at the subsequent chunk ID.
     bool success = trace_writer_->SetFirstChunkId(next_chunk_id);
     PERFETTO_DCHECK(success);
+
+    memory_stream_writer_.reset();
+    memory_buffer_.reset();
   }
 
   return true;
@@ -475,28 +206,6 @@
       lock.unlock();
       return trace_writer_->NewTracePacket();
     }
-
-    // Check if we already exceeded the maximum size of the local buffer, and if
-    // so, write into nowhere.
-    if (null_trace_writer_ ||
-        memory_buffer_->GetTotalSize() >= max_buffer_size_bytes_) {
-      if (!null_trace_writer_) {
-        null_trace_writer_.reset(new NullTraceWriter());
-
-        // Write a packet that marks data loss.
-        std::unique_ptr<protos::pbzero::TracePacket> packet(
-            new protos::pbzero::TracePacket());
-        packet->Reset(memory_stream_writer_.get());
-        {
-          TraceWriter::TracePacketHandle handle(packet.get());
-          handle->set_previous_packet_dropped(true);
-        }
-        uint32_t packet_size = packet->Finalize();
-        packet_sizes_->push_back(packet_size);
-      }
-      return null_trace_writer_->NewTracePacket();
-    }
-
     // Not bound. Make sure it stays this way until the TracePacketHandle goes
     // out of scope by setting |write_in_progress_|.
     PERFETTO_DCHECK(!write_in_progress_);
@@ -511,7 +220,6 @@
   } else {
     cur_packet_.reset(new protos::pbzero::TracePacket());
   }
-
   cur_packet_->Reset(memory_stream_writer_.get());
   TraceWriter::TracePacketHandle handle(cur_packet_.get());
   // |this| outlives the packet handle.
@@ -580,7 +288,7 @@
   PERFETTO_DCHECK(cur_packet_->is_finalized());
   // Finalize() is a no-op because the packet is already finalized.
   uint32_t packet_size = cur_packet_->Finalize();
-  packet_sizes_->push_back(packet_size);
+  packet_sizes_.push_back(packet_size);
 
   // Write is complete, reset the flag to allow binding.
   std::lock_guard<std::mutex> lock(lock_);
@@ -591,37 +299,96 @@
 ChunkID StartupTraceWriter::CommitLocalBufferChunks(
     SharedMemoryArbiterImpl* arbiter,
     WriterID writer_id,
-    BufferID target_buffer,
-    size_t chunks_per_batch,
-    SharedMemoryABI::Chunk first_chunk) {
-  PERFETTO_DCHECK(!packet_sizes_->empty());
-  PERFETTO_DCHECK(writer_id);
+    BufferID target_buffer) {
+  // TODO(eseckler): Write and commit these chunks asynchronously. This would
+  // require that the service is informed of the missing initial chunks, e.g. by
+  // committing our first chunk here before the new trace writer has a chance to
+  // commit its first chunk. Otherwise the service wouldn't know to wait for our
+  // chunks.
+
+  if (packet_sizes_.empty() || !writer_id)
+    return 0;
 
   memory_buffer_->AdjustUsedSizeOfCurrentSlice();
-  memory_stream_writer_.reset();
+  LocalBufferReader local_buffer_reader(memory_buffer_.get());
 
-  std::unique_ptr<LocalBufferReader> local_buffer_reader(
-      new LocalBufferReader(std::move(memory_buffer_)));
-
-  PERFETTO_DCHECK(local_buffer_reader->TotalUsedSize() ==
-                  std::accumulate(packet_sizes_->begin(), packet_sizes_->end(),
+  PERFETTO_DCHECK(local_buffer_reader.TotalUsedSize() ==
+                  std::accumulate(packet_sizes_.begin(), packet_sizes_.end(),
                                   static_cast<size_t>(0u)));
 
-  std::unique_ptr<LocalBufferCommitter> committer(new LocalBufferCommitter(
-      std::move(local_buffer_reader), std::move(packet_sizes_),
-      arbiter->GetWeakPtr(), writer_id, target_buffer, chunks_per_batch,
-      buffer_exhausted_policy_, std::move(first_chunk)));
+  ChunkID next_chunk_id = 0;
+  SharedMemoryABI::Chunk cur_chunk =
+      NewChunk(arbiter, writer_id, next_chunk_id++, false);
 
-  ChunkID next_chunk_id =
-      kFirstChunkId +
-      static_cast<ChunkID>(committer->GetTotalNumChunksRequired());
+  size_t max_payload_size = cur_chunk.payload_size();
+  size_t cur_payload_size = 0;
+  uint16_t cur_num_packets = 0;
+  size_t total_num_packets = packet_sizes_.size();
+  PatchList empty_patch_list;
+  for (size_t packet_idx = 0; packet_idx < total_num_packets; packet_idx++) {
+    uint32_t packet_size = packet_sizes_[packet_idx];
+    uint32_t remaining_packet_size = packet_size;
+    ++cur_num_packets;
+    do {
+      uint32_t fragment_size = static_cast<uint32_t>(
+          std::min(static_cast<size_t>(remaining_packet_size),
+                   max_payload_size - cur_payload_size -
+                       SharedMemoryABI::kPacketHeaderSize));
+      // Write packet header, i.e. the fragment size.
+      protozero::proto_utils::WriteRedundantVarInt(
+          fragment_size, cur_chunk.payload_begin() + cur_payload_size);
+      cur_payload_size += SharedMemoryABI::kPacketHeaderSize;
 
-  // Write the chunks to the SMB in smaller batches to avoid large bursts that
-  // could fill up the SMB completely and lead to stalls or data loss. We'll
-  // continue writing the chunks asynchronously. We need to ensure that we write
-  // at least one chunk now, otherwise the service might receive and erroneously
-  // start reading from a future chunk committed by the underlying trace writer.
-  LocalBufferCommitter::CommitRemainingDataInBatches(std::move(committer));
+      // Copy packet content into the chunk.
+      size_t bytes_read = local_buffer_reader.ReadBytes(
+          &cur_chunk, fragment_size, cur_payload_size);
+      PERFETTO_DCHECK(bytes_read == fragment_size);
+
+      cur_payload_size += fragment_size;
+      remaining_packet_size -= fragment_size;
+
+      bool last_write =
+          packet_idx == total_num_packets - 1 && remaining_packet_size == 0;
+
+      // We should return the current chunk if we've filled its payload, reached
+      // the maximum number of packets, or wrote everything we wanted to.
+      bool return_chunk =
+          cur_payload_size >=
+              max_payload_size - SharedMemoryABI::kPacketHeaderSize ||
+          cur_num_packets == ChunkHeader::Packets::kMaxCount || last_write;
+
+      if (return_chunk) {
+        auto new_packet_count =
+            cur_chunk.IncreasePacketCountTo(cur_num_packets);
+        PERFETTO_DCHECK(new_packet_count == cur_num_packets);
+
+        bool is_fragmenting = remaining_packet_size > 0;
+        if (is_fragmenting) {
+          PERFETTO_DCHECK(cur_payload_size == max_payload_size);
+          cur_chunk.SetFlag(ChunkHeader::kLastPacketContinuesOnNextChunk);
+        }
+
+        arbiter->ReturnCompletedChunk(std::move(cur_chunk), target_buffer,
+                                      &empty_patch_list);
+
+        // Avoid creating a new chunk after the last write.
+        if (!last_write) {
+          cur_chunk =
+              NewChunk(arbiter, writer_id, next_chunk_id++, is_fragmenting);
+          max_payload_size = cur_chunk.payload_size();
+          cur_payload_size = 0;
+          cur_num_packets = is_fragmenting ? 1 : 0;
+        } else {
+          PERFETTO_DCHECK(!is_fragmenting);
+        }
+      }
+    } while (remaining_packet_size > 0);
+  }
+
+  // The last chunk should have been returned.
+  PERFETTO_DCHECK(!cur_chunk.is_valid());
+  // We should have read all data from the local buffer.
+  PERFETTO_DCHECK(local_buffer_reader.DidReadAllData());
 
   return next_chunk_id;
 }
diff --git a/src/tracing/core/startup_trace_writer_registry.cc b/src/tracing/core/startup_trace_writer_registry.cc
index e576be8..c3fcfce 100644
--- a/src/tracing/core/startup_trace_writer_registry.cc
+++ b/src/tracing/core/startup_trace_writer_registry.cc
@@ -14,15 +14,13 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/tracing/core/startup_trace_writer_registry.h"
+#include "perfetto/tracing/core/startup_trace_writer_registry.h"
 
-#include <algorithm>
-#include <cmath>
 #include <functional>
 
 #include "perfetto/base/logging.h"
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/tracing/core/startup_trace_writer.h"
+#include "perfetto/tracing/core/startup_trace_writer.h"
 #include "src/tracing/core/shared_memory_arbiter_impl.h"
 
 using ChunkHeader = perfetto::SharedMemoryABI::ChunkHeader;
@@ -33,11 +31,11 @@
     StartupTraceWriterRegistry* registry)
     : registry_(registry) {}
 
-void StartupTraceWriterRegistryHandle::ReturnWriterToRegistry(
-    std::unique_ptr<StartupTraceWriter> writer) {
+void StartupTraceWriterRegistryHandle::OnWriterDestroyed(
+    StartupTraceWriter* writer) {
   std::lock_guard<std::mutex> lock(lock_);
   if (registry_)
-    registry_->ReturnTraceWriter(std::move(writer));
+    registry_->OnStartupTraceWriterDestroyed(writer);
 }
 
 void StartupTraceWriterRegistryHandle::OnRegistryDestroyed() {
@@ -52,48 +50,22 @@
   handle_->OnRegistryDestroyed();
 }
 
-// static
-constexpr size_t StartupTraceWriterRegistry::kDefaultMaxBufferSizeBytes;
-
 std::unique_ptr<StartupTraceWriter>
-StartupTraceWriterRegistry::CreateUnboundTraceWriter(
-    BufferExhaustedPolicy buffer_exhausted_policy,
-    size_t max_buffer_size_bytes) {
+StartupTraceWriterRegistry::CreateUnboundTraceWriter() {
   std::lock_guard<std::mutex> lock(lock_);
   PERFETTO_DCHECK(!arbiter_);  // Should only be called while unbound.
-  std::unique_ptr<StartupTraceWriter> writer(new StartupTraceWriter(
-      handle_, buffer_exhausted_policy, max_buffer_size_bytes));
-  unbound_writers_.push_back(writer.get());
+  std::unique_ptr<StartupTraceWriter> writer(new StartupTraceWriter(handle_));
+  unbound_writers_.insert(writer.get());
   return writer;
 }
 
-void StartupTraceWriterRegistry::ReturnTraceWriter(
+void StartupTraceWriterRegistry::ReturnUnboundTraceWriter(
     std::unique_ptr<StartupTraceWriter> trace_writer) {
   std::lock_guard<std::mutex> lock(lock_);
+  PERFETTO_DCHECK(!arbiter_);  // Should only be called while unbound.
   PERFETTO_DCHECK(!trace_writer->write_in_progress_);
-  auto it = std::find(unbound_writers_.begin(), unbound_writers_.end(),
-                      trace_writer.get());
-
-  // If the registry is already bound, but the writer wasn't, bind it now.
-  if (arbiter_) {
-    if (it == unbound_writers_.end()) {
-      // Nothing to do, the writer was already bound.
-      return;
-    }
-
-    // This should succeed since nobody can write to this writer concurrently.
-    bool success = trace_writer->BindToArbiter(arbiter_, target_buffer_,
-                                               chunks_per_batch_);
-    PERFETTO_DCHECK(success);
-    unbound_writers_.erase(it);
-
-    OnUnboundWritersRemovedLocked();
-    return;
-  }
-
-  // If the registry was not bound yet, keep the writer alive until it is.
-  PERFETTO_DCHECK(it != unbound_writers_.end());
-  unbound_writers_.erase(it);
+  PERFETTO_DCHECK(unbound_writers_.count(trace_writer.get()));
+  unbound_writers_.erase(trace_writer.get());
   unbound_owned_writers_.push_back(std::move(trace_writer));
 }
 
@@ -109,24 +81,6 @@
     arbiter_ = arbiter;
     target_buffer_ = target_buffer;
     task_runner_ = task_runner;
-
-    // Attempt to use at most half the SMB for binding of StartupTraceWriters at
-    // the same time. In the worst case, all writers are binding at the same
-    // time, so divide it up between them.
-    //
-    // TODO(eseckler): This assumes that there's only a single registry at the
-    // same time. SharedMemoryArbiterImpl should advise us how much of the SMB
-    // we're allowed to use in the first place.
-    size_t num_writers =
-        unbound_owned_writers_.size() + unbound_writers_.size();
-    if (num_writers) {
-      chunks_per_batch_ = arbiter_->num_pages() / 2 / num_writers;
-    } else {
-      chunks_per_batch_ = arbiter_->num_pages() / 2;
-    }
-    // We should use at least one chunk per batch.
-    chunks_per_batch_ = std::max(chunks_per_batch_, static_cast<size_t>(1u));
-
     // Weakptrs should be valid on |task_runner|. For this, the factory needs to
     // be created on |task_runner|, i.e. BindToArbiter must be called on
     // |task_runner|.
@@ -143,8 +97,7 @@
   // Bind and destroy the owned writers.
   for (const auto& writer : unbound_owned_writers) {
     // This should succeed since nobody can write to these writers concurrently.
-    bool success =
-        writer->BindToArbiter(arbiter_, target_buffer_, chunks_per_batch_);
+    bool success = writer->BindToArbiter(arbiter_, target_buffer_);
     PERFETTO_DCHECK(success);
   }
   unbound_owned_writers.clear();
@@ -155,10 +108,10 @@
 void StartupTraceWriterRegistry::TryBindWriters() {
   std::lock_guard<std::mutex> lock(lock_);
   for (auto it = unbound_writers_.begin(); it != unbound_writers_.end();) {
-    if ((*it)->BindToArbiter(arbiter_, target_buffer_, chunks_per_batch_)) {
+    if ((*it)->BindToArbiter(arbiter_, target_buffer_)) {
       it = unbound_writers_.erase(it);
     } else {
-      break;
+      it++;
     }
   }
   if (!unbound_writers_.empty()) {
@@ -171,6 +124,13 @@
   OnUnboundWritersRemovedLocked();
 }
 
+void StartupTraceWriterRegistry::OnStartupTraceWriterDestroyed(
+    StartupTraceWriter* trace_writer) {
+  std::lock_guard<std::mutex> lock(lock_);
+  if (unbound_writers_.erase(trace_writer) > 0)
+    OnUnboundWritersRemovedLocked();
+}
+
 void StartupTraceWriterRegistry::OnUnboundWritersRemovedLocked() {
   if (!unbound_writers_.empty() || !task_runner_ || !on_bound_callback_)
     return;
diff --git a/src/tracing/core/startup_trace_writer_unittest.cc b/src/tracing/core/startup_trace_writer_unittest.cc
index a7cd419..63457d5 100644
--- a/src/tracing/core/startup_trace_writer_unittest.cc
+++ b/src/tracing/core/startup_trace_writer_unittest.cc
@@ -14,23 +14,23 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/tracing/core/startup_trace_writer.h"
+#include "perfetto/tracing/core/startup_trace_writer.h"
 
-#include "perfetto/ext/tracing/core/startup_trace_writer_registry.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
+#include "gtest/gtest.h"
+#include "perfetto/tracing/core/startup_trace_writer_registry.h"
+#include "perfetto/tracing/core/trace_packet.h"
+#include "perfetto/tracing/core/tracing_service.h"
 #include "src/base/test/gtest_test_suite.h"
 #include "src/base/test/test_task_runner.h"
-#include "src/tracing/core/patch_list.h"
 #include "src/tracing/core/shared_memory_arbiter_impl.h"
+#include "src/tracing/core/sliced_protobuf_input_stream.h"
 #include "src/tracing/core/trace_buffer.h"
 #include "src/tracing/test/aligned_buffer_test.h"
 #include "src/tracing/test/fake_producer_endpoint.h"
-#include "test/gtest_and_gmock.h"
 
-#include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/test_event.pbzero.h"
+#include "perfetto/trace/trace_packet.pb.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
 
@@ -38,7 +38,7 @@
  public:
   void SetUp() override {
     SharedMemoryArbiterImpl::set_default_layout_for_testing(
-        SharedMemoryABI::PageLayout::kPageDiv1);
+        SharedMemoryABI::PageLayout::kPageDiv4);
     AlignedBufferTest::SetUp();
     task_runner_.reset(new base::TestTaskRunner());
     arbiter_.reset(new SharedMemoryArbiterImpl(buf(), buf_size(), page_size(),
@@ -53,13 +53,13 @@
 
   std::unique_ptr<StartupTraceWriter> CreateUnboundWriter() {
     std::shared_ptr<StartupTraceWriterRegistryHandle> registry;
-    return std::unique_ptr<StartupTraceWriter>(new StartupTraceWriter(
-        registry, BufferExhaustedPolicy::kDrop, max_buffer_size_bytes()));
+    return std::unique_ptr<StartupTraceWriter>(
+        new StartupTraceWriter(registry));
   }
 
-  bool BindWriter(StartupTraceWriter* writer, size_t chunks_per_batch = 0) {
+  bool BindWriter(StartupTraceWriter* writer) {
     const BufferID kBufId = 42;
-    return writer->BindToArbiter(arbiter_.get(), kBufId, chunks_per_batch);
+    return writer->BindToArbiter(arbiter_.get(), kBufId);
   }
 
   void WritePackets(StartupTraceWriter* writer, size_t packet_count) {
@@ -69,29 +69,10 @@
     }
   }
 
-  size_t CountCompleteChunksInSMB() {
-    SharedMemoryABI* abi = arbiter_->shmem_abi_for_testing();
-    size_t num_complete_chunks = 0;
-    for (size_t page_idx = 0; page_idx < kNumPages; page_idx++) {
-      uint32_t page_layout = abi->GetPageLayout(page_idx);
-      size_t num_chunks = SharedMemoryABI::GetNumChunksForLayout(page_layout);
-      for (size_t chunk_idx = 0; chunk_idx < num_chunks; chunk_idx++) {
-        auto chunk_state = abi->GetChunkState(page_idx, chunk_idx);
-        if (chunk_state == SharedMemoryABI::kChunkComplete)
-          num_complete_chunks++;
-      }
-    }
-    return num_complete_chunks;
-  }
-
-  void VerifyPackets(size_t expected_count,
-                     bool expect_data_loss_packet = false) {
+  void VerifyPackets(size_t expected_count) {
     SharedMemoryABI* abi = arbiter_->shmem_abi_for_testing();
     auto buffer = TraceBuffer::Create(abi->size());
 
-    if (expect_data_loss_packet)
-      expected_count++;
-
     size_t total_packets_count = 0;
     ChunkID current_max_chunk_id = 0;
     for (size_t page_idx = 0; page_idx < kNumPages; page_idx++) {
@@ -146,20 +127,16 @@
       EXPECT_EQ(static_cast<uid_t>(1),
                 sequence_properties.producer_uid_trusted);
 
+      SlicedProtobufInputStream stream(&packet.slices());
+      size_t size = 0;
+      for (const Slice& slice : packet.slices())
+        size += slice.size;
       protos::TracePacket parsed_packet;
-      bool res = parsed_packet.ParseFromString(packet.GetRawBytesForTesting());
-      EXPECT_TRUE(res);
-      if (!res)
+      bool success = parsed_packet.ParseFromBoundedZeroCopyStream(
+          &stream, static_cast<int>(size));
+      EXPECT_TRUE(success);
+      if (!success)
         break;
-
-      // If the buffer size was exceeded, the data loss packet should be the
-      // last committed packet.
-      if (expect_data_loss_packet && parsed_packet.previous_packet_dropped()) {
-        num_packets_read++;
-        EXPECT_EQ(expected_count, num_packets_read);
-        break;
-      }
-
       EXPECT_TRUE(parsed_packet.has_for_testing());
       EXPECT_EQ(kPacketPayload, parsed_packet.for_testing().str());
       num_packets_read++;
@@ -187,12 +164,6 @@
     return count;
   }
 
-  size_t GetTotalBufferSize(StartupTraceWriter* writer) const {
-    return writer->memory_buffer_->GetTotalSize();
-  }
-
-  size_t max_buffer_size_bytes() const { return page_size() * 5; }
-
  protected:
   static constexpr char kPacketPayload[] = "foo";
 
@@ -208,7 +179,7 @@
 
 namespace {
 
-size_t const kPageSizes[] = {4096, 32768};
+size_t const kPageSizes[] = {4096, 65536};
 INSTANTIATE_TEST_SUITE_P(PageSize,
                          StartupTraceWriterTest,
                          ::testing::ValuesIn(kPageSizes));
@@ -300,34 +271,6 @@
   VerifyPackets(kNumAdditionalPackets);
 }
 
-TEST_P(StartupTraceWriterTest, MaxBufferSizeExceeded) {
-  auto writer = CreateUnboundWriter();
-
-  // Write packets until the buffer is extended above kMaxBufferSizeBytes.
-  size_t valid_packets = 0;
-  while (GetTotalBufferSize(writer.get()) < max_buffer_size_bytes()) {
-    WritePackets(writer.get(), 1);
-    valid_packets++;
-  }
-
-  // The next packet should be dropped into a void.
-  WritePackets(writer.get(), 1);
-
-  // Binding the writer should cause the valid previously written packets to be
-  // written to the SMB and committed.
-  EXPECT_TRUE(BindWriter(writer.get()));
-
-  VerifyPackets(valid_packets, /*expect_data_loss_packet=*/true);
-
-  // Any further packets should be written to the SMB directly.
-  const size_t kNumAdditionalPackets = 16;
-  WritePackets(writer.get(), kNumAdditionalPackets);
-  // Finalizes the last packet and returns the chunk.
-  writer.reset();
-
-  VerifyPackets(kNumAdditionalPackets);
-}
-
 TEST_P(StartupTraceWriterTest, BindingWhileWritingFails) {
   auto writer = CreateUnboundWriter();
 
@@ -350,15 +293,13 @@
       new StartupTraceWriterRegistry());
 
   // Create unbound writers.
-  auto writer1 =
-      registry->CreateUnboundTraceWriter(BufferExhaustedPolicy::kDrop);
-  auto writer2 =
-      registry->CreateUnboundTraceWriter(BufferExhaustedPolicy::kDrop);
+  auto writer1 = registry->CreateUnboundTraceWriter();
+  auto writer2 = registry->CreateUnboundTraceWriter();
 
   EXPECT_EQ(2u, GetUnboundWriterCount(*registry));
 
   // Return |writer2|. It should be kept alive until the registry is bound.
-  StartupTraceWriter::ReturnToRegistry(std::move(writer2));
+  registry->ReturnUnboundTraceWriter(std::move(writer2));
 
   {
     // Begin a write by opening a TracePacket on |writer1|.
@@ -383,125 +324,6 @@
   };
   task_runner_->PostDelayedTask(task, 1);
   task_runner_->RunUntilCheckpoint(checkpoint_name);
-
-  StartupTraceWriter::ReturnToRegistry(std::move(writer1));
-}
-
-TEST_P(StartupTraceWriterTest, BindAndCommitInBatches) {
-  auto writer = CreateUnboundWriter();
-
-  // Write a single packet to determine its size in the buffer.
-  WritePackets(writer.get(), 1);
-  size_t packet_size = writer->used_buffer_size();
-
-  // Write at least 3 pages/chunks worth of packets.
-  const size_t kNumPackets = (page_size() * 3 + packet_size - 1) / packet_size;
-  WritePackets(writer.get(), kNumPackets);
-
-  static constexpr size_t kChunksPerBatch = 2;
-
-  // Binding the writer with a batch size of 2 chunks should cause the first 2
-  // chunks of previously written packets to be written to the SMB and
-  // committed. The remaining chunks will be written when the
-  // |commit_data_callback| is executed.
-  EXPECT_TRUE(BindWriter(writer.get(), kChunksPerBatch));
-
-  EXPECT_EQ(
-      fake_producer_endpoint_.last_commit_data_request.chunks_to_move().size(),
-      kChunksPerBatch);
-  EXPECT_EQ(CountCompleteChunksInSMB(), kChunksPerBatch);
-  auto commit_data_callback = fake_producer_endpoint_.last_commit_data_callback;
-  EXPECT_TRUE(commit_data_callback);
-
-  // Send a commit with a single packet from the bound trace writer before the
-  // remaining chunk batches of the buffered data are written.
-  const size_t kNumAdditionalPackets = 1;
-  WritePackets(writer.get(), 1);
-  // Finalizes the packet and returns the chunk.
-  writer.reset();
-
-  // The packet should fit into a chunk.
-  EXPECT_EQ(
-      fake_producer_endpoint_.last_commit_data_request.chunks_to_move().size(),
-      1u);
-  EXPECT_EQ(CountCompleteChunksInSMB(), kChunksPerBatch + 1);
-
-  // Write and commit the remaining chunks to the SMB.
-  while (commit_data_callback) {
-    commit_data_callback();
-    commit_data_callback = fake_producer_endpoint_.last_commit_data_callback;
-  }
-
-  // Verify that all chunks + packets are in the SMB.
-  VerifyPackets(1 + kNumPackets + kNumAdditionalPackets);
-}
-
-TEST_P(StartupTraceWriterTest, BindAndCommitInBatchesWithSMBExhaustion) {
-  auto writer = CreateUnboundWriter();
-
-  // Write a single packet to determine its size in the buffer.
-  WritePackets(writer.get(), 1);
-  size_t packet_size = writer->used_buffer_size();
-
-  // Write at least 3 pages/chunks worth of packets.
-  const size_t kNumPackets = (page_size() * 3 + packet_size - 1) / packet_size;
-  WritePackets(writer.get(), kNumPackets);
-
-  // Acquire all chunks in the SMB.
-  static constexpr size_t kTotChunks = kNumPages;
-  SharedMemoryABI::Chunk chunks[kTotChunks];
-  for (size_t i = 0; i < kTotChunks; i++) {
-    chunks[i] = arbiter_->GetNewChunk({}, BufferExhaustedPolicy::kDrop);
-    ASSERT_TRUE(chunks[i].is_valid());
-  }
-
-  // Binding the writer should fail if no chunks are available in the SMB.
-  static constexpr size_t kChunksPerBatch = 2;
-  EXPECT_FALSE(BindWriter(writer.get(), kChunksPerBatch));
-
-  // Return and free the first chunk, so that there is only a single free chunk.
-  PatchList ignored;
-  arbiter_->ReturnCompletedChunk(std::move(chunks[0]), 0, &ignored);
-  chunks[0] =
-      arbiter_->shmem_abi_for_testing()->TryAcquireChunkForReading(0, 0);
-  ASSERT_TRUE(chunks[0].is_valid());
-  arbiter_->shmem_abi_for_testing()->ReleaseChunkAsFree(std::move(chunks[0]));
-  arbiter_->FlushPendingCommitDataRequests();
-
-  // Binding the writer should only cause the first chunks of previously written
-  // packets to be written to the SMB and committed because no further chunks
-  // are available in the SMB. The remaining chunks will be written when the
-  // |commit_data_callback| is executed.
-  EXPECT_TRUE(BindWriter(writer.get(), kChunksPerBatch));
-
-  EXPECT_EQ(
-      fake_producer_endpoint_.last_commit_data_request.chunks_to_move().size(),
-      1u);
-  EXPECT_EQ(CountCompleteChunksInSMB(), 1u);
-  auto commit_data_callback = fake_producer_endpoint_.last_commit_data_callback;
-  EXPECT_TRUE(commit_data_callback);
-
-  // Free up the other SMB chunks.
-  for (size_t i = 1; i < kTotChunks; i++) {
-    arbiter_->ReturnCompletedChunk(std::move(chunks[i]), 0, &ignored);
-    chunks[i] =
-        arbiter_->shmem_abi_for_testing()->TryAcquireChunkForReading(i, 0);
-    ASSERT_TRUE(chunks[i].is_valid());
-    arbiter_->shmem_abi_for_testing()->ReleaseChunkAsFree(std::move(chunks[i]));
-  }
-  arbiter_->FlushPendingCommitDataRequests();
-
-  // Write and commit the remaining buffered startup writer data to the SMB.
-  while (commit_data_callback) {
-    commit_data_callback();
-    commit_data_callback = fake_producer_endpoint_.last_commit_data_callback;
-  }
-  EXPECT_GT(
-      fake_producer_endpoint_.last_commit_data_request.chunks_to_move().size(),
-      0u);
-
-  // Verify that all chunks + packets are in the SMB.
-  VerifyPackets(1 + kNumPackets);
 }
 
 }  // namespace
diff --git a/src/tracing/core/sys_stats_config.cc b/src/tracing/core/sys_stats_config.cc
new file mode 100644
index 0000000..700fdcf
--- /dev/null
+++ b/src/tracing/core/sys_stats_config.cc
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/sys_stats/sys_stats_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/sys_stats_config.h"
+
+#include "perfetto/common/sys_stats_counters.pb.h"
+#include "perfetto/config/sys_stats/sys_stats_config.pb.h"
+
+namespace perfetto {
+
+SysStatsConfig::SysStatsConfig() = default;
+SysStatsConfig::~SysStatsConfig() = default;
+SysStatsConfig::SysStatsConfig(const SysStatsConfig&) = default;
+SysStatsConfig& SysStatsConfig::operator=(const SysStatsConfig&) = default;
+SysStatsConfig::SysStatsConfig(SysStatsConfig&&) noexcept = default;
+SysStatsConfig& SysStatsConfig::operator=(SysStatsConfig&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool SysStatsConfig::operator==(const SysStatsConfig& other) const {
+  return (meminfo_period_ms_ == other.meminfo_period_ms_) &&
+         (meminfo_counters_ == other.meminfo_counters_) &&
+         (vmstat_period_ms_ == other.vmstat_period_ms_) &&
+         (vmstat_counters_ == other.vmstat_counters_) &&
+         (stat_period_ms_ == other.stat_period_ms_) &&
+         (stat_counters_ == other.stat_counters_);
+}
+#pragma GCC diagnostic pop
+
+void SysStatsConfig::FromProto(const perfetto::protos::SysStatsConfig& proto) {
+  static_assert(sizeof(meminfo_period_ms_) == sizeof(proto.meminfo_period_ms()),
+                "size mismatch");
+  meminfo_period_ms_ =
+      static_cast<decltype(meminfo_period_ms_)>(proto.meminfo_period_ms());
+
+  meminfo_counters_.clear();
+  for (const auto& field : proto.meminfo_counters()) {
+    meminfo_counters_.emplace_back();
+    static_assert(
+        sizeof(meminfo_counters_.back()) == sizeof(proto.meminfo_counters(0)),
+        "size mismatch");
+    meminfo_counters_.back() =
+        static_cast<decltype(meminfo_counters_)::value_type>(field);
+  }
+
+  static_assert(sizeof(vmstat_period_ms_) == sizeof(proto.vmstat_period_ms()),
+                "size mismatch");
+  vmstat_period_ms_ =
+      static_cast<decltype(vmstat_period_ms_)>(proto.vmstat_period_ms());
+
+  vmstat_counters_.clear();
+  for (const auto& field : proto.vmstat_counters()) {
+    vmstat_counters_.emplace_back();
+    static_assert(
+        sizeof(vmstat_counters_.back()) == sizeof(proto.vmstat_counters(0)),
+        "size mismatch");
+    vmstat_counters_.back() =
+        static_cast<decltype(vmstat_counters_)::value_type>(field);
+  }
+
+  static_assert(sizeof(stat_period_ms_) == sizeof(proto.stat_period_ms()),
+                "size mismatch");
+  stat_period_ms_ =
+      static_cast<decltype(stat_period_ms_)>(proto.stat_period_ms());
+
+  stat_counters_.clear();
+  for (const auto& field : proto.stat_counters()) {
+    stat_counters_.emplace_back();
+    static_assert(
+        sizeof(stat_counters_.back()) == sizeof(proto.stat_counters(0)),
+        "size mismatch");
+    stat_counters_.back() =
+        static_cast<decltype(stat_counters_)::value_type>(field);
+  }
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void SysStatsConfig::ToProto(perfetto::protos::SysStatsConfig* proto) const {
+  proto->Clear();
+
+  static_assert(
+      sizeof(meminfo_period_ms_) == sizeof(proto->meminfo_period_ms()),
+      "size mismatch");
+  proto->set_meminfo_period_ms(
+      static_cast<decltype(proto->meminfo_period_ms())>(meminfo_period_ms_));
+
+  for (const auto& it : meminfo_counters_) {
+    proto->add_meminfo_counters(
+        static_cast<decltype(proto->meminfo_counters(0))>(it));
+    static_assert(sizeof(it) == sizeof(proto->meminfo_counters(0)),
+                  "size mismatch");
+  }
+
+  static_assert(sizeof(vmstat_period_ms_) == sizeof(proto->vmstat_period_ms()),
+                "size mismatch");
+  proto->set_vmstat_period_ms(
+      static_cast<decltype(proto->vmstat_period_ms())>(vmstat_period_ms_));
+
+  for (const auto& it : vmstat_counters_) {
+    proto->add_vmstat_counters(
+        static_cast<decltype(proto->vmstat_counters(0))>(it));
+    static_assert(sizeof(it) == sizeof(proto->vmstat_counters(0)),
+                  "size mismatch");
+  }
+
+  static_assert(sizeof(stat_period_ms_) == sizeof(proto->stat_period_ms()),
+                "size mismatch");
+  proto->set_stat_period_ms(
+      static_cast<decltype(proto->stat_period_ms())>(stat_period_ms_));
+
+  for (const auto& it : stat_counters_) {
+    proto->add_stat_counters(
+        static_cast<decltype(proto->stat_counters(0))>(it));
+    static_assert(sizeof(it) == sizeof(proto->stat_counters(0)),
+                  "size mismatch");
+  }
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+}  // namespace perfetto
diff --git a/src/tracing/core/sys_stats_counters.cc b/src/tracing/core/sys_stats_counters.cc
new file mode 100644
index 0000000..6224538
--- /dev/null
+++ b/src/tracing/core/sys_stats_counters.cc
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/common/sys_stats_counters.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/sys_stats_counters.h"
+
+#include "perfetto/common/sys_stats_counters.pb.h"
+
+namespace perfetto {}  // namespace perfetto
diff --git a/src/tracing/core/test_config.cc b/src/tracing/core/test_config.cc
new file mode 100644
index 0000000..582128a
--- /dev/null
+++ b/src/tracing/core/test_config.cc
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/test_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/test_config.h"
+
+#include "perfetto/config/test_config.pb.h"
+
+namespace perfetto {
+
+TestConfig::TestConfig() = default;
+TestConfig::~TestConfig() = default;
+TestConfig::TestConfig(const TestConfig&) = default;
+TestConfig& TestConfig::operator=(const TestConfig&) = default;
+TestConfig::TestConfig(TestConfig&&) noexcept = default;
+TestConfig& TestConfig::operator=(TestConfig&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool TestConfig::operator==(const TestConfig& other) const {
+  return (message_count_ == other.message_count_) &&
+         (max_messages_per_second_ == other.max_messages_per_second_) &&
+         (seed_ == other.seed_) && (message_size_ == other.message_size_) &&
+         (send_batch_on_register_ == other.send_batch_on_register_) &&
+         (dummy_fields_ == other.dummy_fields_);
+}
+#pragma GCC diagnostic pop
+
+void TestConfig::FromProto(const perfetto::protos::TestConfig& proto) {
+  static_assert(sizeof(message_count_) == sizeof(proto.message_count()),
+                "size mismatch");
+  message_count_ = static_cast<decltype(message_count_)>(proto.message_count());
+
+  static_assert(sizeof(max_messages_per_second_) ==
+                    sizeof(proto.max_messages_per_second()),
+                "size mismatch");
+  max_messages_per_second_ = static_cast<decltype(max_messages_per_second_)>(
+      proto.max_messages_per_second());
+
+  static_assert(sizeof(seed_) == sizeof(proto.seed()), "size mismatch");
+  seed_ = static_cast<decltype(seed_)>(proto.seed());
+
+  static_assert(sizeof(message_size_) == sizeof(proto.message_size()),
+                "size mismatch");
+  message_size_ = static_cast<decltype(message_size_)>(proto.message_size());
+
+  static_assert(
+      sizeof(send_batch_on_register_) == sizeof(proto.send_batch_on_register()),
+      "size mismatch");
+  send_batch_on_register_ = static_cast<decltype(send_batch_on_register_)>(
+      proto.send_batch_on_register());
+
+  dummy_fields_.FromProto(proto.dummy_fields());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void TestConfig::ToProto(perfetto::protos::TestConfig* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(message_count_) == sizeof(proto->message_count()),
+                "size mismatch");
+  proto->set_message_count(
+      static_cast<decltype(proto->message_count())>(message_count_));
+
+  static_assert(sizeof(max_messages_per_second_) ==
+                    sizeof(proto->max_messages_per_second()),
+                "size mismatch");
+  proto->set_max_messages_per_second(
+      static_cast<decltype(proto->max_messages_per_second())>(
+          max_messages_per_second_));
+
+  static_assert(sizeof(seed_) == sizeof(proto->seed()), "size mismatch");
+  proto->set_seed(static_cast<decltype(proto->seed())>(seed_));
+
+  static_assert(sizeof(message_size_) == sizeof(proto->message_size()),
+                "size mismatch");
+  proto->set_message_size(
+      static_cast<decltype(proto->message_size())>(message_size_));
+
+  static_assert(sizeof(send_batch_on_register_) ==
+                    sizeof(proto->send_batch_on_register()),
+                "size mismatch");
+  proto->set_send_batch_on_register(
+      static_cast<decltype(proto->send_batch_on_register())>(
+          send_batch_on_register_));
+
+  dummy_fields_.ToProto(proto->mutable_dummy_fields());
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+TestConfig::DummyFields::DummyFields() = default;
+TestConfig::DummyFields::~DummyFields() = default;
+TestConfig::DummyFields::DummyFields(const TestConfig::DummyFields&) = default;
+TestConfig::DummyFields& TestConfig::DummyFields::operator=(
+    const TestConfig::DummyFields&) = default;
+TestConfig::DummyFields::DummyFields(TestConfig::DummyFields&&) noexcept =
+    default;
+TestConfig::DummyFields& TestConfig::DummyFields::operator=(
+    TestConfig::DummyFields&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool TestConfig::DummyFields::operator==(
+    const TestConfig::DummyFields& other) const {
+  return (field_uint32_ == other.field_uint32_) &&
+         (field_int32_ == other.field_int32_) &&
+         (field_uint64_ == other.field_uint64_) &&
+         (field_int64_ == other.field_int64_) &&
+         (field_fixed64_ == other.field_fixed64_) &&
+         (field_sfixed64_ == other.field_sfixed64_) &&
+         (field_fixed32_ == other.field_fixed32_) &&
+         (field_sfixed32_ == other.field_sfixed32_) &&
+         (field_double_ == other.field_double_) &&
+         (field_float_ == other.field_float_) &&
+         (field_sint64_ == other.field_sint64_) &&
+         (field_sint32_ == other.field_sint32_) &&
+         (field_string_ == other.field_string_) &&
+         (field_bytes_ == other.field_bytes_);
+}
+#pragma GCC diagnostic pop
+
+void TestConfig::DummyFields::FromProto(
+    const perfetto::protos::TestConfig_DummyFields& proto) {
+  static_assert(sizeof(field_uint32_) == sizeof(proto.field_uint32()),
+                "size mismatch");
+  field_uint32_ = static_cast<decltype(field_uint32_)>(proto.field_uint32());
+
+  static_assert(sizeof(field_int32_) == sizeof(proto.field_int32()),
+                "size mismatch");
+  field_int32_ = static_cast<decltype(field_int32_)>(proto.field_int32());
+
+  static_assert(sizeof(field_uint64_) == sizeof(proto.field_uint64()),
+                "size mismatch");
+  field_uint64_ = static_cast<decltype(field_uint64_)>(proto.field_uint64());
+
+  static_assert(sizeof(field_int64_) == sizeof(proto.field_int64()),
+                "size mismatch");
+  field_int64_ = static_cast<decltype(field_int64_)>(proto.field_int64());
+
+  static_assert(sizeof(field_fixed64_) == sizeof(proto.field_fixed64()),
+                "size mismatch");
+  field_fixed64_ = static_cast<decltype(field_fixed64_)>(proto.field_fixed64());
+
+  static_assert(sizeof(field_sfixed64_) == sizeof(proto.field_sfixed64()),
+                "size mismatch");
+  field_sfixed64_ =
+      static_cast<decltype(field_sfixed64_)>(proto.field_sfixed64());
+
+  static_assert(sizeof(field_fixed32_) == sizeof(proto.field_fixed32()),
+                "size mismatch");
+  field_fixed32_ = static_cast<decltype(field_fixed32_)>(proto.field_fixed32());
+
+  static_assert(sizeof(field_sfixed32_) == sizeof(proto.field_sfixed32()),
+                "size mismatch");
+  field_sfixed32_ =
+      static_cast<decltype(field_sfixed32_)>(proto.field_sfixed32());
+
+  static_assert(sizeof(field_double_) == sizeof(proto.field_double()),
+                "size mismatch");
+  field_double_ = static_cast<decltype(field_double_)>(proto.field_double());
+
+  static_assert(sizeof(field_float_) == sizeof(proto.field_float()),
+                "size mismatch");
+  field_float_ = static_cast<decltype(field_float_)>(proto.field_float());
+
+  static_assert(sizeof(field_sint64_) == sizeof(proto.field_sint64()),
+                "size mismatch");
+  field_sint64_ = static_cast<decltype(field_sint64_)>(proto.field_sint64());
+
+  static_assert(sizeof(field_sint32_) == sizeof(proto.field_sint32()),
+                "size mismatch");
+  field_sint32_ = static_cast<decltype(field_sint32_)>(proto.field_sint32());
+
+  static_assert(sizeof(field_string_) == sizeof(proto.field_string()),
+                "size mismatch");
+  field_string_ = static_cast<decltype(field_string_)>(proto.field_string());
+
+  static_assert(sizeof(field_bytes_) == sizeof(proto.field_bytes()),
+                "size mismatch");
+  field_bytes_ = static_cast<decltype(field_bytes_)>(proto.field_bytes());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void TestConfig::DummyFields::ToProto(
+    perfetto::protos::TestConfig_DummyFields* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(field_uint32_) == sizeof(proto->field_uint32()),
+                "size mismatch");
+  proto->set_field_uint32(
+      static_cast<decltype(proto->field_uint32())>(field_uint32_));
+
+  static_assert(sizeof(field_int32_) == sizeof(proto->field_int32()),
+                "size mismatch");
+  proto->set_field_int32(
+      static_cast<decltype(proto->field_int32())>(field_int32_));
+
+  static_assert(sizeof(field_uint64_) == sizeof(proto->field_uint64()),
+                "size mismatch");
+  proto->set_field_uint64(
+      static_cast<decltype(proto->field_uint64())>(field_uint64_));
+
+  static_assert(sizeof(field_int64_) == sizeof(proto->field_int64()),
+                "size mismatch");
+  proto->set_field_int64(
+      static_cast<decltype(proto->field_int64())>(field_int64_));
+
+  static_assert(sizeof(field_fixed64_) == sizeof(proto->field_fixed64()),
+                "size mismatch");
+  proto->set_field_fixed64(
+      static_cast<decltype(proto->field_fixed64())>(field_fixed64_));
+
+  static_assert(sizeof(field_sfixed64_) == sizeof(proto->field_sfixed64()),
+                "size mismatch");
+  proto->set_field_sfixed64(
+      static_cast<decltype(proto->field_sfixed64())>(field_sfixed64_));
+
+  static_assert(sizeof(field_fixed32_) == sizeof(proto->field_fixed32()),
+                "size mismatch");
+  proto->set_field_fixed32(
+      static_cast<decltype(proto->field_fixed32())>(field_fixed32_));
+
+  static_assert(sizeof(field_sfixed32_) == sizeof(proto->field_sfixed32()),
+                "size mismatch");
+  proto->set_field_sfixed32(
+      static_cast<decltype(proto->field_sfixed32())>(field_sfixed32_));
+
+  static_assert(sizeof(field_double_) == sizeof(proto->field_double()),
+                "size mismatch");
+  proto->set_field_double(
+      static_cast<decltype(proto->field_double())>(field_double_));
+
+  static_assert(sizeof(field_float_) == sizeof(proto->field_float()),
+                "size mismatch");
+  proto->set_field_float(
+      static_cast<decltype(proto->field_float())>(field_float_));
+
+  static_assert(sizeof(field_sint64_) == sizeof(proto->field_sint64()),
+                "size mismatch");
+  proto->set_field_sint64(
+      static_cast<decltype(proto->field_sint64())>(field_sint64_));
+
+  static_assert(sizeof(field_sint32_) == sizeof(proto->field_sint32()),
+                "size mismatch");
+  proto->set_field_sint32(
+      static_cast<decltype(proto->field_sint32())>(field_sint32_));
+
+  static_assert(sizeof(field_string_) == sizeof(proto->field_string()),
+                "size mismatch");
+  proto->set_field_string(
+      static_cast<decltype(proto->field_string())>(field_string_));
+
+  static_assert(sizeof(field_bytes_) == sizeof(proto->field_bytes()),
+                "size mismatch");
+  proto->set_field_bytes(
+      static_cast<decltype(proto->field_bytes())>(field_bytes_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+}  // namespace perfetto
diff --git a/src/tracing/core/trace_buffer.cc b/src/tracing/core/trace_buffer.cc
index d00e53c..4af9b6d 100644
--- a/src/tracing/core/trace_buffer.cc
+++ b/src/tracing/core/trace_buffer.cc
@@ -19,10 +19,9 @@
 #include <limits>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/tracing/core/shared_memory_abi.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
 #include "perfetto/protozero/proto_utils.h"
+#include "perfetto/tracing/core/shared_memory_abi.h"
+#include "perfetto/tracing/core/trace_packet.h"
 
 #define TRACE_BUFFER_VERBOSE_LOGGING() 0  // Set to 1 when debugging unittests.
 #if TRACE_BUFFER_VERBOSE_LOGGING()
@@ -135,11 +134,7 @@
   if (PERFETTO_UNLIKELY(!chunk_complete)) {
     if (num_fragments > 0) {
       num_fragments--;
-      // These flags should only affect the last packet in the chunk. We clear
-      // them, so that TraceBuffer is able to look at the remaining packets in
-      // this chunk.
       chunk_flags &= ~kLastPacketContinuesOnNextChunk;
-      chunk_flags &= ~kChunkNeedsPatching;
     }
   }
 
@@ -366,11 +361,11 @@
         index_delete.push_back(it);
         will_remove = true;
       }
-      TRACE_BUFFER_DLOG(
-          "  del index {%" PRIu32 ",%" PRIu32 ",%u} @ [%lu - %lu] %d",
-          key.producer_id, key.writer_id, key.chunk_id,
-          next_chunk_ptr - begin(), next_chunk_ptr - begin() + next_chunk.size,
-          will_remove);
+      TRACE_BUFFER_DLOG("  del index {%" PRIu32 ",%" PRIu32
+                        ",%u} @ [%lu - %lu] %d",
+                        key.producer_id, key.writer_id, key.chunk_id,
+                        next_chunk_ptr - begin(),
+                        next_chunk_ptr - begin() + next_chunk.size, removed);
       PERFETTO_DCHECK(will_remove);
     } else {
       padding_bytes_cleared += next_chunk.size;
@@ -848,17 +843,8 @@
   const uint8_t* next_packet = packet_data + packet_size;
   if (PERFETTO_UNLIKELY(next_packet <= packet_begin ||
                         next_packet > record_end)) {
-    // In BufferExhaustedPolicy::kDrop mode, TraceWriter may abort a fragmented
-    // packet by writing an invalid size in the last fragment's header. We
-    // should handle this case without recording an ABI violation (since Android
-    // R).
-    if (packet_size != SharedMemoryABI::kPacketSizeDropPacket) {
-      stats_.set_abi_violations(stats_.abi_violations() + 1);
-      PERFETTO_DCHECK(suppress_sanity_dchecks_for_testing_);
-    } else {
-      stats_.set_trace_writer_packet_loss(stats_.trace_writer_packet_loss() +
-                                          1);
-    }
+    stats_.set_abi_violations(stats_.abi_violations() + 1);
+    PERFETTO_DCHECK(suppress_sanity_dchecks_for_testing_);
     chunk_meta->cur_fragment_offset = 0;
     chunk_meta->num_fragments_read = chunk_meta->num_fragments;
     if (PERFETTO_LIKELY(chunk_meta->is_complete())) {
diff --git a/src/tracing/core/trace_buffer.h b/src/tracing/core/trace_buffer.h
index a95c2f6..35bd5fb 100644
--- a/src/tracing/core/trace_buffer.h
+++ b/src/tracing/core/trace_buffer.h
@@ -26,12 +26,11 @@
 #include <tuple>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/paged_memory.h"
-#include "perfetto/ext/base/thread_annotations.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/slice.h"
-#include "perfetto/ext/tracing/core/trace_stats.h"
+#include "perfetto/base/paged_memory.h"
+#include "perfetto/base/thread_annotations.h"
+#include "perfetto/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/slice.h"
+#include "perfetto/tracing/core/trace_stats.h"
 
 namespace perfetto {
 
@@ -263,7 +262,7 @@
   // | ChunkRecord 1 | Chunk payload 1  || ChunkRecord 2 | Chunk payload 2 | ...
   // +---------------+------------------++---------------+-----------------+
   // Most of the ChunkRecord fields are copied from SharedMemoryABI::ChunkHeader
-  // (the chunk header used in the shared memory buffers).
+  // (the chunk header used in the the shared memory buffers).
   // A ChunkRecord can be a special "padding" record. In this case its payload
   // should be ignored and the record should be just skipped.
   //
@@ -597,7 +596,7 @@
       // to read (assuming a well-behaving client), but the risk of introducing
       // a bug that way outweighs the benefit.
       PERFETTO_ANNOTATE_BENIGN_RACE_SIZED(
-          src, size, "Benign race when copying chunk from shared memory.")
+          src, size, "Benign race when copying chunk from shared memory.");
       memcpy(wptr + sizeof(record), src, size);
     } else {
       PERFETTO_DCHECK(size == record.size - sizeof(record));
diff --git a/src/tracing/core/trace_buffer_unittest.cc b/src/tracing/core/trace_buffer_unittest.cc
index f7012a5..b1f60ca 100644
--- a/src/tracing/core/trace_buffer_unittest.cc
+++ b/src/tracing/core/trace_buffer_unittest.cc
@@ -21,14 +21,15 @@
 #include <sstream>
 #include <vector>
 
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/shared_memory_abi.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
 #include "perfetto/protozero/proto_utils.h"
+#include "perfetto/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/shared_memory_abi.h"
+#include "perfetto/tracing/core/trace_packet.h"
 #include "src/tracing/core/trace_buffer.h"
 #include "src/tracing/test/fake_packet.h"
-#include "test/gtest_and_gmock.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 
@@ -807,43 +808,6 @@
   ASSERT_THAT(ReadPacket(), IsEmpty());
 }
 
-TEST_F(TraceBufferTest, Fragments_DiscardedOnPacketSizeDropPacket) {
-  ResetBuffer(4096);
-  // Set up a fragmented packet in the first chunk, which continues in the
-  // second chunk with kPacketSizeDropPacket size. The corrupted fragmented
-  // packet should be skipped.
-  CreateChunk(ProducerID(1), WriterID(1), ChunkID(0))
-      .AddPacket(10, 'a')
-      .AddPacket(10, 'b', kContOnNextChunk)
-      .CopyIntoTraceBuffer();
-  CreateChunk(ProducerID(1), WriterID(1), ChunkID(1))
-      .SetFlags(kContFromPrevChunk)
-      // Var-int encoded TraceWriterImpl::kPacketSizeDropPacket.
-      .AddPacket({0xff, 0xff, 0xff, 0x7f})
-      .CopyIntoTraceBuffer();
-  CreateChunk(ProducerID(1), WriterID(1), ChunkID(2))
-      .AddPacket(10, 'd')
-      .CopyIntoTraceBuffer();
-  trace_buffer()->BeginRead();
-  ASSERT_THAT(ReadPacket(), ElementsAre(FakePacketFragment(10, 'a')));
-  ASSERT_THAT(ReadPacket(), ElementsAre(FakePacketFragment(10, 'd')));
-  ASSERT_THAT(ReadPacket(), IsEmpty());
-}
-
-TEST_F(TraceBufferTest, Fragments_IncompleteChunkNeedsPatching) {
-  ResetBuffer(4096);
-  CreateChunk(ProducerID(1), WriterID(1), ChunkID(0))
-      .AddPacket(20, 'a')
-      .AddPacket(30, 'b', kContOnNextChunk | kChunkNeedsPatching)
-      .PadTo(512)
-      .CopyIntoTraceBuffer(/*chunk_complete=*/false);
-  trace_buffer()->BeginRead();
-  // First packet should be read even if the chunk's last packet still needs
-  // patching.
-  ASSERT_THAT(ReadPacket(), ElementsAre(FakePacketFragment(20, 'a')));
-  ASSERT_THAT(ReadPacket(), IsEmpty());
-}
-
 // --------------------------
 // Out of band patching tests
 // --------------------------
diff --git a/src/tracing/core/trace_config.cc b/src/tracing/core/trace_config.cc
new file mode 100644
index 0000000..468d04c
--- /dev/null
+++ b/src/tracing/core/trace_config.cc
@@ -0,0 +1,881 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/config/trace_config.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/trace_config.h"
+
+#include "perfetto/config/data_source_config.pb.h"
+#include "perfetto/config/trace_config.pb.h"
+
+namespace perfetto {
+
+TraceConfig::TraceConfig() = default;
+TraceConfig::~TraceConfig() = default;
+TraceConfig::TraceConfig(const TraceConfig&) = default;
+TraceConfig& TraceConfig::operator=(const TraceConfig&) = default;
+TraceConfig::TraceConfig(TraceConfig&&) noexcept = default;
+TraceConfig& TraceConfig::operator=(TraceConfig&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool TraceConfig::operator==(const TraceConfig& other) const {
+  return (buffers_ == other.buffers_) &&
+         (data_sources_ == other.data_sources_) &&
+         (builtin_data_sources_ == other.builtin_data_sources_) &&
+         (duration_ms_ == other.duration_ms_) &&
+         (enable_extra_guardrails_ == other.enable_extra_guardrails_) &&
+         (lockdown_mode_ == other.lockdown_mode_) &&
+         (producers_ == other.producers_) &&
+         (statsd_metadata_ == other.statsd_metadata_) &&
+         (write_into_file_ == other.write_into_file_) &&
+         (file_write_period_ms_ == other.file_write_period_ms_) &&
+         (max_file_size_bytes_ == other.max_file_size_bytes_) &&
+         (guardrail_overrides_ == other.guardrail_overrides_) &&
+         (deferred_start_ == other.deferred_start_) &&
+         (flush_period_ms_ == other.flush_period_ms_) &&
+         (flush_timeout_ms_ == other.flush_timeout_ms_) &&
+         (notify_traceur_ == other.notify_traceur_) &&
+         (trigger_config_ == other.trigger_config_) &&
+         (activate_triggers_ == other.activate_triggers_) &&
+         (incremental_state_config_ == other.incremental_state_config_) &&
+         (allow_user_build_tracing_ == other.allow_user_build_tracing_) &&
+         (unique_session_name_ == other.unique_session_name_) &&
+         (compression_type_ == other.compression_type_) &&
+         (incident_report_config_ == other.incident_report_config_);
+}
+#pragma GCC diagnostic pop
+
+void TraceConfig::FromProto(const perfetto::protos::TraceConfig& proto) {
+  buffers_.clear();
+  for (const auto& field : proto.buffers()) {
+    buffers_.emplace_back();
+    buffers_.back().FromProto(field);
+  }
+
+  data_sources_.clear();
+  for (const auto& field : proto.data_sources()) {
+    data_sources_.emplace_back();
+    data_sources_.back().FromProto(field);
+  }
+
+  builtin_data_sources_.FromProto(proto.builtin_data_sources());
+
+  static_assert(sizeof(duration_ms_) == sizeof(proto.duration_ms()),
+                "size mismatch");
+  duration_ms_ = static_cast<decltype(duration_ms_)>(proto.duration_ms());
+
+  static_assert(sizeof(enable_extra_guardrails_) ==
+                    sizeof(proto.enable_extra_guardrails()),
+                "size mismatch");
+  enable_extra_guardrails_ = static_cast<decltype(enable_extra_guardrails_)>(
+      proto.enable_extra_guardrails());
+
+  static_assert(sizeof(lockdown_mode_) == sizeof(proto.lockdown_mode()),
+                "size mismatch");
+  lockdown_mode_ = static_cast<decltype(lockdown_mode_)>(proto.lockdown_mode());
+
+  producers_.clear();
+  for (const auto& field : proto.producers()) {
+    producers_.emplace_back();
+    producers_.back().FromProto(field);
+  }
+
+  statsd_metadata_.FromProto(proto.statsd_metadata());
+
+  static_assert(sizeof(write_into_file_) == sizeof(proto.write_into_file()),
+                "size mismatch");
+  write_into_file_ =
+      static_cast<decltype(write_into_file_)>(proto.write_into_file());
+
+  static_assert(
+      sizeof(file_write_period_ms_) == sizeof(proto.file_write_period_ms()),
+      "size mismatch");
+  file_write_period_ms_ = static_cast<decltype(file_write_period_ms_)>(
+      proto.file_write_period_ms());
+
+  static_assert(
+      sizeof(max_file_size_bytes_) == sizeof(proto.max_file_size_bytes()),
+      "size mismatch");
+  max_file_size_bytes_ =
+      static_cast<decltype(max_file_size_bytes_)>(proto.max_file_size_bytes());
+
+  guardrail_overrides_.FromProto(proto.guardrail_overrides());
+
+  static_assert(sizeof(deferred_start_) == sizeof(proto.deferred_start()),
+                "size mismatch");
+  deferred_start_ =
+      static_cast<decltype(deferred_start_)>(proto.deferred_start());
+
+  static_assert(sizeof(flush_period_ms_) == sizeof(proto.flush_period_ms()),
+                "size mismatch");
+  flush_period_ms_ =
+      static_cast<decltype(flush_period_ms_)>(proto.flush_period_ms());
+
+  static_assert(sizeof(flush_timeout_ms_) == sizeof(proto.flush_timeout_ms()),
+                "size mismatch");
+  flush_timeout_ms_ =
+      static_cast<decltype(flush_timeout_ms_)>(proto.flush_timeout_ms());
+
+  static_assert(sizeof(notify_traceur_) == sizeof(proto.notify_traceur()),
+                "size mismatch");
+  notify_traceur_ =
+      static_cast<decltype(notify_traceur_)>(proto.notify_traceur());
+
+  trigger_config_.FromProto(proto.trigger_config());
+
+  activate_triggers_.clear();
+  for (const auto& field : proto.activate_triggers()) {
+    activate_triggers_.emplace_back();
+    static_assert(
+        sizeof(activate_triggers_.back()) == sizeof(proto.activate_triggers(0)),
+        "size mismatch");
+    activate_triggers_.back() =
+        static_cast<decltype(activate_triggers_)::value_type>(field);
+  }
+
+  incremental_state_config_.FromProto(proto.incremental_state_config());
+
+  static_assert(sizeof(allow_user_build_tracing_) ==
+                    sizeof(proto.allow_user_build_tracing()),
+                "size mismatch");
+  allow_user_build_tracing_ = static_cast<decltype(allow_user_build_tracing_)>(
+      proto.allow_user_build_tracing());
+
+  static_assert(
+      sizeof(unique_session_name_) == sizeof(proto.unique_session_name()),
+      "size mismatch");
+  unique_session_name_ =
+      static_cast<decltype(unique_session_name_)>(proto.unique_session_name());
+
+  static_assert(sizeof(compression_type_) == sizeof(proto.compression_type()),
+                "size mismatch");
+  compression_type_ =
+      static_cast<decltype(compression_type_)>(proto.compression_type());
+
+  incident_report_config_.FromProto(proto.incident_report_config());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void TraceConfig::ToProto(perfetto::protos::TraceConfig* proto) const {
+  proto->Clear();
+
+  for (const auto& it : buffers_) {
+    auto* entry = proto->add_buffers();
+    it.ToProto(entry);
+  }
+
+  for (const auto& it : data_sources_) {
+    auto* entry = proto->add_data_sources();
+    it.ToProto(entry);
+  }
+
+  builtin_data_sources_.ToProto(proto->mutable_builtin_data_sources());
+
+  static_assert(sizeof(duration_ms_) == sizeof(proto->duration_ms()),
+                "size mismatch");
+  proto->set_duration_ms(
+      static_cast<decltype(proto->duration_ms())>(duration_ms_));
+
+  static_assert(sizeof(enable_extra_guardrails_) ==
+                    sizeof(proto->enable_extra_guardrails()),
+                "size mismatch");
+  proto->set_enable_extra_guardrails(
+      static_cast<decltype(proto->enable_extra_guardrails())>(
+          enable_extra_guardrails_));
+
+  static_assert(sizeof(lockdown_mode_) == sizeof(proto->lockdown_mode()),
+                "size mismatch");
+  proto->set_lockdown_mode(
+      static_cast<decltype(proto->lockdown_mode())>(lockdown_mode_));
+
+  for (const auto& it : producers_) {
+    auto* entry = proto->add_producers();
+    it.ToProto(entry);
+  }
+
+  statsd_metadata_.ToProto(proto->mutable_statsd_metadata());
+
+  static_assert(sizeof(write_into_file_) == sizeof(proto->write_into_file()),
+                "size mismatch");
+  proto->set_write_into_file(
+      static_cast<decltype(proto->write_into_file())>(write_into_file_));
+
+  static_assert(
+      sizeof(file_write_period_ms_) == sizeof(proto->file_write_period_ms()),
+      "size mismatch");
+  proto->set_file_write_period_ms(
+      static_cast<decltype(proto->file_write_period_ms())>(
+          file_write_period_ms_));
+
+  static_assert(
+      sizeof(max_file_size_bytes_) == sizeof(proto->max_file_size_bytes()),
+      "size mismatch");
+  proto->set_max_file_size_bytes(
+      static_cast<decltype(proto->max_file_size_bytes())>(
+          max_file_size_bytes_));
+
+  guardrail_overrides_.ToProto(proto->mutable_guardrail_overrides());
+
+  static_assert(sizeof(deferred_start_) == sizeof(proto->deferred_start()),
+                "size mismatch");
+  proto->set_deferred_start(
+      static_cast<decltype(proto->deferred_start())>(deferred_start_));
+
+  static_assert(sizeof(flush_period_ms_) == sizeof(proto->flush_period_ms()),
+                "size mismatch");
+  proto->set_flush_period_ms(
+      static_cast<decltype(proto->flush_period_ms())>(flush_period_ms_));
+
+  static_assert(sizeof(flush_timeout_ms_) == sizeof(proto->flush_timeout_ms()),
+                "size mismatch");
+  proto->set_flush_timeout_ms(
+      static_cast<decltype(proto->flush_timeout_ms())>(flush_timeout_ms_));
+
+  static_assert(sizeof(notify_traceur_) == sizeof(proto->notify_traceur()),
+                "size mismatch");
+  proto->set_notify_traceur(
+      static_cast<decltype(proto->notify_traceur())>(notify_traceur_));
+
+  trigger_config_.ToProto(proto->mutable_trigger_config());
+
+  for (const auto& it : activate_triggers_) {
+    proto->add_activate_triggers(
+        static_cast<decltype(proto->activate_triggers(0))>(it));
+    static_assert(sizeof(it) == sizeof(proto->activate_triggers(0)),
+                  "size mismatch");
+  }
+
+  incremental_state_config_.ToProto(proto->mutable_incremental_state_config());
+
+  static_assert(sizeof(allow_user_build_tracing_) ==
+                    sizeof(proto->allow_user_build_tracing()),
+                "size mismatch");
+  proto->set_allow_user_build_tracing(
+      static_cast<decltype(proto->allow_user_build_tracing())>(
+          allow_user_build_tracing_));
+
+  static_assert(
+      sizeof(unique_session_name_) == sizeof(proto->unique_session_name()),
+      "size mismatch");
+  proto->set_unique_session_name(
+      static_cast<decltype(proto->unique_session_name())>(
+          unique_session_name_));
+
+  static_assert(sizeof(compression_type_) == sizeof(proto->compression_type()),
+                "size mismatch");
+  proto->set_compression_type(
+      static_cast<decltype(proto->compression_type())>(compression_type_));
+
+  incident_report_config_.ToProto(proto->mutable_incident_report_config());
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+TraceConfig::BufferConfig::BufferConfig() = default;
+TraceConfig::BufferConfig::~BufferConfig() = default;
+TraceConfig::BufferConfig::BufferConfig(const TraceConfig::BufferConfig&) =
+    default;
+TraceConfig::BufferConfig& TraceConfig::BufferConfig::operator=(
+    const TraceConfig::BufferConfig&) = default;
+TraceConfig::BufferConfig::BufferConfig(TraceConfig::BufferConfig&&) noexcept =
+    default;
+TraceConfig::BufferConfig& TraceConfig::BufferConfig::operator=(
+    TraceConfig::BufferConfig&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool TraceConfig::BufferConfig::operator==(
+    const TraceConfig::BufferConfig& other) const {
+  return (size_kb_ == other.size_kb_) && (fill_policy_ == other.fill_policy_);
+}
+#pragma GCC diagnostic pop
+
+void TraceConfig::BufferConfig::FromProto(
+    const perfetto::protos::TraceConfig_BufferConfig& proto) {
+  static_assert(sizeof(size_kb_) == sizeof(proto.size_kb()), "size mismatch");
+  size_kb_ = static_cast<decltype(size_kb_)>(proto.size_kb());
+
+  static_assert(sizeof(fill_policy_) == sizeof(proto.fill_policy()),
+                "size mismatch");
+  fill_policy_ = static_cast<decltype(fill_policy_)>(proto.fill_policy());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void TraceConfig::BufferConfig::ToProto(
+    perfetto::protos::TraceConfig_BufferConfig* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(size_kb_) == sizeof(proto->size_kb()), "size mismatch");
+  proto->set_size_kb(static_cast<decltype(proto->size_kb())>(size_kb_));
+
+  static_assert(sizeof(fill_policy_) == sizeof(proto->fill_policy()),
+                "size mismatch");
+  proto->set_fill_policy(
+      static_cast<decltype(proto->fill_policy())>(fill_policy_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+TraceConfig::DataSource::DataSource() = default;
+TraceConfig::DataSource::~DataSource() = default;
+TraceConfig::DataSource::DataSource(const TraceConfig::DataSource&) = default;
+TraceConfig::DataSource& TraceConfig::DataSource::operator=(
+    const TraceConfig::DataSource&) = default;
+TraceConfig::DataSource::DataSource(TraceConfig::DataSource&&) noexcept =
+    default;
+TraceConfig::DataSource& TraceConfig::DataSource::operator=(
+    TraceConfig::DataSource&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool TraceConfig::DataSource::operator==(
+    const TraceConfig::DataSource& other) const {
+  return (config_ == other.config_) &&
+         (producer_name_filter_ == other.producer_name_filter_);
+}
+#pragma GCC diagnostic pop
+
+void TraceConfig::DataSource::FromProto(
+    const perfetto::protos::TraceConfig_DataSource& proto) {
+  config_.FromProto(proto.config());
+
+  producer_name_filter_.clear();
+  for (const auto& field : proto.producer_name_filter()) {
+    producer_name_filter_.emplace_back();
+    static_assert(sizeof(producer_name_filter_.back()) ==
+                      sizeof(proto.producer_name_filter(0)),
+                  "size mismatch");
+    producer_name_filter_.back() =
+        static_cast<decltype(producer_name_filter_)::value_type>(field);
+  }
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void TraceConfig::DataSource::ToProto(
+    perfetto::protos::TraceConfig_DataSource* proto) const {
+  proto->Clear();
+
+  config_.ToProto(proto->mutable_config());
+
+  for (const auto& it : producer_name_filter_) {
+    proto->add_producer_name_filter(
+        static_cast<decltype(proto->producer_name_filter(0))>(it));
+    static_assert(sizeof(it) == sizeof(proto->producer_name_filter(0)),
+                  "size mismatch");
+  }
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+TraceConfig::BuiltinDataSource::BuiltinDataSource() = default;
+TraceConfig::BuiltinDataSource::~BuiltinDataSource() = default;
+TraceConfig::BuiltinDataSource::BuiltinDataSource(
+    const TraceConfig::BuiltinDataSource&) = default;
+TraceConfig::BuiltinDataSource& TraceConfig::BuiltinDataSource::operator=(
+    const TraceConfig::BuiltinDataSource&) = default;
+TraceConfig::BuiltinDataSource::BuiltinDataSource(
+    TraceConfig::BuiltinDataSource&&) noexcept = default;
+TraceConfig::BuiltinDataSource& TraceConfig::BuiltinDataSource::operator=(
+    TraceConfig::BuiltinDataSource&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool TraceConfig::BuiltinDataSource::operator==(
+    const TraceConfig::BuiltinDataSource& other) const {
+  return (disable_clock_snapshotting_ == other.disable_clock_snapshotting_) &&
+         (disable_trace_config_ == other.disable_trace_config_) &&
+         (disable_system_info_ == other.disable_system_info_);
+}
+#pragma GCC diagnostic pop
+
+void TraceConfig::BuiltinDataSource::FromProto(
+    const perfetto::protos::TraceConfig_BuiltinDataSource& proto) {
+  static_assert(sizeof(disable_clock_snapshotting_) ==
+                    sizeof(proto.disable_clock_snapshotting()),
+                "size mismatch");
+  disable_clock_snapshotting_ =
+      static_cast<decltype(disable_clock_snapshotting_)>(
+          proto.disable_clock_snapshotting());
+
+  static_assert(
+      sizeof(disable_trace_config_) == sizeof(proto.disable_trace_config()),
+      "size mismatch");
+  disable_trace_config_ = static_cast<decltype(disable_trace_config_)>(
+      proto.disable_trace_config());
+
+  static_assert(
+      sizeof(disable_system_info_) == sizeof(proto.disable_system_info()),
+      "size mismatch");
+  disable_system_info_ =
+      static_cast<decltype(disable_system_info_)>(proto.disable_system_info());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void TraceConfig::BuiltinDataSource::ToProto(
+    perfetto::protos::TraceConfig_BuiltinDataSource* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(disable_clock_snapshotting_) ==
+                    sizeof(proto->disable_clock_snapshotting()),
+                "size mismatch");
+  proto->set_disable_clock_snapshotting(
+      static_cast<decltype(proto->disable_clock_snapshotting())>(
+          disable_clock_snapshotting_));
+
+  static_assert(
+      sizeof(disable_trace_config_) == sizeof(proto->disable_trace_config()),
+      "size mismatch");
+  proto->set_disable_trace_config(
+      static_cast<decltype(proto->disable_trace_config())>(
+          disable_trace_config_));
+
+  static_assert(
+      sizeof(disable_system_info_) == sizeof(proto->disable_system_info()),
+      "size mismatch");
+  proto->set_disable_system_info(
+      static_cast<decltype(proto->disable_system_info())>(
+          disable_system_info_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+TraceConfig::ProducerConfig::ProducerConfig() = default;
+TraceConfig::ProducerConfig::~ProducerConfig() = default;
+TraceConfig::ProducerConfig::ProducerConfig(
+    const TraceConfig::ProducerConfig&) = default;
+TraceConfig::ProducerConfig& TraceConfig::ProducerConfig::operator=(
+    const TraceConfig::ProducerConfig&) = default;
+TraceConfig::ProducerConfig::ProducerConfig(
+    TraceConfig::ProducerConfig&&) noexcept = default;
+TraceConfig::ProducerConfig& TraceConfig::ProducerConfig::operator=(
+    TraceConfig::ProducerConfig&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool TraceConfig::ProducerConfig::operator==(
+    const TraceConfig::ProducerConfig& other) const {
+  return (producer_name_ == other.producer_name_) &&
+         (shm_size_kb_ == other.shm_size_kb_) &&
+         (page_size_kb_ == other.page_size_kb_);
+}
+#pragma GCC diagnostic pop
+
+void TraceConfig::ProducerConfig::FromProto(
+    const perfetto::protos::TraceConfig_ProducerConfig& proto) {
+  static_assert(sizeof(producer_name_) == sizeof(proto.producer_name()),
+                "size mismatch");
+  producer_name_ = static_cast<decltype(producer_name_)>(proto.producer_name());
+
+  static_assert(sizeof(shm_size_kb_) == sizeof(proto.shm_size_kb()),
+                "size mismatch");
+  shm_size_kb_ = static_cast<decltype(shm_size_kb_)>(proto.shm_size_kb());
+
+  static_assert(sizeof(page_size_kb_) == sizeof(proto.page_size_kb()),
+                "size mismatch");
+  page_size_kb_ = static_cast<decltype(page_size_kb_)>(proto.page_size_kb());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void TraceConfig::ProducerConfig::ToProto(
+    perfetto::protos::TraceConfig_ProducerConfig* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(producer_name_) == sizeof(proto->producer_name()),
+                "size mismatch");
+  proto->set_producer_name(
+      static_cast<decltype(proto->producer_name())>(producer_name_));
+
+  static_assert(sizeof(shm_size_kb_) == sizeof(proto->shm_size_kb()),
+                "size mismatch");
+  proto->set_shm_size_kb(
+      static_cast<decltype(proto->shm_size_kb())>(shm_size_kb_));
+
+  static_assert(sizeof(page_size_kb_) == sizeof(proto->page_size_kb()),
+                "size mismatch");
+  proto->set_page_size_kb(
+      static_cast<decltype(proto->page_size_kb())>(page_size_kb_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+TraceConfig::StatsdMetadata::StatsdMetadata() = default;
+TraceConfig::StatsdMetadata::~StatsdMetadata() = default;
+TraceConfig::StatsdMetadata::StatsdMetadata(
+    const TraceConfig::StatsdMetadata&) = default;
+TraceConfig::StatsdMetadata& TraceConfig::StatsdMetadata::operator=(
+    const TraceConfig::StatsdMetadata&) = default;
+TraceConfig::StatsdMetadata::StatsdMetadata(
+    TraceConfig::StatsdMetadata&&) noexcept = default;
+TraceConfig::StatsdMetadata& TraceConfig::StatsdMetadata::operator=(
+    TraceConfig::StatsdMetadata&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool TraceConfig::StatsdMetadata::operator==(
+    const TraceConfig::StatsdMetadata& other) const {
+  return (triggering_alert_id_ == other.triggering_alert_id_) &&
+         (triggering_config_uid_ == other.triggering_config_uid_) &&
+         (triggering_config_id_ == other.triggering_config_id_) &&
+         (triggering_subscription_id_ == other.triggering_subscription_id_);
+}
+#pragma GCC diagnostic pop
+
+void TraceConfig::StatsdMetadata::FromProto(
+    const perfetto::protos::TraceConfig_StatsdMetadata& proto) {
+  static_assert(
+      sizeof(triggering_alert_id_) == sizeof(proto.triggering_alert_id()),
+      "size mismatch");
+  triggering_alert_id_ =
+      static_cast<decltype(triggering_alert_id_)>(proto.triggering_alert_id());
+
+  static_assert(
+      sizeof(triggering_config_uid_) == sizeof(proto.triggering_config_uid()),
+      "size mismatch");
+  triggering_config_uid_ = static_cast<decltype(triggering_config_uid_)>(
+      proto.triggering_config_uid());
+
+  static_assert(
+      sizeof(triggering_config_id_) == sizeof(proto.triggering_config_id()),
+      "size mismatch");
+  triggering_config_id_ = static_cast<decltype(triggering_config_id_)>(
+      proto.triggering_config_id());
+
+  static_assert(sizeof(triggering_subscription_id_) ==
+                    sizeof(proto.triggering_subscription_id()),
+                "size mismatch");
+  triggering_subscription_id_ =
+      static_cast<decltype(triggering_subscription_id_)>(
+          proto.triggering_subscription_id());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void TraceConfig::StatsdMetadata::ToProto(
+    perfetto::protos::TraceConfig_StatsdMetadata* proto) const {
+  proto->Clear();
+
+  static_assert(
+      sizeof(triggering_alert_id_) == sizeof(proto->triggering_alert_id()),
+      "size mismatch");
+  proto->set_triggering_alert_id(
+      static_cast<decltype(proto->triggering_alert_id())>(
+          triggering_alert_id_));
+
+  static_assert(
+      sizeof(triggering_config_uid_) == sizeof(proto->triggering_config_uid()),
+      "size mismatch");
+  proto->set_triggering_config_uid(
+      static_cast<decltype(proto->triggering_config_uid())>(
+          triggering_config_uid_));
+
+  static_assert(
+      sizeof(triggering_config_id_) == sizeof(proto->triggering_config_id()),
+      "size mismatch");
+  proto->set_triggering_config_id(
+      static_cast<decltype(proto->triggering_config_id())>(
+          triggering_config_id_));
+
+  static_assert(sizeof(triggering_subscription_id_) ==
+                    sizeof(proto->triggering_subscription_id()),
+                "size mismatch");
+  proto->set_triggering_subscription_id(
+      static_cast<decltype(proto->triggering_subscription_id())>(
+          triggering_subscription_id_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+TraceConfig::GuardrailOverrides::GuardrailOverrides() = default;
+TraceConfig::GuardrailOverrides::~GuardrailOverrides() = default;
+TraceConfig::GuardrailOverrides::GuardrailOverrides(
+    const TraceConfig::GuardrailOverrides&) = default;
+TraceConfig::GuardrailOverrides& TraceConfig::GuardrailOverrides::operator=(
+    const TraceConfig::GuardrailOverrides&) = default;
+TraceConfig::GuardrailOverrides::GuardrailOverrides(
+    TraceConfig::GuardrailOverrides&&) noexcept = default;
+TraceConfig::GuardrailOverrides& TraceConfig::GuardrailOverrides::operator=(
+    TraceConfig::GuardrailOverrides&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool TraceConfig::GuardrailOverrides::operator==(
+    const TraceConfig::GuardrailOverrides& other) const {
+  return (max_upload_per_day_bytes_ == other.max_upload_per_day_bytes_);
+}
+#pragma GCC diagnostic pop
+
+void TraceConfig::GuardrailOverrides::FromProto(
+    const perfetto::protos::TraceConfig_GuardrailOverrides& proto) {
+  static_assert(sizeof(max_upload_per_day_bytes_) ==
+                    sizeof(proto.max_upload_per_day_bytes()),
+                "size mismatch");
+  max_upload_per_day_bytes_ = static_cast<decltype(max_upload_per_day_bytes_)>(
+      proto.max_upload_per_day_bytes());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void TraceConfig::GuardrailOverrides::ToProto(
+    perfetto::protos::TraceConfig_GuardrailOverrides* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(max_upload_per_day_bytes_) ==
+                    sizeof(proto->max_upload_per_day_bytes()),
+                "size mismatch");
+  proto->set_max_upload_per_day_bytes(
+      static_cast<decltype(proto->max_upload_per_day_bytes())>(
+          max_upload_per_day_bytes_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+TraceConfig::TriggerConfig::TriggerConfig() = default;
+TraceConfig::TriggerConfig::~TriggerConfig() = default;
+TraceConfig::TriggerConfig::TriggerConfig(const TraceConfig::TriggerConfig&) =
+    default;
+TraceConfig::TriggerConfig& TraceConfig::TriggerConfig::operator=(
+    const TraceConfig::TriggerConfig&) = default;
+TraceConfig::TriggerConfig::TriggerConfig(
+    TraceConfig::TriggerConfig&&) noexcept = default;
+TraceConfig::TriggerConfig& TraceConfig::TriggerConfig::operator=(
+    TraceConfig::TriggerConfig&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool TraceConfig::TriggerConfig::operator==(
+    const TraceConfig::TriggerConfig& other) const {
+  return (trigger_mode_ == other.trigger_mode_) &&
+         (triggers_ == other.triggers_) &&
+         (trigger_timeout_ms_ == other.trigger_timeout_ms_);
+}
+#pragma GCC diagnostic pop
+
+void TraceConfig::TriggerConfig::FromProto(
+    const perfetto::protos::TraceConfig_TriggerConfig& proto) {
+  static_assert(sizeof(trigger_mode_) == sizeof(proto.trigger_mode()),
+                "size mismatch");
+  trigger_mode_ = static_cast<decltype(trigger_mode_)>(proto.trigger_mode());
+
+  triggers_.clear();
+  for (const auto& field : proto.triggers()) {
+    triggers_.emplace_back();
+    triggers_.back().FromProto(field);
+  }
+
+  static_assert(
+      sizeof(trigger_timeout_ms_) == sizeof(proto.trigger_timeout_ms()),
+      "size mismatch");
+  trigger_timeout_ms_ =
+      static_cast<decltype(trigger_timeout_ms_)>(proto.trigger_timeout_ms());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void TraceConfig::TriggerConfig::ToProto(
+    perfetto::protos::TraceConfig_TriggerConfig* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(trigger_mode_) == sizeof(proto->trigger_mode()),
+                "size mismatch");
+  proto->set_trigger_mode(
+      static_cast<decltype(proto->trigger_mode())>(trigger_mode_));
+
+  for (const auto& it : triggers_) {
+    auto* entry = proto->add_triggers();
+    it.ToProto(entry);
+  }
+
+  static_assert(
+      sizeof(trigger_timeout_ms_) == sizeof(proto->trigger_timeout_ms()),
+      "size mismatch");
+  proto->set_trigger_timeout_ms(
+      static_cast<decltype(proto->trigger_timeout_ms())>(trigger_timeout_ms_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+TraceConfig::TriggerConfig::Trigger::Trigger() = default;
+TraceConfig::TriggerConfig::Trigger::~Trigger() = default;
+TraceConfig::TriggerConfig::Trigger::Trigger(
+    const TraceConfig::TriggerConfig::Trigger&) = default;
+TraceConfig::TriggerConfig::Trigger& TraceConfig::TriggerConfig::Trigger::
+operator=(const TraceConfig::TriggerConfig::Trigger&) = default;
+TraceConfig::TriggerConfig::Trigger::Trigger(
+    TraceConfig::TriggerConfig::Trigger&&) noexcept = default;
+TraceConfig::TriggerConfig::Trigger& TraceConfig::TriggerConfig::Trigger::
+operator=(TraceConfig::TriggerConfig::Trigger&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool TraceConfig::TriggerConfig::Trigger::operator==(
+    const TraceConfig::TriggerConfig::Trigger& other) const {
+  return (name_ == other.name_) &&
+         (producer_name_regex_ == other.producer_name_regex_) &&
+         (stop_delay_ms_ == other.stop_delay_ms_);
+}
+#pragma GCC diagnostic pop
+
+void TraceConfig::TriggerConfig::Trigger::FromProto(
+    const perfetto::protos::TraceConfig_TriggerConfig_Trigger& proto) {
+  static_assert(sizeof(name_) == sizeof(proto.name()), "size mismatch");
+  name_ = static_cast<decltype(name_)>(proto.name());
+
+  static_assert(
+      sizeof(producer_name_regex_) == sizeof(proto.producer_name_regex()),
+      "size mismatch");
+  producer_name_regex_ =
+      static_cast<decltype(producer_name_regex_)>(proto.producer_name_regex());
+
+  static_assert(sizeof(stop_delay_ms_) == sizeof(proto.stop_delay_ms()),
+                "size mismatch");
+  stop_delay_ms_ = static_cast<decltype(stop_delay_ms_)>(proto.stop_delay_ms());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void TraceConfig::TriggerConfig::Trigger::ToProto(
+    perfetto::protos::TraceConfig_TriggerConfig_Trigger* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(name_) == sizeof(proto->name()), "size mismatch");
+  proto->set_name(static_cast<decltype(proto->name())>(name_));
+
+  static_assert(
+      sizeof(producer_name_regex_) == sizeof(proto->producer_name_regex()),
+      "size mismatch");
+  proto->set_producer_name_regex(
+      static_cast<decltype(proto->producer_name_regex())>(
+          producer_name_regex_));
+
+  static_assert(sizeof(stop_delay_ms_) == sizeof(proto->stop_delay_ms()),
+                "size mismatch");
+  proto->set_stop_delay_ms(
+      static_cast<decltype(proto->stop_delay_ms())>(stop_delay_ms_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+TraceConfig::IncrementalStateConfig::IncrementalStateConfig() = default;
+TraceConfig::IncrementalStateConfig::~IncrementalStateConfig() = default;
+TraceConfig::IncrementalStateConfig::IncrementalStateConfig(
+    const TraceConfig::IncrementalStateConfig&) = default;
+TraceConfig::IncrementalStateConfig& TraceConfig::IncrementalStateConfig::
+operator=(const TraceConfig::IncrementalStateConfig&) = default;
+TraceConfig::IncrementalStateConfig::IncrementalStateConfig(
+    TraceConfig::IncrementalStateConfig&&) noexcept = default;
+TraceConfig::IncrementalStateConfig& TraceConfig::IncrementalStateConfig::
+operator=(TraceConfig::IncrementalStateConfig&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool TraceConfig::IncrementalStateConfig::operator==(
+    const TraceConfig::IncrementalStateConfig& other) const {
+  return (clear_period_ms_ == other.clear_period_ms_);
+}
+#pragma GCC diagnostic pop
+
+void TraceConfig::IncrementalStateConfig::FromProto(
+    const perfetto::protos::TraceConfig_IncrementalStateConfig& proto) {
+  static_assert(sizeof(clear_period_ms_) == sizeof(proto.clear_period_ms()),
+                "size mismatch");
+  clear_period_ms_ =
+      static_cast<decltype(clear_period_ms_)>(proto.clear_period_ms());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void TraceConfig::IncrementalStateConfig::ToProto(
+    perfetto::protos::TraceConfig_IncrementalStateConfig* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(clear_period_ms_) == sizeof(proto->clear_period_ms()),
+                "size mismatch");
+  proto->set_clear_period_ms(
+      static_cast<decltype(proto->clear_period_ms())>(clear_period_ms_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+TraceConfig::IncidentReportConfig::IncidentReportConfig() = default;
+TraceConfig::IncidentReportConfig::~IncidentReportConfig() = default;
+TraceConfig::IncidentReportConfig::IncidentReportConfig(
+    const TraceConfig::IncidentReportConfig&) = default;
+TraceConfig::IncidentReportConfig& TraceConfig::IncidentReportConfig::operator=(
+    const TraceConfig::IncidentReportConfig&) = default;
+TraceConfig::IncidentReportConfig::IncidentReportConfig(
+    TraceConfig::IncidentReportConfig&&) noexcept = default;
+TraceConfig::IncidentReportConfig& TraceConfig::IncidentReportConfig::operator=(
+    TraceConfig::IncidentReportConfig&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool TraceConfig::IncidentReportConfig::operator==(
+    const TraceConfig::IncidentReportConfig& other) const {
+  return (destination_package_ == other.destination_package_) &&
+         (destination_class_ == other.destination_class_) &&
+         (privacy_level_ == other.privacy_level_) &&
+         (skip_dropbox_ == other.skip_dropbox_);
+}
+#pragma GCC diagnostic pop
+
+void TraceConfig::IncidentReportConfig::FromProto(
+    const perfetto::protos::TraceConfig_IncidentReportConfig& proto) {
+  static_assert(
+      sizeof(destination_package_) == sizeof(proto.destination_package()),
+      "size mismatch");
+  destination_package_ =
+      static_cast<decltype(destination_package_)>(proto.destination_package());
+
+  static_assert(sizeof(destination_class_) == sizeof(proto.destination_class()),
+                "size mismatch");
+  destination_class_ =
+      static_cast<decltype(destination_class_)>(proto.destination_class());
+
+  static_assert(sizeof(privacy_level_) == sizeof(proto.privacy_level()),
+                "size mismatch");
+  privacy_level_ = static_cast<decltype(privacy_level_)>(proto.privacy_level());
+
+  static_assert(sizeof(skip_dropbox_) == sizeof(proto.skip_dropbox()),
+                "size mismatch");
+  skip_dropbox_ = static_cast<decltype(skip_dropbox_)>(proto.skip_dropbox());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void TraceConfig::IncidentReportConfig::ToProto(
+    perfetto::protos::TraceConfig_IncidentReportConfig* proto) const {
+  proto->Clear();
+
+  static_assert(
+      sizeof(destination_package_) == sizeof(proto->destination_package()),
+      "size mismatch");
+  proto->set_destination_package(
+      static_cast<decltype(proto->destination_package())>(
+          destination_package_));
+
+  static_assert(
+      sizeof(destination_class_) == sizeof(proto->destination_class()),
+      "size mismatch");
+  proto->set_destination_class(
+      static_cast<decltype(proto->destination_class())>(destination_class_));
+
+  static_assert(sizeof(privacy_level_) == sizeof(proto->privacy_level()),
+                "size mismatch");
+  proto->set_privacy_level(
+      static_cast<decltype(proto->privacy_level())>(privacy_level_));
+
+  static_assert(sizeof(skip_dropbox_) == sizeof(proto->skip_dropbox()),
+                "size mismatch");
+  proto->set_skip_dropbox(
+      static_cast<decltype(proto->skip_dropbox())>(skip_dropbox_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+}  // namespace perfetto
diff --git a/src/tracing/core/trace_packet.cc b/src/tracing/core/trace_packet.cc
index 0dea150..ffe6f1a 100644
--- a/src/tracing/core/trace_packet.cc
+++ b/src/tracing/core/trace_packet.cc
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/tracing/core/trace_packet.h"
+#include "perfetto/tracing/core/trace_packet.h"
 
 #include "perfetto/base/logging.h"
 #include "perfetto/protozero/proto_utils.h"
+#include "src/tracing/core/sliced_protobuf_input_stream.h"
 
 namespace perfetto {
 
@@ -62,16 +63,10 @@
   return std::make_tuple(&preamble_[0], preamble_size);
 }
 
-std::string TracePacket::GetRawBytesForTesting() {
-  std::string data;
-  data.resize(size());
-  size_t pos = 0;
-  for (const Slice& slice : slices()) {
-    PERFETTO_CHECK(pos + slice.size <= data.size());
-    memcpy(&data[pos], slice.start, slice.size);
-    pos += slice.size;
-  }
-  return data;
+std::unique_ptr<TracePacket::ZeroCopyInputStream>
+TracePacket::CreateSlicedInputStream() const {
+  return std::unique_ptr<ZeroCopyInputStream>(
+      new SlicedProtobufInputStream(&slices_));
 }
 
 }  // namespace perfetto
diff --git a/src/tracing/core/trace_packet_unittest.cc b/src/tracing/core/trace_packet_unittest.cc
index 0469ae8..61bc001 100644
--- a/src/tracing/core/trace_packet_unittest.cc
+++ b/src/tracing/core/trace_packet_unittest.cc
@@ -14,41 +14,38 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/tracing/core/trace_packet.h"
+#include "perfetto/tracing/core/trace_packet.h"
 
 #include <string>
 
-#include "protos/perfetto/trace/trace.pb.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
-#include "protos/perfetto/trace/trusted_packet.pb.h"
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
+
+#include "perfetto/trace/trace.pb.h"
+#include "perfetto/trace/trace_packet.pb.h"
+#include "perfetto/trace/trusted_packet.pb.h"
 
 namespace perfetto {
 namespace {
 
-static_assert(static_cast<int>(TracePacket::kPacketFieldNumber) ==
-                  static_cast<int>(protos::Trace::kPacketFieldNumber),
+static_assert(TracePacket::kPacketFieldNumber ==
+                  protos::Trace::kPacketFieldNumber,
               "packet field id mismatch");
 
-static_assert(
-    static_cast<int>(protos::TracePacket::kTrustedUidFieldNumber) ==
-        static_cast<int>(protos::TrustedPacket::kTrustedUidFieldNumber),
-    "trusted_uid field id mismatch");
+static_assert(protos::TracePacket::kTrustedUidFieldNumber ==
+                  protos::TrustedPacket::kTrustedUidFieldNumber,
+              "trusted_uid field id mismatch");
 
-static_assert(
-    static_cast<int>(protos::TracePacket::kTraceConfigFieldNumber) ==
-        static_cast<int>(protos::TrustedPacket::kTraceConfigFieldNumber),
-    "trace_config field id mismatch");
+static_assert(protos::TracePacket::kTraceConfigFieldNumber ==
+                  protos::TrustedPacket::kTraceConfigFieldNumber,
+              "trace_config field id mismatch");
 
-static_assert(
-    static_cast<int>(protos::TracePacket::kTraceStatsFieldNumber) ==
-        static_cast<int>(protos::TrustedPacket::kTraceStatsFieldNumber),
-    "trace_stats field id mismatch");
+static_assert(protos::TracePacket::kTraceStatsFieldNumber ==
+                  protos::TrustedPacket::kTraceStatsFieldNumber,
+              "trace_stats field id mismatch");
 
-static_assert(
-    static_cast<int>(protos::TracePacket::kClockSnapshotFieldNumber) ==
-        static_cast<int>(protos::TrustedPacket::kClockSnapshotFieldNumber),
-    "clock_snapshot field id mismatch");
+static_assert(protos::TracePacket::kClockSnapshotFieldNumber ==
+                  protos::TrustedPacket::kClockSnapshotFieldNumber,
+              "clock_snapshot field id mismatch");
 
 TEST(TracePacketTest, Simple) {
   protos::TracePacket proto;
@@ -63,7 +60,7 @@
   ASSERT_EQ(tp.slices().end(), ++slice);
 
   protos::TracePacket decoded_packet;
-  ASSERT_TRUE(decoded_packet.ParseFromString(tp.GetRawBytesForTesting()));
+  ASSERT_TRUE(tp.Decode(&decoded_packet));
   ASSERT_EQ(proto.for_testing().str(), decoded_packet.for_testing().str());
 }
 
@@ -94,7 +91,7 @@
   ASSERT_EQ(tp.slices().end(), ++slice);
 
   protos::TracePacket decoded_packet;
-  ASSERT_TRUE(decoded_packet.ParseFromString(tp.GetRawBytesForTesting()));
+  ASSERT_TRUE(tp.Decode(&decoded_packet));
   ASSERT_EQ(proto.for_testing().str(), decoded_packet.for_testing().str());
 }
 
@@ -105,7 +102,7 @@
   TracePacket tp;
   tp.AddSlice({ser_buf.data(), ser_buf.size() - 2});  // corrupted.
   protos::TracePacket decoded_packet;
-  ASSERT_FALSE(decoded_packet.ParseFromString(tp.GetRawBytesForTesting()));
+  ASSERT_FALSE(tp.Decode(&decoded_packet));
 }
 
 // Tests that the GetProtoPreamble() logic returns a valid preamble that allows
diff --git a/src/tracing/core/trace_stats.cc b/src/tracing/core/trace_stats.cc
new file mode 100644
index 0000000..74de5b5
--- /dev/null
+++ b/src/tracing/core/trace_stats.cc
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/common/trace_stats.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/trace_stats.h"
+
+#include "perfetto/common/trace_stats.pb.h"
+
+namespace perfetto {
+
+TraceStats::TraceStats() = default;
+TraceStats::~TraceStats() = default;
+TraceStats::TraceStats(const TraceStats&) = default;
+TraceStats& TraceStats::operator=(const TraceStats&) = default;
+TraceStats::TraceStats(TraceStats&&) noexcept = default;
+TraceStats& TraceStats::operator=(TraceStats&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool TraceStats::operator==(const TraceStats& other) const {
+  return (buffer_stats_ == other.buffer_stats_) &&
+         (producers_connected_ == other.producers_connected_) &&
+         (producers_seen_ == other.producers_seen_) &&
+         (data_sources_registered_ == other.data_sources_registered_) &&
+         (data_sources_seen_ == other.data_sources_seen_) &&
+         (tracing_sessions_ == other.tracing_sessions_) &&
+         (total_buffers_ == other.total_buffers_) &&
+         (chunks_discarded_ == other.chunks_discarded_) &&
+         (patches_discarded_ == other.patches_discarded_);
+}
+#pragma GCC diagnostic pop
+
+void TraceStats::FromProto(const perfetto::protos::TraceStats& proto) {
+  buffer_stats_.clear();
+  for (const auto& field : proto.buffer_stats()) {
+    buffer_stats_.emplace_back();
+    buffer_stats_.back().FromProto(field);
+  }
+
+  static_assert(
+      sizeof(producers_connected_) == sizeof(proto.producers_connected()),
+      "size mismatch");
+  producers_connected_ =
+      static_cast<decltype(producers_connected_)>(proto.producers_connected());
+
+  static_assert(sizeof(producers_seen_) == sizeof(proto.producers_seen()),
+                "size mismatch");
+  producers_seen_ =
+      static_cast<decltype(producers_seen_)>(proto.producers_seen());
+
+  static_assert(sizeof(data_sources_registered_) ==
+                    sizeof(proto.data_sources_registered()),
+                "size mismatch");
+  data_sources_registered_ = static_cast<decltype(data_sources_registered_)>(
+      proto.data_sources_registered());
+
+  static_assert(sizeof(data_sources_seen_) == sizeof(proto.data_sources_seen()),
+                "size mismatch");
+  data_sources_seen_ =
+      static_cast<decltype(data_sources_seen_)>(proto.data_sources_seen());
+
+  static_assert(sizeof(tracing_sessions_) == sizeof(proto.tracing_sessions()),
+                "size mismatch");
+  tracing_sessions_ =
+      static_cast<decltype(tracing_sessions_)>(proto.tracing_sessions());
+
+  static_assert(sizeof(total_buffers_) == sizeof(proto.total_buffers()),
+                "size mismatch");
+  total_buffers_ = static_cast<decltype(total_buffers_)>(proto.total_buffers());
+
+  static_assert(sizeof(chunks_discarded_) == sizeof(proto.chunks_discarded()),
+                "size mismatch");
+  chunks_discarded_ =
+      static_cast<decltype(chunks_discarded_)>(proto.chunks_discarded());
+
+  static_assert(sizeof(patches_discarded_) == sizeof(proto.patches_discarded()),
+                "size mismatch");
+  patches_discarded_ =
+      static_cast<decltype(patches_discarded_)>(proto.patches_discarded());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void TraceStats::ToProto(perfetto::protos::TraceStats* proto) const {
+  proto->Clear();
+
+  for (const auto& it : buffer_stats_) {
+    auto* entry = proto->add_buffer_stats();
+    it.ToProto(entry);
+  }
+
+  static_assert(
+      sizeof(producers_connected_) == sizeof(proto->producers_connected()),
+      "size mismatch");
+  proto->set_producers_connected(
+      static_cast<decltype(proto->producers_connected())>(
+          producers_connected_));
+
+  static_assert(sizeof(producers_seen_) == sizeof(proto->producers_seen()),
+                "size mismatch");
+  proto->set_producers_seen(
+      static_cast<decltype(proto->producers_seen())>(producers_seen_));
+
+  static_assert(sizeof(data_sources_registered_) ==
+                    sizeof(proto->data_sources_registered()),
+                "size mismatch");
+  proto->set_data_sources_registered(
+      static_cast<decltype(proto->data_sources_registered())>(
+          data_sources_registered_));
+
+  static_assert(
+      sizeof(data_sources_seen_) == sizeof(proto->data_sources_seen()),
+      "size mismatch");
+  proto->set_data_sources_seen(
+      static_cast<decltype(proto->data_sources_seen())>(data_sources_seen_));
+
+  static_assert(sizeof(tracing_sessions_) == sizeof(proto->tracing_sessions()),
+                "size mismatch");
+  proto->set_tracing_sessions(
+      static_cast<decltype(proto->tracing_sessions())>(tracing_sessions_));
+
+  static_assert(sizeof(total_buffers_) == sizeof(proto->total_buffers()),
+                "size mismatch");
+  proto->set_total_buffers(
+      static_cast<decltype(proto->total_buffers())>(total_buffers_));
+
+  static_assert(sizeof(chunks_discarded_) == sizeof(proto->chunks_discarded()),
+                "size mismatch");
+  proto->set_chunks_discarded(
+      static_cast<decltype(proto->chunks_discarded())>(chunks_discarded_));
+
+  static_assert(
+      sizeof(patches_discarded_) == sizeof(proto->patches_discarded()),
+      "size mismatch");
+  proto->set_patches_discarded(
+      static_cast<decltype(proto->patches_discarded())>(patches_discarded_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+TraceStats::BufferStats::BufferStats() = default;
+TraceStats::BufferStats::~BufferStats() = default;
+TraceStats::BufferStats::BufferStats(const TraceStats::BufferStats&) = default;
+TraceStats::BufferStats& TraceStats::BufferStats::operator=(
+    const TraceStats::BufferStats&) = default;
+TraceStats::BufferStats::BufferStats(TraceStats::BufferStats&&) noexcept =
+    default;
+TraceStats::BufferStats& TraceStats::BufferStats::operator=(
+    TraceStats::BufferStats&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool TraceStats::BufferStats::operator==(
+    const TraceStats::BufferStats& other) const {
+  return (buffer_size_ == other.buffer_size_) &&
+         (bytes_written_ == other.bytes_written_) &&
+         (bytes_overwritten_ == other.bytes_overwritten_) &&
+         (bytes_read_ == other.bytes_read_) &&
+         (padding_bytes_written_ == other.padding_bytes_written_) &&
+         (padding_bytes_cleared_ == other.padding_bytes_cleared_) &&
+         (chunks_written_ == other.chunks_written_) &&
+         (chunks_rewritten_ == other.chunks_rewritten_) &&
+         (chunks_overwritten_ == other.chunks_overwritten_) &&
+         (chunks_discarded_ == other.chunks_discarded_) &&
+         (chunks_read_ == other.chunks_read_) &&
+         (chunks_committed_out_of_order_ ==
+          other.chunks_committed_out_of_order_) &&
+         (write_wrap_count_ == other.write_wrap_count_) &&
+         (patches_succeeded_ == other.patches_succeeded_) &&
+         (patches_failed_ == other.patches_failed_) &&
+         (readaheads_succeeded_ == other.readaheads_succeeded_) &&
+         (readaheads_failed_ == other.readaheads_failed_) &&
+         (abi_violations_ == other.abi_violations_);
+}
+#pragma GCC diagnostic pop
+
+void TraceStats::BufferStats::FromProto(
+    const perfetto::protos::TraceStats_BufferStats& proto) {
+  static_assert(sizeof(buffer_size_) == sizeof(proto.buffer_size()),
+                "size mismatch");
+  buffer_size_ = static_cast<decltype(buffer_size_)>(proto.buffer_size());
+
+  static_assert(sizeof(bytes_written_) == sizeof(proto.bytes_written()),
+                "size mismatch");
+  bytes_written_ = static_cast<decltype(bytes_written_)>(proto.bytes_written());
+
+  static_assert(sizeof(bytes_overwritten_) == sizeof(proto.bytes_overwritten()),
+                "size mismatch");
+  bytes_overwritten_ =
+      static_cast<decltype(bytes_overwritten_)>(proto.bytes_overwritten());
+
+  static_assert(sizeof(bytes_read_) == sizeof(proto.bytes_read()),
+                "size mismatch");
+  bytes_read_ = static_cast<decltype(bytes_read_)>(proto.bytes_read());
+
+  static_assert(
+      sizeof(padding_bytes_written_) == sizeof(proto.padding_bytes_written()),
+      "size mismatch");
+  padding_bytes_written_ = static_cast<decltype(padding_bytes_written_)>(
+      proto.padding_bytes_written());
+
+  static_assert(
+      sizeof(padding_bytes_cleared_) == sizeof(proto.padding_bytes_cleared()),
+      "size mismatch");
+  padding_bytes_cleared_ = static_cast<decltype(padding_bytes_cleared_)>(
+      proto.padding_bytes_cleared());
+
+  static_assert(sizeof(chunks_written_) == sizeof(proto.chunks_written()),
+                "size mismatch");
+  chunks_written_ =
+      static_cast<decltype(chunks_written_)>(proto.chunks_written());
+
+  static_assert(sizeof(chunks_rewritten_) == sizeof(proto.chunks_rewritten()),
+                "size mismatch");
+  chunks_rewritten_ =
+      static_cast<decltype(chunks_rewritten_)>(proto.chunks_rewritten());
+
+  static_assert(
+      sizeof(chunks_overwritten_) == sizeof(proto.chunks_overwritten()),
+      "size mismatch");
+  chunks_overwritten_ =
+      static_cast<decltype(chunks_overwritten_)>(proto.chunks_overwritten());
+
+  static_assert(sizeof(chunks_discarded_) == sizeof(proto.chunks_discarded()),
+                "size mismatch");
+  chunks_discarded_ =
+      static_cast<decltype(chunks_discarded_)>(proto.chunks_discarded());
+
+  static_assert(sizeof(chunks_read_) == sizeof(proto.chunks_read()),
+                "size mismatch");
+  chunks_read_ = static_cast<decltype(chunks_read_)>(proto.chunks_read());
+
+  static_assert(sizeof(chunks_committed_out_of_order_) ==
+                    sizeof(proto.chunks_committed_out_of_order()),
+                "size mismatch");
+  chunks_committed_out_of_order_ =
+      static_cast<decltype(chunks_committed_out_of_order_)>(
+          proto.chunks_committed_out_of_order());
+
+  static_assert(sizeof(write_wrap_count_) == sizeof(proto.write_wrap_count()),
+                "size mismatch");
+  write_wrap_count_ =
+      static_cast<decltype(write_wrap_count_)>(proto.write_wrap_count());
+
+  static_assert(sizeof(patches_succeeded_) == sizeof(proto.patches_succeeded()),
+                "size mismatch");
+  patches_succeeded_ =
+      static_cast<decltype(patches_succeeded_)>(proto.patches_succeeded());
+
+  static_assert(sizeof(patches_failed_) == sizeof(proto.patches_failed()),
+                "size mismatch");
+  patches_failed_ =
+      static_cast<decltype(patches_failed_)>(proto.patches_failed());
+
+  static_assert(
+      sizeof(readaheads_succeeded_) == sizeof(proto.readaheads_succeeded()),
+      "size mismatch");
+  readaheads_succeeded_ = static_cast<decltype(readaheads_succeeded_)>(
+      proto.readaheads_succeeded());
+
+  static_assert(sizeof(readaheads_failed_) == sizeof(proto.readaheads_failed()),
+                "size mismatch");
+  readaheads_failed_ =
+      static_cast<decltype(readaheads_failed_)>(proto.readaheads_failed());
+
+  static_assert(sizeof(abi_violations_) == sizeof(proto.abi_violations()),
+                "size mismatch");
+  abi_violations_ =
+      static_cast<decltype(abi_violations_)>(proto.abi_violations());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void TraceStats::BufferStats::ToProto(
+    perfetto::protos::TraceStats_BufferStats* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(buffer_size_) == sizeof(proto->buffer_size()),
+                "size mismatch");
+  proto->set_buffer_size(
+      static_cast<decltype(proto->buffer_size())>(buffer_size_));
+
+  static_assert(sizeof(bytes_written_) == sizeof(proto->bytes_written()),
+                "size mismatch");
+  proto->set_bytes_written(
+      static_cast<decltype(proto->bytes_written())>(bytes_written_));
+
+  static_assert(
+      sizeof(bytes_overwritten_) == sizeof(proto->bytes_overwritten()),
+      "size mismatch");
+  proto->set_bytes_overwritten(
+      static_cast<decltype(proto->bytes_overwritten())>(bytes_overwritten_));
+
+  static_assert(sizeof(bytes_read_) == sizeof(proto->bytes_read()),
+                "size mismatch");
+  proto->set_bytes_read(
+      static_cast<decltype(proto->bytes_read())>(bytes_read_));
+
+  static_assert(
+      sizeof(padding_bytes_written_) == sizeof(proto->padding_bytes_written()),
+      "size mismatch");
+  proto->set_padding_bytes_written(
+      static_cast<decltype(proto->padding_bytes_written())>(
+          padding_bytes_written_));
+
+  static_assert(
+      sizeof(padding_bytes_cleared_) == sizeof(proto->padding_bytes_cleared()),
+      "size mismatch");
+  proto->set_padding_bytes_cleared(
+      static_cast<decltype(proto->padding_bytes_cleared())>(
+          padding_bytes_cleared_));
+
+  static_assert(sizeof(chunks_written_) == sizeof(proto->chunks_written()),
+                "size mismatch");
+  proto->set_chunks_written(
+      static_cast<decltype(proto->chunks_written())>(chunks_written_));
+
+  static_assert(sizeof(chunks_rewritten_) == sizeof(proto->chunks_rewritten()),
+                "size mismatch");
+  proto->set_chunks_rewritten(
+      static_cast<decltype(proto->chunks_rewritten())>(chunks_rewritten_));
+
+  static_assert(
+      sizeof(chunks_overwritten_) == sizeof(proto->chunks_overwritten()),
+      "size mismatch");
+  proto->set_chunks_overwritten(
+      static_cast<decltype(proto->chunks_overwritten())>(chunks_overwritten_));
+
+  static_assert(sizeof(chunks_discarded_) == sizeof(proto->chunks_discarded()),
+                "size mismatch");
+  proto->set_chunks_discarded(
+      static_cast<decltype(proto->chunks_discarded())>(chunks_discarded_));
+
+  static_assert(sizeof(chunks_read_) == sizeof(proto->chunks_read()),
+                "size mismatch");
+  proto->set_chunks_read(
+      static_cast<decltype(proto->chunks_read())>(chunks_read_));
+
+  static_assert(sizeof(chunks_committed_out_of_order_) ==
+                    sizeof(proto->chunks_committed_out_of_order()),
+                "size mismatch");
+  proto->set_chunks_committed_out_of_order(
+      static_cast<decltype(proto->chunks_committed_out_of_order())>(
+          chunks_committed_out_of_order_));
+
+  static_assert(sizeof(write_wrap_count_) == sizeof(proto->write_wrap_count()),
+                "size mismatch");
+  proto->set_write_wrap_count(
+      static_cast<decltype(proto->write_wrap_count())>(write_wrap_count_));
+
+  static_assert(
+      sizeof(patches_succeeded_) == sizeof(proto->patches_succeeded()),
+      "size mismatch");
+  proto->set_patches_succeeded(
+      static_cast<decltype(proto->patches_succeeded())>(patches_succeeded_));
+
+  static_assert(sizeof(patches_failed_) == sizeof(proto->patches_failed()),
+                "size mismatch");
+  proto->set_patches_failed(
+      static_cast<decltype(proto->patches_failed())>(patches_failed_));
+
+  static_assert(
+      sizeof(readaheads_succeeded_) == sizeof(proto->readaheads_succeeded()),
+      "size mismatch");
+  proto->set_readaheads_succeeded(
+      static_cast<decltype(proto->readaheads_succeeded())>(
+          readaheads_succeeded_));
+
+  static_assert(
+      sizeof(readaheads_failed_) == sizeof(proto->readaheads_failed()),
+      "size mismatch");
+  proto->set_readaheads_failed(
+      static_cast<decltype(proto->readaheads_failed())>(readaheads_failed_));
+
+  static_assert(sizeof(abi_violations_) == sizeof(proto->abi_violations()),
+                "size mismatch");
+  proto->set_abi_violations(
+      static_cast<decltype(proto->abi_violations())>(abi_violations_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+}  // namespace perfetto
diff --git a/src/tracing/core/trace_writer_for_testing.cc b/src/tracing/core/trace_writer_for_testing.cc
index 98544b8..6cfb559 100644
--- a/src/tracing/core/trace_writer_for_testing.cc
+++ b/src/tracing/core/trace_writer_for_testing.cc
@@ -17,12 +17,12 @@
 #include "src/tracing/core/trace_writer_for_testing.h"
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/utils.h"
 #include "perfetto/protozero/message.h"
-#include "protos/perfetto/trace/trace.pb.h"
-#include "protos/perfetto/trace/trace.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/trace.pb.h"
+#include "perfetto/trace/trace.pbzero.h"
+#include "perfetto/trace/trace_packet.pb.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
 
@@ -60,10 +60,14 @@
   return ret;
 }
 
-protos::TracePacket TraceWriterForTesting::GetOnlyTracePacket() {
-  auto packets = GetAllTracePackets();
-  PERFETTO_CHECK(packets.size() == 1);
-  return packets[0];
+std::unique_ptr<protos::TracePacket> TraceWriterForTesting::ParseProto() {
+  PERFETTO_CHECK(cur_packet_->is_finalized());
+
+  auto trace = GetAllTracePackets();
+  PERFETTO_CHECK(!trace.empty());
+  auto packet =
+      std::unique_ptr<protos::TracePacket>(new protos::TracePacket(trace[0]));
+  return packet;
 }
 
 TraceWriterForTesting::TracePacketHandle
diff --git a/src/tracing/core/trace_writer_for_testing.h b/src/tracing/core/trace_writer_for_testing.h
index b71f605..f7a1a88 100644
--- a/src/tracing/core/trace_writer_for_testing.h
+++ b/src/tracing/core/trace_writer_for_testing.h
@@ -18,10 +18,10 @@
 
 #include <vector>
 
-#include "perfetto/ext/tracing/core/trace_writer.h"
 #include "perfetto/protozero/message_handle.h"
 #include "perfetto/protozero/scattered_heap_buffer.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
+#include "perfetto/trace/trace_packet.pb.h"
+#include "perfetto/tracing/core/trace_writer.h"
 
 namespace perfetto {
 
@@ -39,7 +39,8 @@
   void Flush(std::function<void()> callback = {}) override;
 
   std::vector<protos::TracePacket> GetAllTracePackets();
-  protos::TracePacket GetOnlyTracePacket();
+  // TODO(rsavitski): rewrite as "get only packet".
+  std::unique_ptr<protos::TracePacket> ParseProto();
 
   WriterID writer_id() const override;
   uint64_t written() const override;
diff --git a/src/tracing/core/trace_writer_impl.cc b/src/tracing/core/trace_writer_impl.cc
index b18f99c..fcc29bc 100644
--- a/src/tracing/core/trace_writer_impl.cc
+++ b/src/tracing/core/trace_writer_impl.cc
@@ -23,11 +23,10 @@
 #include <utility>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/thread_annotations.h"
 #include "perfetto/protozero/proto_utils.h"
 #include "src/tracing/core/shared_memory_arbiter_impl.h"
 
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
 using protozero::proto_utils::kMessageLengthFieldSize;
 using protozero::proto_utils::WriteRedundantVarInt;
@@ -37,17 +36,14 @@
 
 namespace {
 constexpr size_t kPacketHeaderSize = SharedMemoryABI::kPacketHeaderSize;
-uint8_t g_garbage_chunk[1024];
 }  // namespace
 
 TraceWriterImpl::TraceWriterImpl(SharedMemoryArbiterImpl* shmem_arbiter,
                                  WriterID id,
-                                 BufferID target_buffer,
-                                 BufferExhaustedPolicy buffer_exhausted_policy)
+                                 BufferID target_buffer)
     : shmem_arbiter_(shmem_arbiter),
       id_(id),
       target_buffer_(target_buffer),
-      buffer_exhausted_policy_(buffer_exhausted_policy),
       protobuf_stream_writer_(this) {
   // TODO(primiano): we could handle the case of running out of TraceWriterID(s)
   // more gracefully and always return a no-op TracePacket in NewTracePacket().
@@ -84,7 +80,7 @@
 TraceWriterImpl::TracePacketHandle TraceWriterImpl::NewTracePacket() {
   // If we hit this, the caller is calling NewTracePacket() without having
   // finalized the previous packet.
-  PERFETTO_CHECK(cur_packet_->is_finalized());
+  PERFETTO_DCHECK(cur_packet_->is_finalized());
 
   fragmenting_packet_ = false;
 
@@ -94,15 +90,12 @@
   static_assert(kPacketHeaderSize == kMessageLengthFieldSize,
                 "The packet header must match the Message header size");
 
-  bool was_dropping_packets = drop_packets_;
-
   // It doesn't make sense to begin a packet that is going to fragment
   // immediately after (8 is just an arbitrary estimation on the minimum size of
   // a realistic packet).
   bool chunk_too_full =
       protobuf_stream_writer_.bytes_available() < kPacketHeaderSize + 8;
-  if (chunk_too_full || reached_max_packets_per_chunk_ ||
-      retry_new_chunk_after_packet_) {
+  if (chunk_too_full || reached_max_packets_per_chunk_) {
     protobuf_stream_writer_.Reset(GetNewBuffer());
   }
 
@@ -118,25 +111,12 @@
   uint8_t* header = protobuf_stream_writer_.ReserveBytes(kPacketHeaderSize);
   memset(header, 0, kPacketHeaderSize);
   cur_packet_->set_size_field(header);
-  last_packet_size_field_ = header;
-
+  uint16_t new_packet_count = cur_chunk_.IncrementPacketCount();
+  reached_max_packets_per_chunk_ =
+      new_packet_count == ChunkHeader::Packets::kMaxCount;
   TracePacketHandle handle(cur_packet_.get());
   cur_fragment_start_ = protobuf_stream_writer_.write_ptr();
   fragmenting_packet_ = true;
-
-  if (PERFETTO_LIKELY(!drop_packets_)) {
-    uint16_t new_packet_count = cur_chunk_.IncrementPacketCount();
-    reached_max_packets_per_chunk_ =
-        new_packet_count == ChunkHeader::Packets::kMaxCount;
-
-    if (PERFETTO_UNLIKELY(was_dropping_packets)) {
-      // We've succeeded to get a new chunk from the SMB after we entered
-      // drop_packets_ mode. Record a marker into the new packet to indicate the
-      // data loss.
-      cur_packet_->set_previous_packet_dropped(true);
-    }
-  }
-
   return handle;
 }
 
@@ -149,125 +129,7 @@
 // In this case |fragmenting_packet_| == false and we just want a new chunk
 // without creating any fragments.
 protozero::ContiguousMemoryRange TraceWriterImpl::GetNewBuffer() {
-  if (fragmenting_packet_ && drop_packets_) {
-    // We can't write the remaining data of the fragmenting packet to a new
-    // chunk, because we have already lost some of its data in the garbage
-    // chunk. Thus, we will wrap around in the garbage chunk, wait until the
-    // current packet was completed, and then attempt to get a new chunk from
-    // the SMB again. Instead, if |drop_packets_| is true and
-    // |fragmenting_packet_| is false, we try to acquire a valid chunk because
-    // the SMB exhaustion might be resolved.
-    retry_new_chunk_after_packet_ = true;
-    return protozero::ContiguousMemoryRange{
-        &g_garbage_chunk[0], &g_garbage_chunk[0] + sizeof(g_garbage_chunk)};
-  }
-
-  // Attempt to grab the next chunk before finalizing the current one, so that
-  // we know whether we need to start dropping packets before writing the
-  // current packet fragment's header.
-  ChunkHeader::Packets packets = {};
   if (fragmenting_packet_) {
-    packets.count = 1;
-    packets.flags = ChunkHeader::kFirstPacketContinuesFromPrevChunk;
-  }
-
-  // The memory order of the stores below doesn't really matter. This |header|
-  // is just a local temporary object. The GetNewChunk() call below will copy it
-  // into the shared buffer with the proper barriers.
-  ChunkHeader header = {};
-  header.writer_id.store(id_, std::memory_order_relaxed);
-  header.chunk_id.store(next_chunk_id_, std::memory_order_relaxed);
-  header.packets.store(packets, std::memory_order_relaxed);
-
-  SharedMemoryABI::Chunk new_chunk =
-      shmem_arbiter_->GetNewChunk(header, buffer_exhausted_policy_);
-  if (!new_chunk.is_valid()) {
-    // Shared memory buffer exhausted, switch into |drop_packets_| mode. We'll
-    // drop data until the garbage chunk has been filled once and then retry.
-
-    // If we started a packet in one of the previous (valid) chunks, we need to
-    // tell the service to discard it.
-    if (fragmenting_packet_) {
-      // We can only end up here if the previous chunk was a valid chunk,
-      // because we never try to acquire a new chunk in |drop_packets_| mode
-      // while fragmenting.
-      PERFETTO_DCHECK(!drop_packets_);
-
-      // Backfill the last fragment's header with an invalid size (too large),
-      // so that the service's TraceBuffer throws out the incomplete packet.
-      // It'll restart reading from the next chunk we submit.
-      WriteRedundantVarInt(SharedMemoryABI::kPacketSizeDropPacket,
-                           cur_packet_->size_field());
-
-      // Reset the size field, since we should not write the current packet's
-      // size anymore after this.
-      cur_packet_->set_size_field(nullptr);
-
-      // We don't set kLastPacketContinuesOnNextChunk or kChunkNeedsPatching on
-      // the last chunk, because its last fragment will be discarded anyway.
-      // However, the current packet fragment points to a valid |cur_chunk_| and
-      // may have non-finalized nested messages which will continue in the
-      // garbage chunk and currently still point into |cur_chunk_|. As we are
-      // about to return |cur_chunk_|, we need to invalidate the size fields of
-      // those nested messages. Normally we move them in the |patch_list_| (see
-      // below) but in this case, it doesn't make sense to send patches for a
-      // fragment that will be discarded for sure. Thus, we clean up any size
-      // field references into |cur_chunk_|.
-      for (auto* nested_msg = cur_packet_->nested_message(); nested_msg;
-           nested_msg = nested_msg->nested_message()) {
-        uint8_t* const cur_hdr = nested_msg->size_field();
-
-        // If this is false the protozero Message has already been instructed to
-        // write, upon Finalize(), its size into the patch list.
-        bool size_field_points_within_chunk =
-            cur_hdr >= cur_chunk_.payload_begin() &&
-            cur_hdr + kMessageLengthFieldSize <= cur_chunk_.end();
-
-        if (size_field_points_within_chunk)
-          nested_msg->set_size_field(nullptr);
-      }
-    } else if (!drop_packets_ && last_packet_size_field_) {
-      // If we weren't dropping packets before, we should indicate to the
-      // service that we're about to lose data. We do this by invalidating the
-      // size of the last packet in |cur_chunk_|. The service will record
-      // statistics about packets with kPacketSizeDropPacket size.
-      PERFETTO_DCHECK(cur_packet_->is_finalized());
-      PERFETTO_DCHECK(cur_chunk_.is_valid());
-
-      // |last_packet_size_field_| should point within |cur_chunk_|'s payload.
-      PERFETTO_DCHECK(last_packet_size_field_ >= cur_chunk_.payload_begin() &&
-                      last_packet_size_field_ + kMessageLengthFieldSize <=
-                          cur_chunk_.end());
-
-      WriteRedundantVarInt(SharedMemoryABI::kPacketSizeDropPacket,
-                           last_packet_size_field_);
-    }
-
-    if (cur_chunk_.is_valid()) {
-      shmem_arbiter_->ReturnCompletedChunk(std::move(cur_chunk_),
-                                           target_buffer_, &patch_list_);
-    }
-
-    drop_packets_ = true;
-    cur_chunk_ = SharedMemoryABI::Chunk();  // Reset to an invalid chunk.
-    reached_max_packets_per_chunk_ = false;
-    retry_new_chunk_after_packet_ = false;
-    last_packet_size_field_ = nullptr;
-
-    PERFETTO_ANNOTATE_BENIGN_RACE_SIZED(&g_garbage_chunk,
-                                        sizeof(g_garbage_chunk),
-                                        "nobody reads the garbage chunk")
-    return protozero::ContiguousMemoryRange{
-        &g_garbage_chunk[0], &g_garbage_chunk[0] + sizeof(g_garbage_chunk)};
-  }  // if (!new_chunk.is_valid())
-
-  PERFETTO_DCHECK(new_chunk.is_valid());
-
-  if (fragmenting_packet_) {
-    // We should not be fragmenting a packet after we exited drop_packets_ mode,
-    // because we only retry to get a new chunk when a fresh packet is started.
-    PERFETTO_DCHECK(!drop_packets_);
-
     uint8_t* const wptr = protobuf_stream_writer_.write_ptr();
     PERFETTO_DCHECK(wptr >= cur_fragment_start_);
     uint32_t partial_size = static_cast<uint32_t>(wptr - cur_fragment_start_);
@@ -325,18 +187,27 @@
                                          &patch_list_);
   }
 
-  // Switch to the new chunk.
-  drop_packets_ = false;
-  reached_max_packets_per_chunk_ = false;
-  retry_new_chunk_after_packet_ = false;
-  next_chunk_id_++;
-  cur_chunk_ = std::move(new_chunk);
-  last_packet_size_field_ = nullptr;
+  // Start a new chunk.
 
+  ChunkHeader::Packets packets = {};
+  if (fragmenting_packet_) {
+    packets.count = 1;
+    packets.flags = ChunkHeader::kFirstPacketContinuesFromPrevChunk;
+  }
+
+  // The memory order of the stores below doesn't really matter. This |header|
+  // is just a local temporary object. The GetNewChunk() call below will copy it
+  // into the shared buffer with the proper barriers.
+  ChunkHeader header = {};
+  header.writer_id.store(id_, std::memory_order_relaxed);
+  header.chunk_id.store(next_chunk_id_++, std::memory_order_relaxed);
+  header.packets.store(packets, std::memory_order_relaxed);
+
+  cur_chunk_ = shmem_arbiter_->GetNewChunk(header);
+  reached_max_packets_per_chunk_ = false;
   uint8_t* payload_begin = cur_chunk_.payload_begin();
   if (fragmenting_packet_) {
     cur_packet_->set_size_field(payload_begin);
-    last_packet_size_field_ = payload_begin;
     memset(payload_begin, 0, kPacketHeaderSize);
     payload_begin += kPacketHeaderSize;
     cur_fragment_start_ = payload_begin;
diff --git a/src/tracing/core/trace_writer_impl.h b/src/tracing/core/trace_writer_impl.h
index 691f5fb..4bc1df9 100644
--- a/src/tracing/core/trace_writer_impl.h
+++ b/src/tracing/core/trace_writer_impl.h
@@ -17,14 +17,11 @@
 #ifndef SRC_TRACING_CORE_TRACE_WRITER_IMPL_H_
 #define SRC_TRACING_CORE_TRACE_WRITER_IMPL_H_
 
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/shared_memory_abi.h"
-#include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
 #include "perfetto/protozero/message_handle.h"
-#include "perfetto/protozero/proto_utils.h"
 #include "perfetto/protozero/scattered_stream_writer.h"
-#include "perfetto/tracing/buffer_exhausted_policy.h"
+#include "perfetto/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/shared_memory_abi.h"
+#include "perfetto/tracing/core/trace_writer.h"
 #include "src/tracing/core/patch_list.h"
 
 namespace perfetto {
@@ -36,10 +33,7 @@
                         public protozero::ScatteredStreamWriter::Delegate {
  public:
   // TracePacketHandle is defined in trace_writer.h
-  TraceWriterImpl(SharedMemoryArbiterImpl*,
-                  WriterID,
-                  BufferID,
-                  BufferExhaustedPolicy);
+  TraceWriterImpl(SharedMemoryArbiterImpl*, WriterID, BufferID);
   ~TraceWriterImpl() override;
 
   // TraceWriter implementation. See documentation in trace_writer.h.
@@ -52,7 +46,6 @@
   }
 
   void ResetChunkForTesting() { cur_chunk_ = SharedMemoryABI::Chunk(); }
-  bool drop_packets_for_testing() const { return drop_packets_; }
 
  private:
   TraceWriterImpl(const TraceWriterImpl&) = delete;
@@ -72,10 +65,6 @@
   // See comments in data_source_config.proto for |target_buffer|.
   const BufferID target_buffer_;
 
-  // Whether GetNewChunk() should stall or return an invalid chunk if the SMB is
-  // exhausted.
-  const BufferExhaustedPolicy buffer_exhausted_policy_;
-
   // Monotonic (% wrapping) sequence id of the chunk. Together with the WriterID
   // this allows the Service to reconstruct the linear sequence of packets.
   ChunkID next_chunk_id_ = 0;
@@ -106,20 +95,6 @@
   // a new chunk.
   bool reached_max_packets_per_chunk_ = false;
 
-  // If we fail to acquire a new chunk when the arbiter operates in
-  // SharedMemory::BufferExhaustedPolicy::kDrop mode, the trace writer enters a
-  // mode in which data is written to a local garbage chunk and dropped.
-  bool drop_packets_ = false;
-
-  // Whether the trace writer should try to acquire a new chunk from the SMB
-  // when the next TracePacket is started because it filled the garbage chunk at
-  // least once since the last attempt.
-  bool retry_new_chunk_after_packet_ = false;
-
-  // Points to the size field of the last packet we wrote to the current chunk.
-  // If the chunk was already returned, this is reset to |nullptr|.
-  uint8_t* last_packet_size_field_ = nullptr;
-
   // When a packet is fragmented across different chunks, the |size_field| of
   // the outstanding nested protobuf messages is redirected onto Patch entries
   // in this list at the time the Chunk is returned (because at that point we
diff --git a/src/tracing/core/trace_writer_impl_unittest.cc b/src/tracing/core/trace_writer_impl_unittest.cc
index 00f7c0c..2f01eec 100644
--- a/src/tracing/core/trace_writer_impl_unittest.cc
+++ b/src/tracing/core/trace_writer_impl_unittest.cc
@@ -16,19 +16,19 @@
 
 #include "src/tracing/core/trace_writer_impl.h"
 
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/tracing/core/commit_data_request.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/tracing/core/commit_data_request.h"
+#include "perfetto/tracing/core/trace_writer.h"
+#include "perfetto/tracing/core/tracing_service.h"
 #include "src/base/test/gtest_test_suite.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/tracing/core/shared_memory_arbiter_impl.h"
 #include "src/tracing/test/aligned_buffer_test.h"
 #include "src/tracing/test/fake_producer_endpoint.h"
-#include "test/gtest_and_gmock.h"
 
-#include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/test_event.pbzero.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
 namespace {
@@ -145,109 +145,6 @@
   ASSERT_EQ(1, last_commit.chunks_to_patch()[0].patches_size());
 }
 
-// Sets up a scenario in which the SMB is exhausted and TraceWriter fails to get
-// a new chunk while fragmenting a packet. Verifies that data is dropped until
-// the SMB is freed up and TraceWriter can get a new chunk.
-TEST_P(TraceWriterImplTest, FragmentingPacketWhileBufferExhausted) {
-  arbiter_.reset(new SharedMemoryArbiterImpl(buf(), buf_size(), page_size(),
-                                             &fake_producer_endpoint_,
-                                             task_runner_.get()));
-
-  const BufferID kBufId = 42;
-  std::unique_ptr<TraceWriter> writer =
-      arbiter_->CreateTraceWriter(kBufId, BufferExhaustedPolicy::kDrop);
-
-  // Write a small first packet, so that |writer| owns a chunk.
-  auto packet = writer->NewTracePacket();
-  EXPECT_FALSE(reinterpret_cast<TraceWriterImpl*>(writer.get())
-                   ->drop_packets_for_testing());
-  EXPECT_EQ(packet->Finalize(), 0u);
-
-  // Grab all the remaining chunks in the SMB in new writers.
-  std::array<std::unique_ptr<TraceWriter>, kNumPages * 4 - 1> other_writers;
-  for (size_t i = 0; i < other_writers.size(); i++) {
-    other_writers[i] =
-        arbiter_->CreateTraceWriter(kBufId, BufferExhaustedPolicy::kDrop);
-    auto other_writer_packet = other_writers[i]->NewTracePacket();
-    EXPECT_FALSE(reinterpret_cast<TraceWriterImpl*>(other_writers[i].get())
-                     ->drop_packets_for_testing());
-  }
-
-  // Write a packet that's guaranteed to span more than a single chunk, causing
-  // |writer| to attempt to acquire a new chunk but fail to do so.
-  auto packet2 = writer->NewTracePacket();
-  size_t chunk_size = page_size() / 4;
-  std::stringstream large_string_writer;
-  for (size_t pos = 0; pos < chunk_size; pos++)
-    large_string_writer << "x";
-  std::string large_string = large_string_writer.str();
-  packet2->set_for_testing()->set_str(large_string.data(), large_string.size());
-
-  EXPECT_TRUE(reinterpret_cast<TraceWriterImpl*>(writer.get())
-                  ->drop_packets_for_testing());
-
-  // First chunk should be committed.
-  arbiter_->FlushPendingCommitDataRequests();
-  const auto& last_commit = fake_producer_endpoint_.last_commit_data_request;
-  ASSERT_EQ(1, last_commit.chunks_to_move_size());
-  EXPECT_EQ(0u, last_commit.chunks_to_move()[0].page());
-  EXPECT_EQ(0u, last_commit.chunks_to_move()[0].chunk());
-  EXPECT_EQ(kBufId, last_commit.chunks_to_move()[0].target_buffer());
-  EXPECT_EQ(0, last_commit.chunks_to_patch_size());
-
-  // It should not need patching and not have the continuation flag set.
-  SharedMemoryABI* abi = arbiter_->shmem_abi_for_testing();
-  ASSERT_EQ(SharedMemoryABI::kChunkComplete, abi->GetChunkState(0u, 0u));
-  auto chunk = abi->TryAcquireChunkForReading(0u, 0u);
-  ASSERT_TRUE(chunk.is_valid());
-  ASSERT_EQ(2, chunk.header()->packets.load().count);
-  ASSERT_FALSE(chunk.header()->packets.load().flags &
-               SharedMemoryABI::ChunkHeader::kChunkNeedsPatching);
-  ASSERT_FALSE(chunk.header()->packets.load().flags &
-               SharedMemoryABI::ChunkHeader::kLastPacketContinuesOnNextChunk);
-
-  // Writing more data while in garbage mode succeeds. This data is dropped.
-  packet2->Finalize();
-  auto packet3 = writer->NewTracePacket();
-  packet3->set_for_testing()->set_str(large_string.data(), large_string.size());
-
-  // Release the |writer|'s first chunk as free, so that it can grab it again.
-  abi->ReleaseChunkAsFree(std::move(chunk));
-
-  // Starting a new packet should cause TraceWriter to attempt to grab a new
-  // chunk again, because we wrote enough data to wrap the garbage chunk.
-  packet3->Finalize();
-  auto packet4 = writer->NewTracePacket();
-
-  // Grabbing the chunk should have succeeded.
-  EXPECT_FALSE(reinterpret_cast<TraceWriterImpl*>(writer.get())
-                   ->drop_packets_for_testing());
-
-  // The first packet in the chunk should have the previous_packet_dropped flag
-  // set, so shouldn't be empty.
-  EXPECT_GT(packet4->Finalize(), 0u);
-
-  // Flushing the writer causes the chunk to be released again.
-  writer->Flush();
-  EXPECT_EQ(1, last_commit.chunks_to_move_size());
-  EXPECT_EQ(0u, last_commit.chunks_to_move()[0].page());
-  EXPECT_EQ(0u, last_commit.chunks_to_move()[0].chunk());
-  ASSERT_EQ(0, last_commit.chunks_to_patch_size());
-
-  // Chunk should contain only |packet4| and not have any continuation flag set.
-  ASSERT_EQ(SharedMemoryABI::kChunkComplete, abi->GetChunkState(0u, 0u));
-  chunk = abi->TryAcquireChunkForReading(0u, 0u);
-  ASSERT_TRUE(chunk.is_valid());
-  ASSERT_EQ(1, chunk.header()->packets.load().count);
-  ASSERT_FALSE(chunk.header()->packets.load().flags &
-               SharedMemoryABI::ChunkHeader::kChunkNeedsPatching);
-  ASSERT_FALSE(
-      chunk.header()->packets.load().flags &
-      SharedMemoryABI::ChunkHeader::kFirstPacketContinuesFromPrevChunk);
-  ASSERT_FALSE(chunk.header()->packets.load().flags &
-               SharedMemoryABI::ChunkHeader::kLastPacketContinuesOnNextChunk);
-}
-
 // TODO(primiano): add multi-writer test.
 // TODO(primiano): add Flush() test.
 
diff --git a/src/tracing/core/tracing_service_impl.cc b/src/tracing/core/tracing_service_impl.cc
index 26331d7..1f32db6 100644
--- a/src/tracing/core/tracing_service_impl.cc
+++ b/src/tracing/core/tracing_service_impl.cc
@@ -38,26 +38,24 @@
 #include <algorithm>
 
 #include "perfetto/base/build_config.h"
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/metatrace.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/base/watchdog.h"
-#include "perfetto/ext/tracing/core/consumer.h"
-#include "perfetto/ext/tracing/core/producer.h"
-#include "perfetto/ext/tracing/core/shared_memory.h"
-#include "perfetto/ext/tracing/core/shared_memory_abi.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "perfetto/tracing/core/data_source_descriptor.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/tracing/core/consumer.h"
+#include "perfetto/tracing/core/data_source_config.h"
+#include "perfetto/tracing/core/producer.h"
+#include "perfetto/tracing/core/shared_memory.h"
+#include "perfetto/tracing/core/shared_memory_abi.h"
+#include "perfetto/tracing/core/trace_packet.h"
+#include "perfetto/tracing/core/trace_writer.h"
 #include "perfetto/tracing/core/tracing_service_state.h"
 #include "src/tracing/core/packet_stream_validator.h"
 #include "src/tracing/core/shared_memory_arbiter_impl.h"
 #include "src/tracing/core/trace_buffer.h"
 
-#include "protos/perfetto/trace/clock_snapshot.pb.h"
-#include "protos/perfetto/trace/system_info.pb.h"
-#include "protos/perfetto/trace/trusted_packet.pb.h"
+#include "perfetto/trace/clock_snapshot.pb.h"
+#include "perfetto/trace/system_info.pb.h"
+#include "perfetto/trace/trusted_packet.pb.h"
 
 // General note: this class must assume that Producers are malicious and will
 // try to crash / exploit this class. We can trust pointers because they come
@@ -67,6 +65,7 @@
 namespace perfetto {
 
 namespace {
+constexpr size_t kDefaultShmPageSize = base::kPageSize;
 constexpr int kMaxBuffersPerConsumer = 128;
 constexpr base::TimeMillis kSnapshotsInterval(10 * 1000);
 constexpr int kDefaultWriteIntoFilePeriodMs = 5000;
@@ -76,7 +75,7 @@
 constexpr uint32_t kMaxTracingDurationMillis = 7 * 24 * kMillisPerHour;
 
 // These apply only if enable_extra_guardrails is true.
-constexpr uint32_t kGuardrailsMaxTracingBufferSizeKb = 128 * 1024;
+constexpr uint32_t kGuardrailsMaxTracingBufferSizeKb = 32 * 1024;
 constexpr uint32_t kGuardrailsMaxTracingDurationMillis = 24 * kMillisPerHour;
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
@@ -110,34 +109,10 @@
 }
 #endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
 
-// Partially encodes a CommitDataRequest in an int32 for the purposes of
-// metatracing. Note that it encodes only the bottom 10 bits of the producer id
-// (which is technically 16 bits wide).
-//
-// Format (by bit range):
-// [   31 ][         30 ][             29:20 ][            19:10 ][        9:0]
-// [unused][has flush id][num chunks to patch][num chunks to move][producer id]
-static int32_t EncodeCommitDataRequest(ProducerID producer_id,
-                                       const CommitDataRequest& req_untrusted) {
-  uint32_t cmov = static_cast<uint32_t>(req_untrusted.chunks_to_move_size());
-  uint32_t cpatch = static_cast<uint32_t>(req_untrusted.chunks_to_patch_size());
-  uint32_t has_flush_id = req_untrusted.flush_request_id() != 0;
-
-  uint32_t mask = (1 << 10) - 1;
-  uint32_t acc = 0;
-  acc |= has_flush_id << 30;
-  acc |= (cpatch & mask) << 20;
-  acc |= (cmov & mask) << 10;
-  acc |= (producer_id & mask);
-  return static_cast<int32_t>(acc);
-}
-
 }  // namespace
 
 // These constants instead are defined in the header because are used by tests.
 constexpr size_t TracingServiceImpl::kDefaultShmSize;
-constexpr size_t TracingServiceImpl::kDefaultShmPageSize;
-
 constexpr size_t TracingServiceImpl::kMaxShmSize;
 constexpr uint32_t TracingServiceImpl::kDataSourceStopTimeoutMs;
 constexpr uint8_t TracingServiceImpl::kSyncMarker[];
@@ -171,8 +146,7 @@
                                     const std::string& producer_name,
                                     size_t shared_memory_size_hint_bytes,
                                     bool in_process,
-                                    ProducerSMBScrapingMode smb_scraping_mode,
-                                    size_t shared_memory_page_size_hint_bytes) {
+                                    ProducerSMBScrapingMode smb_scraping_mode) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
 
   if (lockdown_mode_ && uid != geteuid()) {
@@ -206,10 +180,9 @@
   auto it_and_inserted = producers_.emplace(id, endpoint.get());
   PERFETTO_DCHECK(it_and_inserted.second);
   endpoint->shmem_size_hint_bytes_ = shared_memory_size_hint_bytes;
-  endpoint->shmem_page_size_hint_bytes_ = shared_memory_page_size_hint_bytes;
   task_runner_->PostTask(std::bind(&Producer::OnConnect, endpoint->producer_));
 
-  return std::unique_ptr<ProducerEndpoint>(std::move(endpoint));
+  return std::move(endpoint);
 }
 
 void TracingServiceImpl::DisconnectProducer(ProducerID id) {
@@ -252,16 +225,8 @@
       new ConsumerEndpointImpl(this, task_runner_, consumer, uid));
   auto it_and_inserted = consumers_.emplace(endpoint.get());
   PERFETTO_DCHECK(it_and_inserted.second);
-  // Consumer might go away before we're able to send the connect notification,
-  // if that is the case just bail out.
-  auto weak_ptr = endpoint->GetWeakPtr();
-  task_runner_->PostTask([weak_ptr] {
-    if (!weak_ptr) {
-      return;
-    }
-    weak_ptr->consumer_->OnConnect();
-  });
-  return std::unique_ptr<ConsumerEndpoint>(std::move(endpoint));
+  task_runner_->PostTask(std::bind(&Consumer::OnConnect, endpoint->consumer_));
+  return std::move(endpoint);
 }
 
 void TracingServiceImpl::DisconnectConsumer(ConsumerEndpointImpl* consumer) {
@@ -342,9 +307,9 @@
   PERFETTO_DCHECK_THREAD(thread_checker_);
   PERFETTO_DLOG("Enabling tracing for consumer %p",
                 reinterpret_cast<void*>(consumer));
-  if (cfg.lockdown_mode() == TraceConfig::LOCKDOWN_SET)
+  if (cfg.lockdown_mode() == TraceConfig::LockdownModeOperation::LOCKDOWN_SET)
     lockdown_mode_ = true;
-  if (cfg.lockdown_mode() == TraceConfig::LOCKDOWN_CLEAR)
+  if (cfg.lockdown_mode() == TraceConfig::LockdownModeOperation::LOCKDOWN_CLEAR)
     lockdown_mode_ = false;
   TracingSession* tracing_session =
       GetTracingSession(consumer->tracing_session_id_);
@@ -417,7 +382,7 @@
     for (auto& kv : tracing_sessions_) {
       if (kv.second.config.unique_session_name() == name) {
         PERFETTO_ELOG(
-            "A trace with this unique session name (%s) already exists",
+            "A trace wtih this unique session name (%s) already exists",
             name.c_str());
         return false;
       }
@@ -837,13 +802,22 @@
   for (auto& data_source_inst : tracing_session->data_source_instances) {
     const ProducerID producer_id = data_source_inst.first;
     DataSourceInstance& instance = data_source_inst.second;
+    const DataSourceInstanceID ds_inst_id = instance.instance_id;
     ProducerEndpointImpl* producer = GetProducer(producer_id);
     PERFETTO_DCHECK(producer);
     PERFETTO_DCHECK(instance.state == DataSourceInstance::CONFIGURED ||
                     instance.state == DataSourceInstance::STARTING ||
                     instance.state == DataSourceInstance::STARTED);
-    StopDataSourceInstance(producer, tracing_session, &instance,
-                           disable_immediately);
+    if (instance.will_notify_on_stop && !disable_immediately) {
+      instance.state = DataSourceInstance::STOPPING;
+    } else {
+      instance.state = DataSourceInstance::STOPPED;
+    }
+    if (tracing_session->consumer_maybe_null) {
+      tracing_session->consumer_maybe_null->OnDataSourceInstanceStateChange(
+          *producer, instance);
+    }
+    producer->StopDataSource(ds_inst_id);
   }
 
   // Either this request is flagged with |disable_immediately| or there are no
@@ -855,12 +829,15 @@
 
   tracing_session->state = TracingSession::DISABLING_WAITING_STOP_ACKS;
   auto weak_this = weak_ptr_factory_.GetWeakPtr();
+  auto timeout_ms = override_data_source_test_timeout_ms_for_testing
+                        ? override_data_source_test_timeout_ms_for_testing
+                        : kDataSourceStopTimeoutMs;
   task_runner_->PostDelayedTask(
       [weak_this, tsid] {
         if (weak_this)
           weak_this->OnDisableTracingTimeout(tsid);
       },
-      tracing_session->data_source_stop_timeout_ms());
+      timeout_ms);
 
   // Deliberately NOT removing the session from |tracing_session_|, it's still
   // needed to call ReadBuffers(). FreeBuffers() will erase() the session.
@@ -878,13 +855,8 @@
     if (!instance)
       continue;
 
-    // If the tracing session was already stopped, ignore this notification.
-    if (tracing_session.state != TracingSession::STARTED)
-      continue;
-
     if (instance->state != DataSourceInstance::STARTING) {
-      PERFETTO_ELOG("Started data source instance in incorrect state: %d",
-                    instance->state);
+      PERFETTO_ELOG("Data source instance in incorrect state.");
       continue;
     }
 
@@ -912,10 +884,11 @@
       continue;
 
     if (instance->state != DataSourceInstance::STOPPING) {
-      PERFETTO_ELOG("Stopped data source instance in incorrect state: %d",
-                    instance->state);
+      PERFETTO_ELOG("Data source instance in incorrect state.");
       continue;
     }
+    PERFETTO_DCHECK(tracing_session.state ==
+                    TracingSession::DISABLING_WAITING_STOP_ACKS);
 
     instance->state = DataSourceInstance::STOPPED;
 
@@ -929,9 +902,6 @@
     if (!tracing_session.AllDataSourceInstancesStopped())
       continue;
 
-    if (tracing_session.state != TracingSession::DISABLING_WAITING_STOP_ACKS)
-      continue;
-
     // All data sources acked the termination.
     DisableTracingNotifyConsumerAndFlushFile(&tracing_session);
   }  // for (tracing_session)
@@ -1456,13 +1426,8 @@
   base::TimeMillis now = base::GetWallTimeMs();
   if (now >= tracing_session->last_snapshot_time + kSnapshotsInterval) {
     tracing_session->last_snapshot_time = now;
-    // Don't emit the stats immediately, but instead wait until no more trace
-    // data is available to read. That way, any problems that occur while
-    // reading from the buffers are reflected in the emitted stats. This is
-    // particularly important for use cases where ReadBuffers is only ever
-    // called after the tracing session is stopped.
-    tracing_session->should_emit_stats = true;
     SnapshotSyncMarker(&packets);
+    SnapshotStats(tracing_session, &packets);
 
     if (!tracing_session->config.builtin_data_sources()
              .disable_clock_snapshotting()) {
@@ -1527,7 +1492,6 @@
       PERFETTO_DCHECK(sequence_properties.producer_uid_trusted != kInvalidUid);
       PERFETTO_DCHECK(packet.size() > 0);
       if (!PacketStreamValidator::Validate(packet.slices())) {
-        tracing_session->invalid_packets++;
         PERFETTO_DLOG("Dropping invalid packet");
         continue;
       }
@@ -1566,19 +1530,6 @@
     }  // for(packets...)
   }    // for(buffers...)
 
-  const bool has_more = did_hit_threshold;
-  if (!has_more && tracing_session->should_emit_stats) {
-    size_t prev_packets_size = packets.size();
-    SnapshotStats(tracing_session, &packets);
-    tracing_session->should_emit_stats = false;
-
-    // Add sizes of packets emitted by SnapshotStats.
-    for (size_t i = prev_packets_size; i < packets.size(); ++i) {
-      packets_bytes += packets[i].size();
-      total_slices += packets[i].slices().size();
-    }
-  }
-
   // If the caller asked us to write into a file by setting
   // |write_into_file| == true in the trace config, drain the packets read
   // (if any) into the given file descriptor.
@@ -1663,6 +1614,7 @@
     return true;
   }  // if (tracing_session->write_into_file)
 
+  const bool has_more = did_hit_threshold;
   if (has_more) {
     auto weak_consumer = consumer->GetWeakPtr();
     auto weak_this = weak_ptr_factory_.GetWeakPtr();
@@ -1764,28 +1716,9 @@
   }
 }
 
-void TracingServiceImpl::StopDataSourceInstance(ProducerEndpointImpl* producer,
-                                                TracingSession* tracing_session,
-                                                DataSourceInstance* instance,
-                                                bool disable_immediately) {
-  const DataSourceInstanceID ds_inst_id = instance->instance_id;
-  if (instance->will_notify_on_stop && !disable_immediately) {
-    instance->state = DataSourceInstance::STOPPING;
-  } else {
-    instance->state = DataSourceInstance::STOPPED;
-  }
-  if (tracing_session->consumer_maybe_null) {
-    tracing_session->consumer_maybe_null->OnDataSourceInstanceStateChange(
-        *producer, *instance);
-  }
-  producer->StopDataSource(ds_inst_id);
-}
-
 void TracingServiceImpl::UnregisterDataSource(ProducerID producer_id,
                                               const std::string& name) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
-  PERFETTO_DLOG("Producer %" PRIu16 " unregistered data source \"%s\"",
-                producer_id, name.c_str());
   PERFETTO_CHECK(producer_id);
   ProducerEndpointImpl* producer = GetProducer(producer_id);
   PERFETTO_DCHECK(producer);
@@ -1796,8 +1729,7 @@
         DataSourceInstanceID ds_inst_id = it->second.instance_id;
         if (it->second.state != DataSourceInstance::STOPPED) {
           if (it->second.state != DataSourceInstance::STOPPING)
-            StopDataSourceInstance(producer, &kv.second, &it->second,
-                                   /* disable_immediately = */ false);
+            producer->StopDataSource(ds_inst_id);
           // Mark the instance as stopped immediately, since we are
           // unregistering it below.
           if (it->second.state == DataSourceInstance::STOPPING)
@@ -1891,7 +1823,6 @@
 
   DataSourceConfig& ds_config = ds_instance->config;
   ds_config.set_trace_duration_ms(tracing_session->config.duration_ms());
-  ds_config.set_stop_timeout_ms(tracing_session->data_source_stop_timeout_ms());
   ds_config.set_enable_extra_guardrails(
       tracing_session->config.enable_extra_guardrails());
   ds_config.set_tracing_session_id(tracing_session->id);
@@ -1903,22 +1834,14 @@
                 ds_config.name().c_str(), global_id);
   if (!producer->shared_memory()) {
     // Determine the SMB page size. Must be an integer multiple of 4k.
-    // As for the SMB size below, the decision tree is as follows:
-    // 1. Give priority to what is defined in the trace config.
-    // 2. If unset give priority to the hint passed by the producer.
-    // 3. Keep within bounds and ensure it's a multiple of 4k.
     size_t page_size = std::min<size_t>(producer_config.page_size_kb() * 1024,
                                         SharedMemoryABI::kMaxPageSize);
-    if (page_size == 0) {
-      page_size = std::min<size_t>(producer->shmem_page_size_hint_bytes_,
-                                   SharedMemoryABI::kMaxPageSize);
-    }
     if (page_size < base::kPageSize || page_size % base::kPageSize != 0)
       page_size = kDefaultShmPageSize;
     producer->shared_buffer_page_size_kb_ = page_size / 1024;
 
     // Determine the SMB size. Must be an integer multiple of the SMB page size.
-    // The decision tree is as follows:
+    // The decisional tree is as follows:
     // 1. Give priority to what defined in the trace config.
     // 2. If unset give priority to the hint passed by the producer.
     // 3. Keep within bounds and ensure it's a multiple of the page size.
@@ -1932,8 +1855,6 @@
     // TODO(primiano): right now Create() will suicide in case of OOM if the
     // mmap fails. We should instead gracefully fail the request and tell the
     // client to go away.
-    PERFETTO_DLOG("Creating SMB of %zu KB for producer \"%s\"", shm_size / 1024,
-                  producer->name_.c_str());
     auto shared_memory = shm_factory_->CreateSharedMemory(shm_size);
     producer->SetSharedMemory(std::move(shared_memory));
     producer->OnTracingSetup();
@@ -2021,10 +1942,7 @@
     static_assert(std::numeric_limits<ChunkID>::max() == kMaxChunkID,
                   "Add a '|| chunk_id > kMaxChunkID' below if this fails");
     if (!writer_id || writer_id > kMaxWriterID || !buf) {
-      // This can genuinely happen when the trace is stopped. The producers
-      // might see the stop signal with some delay and try to keep sending
-      // patches left soon after.
-      PERFETTO_DLOG(
+      PERFETTO_ELOG(
           "Received invalid chunks_to_patch request from Producer: %" PRIu16
           ", BufferID: %" PRIu32 " ChunkdID: %" PRIu32 " WriterID: %" PRIu16,
           producer_id_trusted, chunk.target_buffer(), chunk_id, writer_id);
@@ -2135,7 +2053,8 @@
 }
 
 void TracingServiceImpl::UpdateMemoryGuardrail() {
-#if PERFETTO_BUILDFLAG(PERFETTO_WATCHDOG)
+#if !PERFETTO_BUILDFLAG(PERFETTO_EMBEDDER_BUILD) && \
+    !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
   uint64_t total_buffer_bytes = 0;
 
   // Sum up all the shared memory buffers.
@@ -2157,7 +2076,7 @@
 }
 
 void TracingServiceImpl::SnapshotSyncMarker(std::vector<TracePacket>* packets) {
-  // The sync marks are used to tokenize large traces efficiently.
+  // The sync markes is used to tokenize large traces efficiently.
   // See description in trace_packet.proto.
   if (sync_marker_packet_size_ == 0) {
     // Serialize the marker and the uid separately to guarantee that the marker
@@ -2177,7 +2096,7 @@
     PERFETTO_CHECK(packet.SerializeToArray(dst, size_left));
     sync_marker_packet_size_ += static_cast<size_t>(packet.ByteSize());
     PERFETTO_CHECK(sync_marker_packet_size_ <= sizeof(sync_marker_packet_));
-  }
+  };
   packets->emplace_back();
   packets->back().AddSlice(&sync_marker_packet_[0], sync_marker_packet_size_);
 }
@@ -2191,7 +2110,7 @@
     !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
   struct {
     clockid_t id;
-    protos::ClockSnapshot::Clock::BuiltinClocks type;
+    protos::ClockSnapshot::Clock::Type type;
     struct timespec ts;
   } clocks[] = {
       {CLOCK_BOOTTIME, protos::ClockSnapshot::Clock::BOOTTIME, {0, 0}},
@@ -2223,9 +2142,9 @@
         clock.type == protos::ClockSnapshot::Clock::BOOTTIME) {
       packet.set_timestamp(
           static_cast<uint64_t>(base::FromPosixTimespec(clock.ts).count()));
-    }
+    };
     protos::ClockSnapshot::Clock* c = clock_snapshot->add_clocks();
-    c->set_clock_id(static_cast<uint32_t>(clock.type));
+    c->set_type(clock.type);
     c->set_timestamp(
         static_cast<uint64_t>(base::FromPosixTimespec(clock.ts).count()));
   }
@@ -2234,7 +2153,7 @@
   if (set_root_timestamp)
     packet.set_timestamp(wall_time_ns);
   protos::ClockSnapshot::Clock* c = clock_snapshot->add_clocks();
-  c->set_clock_id(protos::ClockSnapshot::Clock::MONOTONIC);
+  c->set_type(protos::ClockSnapshot::Clock::MONOTONIC);
   c->set_timestamp(wall_time_ns);
 #endif  // !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
 
@@ -2272,7 +2191,6 @@
   trace_stats.set_total_buffers(static_cast<uint32_t>(buffers_.size()));
   trace_stats.set_chunks_discarded(chunks_discarded_);
   trace_stats.set_patches_discarded(patches_discarded_);
-  trace_stats.set_invalid_packets(tracing_session->invalid_packets);
 
   for (BufferID buf_id : tracing_session->buffers_index) {
     TraceBuffer* buf = GetBufferByID(buf_id);
@@ -2537,9 +2455,11 @@
   change->set_producer_name(producer.name_);
   change->set_data_source_name(instance.data_source_name);
   if (instance.state == DataSourceInstance::STARTED) {
-    change->set_state(ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STARTED);
+    change->set_state(ObservableEvents::DataSourceInstanceStateChange::
+                          DATA_SOURCE_INSTANCE_STATE_STARTED);
   } else {
-    change->set_state(ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STOPPED);
+    change->set_state(ObservableEvents::DataSourceInstanceStateChange::
+                          DATA_SOURCE_INSTANCE_STATE_STOPPED);
   }
 }
 
@@ -2590,7 +2510,7 @@
   for (const auto& kv : service_->data_sources_) {
     const auto& registered_data_source = kv.second;
     auto* data_source = svc_state.add_data_sources();
-    *data_source->mutable_ds_descriptor() = registered_data_source.descriptor;
+    *data_source->mutable_descriptor() = registered_data_source.descriptor;
     data_source->set_producer_id(
         static_cast<int>(registered_data_source.producer_id));
   }
@@ -2663,11 +2583,6 @@
     CommitDataCallback callback) {
   PERFETTO_DCHECK_THREAD(thread_checker_);
 
-  if (metatrace::IsEnabled(metatrace::TAG_TRACE_SERVICE)) {
-    PERFETTO_METATRACE_COUNTER(TAG_TRACE_SERVICE, TRACE_SERVICE_COMMIT_DATA,
-                               EncodeCommitDataRequest(id_, req_untrusted));
-  }
-
   if (!shared_memory_) {
     PERFETTO_DLOG(
         "Attempted to commit data before the shared memory was allocated.");
@@ -2778,11 +2693,8 @@
 
 // Can be called on any thread.
 std::unique_ptr<TraceWriter>
-TracingServiceImpl::ProducerEndpointImpl::CreateTraceWriter(
-    BufferID buf_id,
-    BufferExhaustedPolicy buffer_exhausted_policy) {
-  return GetInProcessShmemArbiter()->CreateTraceWriter(buf_id,
-                                                       buffer_exhausted_policy);
+TracingServiceImpl::ProducerEndpointImpl::CreateTraceWriter(BufferID buf_id) {
+  return GetInProcessShmemArbiter()->CreateTraceWriter(buf_id);
 }
 
 void TracingServiceImpl::ProducerEndpointImpl::NotifyFlushComplete(
diff --git a/src/tracing/core/tracing_service_impl.h b/src/tracing/core/tracing_service_impl.h
index 76ce0e2..038958e 100644
--- a/src/tracing/core/tracing_service_impl.h
+++ b/src/tracing/core/tracing_service_impl.h
@@ -24,19 +24,19 @@
 #include <set>
 #include <vector>
 
+#include "perfetto/base/gtest_prod_util.h"
 #include "perfetto/base/logging.h"
+#include "perfetto/base/optional.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/commit_data_request.h"
-#include "perfetto/ext/tracing/core/observable_events.h"
-#include "perfetto/ext/tracing/core/shared_memory_abi.h"
-#include "perfetto/ext/tracing/core/trace_stats.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
-#include "perfetto/tracing/core/data_source_config.h"
+#include "perfetto/base/weak_ptr.h"
+#include "perfetto/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/commit_data_request.h"
 #include "perfetto/tracing/core/data_source_descriptor.h"
+#include "perfetto/tracing/core/observable_events.h"
+#include "perfetto/tracing/core/shared_memory_abi.h"
 #include "perfetto/tracing/core/trace_config.h"
+#include "perfetto/tracing/core/trace_stats.h"
+#include "perfetto/tracing/core/tracing_service.h"
 #include "src/tracing/core/id_allocator.h"
 
 namespace perfetto {
@@ -60,7 +60,6 @@
   struct DataSourceInstance;
 
  public:
-  static constexpr size_t kDefaultShmPageSize = base::kPageSize;
   static constexpr size_t kDefaultShmSize = 256 * 1024ul;
   static constexpr size_t kMaxShmSize = 32 * 1024 * 1024ul;
   static constexpr uint32_t kDataSourceStopTimeoutMs = 5000;
@@ -89,9 +88,7 @@
     void UnregisterTraceWriter(uint32_t writer_id) override;
     void CommitData(const CommitDataRequest&, CommitDataCallback) override;
     void SetSharedMemory(std::unique_ptr<SharedMemory>);
-    std::unique_ptr<TraceWriter> CreateTraceWriter(
-        BufferID,
-        BufferExhaustedPolicy) override;
+    std::unique_ptr<TraceWriter> CreateTraceWriter(BufferID) override;
     SharedMemoryArbiter* GetInProcessShmemArbiter() override;
     void NotifyFlushComplete(FlushRequestID) override;
     void NotifyDataSourceStarted(DataSourceInstanceID) override;
@@ -137,7 +134,6 @@
     size_t shared_buffer_page_size_kb_ = 0;
     SharedMemoryABI shmem_abi_;
     size_t shmem_size_hint_bytes_ = 0;
-    size_t shmem_page_size_hint_bytes_ = 0;
     const std::string name_;
     bool in_process_;
     bool smb_scraping_enabled_;
@@ -272,8 +268,7 @@
       size_t shared_memory_size_hint_bytes = 0,
       bool in_process = false,
       ProducerSMBScrapingMode smb_scraping_mode =
-          ProducerSMBScrapingMode::kDefault,
-      size_t shared_memory_page_size_hint_bytes = 0) override;
+          ProducerSMBScrapingMode::kDefault) override;
 
   std::unique_ptr<TracingService::ConsumerEndpoint> ConnectConsumer(
       Consumer*,
@@ -289,6 +284,8 @@
   size_t num_producers() const { return producers_.size(); }
   ProducerEndpointImpl* GetProducer(ProducerID) const;
 
+  uint32_t override_data_source_test_timeout_ms_for_testing = 0;
+
  private:
   friend class TracingServiceImplTest;
   friend class TracingIntegrationTest;
@@ -364,11 +361,6 @@
       return timeout_ms ? timeout_ms : kDefaultFlushTimeoutMs;
     }
 
-    uint32_t data_source_stop_timeout_ms() {
-      uint32_t timeout_ms = config.data_source_stop_timeout_ms();
-      return timeout_ms ? timeout_ms : kDataSourceStopTimeoutMs;
-    }
-
     PacketSequenceID GetPacketSequenceID(ProducerID producer_id,
                                          WriterID writer_id) {
       auto key = std::make_pair(producer_id, writer_id);
@@ -458,10 +450,6 @@
     // the output stream.
     base::TimeMillis last_snapshot_time = {};
 
-    // Whether we should emit the trace stats next time we reach EOF while
-    // performing ReadBuffers.
-    bool should_emit_stats = false;
-
     // Whether we mirrored the trace config back to the trace output yet.
     bool did_emit_config = false;
 
@@ -471,9 +459,6 @@
     // The number of received triggers we've emitted into the trace output.
     size_t num_triggers_emitted_into_trace = 0;
 
-    // Packets that failed validation of the TrustedPacket.
-    uint64_t invalid_packets = 0;
-
     // Initial clock snapshot, captured at trace start time (when state goes
     // to TracingSession::STARTED). Emitted into the trace when the consumer
     // first begins reading the trace.
@@ -521,10 +506,6 @@
   void StartDataSourceInstance(ProducerEndpointImpl* producer,
                                TracingSession* tracing_session,
                                DataSourceInstance* instance);
-  void StopDataSourceInstance(ProducerEndpointImpl* producer,
-                              TracingSession* tracing_session,
-                              DataSourceInstance* instance,
-                              bool disable_immediately);
   void SnapshotSyncMarker(std::vector<TracePacket>*);
   void SnapshotClocks(std::vector<TracePacket>*, bool set_root_timestamp);
   void SnapshotStats(TracingSession*, std::vector<TracePacket>*);
diff --git a/src/tracing/core/tracing_service_impl_unittest.cc b/src/tracing/core/tracing_service_impl_unittest.cc
index b301612..ae54834 100644
--- a/src/tracing/core/tracing_service_impl_unittest.cc
+++ b/src/tracing/core/tracing_service_impl_unittest.cc
@@ -18,60 +18,53 @@
 
 #include <string.h>
 
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/tracing/core/consumer.h"
-#include "perfetto/ext/tracing/core/producer.h"
-#include "perfetto/ext/tracing/core/shared_memory.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/file_utils.h"
+#include "perfetto/base/temp_file.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/tracing/core/consumer.h"
 #include "perfetto/tracing/core/data_source_config.h"
 #include "perfetto/tracing/core/data_source_descriptor.h"
+#include "perfetto/tracing/core/producer.h"
+#include "perfetto/tracing/core/shared_memory.h"
+#include "perfetto/tracing/core/trace_packet.h"
+#include "perfetto/tracing/core/trace_writer.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/tracing/core/shared_memory_arbiter_impl.h"
 #include "src/tracing/core/trace_writer_impl.h"
 #include "src/tracing/test/mock_consumer.h"
 #include "src/tracing/test/mock_producer.h"
 #include "src/tracing/test/test_shared_memory.h"
-#include "test/gtest_and_gmock.h"
 
-#include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/trace.pb.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/test_event.pbzero.h"
+#include "perfetto/trace/trace.pb.h"
+#include "perfetto/trace/trace_packet.pb.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
 using ::testing::_;
-using ::testing::AssertionFailure;
-using ::testing::AssertionResult;
-using ::testing::AssertionSuccess;
 using ::testing::Contains;
 using ::testing::ElementsAreArray;
 using ::testing::Eq;
-using ::testing::ExplainMatchResult;
 using ::testing::InSequence;
 using ::testing::Invoke;
 using ::testing::InvokeWithoutArgs;
-using ::testing::IsEmpty;
 using ::testing::Mock;
 using ::testing::Not;
 using ::testing::Property;
 using ::testing::StrictMock;
-using ::testing::StringMatchResultListener;
 
 namespace perfetto {
 
 namespace {
 constexpr size_t kDefaultShmSizeKb = TracingServiceImpl::kDefaultShmSize / 1024;
-constexpr size_t kDefaultShmPageSizeKb =
-    TracingServiceImpl::kDefaultShmPageSize / 1024;
 constexpr size_t kMaxShmSizeKb = TracingServiceImpl::kMaxShmSize / 1024;
 
-AssertionResult HasTriggerModeInternal(
+::testing::AssertionResult HasTriggerModeInternal(
     const std::vector<protos::TracePacket>& packets,
     protos::TraceConfig::TriggerConfig::TriggerMode mode) {
-  StringMatchResultListener matcher_result_string;
-  bool contains = ExplainMatchResult(
+  ::testing::StringMatchResultListener matcher_result_string;
+  bool contains = ::testing::ExplainMatchResult(
       Contains(Property(
           &protos::TracePacket::trace_config,
           Property(&protos::TraceConfig::trigger_config,
@@ -79,9 +72,9 @@
                             Eq(mode))))),
       packets, &matcher_result_string);
   if (contains) {
-    return AssertionSuccess();
+    return ::testing::AssertionSuccess();
   }
-  return AssertionFailure() << matcher_result_string.str();
+  return ::testing::AssertionFailure() << matcher_result_string.str();
 }
 
 MATCHER_P(HasTriggerMode, mode, "") {
@@ -219,7 +212,7 @@
   consumer_a->DisableTracing();
   consumer_a->WaitForTracingDisabled();
 
-  EXPECT_THAT(consumer_b->ReadBuffers(), IsEmpty());
+  EXPECT_THAT(consumer_b->ReadBuffers(), ::testing::IsEmpty());
 }
 
 TEST_F(TracingServiceImplTest, RegisterAndUnregister) {
@@ -371,7 +364,7 @@
 
   producer->WaitForDataSourceStop("ds_1");
   consumer->WaitForTracingDisabled();
-  EXPECT_THAT(consumer->ReadBuffers(), IsEmpty());
+  EXPECT_THAT(consumer->ReadBuffers(), ::testing::IsEmpty());
 }
 
 // Creates a tracing session with a START_TRACING trigger and checks that
@@ -419,7 +412,7 @@
 
   producer->WaitForDataSourceStop("ds_1");
   consumer->WaitForTracingDisabled();
-  EXPECT_THAT(consumer->ReadBuffers(), IsEmpty());
+  EXPECT_THAT(consumer->ReadBuffers(), ::testing::IsEmpty());
 }
 
 // Creates a tracing session with a START_TRACING trigger and checks that the
@@ -511,7 +504,7 @@
 
   producer->WaitForDataSourceStop("ds_1");
   consumer->WaitForTracingDisabled();
-  EXPECT_THAT(consumer->ReadBuffers(), IsEmpty());
+  EXPECT_THAT(consumer->ReadBuffers(), ::testing::IsEmpty());
 }
 
 // Creates a tracing session with a START_TRACING trigger and checks that any
@@ -759,8 +752,10 @@
                  Eq(kServicePacketSequenceID))));
   };
   EXPECT_THAT(packets, expect_received_trigger("trigger_name"));
-  EXPECT_THAT(packets, Not(expect_received_trigger("trigger_name_2")));
-  EXPECT_THAT(packets, Not(expect_received_trigger("trigger_name_3")));
+  EXPECT_THAT(packets,
+              ::testing::Not(expect_received_trigger("trigger_name_2")));
+  EXPECT_THAT(packets,
+              ::testing::Not(expect_received_trigger("trigger_name_3")));
 }
 
 // Creates a tracing session with a START_TRACING trigger and checks that the
@@ -835,7 +830,8 @@
                  Eq(kServicePacketSequenceID))));
   };
   EXPECT_THAT(packets, expect_received_trigger("trigger_name"));
-  EXPECT_THAT(packets, Not(expect_received_trigger("trigger_name_2")));
+  EXPECT_THAT(packets,
+              ::testing::Not(expect_received_trigger("trigger_name_2")));
   EXPECT_THAT(packets, expect_received_trigger("trigger_name_3"));
 }
 
@@ -897,7 +893,8 @@
                   &protos::TraceConfig::TriggerConfig::trigger_mode,
                   Eq(protos::TraceConfig::TriggerConfig::STOP_TRACING))))));
   EXPECT_THAT(packets, expect_received_trigger("trigger_name"));
-  EXPECT_THAT(packets, Not(expect_received_trigger("trigger_name_2")));
+  EXPECT_THAT(packets,
+              ::testing::Not(expect_received_trigger("trigger_name_2")));
 
   // Send a new trigger.
   producer->endpoint()->ActivateTriggers({"trigger_name_2"});
@@ -915,7 +912,7 @@
 
   packets = consumer->ReadBuffers();
   // We don't rewrite the old trigger.
-  EXPECT_THAT(packets, Not(expect_received_trigger("trigger_name")));
+  EXPECT_THAT(packets, ::testing::Not(expect_received_trigger("trigger_name")));
   EXPECT_THAT(packets, expect_received_trigger("trigger_name_2"));
 }
 
@@ -953,7 +950,7 @@
   producer->WaitForDataSourceStart("ds_1");
 
   // The trace won't return data until unless we send a trigger at this point.
-  EXPECT_THAT(consumer->ReadBuffers(), IsEmpty());
+  EXPECT_THAT(consumer->ReadBuffers(), ::testing::IsEmpty());
 
   auto writer = producer->CreateTraceWriter("ds_1");
   producer->WaitForFlush(writer.get());
@@ -962,7 +959,7 @@
 
   producer->WaitForDataSourceStop("ds_1");
   consumer->WaitForTracingDisabled();
-  EXPECT_THAT(consumer->ReadBuffers(), IsEmpty());
+  EXPECT_THAT(consumer->ReadBuffers(), ::testing::IsEmpty());
 }
 
 // Creates a tracing session with a STOP_TRACING trigger and checks that the
@@ -997,7 +994,7 @@
   producer->WaitForDataSourceStart("ds_1");
 
   // The trace won't return data until unless we send a trigger at this point.
-  EXPECT_THAT(consumer->ReadBuffers(), IsEmpty());
+  EXPECT_THAT(consumer->ReadBuffers(), ::testing::IsEmpty());
 
   // We write into the buffer a large packet which takes up the whole buffer. We
   // then add a bunch of smaller ones which causes the larger packet to be
@@ -1053,9 +1050,10 @@
 
   // The large payload was overwritten before we trigger and ReadBuffers so it
   // should not be in the returned data.
-  EXPECT_THAT(packets, Not(Contains(Property(&protos::TracePacket::for_testing,
-                                             Property(&protos::TestEvent::str,
-                                                      Eq(large_payload))))));
+  EXPECT_THAT(packets,
+              ::testing::Not(Contains(Property(
+                  &protos::TracePacket::for_testing,
+                  Property(&protos::TestEvent::str, Eq(large_payload))))));
 }
 
 // Creates a tracing session with a STOP_TRACING trigger and checks that the
@@ -1092,7 +1090,7 @@
   producer->WaitForDataSourceStart("ds_1");
 
   // The trace won't return data until unless we send a trigger at this point.
-  EXPECT_THAT(consumer->ReadBuffers(), IsEmpty());
+  EXPECT_THAT(consumer->ReadBuffers(), ::testing::IsEmpty());
 
   std::vector<std::string> req;
   req.push_back("trigger_name");
@@ -1127,7 +1125,8 @@
   trace_config.add_buffers()->set_size_kb(128);
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
   ds_config->set_name("data_source");
-  trace_config.set_lockdown_mode(TraceConfig::LOCKDOWN_SET);
+  trace_config.set_lockdown_mode(
+      TraceConfig::LockdownModeOperation::LOCKDOWN_SET);
   consumer->EnableTracing(trace_config);
 
   producer->WaitForTracingSetup();
@@ -1146,7 +1145,8 @@
   producer->WaitForDataSourceStop("data_source");
   consumer->WaitForTracingDisabled();
 
-  trace_config.set_lockdown_mode(TraceConfig::LOCKDOWN_CLEAR);
+  trace_config.set_lockdown_mode(
+      TraceConfig::LockdownModeOperation::LOCKDOWN_CLEAR);
   consumer->EnableTracing(trace_config);
   producer->WaitForDataSourceSetup("data_source");
   producer->WaitForDataSourceStart("data_source");
@@ -1349,7 +1349,8 @@
   // SystemInfo
   // Trace read clocksnapshot
   // Trace synchronisation
-  static const int kNumPreamblePackets = 5;
+  // Trace stats
+  static const int kNumPreamblePackets = 6;
   static const int kNumTestPackets = 9;
   static const char kPayload[] = "1234567890abcdef-";
 
@@ -1398,20 +1399,8 @@
 TEST_F(TracingServiceImplTest, ProducerShmAndPageSizeOverriddenByTraceConfig) {
   std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
   consumer->Connect(svc.get());
-  const size_t kMaxPageSizeKb = SharedMemoryABI::kMaxPageSize / 1024;
-  const size_t kConfigPageSizesKb[] = /**/ {16, 0, 3, 2, 16, 8, 0, 4096, 0};
-  const size_t kPageHintSizesKb[] = /****/ {0, 4, 0, 0, 8, 0, 4096, 0, 0};
-  const size_t kExpectedPageSizesKb[] = {
-      16,                     // Use config value.
-      4,                      // Config is 0, use hint.
-      kDefaultShmPageSizeKb,  // Config % 4 != 0, take default.
-      kDefaultShmPageSizeKb,  // Less than page size, take default.
-      16,                     // Ignore the hint.
-      8,                      // Use config value.
-      kMaxPageSizeKb,         // Hint too big, take max value.
-      kMaxPageSizeKb,         // Config too high, take max value.
-      4                       // Fallback to default.
-  };
+  const size_t kConfigPageSizesKb[] = /****/ {16, 16, 4, 0, 16, 8, 3, 4096, 4};
+  const size_t kExpectedPageSizesKb[] = /**/ {16, 16, 4, 4, 16, 8, 4, 64, 4};
 
   const size_t kConfigSizesKb[] = /**/ {0, 16, 0, 20, 32, 7, 0, 96, 4096000};
   const size_t kHintSizesKb[] = /****/ {0, 0, 16, 32, 16, 0, 7, 96, 4096000};
@@ -1432,8 +1421,7 @@
   for (size_t i = 0; i < kNumProducers; i++) {
     auto name = "mock_producer_" + std::to_string(i);
     producer[i] = CreateMockProducer();
-    producer[i]->Connect(svc.get(), name, geteuid(), kHintSizesKb[i] * 1024,
-                         kPageHintSizesKb[i] * 1024);
+    producer[i]->Connect(svc.get(), name, geteuid(), kHintSizesKb[i] * 1024);
     producer[i]->RegisterDataSource("data_source");
   }
 
@@ -1580,7 +1568,7 @@
   ASSERT_EQ(4u, GetNumPendingFlushes());
 
   // Make the producer reply only to the 3rd flush request.
-  InSequence seq;
+  testing::InSequence seq;
   producer->WaitForFlush(nullptr, /*reply=*/false);  // Do NOT reply to flush 1.
   producer->WaitForFlush(nullptr, /*reply=*/false);  // Do NOT reply to flush 2.
   producer->WaitForFlush(writer.get());              // Reply only to flush 3.
@@ -1857,6 +1845,7 @@
 // skips the ack and checks that the service invokes the OnTracingDisabled()
 // after the timeout.
 TEST_F(TracingServiceImplTest, OnTracingDisabledCalledAnywaysInCaseOfTimeout) {
+  svc->override_data_source_test_timeout_ms_for_testing = 1;
   std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
   consumer->Connect(svc.get());
 
@@ -1868,7 +1857,6 @@
   trace_config.add_buffers()->set_size_kb(128);
   trace_config.add_data_sources()->mutable_config()->set_name("data_source");
   trace_config.set_duration_ms(1);
-  trace_config.set_data_source_stop_timeout_ms(1);
 
   consumer->EnableTracing(trace_config);
   producer->WaitForTracingSetup();
@@ -1898,7 +1886,7 @@
   producer2->Connect(svc.get(), "mock_producer2");
   producer2->RegisterDataSource("ds_2A");
 
-  InSequence seq;
+  testing::InSequence seq;
   TracingSessionID last_session_id = 0;
   for (int i = 0; i < 3; i++) {
     TraceConfig trace_config;
@@ -2701,7 +2689,8 @@
     ObservableEvents::DataSourceInstanceStateChange change;
     change.set_producer_name("mock_producer");
     change.set_data_source_name("data_source");
-    change.set_state(ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STARTED);
+    change.set_state(ObservableEvents::DataSourceInstanceStateChange::
+                         DATA_SOURCE_INSTANCE_STATE_STARTED);
     EXPECT_EQ(events.instance_state_changes_size(), 1);
     EXPECT_THAT(events.instance_state_changes(), Contains(Eq(change)));
   }
@@ -2715,7 +2704,8 @@
     ObservableEvents::DataSourceInstanceStateChange change;
     change.set_producer_name("mock_producer");
     change.set_data_source_name("data_source");
-    change.set_state(ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STOPPED);
+    change.set_state(ObservableEvents::DataSourceInstanceStateChange::
+                         DATA_SOURCE_INSTANCE_STATE_STOPPED);
     EXPECT_EQ(events.instance_state_changes_size(), 1);
     EXPECT_THAT(events.instance_state_changes(), Contains(Eq(change)));
   }
@@ -2735,7 +2725,8 @@
     ObservableEvents::DataSourceInstanceStateChange change;
     change.set_producer_name("mock_producer");
     change.set_data_source_name("data_source");
-    change.set_state(ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STOPPED);
+    change.set_state(ObservableEvents::DataSourceInstanceStateChange::
+                         DATA_SOURCE_INSTANCE_STATE_STOPPED);
     EXPECT_EQ(events.instance_state_changes_size(), 1);
     EXPECT_THAT(events.instance_state_changes(), Contains(Eq(change)));
   }
@@ -2751,7 +2742,8 @@
     ObservableEvents::DataSourceInstanceStateChange change;
     change.set_producer_name("mock_producer");
     change.set_data_source_name("data_source");
-    change.set_state(ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STARTED);
+    change.set_state(ObservableEvents::DataSourceInstanceStateChange::
+                         DATA_SOURCE_INSTANCE_STATE_STARTED);
     EXPECT_EQ(events.instance_state_changes_size(), 1);
     EXPECT_THAT(events.instance_state_changes(), Contains(Eq(change)));
   }
@@ -2768,61 +2760,6 @@
   consumer->WaitForTracingDisabled();
 }
 
-TEST_F(TracingServiceImplTest, ObserveEventsDataSourceInstancesUnregister) {
-  std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
-  consumer->Connect(svc.get());
-
-  std::unique_ptr<MockProducer> producer = CreateMockProducer();
-  producer->Connect(svc.get(), "mock_producer");
-  producer->RegisterDataSource("data_source");
-
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(128);
-  auto* ds_config = trace_config.add_data_sources()->mutable_config();
-  ds_config->set_name("data_source");
-
-  // Start tracing before the consumer is interested in events. The consumer's
-  // OnObservableEvents() should not be called yet.
-  consumer->EnableTracing(trace_config);
-  producer->WaitForTracingSetup();
-  producer->WaitForDataSourceSetup("data_source");
-  producer->WaitForDataSourceStart("data_source");
-
-  // Calling ObserveEvents should cause an event for the initial instance state.
-  consumer->ObserveEvents(TracingService::ConsumerEndpoint::
-                              ObservableEventType::kDataSourceInstances);
-  {
-    ObservableEvents event;
-    ObservableEvents::DataSourceInstanceStateChange* change =
-        event.add_instance_state_changes();
-    change->set_producer_name("mock_producer");
-    change->set_data_source_name("data_source");
-    change->set_state(ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STARTED);
-    EXPECT_CALL(*consumer, OnObservableEvents(Eq(event)))
-        .WillOnce(InvokeWithoutArgs(
-            task_runner.CreateCheckpoint("data_source_started")));
-
-    task_runner.RunUntilCheckpoint("data_source_started");
-  }
-  {
-    ObservableEvents event;
-    ObservableEvents::DataSourceInstanceStateChange* change =
-        event.add_instance_state_changes();
-    change->set_producer_name("mock_producer");
-    change->set_data_source_name("data_source");
-    change->set_state(ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STOPPED);
-    EXPECT_CALL(*consumer, OnObservableEvents(Eq(event)))
-        .WillOnce(InvokeWithoutArgs(
-            task_runner.CreateCheckpoint("data_source_stopped")));
-  }
-  producer->UnregisterDataSource("data_source");
-  producer->WaitForDataSourceStop("data_source");
-  task_runner.RunUntilCheckpoint("data_source_stopped");
-
-  consumer->DisableTracing();
-  consumer->WaitForTracingDisabled();
-}
-
 TEST_F(TracingServiceImplTest, QueryServiceState) {
   std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
   consumer->Connect(svc.get());
@@ -2841,37 +2778,37 @@
 
   TracingServiceState svc_state = consumer->QueryServiceState();
 
-  EXPECT_EQ(svc_state.producers_size(), 2);
+  EXPECT_EQ(svc_state.producers_size(), 2u);
   EXPECT_EQ(svc_state.producers().at(0).id(), 1);
   EXPECT_EQ(svc_state.producers().at(0).name(), "producer1");
   EXPECT_EQ(svc_state.producers().at(1).id(), 2);
   EXPECT_EQ(svc_state.producers().at(1).name(), "producer2");
 
-  EXPECT_EQ(svc_state.data_sources_size(), 4);
+  EXPECT_EQ(svc_state.data_sources_size(), 4u);
 
   EXPECT_EQ(svc_state.data_sources().at(0).producer_id(), 1);
-  EXPECT_EQ(svc_state.data_sources().at(0).ds_descriptor().name(), "common_ds");
+  EXPECT_EQ(svc_state.data_sources().at(0).descriptor().name(), "common_ds");
 
   EXPECT_EQ(svc_state.data_sources().at(1).producer_id(), 2);
-  EXPECT_EQ(svc_state.data_sources().at(1).ds_descriptor().name(), "common_ds");
+  EXPECT_EQ(svc_state.data_sources().at(1).descriptor().name(), "common_ds");
 
   EXPECT_EQ(svc_state.data_sources().at(2).producer_id(), 1);
-  EXPECT_EQ(svc_state.data_sources().at(2).ds_descriptor().name(), "p1_ds");
+  EXPECT_EQ(svc_state.data_sources().at(2).descriptor().name(), "p1_ds");
 
   EXPECT_EQ(svc_state.data_sources().at(3).producer_id(), 2);
-  EXPECT_EQ(svc_state.data_sources().at(3).ds_descriptor().name(), "p2_ds");
+  EXPECT_EQ(svc_state.data_sources().at(3).descriptor().name(), "p2_ds");
 
   // Test that descriptors are cleared when a producer disconnects.
   producer1.reset();
   svc_state = consumer->QueryServiceState();
 
-  EXPECT_EQ(svc_state.producers_size(), 1);
-  EXPECT_EQ(svc_state.data_sources_size(), 2);
+  EXPECT_EQ(svc_state.producers_size(), 1u);
+  EXPECT_EQ(svc_state.data_sources_size(), 2u);
 
   EXPECT_EQ(svc_state.data_sources().at(0).producer_id(), 2);
-  EXPECT_EQ(svc_state.data_sources().at(0).ds_descriptor().name(), "common_ds");
+  EXPECT_EQ(svc_state.data_sources().at(0).descriptor().name(), "common_ds");
   EXPECT_EQ(svc_state.data_sources().at(1).producer_id(), 2);
-  EXPECT_EQ(svc_state.data_sources().at(1).ds_descriptor().name(), "p2_ds");
+  EXPECT_EQ(svc_state.data_sources().at(1).descriptor().name(), "p2_ds");
 }
 
 }  // namespace perfetto
diff --git a/src/tracing/core/tracing_service_state.cc b/src/tracing/core/tracing_service_state.cc
new file mode 100644
index 0000000..38601f2
--- /dev/null
+++ b/src/tracing/core/tracing_service_state.cc
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * perfetto/common/tracing_service_state.proto
+ * by
+ * ../../tools/proto_to_cpp/proto_to_cpp.cc.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+#include "perfetto/tracing/core/tracing_service_state.h"
+
+#include "perfetto/common/data_source_descriptor.pb.h"
+#include "perfetto/common/tracing_service_state.pb.h"
+
+namespace perfetto {
+
+TracingServiceState::TracingServiceState() = default;
+TracingServiceState::~TracingServiceState() = default;
+TracingServiceState::TracingServiceState(const TracingServiceState&) = default;
+TracingServiceState& TracingServiceState::operator=(
+    const TracingServiceState&) = default;
+TracingServiceState::TracingServiceState(TracingServiceState&&) noexcept =
+    default;
+TracingServiceState& TracingServiceState::operator=(TracingServiceState&&) =
+    default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool TracingServiceState::operator==(const TracingServiceState& other) const {
+  return (producers_ == other.producers_) &&
+         (data_sources_ == other.data_sources_) &&
+         (num_sessions_ == other.num_sessions_) &&
+         (num_sessions_started_ == other.num_sessions_started_);
+}
+#pragma GCC diagnostic pop
+
+void TracingServiceState::FromProto(
+    const perfetto::protos::TracingServiceState& proto) {
+  producers_.clear();
+  for (const auto& field : proto.producers()) {
+    producers_.emplace_back();
+    producers_.back().FromProto(field);
+  }
+
+  data_sources_.clear();
+  for (const auto& field : proto.data_sources()) {
+    data_sources_.emplace_back();
+    data_sources_.back().FromProto(field);
+  }
+
+  static_assert(sizeof(num_sessions_) == sizeof(proto.num_sessions()),
+                "size mismatch");
+  num_sessions_ = static_cast<decltype(num_sessions_)>(proto.num_sessions());
+
+  static_assert(
+      sizeof(num_sessions_started_) == sizeof(proto.num_sessions_started()),
+      "size mismatch");
+  num_sessions_started_ = static_cast<decltype(num_sessions_started_)>(
+      proto.num_sessions_started());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void TracingServiceState::ToProto(
+    perfetto::protos::TracingServiceState* proto) const {
+  proto->Clear();
+
+  for (const auto& it : producers_) {
+    auto* entry = proto->add_producers();
+    it.ToProto(entry);
+  }
+
+  for (const auto& it : data_sources_) {
+    auto* entry = proto->add_data_sources();
+    it.ToProto(entry);
+  }
+
+  static_assert(sizeof(num_sessions_) == sizeof(proto->num_sessions()),
+                "size mismatch");
+  proto->set_num_sessions(
+      static_cast<decltype(proto->num_sessions())>(num_sessions_));
+
+  static_assert(
+      sizeof(num_sessions_started_) == sizeof(proto->num_sessions_started()),
+      "size mismatch");
+  proto->set_num_sessions_started(
+      static_cast<decltype(proto->num_sessions_started())>(
+          num_sessions_started_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+TracingServiceState::Producer::Producer() = default;
+TracingServiceState::Producer::~Producer() = default;
+TracingServiceState::Producer::Producer(const TracingServiceState::Producer&) =
+    default;
+TracingServiceState::Producer& TracingServiceState::Producer::operator=(
+    const TracingServiceState::Producer&) = default;
+TracingServiceState::Producer::Producer(
+    TracingServiceState::Producer&&) noexcept = default;
+TracingServiceState::Producer& TracingServiceState::Producer::operator=(
+    TracingServiceState::Producer&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool TracingServiceState::Producer::operator==(
+    const TracingServiceState::Producer& other) const {
+  return (id_ == other.id_) && (name_ == other.name_) && (uid_ == other.uid_);
+}
+#pragma GCC diagnostic pop
+
+void TracingServiceState::Producer::FromProto(
+    const perfetto::protos::TracingServiceState_Producer& proto) {
+  static_assert(sizeof(id_) == sizeof(proto.id()), "size mismatch");
+  id_ = static_cast<decltype(id_)>(proto.id());
+
+  static_assert(sizeof(name_) == sizeof(proto.name()), "size mismatch");
+  name_ = static_cast<decltype(name_)>(proto.name());
+
+  static_assert(sizeof(uid_) == sizeof(proto.uid()), "size mismatch");
+  uid_ = static_cast<decltype(uid_)>(proto.uid());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void TracingServiceState::Producer::ToProto(
+    perfetto::protos::TracingServiceState_Producer* proto) const {
+  proto->Clear();
+
+  static_assert(sizeof(id_) == sizeof(proto->id()), "size mismatch");
+  proto->set_id(static_cast<decltype(proto->id())>(id_));
+
+  static_assert(sizeof(name_) == sizeof(proto->name()), "size mismatch");
+  proto->set_name(static_cast<decltype(proto->name())>(name_));
+
+  static_assert(sizeof(uid_) == sizeof(proto->uid()), "size mismatch");
+  proto->set_uid(static_cast<decltype(proto->uid())>(uid_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+TracingServiceState::DataSource::DataSource() = default;
+TracingServiceState::DataSource::~DataSource() = default;
+TracingServiceState::DataSource::DataSource(
+    const TracingServiceState::DataSource&) = default;
+TracingServiceState::DataSource& TracingServiceState::DataSource::operator=(
+    const TracingServiceState::DataSource&) = default;
+TracingServiceState::DataSource::DataSource(
+    TracingServiceState::DataSource&&) noexcept = default;
+TracingServiceState::DataSource& TracingServiceState::DataSource::operator=(
+    TracingServiceState::DataSource&&) = default;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+bool TracingServiceState::DataSource::operator==(
+    const TracingServiceState::DataSource& other) const {
+  return (descriptor_ == other.descriptor_) &&
+         (producer_id_ == other.producer_id_);
+}
+#pragma GCC diagnostic pop
+
+void TracingServiceState::DataSource::FromProto(
+    const perfetto::protos::TracingServiceState_DataSource& proto) {
+  descriptor_.FromProto(proto.descriptor());
+
+  static_assert(sizeof(producer_id_) == sizeof(proto.producer_id()),
+                "size mismatch");
+  producer_id_ = static_cast<decltype(producer_id_)>(proto.producer_id());
+  unknown_fields_ = proto.unknown_fields();
+}
+
+void TracingServiceState::DataSource::ToProto(
+    perfetto::protos::TracingServiceState_DataSource* proto) const {
+  proto->Clear();
+
+  descriptor_.ToProto(proto->mutable_descriptor());
+
+  static_assert(sizeof(producer_id_) == sizeof(proto->producer_id()),
+                "size mismatch");
+  proto->set_producer_id(
+      static_cast<decltype(proto->producer_id())>(producer_id_));
+  *(proto->mutable_unknown_fields()) = unknown_fields_;
+}
+
+}  // namespace perfetto
diff --git a/src/tracing/core/virtual_destructors.cc b/src/tracing/core/virtual_destructors.cc
index 75fc806..aa73453 100644
--- a/src/tracing/core/virtual_destructors.cc
+++ b/src/tracing/core/virtual_destructors.cc
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/tracing/core/consumer.h"
-#include "perfetto/ext/tracing/core/producer.h"
-#include "perfetto/ext/tracing/core/shared_memory.h"
-#include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
+#include "perfetto/tracing/core/consumer.h"
+#include "perfetto/tracing/core/producer.h"
+#include "perfetto/tracing/core/shared_memory.h"
+#include "perfetto/tracing/core/shared_memory_arbiter.h"
+#include "perfetto/tracing/core/tracing_service.h"
 
 // This translation unit contains the definitions for the destructor of pure
 // virtual interfaces for the current build target. The alternative would be
diff --git a/src/tracing/data_source.cc b/src/tracing/data_source.cc
deleted file mode 100644
index 418ba43..0000000
--- a/src/tracing/data_source.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/tracing/data_source.h"
-
-namespace perfetto {
-
-DataSourceBase::StopArgs::~StopArgs() = default;
-DataSourceBase::~DataSourceBase() = default;
-void DataSourceBase::OnSetup(const SetupArgs&) {}
-void DataSourceBase::OnStart(const StartArgs&) {}
-void DataSourceBase::OnStop(const StopArgs&) {}
-
-}  // namespace perfetto
diff --git a/src/tracing/internal/in_process_tracing_backend.cc b/src/tracing/internal/in_process_tracing_backend.cc
deleted file mode 100644
index 7f6d350..0000000
--- a/src/tracing/internal/in_process_tracing_backend.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/tracing/internal/in_process_tracing_backend.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/paged_memory.h"
-#include "perfetto/ext/tracing/core/shared_memory.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
-
-// TODO(primiano): When the in-process backend is used, we should never end up
-// in a situation where the thread where the TracingService and Producer live
-// writes a packet and hence can get into the GetNewChunk() stall.
-// This would happen only if the API client code calls Trace() from one of the
-// callbacks it receives (e.g. OnStart(), OnStop()). We should either cause a
-// hard crash or ignore traces from that thread if that happens, because it
-// will deadlock (the Service will never free up the SMB because won't ever get
-// to run the task).
-
-namespace perfetto {
-namespace internal {
-
-namespace {
-
-class InProcessShm : public SharedMemory {
- public:
-  explicit InProcessShm(size_t size);
-  ~InProcessShm() override;
-  void* start() const override;
-  size_t size() const override;
-
- private:
-  base::PagedMemory mem_;
-};
-
-class InProcessShmFactory : public SharedMemory::Factory {
- public:
-  ~InProcessShmFactory() override;
-  std::unique_ptr<SharedMemory> CreateSharedMemory(size_t) override;
-};
-
-InProcessShm::~InProcessShm() = default;
-
-InProcessShm::InProcessShm(size_t size)
-    : mem_(base::PagedMemory::Allocate(size)) {}
-
-void* InProcessShm::start() const {
-  return mem_.Get();
-}
-
-size_t InProcessShm::size() const {
-  return mem_.size();
-}
-
-InProcessShmFactory::~InProcessShmFactory() = default;
-std::unique_ptr<SharedMemory> InProcessShmFactory::CreateSharedMemory(
-    size_t size) {
-  return std::unique_ptr<SharedMemory>(new InProcessShm(size));
-}
-
-}  // namespace
-
-// static
-InProcessTracingBackend* InProcessTracingBackend::GetInstance() {
-  static auto* instance = new InProcessTracingBackend();
-  return instance;
-}
-
-InProcessTracingBackend::InProcessTracingBackend() {}
-
-std::unique_ptr<ProducerEndpoint> InProcessTracingBackend::ConnectProducer(
-    const ConnectProducerArgs& args) {
-  PERFETTO_DCHECK(args.task_runner->RunsTasksOnCurrentThread());
-
-  // This should never happen as we can have at most one in-process backend.
-  if (service_)
-    PERFETTO_FATAL("InProcessTracingBackend initialized twice");
-
-  return GetOrCreateService(args.task_runner)
-      ->ConnectProducer(args.producer, /*uid=*/0, args.producer_name,
-                        args.shmem_size_hint_bytes,
-                        /*in_process=*/true,
-                        TracingService::ProducerSMBScrapingMode::kEnabled,
-                        args.shmem_page_size_hint_bytes);
-}
-
-std::unique_ptr<ConsumerEndpoint> InProcessTracingBackend::ConnectConsumer(
-    const ConnectConsumerArgs& args) {
-  return GetOrCreateService(args.task_runner)
-      ->ConnectConsumer(args.consumer, /*uid=*/0);
-}
-
-TracingService* InProcessTracingBackend::GetOrCreateService(
-    base::TaskRunner* task_runner) {
-  if (!service_) {
-    std::unique_ptr<InProcessShmFactory> shm(new InProcessShmFactory());
-    service_ = TracingService::CreateInstance(std::move(shm), task_runner);
-    service_->SetSMBScrapingEnabled(true);
-  }
-  return service_.get();
-}
-
-}  // namespace internal
-}  // namespace perfetto
diff --git a/src/tracing/internal/in_process_tracing_backend.h b/src/tracing/internal/in_process_tracing_backend.h
deleted file mode 100644
index 8d07ae7..0000000
--- a/src/tracing/internal/in_process_tracing_backend.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACING_INTERNAL_IN_PROCESS_TRACING_BACKEND_H_
-#define SRC_TRACING_INTERNAL_IN_PROCESS_TRACING_BACKEND_H_
-
-#include "perfetto/tracing/tracing_backend.h"
-
-namespace perfetto {
-
-namespace base {
-class TaskRunner;
-}
-
-class Producer;
-class TracingService;
-
-namespace internal {
-
-// A built-in implementation of TracingBackend that creates a tracing service
-// instance in-process. Instantiated when the embedder calls
-// Tracing::Initialize(kInProcessBackend). Solves most in-app-only tracing
-// use-cases.
-class InProcessTracingBackend : public TracingBackend {
- public:
-  static InProcessTracingBackend* GetInstance();
-
-  // TracingBackend implementation.
-  std::unique_ptr<ProducerEndpoint> ConnectProducer(
-      const ConnectProducerArgs&) override;
-  std::unique_ptr<ConsumerEndpoint> ConnectConsumer(
-      const ConnectConsumerArgs&) override;
-
- private:
-  InProcessTracingBackend();
-  TracingService* GetOrCreateService(base::TaskRunner*);
-
-  std::unique_ptr<TracingService> service_;
-};
-
-}  // namespace internal
-}  // namespace perfetto
-
-#endif  // SRC_TRACING_INTERNAL_IN_PROCESS_TRACING_BACKEND_H_
diff --git a/src/tracing/internal/system_tracing_backend.cc b/src/tracing/internal/system_tracing_backend.cc
deleted file mode 100644
index d8e89f2..0000000
--- a/src/tracing/internal/system_tracing_backend.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/tracing/internal/system_tracing_backend.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/base/task_runner.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
-#include "perfetto/ext/tracing/ipc/default_socket.h"
-#include "perfetto/ext/tracing/ipc/producer_ipc_client.h"
-
-namespace perfetto {
-namespace internal {
-
-// static
-SystemTracingBackend* SystemTracingBackend::GetInstance() {
-  static auto* instance = new SystemTracingBackend();
-  return instance;
-}
-
-SystemTracingBackend::SystemTracingBackend() {}
-
-std::unique_ptr<ProducerEndpoint> SystemTracingBackend::ConnectProducer(
-    const ConnectProducerArgs& args) {
-  PERFETTO_DCHECK(args.task_runner->RunsTasksOnCurrentThread());
-
-  auto endpoint = ProducerIPCClient::Connect(
-      GetProducerSocket(), args.producer, args.producer_name, args.task_runner,
-      TracingService::ProducerSMBScrapingMode::kEnabled,
-      args.shmem_size_hint_bytes, args.shmem_page_size_hint_bytes);
-  PERFETTO_CHECK(endpoint);
-  return endpoint;
-}
-
-std::unique_ptr<ConsumerEndpoint> SystemTracingBackend::ConnectConsumer(
-    const ConnectConsumerArgs&) {
-  PERFETTO_FATAL(
-      "Trace session creation is not supported yet when using the system "
-      "tracing backend. Use the perfetto cmdline client instead to start "
-      "system-wide tracing sessions");
-}
-
-}  // namespace internal
-}  // namespace perfetto
diff --git a/src/tracing/internal/system_tracing_backend.h b/src/tracing/internal/system_tracing_backend.h
deleted file mode 100644
index ca70242..0000000
--- a/src/tracing/internal/system_tracing_backend.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACING_INTERNAL_SYSTEM_TRACING_BACKEND_H_
-#define SRC_TRACING_INTERNAL_SYSTEM_TRACING_BACKEND_H_
-
-#include "perfetto/tracing/tracing_backend.h"
-
-namespace perfetto {
-
-namespace base {
-class TaskRunner;
-}
-
-class Producer;
-
-// A built-in implementation of TracingBackend that connects to the system
-// tracing daemon (traced) via a UNIX socket using the perfetto built-in
-// proto-based IPC mechanism. Instantiated when the embedder calls
-// Tracing::Initialize(kSystemBackend). It allows to get app-traces fused
-// together with system traces, useful to correlate on the timeline system
-// events (e.g. scheduling slices from the kernel) with in-app events.
-namespace internal {
-class SystemTracingBackend : public TracingBackend {
- public:
-  static SystemTracingBackend* GetInstance();
-
-  // TracingBackend implementation.
-  std::unique_ptr<ProducerEndpoint> ConnectProducer(
-      const ConnectProducerArgs&) override;
-  std::unique_ptr<ConsumerEndpoint> ConnectConsumer(
-      const ConnectConsumerArgs&) override;
-
- private:
-  SystemTracingBackend();
-};
-
-}  // namespace internal
-}  // namespace perfetto
-
-#endif  // SRC_TRACING_INTERNAL_SYSTEM_TRACING_BACKEND_H_
diff --git a/src/tracing/internal/tracing_muxer_impl.cc b/src/tracing/internal/tracing_muxer_impl.cc
deleted file mode 100644
index 1ce6f93..0000000
--- a/src/tracing/internal/tracing_muxer_impl.cc
+++ /dev/null
@@ -1,958 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/tracing/internal/tracing_muxer_impl.h"
-
-#include <algorithm>
-#include <atomic>
-#include <mutex>
-#include <vector>
-
-#include "perfetto/base/build_config.h"
-#include "perfetto/base/logging.h"
-#include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/hash.h"
-#include "perfetto/ext/base/thread_checker.h"
-#include "perfetto/ext/base/waitable_event.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
-#include "perfetto/tracing/buffer_exhausted_policy.h"
-#include "perfetto/tracing/core/data_source_config.h"
-#include "perfetto/tracing/data_source.h"
-#include "perfetto/tracing/internal/data_source_internal.h"
-#include "perfetto/tracing/trace_writer_base.h"
-#include "perfetto/tracing/tracing.h"
-#include "perfetto/tracing/tracing_backend.h"
-#include "protos/perfetto/config/trace_config.pb.h"
-#include "src/tracing/internal/in_process_tracing_backend.h"
-#include "src/tracing/internal/system_tracing_backend.h"
-
-namespace perfetto {
-namespace internal {
-
-namespace {
-
-class StopArgsImpl : public DataSourceBase::StopArgs {
- public:
-  std::function<void()> HandleStopAsynchronously() const override {
-    auto closure = std::move(async_stop_closure);
-    async_stop_closure = std::function<void()>();
-    return closure;
-  }
-
-  mutable std::function<void()> async_stop_closure;
-};
-
-uint64_t ComputeConfigHash(const DataSourceConfig& config) {
-  base::Hash hasher;
-  perfetto::protos::DataSourceConfig config_proto;
-  config.ToProto(&config_proto);
-  std::string config_bytes;
-  bool serialized = config_proto.SerializeToString(&config_bytes);
-  PERFETTO_DCHECK(serialized);
-  hasher.Update(&config_bytes[0], config_bytes.size());
-  return hasher.digest();
-}
-
-}  // namespace
-
-// ----- Begin of TracingMuxerImpl::ProducerImpl
-TracingMuxerImpl::ProducerImpl::ProducerImpl(TracingMuxerImpl* muxer,
-                                             TracingBackendId backend_id)
-    : muxer_(muxer), backend_id_(backend_id) {}
-TracingMuxerImpl::ProducerImpl::~ProducerImpl() = default;
-
-void TracingMuxerImpl::ProducerImpl::Initialize(
-    std::unique_ptr<ProducerEndpoint> endpoint) {
-  service_ = std::move(endpoint);
-}
-
-void TracingMuxerImpl::ProducerImpl::OnConnect() {
-  PERFETTO_DLOG("Producer connected");
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  PERFETTO_DCHECK(!connected_);
-  connected_ = true;
-  muxer_->UpdateDataSourcesOnAllBackends();
-}
-
-void TracingMuxerImpl::ProducerImpl::OnDisconnect() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  connected_ = false;
-  // TODO: handle more graceful.
-  PERFETTO_ELOG("Cannot connect to traced. Is it running?");
-}
-
-void TracingMuxerImpl::ProducerImpl::OnTracingSetup() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-}
-
-void TracingMuxerImpl::ProducerImpl::SetupDataSource(
-    DataSourceInstanceID id,
-    const DataSourceConfig& cfg) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  muxer_->SetupDataSource(backend_id_, id, cfg);
-}
-
-void TracingMuxerImpl::ProducerImpl::StartDataSource(DataSourceInstanceID id,
-                                                     const DataSourceConfig&) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  muxer_->StartDataSource(backend_id_, id);
-  service_->NotifyDataSourceStarted(id);
-}
-
-void TracingMuxerImpl::ProducerImpl::StopDataSource(DataSourceInstanceID id) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  muxer_->StopDataSource_AsyncBegin(backend_id_, id);
-}
-
-void TracingMuxerImpl::ProducerImpl::Flush(FlushRequestID flush_id,
-                                           const DataSourceInstanceID*,
-                                           size_t) {
-  // Flush is not plumbed for now, we just ack straight away.
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  service_->NotifyFlushComplete(flush_id);
-}
-
-void TracingMuxerImpl::ProducerImpl::ClearIncrementalState(
-    const DataSourceInstanceID*,
-    size_t) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  // TODO(skyostil): Mark each affected data source's incremental state as
-  // needing to be cleared.
-}
-// ----- End of TracingMuxerImpl::ProducerImpl methods.
-
-// ----- Begin of TracingMuxerImpl::ConsumerImpl
-TracingMuxerImpl::ConsumerImpl::ConsumerImpl(TracingMuxerImpl* muxer,
-                                             TracingBackendId backend_id,
-                                             TracingSessionGlobalID session_id)
-    : muxer_(muxer), backend_id_(backend_id), session_id_(session_id) {}
-
-TracingMuxerImpl::ConsumerImpl::~ConsumerImpl() = default;
-
-void TracingMuxerImpl::ConsumerImpl::Initialize(
-    std::unique_ptr<ConsumerEndpoint> endpoint) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  service_ = std::move(endpoint);
-  // Observe data source instance events so we get notified when tracing starts.
-  service_->ObserveEvents(ConsumerEndpoint::kDataSourceInstances);
-}
-
-void TracingMuxerImpl::ConsumerImpl::OnConnect() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  PERFETTO_DCHECK(!connected_);
-  connected_ = true;
-
-  // If the API client configured and started tracing before we connected,
-  // tell the backend about it now.
-  if (trace_config_) {
-    muxer_->SetupTracingSession(session_id_, trace_config_);
-    if (start_pending_)
-      muxer_->StartTracingSession(session_id_);
-    if (stop_pending_)
-      muxer_->StopTracingSession(session_id_);
-  }
-}
-
-void TracingMuxerImpl::ConsumerImpl::OnDisconnect() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  // It shouldn't be necessary to call StopTracingSession. If we get this call
-  // it means that the service did shutdown before us, so there is no point
-  // trying it to ask it to stop the session. We should just remember to cleanup
-  // the consumer vector.
-  connected_ = false;
-
-  // TODO notify the client somehow.
-
-  // Notify the muxer that it is safe to destroy |this|. This is needed because
-  // the ConsumerEndpoint stored in |service_| requires that |this| be safe to
-  // access until OnDisconnect() is called.
-  muxer_->OnConsumerDisconnected(this);
-}
-
-void TracingMuxerImpl::ConsumerImpl::Disconnect() {
-  // This is weird and deserves a comment.
-  //
-  // When we called the ConnectConsumer method on the service it returns
-  // us a ConsumerEndpoint which we stored in |service_|, however this
-  // ConsumerEndpoint holds a pointer to the ConsumerImpl pointed to by
-  // |this|. Part of the API contract to TracingService::ConnectConsumer is that
-  // the ConsumerImpl pointer has to be valid until the
-  // ConsumerImpl::OnDisconnect method is called. Therefore we reset the
-  // ConsumerEndpoint |service_|. Eventually this will call
-  // ConsumerImpl::OnDisconnect and we will inform the muxer it is safe to
-  // call the destructor of |this|.
-  service_.reset();
-}
-
-void TracingMuxerImpl::ConsumerImpl::OnTracingDisabled() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  PERFETTO_DCHECK(!stopped_);
-  stopped_ = true;
-  // If we're still waiting for the start event, fire it now. This may happen if
-  // there are no active data sources in the session.
-  NotifyStartComplete();
-  NotifyStopComplete();
-}
-
-void TracingMuxerImpl::ConsumerImpl::NotifyStartComplete() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  if (blocking_start_complete_callback_) {
-    muxer_->task_runner_->PostTask(
-        std::move(blocking_start_complete_callback_));
-    blocking_start_complete_callback_ = nullptr;
-  }
-}
-
-void TracingMuxerImpl::ConsumerImpl::NotifyStopComplete() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  if (stop_complete_callback_) {
-    muxer_->task_runner_->PostTask(std::move(stop_complete_callback_));
-    stop_complete_callback_ = nullptr;
-  }
-  if (blocking_stop_complete_callback_) {
-    muxer_->task_runner_->PostTask(std::move(blocking_stop_complete_callback_));
-    blocking_stop_complete_callback_ = nullptr;
-  }
-}
-
-void TracingMuxerImpl::ConsumerImpl::OnTraceData(
-    std::vector<TracePacket> packets,
-    bool has_more) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  if (!read_trace_callback_)
-    return;
-
-  size_t capacity = 0;
-  for (const auto& packet : packets) {
-    // 16 is an over-estimation of the proto preamble size
-    capacity += packet.size() + 16;
-  }
-
-  // The shared_ptr is to avoid making a copy of the buffer when PostTask-ing.
-  std::shared_ptr<std::vector<char>> buf(new std::vector<char>());
-  buf->reserve(capacity);
-  for (auto& packet : packets) {
-    char* start;
-    size_t size;
-    std::tie(start, size) = packet.GetProtoPreamble();
-    buf->insert(buf->end(), start, start + size);
-    for (auto& slice : packet.slices()) {
-      const auto* slice_data = reinterpret_cast<const char*>(slice.start);
-      buf->insert(buf->end(), slice_data, slice_data + slice.size);
-    }
-  }
-
-  auto callback = read_trace_callback_;
-  muxer_->task_runner_->PostTask([callback, buf, has_more] {
-    TracingSession::ReadTraceCallbackArgs callback_arg{};
-    callback_arg.data = &(*buf)[0];
-    callback_arg.size = buf->size();
-    callback_arg.has_more = has_more;
-    callback(callback_arg);
-  });
-
-  if (!has_more)
-    read_trace_callback_ = nullptr;
-}
-
-void TracingMuxerImpl::ConsumerImpl::OnObservableEvents(
-    const ObservableEvents& events) {
-  if (events.instance_state_changes_size()) {
-    for (const auto& state_change : events.instance_state_changes()) {
-      DataSourceHandle handle{state_change.producer_name(),
-                              state_change.data_source_name()};
-      data_source_states_[handle] =
-          state_change.state() ==
-          ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STARTED;
-    }
-    // Data sources are first reported as being stopped before starting, so once
-    // all the data sources we know about have started we can declare tracing
-    // begun.
-    if (blocking_start_complete_callback_) {
-      bool all_data_sources_started = std::all_of(
-          data_source_states_.cbegin(), data_source_states_.cend(),
-          [](std::pair<DataSourceHandle, bool> state) { return state.second; });
-      if (all_data_sources_started)
-        NotifyStartComplete();
-    }
-  }
-}
-
-// The callbacks below are not used.
-void TracingMuxerImpl::ConsumerImpl::OnDetach(bool) {}
-void TracingMuxerImpl::ConsumerImpl::OnAttach(bool, const TraceConfig&) {}
-void TracingMuxerImpl::ConsumerImpl::OnTraceStats(bool, const TraceStats&) {}
-// ----- End of TracingMuxerImpl::ConsumerImpl
-
-// ----- Begin of TracingMuxerImpl::TracingSessionImpl
-
-// TracingSessionImpl is the RAII object returned to API clients when they
-// invoke Tracing::CreateTracingSession. They use it for starting/stopping
-// tracing.
-
-TracingMuxerImpl::TracingSessionImpl::TracingSessionImpl(
-    TracingMuxerImpl* muxer,
-    TracingSessionGlobalID session_id)
-    : muxer_(muxer), session_id_(session_id) {}
-
-// Can be destroyed from any thread.
-TracingMuxerImpl::TracingSessionImpl::~TracingSessionImpl() {
-  auto* muxer = muxer_;
-  auto session_id = session_id_;
-  muxer->task_runner_->PostTask(
-      [muxer, session_id] { muxer->DestroyTracingSession(session_id); });
-}
-
-// Can be called from any thread.
-void TracingMuxerImpl::TracingSessionImpl::Setup(const TraceConfig& cfg,
-                                                 int fd) {
-  auto* muxer = muxer_;
-  auto session_id = session_id_;
-  std::shared_ptr<TraceConfig> trace_config(new TraceConfig(cfg));
-  if (fd >= 0) {
-    trace_config->set_write_into_file(true);
-    fd = dup(fd);
-  }
-  muxer->task_runner_->PostTask([muxer, session_id, trace_config, fd] {
-    muxer->SetupTracingSession(session_id, trace_config, base::ScopedFile(fd));
-  });
-}
-
-// Can be called from any thread.
-void TracingMuxerImpl::TracingSessionImpl::Start() {
-  auto* muxer = muxer_;
-  auto session_id = session_id_;
-  muxer->task_runner_->PostTask(
-      [muxer, session_id] { muxer->StartTracingSession(session_id); });
-}
-
-// Can be called from any thread except the service thread.
-void TracingMuxerImpl::TracingSessionImpl::StartBlocking() {
-  PERFETTO_DCHECK(!muxer_->task_runner_->RunsTasksOnCurrentThread());
-  auto* muxer = muxer_;
-  auto session_id = session_id_;
-  base::WaitableEvent tracing_started;
-  muxer->task_runner_->PostTask([muxer, session_id, &tracing_started] {
-    auto* consumer = muxer->FindConsumer(session_id);
-    PERFETTO_DCHECK(!consumer->blocking_start_complete_callback_);
-    consumer->blocking_start_complete_callback_ = [&] {
-      tracing_started.Notify();
-    };
-    muxer->StartTracingSession(session_id);
-  });
-  tracing_started.Wait();
-}
-
-// Can be called from any thread.
-void TracingMuxerImpl::TracingSessionImpl::Stop() {
-  auto* muxer = muxer_;
-  auto session_id = session_id_;
-  muxer->task_runner_->PostTask(
-      [muxer, session_id] { muxer->StopTracingSession(session_id); });
-}
-
-// Can be called from any thread except the service thread.
-void TracingMuxerImpl::TracingSessionImpl::StopBlocking() {
-  PERFETTO_DCHECK(!muxer_->task_runner_->RunsTasksOnCurrentThread());
-  auto* muxer = muxer_;
-  auto session_id = session_id_;
-  base::WaitableEvent tracing_stopped;
-  muxer->task_runner_->PostTask([muxer, session_id, &tracing_stopped] {
-    auto* consumer = muxer->FindConsumer(session_id);
-    PERFETTO_DCHECK(!consumer->blocking_stop_complete_callback_);
-    consumer->blocking_stop_complete_callback_ = [&] {
-      tracing_stopped.Notify();
-    };
-    muxer->StopTracingSession(session_id);
-  });
-  tracing_stopped.Wait();
-}
-
-// Can be called from any thread.
-void TracingMuxerImpl::TracingSessionImpl::ReadTrace(ReadTraceCallback cb) {
-  auto* muxer = muxer_;
-  auto session_id = session_id_;
-  muxer->task_runner_->PostTask([muxer, session_id, cb] {
-    muxer->ReadTracingSessionData(session_id, std::move(cb));
-  });
-}
-
-// Can be called from any thread.
-void TracingMuxerImpl::TracingSessionImpl::SetOnStopCallback(
-    std::function<void()> cb) {
-  auto* muxer = muxer_;
-  auto session_id = session_id_;
-  muxer->task_runner_->PostTask([muxer, session_id, cb] {
-    auto* consumer = muxer->FindConsumer(session_id);
-    consumer->stop_complete_callback_ = cb;
-  });
-}
-// ----- End of TracingMuxerImpl::TracingSessionImpl
-
-// static
-TracingMuxer* TracingMuxer::instance_ = nullptr;
-
-// This is called by perfetto::Tracing::Initialize().
-// Can be called on any thread. Typically, but not necessarily, that will be
-// the embedder's main thread.
-TracingMuxerImpl::TracingMuxerImpl(const TracingInitArgs& args)
-    : TracingMuxer(args.platform ? args.platform
-                                 : Platform::GetDefaultPlatform()) {
-  PERFETTO_DETACH_FROM_THREAD(thread_checker_);
-
-  // Create the thread where muxer, producers and service will live.
-  task_runner_ = platform_->CreateTaskRunner({});
-
-  // Run the initializer on that thread.
-  task_runner_->PostTask([this, args] { Initialize(args); });
-}
-
-void TracingMuxerImpl::Initialize(const TracingInitArgs& args) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);  // Rebind the thread checker.
-
-  auto add_backend = [this, &args](TracingBackend* backend, BackendType type) {
-    TracingBackendId backend_id = backends_.size();
-    backends_.emplace_back();
-    RegisteredBackend& rb = backends_.back();
-    rb.backend = backend;
-    rb.id = backend_id;
-    rb.type = type;
-    rb.producer.reset(new ProducerImpl(this, backend_id));
-    TracingBackend::ConnectProducerArgs conn_args;
-    conn_args.producer = rb.producer.get();
-    conn_args.producer_name = platform_->GetCurrentProcessName();
-    conn_args.task_runner = task_runner_.get();
-    conn_args.shmem_size_hint_bytes = args.shmem_size_hint_kb * 1024;
-    conn_args.shmem_page_size_hint_bytes = args.shmem_page_size_hint_kb * 1024;
-    rb.producer->Initialize(rb.backend->ConnectProducer(conn_args));
-  };
-
-  if (args.backends & kSystemBackend) {
-#if (PERFETTO_BUILDFLAG(PERFETTO_IPC))
-    add_backend(SystemTracingBackend::GetInstance(), kSystemBackend);
-#else
-    PERFETTO_ELOG("System backend not supporteed in the current configuration");
-#endif
-  }
-
-  if (args.backends & kInProcessBackend)
-    add_backend(InProcessTracingBackend::GetInstance(), kInProcessBackend);
-
-  if (args.backends & kCustomBackend) {
-    PERFETTO_CHECK(args.custom_backend);
-    add_backend(args.custom_backend, kCustomBackend);
-  }
-
-  if (args.backends & ~(kSystemBackend | kInProcessBackend | kCustomBackend)) {
-    PERFETTO_FATAL("Unsupported tracing backend type");
-  }
-}
-
-// Can be called from any thread (but not concurrently).
-bool TracingMuxerImpl::RegisterDataSource(
-    const DataSourceDescriptor& descriptor,
-    DataSourceFactory factory,
-    DataSourceStaticState* static_state) {
-  // Ignore repeated registrations.
-  if (static_state->index != kMaxDataSources)
-    return true;
-
-  static std::atomic<uint32_t> last_id{};
-  uint32_t new_index = last_id++;
-  if (new_index >= kMaxDataSources) {
-    PERFETTO_DLOG(
-        "RegisterDataSource failed: too many data sources already registered");
-    return false;
-  }
-
-  // Initialize the static state.
-  static_assert(sizeof(static_state->instances[0]) >= sizeof(DataSourceState),
-                "instances[] size mismatch");
-  for (size_t i = 0; i < static_state->instances.size(); i++)
-    new (&static_state->instances[i]) DataSourceState{};
-
-  static_state->index = new_index;
-
-  task_runner_->PostTask([this, descriptor, factory, static_state] {
-    data_sources_.emplace_back();
-    RegisteredDataSource& rds = data_sources_.back();
-    rds.descriptor = descriptor;
-    rds.factory = factory;
-    rds.static_state = static_state;
-    UpdateDataSourcesOnAllBackends();
-  });
-  return true;
-}
-
-// Called by the service of one of the backends.
-void TracingMuxerImpl::SetupDataSource(TracingBackendId backend_id,
-                                       DataSourceInstanceID instance_id,
-                                       const DataSourceConfig& cfg) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  PERFETTO_DLOG("Setting up data source %" PRIu64 " %s", instance_id,
-                cfg.name().c_str());
-  uint64_t config_hash = ComputeConfigHash(cfg);
-
-  for (const auto& rds : data_sources_) {
-    if (rds.descriptor.name() != cfg.name())
-      continue;
-    DataSourceStaticState& static_state = *rds.static_state;
-
-    // If this data source is already active for this exact config, don't start
-    // another instance. This happens when we have several data sources with the
-    // same name, in which case the service sends one SetupDataSource event for
-    // each one. Since we can't map which event maps to which data source, we
-    // ensure each event only starts one data source instance.
-    // TODO(skyostil): Register a unique id with each data source to the service
-    // to disambiguate.
-    bool active_for_config = false;
-    for (uint32_t i = 0; i < kMaxDataSourceInstances; i++) {
-      if (!static_state.TryGet(i))
-        continue;
-      auto* internal_state =
-          reinterpret_cast<DataSourceState*>(&static_state.instances[i]);
-      if (internal_state->backend_id == backend_id &&
-          internal_state->config_hash == config_hash) {
-        active_for_config = true;
-        break;
-      }
-    }
-    if (active_for_config) {
-      PERFETTO_DLOG(
-          "Data source %s is already active with this config, skipping",
-          cfg.name().c_str());
-      continue;
-    }
-
-    for (uint32_t i = 0; i < kMaxDataSourceInstances; i++) {
-      // Find a free slot.
-      if (static_state.TryGet(i))
-        continue;
-
-      auto* internal_state =
-          reinterpret_cast<DataSourceState*>(&static_state.instances[i]);
-      std::lock_guard<std::recursive_mutex> guard(internal_state->lock);
-      static_assert(
-          std::is_same<decltype(internal_state->data_source_instance_id),
-                       DataSourceInstanceID>::value,
-          "data_source_instance_id type mismatch");
-      internal_state->backend_id = backend_id;
-      internal_state->data_source_instance_id = instance_id;
-      internal_state->buffer_id =
-          static_cast<internal::BufferId>(cfg.target_buffer());
-      internal_state->config_hash = config_hash;
-      internal_state->data_source = rds.factory();
-
-      // This must be made at the end. See matching acquire-load in
-      // DataSource::Trace().
-      static_state.valid_instances.fetch_or(1 << i, std::memory_order_release);
-
-      DataSourceBase::SetupArgs setup_args;
-      setup_args.config = &cfg;
-      setup_args.internal_instance_index = i;
-      internal_state->data_source->OnSetup(setup_args);
-      return;
-    }
-    PERFETTO_ELOG(
-        "Maximum number of data source instances exhausted. "
-        "Dropping data source %" PRIu64,
-        instance_id);
-    break;
-  }
-}
-
-// Called by the service of one of the backends.
-void TracingMuxerImpl::StartDataSource(TracingBackendId backend_id,
-                                       DataSourceInstanceID instance_id) {
-  PERFETTO_DLOG("Starting data source %" PRIu64, instance_id);
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-
-  auto ds = FindDataSource(backend_id, instance_id);
-  if (!ds) {
-    PERFETTO_ELOG("Could not find data source to start");
-    return;
-  }
-
-  DataSourceBase::StartArgs start_args{};
-  start_args.internal_instance_index = ds.instance_idx;
-
-  std::lock_guard<std::recursive_mutex> guard(ds.internal_state->lock);
-  ds.internal_state->trace_lambda_enabled = true;
-  ds.internal_state->data_source->OnStart(start_args);
-}
-
-// Called by the service of one of the backends.
-void TracingMuxerImpl::StopDataSource_AsyncBegin(
-    TracingBackendId backend_id,
-    DataSourceInstanceID instance_id) {
-  PERFETTO_DLOG("Stopping data source %" PRIu64, instance_id);
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-
-  auto ds = FindDataSource(backend_id, instance_id);
-  if (!ds) {
-    PERFETTO_ELOG("Could not find data source to stop");
-    return;
-  }
-
-  StopArgsImpl stop_args{};
-  stop_args.internal_instance_index = ds.instance_idx;
-  stop_args.async_stop_closure = [this, backend_id, instance_id] {
-    // TracingMuxerImpl is long lived, capturing |this| is okay.
-    // The notification closure can be moved out of the StopArgs by the
-    // embedder to handle stop asynchronously. The embedder might then
-    // call the closure on a different thread than the current one, hence
-    // this nested PostTask().
-    task_runner_->PostTask([this, backend_id, instance_id] {
-      StopDataSource_AsyncEnd(backend_id, instance_id);
-    });
-  };
-
-  {
-    std::lock_guard<std::recursive_mutex> guard(ds.internal_state->lock);
-    ds.internal_state->data_source->OnStop(stop_args);
-  }
-
-  // If the embedder hasn't called StopArgs.HandleStopAsynchronously() run the
-  // async closure here. In theory we could avoid the PostTask and call
-  // straight into CompleteDataSourceAsyncStop(). We keep that to reduce
-  // divergencies between the deferred-stop vs non-deferred-stop code paths.
-  if (stop_args.async_stop_closure)
-    std::move(stop_args.async_stop_closure)();
-}
-
-void TracingMuxerImpl::StopDataSource_AsyncEnd(
-    TracingBackendId backend_id,
-    DataSourceInstanceID instance_id) {
-  PERFETTO_DLOG("Ending async stop of data source %" PRIu64, instance_id);
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-
-  auto ds = FindDataSource(backend_id, instance_id);
-  if (!ds) {
-    PERFETTO_ELOG(
-        "Async stop of data source %" PRIu64
-        " failed. This might be due to calling the async_stop_closure twice.",
-        instance_id);
-    return;
-  }
-
-  const uint32_t mask = ~(1 << ds.instance_idx);
-  ds.static_state->valid_instances.fetch_and(mask, std::memory_order_acq_rel);
-
-  // Take the mutex to prevent that the data source is in the middle of
-  // a Trace() execution where it called GetDataSourceLocked() while we
-  // destroy it.
-  {
-    std::lock_guard<std::recursive_mutex> guard(ds.internal_state->lock);
-    ds.internal_state->trace_lambda_enabled = false;
-    ds.internal_state->data_source.reset();
-  }
-
-  // The other fields of internal_state are deliberately *not* cleared.
-  // See races-related comments of DataSource::Trace().
-
-  TracingMuxer::generation_++;
-
-  // |backends_| is append-only, Backend instances are always valid.
-  PERFETTO_CHECK(backend_id < backends_.size());
-  ProducerImpl* producer = backends_[backend_id].producer.get();
-  if (producer && producer->connected_)
-    producer->service_->NotifyDataSourceStopped(instance_id);
-}
-
-void TracingMuxerImpl::DestroyStoppedTraceWritersForCurrentThread() {
-  // Iterate across all possible data source types.
-  auto cur_generation = generation_.load(std::memory_order_acquire);
-  auto* root_tls = GetOrCreateTracingTLS();
-
-  auto destroy_stopped_instances = [](DataSourceThreadLocalState& tls) {
-    // |tls| has a vector of per-data-source-instance thread-local state.
-    DataSourceStaticState* static_state = tls.static_state;
-    if (!static_state)
-      return;  // Slot not used.
-
-    // Iterate across all possible instances for this data source.
-    for (uint32_t inst = 0; inst < kMaxDataSourceInstances; inst++) {
-      DataSourceInstanceThreadLocalState& ds_tls = tls.per_instance[inst];
-      if (!ds_tls.trace_writer)
-        continue;
-
-      DataSourceState* ds_state = static_state->TryGet(inst);
-      if (ds_state && ds_state->backend_id == ds_tls.backend_id &&
-          ds_state->buffer_id == ds_tls.buffer_id) {
-        continue;
-      }
-
-      // The DataSource instance has been destroyed or recycled.
-      ds_tls.Reset();  // Will also destroy the |ds_tls.trace_writer|.
-    }
-  };
-
-  for (size_t ds_idx = 0; ds_idx < kMaxDataSources; ds_idx++) {
-    // |tls| has a vector of per-data-source-instance thread-local state.
-    DataSourceThreadLocalState& tls = root_tls->data_sources_tls[ds_idx];
-    destroy_stopped_instances(tls);
-  }
-  destroy_stopped_instances(root_tls->track_event_tls);
-  root_tls->generation = cur_generation;
-}
-
-// Called both when a new data source is registered or when a new backend
-// connects. In both cases we want to be sure we reflected the data source
-// registrations on the backends.
-void TracingMuxerImpl::UpdateDataSourcesOnAllBackends() {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  for (RegisteredDataSource& rds : data_sources_) {
-    for (RegisteredBackend& backend : backends_) {
-      // We cannot call RegisterDataSource on the backend before it connects.
-      if (!backend.producer->connected_)
-        continue;
-
-      PERFETTO_DCHECK(rds.static_state->index < kMaxDataSourceInstances);
-      if (backend.producer->registered_data_sources_.test(
-              rds.static_state->index))
-        continue;
-
-      rds.descriptor.set_will_notify_on_start(true);
-      rds.descriptor.set_will_notify_on_stop(true);
-      backend.producer->service_->RegisterDataSource(rds.descriptor);
-      backend.producer->registered_data_sources_.set(rds.static_state->index);
-    }
-  }
-}
-
-void TracingMuxerImpl::SetupTracingSession(
-    TracingSessionGlobalID session_id,
-    const std::shared_ptr<TraceConfig>& trace_config,
-    base::ScopedFile trace_fd) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  PERFETTO_CHECK(!trace_fd || trace_config->write_into_file());
-
-  auto* consumer = FindConsumer(session_id);
-  if (!consumer)
-    return;
-
-  consumer->trace_config_ = trace_config;
-  if (trace_fd)
-    consumer->trace_fd_ = std::move(trace_fd);
-
-  if (!consumer->connected_)
-    return;
-
-  // Only used in the deferred start mode.
-  if (trace_config->deferred_start()) {
-    consumer->service_->EnableTracing(*trace_config,
-                                      std::move(consumer->trace_fd_));
-  }
-}
-
-void TracingMuxerImpl::StartTracingSession(TracingSessionGlobalID session_id) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-
-  auto* consumer = FindConsumer(session_id);
-
-  if (!consumer)
-    return;
-
-  if (!consumer->trace_config_) {
-    PERFETTO_ELOG("Must call Setup(config) first");
-    return;
-  }
-
-  if (!consumer->connected_) {
-    consumer->start_pending_ = true;
-    return;
-  }
-
-  consumer->start_pending_ = false;
-  if (consumer->trace_config_->deferred_start()) {
-    consumer->service_->StartTracing();
-  } else {
-    consumer->service_->EnableTracing(*consumer->trace_config_,
-                                      std::move(consumer->trace_fd_));
-  }
-
-  // TODO implement support for the deferred-start + fast-triggering case.
-}
-
-void TracingMuxerImpl::StopTracingSession(TracingSessionGlobalID session_id) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  auto* consumer = FindConsumer(session_id);
-  if (!consumer)
-    return;
-
-  if (consumer->start_pending_) {
-    // If the session hasn't started yet, wait until it does before stopping.
-    consumer->stop_pending_ = true;
-    return;
-  }
-
-  consumer->stop_pending_ = false;
-  if (consumer->stopped_) {
-    // If the session was already stopped (e.g., it failed to start), don't try
-    // stopping again.
-    consumer->NotifyStopComplete();
-  } else if (!consumer->trace_config_) {
-    PERFETTO_ELOG("Must call Setup(config) and Start() first");
-    return;
-  } else {
-    consumer->service_->DisableTracing();
-  }
-
-  consumer->trace_config_.reset();
-}
-
-void TracingMuxerImpl::DestroyTracingSession(
-    TracingSessionGlobalID session_id) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  for (RegisteredBackend& backend : backends_) {
-    // We need to find the consumer (if any) and call Disconnect as we destroy
-    // the tracing session. We can't call Disconnect() inside this for loop
-    // because in the in-process case this will end up to a synchronous call to
-    // OnConsumerDisconnect which will invalidate all the iterators to
-    // |backend.consumers|.
-    ConsumerImpl* consumer = nullptr;
-    for (auto& con : backend.consumers) {
-      if (con->session_id_ == session_id) {
-        consumer = con.get();
-        break;
-      }
-    }
-    if (consumer) {
-      // We broke out of the loop above on the assumption that each backend will
-      // only have a single consumer per session. This DCHECK ensures that
-      // this is the case.
-      PERFETTO_DCHECK(
-          std::count_if(backend.consumers.begin(), backend.consumers.end(),
-                        [session_id](const std::unique_ptr<ConsumerImpl>& con) {
-                          return con->session_id_ == session_id;
-                        }) == 1u);
-      consumer->Disconnect();
-    }
-  }
-}
-
-void TracingMuxerImpl::ReadTracingSessionData(
-    TracingSessionGlobalID session_id,
-    std::function<void(TracingSession::ReadTraceCallbackArgs)> callback) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  auto* consumer = FindConsumer(session_id);
-  if (!consumer)
-    return;
-  PERFETTO_DCHECK(!consumer->read_trace_callback_);
-  consumer->read_trace_callback_ = std::move(callback);
-  consumer->service_->ReadBuffers();
-}
-
-TracingMuxerImpl::ConsumerImpl* TracingMuxerImpl::FindConsumer(
-    TracingSessionGlobalID session_id) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  for (RegisteredBackend& backend : backends_) {
-    for (auto& consumer : backend.consumers) {
-      if (consumer->session_id_ == session_id) {
-        PERFETTO_DCHECK(consumer->service_);
-        return consumer.get();
-      }
-    }
-  }
-  return nullptr;
-}
-
-void TracingMuxerImpl::OnConsumerDisconnected(ConsumerImpl* consumer) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  for (RegisteredBackend& backend : backends_) {
-    auto pred = [consumer](const std::unique_ptr<ConsumerImpl>& con) {
-      return con.get() == consumer;
-    };
-    backend.consumers.erase(std::remove_if(backend.consumers.begin(),
-                                           backend.consumers.end(), pred),
-                            backend.consumers.end());
-  }
-}
-
-TracingMuxerImpl::FindDataSourceRes TracingMuxerImpl::FindDataSource(
-    TracingBackendId backend_id,
-    DataSourceInstanceID instance_id) {
-  PERFETTO_DCHECK_THREAD(thread_checker_);
-  for (const auto& rds : data_sources_) {
-    DataSourceStaticState* static_state = rds.static_state;
-    for (uint32_t i = 0; i < kMaxDataSourceInstances; i++) {
-      auto* internal_state = static_state->TryGet(i);
-      if (internal_state && internal_state->backend_id == backend_id &&
-          internal_state->data_source_instance_id == instance_id) {
-        return FindDataSourceRes(static_state, internal_state, i);
-      }
-    }
-  }
-  return FindDataSourceRes();
-}
-
-// Can be called from any thread.
-std::unique_ptr<TraceWriterBase> TracingMuxerImpl::CreateTraceWriter(
-    DataSourceState* data_source,
-    BufferExhaustedPolicy buffer_exhausted_policy) {
-  ProducerImpl* producer = backends_[data_source->backend_id].producer.get();
-  return producer->service_->CreateTraceWriter(data_source->buffer_id,
-                                               buffer_exhausted_policy);
-}
-
-// This is called via the public API Tracing::NewTrace().
-// Can be called from any thread.
-std::unique_ptr<TracingSession> TracingMuxerImpl::CreateTracingSession(
-    BackendType backend_type) {
-  TracingSessionGlobalID session_id = ++next_tracing_session_id_;
-
-  // |backend_type| can only specify one backend, not an OR-ed mask.
-  PERFETTO_CHECK((backend_type & (backend_type - 1)) == 0);
-
-  // Capturing |this| is fine because the TracingMuxer is a leaky singleton.
-  task_runner_->PostTask([this, backend_type, session_id] {
-    for (RegisteredBackend& backend : backends_) {
-      if (backend_type && backend.type != backend_type)
-        continue;
-
-      backend.consumers.emplace_back(
-          new ConsumerImpl(this, backend.id, session_id));
-      auto& consumer = backend.consumers.back();
-      TracingBackend::ConnectConsumerArgs conn_args;
-      conn_args.consumer = consumer.get();
-      conn_args.task_runner = task_runner_.get();
-      consumer->Initialize(backend.backend->ConnectConsumer(conn_args));
-      return;
-    }
-    PERFETTO_ELOG(
-        "Cannot create tracing session, no tracing backend ready for type=%d",
-        backend_type);
-  });
-
-  return std::unique_ptr<TracingSession>(
-      new TracingSessionImpl(this, session_id));
-}
-
-void TracingMuxerImpl::InitializeInstance(const TracingInitArgs& args) {
-  if (instance_)
-    PERFETTO_FATAL("Tracing already initialized");
-  instance_ = new TracingMuxerImpl(args);
-}
-
-TracingMuxer::~TracingMuxer() = default;
-
-static_assert(std::is_same<internal::BufferId, BufferID>::value,
-              "public's BufferId and tracing/core's BufferID diverged");
-
-}  // namespace internal
-}  // namespace perfetto
diff --git a/src/tracing/internal/tracing_muxer_impl.h b/src/tracing/internal/tracing_muxer_impl.h
deleted file mode 100644
index 1f0f8be..0000000
--- a/src/tracing/internal/tracing_muxer_impl.h
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACING_INTERNAL_TRACING_MUXER_IMPL_H_
-#define SRC_TRACING_INTERNAL_TRACING_MUXER_IMPL_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <array>
-#include <atomic>
-#include <bitset>
-#include <map>
-#include <memory>
-#include <vector>
-
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/thread_checker.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/consumer.h"
-#include "perfetto/ext/tracing/core/producer.h"
-#include "perfetto/tracing/core/data_source_descriptor.h"
-#include "perfetto/tracing/core/trace_config.h"
-#include "perfetto/tracing/internal/basic_types.h"
-#include "perfetto/tracing/internal/tracing_muxer.h"
-#include "perfetto/tracing/tracing.h"
-
-namespace perfetto {
-
-class ConsumerEndpoint;
-class DataSourceBase;
-class DataSourceConfig;
-class ProducerEndpoint;
-class TraceWriterBase;
-class TracingBackend;
-class TracingSession;
-struct TracingInitArgs;
-
-namespace base {
-class TaskRunner;
-}
-
-namespace internal {
-
-struct DataSourceStaticState;
-
-// This class acts as a bridge between the public API and the TracingBackend(s).
-// It exposes a simplified view of the world to the API methods handling all the
-// bookkeeping to map data source instances and trace writers to the various
-// backends. It deals with N data sources, M backends (1 backend == 1 tracing
-// service == 1 producer connection) and T concurrent tracing sessions.
-//
-// Handing data source registration and start/stop flows [producer side]:
-// ----------------------------------------------------------------------
-// 1. The API client subclasses perfetto::DataSource and calls
-//    DataSource::Register<MyDataSource>(). In turn this calls into the
-//    TracingMuxer.
-// 2. The tracing muxer iterates through all the backends (1 backend == 1
-//    service == 1 producer connection) and registers the data source on each
-//    backend.
-// 3. When any (services behind a) backend starts tracing and requests to start
-//    that specific data source, the TracingMuxerImpl constructs a new instance
-//    of MyDataSource and calls the OnStart() method.
-//
-// Controlling trace and retrieving trace data [consumer side]:
-// ------------------------------------------------------------
-// 1. The API client calls Tracing::NewTrace(), returns a RAII TracingSession
-//    object.
-// 2. NewTrace() calls into internal::TracingMuxer(Impl). TracingMuxer
-//    subclasses the TracingSession object (TracingSessionImpl) and returns it.
-// 3. The tracing muxer identifies the backend (according to the args passed to
-//    NewTrace), creates a new Consumer and connects to it.
-// 4. When the API client calls Start()/Stop()/ReadTrace() methods, the
-//    TracingMuxer forwards them to the consumer associated to the
-//    TracingSession. Likewise for callbacks coming from the consumer-side of
-//    the service.
-class TracingMuxerImpl : public TracingMuxer {
- public:
-  // This is different than TracingSessionID because it's global across all
-  // backends. TracingSessionID is global only within the scope of one service.
-  using TracingSessionGlobalID = uint64_t;
-
-  static void InitializeInstance(const TracingInitArgs&);
-
-  // TracingMuxer implementation.
-  bool RegisterDataSource(const DataSourceDescriptor&,
-                          DataSourceFactory,
-                          DataSourceStaticState*) override;
-  std::unique_ptr<TraceWriterBase> CreateTraceWriter(
-      DataSourceState*,
-      BufferExhaustedPolicy buffer_exhausted_policy) override;
-  void DestroyStoppedTraceWritersForCurrentThread() override;
-
-  std::unique_ptr<TracingSession> CreateTracingSession(BackendType);
-
-  // Producer-side bookkeeping methods.
-  void UpdateDataSourcesOnAllBackends();
-  void SetupDataSource(TracingBackendId,
-                       DataSourceInstanceID,
-                       const DataSourceConfig&);
-  void StartDataSource(TracingBackendId, DataSourceInstanceID);
-  void StopDataSource_AsyncBegin(TracingBackendId, DataSourceInstanceID);
-  void StopDataSource_AsyncEnd(TracingBackendId, DataSourceInstanceID);
-
-  // Consumer-side bookkeeping methods.
-  void SetupTracingSession(TracingSessionGlobalID,
-                           const std::shared_ptr<TraceConfig>&,
-                           base::ScopedFile trace_fd = base::ScopedFile());
-  void StartTracingSession(TracingSessionGlobalID);
-  void StopTracingSession(TracingSessionGlobalID);
-  void DestroyTracingSession(TracingSessionGlobalID);
-  void ReadTracingSessionData(
-      TracingSessionGlobalID,
-      std::function<void(TracingSession::ReadTraceCallbackArgs)>);
-
- private:
-  // For each TracingBackend we create and register one ProducerImpl instance.
-  // This talks to the producer-side of the service, gets start/stop requests
-  // from it and routes them to the registered data sources.
-  // One ProducerImpl == one backend == one tracing service.
-  // This class is needed to disambiguate callbacks coming from different
-  // services. TracingMuxerImpl can't directly implement the Producer interface
-  // because the Producer virtual methods don't allow to identify the service.
-  class ProducerImpl : public Producer {
-   public:
-    ProducerImpl(TracingMuxerImpl*, TracingBackendId);
-    ~ProducerImpl() override;
-
-    void Initialize(std::unique_ptr<ProducerEndpoint> endpoint);
-    void RegisterDataSource(const DataSourceDescriptor&,
-                            DataSourceFactory,
-                            DataSourceStaticState*);
-
-    // perfetto::Producer implementation.
-    void OnConnect() override;
-    void OnDisconnect() override;
-    void OnTracingSetup() override;
-    void SetupDataSource(DataSourceInstanceID,
-                         const DataSourceConfig&) override;
-    void StartDataSource(DataSourceInstanceID,
-                         const DataSourceConfig&) override;
-    void StopDataSource(DataSourceInstanceID) override;
-    void Flush(FlushRequestID, const DataSourceInstanceID*, size_t) override;
-    void ClearIncrementalState(const DataSourceInstanceID*, size_t) override;
-
-    PERFETTO_THREAD_CHECKER(thread_checker_)
-    TracingMuxerImpl* const muxer_;
-    TracingBackendId const backend_id_;
-    bool connected_ = false;
-
-    // Set of data sources that have been actually registered on this producer.
-    // This can be a subset of the global |data_sources_|, because data sources
-    // can register before the producer is fully connected.
-    std::bitset<kMaxDataSources> registered_data_sources_{};
-
-    std::unique_ptr<ProducerEndpoint> service_;  // Keep last.
-  };
-
-  // For each TracingSession created by the API client (Tracing::NewTrace() we
-  // create and register one ConsumerImpl instance.
-  // This talks to the consumer-side of the service, gets end-of-trace and
-  // on-trace-data callbacks and routes them to the API client callbacks.
-  // This class is needed to disambiguate callbacks coming from different
-  // tracing sessions.
-  class ConsumerImpl : public Consumer {
-   public:
-    ConsumerImpl(TracingMuxerImpl*, TracingBackendId, TracingSessionGlobalID);
-    ~ConsumerImpl() override;
-
-    void Initialize(std::unique_ptr<ConsumerEndpoint> endpoint);
-
-    // perfetto::Consumer implementation.
-    void OnConnect() override;
-    void OnDisconnect() override;
-    void OnTracingDisabled() override;
-    void OnTraceData(std::vector<TracePacket>, bool has_more) override;
-    void OnDetach(bool success) override;
-    void OnAttach(bool success, const TraceConfig&) override;
-    void OnTraceStats(bool success, const TraceStats&) override;
-    void OnObservableEvents(const ObservableEvents&) override;
-
-    void NotifyStartComplete();
-    void NotifyStopComplete();
-
-    // Will eventually inform the |muxer_| when it is safe to remove |this|.
-    void Disconnect();
-
-    TracingMuxerImpl* const muxer_;
-    TracingBackendId const backend_id_;
-    TracingSessionGlobalID const session_id_;
-    bool connected_ = false;
-
-    // This is to handle the case where the Setup call from the API client
-    // arrives before the consumer has connected. In this case we keep around
-    // the config and check if we have it after connection.
-    bool start_pending_ = false;
-
-    // Similarly if the session is stopped before the consumer was connected, we
-    // need to wait until the session has started before stopping it.
-    bool stop_pending_ = false;
-
-    // Whether this session was already stopped. This will happen in response to
-    // Stop{,Blocking}, but also if the service stops the session for us
-    // automatically (e.g., when there are no data sources).
-    bool stopped_ = false;
-
-    // shared_ptr because it's posted across threads. This is to avoid copying
-    // it more than once.
-    std::shared_ptr<TraceConfig> trace_config_;
-    base::ScopedFile trace_fd_;
-
-    // An internal callback used to implement StartBlocking().
-    std::function<void()> blocking_start_complete_callback_;
-
-    // If the API client passes a callback to stop, we should invoke this when
-    // OnTracingDisabled() is invoked.
-    std::function<void()> stop_complete_callback_;
-
-    // An internal callback used to implement StopBlocking().
-    std::function<void()> blocking_stop_complete_callback_;
-
-    // Callback passed to ReadTrace().
-    std::function<void(TracingSession::ReadTraceCallbackArgs)>
-        read_trace_callback_;
-
-    // The states of all data sources in this tracing session. |true| means the
-    // data source has started tracing.
-    using DataSourceHandle = std::pair<std::string, std::string>;
-    std::map<DataSourceHandle, bool> data_source_states_;
-
-    std::unique_ptr<ConsumerEndpoint> service_;  // Keep before last.
-    PERFETTO_THREAD_CHECKER(thread_checker_)     // Keep last.
-  };
-
-  // This object is returned to API clients when they call
-  // Tracing::CreateTracingSession().
-  class TracingSessionImpl : public TracingSession {
-   public:
-    TracingSessionImpl(TracingMuxerImpl*, TracingSessionGlobalID);
-    ~TracingSessionImpl() override;
-    void Setup(const TraceConfig&, int fd) override;
-    void Start() override;
-    void StartBlocking() override;
-    void Stop() override;
-    void StopBlocking() override;
-    void ReadTrace(ReadTraceCallback) override;
-    void SetOnStopCallback(std::function<void()>) override;
-
-   private:
-    TracingMuxerImpl* const muxer_;
-    TracingSessionGlobalID const session_id_;
-  };
-
-  struct RegisteredDataSource {
-    DataSourceDescriptor descriptor;
-    DataSourceFactory factory{};
-    DataSourceStaticState* static_state = nullptr;
-  };
-
-  struct RegisteredBackend {
-    // Backends are supposed to have static lifetime.
-    TracingBackend* backend = nullptr;
-    TracingBackendId id = 0;
-    BackendType type{};
-
-    std::unique_ptr<ProducerImpl> producer;
-
-    // The calling code can request more than one concurrently active tracing
-    // session for the same backend. We need to create one consumer per session.
-    std::vector<std::unique_ptr<ConsumerImpl>> consumers;
-  };
-
-  explicit TracingMuxerImpl(const TracingInitArgs&);
-  void Initialize(const TracingInitArgs& args);
-  ConsumerImpl* FindConsumer(TracingSessionGlobalID session_id);
-  void OnConsumerDisconnected(ConsumerImpl* consumer);
-
-  struct FindDataSourceRes {
-    FindDataSourceRes() = default;
-    FindDataSourceRes(DataSourceStaticState* a, DataSourceState* b, uint32_t c)
-        : static_state(a), internal_state(b), instance_idx(c) {}
-    explicit operator bool() const { return !!internal_state; }
-
-    DataSourceStaticState* static_state = nullptr;
-    DataSourceState* internal_state = nullptr;
-    uint32_t instance_idx = 0;
-  };
-  FindDataSourceRes FindDataSource(TracingBackendId, DataSourceInstanceID);
-
-  std::unique_ptr<base::TaskRunner> task_runner_;
-  std::vector<RegisteredDataSource> data_sources_;
-  std::vector<RegisteredBackend> backends_;
-
-  std::atomic<TracingSessionGlobalID> next_tracing_session_id_{};
-
-  PERFETTO_THREAD_CHECKER(thread_checker_)
-};
-
-}  // namespace internal
-}  // namespace perfetto
-
-#endif  // SRC_TRACING_INTERNAL_TRACING_MUXER_IMPL_H_
diff --git a/src/tracing/internal/track_event_internal.cc b/src/tracing/internal/track_event_internal.cc
deleted file mode 100644
index 2e65517..0000000
--- a/src/tracing/internal/track_event_internal.cc
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/tracing/internal/track_event_internal.h"
-
-#include "perfetto/base/time.h"
-#include "perfetto/ext/base/proc_utils.h"
-#include "perfetto/ext/base/thread_utils.h"
-#include "perfetto/tracing/core/data_source_config.h"
-#include "perfetto/tracing/track_event.h"
-#include "perfetto/tracing/track_event_category_registry.h"
-#include "perfetto/tracing/track_event_interned_data_index.h"
-#include "protos/perfetto/common/data_source_descriptor.gen.h"
-#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
-#include "protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
-#include "protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
-
-namespace perfetto {
-namespace internal {
-
-BaseTrackEventInternedDataIndex::~BaseTrackEventInternedDataIndex() = default;
-
-namespace {
-
-std::atomic<perfetto::base::PlatformThreadID> g_main_thread;
-
-struct InternedEventCategory
-    : public TrackEventInternedDataIndex<
-          InternedEventCategory,
-          perfetto::protos::pbzero::InternedData::kEventCategoriesFieldNumber,
-          const char*,
-          SmallInternedDataTraits> {
-  static void Add(protos::pbzero::InternedData* interned_data,
-                  size_t iid,
-                  const char* value) {
-    auto category = interned_data->add_event_categories();
-    category->set_iid(iid);
-    category->set_name(value);
-  }
-};
-
-struct InternedEventName
-    : public TrackEventInternedDataIndex<
-          InternedEventName,
-          perfetto::protos::pbzero::InternedData::kEventNamesFieldNumber,
-          const char*,
-          SmallInternedDataTraits> {
-  static void Add(protos::pbzero::InternedData* interned_data,
-                  size_t iid,
-                  const char* value) {
-    auto name = interned_data->add_event_names();
-    name->set_iid(iid);
-    name->set_name(value);
-  }
-};
-
-uint64_t GetTimeNs() {
-  // TODO(skyostil): Consider using boot time where available.
-  return static_cast<uint64_t>(perfetto::base::GetWallTimeNs().count());
-}
-
-// static
-void WriteSequenceDescriptors(TraceWriterBase* trace_writer,
-                              uint64_t timestamp) {
-  if (perfetto::base::GetThreadId() == g_main_thread) {
-    auto packet = trace_writer->NewTracePacket();
-    packet->set_timestamp(timestamp);
-    packet->set_incremental_state_cleared(true);
-    auto pd = packet->set_process_descriptor();
-    pd->set_pid(static_cast<int32_t>(base::GetProcessId()));
-    // TODO(skyostil): Record command line.
-  }
-  {
-    auto packet = trace_writer->NewTracePacket();
-    packet->set_timestamp(timestamp);
-    auto td = packet->set_thread_descriptor();
-    td->set_pid(static_cast<int32_t>(base::GetProcessId()));
-    td->set_tid(static_cast<int32_t>(perfetto::base::GetThreadId()));
-  }
-}
-
-}  // namespace
-
-// static
-bool TrackEventInternal::Initialize(
-    bool (*register_data_source)(const DataSourceDescriptor&)) {
-  if (!g_main_thread)
-    g_main_thread = perfetto::base::GetThreadId();
-
-  perfetto::DataSourceDescriptor dsd;
-  // TODO(skyostil): Advertise the known categories.
-  dsd.set_name("track_event");
-  return register_data_source(dsd);
-}
-
-// static
-void TrackEventInternal::EnableTracing(
-    const TrackEventCategoryRegistry& registry,
-    const DataSourceConfig& config,
-    uint32_t instance_index) {
-  for (size_t i = 0; i < registry.category_count(); i++) {
-    // TODO(skyostil): Support the full category config syntax instead of
-    // just strict matching.
-    // TODO(skyostil): Support comma-separated categories.
-    if (config.legacy_config().empty() ||
-        config.legacy_config() == registry.GetCategory(i)->name) {
-      registry.EnableCategoryForInstance(i, instance_index);
-    }
-  }
-}
-
-// static
-void TrackEventInternal::DisableTracing(
-    const TrackEventCategoryRegistry& registry,
-    uint32_t instance_index) {
-  for (size_t i = 0; i < registry.category_count(); i++)
-    registry.DisableCategoryForInstance(i, instance_index);
-}
-
-// static
-TrackEventContext TrackEventInternal::WriteEvent(
-    TraceWriterBase* trace_writer,
-    TrackEventIncrementalState* incr_state,
-    const char* category,
-    const char* name,
-    perfetto::protos::pbzero::TrackEvent::Type type) {
-  PERFETTO_DCHECK(category);
-  PERFETTO_DCHECK(g_main_thread);
-  auto timestamp = GetTimeNs();
-
-  if (incr_state->was_cleared) {
-    incr_state->was_cleared = false;
-    WriteSequenceDescriptors(trace_writer, timestamp);
-  }
-  auto packet = trace_writer->NewTracePacket();
-  packet->set_timestamp(timestamp);
-
-  // We assume that |category| and |name| point to strings with static lifetime.
-  // This means we can use their addresses as interning keys.
-  TrackEventContext ctx(std::move(packet), incr_state);
-  size_t category_iid = InternedEventCategory::Get(&ctx, category);
-
-  auto track_event = ctx.track_event();
-  track_event->set_type(type);
-  // TODO(skyostil): Handle multiple categories.
-  track_event->add_category_iids(category_iid);
-  if (name) {
-    size_t name_iid = InternedEventName::Get(&ctx, name);
-    track_event->set_name_iid(name_iid);
-  }
-  return ctx;
-}
-
-}  // namespace internal
-}  // namespace perfetto
diff --git a/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc b/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
index c9611a0..69465cf 100644
--- a/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
+++ b/src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
@@ -20,11 +20,11 @@
 #include <string.h>
 
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/ipc/client.h"
-#include "perfetto/ext/tracing/core/consumer.h"
-#include "perfetto/ext/tracing/core/observable_events.h"
-#include "perfetto/ext/tracing/core/trace_stats.h"
+#include "perfetto/ipc/client.h"
+#include "perfetto/tracing/core/consumer.h"
+#include "perfetto/tracing/core/observable_events.h"
 #include "perfetto/tracing/core/trace_config.h"
+#include "perfetto/tracing/core/trace_stats.h"
 #include "perfetto/tracing/core/tracing_service_state.h"
 
 // TODO(fmayer): Add a test to check to what happens when ConsumerIPCClientImpl
diff --git a/src/tracing/ipc/consumer/consumer_ipc_client_impl.h b/src/tracing/ipc/consumer/consumer_ipc_client_impl.h
index ae5a479..c3933c0 100644
--- a/src/tracing/ipc/consumer/consumer_ipc_client_impl.h
+++ b/src/tracing/ipc/consumer/consumer_ipc_client_impl.h
@@ -21,15 +21,15 @@
 
 #include <vector>
 
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/ipc/service_proxy.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
-#include "perfetto/ext/tracing/ipc/consumer_ipc_client.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/weak_ptr.h"
+#include "perfetto/ipc/service_proxy.h"
+#include "perfetto/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/trace_packet.h"
+#include "perfetto/tracing/core/tracing_service.h"
+#include "perfetto/tracing/ipc/consumer_ipc_client.h"
 
-#include "protos/perfetto/ipc/consumer_port.ipc.h"
+#include "perfetto/ipc/consumer_port.ipc.h"
 
 namespace perfetto {
 
diff --git a/src/tracing/ipc/default_socket.cc b/src/tracing/ipc/default_socket.cc
index 519bb06..7234cb4 100644
--- a/src/tracing/ipc/default_socket.cc
+++ b/src/tracing/ipc/default_socket.cc
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-#include "perfetto/ext/tracing/ipc/default_socket.h"
+#include "src/tracing/ipc/default_socket.h"
 
 #include "perfetto/base/build_config.h"
-#include "perfetto/ext/ipc/basic_types.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
+#include "perfetto/ipc/basic_types.h"
+#include "perfetto/tracing/core/basic_types.h"
 
 #include <stdlib.h>
 
diff --git a/src/tracing/ipc/default_socket.h b/src/tracing/ipc/default_socket.h
new file mode 100644
index 0000000..0cfa00e
--- /dev/null
+++ b/src/tracing/ipc/default_socket.h
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_TRACING_IPC_DEFAULT_SOCKET_H_
+#define SRC_TRACING_IPC_DEFAULT_SOCKET_H_
+
+namespace perfetto {
+
+const char* GetConsumerSocket();
+const char* GetProducerSocket();
+
+}  // namespace perfetto
+
+#endif  // SRC_TRACING_IPC_DEFAULT_SOCKET_H_
diff --git a/src/tracing/ipc/posix_shared_memory.cc b/src/tracing/ipc/posix_shared_memory.cc
index d7f0904..714284d 100644
--- a/src/tracing/ipc/posix_shared_memory.cc
+++ b/src/tracing/ipc/posix_shared_memory.cc
@@ -29,7 +29,7 @@
 
 #include "perfetto/base/build_config.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/temp_file.h"
+#include "perfetto/base/temp_file.h"
 
 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
 #include <linux/memfd.h>
diff --git a/src/tracing/ipc/posix_shared_memory.h b/src/tracing/ipc/posix_shared_memory.h
index 4bb3baf..88f410c 100644
--- a/src/tracing/ipc/posix_shared_memory.h
+++ b/src/tracing/ipc/posix_shared_memory.h
@@ -21,8 +21,8 @@
 
 #include <memory>
 
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/tracing/core/shared_memory.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/tracing/core/shared_memory.h"
 
 namespace perfetto {
 
diff --git a/src/tracing/ipc/posix_shared_memory_unittest.cc b/src/tracing/ipc/posix_shared_memory_unittest.cc
index 1156556..e6739bf 100644
--- a/src/tracing/ipc/posix_shared_memory_unittest.cc
+++ b/src/tracing/ipc/posix_shared_memory_unittest.cc
@@ -23,14 +23,14 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
+#include "gtest/gtest.h"
 #include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/file_utils.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/base/temp_file.h"
+#include "perfetto/base/utils.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/base/test/vm_test_utils.h"
-#include "test/gtest_and_gmock.h"
 
 namespace perfetto {
 namespace {
diff --git a/src/tracing/ipc/producer/producer_ipc_client_impl.cc b/src/tracing/ipc/producer/producer_ipc_client_impl.cc
index bee2026..bf6e1b0 100644
--- a/src/tracing/ipc/producer/producer_ipc_client_impl.cc
+++ b/src/tracing/ipc/producer/producer_ipc_client_impl.cc
@@ -19,16 +19,15 @@
 #include <inttypes.h>
 #include <string.h>
 
-#include "perfetto/base/logging.h"
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/ipc/client.h"
-#include "perfetto/ext/tracing/core/commit_data_request.h"
-#include "perfetto/ext/tracing/core/producer.h"
-#include "perfetto/ext/tracing/core/shared_memory_arbiter.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
+#include "perfetto/ipc/client.h"
+#include "perfetto/tracing/core/commit_data_request.h"
 #include "perfetto/tracing/core/data_source_config.h"
 #include "perfetto/tracing/core/data_source_descriptor.h"
+#include "perfetto/tracing/core/producer.h"
+#include "perfetto/tracing/core/shared_memory_arbiter.h"
 #include "perfetto/tracing/core/trace_config.h"
+#include "perfetto/tracing/core/trace_writer.h"
 #include "src/tracing/ipc/posix_shared_memory.h"
 
 // TODO(fmayer): think to what happens when ProducerIPCClientImpl gets destroyed
@@ -43,14 +42,10 @@
     Producer* producer,
     const std::string& producer_name,
     base::TaskRunner* task_runner,
-    TracingService::ProducerSMBScrapingMode smb_scraping_mode,
-    size_t shared_memory_size_hint_bytes,
-    size_t shared_memory_page_size_hint_bytes) {
+    TracingService::ProducerSMBScrapingMode smb_scraping_mode) {
   return std::unique_ptr<TracingService::ProducerEndpoint>(
       new ProducerIPCClientImpl(service_sock_name, producer, producer_name,
-                                task_runner, smb_scraping_mode,
-                                shared_memory_size_hint_bytes,
-                                shared_memory_page_size_hint_bytes));
+                                task_runner, smb_scraping_mode));
 }
 
 ProducerIPCClientImpl::ProducerIPCClientImpl(
@@ -58,16 +53,12 @@
     Producer* producer,
     const std::string& producer_name,
     base::TaskRunner* task_runner,
-    TracingService::ProducerSMBScrapingMode smb_scraping_mode,
-    size_t shared_memory_size_hint_bytes,
-    size_t shared_memory_page_size_hint_bytes)
+    TracingService::ProducerSMBScrapingMode smb_scraping_mode)
     : producer_(producer),
       task_runner_(task_runner),
       ipc_channel_(ipc::Client::CreateInstance(service_sock_name, task_runner)),
       producer_port_(this /* event_listener */),
       name_(producer_name),
-      shared_memory_page_size_hint_bytes_(shared_memory_page_size_hint_bytes),
-      shared_memory_size_hint_bytes_(shared_memory_size_hint_bytes),
       smb_scraping_mode_(smb_scraping_mode) {
   ipc_channel_->BindService(producer_port_.GetWeakPtr());
   PERFETTO_DCHECK_THREAD(thread_checker_);
@@ -90,10 +81,6 @@
       });
   protos::InitializeConnectionRequest req;
   req.set_producer_name(name_);
-  req.set_shared_memory_size_hint_bytes(
-      static_cast<uint32_t>(shared_memory_size_hint_bytes_));
-  req.set_shared_memory_page_size_hint_bytes(
-      static_cast<uint32_t>(shared_memory_page_size_hint_bytes_));
   switch (smb_scraping_mode_) {
     case TracingService::ProducerSMBScrapingMode::kDefault:
       // No need to set the mode, it defaults to use the service default if
@@ -108,14 +95,6 @@
           protos::InitializeConnectionRequest::SMB_SCRAPING_DISABLED);
       break;
   }
-
-#if PERFETTO_DCHECK_IS_ON()
-  req.set_build_flags(
-      protos::InitializeConnectionRequest::BUILD_FLAGS_DCHECKS_ON);
-#else
-  req.set_build_flags(
-      protos::InitializeConnectionRequest::BUILD_FLAGS_DCHECKS_OFF);
-#endif
   producer_port_.InitializeConnection(req, std::move(on_init));
 
   // Create the back channel to receive commands from the Service.
@@ -356,12 +335,10 @@
 }
 
 std::unique_ptr<TraceWriter> ProducerIPCClientImpl::CreateTraceWriter(
-    BufferID target_buffer,
-    BufferExhaustedPolicy buffer_exhausted_policy) {
+    BufferID target_buffer) {
   // This method can be called by different threads. |shared_memory_arbiter_| is
   // thread-safe but be aware of accessing any other state in this function.
-  return shared_memory_arbiter_->CreateTraceWriter(target_buffer,
-                                                   buffer_exhausted_policy);
+  return shared_memory_arbiter_->CreateTraceWriter(target_buffer);
 }
 
 SharedMemoryArbiter* ProducerIPCClientImpl::GetInProcessShmemArbiter() {
diff --git a/src/tracing/ipc/producer/producer_ipc_client_impl.h b/src/tracing/ipc/producer/producer_ipc_client_impl.h
index 6551d30..ba43421 100644
--- a/src/tracing/ipc/producer/producer_ipc_client_impl.h
+++ b/src/tracing/ipc/producer/producer_ipc_client_impl.h
@@ -22,14 +22,14 @@
 #include <set>
 #include <vector>
 
-#include "perfetto/ext/base/thread_checker.h"
-#include "perfetto/ext/ipc/service_proxy.h"
-#include "perfetto/ext/tracing/core/basic_types.h"
-#include "perfetto/ext/tracing/core/shared_memory.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
-#include "perfetto/ext/tracing/ipc/producer_ipc_client.h"
+#include "perfetto/base/thread_checker.h"
+#include "perfetto/ipc/service_proxy.h"
+#include "perfetto/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/shared_memory.h"
+#include "perfetto/tracing/core/tracing_service.h"
+#include "perfetto/tracing/ipc/producer_ipc_client.h"
 
-#include "protos/perfetto/ipc/producer_port.ipc.h"
+#include "perfetto/ipc/producer_port.ipc.h"
 
 namespace perfetto {
 
@@ -56,9 +56,7 @@
                         Producer*,
                         const std::string& producer_name,
                         base::TaskRunner*,
-                        TracingService::ProducerSMBScrapingMode,
-                        size_t shared_memory_size_hint_bytes = 0,
-                        size_t shared_memory_page_size_hint_bytes = 0);
+                        TracingService::ProducerSMBScrapingMode);
   ~ProducerIPCClientImpl() override;
 
   // TracingService::ProducerEndpoint implementation.
@@ -74,8 +72,7 @@
   void ActivateTriggers(const std::vector<std::string>&) override;
 
   std::unique_ptr<TraceWriter> CreateTraceWriter(
-      BufferID target_buffer,
-      BufferExhaustedPolicy) override;
+      BufferID target_buffer) override;
   SharedMemoryArbiter* GetInProcessShmemArbiter() override;
   void NotifyFlushComplete(FlushRequestID) override;
   SharedMemory* shared_memory() const override;
@@ -112,8 +109,6 @@
   std::set<DataSourceInstanceID> data_sources_setup_;
   bool connected_ = false;
   std::string const name_;
-  size_t shared_memory_page_size_hint_bytes_ = 0;
-  size_t shared_memory_size_hint_bytes_ = 0;
   TracingService::ProducerSMBScrapingMode const smb_scraping_mode_;
   PERFETTO_THREAD_CHECKER(thread_checker_)
 };
diff --git a/src/tracing/ipc/service/consumer_ipc_service.cc b/src/tracing/ipc/service/consumer_ipc_service.cc
index 698c4f3..8a31f1f 100644
--- a/src/tracing/ipc/service/consumer_ipc_service.cc
+++ b/src/tracing/ipc/service/consumer_ipc_service.cc
@@ -19,16 +19,16 @@
 #include <inttypes.h>
 
 #include "perfetto/base/logging.h"
+#include "perfetto/base/scoped_file.h"
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/ipc/basic_types.h"
-#include "perfetto/ext/ipc/host.h"
-#include "perfetto/ext/tracing/core/shared_memory_abi.h"
-#include "perfetto/ext/tracing/core/slice.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/core/trace_stats.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
+#include "perfetto/ipc/basic_types.h"
+#include "perfetto/ipc/host.h"
+#include "perfetto/tracing/core/shared_memory_abi.h"
+#include "perfetto/tracing/core/slice.h"
 #include "perfetto/tracing/core/trace_config.h"
+#include "perfetto/tracing/core/trace_packet.h"
+#include "perfetto/tracing/core/trace_stats.h"
+#include "perfetto/tracing/core/tracing_service.h"
 #include "perfetto/tracing/core/tracing_service_state.h"
 
 namespace perfetto {
diff --git a/src/tracing/ipc/service/consumer_ipc_service.h b/src/tracing/ipc/service/consumer_ipc_service.h
index 9d59556..cb9aa0f 100644
--- a/src/tracing/ipc/service/consumer_ipc_service.h
+++ b/src/tracing/ipc/service/consumer_ipc_service.h
@@ -22,12 +22,12 @@
 #include <memory>
 #include <string>
 
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/ipc/basic_types.h"
-#include "perfetto/ext/tracing/core/consumer.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
+#include "perfetto/base/weak_ptr.h"
+#include "perfetto/ipc/basic_types.h"
+#include "perfetto/tracing/core/consumer.h"
+#include "perfetto/tracing/core/tracing_service.h"
 
-#include "protos/perfetto/ipc/consumer_port.ipc.h"
+#include "perfetto/ipc/consumer_port.ipc.h"
 
 namespace perfetto {
 
diff --git a/src/tracing/ipc/service/producer_ipc_service.cc b/src/tracing/ipc/service/producer_ipc_service.cc
index 96acf71..15f7808 100644
--- a/src/tracing/ipc/service/producer_ipc_service.cc
+++ b/src/tracing/ipc/service/producer_ipc_service.cc
@@ -20,11 +20,11 @@
 
 #include "perfetto/base/logging.h"
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/ipc/host.h"
-#include "perfetto/ext/tracing/core/commit_data_request.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
+#include "perfetto/ipc/host.h"
+#include "perfetto/tracing/core/commit_data_request.h"
 #include "perfetto/tracing/core/data_source_config.h"
 #include "perfetto/tracing/core/data_source_descriptor.h"
+#include "perfetto/tracing/core/tracing_service.h"
 #include "src/tracing/ipc/posix_shared_memory.h"
 
 // The remote Producer(s) are not trusted. All the methods from the ProducerPort
@@ -78,33 +78,15 @@
       break;
   }
 
-  bool dcheck_mismatch = false;
-#if PERFETTO_DCHECK_IS_ON()
-  dcheck_mismatch =
-      req.build_flags() ==
-      protos::InitializeConnectionRequest::BUILD_FLAGS_DCHECKS_OFF;
-#else
-  dcheck_mismatch = req.build_flags() ==
-                    protos::InitializeConnectionRequest::BUILD_FLAGS_DCHECKS_ON;
-#endif
-  if (dcheck_mismatch) {
-    PERFETTO_LOG(
-        "The producer and the service binaries are built using different "
-        "DEBUG/NDEBUG flags. This will likely cause crashes.");
-  }
-
   // ConnectProducer will call OnConnect() on the next task.
   producer->service_endpoint = core_service_->ConnectProducer(
       producer.get(), client_info.uid(), req.producer_name(),
-      req.shared_memory_size_hint_bytes(),
-      /*in_process=*/false, smb_scraping_mode,
-      req.shared_memory_page_size_hint_bytes());
+      req.shared_memory_size_hint_bytes(), /*in_process=*/false,
+      smb_scraping_mode);
 
   // Could happen if the service has too many producers connected.
-  if (!producer->service_endpoint) {
+  if (!producer->service_endpoint)
     response.Reject();
-    return;
-  }
 
   producers_.emplace(ipc_client_id, std::move(producer));
   // Because of the std::move() |producer| is invalid after this point.
diff --git a/src/tracing/ipc/service/producer_ipc_service.h b/src/tracing/ipc/service/producer_ipc_service.h
index 21edfa9..5954680 100644
--- a/src/tracing/ipc/service/producer_ipc_service.h
+++ b/src/tracing/ipc/service/producer_ipc_service.h
@@ -21,12 +21,12 @@
 #include <memory>
 #include <string>
 
-#include "perfetto/ext/base/weak_ptr.h"
-#include "perfetto/ext/ipc/basic_types.h"
-#include "perfetto/ext/tracing/core/producer.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
+#include "perfetto/base/weak_ptr.h"
+#include "perfetto/ipc/basic_types.h"
+#include "perfetto/tracing/core/producer.h"
+#include "perfetto/tracing/core/tracing_service.h"
 
-#include "protos/perfetto/ipc/producer_port.ipc.h"
+#include "perfetto/ipc/producer_port.ipc.h"
 
 namespace perfetto {
 
diff --git a/src/tracing/ipc/service/service_ipc_host_impl.cc b/src/tracing/ipc/service/service_ipc_host_impl.cc
index ad6f9ef..9c185ac 100644
--- a/src/tracing/ipc/service/service_ipc_host_impl.cc
+++ b/src/tracing/ipc/service/service_ipc_host_impl.cc
@@ -18,8 +18,8 @@
 
 #include "perfetto/base/logging.h"
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/ipc/host.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
+#include "perfetto/ipc/host.h"
+#include "perfetto/tracing/core/tracing_service.h"
 #include "src/tracing/ipc/posix_shared_memory.h"
 #include "src/tracing/ipc/service/consumer_ipc_service.h"
 #include "src/tracing/ipc/service/producer_ipc_service.h"
diff --git a/src/tracing/ipc/service/service_ipc_host_impl.h b/src/tracing/ipc/service/service_ipc_host_impl.h
index d06ef60..e7f5cdd 100644
--- a/src/tracing/ipc/service/service_ipc_host_impl.h
+++ b/src/tracing/ipc/service/service_ipc_host_impl.h
@@ -19,7 +19,7 @@
 
 #include <memory>
 
-#include "perfetto/ext/tracing/ipc/service_ipc_host.h"
+#include "perfetto/tracing/ipc/service_ipc_host.h"
 
 namespace perfetto {
 
diff --git a/src/tracing/platform.cc b/src/tracing/platform.cc
deleted file mode 100644
index e6865cd..0000000
--- a/src/tracing/platform.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/tracing/platform.h"
-#include "perfetto/tracing/internal/tracing_tls.h"
-#include "perfetto/tracing/trace_writer_base.h"
-
-namespace perfetto {
-
-PlatformThreadLocalObject::~PlatformThreadLocalObject() = default;
-Platform::~Platform() = default;
-
-// static
-std::unique_ptr<PlatformThreadLocalObject>
-PlatformThreadLocalObject::CreateInstance() {
-  return std::unique_ptr<PlatformThreadLocalObject>(new internal::TracingTLS());
-}
-
-}  // namespace perfetto
diff --git a/src/tracing/platform_posix.cc b/src/tracing/platform_posix.cc
deleted file mode 100644
index 75551fc..0000000
--- a/src/tracing/platform_posix.cc
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/base/build_config.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/thread_task_runner.h"
-#include "perfetto/tracing/internal/tracing_tls.h"
-#include "perfetto/tracing/platform.h"
-#include "perfetto/tracing/trace_writer_base.h"
-
-#include <pthread.h>
-#include <stdlib.h>
-
-namespace perfetto {
-
-namespace {
-
-class PlatformPosix : public Platform {
- public:
-  PlatformPosix();
-  ~PlatformPosix() override;
-
-  ThreadLocalObject* GetOrCreateThreadLocalObject() override;
-  std::unique_ptr<base::TaskRunner> CreateTaskRunner(
-      const CreateTaskRunnerArgs&) override;
-  std::string GetCurrentProcessName() override;
-
- private:
-  pthread_key_t tls_key_{};
-};
-
-// TODO(primiano): make base::ThreadTaskRunner directly inherit TaskRunner, so
-// we can avoid this boilerplate.
-class TaskRunnerInstance : public base::TaskRunner {
- public:
-  TaskRunnerInstance();
-  ~TaskRunnerInstance() override;
-
-  void PostTask(std::function<void()>) override;
-  void PostDelayedTask(std::function<void()>, uint32_t delay_ms) override;
-  void AddFileDescriptorWatch(int fd, std::function<void()>) override;
-  void RemoveFileDescriptorWatch(int fd) override;
-  bool RunsTasksOnCurrentThread() const override;
-
- private:
-  base::ThreadTaskRunner thread_task_runner_;
-};
-
-using ThreadLocalObject = Platform::ThreadLocalObject;
-
-PlatformPosix::PlatformPosix() {
-  auto tls_dtor = [](void* obj) {
-    delete static_cast<ThreadLocalObject*>(obj);
-  };
-  PERFETTO_CHECK(pthread_key_create(&tls_key_, tls_dtor) == 0);
-}
-
-PlatformPosix::~PlatformPosix() {
-  pthread_key_delete(tls_key_);
-}
-
-ThreadLocalObject* PlatformPosix::GetOrCreateThreadLocalObject() {
-  // In chromium this should be implemented using base::ThreadLocalStorage.
-  auto tls = static_cast<ThreadLocalObject*>(pthread_getspecific(tls_key_));
-  if (!tls) {
-    tls = ThreadLocalObject::CreateInstance().release();
-    pthread_setspecific(tls_key_, tls);
-  }
-  return tls;
-}
-
-std::unique_ptr<base::TaskRunner> PlatformPosix::CreateTaskRunner(
-    const CreateTaskRunnerArgs&) {
-  return std::unique_ptr<base::TaskRunner>(new TaskRunnerInstance());
-}
-
-std::string PlatformPosix::GetCurrentProcessName() {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
-    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-  std::string cmdline;
-  base::ReadFile("/proc/self/cmdline", &cmdline);
-  return cmdline.substr(0, cmdline.find('\0'));
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
-  return std::string(getprogname());
-#else
-  return "unknown_producer";
-#endif
-}
-
-TaskRunnerInstance::TaskRunnerInstance()
-    : thread_task_runner_(base::ThreadTaskRunner::CreateAndStart()) {}
-TaskRunnerInstance::~TaskRunnerInstance() = default;
-void TaskRunnerInstance::PostTask(std::function<void()> func) {
-  thread_task_runner_.get()->PostTask(func);
-}
-
-void TaskRunnerInstance::PostDelayedTask(std::function<void()> func,
-                                         uint32_t delay_ms) {
-  thread_task_runner_.get()->PostDelayedTask(func, delay_ms);
-}
-
-void TaskRunnerInstance::AddFileDescriptorWatch(int fd,
-                                                std::function<void()> func) {
-  thread_task_runner_.get()->AddFileDescriptorWatch(fd, func);
-}
-
-void TaskRunnerInstance::RemoveFileDescriptorWatch(int fd) {
-  thread_task_runner_.get()->RemoveFileDescriptorWatch(fd);
-}
-
-bool TaskRunnerInstance::RunsTasksOnCurrentThread() const {
-  return thread_task_runner_.get()->RunsTasksOnCurrentThread();
-}
-
-}  // namespace
-
-// static
-Platform* Platform::GetDefaultPlatform() {
-  static PlatformPosix* instance = new PlatformPosix();
-  return instance;
-}
-
-}  // namespace perfetto
diff --git a/src/tracing/test/BUILD.gn b/src/tracing/test/BUILD.gn
deleted file mode 100644
index 2c99bc9..0000000
--- a/src/tracing/test/BUILD.gn
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (C) 2019 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.
-
-# api_test_support needs to be self-contained and not leak any other perfetto
-# deps. See comment in api_test_support.h
-source_set("api_test_support") {
-  testonly = true
-  deps = [
-    "../../../gn:default_deps",
-    "../../base",
-  ]
-  sources = [
-    "api_test_support.cc",
-    "api_test_support.h",
-  ]
-}
diff --git a/src/tracing/test/aligned_buffer_test.h b/src/tracing/test/aligned_buffer_test.h
index 18ee4ba..23c8b1c 100644
--- a/src/tracing/test/aligned_buffer_test.h
+++ b/src/tracing/test/aligned_buffer_test.h
@@ -21,9 +21,9 @@
 
 #include <memory>
 
-#include "perfetto/ext/base/utils.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/utils.h"
 #include "src/tracing/test/test_shared_memory.h"
-#include "test/gtest_and_gmock.h"
 
 namespace perfetto {
 
diff --git a/src/tracing/test/api_test_support.cc b/src/tracing/test/api_test_support.cc
deleted file mode 100644
index ce49407..0000000
--- a/src/tracing/test/api_test_support.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/tracing/test/api_test_support.h"
-
-#include "perfetto/base/time.h"
-#include "perfetto/ext/base/proc_utils.h"
-
-namespace perfetto {
-namespace test {
-
-int32_t GetCurrentProcessId() {
-  return static_cast<int32_t>(base::GetProcessId());
-}
-
-uint64_t GetWallTimeNs() {
-  return static_cast<uint64_t>(perfetto::base::GetWallTimeNs().count());
-}
-
-}  // namespace test
-}  // namespace perfetto
diff --git a/src/tracing/test/api_test_support.h b/src/tracing/test/api_test_support.h
deleted file mode 100644
index d85b9ec..0000000
--- a/src/tracing/test/api_test_support.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACING_TEST_API_TEST_SUPPORT_H_
-#define SRC_TRACING_TEST_API_TEST_SUPPORT_H_
-
-// This header is intended to be used only for api_integrationtest.cc and solves
-// the following problem: api_integrationtest.cc doesn't pull any non-public
-// perfetto header, to spot accidental public->non-public dependencies.
-// Sometimes, however, we need to use some internal perfetto code for the test
-// itself. This header exposes wrapper functions to achieve that without leaking
-// internal headers.
-
-//  IMPORTANT: This header must not pull any non-public perfetto header.
-
-#include <stdint.h>
-
-namespace perfetto {
-namespace test {
-
-int32_t GetCurrentProcessId();
-uint64_t GetWallTimeNs();
-
-}  // namespace test
-}  // namespace perfetto
-
-#endif  // SRC_TRACING_TEST_API_TEST_SUPPORT_H_
diff --git a/src/tracing/test/fake_packet.cc b/src/tracing/test/fake_packet.cc
index eef70df..210f5fa 100644
--- a/src/tracing/test/fake_packet.cc
+++ b/src/tracing/test/fake_packet.cc
@@ -19,8 +19,8 @@
 #include <ostream>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/tracing/core/shared_memory_abi.h"
 #include "perfetto/protozero/proto_utils.h"
+#include "perfetto/tracing/core/shared_memory_abi.h"
 #include "src/tracing/core/trace_buffer.h"
 
 using protozero::proto_utils::ParseVarInt;
@@ -131,11 +131,6 @@
   return *this;
 }
 
-FakeChunk& FakeChunk::SetFlags(uint8_t flags_to_set) {
-  flags |= flags_to_set;
-  return *this;
-}
-
 FakeChunk& FakeChunk::ClearBytes(size_t offset, size_t len) {
   PERFETTO_DCHECK(offset + len <= data.size());
   memset(data.data() + offset, 0, len);
diff --git a/src/tracing/test/fake_packet.h b/src/tracing/test/fake_packet.h
index 117df5c..6f24408 100644
--- a/src/tracing/test/fake_packet.h
+++ b/src/tracing/test/fake_packet.h
@@ -24,7 +24,7 @@
 #include <string>
 #include <vector>
 
-#include "perfetto/ext/tracing/core/basic_types.h"
+#include "perfetto/tracing/core/basic_types.h"
 
 namespace perfetto {
 
@@ -65,8 +65,6 @@
   // Increments the number of packets in the chunk without adding new data.
   FakeChunk& IncrementNumPackets();
 
-  FakeChunk& SetFlags(uint8_t flags_to_set);
-
   FakeChunk& ClearBytes(size_t offset, size_t len);
 
   FakeChunk& SetUID(uid_t);
diff --git a/src/tracing/test/fake_producer_endpoint.h b/src/tracing/test/fake_producer_endpoint.h
index fc364cf..29183b1 100644
--- a/src/tracing/test/fake_producer_endpoint.h
+++ b/src/tracing/test/fake_producer_endpoint.h
@@ -17,8 +17,8 @@
 #ifndef SRC_TRACING_TEST_FAKE_PRODUCER_ENDPOINT_H_
 #define SRC_TRACING_TEST_FAKE_PRODUCER_ENDPOINT_H_
 
-#include "perfetto/ext/tracing/core/commit_data_request.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
+#include "perfetto/tracing/core/commit_data_request.h"
+#include "perfetto/tracing/core/tracing_service.h"
 
 namespace perfetto {
 
@@ -28,10 +28,8 @@
   void UnregisterDataSource(const std::string&) override {}
   void RegisterTraceWriter(uint32_t, uint32_t) override {}
   void UnregisterTraceWriter(uint32_t) override {}
-  void CommitData(const CommitDataRequest& req,
-                  CommitDataCallback callback) override {
+  void CommitData(const CommitDataRequest& req, CommitDataCallback) override {
     last_commit_data_request = req;
-    last_commit_data_callback = callback;
   }
   void NotifyFlushComplete(FlushRequestID) override {}
   void NotifyDataSourceStarted(DataSourceInstanceID) override {}
@@ -39,15 +37,12 @@
   void ActivateTriggers(const std::vector<std::string>&) override {}
   SharedMemory* shared_memory() const override { return nullptr; }
   size_t shared_buffer_page_size_kb() const override { return 0; }
-  std::unique_ptr<TraceWriter> CreateTraceWriter(
-      BufferID,
-      BufferExhaustedPolicy) override {
+  std::unique_ptr<TraceWriter> CreateTraceWriter(BufferID) override {
     return nullptr;
   }
   SharedMemoryArbiter* GetInProcessShmemArbiter() override { return nullptr; }
 
   CommitDataRequest last_commit_data_request;
-  CommitDataCallback last_commit_data_callback;
 };
 
 }  // namespace perfetto
diff --git a/src/tracing/test/hello_world_benchmark.cc b/src/tracing/test/hello_world_benchmark.cc
new file mode 100644
index 0000000..c554de9
--- /dev/null
+++ b/src/tracing/test/hello_world_benchmark.cc
@@ -0,0 +1,9 @@
+#include "benchmark/benchmark.h"
+
+static void BM_StringCreation(benchmark::State& state) {
+  while (state.KeepRunning())
+    std::string empty_string;
+}
+// Register the function as a benchmark
+BENCHMARK(BM_StringCreation);
+
diff --git a/src/tracing/test/mock_consumer.cc b/src/tracing/test/mock_consumer.cc
index 17a983d..c2f4548 100644
--- a/src/tracing/test/mock_consumer.cc
+++ b/src/tracing/test/mock_consumer.cc
@@ -16,8 +16,8 @@
 
 #include "src/tracing/test/mock_consumer.h"
 
-#include "perfetto/ext/tracing/core/trace_stats.h"
 #include "perfetto/tracing/core/trace_config.h"
+#include "perfetto/tracing/core/trace_stats.h"
 #include "src/base/test/test_task_runner.h"
 
 using ::testing::_;
@@ -109,7 +109,7 @@
             for (TracePacket& packet : *packets) {
               decoded_packets.emplace_back();
               protos::TracePacket* decoded_packet = &decoded_packets.back();
-              decoded_packet->ParseFromString(packet.GetRawBytesForTesting());
+              packet.Decode(decoded_packet);
             }
             if (!has_more)
               on_read_buffers();
diff --git a/src/tracing/test/mock_consumer.h b/src/tracing/test/mock_consumer.h
index b2f3563..fe43fb5 100644
--- a/src/tracing/test/mock_consumer.h
+++ b/src/tracing/test/mock_consumer.h
@@ -19,13 +19,13 @@
 
 #include <memory>
 
-#include "perfetto/ext/tracing/core/consumer.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
+#include "gmock/gmock.h"
+#include "perfetto/tracing/core/consumer.h"
+#include "perfetto/tracing/core/trace_packet.h"
+#include "perfetto/tracing/core/tracing_service.h"
 #include "perfetto/tracing/core/tracing_service_state.h"
-#include "test/gtest_and_gmock.h"
 
-#include "protos/perfetto/trace/trace_packet.pb.h"
+#include "perfetto/trace/trace_packet.pb.h"
 
 namespace perfetto {
 
diff --git a/src/tracing/test/mock_producer.cc b/src/tracing/test/mock_producer.cc
index 39ee0a8..02c33ba 100644
--- a/src/tracing/test/mock_producer.cc
+++ b/src/tracing/test/mock_producer.cc
@@ -16,10 +16,9 @@
 
 #include "src/tracing/test/mock_producer.h"
 
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
 #include "perfetto/tracing/core/data_source_config.h"
 #include "perfetto/tracing/core/data_source_descriptor.h"
+#include "perfetto/tracing/core/trace_writer.h"
 #include "src/base/test/test_task_runner.h"
 
 using ::testing::_;
@@ -47,13 +46,11 @@
 void MockProducer::Connect(TracingService* svc,
                            const std::string& producer_name,
                            uid_t uid,
-                           size_t shared_memory_size_hint_bytes,
-                           size_t shared_memory_page_size_hint_bytes) {
+                           size_t shared_memory_size_hint_bytes) {
   producer_name_ = producer_name;
-  service_endpoint_ = svc->ConnectProducer(
-      this, uid, producer_name, shared_memory_size_hint_bytes,
-      /*in_process=*/true, TracingService::ProducerSMBScrapingMode::kDefault,
-      shared_memory_page_size_hint_bytes);
+  service_endpoint_ =
+      svc->ConnectProducer(this, uid, producer_name,
+                           shared_memory_size_hint_bytes, /*in_process=*/true);
   auto checkpoint_name = "on_producer_connect_" + producer_name;
   auto on_connect = task_runner_->CreateCheckpoint(checkpoint_name);
   EXPECT_CALL(*this, OnConnect()).WillOnce(Invoke(on_connect));
diff --git a/src/tracing/test/mock_producer.h b/src/tracing/test/mock_producer.h
index 7b23f2c..3094678 100644
--- a/src/tracing/test/mock_producer.h
+++ b/src/tracing/test/mock_producer.h
@@ -21,10 +21,10 @@
 #include <memory>
 #include <string>
 
-#include "perfetto/ext/tracing/core/producer.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "perfetto/ext/tracing/core/tracing_service.h"
-#include "test/gtest_and_gmock.h"
+#include "gmock/gmock.h"
+#include "perfetto/tracing/core/producer.h"
+#include "perfetto/tracing/core/trace_writer.h"
+#include "perfetto/tracing/core/tracing_service.h"
 
 namespace perfetto {
 
@@ -46,8 +46,7 @@
   void Connect(TracingService* svc,
                const std::string& producer_name,
                uid_t uid = 42,
-               size_t shared_memory_size_hint_bytes = 0,
-               size_t shared_memory_page_size_hint_bytes = 0);
+               size_t shared_memory_size_hint_bytes = 0);
   void RegisterDataSource(const std::string& name,
                           bool ack_stop = false,
                           bool ack_start = false,
diff --git a/src/tracing/test/test_shared_memory.h b/src/tracing/test/test_shared_memory.h
index 9db6bcb..4b11b92 100644
--- a/src/tracing/test/test_shared_memory.h
+++ b/src/tracing/test/test_shared_memory.h
@@ -21,8 +21,8 @@
 
 #include <memory>
 
-#include "perfetto/ext/base/paged_memory.h"
-#include "perfetto/ext/tracing/core/shared_memory.h"
+#include "perfetto/base/paged_memory.h"
+#include "perfetto/tracing/core/shared_memory.h"
 
 namespace perfetto {
 
diff --git a/src/tracing/test/tracing_integration_test.cc b/src/tracing/test/tracing_integration_test.cc
index 799b614..16a2181 100644
--- a/src/tracing/test/tracing_integration_test.cc
+++ b/src/tracing/test/tracing_integration_test.cc
@@ -17,28 +17,29 @@
 #include <inttypes.h>
 #include <unistd.h>
 
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/ext/tracing/core/consumer.h"
-#include "perfetto/ext/tracing/core/producer.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/core/trace_stats.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "perfetto/ext/tracing/ipc/consumer_ipc_client.h"
-#include "perfetto/ext/tracing/ipc/producer_ipc_client.h"
-#include "perfetto/ext/tracing/ipc/service_ipc_host.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/temp_file.h"
+#include "perfetto/tracing/core/consumer.h"
 #include "perfetto/tracing/core/data_source_config.h"
 #include "perfetto/tracing/core/data_source_descriptor.h"
+#include "perfetto/tracing/core/producer.h"
 #include "perfetto/tracing/core/trace_config.h"
+#include "perfetto/tracing/core/trace_packet.h"
+#include "perfetto/tracing/core/trace_stats.h"
+#include "perfetto/tracing/core/trace_writer.h"
+#include "perfetto/tracing/ipc/consumer_ipc_client.h"
+#include "perfetto/tracing/ipc/producer_ipc_client.h"
+#include "perfetto/tracing/ipc/service_ipc_host.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/ipc/test/test_socket.h"
 #include "src/tracing/core/tracing_service_impl.h"
-#include "test/gtest_and_gmock.h"
 
-#include "protos/perfetto/config/trace_config.pb.h"
-#include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/trace.pb.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/config/trace_config.pb.h"
+#include "perfetto/trace/test_event.pbzero.h"
+#include "perfetto/trace/trace.pb.h"
+#include "perfetto/trace/trace_packet.pb.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
 namespace {
@@ -308,8 +309,7 @@
 
             for (auto& encoded_packet : *packets) {
               protos::TracePacket packet;
-              ASSERT_TRUE(packet.ParseFromString(
-                  encoded_packet.GetRawBytesForTesting()));
+              ASSERT_TRUE(encoded_packet.Decode(&packet));
               if (packet.has_for_testing()) {
                 char buf[8];
                 sprintf(buf, "evt_%zu", num_pack_rx++);
@@ -517,8 +517,7 @@
                      std::vector<TracePacket>* packets, bool has_more) {
             for (auto& encoded_packet : *packets) {
               protos::TracePacket packet;
-              ASSERT_TRUE(packet.ParseFromString(
-                  encoded_packet.GetRawBytesForTesting()));
+              ASSERT_TRUE(encoded_packet.Decode(&packet));
               if (packet.has_for_testing()) {
                 num_test_pack_rx++;
               }
@@ -527,7 +526,7 @@
               all_packets_rx();
           }));
   task_runner_->RunUntilCheckpoint("all_packets_rx");
-  ASSERT_EQ(2u, num_test_pack_rx);
+  ASSERT_EQ(2, num_test_pack_rx);
 
   // Disable tracing.
   consumer_endpoint_->DisableTracing();
diff --git a/src/tracing/test/tracing_module.cc b/src/tracing/test/tracing_module.cc
deleted file mode 100644
index 731d68b..0000000
--- a/src/tracing/test/tracing_module.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/tracing/test/tracing_module.h"
-
-#include "protos/perfetto/trace/track_event/log_message.pbzero.h"
-#include "src/tracing/test/tracing_module_categories.h"
-
-#include <stdio.h>
-
-// This file is for checking that multiple sets of trace event categories can be
-// combined into the same program.
-
-PERFETTO_TRACK_EVENT_STATIC_STORAGE();
-
-namespace tracing_module {
-
-void InitializeCategories() {
-  TrackEvent::Register();
-}
-
-void EmitTrackEvents() {
-  TRACE_EVENT_BEGIN("cat1", "DisabledEventFromModule");
-  TRACE_EVENT_END("cat1");
-  TRACE_EVENT_BEGIN("cat4", "DisabledEventFromModule");
-  TRACE_EVENT_END("cat4");
-  TRACE_EVENT_BEGIN("cat9", "DisabledEventFromModule");
-  TRACE_EVENT_END("cat9");
-  TRACE_EVENT_BEGIN("foo", "FooEventFromModule");
-  TRACE_EVENT_END("foo");
-}
-
-perfetto::internal::TrackEventIncrementalState* GetIncrementalState() {
-  perfetto::internal::TrackEventIncrementalState* state = nullptr;
-  TrackEvent::Trace([&state](TrackEvent::TraceContext ctx) {
-    state = ctx.GetIncrementalState();
-  });
-  return state;
-}
-
-void FunctionWithOneTrackEvent() {
-  TRACE_EVENT_BEGIN("cat1", "DisabledEventFromModule");
-  // Simulates the non-tracing work of this function, which should take priority
-  // over the above trace event in terms of instruction scheduling.
-  puts("Hello");
-}
-
-void FunctionWithOneTrackEventWithTypedArgument() {
-  TRACE_EVENT_BEGIN("cat1", "EventWithArg",
-                    [](perfetto::TrackEventContext ctx) {
-                      auto log = ctx.track_event()->set_log_message();
-                      log->set_body_iid(0x42);
-                    });
-  // Simulates the non-tracing work of this function, which should take priority
-  // over the above trace event in terms of instruction scheduling.
-  puts("Hello");
-}
-
-}  // namespace tracing_module
diff --git a/src/tracing/test/tracing_module.h b/src/tracing/test/tracing_module.h
deleted file mode 100644
index 73ac7fd..0000000
--- a/src/tracing/test/tracing_module.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACING_TEST_TRACING_MODULE_H_
-#define SRC_TRACING_TEST_TRACING_MODULE_H_
-
-// Note: No non-client API header includes are allowed here.
-
-namespace perfetto {
-namespace internal {
-struct TrackEventIncrementalState;
-}  // namespace internal
-}  // namespace perfetto
-
-namespace tracing_module {
-
-void InitializeCategories();
-void EmitTrackEvents();
-void EmitTrackEvents2();
-perfetto::internal::TrackEventIncrementalState* GetIncrementalState();
-
-// These functions are used to check the instruction size overhead track events.
-void FunctionWithOneTrackEvent();
-void FunctionWithOneTrackEventWithTypedArgument();
-
-}  // namespace tracing_module
-
-#endif  // SRC_TRACING_TEST_TRACING_MODULE_H_
diff --git a/src/tracing/test/tracing_module2.cc b/src/tracing/test/tracing_module2.cc
deleted file mode 100644
index e907d71..0000000
--- a/src/tracing/test/tracing_module2.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2019 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 "src/tracing/test/tracing_module.h"
-
-#include "src/tracing/test/tracing_module_categories.h"
-
-#include <stdio.h>
-
-// This file checks that one track event category list can be shared by two
-// compilation units.
-
-namespace tracing_module {
-
-void EmitTrackEvents2() {
-  TRACE_EVENT_BEGIN("cat1", "DisabledEventFromModule2");
-  TRACE_EVENT_END("cat1");
-  TRACE_EVENT_BEGIN("cat4", "DisabledEventFromModule2");
-  TRACE_EVENT_END("cat4");
-  TRACE_EVENT_BEGIN("cat9", "DisabledEventFromModule2");
-  TRACE_EVENT_END("cat9");
-  TRACE_EVENT_BEGIN("foo", "FooEventFromModule2");
-  TRACE_EVENT_END("foo");
-}
-
-}  // namespace tracing_module
diff --git a/src/tracing/test/tracing_module_categories.h b/src/tracing/test/tracing_module_categories.h
deleted file mode 100644
index f776894..0000000
--- a/src/tracing/test/tracing_module_categories.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2019 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 SRC_TRACING_TEST_TRACING_MODULE_CATEGORIES_H_
-#define SRC_TRACING_TEST_TRACING_MODULE_CATEGORIES_H_
-
-// This header defines the tracing categories (and track event data source) used
-// in the external tracing test module. These categories are distinct from the
-// ones defined in api_integrationtest.cc, but events for both sets of
-// categories can be written to the same trace writer.
-
-#define PERFETTO_TRACK_EVENT_NAMESPACE tracing_module
-
-#include "perfetto/tracing.h"
-
-PERFETTO_DEFINE_CATEGORIES(PERFETTO_CATEGORY(cat1),
-                           PERFETTO_CATEGORY(cat2),
-                           PERFETTO_CATEGORY(cat3),
-                           PERFETTO_CATEGORY(cat4),
-                           PERFETTO_CATEGORY(cat5),
-                           PERFETTO_CATEGORY(cat6),
-                           PERFETTO_CATEGORY(cat7),
-                           PERFETTO_CATEGORY(cat8),
-                           PERFETTO_CATEGORY(cat9),
-                           PERFETTO_CATEGORY(foo));
-
-#endif  // SRC_TRACING_TEST_TRACING_MODULE_CATEGORIES_H_
diff --git a/src/tracing/trace_writer_base.cc b/src/tracing/trace_writer_base.cc
deleted file mode 100644
index b1e63c4..0000000
--- a/src/tracing/trace_writer_base.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/tracing/trace_writer_base.h"
-
-namespace perfetto {
-
-// This destructor needs to be defined in a dedicated translation unit and
-// cannot be merged together with the other ones in virtual_destructors.cc.
-// This is because trace_writer_base.h/cc  is part of a separate target
-// (src/public:common) that is linked also by other part of the codebase.
-
-TraceWriterBase::~TraceWriterBase() = default;
-
-}  // namespace perfetto
diff --git a/src/tracing/tracing.cc b/src/tracing/tracing.cc
deleted file mode 100644
index fc6a6964..0000000
--- a/src/tracing/tracing.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/tracing/tracing.h"
-#include "src/tracing/internal/tracing_muxer_impl.h"
-
-#include <condition_variable>
-#include <mutex>
-
-namespace perfetto {
-
-// static
-void Tracing::Initialize(const TracingInitArgs& args) {
-  // Make sure the headers and implementation files agree on the build config.
-  PERFETTO_CHECK(args.dcheck_is_on_ == PERFETTO_DCHECK_IS_ON());
-  internal::TracingMuxerImpl::InitializeInstance(args);
-}
-
-//  static
-std::unique_ptr<TracingSession> Tracing::NewTrace(BackendType backend) {
-  return static_cast<internal::TracingMuxerImpl*>(internal::TracingMuxer::Get())
-      ->CreateTracingSession(backend);
-}
-
-std::vector<char> TracingSession::ReadTraceBlocking() {
-  std::vector<char> raw_trace;
-  std::mutex mutex;
-  std::condition_variable cv;
-  bool all_read = false;
-
-  ReadTrace([&mutex, &raw_trace, &all_read, &cv](ReadTraceCallbackArgs cb) {
-    raw_trace.insert(raw_trace.end(), cb.data, cb.data + cb.size);
-    std::unique_lock<std::mutex> lock(mutex);
-    all_read = !cb.has_more;
-    if (all_read)
-      cv.notify_one();
-  });
-
-  {
-    std::unique_lock<std::mutex> lock(mutex);
-    cv.wait(lock, [&all_read] { return all_read; });
-  }
-  return raw_trace;
-}
-
-}  // namespace perfetto
diff --git a/src/tracing/track_event_category_registry.cc b/src/tracing/track_event_category_registry.cc
deleted file mode 100644
index e64fa3b..0000000
--- a/src/tracing/track_event_category_registry.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/tracing/track_event_category_registry.h"
-
-namespace perfetto {
-namespace internal {
-
-const TrackEventCategory* TrackEventCategoryRegistry::GetCategory(
-    size_t index) const {
-  PERFETTO_DCHECK(index < category_count_);
-  return &categories_[index];
-}
-
-void TrackEventCategoryRegistry::EnableCategoryForInstance(
-    size_t category_index,
-    uint32_t instance_index) const {
-  PERFETTO_DCHECK(instance_index < kMaxDataSourceInstances);
-  PERFETTO_DCHECK(category_index < category_count_);
-  // Matches the acquire_load in DataSource::Trace().
-  state_storage_[category_index].fetch_or(
-      static_cast<uint8_t>(1u << instance_index), std::memory_order_release);
-}
-
-void TrackEventCategoryRegistry::DisableCategoryForInstance(
-    size_t category_index,
-    uint32_t instance_index) const {
-  PERFETTO_DCHECK(instance_index < kMaxDataSourceInstances);
-  PERFETTO_DCHECK(category_index < category_count_);
-  // Matches the acquire_load in DataSource::Trace().
-  state_storage_[category_index].fetch_and(
-      static_cast<uint8_t>(~(1u << instance_index)), std::memory_order_release);
-}
-
-}  // namespace internal
-}  // namespace perfetto
diff --git a/src/tracing/track_event_context.cc b/src/tracing/track_event_context.cc
deleted file mode 100644
index 93f45cb..0000000
--- a/src/tracing/track_event_context.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/tracing/track_event_context.h"
-
-#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
-#include "protos/perfetto/trace/track_event/track_event.pbzero.h"
-
-namespace perfetto {
-
-TrackEventContext::TrackEventContext(
-    TrackEventContext::TracePacketHandle trace_packet,
-    internal::TrackEventIncrementalState* incremental_state)
-    : trace_packet_(std::move(trace_packet)),
-      track_event_(trace_packet_->set_track_event()),
-      incremental_state_(incremental_state) {}
-
-TrackEventContext::~TrackEventContext() {
-  // When the track event is finalized (i.e., the context is destroyed), we
-  // should flush any newly seen interned data to the trace. The data has
-  // earlier been written to a heap allocated protobuf message
-  // (|serialized_interned_data|). Here we just need to flush it to the main
-  // trace.
-  auto& serialized_interned_data = incremental_state_->serialized_interned_data;
-  if (PERFETTO_LIKELY(serialized_interned_data.empty()))
-    return;
-
-  auto ranges = serialized_interned_data.GetRanges();
-  trace_packet_->AppendScatteredBytes(
-      perfetto::protos::pbzero::TracePacket::kInternedDataFieldNumber,
-      &ranges[0], ranges.size());
-
-  // Reset the message but keep one buffer allocated for future use.
-  serialized_interned_data.Reset();
-}
-
-}  // namespace perfetto
diff --git a/src/tracing/virtual_destructors.cc b/src/tracing/virtual_destructors.cc
deleted file mode 100644
index d548c8e..0000000
--- a/src/tracing/virtual_destructors.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/tracing/internal/tracing_tls.h"
-#include "perfetto/tracing/tracing.h"
-#include "perfetto/tracing/tracing_backend.h"
-
-// This translation unit contains the definitions for the destructor of pure
-// virtual interfaces for the src/public:public target. The alternative would be
-// introducing a one-liner .cc file for each pure virtual interface, which is
-// overkill. This is for compliance with -Wweak-vtables.
-
-namespace perfetto {
-namespace internal {
-
-TracingTLS::~TracingTLS() = default;
-
-}  // namespace internal
-
-TracingBackend::~TracingBackend() = default;
-TracingSession::~TracingSession() = default;
-
-}  // namespace perfetto
diff --git a/test/BUILD.gn b/test/BUILD.gn
index b9e6654..44caac8 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -12,9 +12,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("//build_overrides/build.gni")
 import("../gn/fuzzer.gni")
 import("../gn/perfetto.gni")
+import("//build_overrides/build.gni")
 
 source_set("end_to_end_integrationtests") {
   testonly = true
@@ -23,12 +23,8 @@
     ":task_runner_thread_delegates",
     ":test_helper",
     "../gn:default_deps",
-    "../gn:gtest_and_gmock",
-    "../include/perfetto/ext/traced",
-    "../include/perfetto/protozero",
-    "../protos/perfetto/config:cpp",
-    "../protos/perfetto/config:zero",
-    "../protos/perfetto/config/power:zero",
+    "../gn:gtest_deps",
+    "../include/perfetto/traced",
     "../protos/perfetto/trace:lite",
     "../protos/perfetto/trace:zero",
     "../src/base:base",
@@ -38,6 +34,9 @@
   sources = [
     "end_to_end_integrationtest.cc",
   ]
+  if (is_android && (perfetto_build_standalone || perfetto_build_with_android)) {
+    deps += [ "../src/base:android_task_runner" ]
+  }
   if (start_daemons_for_testing) {
     cflags = [ "-DPERFETTO_START_DAEMONS_FOR_TESTING" ]
 
@@ -51,17 +50,6 @@
   }
 }
 
-executable("client_api_example") {
-  sources = [
-    "client_api_example.cc",
-  ]
-  deps = [
-    "..:libperfetto_client_experimental",
-    "../gn:default_deps",
-    "../protos/perfetto/trace:zero",
-  ]
-}
-
 perfetto_fuzzer_test("end_to_end_shared_memory_fuzzer") {
   sources = [
     "end_to_end_shared_memory_fuzzer.cc",
@@ -72,7 +60,7 @@
     ":task_runner_thread_delegates",
     ":test_helper",
     "../gn:default_deps",
-    "../protos/perfetto/trace:zero",
+    "../protos/perfetto/trace:lite",
     "../src/base:test_support",
     "../src/protozero",
     "../src/tracing",
@@ -80,19 +68,6 @@
   ]
 }
 
-perfetto_fuzzer_test("producer_socket_fuzzer") {
-  sources = [
-    "producer_socket_fuzzer.cc",
-  ]
-  testonly = true
-  deps = [
-    ":test_helper",
-    "../gn:default_deps",
-    "../protos/perfetto/trace:zero",
-    "../src/base:test_support",
-  ]
-}
-
 source_set("task_runner_thread") {
   testonly = true
   deps = [
@@ -111,8 +86,7 @@
   deps = [
     ":task_runner_thread",
     "../gn:default_deps",
-    "../include/perfetto/ext/traced",
-    "../protos/perfetto/config:cpp",
+    "../include/perfetto/traced",
     "../src/base:test_support",
     "../src/traced/probes:probes_src",
     "../src/tracing:ipc",
@@ -120,7 +94,6 @@
   sources = [
     "fake_producer.cc",
     "fake_producer.h",
-    "task_runner_thread_delegates.cc",
     "task_runner_thread_delegates.h",
   ]
 }
@@ -134,7 +107,7 @@
     ":task_runner_thread",
     ":task_runner_thread_delegates",
     "../gn:default_deps",
-    "../include/perfetto/ext/traced",
+    "../include/perfetto/traced",
     "../protos/perfetto/trace:lite",
     "../protos/perfetto/trace:zero",
     "../src/base:test_support",
@@ -148,18 +121,17 @@
   }
 }
 
-if (enable_perfetto_benchmarks) {
+if (perfetto_build_standalone) {
   source_set("end_to_end_benchmarks") {
     testonly = true
     deps = [
       ":task_runner_thread",
       ":task_runner_thread_delegates",
       ":test_helper",
-      "../gn:benchmark",
-      "../gn:default_deps",
-      "../gn:gtest_and_gmock",
-      "../include/perfetto/ext/traced",
-      "../protos/perfetto/config:cpp",
+      "../../gn:default_deps",
+      "../buildtools:benchmark",
+      "../gn:gtest_deps",
+      "../include/perfetto/traced",
       "../protos/perfetto/trace:lite",
       "../protos/perfetto/trace:zero",
       "../src/base:test_support",
@@ -167,6 +139,9 @@
     sources = [
       "end_to_end_benchmark.cc",
     ]
+    if (is_android) {
+      deps += [ "../src/base:android_task_runner" ]
+    }
     if (start_daemons_for_testing) {
       cflags = [ "-DPERFETTO_START_DAEMONS_FOR_TESTING" ]
     }
@@ -175,11 +150,11 @@
   source_set("benchmark_main") {
     testonly = true
     deps = [
-      "../gn:benchmark",
-      "../gn:default_deps",
+      "../../gn:default_deps",
+      "../buildtools:benchmark",
     ]
     sources = [
       "benchmark_main.cc",
     ]
   }
-}  # if (enable_perfetto_benchmarks)
+}
diff --git a/test/benchmark_main.cc b/test/benchmark_main.cc
index e410e52..f904cfc 100644
--- a/test/benchmark_main.cc
+++ b/test/benchmark_main.cc
@@ -12,6 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <benchmark/benchmark.h>
+#include "benchmark/benchmark.h"
 
 BENCHMARK_MAIN();
diff --git a/test/ci/android_tests.sh b/test/ci/android_tests.sh
deleted file mode 100755
index 89d27cf..0000000
--- a/test/ci/android_tests.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2019 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.
-
-INSTALL_BUILD_DEPS_ARGS=""  # Run without args, without --no-android.
-source $(dirname ${BASH_SOURCE[0]})/common.sh
-
-# Run the emulator earlier so by the time we build it's booted.
-# tools/run_android_test will perform a wait-for-device. This is just an
-# optimization to remove bubbles in the pipeline.
-tools/run_android_emulator --pid /tmp/emulator.pid -v &
-
-tools/gn gen ${OUT_PATH} --args="${PERFETTO_TEST_GN_ARGS}" --check
-tools/ninja -C ${OUT_PATH} ${PERFETTO_TEST_NINJA_ARGS}
-
-# run_android_test takes long time to push the test_data files. Do that only
-# once and avoid re-pushing for each type of test.
-tools/run_android_test -n ${OUT_PATH} perfetto_unittests
-tools/run_android_test -n -x ${OUT_PATH} perfetto_integrationtests
-tools/run_android_test -n -x --env BENCHMARK_FUNCTIONAL_TEST_ONLY=true \
-  ${OUT_PATH} perfetto_benchmarks
-
-test -f /tmp/emulator.pid && kill -9 $(cat /tmp/emulator.pid); true
diff --git a/test/ci/bazel_tests.sh b/test/ci/bazel_tests.sh
deleted file mode 100755
index 2e8b447..0000000
--- a/test/ci/bazel_tests.sh
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2019 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.
-
-INSTALL_BUILD_DEPS_ARGS="--no-android"
-source $(dirname ${BASH_SOURCE[0]})/common.sh
-
-bazel build //:all --verbose_failures
-
-# Smoke test that processes run without crashing.
-./bazel-bin/traced &
-./bazel-bin/traced_probes &
-sleep 5
-TRACE=/ci/artifacts/bazel.trace
-./bazel-bin/perfetto -c :test -o $TRACE
-kill $(jobs -p)
-./bazel-bin/trace_processor_shell -q <(echo 'select count(1) from sched') $TRACE
-
-# Check the amalgamated build here to avoid slowing down all the Linux bots.
-tools/test_gen_amalgamated.py
\ No newline at end of file
diff --git a/test/ci/common.sh b/test/ci/common.sh
deleted file mode 100644
index a798448..0000000
--- a/test/ci/common.sh
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2019 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.
-
-set -eux -o pipefail
-
-cd $(dirname ${BASH_SOURCE[0]})/../..
-OUT_PATH="out/dist"
-
-if [[ -e buildtools/clang/bin/llvm-symbolizer ]]; then
-  export ASAN_SYMBOLIZER_PATH="buildtools/clang/bin/llvm-symbolizer"
-  export MSAN_SYMBOLIZER_PATH="buildtools/clang/bin/llvm-symbolizer"
-fi
-
-tools/install-build-deps $INSTALL_BUILD_DEPS_ARGS
-
-# Performs checks on generated protos and build files.
-tools/gn gen out/tmp.protoc --args="is_debug=false cc_wrapper=\"ccache\""
-tools/gen_all --check-only out/tmp.protoc
-rm -rf out/tmp.protoc
diff --git a/test/ci/fuzzer_tests.sh b/test/ci/fuzzer_tests.sh
deleted file mode 100755
index 9ef9738..0000000
--- a/test/ci/fuzzer_tests.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2019 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.
-
-INSTALL_BUILD_DEPS_ARGS="--no-android"
-source $(dirname ${BASH_SOURCE[0]})/common.sh
-
-tools/gn gen ${OUT_PATH} --args="${PERFETTO_TEST_GN_ARGS}" --check
-tools/ninja -C ${OUT_PATH} ${PERFETTO_TEST_NINJA_ARGS} fuzzers
-
-# Run a single iteration each to make sure they are not crashing.
-for fuzzer in $(find ${OUT_PATH} -name '*_fuzzer' -executable); do
-  $fuzzer -runs=1
-done
diff --git a/test/ci/linux_tests.sh b/test/ci/linux_tests.sh
deleted file mode 100755
index 11f60a0..0000000
--- a/test/ci/linux_tests.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2019 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.
-
-INSTALL_BUILD_DEPS_ARGS="--no-android"
-source $(dirname ${BASH_SOURCE[0]})/common.sh
-
-tools/gn gen ${OUT_PATH} --args="${PERFETTO_TEST_GN_ARGS}" --check
-tools/ninja -C ${OUT_PATH} ${PERFETTO_TEST_NINJA_ARGS}
-
-# Run the tests
-
-${OUT_PATH}/perfetto_unittests
-${OUT_PATH}/perfetto_integrationtests
-
-# If this is a split host+target build, use the trace_processoer_shell binary
-# from the host directory. In some cases (e.g. lsan x86 builds) the host binary
-# that is copied into the target directory (OUT_PATH) cannot run because depends
-# on libc++.so within the same folder (which is built using target bitness,
-# not host bitness).
-TP_SHELL=${OUT_PATH}/gcc_like_host/trace_processor_shell
-if [ ! -f ${TP_SHELL} ]; then
-  TP_SHELL=${OUT_PATH}/trace_processor_shell
-fi
-
-mkdir -p /ci/artifacts/perf
-
-tools/diff_test_trace_processor.py \
-  --test-type=queries \
-  --perf-file=/ci/artifacts/perf/tp-perf-queries.json \
-  ${TP_SHELL}
-
-tools/diff_test_trace_processor.py \
-  --test-type=metrics \
-  --perf-file=/ci/artifacts/perf/tp-perf-metrics.json \
-  ${TP_SHELL}
-
-# Don't run benchmarks under sanitizers or debug, too slow and pointless.
-USING_SANITIZER="$(tools/gn args --short --list=using_sanitizer ${OUT_PATH} | awk '{print $3}')"
-IS_DEBUG="$(tools/gn args --short --list=is_debug ${OUT_PATH} | awk '{print $3}')"
-if [ "$USING_SANITIZER" == "false" ] && [ "$IS_DEBUG" == "false" ]; then
-  BENCHMARK_FUNCTIONAL_TEST_ONLY=true ${OUT_PATH}/perfetto_benchmarks
-fi
diff --git a/test/ci/ui_tests.sh b/test/ci/ui_tests.sh
deleted file mode 100755
index 5476840..0000000
--- a/test/ci/ui_tests.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2019 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.
-
-INSTALL_BUILD_DEPS_ARGS="--no-android --ui"
-source $(dirname ${BASH_SOURCE[0]})/common.sh
-
-tools/gn gen ${OUT_PATH} --args="${PERFETTO_TEST_GN_ARGS}" --check
-tools/ninja -C ${OUT_PATH} ${PERFETTO_TEST_NINJA_ARGS} ui
-
-cp -a ${OUT_PATH}/ui /ci/artifacts/
-
-# Run the tests
-${OUT_PATH}/ui_unittests --ci
diff --git a/test/client_api_example.cc b/test/client_api_example.cc
deleted file mode 100644
index 1448721..0000000
--- a/test/client_api_example.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/tracing.h"
-
-#include <thread>
-
-#include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-// Deliberately not pulling any non-public perfetto header to spot accidental
-// header public -> non-public dependency while building this file.
-
-namespace {
-
-class MyDataSource : public perfetto::DataSource<MyDataSource> {
- public:
-  void OnSetup(const SetupArgs& args) override {
-    // This can be used to access the domain-specific DataSourceConfig, via
-    // args.config->xxx_config_raw().
-    PERFETTO_ILOG("OnSetup called, name: %s", args.config->name().c_str());
-  }
-
-  void OnStart(const StartArgs&) override { PERFETTO_ILOG("OnStart called"); }
-
-  void OnStop(const StopArgs& args) override {
-    PERFETTO_ILOG("OnStop called");
-
-    // Demonstrates the ability to defer stop and handle it asynchronously,
-    // writing data at the very end of the trace.
-    auto stop_closure = args.HandleStopAsynchronously();
-    std::thread another_thread([stop_closure] {
-      sleep(2);
-      MyDataSource::Trace([](MyDataSource::TraceContext ctx) {
-        PERFETTO_LOG("Tracing lambda called while stopping");
-        auto packet = ctx.NewTracePacket();
-        packet->set_for_testing()->set_str("event recorded while stopping");
-        packet->Finalize();  //  Required because of the Flush below.
-
-        // This explicit Flush() is required because the service doesn't issue
-        // any other flush requests after the Stop() signal.
-        ctx.Flush();
-      });
-      stop_closure();
-    });
-    another_thread.detach();
-  }
-};
-
-}  // namespace
-
-PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(MyDataSource);
-
-int main() {
-  perfetto::TracingInitArgs args;
-  args.backends = perfetto::kSystemBackend;
-  perfetto::Tracing::Initialize(args);
-
-  // DataSourceDescriptor can be used to advertise domain-specific features.
-  perfetto::DataSourceDescriptor dsd;
-  dsd.set_name("com.example.mytrace");
-  MyDataSource::Register(dsd);
-
-  for (;;) {
-    MyDataSource::Trace([](MyDataSource::TraceContext ctx) {
-      PERFETTO_LOG("Tracing lambda called");
-      auto packet = ctx.NewTracePacket();
-      packet->set_timestamp(42);
-      packet->set_for_testing()->set_str("event 1");
-    });
-    sleep(1);
-  }
-}
diff --git a/test/configs/BUILD.gn b/test/configs/BUILD.gn
index 2ce30f6..9fbbea7 100644
--- a/test/configs/BUILD.gn
+++ b/test/configs/BUILD.gn
@@ -14,48 +14,37 @@
 
 import("../../gn/perfetto.gni")
 
-protoc_target = "../../gn:protoc($host_toolchain)"
+if (perfetto_build_standalone) {
+  action_foreach("configs") {
+    testonly = true
+    script = "$root_out_dir/protoc_helper"
 
-action_foreach("configs") {
-  testonly = true
-  script = "../../tools/protoc_helper.py"
+    deps = [
+      "../../tools:protoc_helper",
+    ]
 
-  deps = [
-    "../../protos/perfetto/config:merged_config",
-    "../../protos/perfetto/trace:merged_trace",
-    protoc_target,
-  ]
+    sources = [
+      "android_log.cfg",
+      "atrace.cfg",
+      "background.cfg",
+      "ftrace.cfg",
+      "ftrace_largebuffer.cfg",
+      "heapprofd.cfg",
+      "long_trace.cfg",
+      "processes.cfg",
+      "summary.cfg",
+      "sys_stats.cfg",
+    ]
 
-  sources = [
-    "android_log.cfg",
-    "atrace.cfg",
-    "background.cfg",
-    "bad_config.cfg",
-    "camera.cfg",
-    "client_api.cfg",
-    "ftrace.cfg",
-    "ftrace_largebuffer.cfg",
-    "heapprofd.cfg",
-    "long_trace.cfg",
-    "processes.cfg",
-    "summary.cfg",
-    "sys_stats.cfg",
-  ]
+    outputs = [
+      "$root_out_dir/{{source_file_part}}.protobuf",
+    ]
 
-  outputs = [
-    "$root_out_dir/{{source_file_part}}.protobuf",
-  ]
-
-  # Retrieves the path where protoc is built relative to the dir where commands
-  # are ran (root_build_dir == out/xxx). protoc_rel_dir ends up being "." for
-  # pure host build and "gcc_like_host" for android builds
-  protoc_out_dir = get_label_info(protoc_target, "root_out_dir")
-  protoc_rel_dir = rebase_path(protoc_out_dir, root_build_dir)
-
-  args = [
-    "encode",
-    "--protoc=$protoc_rel_dir/protoc",
-    "--input={{source}}",
-    "--output={{source_file_part}}.protobuf",
-  ]
+    args = [
+      "encode",
+      "--root=" + rebase_path(perfetto_root_path, ""),
+      "--input={{source}}",
+      "--output={{source_file_part}}.protobuf",
+    ]
+  }
 }
diff --git a/test/configs/bad_config.cfg b/test/configs/bad_config.cfg
deleted file mode 100644
index c23f976..0000000
--- a/test/configs/bad_config.cfg
+++ /dev/null
@@ -1,28 +0,0 @@
-# The trigger_timeout_ms on this config is much too long and so the config
-# should be rejected by the service. This is useful for testing bugs that
-# occur when the service rejects a config.
-
-buffers {
-  size_kb: 65536
-  fill_policy: RING_BUFFER
-}
-
-data_sources {
-  config {
-    name: "linux.ftrace"
-    target_buffer: 0
-    ftrace_config {
-      ftrace_events: "sched_switch"
-    }
-  }
-}
-
-
-trigger_config {
-  trigger_mode: START_TRACING
-  triggers: {
-    name: "foo"
-  }
-  trigger_timeout_ms: 900000000
-}
-
diff --git a/test/configs/camera.cfg b/test/configs/camera.cfg
deleted file mode 100644
index 8677434..0000000
--- a/test/configs/camera.cfg
+++ /dev/null
@@ -1,63 +0,0 @@
-buffers {
-  size_kb: 102400
-  fill_policy: RING_BUFFER
-}
-
-data_sources {
-  config {
-    name: "linux.ftrace"
-    target_buffer: 0
-    ftrace_config {
-      # Scheduling information & process tracking. Useful for:
-      # - what is happening on each CPU at each moment
-      # - why a thread was descheduled
-      # - parent/child relationships between processes and threads.
-      ftrace_events: "sched/sched_switch"
-      ftrace_events: "power/suspend_resume"
-      ftrace_events: "sched/sched_process_exit"
-      ftrace_events: "sched/sched_process_free"
-      ftrace_events: "task/task_newtask"
-      ftrace_events: "task/task_rename"
-
-      # Wakeup info. Allows you to compute how long a task was
-      # blocked due to CPU contention.
-      ftrace_events: "sched/sched_wakeup"
-
-      # os.Trace markers:
-      ftrace_events: "ftrace/print"
-
-      # Atrace events from com.google.android.GoogleCamera
-      atrace_apps: "com.google.android.GoogleCamera"
-
-      # LMK
-      atrace_apps: "lmkd"
-      ftrace_events: "lowmemorykiller/lowmemory_kill"
-      ftrace_events: "oom/oom_score_adj_update"
-
-      # Atrace camera category:
-      atrace_categories: "camera"
-      # Atrace activity manager:
-      atrace_categories: "am"
-      # Atrace system_server:
-      atrace_categories: "ss"
-
-      # RSS and ION buffer events:
-      ftrace_events: "kmem/rss_stat"
-      ftrace_events: "kmem/mm_event"
-      ftrace_events: "kmem/ion_heap_grow"
-      ftrace_events: "kmem/ion_heap_shrink"
-    }
-  }
-}
-
-data_sources: {
-    config {
-        name: "linux.process_stats"
-        target_buffer: 0
-        process_stats_config {
-            scan_all_processes_on_start: true
-        }
-    }
-}
-
-duration_ms: 10000
diff --git a/test/configs/client_api.cfg b/test/configs/client_api.cfg
deleted file mode 100644
index c610ab8..0000000
--- a/test/configs/client_api.cfg
+++ /dev/null
@@ -1,12 +0,0 @@
-# This config is for trying out test/client_api_example.cc .
-
-buffers {
-  size_kb: 1024
-  fill_policy: RING_BUFFER
-}
-
-data_sources {
-  config {
-    name: "com.example.mytrace"
-  }
-}
diff --git a/test/configs/ftrace.cfg b/test/configs/ftrace.cfg
index 27b80f5..a092af3 100644
--- a/test/configs/ftrace.cfg
+++ b/test/configs/ftrace.cfg
@@ -1,5 +1,5 @@
 buffers {
-  size_kb: 65536
+  size_kb: 100024
   fill_policy: RING_BUFFER
 }
 
@@ -8,8 +8,8 @@
     name: "linux.ftrace"
     target_buffer: 0
     ftrace_config {
-      buffer_size_kb: 8192
-      drain_period_ms: 500
+      buffer_size_kb: 512 # 4 (page size) * 128
+      drain_period_ms: 200
       ftrace_events: "binder_lock"
       ftrace_events: "binder_locked"
       ftrace_events: "binder_set_priority"
@@ -280,13 +280,6 @@
   }
 }
 
-data_sources {
-  config {
-    name: "perfetto.metatrace"
-    target_buffer: 0
-  }
-}
-
 producers {
   producer_name: "perfetto.traced_probes"
   shm_size_kb: 4096
diff --git a/test/configs/java_hprof.cfg b/test/configs/java_hprof.cfg
deleted file mode 100644
index 652412c..0000000
--- a/test/configs/java_hprof.cfg
+++ /dev/null
@@ -1,17 +0,0 @@
-buffers {
-  size_kb: 100024
-  fill_policy: RING_BUFFER
-}
-
-data_sources {
-  config {
-    name: "android.java_hprof"
-    java_hprof_config {
-      process_cmdline: "com.google.android.inputmethod.latin"
-    }
-  }
-}
-
-duration_ms: 60000
-write_into_file: true
-
diff --git a/test/cts/Android.bp b/test/cts/Android.bp
index 69803de..6340440 100644
--- a/test/cts/Android.bp
+++ b/test/cts/Android.bp
@@ -4,17 +4,11 @@
     "device_feature_test_cts.cc",
     "end_to_end_integrationtest_cts.cc",
     "heapprofd_test_cts.cc",
-    "heapprofd_java_test_cts.cc",
-    "utils.cc",
-    ":perfetto_protos_perfetto_config_cpp_gen",
-  ],
-  generated_headers: [
-    "perfetto_protos_perfetto_config_cpp_gen_headers",
   ],
   static_libs: [
     "libgmock",
     "libprotobuf-cpp-lite",
-    "libperfetto_client_experimental",
+    "perfetto_src_tracing_ipc",
     "perfetto_trace_protos",
   ],
   shared_libs: [
@@ -39,7 +33,7 @@
     },
   },
   stl: "libc++_static",
-  defaults: [
-    "perfetto_defaults",
+  cflags: [
+    "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
 }
diff --git a/test/cts/AndroidTest.xml b/test/cts/AndroidTest.xml
index d34d264..a6deef2 100644
--- a/test/cts/AndroidTest.xml
+++ b/test/cts/AndroidTest.xml
@@ -24,7 +24,6 @@
         <option name="test-file-name" value="CtsPerfettoProducerApp.apk" />
         <option name="test-file-name" value="CtsPerfettoDebuggableApp.apk" />
         <option name="test-file-name" value="CtsPerfettoReleaseApp.apk" />
-        <option name="test-file-name" value="CtsPerfettoProfileableApp.apk" />
     </target_preparer>
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
         <option name="cleanup" value="true" />
diff --git a/test/cts/README.md b/test/cts/README.md
index 02b5bdb..27670de 100644
--- a/test/cts/README.md
+++ b/test/cts/README.md
@@ -1,4 +1,5 @@
-This directory contains the CTS tests for the Perfetto library.
+This directory contains the CTS tests for the Perfetto library (at the time of
+writing - a single native GTest suite, and several helper apps).
 
 # Background
 For information about what CTS is, please go to
@@ -6,8 +7,7 @@
 on the purpose of CTS and how to run these tests.
 
 # Test contents
-The single GTest target (CtsPerfettoTestCases) contains the following notable
-test suites:
+The single GTest target contains the following notable test suites:
 * PerfettoCtsTest - verifies that any Android app can operate as a perfetto
   producer.
 * HeapprofdCtsTest - verifies that Android apps can be heap-profiled, and that
@@ -24,8 +24,8 @@
 
 The mock producer is an Android app with a thin Java wrapping around the C++
 library interfaced using JNI. The purpose of this target is to ensure that the
-TraceProto received from the consumer is valid and then push some fake data.
-This ensures that any arbitrary app can push data to the Perfetto socket which
+TraceProto received from the consumer is valid and and then push some fake data.
+This ensures that any arbitary app can push data to the Perfetto socket which
 can then be decoded by the GTest consumer.
 
 ## HeapprofdCtsTest
diff --git a/test/cts/device_feature_test_cts.cc b/test/cts/device_feature_test_cts.cc
index c91fe49..3664476 100644
--- a/test/cts/device_feature_test_cts.cc
+++ b/test/cts/device_feature_test_cts.cc
@@ -16,7 +16,7 @@
 
 #include <sys/sysinfo.h>
 
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 
diff --git a/test/cts/end_to_end_integrationtest_cts.cc b/test/cts/end_to_end_integrationtest_cts.cc
index e174bb4..d40d92f 100644
--- a/test/cts/end_to_end_integrationtest_cts.cc
+++ b/test/cts/end_to_end_integrationtest_cts.cc
@@ -14,20 +14,19 @@
  * limitations under the License.
  */
 
-#include <sys/system_properties.h>
 #include <random>
-#include "test/gtest_and_gmock.h"
+#include <sys/system_properties.h>
 
-#include "perfetto/ext/traced/traced.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/tracing/core/data_source_config.h"
+#include "gtest/gtest.h"
+#include "perfetto/trace/test_event.pbzero.h"
+#include "perfetto/trace/trace_packet.pb.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/traced/traced.h"
+#include "perfetto/tracing/core/trace_packet.h"
 #include "src/base/test/test_task_runner.h"
 #include "test/test_helper.h"
 
-#include "protos/perfetto/config/test_config.gen.h"
-#include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/trace_packet.pb.h"
 
 namespace perfetto {
 
diff --git a/test/cts/heapprofd_java_test_cts.cc b/test/cts/heapprofd_java_test_cts.cc
deleted file mode 100644
index 8ac3760..0000000
--- a/test/cts/heapprofd_java_test_cts.cc
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2019 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 <stdlib.h>
-#include <sys/system_properties.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/tracing/core/data_source_config.h"
-#include "src/base/test/test_task_runner.h"
-#include "test/cts/utils.h"
-#include "test/gtest_and_gmock.h"
-#include "test/test_helper.h"
-
-#include "protos/perfetto/config/profiling/java_hprof_config.pb.h"
-
-namespace perfetto {
-namespace {
-
-std::vector<protos::TracePacket> ProfileRuntime(std::string app_name) {
-  base::TestTaskRunner task_runner;
-
-  // (re)start the target app's main activity
-  if (IsAppRunning(app_name)) {
-    StopApp(app_name, "old.app.stopped", &task_runner);
-    task_runner.RunUntilCheckpoint("old.app.stopped", 1000 /*ms*/);
-  }
-  StartAppActivity(app_name, "target.app.running", &task_runner,
-                   /*delay_ms=*/100);
-  task_runner.RunUntilCheckpoint("target.app.running", 1000 /*ms*/);
-  // TODO(b/143467832): Remove this workaround.
-  // If we try to dump too early in app initialization, we sometimes deadlock.
-  sleep(1);
-
-  // set up tracing
-  TestHelper helper(&task_runner);
-  helper.ConnectConsumer();
-  helper.WaitForConsumerConnect();
-
-  TraceConfig trace_config;
-  trace_config.add_buffers()->set_size_kb(20 * 1024);
-  trace_config.set_duration_ms(6000);
-
-  auto* ds_config = trace_config.add_data_sources()->mutable_config();
-  ds_config->set_name("android.java_hprof");
-  ds_config->set_target_buffer(0);
-
-  protos::JavaHprofConfig java_hprof_config;
-  java_hprof_config.add_process_cmdline(app_name.c_str());
-  ds_config->set_java_hprof_config_raw(java_hprof_config.SerializeAsString());
-
-  // start tracing
-  helper.StartTracing(trace_config);
-  helper.WaitForTracingDisabled(10000 /*ms*/);
-  helper.ReadData();
-  helper.WaitForReadData();
-  StopApp(app_name, "new.app.stopped", &task_runner);
-  task_runner.RunUntilCheckpoint("new.app.stopped", 1000 /*ms*/);
-  return helper.trace();
-}
-
-void AssertGraphPresent(std::vector<protos::TracePacket> packets) {
-  ASSERT_GT(packets.size(), 0);
-
-  size_t objects = 0;
-  size_t roots = 0;
-  for (const auto& packet : packets) {
-    objects += packet.heap_graph().objects_size();
-    roots += packet.heap_graph().roots_size();
-  }
-  ASSERT_GT(objects, 0);
-  ASSERT_GT(roots, 0);
-}
-
-void AssertNoProfileContents(std::vector<protos::TracePacket> packets) {
-  // If profile packets are present, they must be empty.
-  for (const auto& packet : packets) {
-    ASSERT_EQ(packet.heap_graph().roots_size(), 0);
-    ASSERT_EQ(packet.heap_graph().objects_size(), 0);
-    ASSERT_EQ(packet.heap_graph().type_names_size(), 0);
-    ASSERT_EQ(packet.heap_graph().field_names_size(), 0);
-  }
-}
-
-TEST(HeapprofdJavaCtsTest, DebuggableAppRuntime) {
-  std::string app_name = "android.perfetto.cts.app.debuggable";
-  const auto& packets = ProfileRuntime(app_name);
-  AssertGraphPresent(packets);
-}
-
-TEST(HeapprofdJavaCtsTest, ProfileableAppRuntime) {
-  std::string app_name = "android.perfetto.cts.app.profileable";
-  const auto& packets = ProfileRuntime(app_name);
-  AssertGraphPresent(packets);
-}
-
-TEST(HeapprofdJavaCtsTest, ReleaseAppRuntime) {
-  std::string app_name = "android.perfetto.cts.app.release";
-  const auto& packets = ProfileRuntime(app_name);
-
-  if (IsDebuggableBuild())
-    AssertGraphPresent(packets);
-  else
-    AssertNoProfileContents(packets);
-}
-
-}  // namespace
-}  // namespace perfetto
diff --git a/test/cts/heapprofd_test_apps/Android.bp b/test/cts/heapprofd_test_apps/Android.bp
index bc2b323..e759410 100644
--- a/test/cts/heapprofd_test_apps/Android.bp
+++ b/test/cts/heapprofd_test_apps/Android.bp
@@ -51,23 +51,3 @@
         "libnativehelper_compat_libc++",
     ],
 }
-
-android_test_helper_app {
-    name: "CtsPerfettoProfileableApp",
-    // tag this module as a cts test artifact
-    test_suites: [
-        "cts",
-        "vts",
-        "general-tests",
-    ],
-
-    manifest: "AndroidManifest_profileable.xml",
-
-    compile_multilib: "both",
-    srcs: ["src/**/*.java"],
-    sdk_version: "current",
-    jni_libs: [
-        "libperfettocts_heapprofdtarget",
-        "libnativehelper_compat_libc++",
-    ],
-}
diff --git a/test/cts/heapprofd_test_apps/AndroidManifest_profileable.xml b/test/cts/heapprofd_test_apps/AndroidManifest_profileable.xml
deleted file mode 100755
index 99ceda2..0000000
--- a/test/cts/heapprofd_test_apps/AndroidManifest_profileable.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2019 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.perfetto.cts.app.profileable">
-
-    <application>
-        <profileable android:shell="true"/>
-        <activity
-          android:name="android.perfetto.cts.app.MainActivity"
-          android:exported="false">
-        </activity>
-        <activity-alias
-          android:name="android.perfetto.cts.app.profileable.MainActivity"
-          android:targetActivity="android.perfetto.cts.app.MainActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity-alias>
-    </application>
-</manifest>
-
diff --git a/test/cts/heapprofd_test_apps/jni/Android.bp b/test/cts/heapprofd_test_apps/jni/Android.bp
index de090d2..a518779 100644
--- a/test/cts/heapprofd_test_apps/jni/Android.bp
+++ b/test/cts/heapprofd_test_apps/jni/Android.bp
@@ -28,7 +28,4 @@
   ],
   compile_multilib: "both",
   stl: "libc++_static",
-  defaults: [
-    "perfetto_defaults",
-  ],
 }
diff --git a/test/cts/heapprofd_test_cts.cc b/test/cts/heapprofd_test_cts.cc
index acb92c3..7ef6358 100644
--- a/test/cts/heapprofd_test_cts.cc
+++ b/test/cts/heapprofd_test_cts.cc
@@ -16,18 +16,15 @@
  */
 
 #include <stdlib.h>
-#include <sys/system_properties.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
-#include "perfetto/base/logging.h"
-#include "perfetto/tracing/core/data_source_config.h"
-#include "src/base/test/test_task_runner.h"
-#include "test/cts/utils.h"
-#include "test/gtest_and_gmock.h"
-#include "test/test_helper.h"
+#include <sys/system_properties.h>
 
-#include "protos/perfetto/config/profiling/heapprofd_config.pb.h"
+#include "gtest/gtest.h"
+#include "perfetto/base/logging.h"
+#include "src/base/test/test_task_runner.h"
+#include "test/test_helper.h"
 
 namespace perfetto {
 namespace {
@@ -41,6 +38,76 @@
 static_assert(kExpectedIndividualAllocSz > kTestSamplingInterval,
               "kTestSamplingInterval invalid");
 
+bool IsDebuggableBuild() {
+  char buf[PROP_VALUE_MAX + 1] = {};
+  int ret = __system_property_get("ro.debuggable", buf);
+  PERFETTO_CHECK(ret >= 0);
+  std::string debuggable(buf);
+  if (debuggable == "1")
+    return true;
+  return false;
+}
+
+// note: cannot use gtest macros due to return type
+bool IsAppRunning(const std::string& name) {
+  std::string cmd = "pgrep -f " + name;
+  int retcode = system(cmd.c_str());
+  PERFETTO_CHECK(retcode >= 0);
+  int exit_status = WEXITSTATUS(retcode);
+  if (exit_status == 0)
+    return true;
+  if (exit_status == 1)
+    return false;
+  PERFETTO_FATAL("unexpected exit status from system(pgrep): %d", exit_status);
+}
+
+// invokes |callback| once the target app is in the desired state
+void PollRunState(bool desired_run_state,
+                  base::TestTaskRunner* task_runner,
+                  const std::string& name,
+                  std::function<void()> callback) {
+  bool app_running = IsAppRunning(name);
+  if (app_running == desired_run_state) {
+    callback();
+    return;
+  }
+  task_runner->PostTask([desired_run_state, task_runner, name, callback] {
+    PollRunState(desired_run_state, task_runner, name, std::move(callback));
+  });
+}
+
+void StartAppActivity(const std::string& app_name,
+                      const std::string& checkpoint_name,
+                      base::TestTaskRunner* task_runner,
+                      int delay_ms = 1) {
+  std::string start_cmd = "am start " + app_name + "/.MainActivity";
+  int status = system(start_cmd.c_str());
+  ASSERT_TRUE(status >= 0 && WEXITSTATUS(status) == 0) << "status: " << status;
+
+  bool desired_run_state = true;
+  const auto checkpoint = task_runner->CreateCheckpoint(checkpoint_name);
+  task_runner->PostDelayedTask(
+      [desired_run_state, task_runner, app_name, checkpoint] {
+        PollRunState(desired_run_state, task_runner, app_name,
+                     std::move(checkpoint));
+      },
+      delay_ms);
+}
+
+void StopApp(const std::string& app_name,
+             const std::string& checkpoint_name,
+             base::TestTaskRunner* task_runner) {
+  std::string stop_cmd = "am force-stop " + app_name;
+  int status = system(stop_cmd.c_str());
+  ASSERT_TRUE(status >= 0 && WEXITSTATUS(status) == 0) << "status: " << status;
+
+  bool desired_run_state = false;
+  auto checkpoint = task_runner->CreateCheckpoint(checkpoint_name);
+  task_runner->PostTask([desired_run_state, task_runner, app_name, checkpoint] {
+    PollRunState(desired_run_state, task_runner, app_name,
+                 std::move(checkpoint));
+  });
+}
 
 std::vector<protos::TracePacket> ProfileRuntime(std::string app_name) {
   base::TestTaskRunner task_runner;
@@ -61,22 +128,20 @@
 
   TraceConfig trace_config;
   trace_config.add_buffers()->set_size_kb(10 * 1024);
-  trace_config.set_duration_ms(4000);
+  trace_config.set_duration_ms(2000);
 
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
   ds_config->set_name("android.heapprofd");
   ds_config->set_target_buffer(0);
 
-  protos::HeapprofdConfig heapprofd_config;
-  heapprofd_config.set_sampling_interval_bytes(kTestSamplingInterval);
-  heapprofd_config.add_process_cmdline(app_name.c_str());
-  heapprofd_config.set_block_client(true);
-  heapprofd_config.set_all(false);
-  ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
+  auto* heapprofd_config = ds_config->mutable_heapprofd_config();
+  heapprofd_config->set_sampling_interval_bytes(kTestSamplingInterval);
+  *heapprofd_config->add_process_cmdline() = app_name.c_str();
+  heapprofd_config->set_all(false);
 
   // start tracing
   helper.StartTracing(trace_config);
-  helper.WaitForTracingDisabled(10000 /*ms*/);
+  helper.WaitForTracingDisabled(4000 /*ms*/);
   helper.ReadData();
   helper.WaitForReadData();
 
@@ -104,12 +169,10 @@
   ds_config->set_name("android.heapprofd");
   ds_config->set_target_buffer(0);
 
-  protos::HeapprofdConfig heapprofd_config;
-  heapprofd_config.set_sampling_interval_bytes(kTestSamplingInterval);
-  heapprofd_config.add_process_cmdline(app_name.c_str());
-  heapprofd_config.set_block_client(true);
-  heapprofd_config.set_all(false);
-  ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
+  auto* heapprofd_config = ds_config->mutable_heapprofd_config();
+  heapprofd_config->set_sampling_interval_bytes(kTestSamplingInterval);
+  *heapprofd_config->add_process_cmdline() = app_name.c_str();
+  heapprofd_config->set_all(false);
 
   // start tracing
   helper.StartTracing(trace_config);
@@ -159,35 +222,33 @@
   }
 }
 
-TEST(HeapprofdCtsTest, DebuggableAppRuntime) {
+void StopApp(std::string app_name) {
+  std::string stop_cmd = "am force-stop " + app_name;
+  system(stop_cmd.c_str());
+}
+
+// TODO(b/118428762): look into unwinding issues on x86.
+#if defined(__i386__) || defined(__x86_64__)
+#define MAYBE_SKIP(x) DISABLED_##x
+#else
+#define MAYBE_SKIP(x) x
+#endif
+
+TEST(HeapprofdCtsTest, MAYBE_SKIP(DebuggableAppRuntime)) {
   std::string app_name = "android.perfetto.cts.app.debuggable";
   const auto& packets = ProfileRuntime(app_name);
   AssertExpectedAllocationsPresent(packets);
   StopApp(app_name);
 }
 
-TEST(HeapprofdCtsTest, DebuggableAppStartup) {
+TEST(HeapprofdCtsTest, MAYBE_SKIP(DebuggableAppStartup)) {
   std::string app_name = "android.perfetto.cts.app.debuggable";
   const auto& packets = ProfileStartup(app_name);
   AssertExpectedAllocationsPresent(packets);
   StopApp(app_name);
 }
 
-TEST(HeapprofdCtsTest, ProfileableAppRuntime) {
-  std::string app_name = "android.perfetto.cts.app.profileable";
-  const auto& packets = ProfileRuntime(app_name);
-  AssertExpectedAllocationsPresent(packets);
-  StopApp(app_name);
-}
-
-TEST(HeapprofdCtsTest, ProfileableAppStartup) {
-  std::string app_name = "android.perfetto.cts.app.profileable";
-  const auto& packets = ProfileStartup(app_name);
-  AssertExpectedAllocationsPresent(packets);
-  StopApp(app_name);
-}
-
-TEST(HeapprofdCtsTest, ReleaseAppRuntime) {
+TEST(HeapprofdCtsTest, MAYBE_SKIP(ReleaseAppRuntime)) {
   std::string app_name = "android.perfetto.cts.app.release";
   const auto& packets = ProfileRuntime(app_name);
 
@@ -199,7 +260,7 @@
   StopApp(app_name);
 }
 
-TEST(HeapprofdCtsTest, ReleaseAppStartup) {
+TEST(HeapprofdCtsTest, MAYBE_SKIP(ReleaseAppStartup)) {
   std::string app_name = "android.perfetto.cts.app.release";
   const auto& packets = ProfileStartup(app_name);
 
diff --git a/test/cts/producer/jni/Android.bp b/test/cts/producer/jni/Android.bp
index b97ecdb..aae7201 100644
--- a/test/cts/producer/jni/Android.bp
+++ b/test/cts/producer/jni/Android.bp
@@ -7,7 +7,7 @@
     "libgtest",
     "libprotobuf-cpp-lite",
     "perfetto_cts_jni_deps",
-    "libperfetto_client_experimental",
+    "perfetto_src_tracing_ipc",
   ],
   shared_libs: [
     "libandroid",
@@ -16,7 +16,7 @@
   ],
   compile_multilib: "both",
   stl: "libc++_static",
-  defaults: [
-    "perfetto_defaults",
+  cflags: [
+    "-DPERFETTO_BUILD_WITH_ANDROID",
   ],
 }
diff --git a/test/cts/producer/jni/fake_producer_jni.cc b/test/cts/producer/jni/fake_producer_jni.cc
index 47d4356..cbeafe2 100644
--- a/test/cts/producer/jni/fake_producer_jni.cc
+++ b/test/cts/producer/jni/fake_producer_jni.cc
@@ -16,10 +16,10 @@
 
 #include <jni.h>
 
-#include "perfetto/ext/traced/traced.h"
-#include "perfetto/ext/tracing/ipc/default_socket.h"
+#include "perfetto/traced/traced.h"
 
 #include "src/base/test/test_task_runner.h"
+#include "src/tracing/ipc/default_socket.h"
 
 #include "test/fake_producer.h"
 
diff --git a/test/cts/utils.cc b/test/cts/utils.cc
deleted file mode 100644
index e37cbc7..0000000
--- a/test/cts/utils.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2019 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 "test/cts/utils.h"
-
-#include <stdlib.h>
-#include <sys/system_properties.h>
-
-#include "perfetto/base/logging.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace {
-
-// invokes |callback| once the target app is in the desired state
-void PollRunState(bool desired_run_state,
-                  base::TestTaskRunner* task_runner,
-                  const std::string& name,
-                  std::function<void()> callback) {
-  bool app_running = IsAppRunning(name);
-  if (app_running == desired_run_state) {
-    callback();
-    return;
-  }
-  task_runner->PostDelayedTask(
-      [desired_run_state, task_runner, name, callback] {
-        PollRunState(desired_run_state, task_runner, name, std::move(callback));
-      },
-      /*delay_ms=*/5);
-}
-
-}  // namespace
-
-bool IsDebuggableBuild() {
-  char buf[PROP_VALUE_MAX + 1] = {};
-  int ret = __system_property_get("ro.debuggable", buf);
-  PERFETTO_CHECK(ret >= 0);
-  std::string debuggable(buf);
-  if (debuggable == "1")
-    return true;
-  return false;
-}
-
-// note: cannot use gtest macros due to return type
-bool IsAppRunning(const std::string& name) {
-  std::string cmd = "pgrep -f " + name;
-  int retcode = system(cmd.c_str());
-  PERFETTO_CHECK(retcode >= 0);
-  int exit_status = WEXITSTATUS(retcode);
-  if (exit_status == 0)
-    return true;
-  if (exit_status == 1)
-    return false;
-  PERFETTO_FATAL("unexpected exit status from system(pgrep): %d", exit_status);
-}
-
-void StartAppActivity(const std::string& app_name,
-                      const std::string& checkpoint_name,
-                      base::TestTaskRunner* task_runner,
-                      int delay_ms) {
-  std::string start_cmd = "am start " + app_name + "/.MainActivity";
-  int status = system(start_cmd.c_str());
-  ASSERT_TRUE(status >= 0 && WEXITSTATUS(status) == 0) << "status: " << status;
-
-  bool desired_run_state = true;
-  const auto checkpoint = task_runner->CreateCheckpoint(checkpoint_name);
-  task_runner->PostDelayedTask(
-      [desired_run_state, task_runner, app_name, checkpoint] {
-        PollRunState(desired_run_state, task_runner, app_name,
-                     std::move(checkpoint));
-      },
-      delay_ms);
-}
-
-void StopApp(const std::string& app_name,
-             const std::string& checkpoint_name,
-             base::TestTaskRunner* task_runner) {
-  std::string stop_cmd = "am force-stop " + app_name;
-  int status = system(stop_cmd.c_str());
-  ASSERT_TRUE(status >= 0 && WEXITSTATUS(status) == 0) << "status: " << status;
-
-  bool desired_run_state = false;
-  auto checkpoint = task_runner->CreateCheckpoint(checkpoint_name);
-  task_runner->PostTask([desired_run_state, task_runner, app_name, checkpoint] {
-    PollRunState(desired_run_state, task_runner, app_name,
-                 std::move(checkpoint));
-  });
-}
-
-void StopApp(std::string app_name) {
-  std::string stop_cmd = "am force-stop " + app_name;
-  system(stop_cmd.c_str());
-}
-
-}  // namespace perfetto
diff --git a/test/cts/utils.h b/test/cts/utils.h
deleted file mode 100644
index 1c8ed26..0000000
--- a/test/cts/utils.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2019 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 TEST_CTS_UTILS_H_
-#define TEST_CTS_UTILS_H_
-
-#include <string>
-
-#include "src/base/test/test_task_runner.h"
-
-namespace perfetto {
-
-bool IsDebuggableBuild();
-
-bool IsAppRunning(const std::string& name);
-
-void StartAppActivity(const std::string& app_name,
-                      const std::string& checkpoint_name,
-                      base::TestTaskRunner* task_runner,
-                      int delay_ms = 1);
-
-void StopApp(const std::string& app_name,
-             const std::string& checkpoint_name,
-             base::TestTaskRunner* task_runner);
-
-void StopApp(std::string app_name);
-
-}  // namespace perfetto
-
-#endif  // TEST_CTS_UTILS_H_
diff --git a/test/end_to_end_benchmark.cc b/test/end_to_end_benchmark.cc
index 5cdedb3..fd1fd3e 100644
--- a/test/end_to_end_benchmark.cc
+++ b/test/end_to_end_benchmark.cc
@@ -12,22 +12,21 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include <gtest/gtest.h>
 #include <random>
 
-#include <benchmark/benchmark.h>
-
+#include "benchmark/benchmark.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/traced/traced.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
+#include "perfetto/traced/traced.h"
 #include "perfetto/tracing/core/trace_config.h"
+#include "perfetto/tracing/core/trace_packet.h"
 #include "src/base/test/test_task_runner.h"
-#include "test/gtest_and_gmock.h"
 #include "test/task_runner_thread.h"
 #include "test/task_runner_thread_delegates.h"
 #include "test/test_helper.h"
 
-#include "protos/perfetto/config/test_config.gen.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/trace_packet.pb.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
 
diff --git a/test/end_to_end_integrationtest.cc b/test/end_to_end_integrationtest.cc
index eab9338..15bef9d 100644
--- a/test/end_to_end_integrationtest.cc
+++ b/test/end_to_end_integrationtest.cc
@@ -17,34 +17,34 @@
 #include <unistd.h>
 
 #include <chrono>
+#include <condition_variable>
 #include <functional>
 #include <initializer_list>
 #include <random>
 #include <thread>
 
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 #include "perfetto/base/build_config.h"
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/pipe.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/ext/traced/traced.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/ipc/default_socket.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "protos/perfetto/config/power/android_power_config.pbzero.h"
-#include "protos/perfetto/config/test_config.gen.h"
-#include "protos/perfetto/config/trace_config.gen.h"
-#include "protos/perfetto/trace/trace.pb.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/base/pipe.h"
+#include "perfetto/base/temp_file.h"
+#include "perfetto/traced/traced.h"
+#include "perfetto/tracing/core/trace_config.h"
+#include "perfetto/tracing/core/trace_packet.h"
 #include "src/base/test/test_task_runner.h"
 #include "src/traced/probes/ftrace/ftrace_controller.h"
 #include "src/traced/probes/ftrace/ftrace_procfs.h"
-#include "test/gtest_and_gmock.h"
+#include "src/tracing/ipc/default_socket.h"
 #include "test/task_runner_thread.h"
 #include "test/task_runner_thread_delegates.h"
 #include "test/test_helper.h"
 
+#include "perfetto/trace/trace.pb.h"
+#include "perfetto/trace/trace_packet.pb.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
+
 namespace perfetto {
 
 namespace {
@@ -69,191 +69,6 @@
   return path;
 }
 
-// This class is a reference to a child process that has in essence been execv
-// to the requested binary. The process will start and then wait for Run()
-// before proceeding. We use this to fork new processes before starting any
-// additional threads in the parent process (otherwise you would risk
-// deadlocks), but pause the forked processes until remaining setup (including
-// any necessary threads) in the parent process is complete.
-class Exec {
- public:
-  // Starts the forked process that was created. If not null then |stderr_out
-  // will contain the std::cerr output of the process.
-  int Run(std::string* stderr_out = nullptr) {
-    // We can't be the child process.
-    PERFETTO_CHECK(pid_ != 0);
-
-    // Send some random bytes so the child process knows the service is up and
-    // it can connect and execute.
-    PERFETTO_CHECK(PERFETTO_EINTR(write(*start_pipe_.wr, "42", 2)) ==
-                   static_cast<ssize_t>(2));
-    start_pipe_.wr.reset();
-
-    // Setup a large enough buffer and read all of stderr (until the process
-    // closes the err_pipe on process exit).
-    std::string stderr_str = std::string(1024 * 1024, '\0');
-    ssize_t rsize = 0;
-    size_t stderr_pos = 0;
-    while (stderr_pos < stderr_str.size()) {
-      rsize = PERFETTO_EINTR(read(*err_pipe_.rd, &stderr_str[stderr_pos],
-                                  stderr_str.size() - stderr_pos - 1));
-      if (rsize <= 0)
-        break;
-      stderr_pos += static_cast<size_t>(rsize);
-    }
-    stderr_str.resize(stderr_pos);
-
-    // Either output the stderr_out to the provided variable or for the record
-    // it into the info logs.
-    if (stderr_out) {
-      *stderr_out = stderr_str;
-    } else {
-      PERFETTO_LOG("Child proc %d exited with stderr: \"%s\"", pid_,
-                   stderr_str.c_str());
-    }
-
-    int status = 1;
-    PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid_, &status, 0)) == pid_);
-    int exit_code;
-    if (WIFEXITED(status)) {
-      exit_code = WEXITSTATUS(status);
-    } else if (WIFSIGNALED(status)) {
-      exit_code = -(WTERMSIG(status));
-      PERFETTO_CHECK(exit_code < 0);
-    } else {
-      PERFETTO_FATAL("Unexpected exit status: %d", status);
-    }
-    return exit_code;
-  }
-
- private:
-  Exec(pid_t pid, base::Pipe err, base::Pipe start)
-      : pid_(pid), err_pipe_(std::move(err)), start_pipe_(std::move(start)) {}
-
-  static Exec Create(const std::string& argv0,
-                     std::initializer_list<std::string> args,
-                     std::string input = "") {
-    if (argv0 != "perfetto" && argv0 != "trigger_perfetto") {
-      PERFETTO_FATAL(
-          "Received argv0: \"%s\" which isn't supported. Supported binaries "
-          "are \"perfetto\" or \"trigger_perfetto\".",
-          argv0.c_str());
-    }
-
-    // |in_pipe| == std::cin, |err_pipe| == std::cerr for the process we're
-    // about to fork. |start_pipe| is used to block the process so we can hold
-    // it until we're ready (the service has started up).
-    base::Pipe in_pipe = base::Pipe::Create();
-    base::Pipe err_pipe = base::Pipe::Create();
-    base::Pipe start_pipe = base::Pipe::Create();
-
-    pid_t pid = fork();
-    PERFETTO_CHECK(pid >= 0);
-    if (pid == 0) {
-      // Child process, we need to block the child process until we've been
-      // signaled on the |start_pipe|.
-      std::string junk = std::string(4, '\0');
-      start_pipe.wr.reset();
-      ssize_t rsize = 0;
-      rsize = PERFETTO_EINTR(read(*start_pipe.rd, &junk[0], junk.size() - 1));
-      PERFETTO_CHECK(rsize >= 0);
-      start_pipe.rd.reset();
-
-      // We've been signalled to start so execute in a sub function.
-      _exit(RunChild(argv0, std::move(args), std::move(in_pipe),
-                     std::move(err_pipe)));
-    } else {
-      // Parent, we don't need to write to the childs std::cerr nor do we need
-      // to read the start_pipe.
-      err_pipe.wr.reset();
-      start_pipe.rd.reset();
-
-      // This is generally an unsafe pattern because the child process might
-      // be blocked on stdout and stall the stdin reads. It's pragmatically
-      // okay for our test cases because stdin is not expected to exceed the
-      // pipe buffer.
-      //
-      // We need to write this now up front (rather than in Run(), because in
-      // some tests we create multiple Exec classes, and if we don't close the
-      // input pipe up front then future Exec's will have a reference and the
-      // pipe won't close properly.
-      PERFETTO_CHECK(input.size() <= base::kPageSize);
-      PERFETTO_CHECK(
-          PERFETTO_EINTR(write(*in_pipe.wr, input.data(), input.size())) ==
-          static_cast<ssize_t>(input.size()));
-      in_pipe.wr.reset();
-      // Close the input pipe only after the write so we don't get an EPIPE
-      // signal in the cases when the child process earlies out without
-      // reading stdin.
-      in_pipe.rd.reset();
-
-      return Exec(pid, std::move(err_pipe), std::move(start_pipe));
-    }
-  }
-
-  // Wrapper to contain all the work the child process needs to do.
-  static int RunChild(const std::string& argv0,
-                      std::initializer_list<std::string> args,
-                      base::Pipe in_pipe,
-                      base::Pipe err_pipe) {
-    // This sets up the char** argv buffer we're going to provide to the main
-    // function for |argv0| binary.
-    std::vector<char> argv_buffer;
-    std::vector<size_t> argv_offsets;
-    std::vector<char*> argv;
-    argv_offsets.push_back(0);
-
-    argv_buffer.insert(argv_buffer.end(), argv0.begin(), argv0.end());
-    argv_buffer.push_back('\0');
-
-    for (const std::string& arg : args) {
-      argv_offsets.push_back(argv_buffer.size());
-      argv_buffer.insert(argv_buffer.end(), arg.begin(), arg.end());
-      argv_buffer.push_back('\0');
-    }
-
-    for (size_t off : argv_offsets)
-      argv.push_back(&argv_buffer[off]);
-    argv.push_back(nullptr);
-
-    // We aren't reading std::cerr nor writing to std::cin.
-    err_pipe.rd.reset();
-    in_pipe.wr.reset();
-
-    // This makes it so the binaries below will correctly write their std::cin
-    // and std::cerr to the right pipes.
-    int devnull = open("/dev/null", O_RDWR);
-    PERFETTO_CHECK(devnull >= 0);
-    PERFETTO_CHECK(dup2(*in_pipe.rd, STDIN_FILENO) != -1);
-    PERFETTO_CHECK(dup2(devnull, STDOUT_FILENO) != -1);
-    PERFETTO_CHECK(dup2(*err_pipe.wr, STDERR_FILENO) != -1);
-#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
-    setenv("PERFETTO_CONSUMER_SOCK_NAME", TestHelper::GetConsumerSocketName(),
-           1);
-    setenv("PERFETTO_PRODUCER_SOCK_NAME", TestHelper::GetProducerSocketName(),
-           1);
-    if (argv0 == "perfetto") {
-      return PerfettoCmdMain(static_cast<int>(argv.size() - 1), argv.data());
-    } else if (argv0 == "trigger_perfetto") {
-      return TriggerPerfettoMain(static_cast<int>(argv.size() - 1),
-                                 argv.data());
-    } else {
-      PERFETTO_FATAL("Unknown binary: %s", argv0.c_str());
-      return 4;
-    }
-#else
-    execv((std::string("/system/bin/") + argv0).c_str(), &argv[0]);
-    return 3;
-#endif
-  }
-
-  friend class PerfettoCmdlineTest;
-
-  pid_t pid_;
-  base::Pipe err_pipe_;
-  base::Pipe start_pipe_;
-};
-
 class PerfettoTest : public ::testing::Test {
  public:
   void SetUp() override {
@@ -278,55 +93,123 @@
 
 class PerfettoCmdlineTest : public ::testing::Test {
  public:
-  void SetUp() override { exec_allowed_ = true; }
-
-  void TearDown() override {}
-
-  void StartServiceIfRequiredNoNewExecsAfterThis() {
-    exec_allowed_ = false;
+  void SetUp() override {
     test_helper_.StartServiceIfRequired();
   }
 
-  FakeProducer* ConnectFakeProducer() {
-    return test_helper_.ConnectFakeProducer();
+  void TearDown() override {}
+
+  int ExecPerfetto(std::initializer_list<std::string> args,
+                   std::string input = "") {
+    return Exec("perfetto", args, input);
   }
 
-  std::function<void()> WrapTask(const std::function<void()>& function) {
-    return test_helper_.WrapTask(function);
+  int ExecTrigger(std::initializer_list<std::string> args,
+                  std::string input = "") {
+    return Exec("trigger_perfetto", args, input);
   }
 
-  void WaitForProducerSetup() { test_helper_.WaitForProducerSetup(); }
+  // Fork() + executes the perfetto cmdline client with the given args and
+  // returns the exit code.
+  int Exec(const std::string& argv0,
+           std::initializer_list<std::string> args,
+           std::string input = "") {
+    std::vector<char> argv_buffer;
+    std::vector<size_t> argv_offsets;
+    std::vector<char*> argv;
+    argv_offsets.push_back(0);
 
-  void WaitForProducerEnabled() { test_helper_.WaitForProducerEnabled(); }
+    argv_buffer.insert(argv_buffer.end(), argv0.begin(), argv0.end());
+    argv_buffer.push_back('\0');
 
-  // Creates a process that represents the perfetto binary that will
-  // start when Run() is called. |args| will be passed as part of
-  // the command line and |std_in| will be piped into std::cin.
-  Exec ExecPerfetto(std::initializer_list<std::string> args,
-                    std::string std_in = "") {
-    // You can not fork after you've started the service due to risk of
-    // deadlocks.
-    PERFETTO_CHECK(exec_allowed_);
-    return Exec::Create("perfetto", std::move(args), std::move(std_in));
+    for (const std::string& arg : args) {
+      argv_offsets.push_back(argv_buffer.size());
+      argv_buffer.insert(argv_buffer.end(), arg.begin(), arg.end());
+      argv_buffer.push_back('\0');
+    }
+
+    for (size_t off : argv_offsets)
+      argv.push_back(&argv_buffer[off]);
+    argv.push_back(nullptr);
+
+    // Create the pipe for the child process to return stderr.
+    base::Pipe err_pipe = base::Pipe::Create();
+    base::Pipe in_pipe = base::Pipe::Create();
+
+    pid_t pid = fork();
+    PERFETTO_CHECK(pid >= 0);
+    if (pid == 0) {
+      // Child process.
+      err_pipe.rd.reset();
+      in_pipe.wr.reset();
+
+      int devnull = open("/dev/null", O_RDWR);
+      PERFETTO_CHECK(devnull >= 0);
+      PERFETTO_CHECK(dup2(*in_pipe.rd, STDIN_FILENO) != -1);
+      PERFETTO_CHECK(dup2(devnull, STDOUT_FILENO) != -1);
+      PERFETTO_CHECK(dup2(*err_pipe.wr, STDERR_FILENO) != -1);
+#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
+      setenv("PERFETTO_CONSUMER_SOCK_NAME", TestHelper::GetConsumerSocketName(),
+             1);
+      setenv("PERFETTO_PRODUCER_SOCK_NAME", TestHelper::GetProducerSocketName(),
+             1);
+      if (argv0 == "perfetto") {
+        _exit(PerfettoCmdMain(static_cast<int>(argv.size() - 1), argv.data()));
+      } else if (argv0 == "trigger_perfetto") {
+        _exit(TriggerPerfettoMain(static_cast<int>(argv.size() - 1),
+                                  argv.data()));
+      } else {
+        ADD_FAILURE() << "Unknown binary: " << argv0.c_str();
+      }
+#else
+      execv((std::string("/system/bin/") + argv0).c_str(), &argv[0]);
+      _exit(3);
+#endif
+    }
+
+    // Parent.
+    err_pipe.wr.reset();
+    stderr_ = std::string(1024 * 1024, '\0');
+
+    // This is generally an unsafe pattern because the child process might be
+    // blocked on stdout and stall the stdin reads. It's pragmatically okay for
+    // our test cases because stdin is not expected to exceed the pipe buffer.
+    PERFETTO_CHECK(input.size() <= base::kPageSize);
+    PERFETTO_CHECK(
+        PERFETTO_EINTR(write(*in_pipe.wr, input.data(), input.size())) ==
+        static_cast<ssize_t>(input.size()));
+    in_pipe.wr.reset();
+
+    // Close the input pipe only after the write so we don't get an EPIPE signal
+    // in the cases when the child process earlies out without reading stdin.
+    in_pipe.rd.reset();
+
+    ssize_t rsize = 0;
+    size_t stderr_pos = 0;
+    while (stderr_pos < stderr_.size()) {
+      rsize = PERFETTO_EINTR(read(*err_pipe.rd, &stderr_[stderr_pos],
+                                  stderr_.size() - stderr_pos - 1));
+      if (rsize <= 0)
+        break;
+      stderr_pos += static_cast<size_t>(rsize);
+    }
+    stderr_.resize(stderr_pos);
+    int status = 1;
+    PERFETTO_CHECK(PERFETTO_EINTR(waitpid(pid, &status, 0)) == pid);
+    int exit_code;
+    if (WIFEXITED(status)) {
+      exit_code = WEXITSTATUS(status);
+    } else if (WIFSIGNALED(status)) {
+      exit_code = -(WTERMSIG(status));
+      PERFETTO_CHECK(exit_code < 0);
+    } else {
+      PERFETTO_FATAL("Unexpected exit status: %d", status);
+    }
+    return exit_code;
   }
 
-  // Creates a process that represents the trigger_perfetto binary that will
-  // start when Run() is called. |args| will be passed as part of
-  // the command line and |std_in| will be piped into std::cin.
-  Exec ExecTrigger(std::initializer_list<std::string> args,
-                   std::string std_in = "") {
-    // You can not fork after you've started the service due to risk of
-    // deadlocks.
-    PERFETTO_CHECK(exec_allowed_);
-    return Exec::Create("trigger_perfetto", std::move(args), std::move(std_in));
-  }
-
-  // Tests are allowed to freely use these variables.
   std::string stderr_;
   base::TestTaskRunner task_runner_;
-
- private:
-  bool exec_allowed_;
   TestHelper test_helper_{&task_runner_};
 };
 
@@ -371,10 +254,9 @@
   ds_config->set_name("linux.ftrace");
   ds_config->set_target_buffer(0);
 
-  protos::FtraceConfig ftrace_config;
-  ftrace_config.add_ftrace_events("sched_switch");
-  ftrace_config.add_ftrace_events("bar");
-  ds_config->set_ftrace_config_raw(ftrace_config.SerializeAsString());
+  auto* ftrace_config = ds_config->mutable_ftrace_config();
+  *ftrace_config->add_ftrace_events() = "sched_switch";
+  *ftrace_config->add_ftrace_events() = "bar";
 
   helper.StartTracing(trace_config);
   helper.WaitForTracingDisabled();
@@ -415,9 +297,8 @@
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
   ds_config->set_name("linux.ftrace");
 
-  protos::FtraceConfig ftrace_config;
-  ftrace_config.add_ftrace_events("print");
-  ds_config->set_ftrace_config_raw(ftrace_config.SerializeAsString());
+  auto* ftrace_config = ds_config->mutable_ftrace_config();
+  *ftrace_config->add_ftrace_events() = "print";
 
   helper.StartTracing(trace_config);
 
@@ -475,15 +356,12 @@
   auto* ds_config = trace_config.add_data_sources()->mutable_config();
   ds_config->set_name("android.power");
   ds_config->set_target_buffer(0);
-
-  using protos::pbzero::AndroidPowerConfig;
-  protozero::HeapBuffered<AndroidPowerConfig> power_config;
+  auto* power_config = ds_config->mutable_android_power_config();
   power_config->set_battery_poll_ms(250);
-  power_config->add_battery_counters(
-      AndroidPowerConfig::BATTERY_COUNTER_CHARGE);
-  power_config->add_battery_counters(
-      AndroidPowerConfig::BATTERY_COUNTER_CAPACITY_PERCENT);
-  ds_config->set_android_power_config_raw(power_config.SerializeAsString());
+  *power_config->add_battery_counters() =
+      AndroidPowerConfig::BATTERY_COUNTER_CHARGE;
+  *power_config->add_battery_counters() =
+      AndroidPowerConfig::BATTERY_COUNTER_CAPACITY_PERCENT;
 
   helper.StartTracing(trace_config);
   helper.WaitForTracingDisabled();
@@ -694,120 +572,74 @@
 TEST_F(PerfettoCmdlineTest, NoSanitizers(InvalidCases)) {
   std::string cfg("duration_ms: 100");
 
-  auto invalid_arg = ExecPerfetto({"--invalid-arg"});
-  auto empty_config = ExecPerfetto({"-c", "-", "-o", "-"}, "");
+  EXPECT_EQ(1, ExecPerfetto({"--invalid-arg"}));
 
-  // Cannot make assertions on --dropbox because on standalone builds it fails
-  // prematurely due to lack of dropbox.
-  auto missing_dropbox =
-      ExecPerfetto({"-c", "-", "--txt", "-o", "-", "--dropbox=foo"}, cfg);
-  auto either_out_or_dropbox = ExecPerfetto({"-c", "-", "--txt"}, cfg);
-
-  // Disallow mixing simple and file config.
-  auto simple_and_file_1 =
-      ExecPerfetto({"-o", "-", "-c", "-", "-t", "2s"}, cfg);
-  auto simple_and_file_2 =
-      ExecPerfetto({"-o", "-", "-c", "-", "-b", "2m"}, cfg);
-  auto simple_and_file_3 =
-      ExecPerfetto({"-o", "-", "-c", "-", "-s", "2m"}, cfg);
-
-  // Invalid --attach / --detach cases.
-  auto invalid_stop =
-      ExecPerfetto({"-c", "-", "--txt", "-o", "-", "--stop"}, cfg);
-  auto attach_and_config_1 =
-      ExecPerfetto({"-c", "-", "--txt", "-o", "-", "--attach=foo"}, cfg);
-  auto attach_and_config_2 =
-      ExecPerfetto({"-t", "2s", "-o", "-", "--attach=foo"}, cfg);
-  auto attach_needs_argument = ExecPerfetto({"--attach"}, cfg);
-  auto detach_needs_argument =
-      ExecPerfetto({"-t", "2s", "-o", "-", "--detach"}, cfg);
-  auto detach_without_out_or_dropbox =
-      ExecPerfetto({"-t", "2s", "--detach=foo"}, cfg);
-
-  // Cannot trace and use --query.
-  auto trace_and_query_1 = ExecPerfetto({"-t", "2s", "--query"}, cfg);
-  auto trace_and_query_2 = ExecPerfetto({"-c", "-", "--query"}, cfg);
-
-  // Ensure all Exec:: calls have been saved to prevent deadlocks.
-  StartServiceIfRequiredNoNewExecsAfterThis();
-
-  EXPECT_EQ(1, invalid_arg.Run(&stderr_));
-
-  EXPECT_EQ(1, empty_config.Run(&stderr_));
+  EXPECT_EQ(1, ExecPerfetto({"-c", "-", "-o", "-"}, ""));
   EXPECT_THAT(stderr_, HasSubstr("TraceConfig is empty"));
 
   // Cannot make assertions on --dropbox because on standalone builds it fails
   // prematurely due to lack of dropbox.
-  EXPECT_EQ(1, missing_dropbox.Run(&stderr_));
+  EXPECT_EQ(
+      1, ExecPerfetto({"-c", "-", "--txt", "-o", "-", "--dropbox=foo"}, cfg));
 
-  EXPECT_EQ(1, either_out_or_dropbox.Run(&stderr_));
+  EXPECT_EQ(1, ExecPerfetto({"-c", "-", "--txt"}, cfg));
   EXPECT_THAT(stderr_, HasSubstr("Either --out or --dropbox"));
 
   // Disallow mixing simple and file config.
-  EXPECT_EQ(1, simple_and_file_1.Run(&stderr_));
+  EXPECT_EQ(1, ExecPerfetto({"-o", "-", "-c", "-", "-t", "2s"}, cfg));
   EXPECT_THAT(stderr_, HasSubstr("Cannot specify both -c"));
 
-  EXPECT_EQ(1, simple_and_file_2.Run(&stderr_));
+  EXPECT_EQ(1, ExecPerfetto({"-o", "-", "-c", "-", "-b", "2m"}, cfg));
   EXPECT_THAT(stderr_, HasSubstr("Cannot specify both -c"));
 
-  EXPECT_EQ(1, simple_and_file_3.Run(&stderr_));
+  EXPECT_EQ(1, ExecPerfetto({"-o", "-", "-c", "-", "-s", "2m"}, cfg));
   EXPECT_THAT(stderr_, HasSubstr("Cannot specify both -c"));
 
   // Invalid --attach / --detach cases.
-  EXPECT_EQ(1, invalid_stop.Run(&stderr_));
+  EXPECT_EQ(1, ExecPerfetto({"-c", "-", "--txt", "-o", "-", "--stop"}, cfg));
   EXPECT_THAT(stderr_, HasSubstr("--stop is supported only in combination"));
 
-  EXPECT_EQ(1, attach_and_config_1.Run(&stderr_));
+  EXPECT_EQ(1,
+            ExecPerfetto({"-c", "-", "--txt", "-o", "-", "--attach=foo"}, cfg));
   EXPECT_THAT(stderr_, HasSubstr("Cannot specify a trace config"));
 
-  EXPECT_EQ(1, attach_and_config_2.Run(&stderr_));
+  EXPECT_EQ(1, ExecPerfetto({"-t", "2s", "-o", "-", "--attach=foo"}, cfg));
   EXPECT_THAT(stderr_, HasSubstr("Cannot specify a trace config"));
 
-  EXPECT_EQ(1, attach_needs_argument.Run(&stderr_));
+  EXPECT_EQ(1, ExecPerfetto({"--attach"}, cfg));
   EXPECT_THAT(stderr_, ContainsRegex("option.*--attach.*requires an argument"));
 
-  EXPECT_EQ(1, detach_needs_argument.Run(&stderr_));
+  EXPECT_EQ(1, ExecPerfetto({"-t", "2s", "-o", "-", "--detach"}, cfg));
   EXPECT_THAT(stderr_, ContainsRegex("option.*--detach.*requires an argument"));
 
-  EXPECT_EQ(1, detach_without_out_or_dropbox.Run(&stderr_));
+  EXPECT_EQ(1, ExecPerfetto({"-t", "2s", "--detach=foo"}, cfg));
   EXPECT_THAT(stderr_, HasSubstr("--out or --dropbox is required"));
 
-  // Cannot trace and use --query.
-  EXPECT_EQ(1, trace_and_query_1.Run(&stderr_));
+  EXPECT_EQ(1, ExecPerfetto({"-t", "2s", "--query"}, cfg));
   EXPECT_THAT(stderr_, HasSubstr("Cannot specify a trace config"));
 
-  EXPECT_EQ(1, trace_and_query_2.Run(&stderr_));
+  EXPECT_EQ(1, ExecPerfetto({"-c", "-", "--query"}, cfg));
   EXPECT_THAT(stderr_, HasSubstr("Cannot specify a trace config"));
 }
 
 TEST_F(PerfettoCmdlineTest, NoSanitizers(TxtConfig)) {
   std::string cfg("duration_ms: 100");
-  auto perfetto = ExecPerfetto({"-c", "-", "--txt", "-o", "-"}, cfg);
-  StartServiceIfRequiredNoNewExecsAfterThis();
-  EXPECT_EQ(0, perfetto.Run(&stderr_)) << stderr_;
+  EXPECT_EQ(0, ExecPerfetto({"-c", "-", "--txt", "-o", "-"}, cfg)) << stderr_;
 }
 
 TEST_F(PerfettoCmdlineTest, NoSanitizers(SimpleConfig)) {
-  auto perfetto = ExecPerfetto({"-o", "-", "-c", "-", "-t", "100ms"});
-  StartServiceIfRequiredNoNewExecsAfterThis();
-  EXPECT_EQ(0, perfetto.Run(&stderr_)) << stderr_;
+  EXPECT_EQ(0, ExecPerfetto({"-o", "-", "-c", "-", "-t", "100ms"}));
 }
 
 TEST_F(PerfettoCmdlineTest, NoSanitizers(DetachAndAttach)) {
-  auto attach_to_not_existing = ExecPerfetto({"--attach=not_existent"});
-
-  std::string cfg("duration_ms: 10000; write_into_file: true");
-  auto detach_valid_stop =
-      ExecPerfetto({"-o", "-", "-c", "-", "--txt", "--detach=valid_stop"}, cfg);
-  auto stop_valid_stop = ExecPerfetto({"--attach=valid_stop", "--stop"});
-
-  StartServiceIfRequiredNoNewExecsAfterThis();
-
-  EXPECT_NE(0, attach_to_not_existing.Run(&stderr_));
+  EXPECT_NE(0, ExecPerfetto({"--attach=not_existent"}));
   EXPECT_THAT(stderr_, HasSubstr("Session re-attach failed"));
 
-  EXPECT_EQ(0, detach_valid_stop.Run(&stderr_)) << stderr_;
-  EXPECT_EQ(0, stop_valid_stop.Run(&stderr_));
+  std::string cfg("duration_ms: 10000; write_into_file: true");
+  EXPECT_EQ(0, ExecPerfetto(
+                   {"-o", "-", "-c", "-", "--txt", "--detach=valid_stop"}, cfg))
+      << stderr_;
+  EXPECT_EQ(0, ExecPerfetto({"--attach=valid_stop", "--stop"}));
 }
 
 TEST_F(PerfettoCmdlineTest, NoSanitizers(StartTracingTrigger)) {
@@ -837,51 +669,37 @@
   // trigger config we have an additional ReceivedTriggers packet.
   constexpr size_t kPreamblePackets = 7;
 
-  // We have to construct all the processes we want to fork before we start the
-  // service with |StartServiceIfRequired()|. this is because it is unsafe
-  // (could deadlock) to fork after we've spawned some threads which might
-  // printf (and thus hold locks).
-  const std::string path = RandomTraceFileName();
-  auto perfetto_proc = ExecPerfetto(
-      {
-          "-o",
-          path,
-          "-c",
-          "-",
-      },
-      trace_config.SerializeAsString());
+  base::TestTaskRunner task_runner;
 
-  auto trigger_proc = ExecTrigger({"trigger_name"});
-
-  // Start the service and connect a simple fake producer.
-  StartServiceIfRequiredNoNewExecsAfterThis();
-
-  auto* fake_producer = ConnectFakeProducer();
+  // Enable tracing and detach as soon as it gets started.
+  TestHelper helper(&task_runner);
+  helper.StartServiceIfRequired();
+  auto* fake_producer = helper.ConnectFakeProducer();
   EXPECT_TRUE(fake_producer);
-
-  // Start a background thread that will deliver the config now that we've
-  // started the service. See |perfetto_proc| above for the args passed.
-  std::thread background_trace([&perfetto_proc]() {
-    std::string stderr_str;
-    EXPECT_EQ(0, perfetto_proc.Run(&stderr_str)) << stderr_str;
+  const std::string path = RandomTraceFileName();
+  std::thread background_trace([&path, &trace_config, this]() {
+    EXPECT_EQ(0, ExecPerfetto(
+                     {
+                         "-o", path, "-c", "-",
+                     },
+                     trace_config.SerializeAsString()));
   });
 
-  WaitForProducerSetup();
-  EXPECT_EQ(0, trigger_proc.Run(&stderr_));
+  helper.WaitForProducerSetup();
+  EXPECT_EQ(0, ExecTrigger({"trigger_name"})) << "stderr: " << stderr_;
 
   // Wait for the producer to start, and then write out 11 packets.
-  WaitForProducerEnabled();
-  auto on_data_written = task_runner_.CreateCheckpoint("data_written");
-  fake_producer->ProduceEventBatch(WrapTask(on_data_written));
-  task_runner_.RunUntilCheckpoint("data_written");
+  helper.WaitForProducerEnabled();
+  auto on_data_written = task_runner.CreateCheckpoint("data_written");
+  fake_producer->ProduceEventBatch(helper.WrapTask(on_data_written));
+  task_runner.RunUntilCheckpoint("data_written");
   background_trace.join();
 
   std::string trace_str;
   base::ReadFile(path, &trace_str);
   protos::Trace trace;
   ASSERT_TRUE(trace.ParseFromString(trace_str));
-  EXPECT_EQ(static_cast<int>(kPreamblePackets + kMessageCount),
-            trace.packet_size());
+  EXPECT_EQ(kPreamblePackets + kMessageCount, trace.packet_size());
   for (const auto& packet : trace.packet()) {
     if (packet.data_case() == protos::TracePacket::kTraceConfig) {
       // Ensure the trace config properly includes the trigger mode we set.
@@ -928,43 +746,33 @@
   // trigger config we have an additional ReceivedTriggers packet.
   constexpr size_t kPreamblePackets = 8;
 
-  // We have to construct all the processes we want to fork before we start the
-  // service with |StartServiceIfRequired()|. this is because it is unsafe
-  // (could deadlock) to fork after we've spawned some threads which might
-  // printf (and thus hold locks).
-  const std::string path = RandomTraceFileName();
-  auto perfetto_proc = ExecPerfetto(
-      {
-          "-o",
-          path,
-          "-c",
-          "-",
-      },
-      trace_config.SerializeAsString());
+  base::TestTaskRunner task_runner;
 
-  auto trigger_proc =
-      ExecTrigger({"trigger_name_2", "trigger_name", "trigger_name_3"});
-
-  // Start the service and connect a simple fake producer.
-  StartServiceIfRequiredNoNewExecsAfterThis();
-  auto* fake_producer = ConnectFakeProducer();
+  // Enable tracing and detach as soon as it gets started.
+  TestHelper helper(&task_runner);
+  helper.StartServiceIfRequired();
+  auto* fake_producer = helper.ConnectFakeProducer();
   EXPECT_TRUE(fake_producer);
 
-  // Start a background thread that will deliver the config now that we've
-  // started the service. See |perfetto_proc| above for the args passed.
-  std::thread background_trace([&perfetto_proc]() {
-    std::string stderr_str;
-    EXPECT_EQ(0, perfetto_proc.Run(&stderr_str)) << stderr_str;
+  const std::string path = RandomTraceFileName();
+  std::thread background_trace([&path, &trace_config, this]() {
+    EXPECT_EQ(0, ExecPerfetto(
+                     {
+                         "-o", path, "-c", "-",
+                     },
+                     trace_config.SerializeAsString()));
   });
 
-  WaitForProducerEnabled();
+  helper.WaitForProducerEnabled();
   // Wait for the producer to start, and then write out 11 packets, before the
   // trace actually starts (the trigger is seen).
-  auto on_data_written = task_runner_.CreateCheckpoint("data_written_1");
-  fake_producer->ProduceEventBatch(WrapTask(on_data_written));
-  task_runner_.RunUntilCheckpoint("data_written_1");
+  auto on_data_written = task_runner.CreateCheckpoint("data_written_1");
+  fake_producer->ProduceEventBatch(helper.WrapTask(on_data_written));
+  task_runner.RunUntilCheckpoint("data_written_1");
 
-  EXPECT_EQ(0, trigger_proc.Run(&stderr_)) << "stderr: " << stderr_;
+  EXPECT_EQ(0,
+            ExecTrigger({"trigger_name_2", "trigger_name", "trigger_name_3"}))
+      << "stderr: " << stderr_;
 
   background_trace.join();
 
@@ -972,8 +780,7 @@
   base::ReadFile(path, &trace_str);
   protos::Trace trace;
   ASSERT_TRUE(trace.ParseFromString(trace_str));
-  EXPECT_EQ(static_cast<int>(kPreamblePackets + kMessageCount),
-            trace.packet_size());
+  EXPECT_EQ(kPreamblePackets + kMessageCount, trace.packet_size());
   bool seen_first_trigger = false;
   for (const auto& packet : trace.packet()) {
     if (packet.data_case() == protos::TracePacket::kTraceConfig) {
@@ -1026,32 +833,23 @@
   trigger->set_stop_delay_ms(500);
   trigger = trigger_cfg->add_triggers();
 
-  // We have to construct all the processes we want to fork before we start the
-  // service with |StartServiceIfRequired()|. this is because it is unsafe
-  // (could deadlock) to fork after we've spawned some threads which might
-  // printf (and thus hold locks).
-  const std::string path = RandomTraceFileName();
-  auto perfetto_proc = ExecPerfetto(
-      {
-          "--dropbox",
-          "TAG",
-          "--no-guardrails",
-          "-c",
-          "-",
-      },
-      trace_config.SerializeAsString());
-
-  StartServiceIfRequiredNoNewExecsAfterThis();
-  auto* fake_producer = ConnectFakeProducer();
+  // Enable tracing and detach as soon as it gets started.
+  base::TestTaskRunner task_runner;
+  TestHelper helper(&task_runner);
+  helper.StartServiceIfRequired();
+  auto* fake_producer = helper.ConnectFakeProducer();
   EXPECT_TRUE(fake_producer);
 
-  std::string stderr_str;
-  std::thread background_trace([&perfetto_proc, &stderr_str]() {
-    EXPECT_EQ(0, perfetto_proc.Run(&stderr_str));
+  std::thread background_trace([&trace_config, this]() {
+    EXPECT_EQ(0, ExecPerfetto(
+                     {
+                         "--dropbox", "TAG", "--no-guardrails", "-c", "-",
+                     },
+                     trace_config.SerializeAsString()));
   });
   background_trace.join();
 
-  EXPECT_THAT(stderr_str,
+  EXPECT_THAT(stderr_,
               ::testing::HasSubstr("Skipping write to dropbox. Empty trace."));
 }
 
@@ -1080,53 +878,45 @@
   trigger->set_name("trigger_name_3");
   trigger->set_stop_delay_ms(60000);
 
-  // We have to construct all the processes we want to fork before we start the
-  // service with |StartServiceIfRequired()|. this is because it is unsafe
-  // (could deadlock) to fork after we've spawned some threads which might
-  // printf (and thus hold locks).
+  // We have 5 normal preample packets (trace config, clock, system info, sync
+  // marker, stats) and then since this is a trace with a trigger config we have
+  // an additional ReceivedTriggers packet.
+  base::TestTaskRunner task_runner;
+
+  // Enable tracing and detach as soon as it gets started.
+  TestHelper helper(&task_runner);
+  helper.StartServiceIfRequired();
+  auto* fake_producer = helper.ConnectFakeProducer();
+  EXPECT_TRUE(fake_producer);
+
   const std::string path = RandomTraceFileName();
-  auto perfetto_proc = ExecPerfetto(
-      {
-          "-o",
-          path,
-          "-c",
-          "-",
-      },
-      trace_config.SerializeAsString());
+  std::thread background_trace([&path, &trace_config, this]() {
+    EXPECT_EQ(0, ExecPerfetto(
+                     {
+                         "-o", path, "-c", "-",
+                     },
+                     trace_config.SerializeAsString()));
+  });
+
+  helper.WaitForProducerEnabled();
+  // Wait for the producer to start, and then write out 11 packets, before the
+  // trace actually starts (the trigger is seen).
+  auto on_data_written = task_runner.CreateCheckpoint("data_written_1");
+  fake_producer->ProduceEventBatch(helper.WrapTask(on_data_written));
+  task_runner.RunUntilCheckpoint("data_written_1");
 
   std::string triggers = R"(
     activate_triggers: "trigger_name_2"
     activate_triggers: "trigger_name"
     activate_triggers: "trigger_name_3"
   )";
-  auto perfetto_proc_2 = ExecPerfetto(
-      {
-          "-o",
-          path,
-          "-c",
-          "-",
-          "--txt",
-      },
-      triggers);
 
-  // Start the service and connect a simple fake producer.
-  StartServiceIfRequiredNoNewExecsAfterThis();
-  auto* fake_producer = ConnectFakeProducer();
-  EXPECT_TRUE(fake_producer);
-
-  std::thread background_trace([&perfetto_proc]() {
-    std::string stderr_str;
-    EXPECT_EQ(0, perfetto_proc.Run(&stderr_str)) << stderr_str;
-  });
-
-  WaitForProducerEnabled();
-  // Wait for the producer to start, and then write out 11 packets, before the
-  // trace actually starts (the trigger is seen).
-  auto on_data_written = task_runner_.CreateCheckpoint("data_written_1");
-  fake_producer->ProduceEventBatch(WrapTask(on_data_written));
-  task_runner_.RunUntilCheckpoint("data_written_1");
-
-  EXPECT_EQ(0, perfetto_proc_2.Run(&stderr_)) << "stderr: " << stderr_;
+  EXPECT_EQ(0, ExecPerfetto(
+                   {
+                       "-o", path, "-c", "-", "--txt",
+                   },
+                   triggers))
+      << "stderr: " << stderr_;
 
   background_trace.join();
 
@@ -1134,7 +924,7 @@
   base::ReadFile(path, &trace_str);
   protos::Trace trace;
   ASSERT_TRUE(trace.ParseFromString(trace_str));
-  EXPECT_LT(static_cast<int>(kMessageCount), trace.packet_size());
+  EXPECT_LT(kMessageCount, trace.packet_size());
   bool seen_first_trigger = false;
   for (const auto& packet : trace.packet()) {
     if (packet.data_case() == protos::TracePacket::kTraceConfig) {
@@ -1182,45 +972,41 @@
   trigger->set_name("trigger_name_3");
   trigger->set_stop_delay_ms(60000);
 
-  // We have to construct all the processes we want to fork before we start the
-  // service with |StartServiceIfRequired()|. this is because it is unsafe
-  // (could deadlock) to fork after we've spawned some threads which might
-  // printf (and thus hold locks).
+  // We have 5 normal preample packets (trace config, clock, system info, sync
+  // marker, stats) and then since this is a trace with a trigger config we have
+  // an additional ReceivedTriggers packet.
+  base::TestTaskRunner task_runner;
+
+  // Enable tracing and detach as soon as it gets started.
+  TestHelper helper(&task_runner);
+  helper.StartServiceIfRequired();
+  auto* fake_producer = helper.ConnectFakeProducer();
+  EXPECT_TRUE(fake_producer);
+
   const std::string path = RandomTraceFileName();
+
+  std::string trace_str;
+  EXPECT_FALSE(base::ReadFile(path, &trace_str));
+
   std::string triggers = R"(
     activate_triggers: "trigger_name_2"
     activate_triggers: "trigger_name"
     activate_triggers: "trigger_name_3"
   )";
-  auto perfetto_proc = ExecPerfetto(
-      {
-          "-o",
-          path,
-          "-c",
-          "-",
-          "--txt",
-      },
-      triggers);
 
-  // Start the service and connect a simple fake producer.
-  StartServiceIfRequiredNoNewExecsAfterThis();
-  auto* fake_producer = ConnectFakeProducer();
-  EXPECT_TRUE(fake_producer);
-
-  std::string trace_str;
-  EXPECT_FALSE(base::ReadFile(path, &trace_str));
-
-  EXPECT_EQ(0, perfetto_proc.Run(&stderr_)) << "stderr: " << stderr_;
+  EXPECT_EQ(0, ExecPerfetto(
+                   {
+                       "-o", path, "-c", "-", "--txt",
+                   },
+                   triggers))
+      << "stderr: " << stderr_;
 
   EXPECT_FALSE(base::ReadFile(path, &trace_str));
 }
 
 TEST_F(PerfettoCmdlineTest, NoSanitizers(Query)) {
-  auto query = ExecPerfetto({"--query"});
-  auto query_raw = ExecPerfetto({"--query-raw"});
-  StartServiceIfRequiredNoNewExecsAfterThis();
-  EXPECT_EQ(0, query.Run(&stderr_)) << stderr_;
-  EXPECT_EQ(0, query_raw.Run(&stderr_)) << stderr_;
+  EXPECT_EQ(0, ExecPerfetto({"--query"})) << stderr_;
+  EXPECT_EQ(0, ExecPerfetto({"--query-raw"})) << stderr_;
 }
 
 }  // namespace perfetto
diff --git a/test/end_to_end_shared_memory_fuzzer.cc b/test/end_to_end_shared_memory_fuzzer.cc
index 052f888..c390340 100644
--- a/test/end_to_end_shared_memory_fuzzer.cc
+++ b/test/end_to_end_shared_memory_fuzzer.cc
@@ -20,21 +20,25 @@
 
 #include "perfetto/base/logging.h"
 #include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/tracing/core/producer.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "perfetto/ext/tracing/ipc/default_socket.h"
-#include "perfetto/ext/tracing/ipc/producer_ipc_client.h"
-#include "perfetto/ext/tracing/ipc/service_ipc_host.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/trace/test_event.pbzero.h"
 #include "perfetto/tracing/core/data_source_config.h"
 #include "perfetto/tracing/core/data_source_descriptor.h"
-#include "protos/perfetto/trace/test_event.pbzero.h"
+#include "perfetto/tracing/core/producer.h"
+#include "perfetto/tracing/core/trace_writer.h"
+#include "perfetto/tracing/ipc/producer_ipc_client.h"
+#include "perfetto/tracing/ipc/service_ipc_host.h"
 #include "src/base/test/test_task_runner.h"
+#include "src/tracing/ipc/default_socket.h"
 #include "test/task_runner_thread.h"
 #include "test/task_runner_thread_delegates.h"
 #include "test/test_helper.h"
 
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/trace_packet.pb.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
+
+namespace perfetto {
+namespace shm_fuzz {
 
 // If we're building on Android and starting the daemons ourselves,
 // create the sockets in a world-writable location.
@@ -45,10 +49,6 @@
 #define TEST_PRODUCER_SOCK_NAME ::perfetto::GetProducerSocket()
 #endif
 
-namespace perfetto {
-namespace shm_fuzz {
-namespace {
-
 // Fake producer writing a protozero message of data into shared memory
 // buffer, followed by a sentinel message to signal completion to the
 // consumer.
@@ -85,7 +85,7 @@
         static_cast<BufferID>(source_config.target_buffer()));
     {
       auto packet = trace_writer->NewTracePacket();
-      packet->stream_writer_for_testing()->WriteBytes(data_, size_);
+      packet->stream_writer_->WriteBytes(data_, size_);
     }
     trace_writer->Flush();
 
@@ -99,7 +99,7 @@
   void StopDataSource(DataSourceInstanceID) override {}
   void OnTracingSetup() override {}
   void Flush(FlushRequestID, const DataSourceInstanceID*, size_t) override {}
-  void ClearIncrementalState(const DataSourceInstanceID*, size_t) override {}
+  void ClearIncrementalState(const DataSourceInstanceID*, size_t) {}
 
  private:
   const std::string name_;
@@ -165,7 +165,6 @@
   return 0;
 }
 
-}  // namespace
 }  // namespace shm_fuzz
 }  // namespace perfetto
 
diff --git a/test/fake_producer.cc b/test/fake_producer.cc
index 17f80f0..0ae52a1 100644
--- a/test/fake_producer.cc
+++ b/test/fake_producer.cc
@@ -19,17 +19,15 @@
 #include <condition_variable>
 #include <mutex>
 
+#include "gtest/gtest.h"
 #include "perfetto/base/logging.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/ext/traced/traced.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/core/trace_writer.h"
-#include "perfetto/tracing/core/data_source_config.h"
-
-#include "protos/perfetto/config/test_config.gen.h"
-#include "protos/perfetto/trace/test_event.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/base/utils.h"
+#include "perfetto/trace/test_event.pbzero.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/traced/traced.h"
+#include "perfetto/tracing/core/trace_packet.h"
+#include "perfetto/tracing/core/trace_writer.h"
 
 namespace perfetto {
 
@@ -58,7 +56,7 @@
 
 void FakeProducer::OnDisconnect() {
   PERFETTO_DCHECK_THREAD(thread_checker_);
-  PERFETTO_FATAL("Producer unexpectedly disconnected from the service");
+  FAIL() << "Producer unexpectedly disconnected from the service";
 }
 
 void FakeProducer::SetupDataSource(DataSourceInstanceID,
diff --git a/test/fake_producer.h b/test/fake_producer.h
index 4f2c6be..460d88c 100644
--- a/test/fake_producer.h
+++ b/test/fake_producer.h
@@ -21,11 +21,11 @@
 #include <random>
 #include <string>
 
-#include "perfetto/ext/base/thread_checker.h"
-#include "perfetto/ext/tracing/core/producer.h"
-#include "perfetto/ext/tracing/ipc/producer_ipc_client.h"
+#include "perfetto/base/thread_checker.h"
 #include "perfetto/tracing/core/data_source_descriptor.h"
+#include "perfetto/tracing/core/producer.h"
 #include "perfetto/tracing/core/trace_config.h"
+#include "perfetto/tracing/ipc/producer_ipc_client.h"
 #include "src/base/test/test_task_runner.h"
 
 namespace perfetto {
diff --git a/test/gtest_and_gmock.h b/test/gtest_and_gmock.h
deleted file mode 100644
index aa733e2..0000000
--- a/test/gtest_and_gmock.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2019 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 TEST_GTEST_AND_GMOCK_H_
-#define TEST_GTEST_AND_GMOCK_H_
-
-// This file is used to proxy the include of gtest/gmock headers and suppress
-// the warnings generated by that.
-// There are two ways we suppress gtest/gmock warnings:
-// 1: Using config("test_warning_suppressions") in BUILD.gn
-// 2: Via this file.
-// 1 applies recursively also to the test translation units, 2 applies only
-// to gmock/gtest includes.
-
-#if defined(__GNUC__)  // GCC & clang
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wundef"
-#pragma GCC diagnostic ignored "-Wdeprecated"
-#pragma GCC diagnostic ignored "-Wmissing-noreturn"
-#pragma GCC diagnostic ignored "-Wsign-conversion"
-#endif  // __GNUC__
-
-#if defined(__clang__)
-#pragma GCC diagnostic ignored "-Wshift-sign-overflow"
-#pragma GCC diagnostic ignored "-Wcomma"
-#endif
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#if defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
-
-#endif  // TEST_GTEST_AND_GMOCK_H_
diff --git a/test/metrics/android_batt_counters.out b/test/metrics/android_batt_counters.out
deleted file mode 100644
index 82c7a2e..0000000
--- a/test/metrics/android_batt_counters.out
+++ /dev/null
@@ -1,29 +0,0 @@
-android_batt{
-   battery_counters{
-      timestamp_ns: 20
-      charge_counter_uah: 52
-      capacity_percent: 0.2
-      current_ua: 10
-      current_avg_ua: 12
-   }
-   battery_counters {
-      timestamp_ns: 52
-      charge_counter_uah: 32
-      capacity_percent: 0.8
-      current_ua: 8
-      current_avg_ua: 93
-   }
-   battery_counters {
-      timestamp_ns: 80
-      charge_counter_uah: 15
-      capacity_percent: 0.5
-      current_ua: 9
-      current_avg_ua: 5
-   }
-   battery_counters {
-      timestamp_ns: 92
-      charge_counter_uah: 21
-      capacity_percent: 0.3
-      current_avg_ua: 25
-   }
-}
\ No newline at end of file
diff --git a/test/metrics/android_ion.out b/test/metrics/android_ion.out
deleted file mode 100644
index 0e22a97..0000000
--- a/test/metrics/android_ion.out
+++ /dev/null
@@ -1,14 +0,0 @@
-android_ion {
-  buffer {
-    name: "adsp"
-    avg_size_bytes: 1000.0
-    min_size_bytes: 1000.0
-    max_size_bytes: 1000.0
-  }
-  buffer {
-    name: "system"
-    avg_size_bytes: 1500.0
-    min_size_bytes: 1000.0
-    max_size_bytes: 2000.0
-  }
-}
diff --git a/test/metrics/android_ion.py b/test/metrics/android_ion.py
deleted file mode 100644
index 4993245..0000000
--- a/test/metrics/android_ion.py
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/python
-# 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.
-
-from os import sys, path
-
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_process_tree_packet()
-trace.add_process(1, 0, 'init')
-trace.add_process(2, 1, 'system_server')
-trace.add_process(3, 1, 'com.google.android.calendar')
-
-trace.add_ftrace_packet(cpu=0)
-trace.add_ion_event(ts=100, tid=3, heap_name='system', size=1000)
-trace.add_ion_event(ts=150, tid=3, heap_name='adsp', size=1000)
-trace.add_ion_event(ts=200, tid=3, heap_name='system', size=2000)
-trace.add_ion_event(ts=299, tid=3, heap_name='adsp', size=1000)
-
-print(trace.trace.SerializeToString())
diff --git a/test/metrics/android_lmk.py b/test/metrics/android_lmk.py
deleted file mode 100644
index a6cc12e..0000000
--- a/test/metrics/android_lmk.py
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/usr/bin/python
-# 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.
-
-from os import sys, path
-
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_process_tree_packet()
-trace.add_process(1, 0, 'init')
-trace.add_process(2, 1, 'system_server')
-trace.add_process(3, 1, 'com.google.android.calendar')
-trace.add_thread(4, 3, 'mythread')
-
-trace.add_ftrace_packet(cpu=0)
-trace.add_oom_score_update(ts=100, oom_score_adj=0, pid=3)
-trace.add_oom_score_update(ts=105, oom_score_adj=900, pid=3)
-trace.add_kernel_lmk(ts=150, tid=3)
-trace.add_oom_score_update(ts=151, oom_score_adj=0, pid=3)
-trace.add_kernel_lmk(ts=152, tid=4)
-
-print(trace.trace.SerializeToString())
diff --git a/test/metrics/android_mem_by_priority.out b/test/metrics/android_mem_by_priority.out
deleted file mode 100644
index 4189eac..0000000
--- a/test/metrics/android_mem_by_priority.out
+++ /dev/null
@@ -1,152 +0,0 @@
-android_mem {
-  process_metrics {
-    process_name: "com.google.android.calendar"
-    total_counters {
-      anon_rss {
-        min: 2000.0
-        max: 4000.0
-        avg: 3000.0
-      }
-      file_rss {
-        min: 10000.0
-        max: 10000.0
-        avg: 10000.0
-      }
-      swap {
-        min: 0.0
-        max: 0.0
-        avg: 0.0
-      }
-      anon_and_swap {
-        min: 2000.0
-        max: 4000.0
-        avg: 3000.0
-      }
-    }
-    priority_breakdown {
-      priority: "cached"
-      counters {
-        anon_rss {
-          min: 3000.0
-          max: 3000.0
-          avg: 3000.0
-        }
-        file_rss {
-          min: 10000.0
-          max: 10000.0
-          avg: 10000.0
-        }
-        swap {
-          min: 0.0
-          max: 0.0
-          avg: 0.0
-        }
-        anon_and_swap {
-          min: 3000.0
-          max: 3000.0
-          avg: 3000.0
-        }
-      }
-    }
-    priority_breakdown {
-      priority: "foreground"
-      counters {
-        anon_rss {
-          min: 2000.0
-          max: 4000.0
-          avg: 3000.0
-        }
-        file_rss {
-          min: 10000.0
-          max: 10000.0
-          avg: 10000.0
-        }
-        swap {
-          min: 0.0
-          max: 0.0
-          avg: 0.0
-        }
-        anon_and_swap {
-          min: 2000.0
-          max: 4000.0
-          avg: 3000.0
-        }
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.google.android.deskclock"
-    total_counters {
-      anon_rss {
-        min: 4000.0
-        max: 8000.0
-        avg: 6000.0
-      }
-      file_rss {
-        min: 10000.0
-        max: 10000.0
-        avg: 10000.0
-      }
-      swap {
-        min: 0.0
-        max: 0.0
-        avg: 0.0
-      }
-      anon_and_swap {
-        min: 4000.0
-        max: 8000.0
-        avg: 6000.0
-      }
-    }
-    priority_breakdown {
-      priority: "cached"
-      counters {
-        anon_rss {
-          min: 4000.0
-          max: 8000.0
-          avg: 6000.0
-        }
-        file_rss {
-          min: 10000.0
-          max: 10000.0
-          avg: 10000.0
-        }
-        swap {
-          min: 0.0
-          max: 0.0
-          avg: 0.0
-        }
-        anon_and_swap {
-          min: 4000.0
-          max: 8000.0
-          avg: 6000.0
-        }
-      }
-    }
-    priority_breakdown {
-      priority: "foreground"
-      counters {
-        anon_rss {
-          min: 6000.0
-          max: 6000.0
-          avg: 6000.0
-        }
-        file_rss {
-          min: 10000.0
-          max: 10000.0
-          avg: 10000.0
-        }
-        swap {
-          min: 0.0
-          max: 0.0
-          avg: 0.0
-        }
-        anon_and_swap {
-          min: 6000.0
-          max: 6000.0
-          avg: 6000.0
-        }
-      }
-    }
-  }
-}
diff --git a/test/metrics/android_mem_by_priority.py b/test/metrics/android_mem_by_priority.py
deleted file mode 100644
index 0d9227b..0000000
--- a/test/metrics/android_mem_by_priority.py
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/usr/bin/python
-# 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.
-
-from os import sys, path
-
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-file_member = 0
-anon_member = 1
-swap_member = 2
-
-trace = synth_common.create_trace()
-trace.add_process_tree_packet()
-trace.add_process(1, 0, 'init')
-trace.add_process(2, 1, 'system_server')
-trace.add_process(3, 1, 'com.google.android.calendar')
-trace.add_process(4, 1, 'com.google.android.deskclock')
-
-trace.add_ftrace_packet(cpu=0)
-# We are not yet aware of the OOM score. Will be ignored in the breakdowns.
-trace.add_rss_stat(100, 3, file_member, 10000)
-trace.add_rss_stat(100, 4, file_member, 10000)
-trace.add_rss_stat(100, 3, anon_member, 3000)
-trace.add_rss_stat(100, 4, anon_member, 6000)
-trace.add_rss_stat(100, 3, swap_member, 0)
-trace.add_rss_stat(100, 4, swap_member, 0)
-
-# Update the OOM scores.
-trace.add_oom_score_update(200, 0, 3)
-trace.add_oom_score_update(200, 900, 4)
-
-trace.add_rss_stat(200, 3, anon_member, 2000)
-trace.add_rss_stat(200, 4, anon_member, 4000)
-
-trace.add_rss_stat(250, 3, anon_member, 4000)
-trace.add_rss_stat(250, 4, anon_member, 8000)
-
-trace.add_oom_score_update(300, 910, 3)
-trace.add_oom_score_update(300, 0, 4)
-
-trace.add_rss_stat(300, 3, anon_member, 3000)
-trace.add_rss_stat(300, 4, anon_member, 6000)
-
-print(trace.trace.SerializeToString())
diff --git a/test/metrics/android_mem_counters.out b/test/metrics/android_mem_counters.out
deleted file mode 100644
index c729120..0000000
--- a/test/metrics/android_mem_counters.out
+++ /dev/null
@@ -1,3157 +0,0 @@
-android_mem {
-  process_metrics {
-    process_name: "/system/bin/adbd"
-    total_counters {
-      anon_rss {
-        min: 2523136
-        max: 2523136
-        avg: 2523136
-      }
-      file_rss {
-        min: 2392064
-        max: 2392064
-        avg: 2392064
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 2523136
-        max: 2523136
-        avg: 2523136
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/apexd"
-    total_counters {
-      anon_rss {
-        min: 884736
-        max: 884736
-        avg: 884736
-      }
-      file_rss {
-        min: 2101248
-        max: 2101248
-        avg: 2101248
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 884736
-        max: 884736
-        avg: 884736
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/audioserver"
-    total_counters {
-      anon_rss {
-        min: 3989504
-        max: 3989504
-        avg: 3989504
-      }
-      file_rss {
-        min: 9334784
-        max: 9334784
-        avg: 9334784
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 3989504
-        max: 3989504
-        avg: 3989504
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/cameraserver"
-    total_counters {
-      anon_rss {
-        min: 2052096
-        max: 2191360
-        avg: 2075342.7950470024
-      }
-      file_rss {
-        min: 6197248
-        max: 6594560
-        avg: 6277623.7430821592
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 2052096
-        max: 2191360
-        avg: 2075342.7950470024
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/drmserver"
-    total_counters {
-      anon_rss {
-        min: 1552384
-        max: 1552384
-        avg: 1552384
-      }
-      file_rss {
-        min: 4943872
-        max: 4943872
-        avg: 4943872
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1552384
-        max: 1552384
-        avg: 1552384
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/folio_daemon"
-    total_counters {
-      anon_rss {
-        min: 3444736
-        max: 3444736
-        avg: 3444736
-      }
-      file_rss {
-        min: 8974336
-        max: 8974336
-        avg: 8974336
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 3444736
-        max: 3444736
-        avg: 3444736
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/gatekeeperd"
-    total_counters {
-      anon_rss {
-        min: 1134592
-        max: 1134592
-        avg: 1134592
-      }
-      file_rss {
-        min: 2863104
-        max: 2863104
-        avg: 2863104
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1134592
-        max: 1134592
-        avg: 1134592
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/gpuservice"
-    total_counters {
-      anon_rss {
-        min: 1146880
-        max: 1146880
-        avg: 1146880
-      }
-      file_rss {
-        min: 2678784
-        max: 2678784
-        avg: 2678784
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1146880
-        max: 1146880
-        avg: 1146880
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/healthd"
-    total_counters {
-      anon_rss {
-        min: 794624
-        max: 794624
-        avg: 794624
-      }
-      file_rss {
-        min: 2117632
-        max: 2117632
-        avg: 2117632
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 794624
-        max: 794624
-        avg: 794624
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/hw/android.hidl.allocator@1.0-service"
-    total_counters {
-      anon_rss {
-        min: 770048
-        max: 770048
-        avg: 770048
-      }
-      file_rss {
-        min: 1875968
-        max: 1875968
-        avg: 1875968
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 770048
-        max: 770048
-        avg: 770048
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/hw/android.system.suspend@1.0-service"
-    total_counters {
-      anon_rss {
-        min: 868352
-        max: 868352
-        avg: 868352
-      }
-      file_rss {
-        min: 2994176
-        max: 2994176
-        avg: 2994176
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 868352
-        max: 868352
-        avg: 868352
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/hwservicemanager"
-    total_counters {
-      anon_rss {
-        min: 1314816
-        max: 1417216
-        avg: 1334151.2064734141
-      }
-      file_rss {
-        min: 2895872
-        max: 2940928
-        avg: 2905098.926868665
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1314816
-        max: 1417216
-        avg: 1334151.2064734141
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/incidentd"
-    total_counters {
-      anon_rss {
-        min: 974848
-        max: 974848
-        avg: 974848
-      }
-      file_rss {
-        min: 2359296
-        max: 2359296
-        avg: 2359296
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 974848
-        max: 974848
-        avg: 974848
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/init"
-    total_counters {
-      anon_rss {
-        min: 1355776
-        max: 2281472
-        avg: 1686186.6666666667
-      }
-      file_rss {
-        min: 2297856
-        max: 3047424
-        avg: 2681514.6666666665
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1355776
-        max: 2281472
-        avg: 1686186.6666666667
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/installd"
-    total_counters {
-      anon_rss {
-        min: 1699840
-        max: 1699840
-        avg: 1699840
-      }
-      file_rss {
-        min: 2519040
-        max: 2519040
-        avg: 2519040
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1699840
-        max: 1699840
-        avg: 1699840
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/iorapd"
-    total_counters {
-      anon_rss {
-        min: 749568
-        max: 749568
-        avg: 749568
-      }
-      file_rss {
-        min: 1724416
-        max: 1724416
-        avg: 1724416
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 749568
-        max: 749568
-        avg: 749568
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/ip6tables-restore"
-    total_counters {
-      anon_rss {
-        min: 897024
-        max: 897024
-        avg: 897024
-      }
-      file_rss {
-        min: 1445888
-        max: 1445888
-        avg: 1445888
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 897024
-        max: 897024
-        avg: 897024
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/iptables-restore"
-    total_counters {
-      anon_rss {
-        min: 901120
-        max: 901120
-        avg: 901120
-      }
-      file_rss {
-        min: 1429504
-        max: 1429504
-        avg: 1429504
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 901120
-        max: 901120
-        avg: 901120
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/keystore"
-    total_counters {
-      anon_rss {
-        min: 1302528
-        max: 1302528
-        avg: 1302528
-      }
-      file_rss {
-        min: 3624960
-        max: 3624960
-        avg: 3624960
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1302528
-        max: 1302528
-        avg: 1302528
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/lmkd"
-    total_counters {
-      anon_rss {
-        min: 569344
-        max: 569344
-        avg: 569344
-      }
-      file_rss {
-        min: 1130496
-        max: 1130496
-        avg: 1130496
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 569344
-        max: 569344
-        avg: 569344
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/logd"
-    total_counters {
-      anon_rss {
-        min: 7372800
-        max: 7553024
-        avg: 7448831.74711258
-      }
-      file_rss {
-        min: 1527808
-        max: 1527808
-        avg: 1527808
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 7372800
-        max: 7553024
-        avg: 7448831.74711258
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/mediadrmserver"
-    total_counters {
-      anon_rss {
-        min: 823296
-        max: 823296
-        avg: 823296
-      }
-      file_rss {
-        min: 2424832
-        max: 2424832
-        avg: 2424832
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 823296
-        max: 823296
-        avg: 823296
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/mediaserver"
-    total_counters {
-      anon_rss {
-        min: 3031040
-        max: 3248128
-        avg: 3093219.997135757
-      }
-      file_rss {
-        min: 9068544
-        max: 9179136
-        avg: 9086542.591674462
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 3031040
-        max: 3248128
-        avg: 3093219.997135757
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/netd"
-    total_counters {
-      anon_rss {
-        min: 1515520
-        max: 1515520
-        avg: 1515520
-      }
-      file_rss {
-        min: 3424256
-        max: 3424256
-        avg: 3424256
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1515520
-        max: 1515520
-        avg: 1515520
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/perfprofd"
-    total_counters {
-      anon_rss {
-        min: 1691648
-        max: 1691648
-        avg: 1691648
-      }
-      file_rss {
-        min: 3538944
-        max: 3538944
-        avg: 3538944
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1691648
-        max: 1691648
-        avg: 1691648
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/servicemanager"
-    total_counters {
-      anon_rss {
-        min: 888832
-        max: 888832
-        avg: 888832
-      }
-      file_rss {
-        min: 1548288
-        max: 1548288
-        avg: 1548288
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 888832
-        max: 888832
-        avg: 888832
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/statsd"
-    total_counters {
-      anon_rss {
-        min: 1196032
-        max: 1196032
-        avg: 1196032
-      }
-      file_rss {
-        min: 3047424
-        max: 3047424
-        avg: 3047424
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1196032
-        max: 1196032
-        avg: 1196032
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/storaged"
-    total_counters {
-      anon_rss {
-        min: 1069056
-        max: 1069056
-        avg: 1069056
-      }
-      file_rss {
-        min: 2637824
-        max: 2637824
-        avg: 2637824
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1069056
-        max: 1069056
-        avg: 1069056
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/surfaceflinger"
-    total_counters {
-      anon_rss {
-        min: 8888320
-        max: 9207808
-        avg: 9034572.8459068146
-      }
-      file_rss {
-        min: 16490496
-        max: 16498688
-        avg: 16492131.200899113
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 8888320
-        max: 9207808
-        avg: 9034572.8459068146
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/thermalserviced"
-    total_counters {
-      anon_rss {
-        min: 901120
-        max: 901120
-        avg: 901120
-      }
-      file_rss {
-        min: 2269184
-        max: 2269184
-        avg: 2269184
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 901120
-        max: 901120
-        avg: 901120
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/tombstoned"
-    total_counters {
-      anon_rss {
-        min: 552960
-        max: 552960
-        avg: 552960
-      }
-      file_rss {
-        min: 1138688
-        max: 1138688
-        avg: 1138688
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 552960
-        max: 552960
-        avg: 552960
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/traced"
-    total_counters {
-      anon_rss {
-        min: 937984
-        max: 7172096
-        avg: 2960290.8411428952
-      }
-      file_rss {
-        min: 1740800
-        max: 1744896
-        avg: 1743446.0249764551
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 937984
-        max: 7172096
-        avg: 2960290.8411428952
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/traced_probes"
-    total_counters {
-      anon_rss {
-        min: 929792
-        max: 1056768
-        avg: 992675.73074393929
-      }
-      file_rss {
-        min: 1863680
-        max: 1863680
-        avg: 1863680
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 929792
-        max: 1056768
-        avg: 992675.73074393929
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/ueventd"
-    total_counters {
-      anon_rss {
-        min: 1437696
-        max: 1437696
-        avg: 1437696
-      }
-      file_rss {
-        min: 2740224
-        max: 2740224
-        avg: 2740224
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1437696
-        max: 1437696
-        avg: 1437696
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/update_engine"
-    total_counters {
-      anon_rss {
-        min: 1421312
-        max: 1421312
-        avg: 1421312
-      }
-      file_rss {
-        min: 4141056
-        max: 4141056
-        avg: 4141056
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1421312
-        max: 1421312
-        avg: 1421312
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/vold"
-    total_counters {
-      anon_rss {
-        min: 1830912
-        max: 1830912
-        avg: 1830912
-      }
-      file_rss {
-        min: 3612672
-        max: 3612672
-        avg: 3612672
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1830912
-        max: 1830912
-        avg: 1830912
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/system/bin/wificond"
-    total_counters {
-      anon_rss {
-        min: 1167360
-        max: 1224704
-        avg: 1201049.4439232084
-      }
-      file_rss {
-        min: 2777088
-        max: 2777088
-        avg: 2777088
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1167360
-        max: 1224704
-        avg: 1201049.4439232084
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/adsprpcd"
-    total_counters {
-      anon_rss {
-        min: 745472
-        max: 745472
-        avg: 745472
-      }
-      file_rss {
-        min: 1507328
-        max: 1507328
-        avg: 1507328
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 745472
-        max: 745472
-        avg: 745472
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/chre"
-    total_counters {
-      anon_rss {
-        min: 1929216
-        max: 1929216
-        avg: 1929216
-      }
-      file_rss {
-        min: 1703936
-        max: 1703936
-        avg: 1703936
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1929216
-        max: 1929216
-        avg: 1929216
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/cnd"
-    total_counters {
-      anon_rss {
-        min: 1552384
-        max: 1552384
-        avg: 1552384
-      }
-      file_rss {
-        min: 3313664
-        max: 3313664
-        avg: 3313664
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1552384
-        max: 1552384
-        avg: 1552384
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/cnss-daemon"
-    total_counters {
-      anon_rss {
-        min: 1363968
-        max: 1363968
-        avg: 1363968
-      }
-      file_rss {
-        min: 2265088
-        max: 2265088
-        avg: 2265088
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1363968
-        max: 1363968
-        avg: 1363968
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/esed"
-    total_counters {
-      anon_rss {
-        min: 921600
-        max: 921600
-        avg: 921600
-      }
-      file_rss {
-        min: 2301952
-        max: 2301952
-        avg: 2301952
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 921600
-        max: 921600
-        avg: 921600
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.audio@2.0-service"
-    total_counters {
-      anon_rss {
-        min: 7827456
-        max: 7835648
-        avg: 7828961.4625952831
-      }
-      file_rss {
-        min: 5828608
-        max: 5853184
-        avg: 5833124.38778585
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 7827456
-        max: 7835648
-        avg: 7828961.4625952831
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.biometrics.fingerprint@2.1-service.fpc"
-    total_counters {
-      anon_rss {
-        min: 987136
-        max: 987136
-        avg: 987136
-      }
-      file_rss {
-        min: 2682880
-        max: 2682880
-        avg: 2682880
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 987136
-        max: 987136
-        avg: 987136
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.bluetooth@1.0-service-qti"
-    total_counters {
-      anon_rss {
-        min: 1134592
-        max: 1134592
-        avg: 1134592
-      }
-      file_rss {
-        min: 2670592
-        max: 2670592
-        avg: 2670592
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1134592
-        max: 1134592
-        avg: 1134592
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.boot@1.0-service"
-    total_counters {
-      anon_rss {
-        min: 933888
-        max: 933888
-        avg: 933888
-      }
-      file_rss {
-        min: 2416640
-        max: 2416640
-        avg: 2416640
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 933888
-        max: 933888
-        avg: 933888
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.camera.provider@2.4-service"
-    total_counters {
-      anon_rss {
-        min: 19959808
-        max: 30146560
-        avg: 20339380.697334375
-      }
-      file_rss {
-        min: 19906560
-        max: 20475904
-        avg: 19984240.090238161
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 19959808
-        max: 30146560
-        avg: 20339380.697334375
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.cas@1.0-service"
-    total_counters {
-      anon_rss {
-        min: 753664
-        max: 753664
-        avg: 753664
-      }
-      file_rss {
-        min: 2359296
-        max: 2359296
-        avg: 2359296
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 753664
-        max: 753664
-        avg: 753664
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.configstore@1.1-service"
-    total_counters {
-      anon_rss {
-        min: 954368
-        max: 954368
-        avg: 954368
-      }
-      file_rss {
-        min: 2400256
-        max: 2400256
-        avg: 2400256
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 954368
-        max: 954368
-        avg: 954368
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.contexthub@1.0-service"
-    total_counters {
-      anon_rss {
-        min: 925696
-        max: 925696
-        avg: 925696
-      }
-      file_rss {
-        min: 2424832
-        max: 2424832
-        avg: 2424832
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 925696
-        max: 925696
-        avg: 925696
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.drm@1.0-service"
-    total_counters {
-      anon_rss {
-        min: 884736
-        max: 884736
-        avg: 884736
-      }
-      file_rss {
-        min: 2772992
-        max: 2772992
-        avg: 2772992
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 884736
-        max: 884736
-        avg: 884736
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.drm@1.1-service.clearkey"
-    total_counters {
-      anon_rss {
-        min: 1056768
-        max: 1056768
-        avg: 1056768
-      }
-      file_rss {
-        min: 2912256
-        max: 2912256
-        avg: 2912256
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1056768
-        max: 1056768
-        avg: 1056768
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.drm@1.1-service.widevine"
-    total_counters {
-      anon_rss {
-        min: 901120
-        max: 901120
-        avg: 901120
-      }
-      file_rss {
-        min: 3371008
-        max: 3371008
-        avg: 3371008
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 901120
-        max: 901120
-        avg: 901120
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.dumpstate@1.0-service.wahoo"
-    total_counters {
-      anon_rss {
-        min: 856064
-        max: 856064
-        avg: 856064
-      }
-      file_rss {
-        min: 2285568
-        max: 2285568
-        avg: 2285568
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 856064
-        max: 856064
-        avg: 856064
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.gatekeeper@1.0-service-qti"
-    total_counters {
-      anon_rss {
-        min: 978944
-        max: 978944
-        avg: 978944
-      }
-      file_rss {
-        min: 2523136
-        max: 2523136
-        avg: 2523136
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 978944
-        max: 978944
-        avg: 978944
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.gnss@1.0-service-qti"
-    total_counters {
-      anon_rss {
-        min: 2297856
-        max: 2297856
-        avg: 2297856
-      }
-      file_rss {
-        min: 4608000
-        max: 4608000
-        avg: 4608000
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 2297856
-        max: 2297856
-        avg: 2297856
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.graphics.allocator@2.0-service"
-    total_counters {
-      anon_rss {
-        min: 1036288
-        max: 1036288
-        avg: 1036288
-      }
-      file_rss {
-        min: 2646016
-        max: 2646016
-        avg: 2646016
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1036288
-        max: 1036288
-        avg: 1036288
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.graphics.composer@2.1-service"
-    total_counters {
-      anon_rss {
-        min: 7061504
-        max: 7127040
-        avg: 7093193.651419105
-      }
-      file_rss {
-        min: 6201344
-        max: 6209536
-        avg: 6206722.4514569445
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 7061504
-        max: 7127040
-        avg: 7093193.651419105
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.health@2.0-service.wahoo"
-    total_counters {
-      anon_rss {
-        min: 884736
-        max: 884736
-        avg: 884736
-      }
-      file_rss {
-        min: 2453504
-        max: 2453504
-        avg: 2453504
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 884736
-        max: 884736
-        avg: 884736
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.keymaster@3.0-service-qti"
-    total_counters {
-      anon_rss {
-        min: 1024000
-        max: 1024000
-        avg: 1024000
-      }
-      file_rss {
-        min: 2637824
-        max: 2637824
-        avg: 2637824
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1024000
-        max: 1024000
-        avg: 1024000
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.light@2.0-service"
-    total_counters {
-      anon_rss {
-        min: 880640
-        max: 880640
-        avg: 880640
-      }
-      file_rss {
-        min: 2248704
-        max: 2248704
-        avg: 2248704
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 880640
-        max: 880640
-        avg: 880640
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.memtrack@1.0-service"
-    total_counters {
-      anon_rss {
-        min: 868352
-        max: 868352
-        avg: 868352
-      }
-      file_rss {
-        min: 2347008
-        max: 2347008
-        avg: 2347008
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 868352
-        max: 868352
-        avg: 868352
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.nfc@1.1-service"
-    total_counters {
-      anon_rss {
-        min: 1064960
-        max: 1064960
-        avg: 1064960
-      }
-      file_rss {
-        min: 2842624
-        max: 2842624
-        avg: 2842624
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1064960
-        max: 1064960
-        avg: 1064960
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.oemlock@1.0-service"
-    total_counters {
-      anon_rss {
-        min: 868352
-        max: 868352
-        avg: 868352
-      }
-      file_rss {
-        min: 2273280
-        max: 2273280
-        avg: 2273280
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 868352
-        max: 868352
-        avg: 868352
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.power@1.2-service.wahoo-libperfmgr"
-    total_counters {
-      anon_rss {
-        min: 1007616
-        max: 1007616
-        avg: 1007616
-      }
-      file_rss {
-        min: 2568192
-        max: 2568192
-        avg: 2568192
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1007616
-        max: 1007616
-        avg: 1007616
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.sensors@1.0-service"
-    total_counters {
-      anon_rss {
-        min: 1605632
-        max: 1605632
-        avg: 1605632
-      }
-      file_rss {
-        min: 4190208
-        max: 4190208
-        avg: 4190208
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1605632
-        max: 1605632
-        avg: 1605632
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.usb@1.1-service.wahoo"
-    total_counters {
-      anon_rss {
-        min: 1064960
-        max: 1064960
-        avg: 1064960
-      }
-      file_rss {
-        min: 2486272
-        max: 2486272
-        avg: 2486272
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1064960
-        max: 1064960
-        avg: 1064960
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.vibrator@1.2-service.wahoo"
-    total_counters {
-      anon_rss {
-        min: 925696
-        max: 925696
-        avg: 925696
-      }
-      file_rss {
-        min: 2416640
-        max: 2416640
-        avg: 2416640
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 925696
-        max: 925696
-        avg: 925696
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.vr@1.0-service.wahoo"
-    total_counters {
-      anon_rss {
-        min: 856064
-        max: 856064
-        avg: 856064
-      }
-      file_rss {
-        min: 2265088
-        max: 2265088
-        avg: 2265088
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 856064
-        max: 856064
-        avg: 856064
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/android.hardware.wifi@1.0-service"
-    total_counters {
-      anon_rss {
-        min: 4300800
-        max: 4362240
-        avg: 4333974.416470373
-      }
-      file_rss {
-        min: 3801088
-        max: 3801088
-        avg: 3801088
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 4300800
-        max: 4362240
-        avg: 4333974.416470373
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/rild"
-    total_counters {
-      anon_rss {
-        min: 4169728
-        max: 4169728
-        avg: 4169728
-      }
-      file_rss {
-        min: 14327808
-        max: 14327808
-        avg: 14327808
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 4169728
-        max: 4169728
-        avg: 4169728
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/hw/wpa_supplicant"
-    total_counters {
-      anon_rss {
-        min: 1421312
-        max: 1425408
-        avg: 1422839.3064999864
-      }
-      file_rss {
-        min: 4632576
-        max: 4632576
-        avg: 4632576
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1421312
-        max: 1425408
-        avg: 1422839.3064999864
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/imsdatadaemon"
-    total_counters {
-      anon_rss {
-        min: 1683456
-        max: 1683456
-        avg: 1683456
-      }
-      file_rss {
-        min: 2973696
-        max: 2973696
-        avg: 2973696
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1683456
-        max: 1683456
-        avg: 1683456
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/imsqmidaemon"
-    total_counters {
-      anon_rss {
-        min: 901120
-        max: 901120
-        avg: 901120
-      }
-      file_rss {
-        min: 1757184
-        max: 1757184
-        avg: 1757184
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 901120
-        max: 901120
-        avg: 901120
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/ipacm"
-    total_counters {
-      anon_rss {
-        min: 1089536
-        max: 1089536
-        avg: 1089536
-      }
-      file_rss {
-        min: 3125248
-        max: 3125248
-        avg: 3125248
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1089536
-        max: 1089536
-        avg: 1089536
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/loc_launcher"
-    total_counters {
-      anon_rss {
-        min: 741376
-        max: 741376
-        avg: 741376
-      }
-      file_rss {
-        min: 1617920
-        max: 1617920
-        avg: 1617920
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 741376
-        max: 741376
-        avg: 741376
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/msm_irqbalance"
-    total_counters {
-      anon_rss {
-        min: 761856
-        max: 761856
-        avg: 761856
-      }
-      file_rss {
-        min: 1630208
-        max: 1630208
-        avg: 1630208
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 761856
-        max: 761856
-        avg: 761856
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/netmgrd"
-    total_counters {
-      anon_rss {
-        min: 3330048
-        max: 3330048
-        avg: 3330048
-      }
-      file_rss {
-        min: 4530176
-        max: 4530176
-        avg: 4530176
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 3330048
-        max: 3330048
-        avg: 3330048
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/oemlock-bridge"
-    total_counters {
-      anon_rss {
-        min: 659456
-        max: 659456
-        avg: 659456
-      }
-      file_rss {
-        min: 1441792
-        max: 1441792
-        avg: 1441792
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 659456
-        max: 659456
-        avg: 659456
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/pd-mapper"
-    total_counters {
-      anon_rss {
-        min: 884736
-        max: 884736
-        avg: 884736
-      }
-      file_rss {
-        min: 1736704
-        max: 1736704
-        avg: 1736704
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 884736
-        max: 884736
-        avg: 884736
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/pm-proxy"
-    total_counters {
-      anon_rss {
-        min: 778240
-        max: 778240
-        avg: 778240
-      }
-      file_rss {
-        min: 1798144
-        max: 1798144
-        avg: 1798144
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 778240
-        max: 778240
-        avg: 778240
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/pm-service"
-    total_counters {
-      anon_rss {
-        min: 966656
-        max: 966656
-        avg: 966656
-      }
-      file_rss {
-        min: 2080768
-        max: 2080768
-        avg: 2080768
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 966656
-        max: 966656
-        avg: 966656
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/port-bridge"
-    total_counters {
-      anon_rss {
-        min: 696320
-        max: 696320
-        avg: 696320
-      }
-      file_rss {
-        min: 1470464
-        max: 1470464
-        avg: 1470464
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 696320
-        max: 696320
-        avg: 696320
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/qseecomd"
-    total_counters {
-      anon_rss {
-        min: 729088
-        max: 815104
-        avg: 772096
-      }
-      file_rss {
-        min: 749568
-        max: 1642496
-        avg: 1196032
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 729088
-        max: 815104
-        avg: 772096
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/qti"
-    total_counters {
-      anon_rss {
-        min: 1069056
-        max: 1069056
-        avg: 1069056
-      }
-      file_rss {
-        min: 1925120
-        max: 1925120
-        avg: 1925120
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1069056
-        max: 1069056
-        avg: 1069056
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/rmt_storage"
-    total_counters {
-      anon_rss {
-        min: 794624
-        max: 794624
-        avg: 794624
-      }
-      file_rss {
-        min: 1634304
-        max: 1634304
-        avg: 1634304
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 794624
-        max: 794624
-        avg: 794624
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/sensors.qcom"
-    total_counters {
-      anon_rss {
-        min: 868352
-        max: 872448
-        avg: 871437.0053584798
-      }
-      file_rss {
-        min: 1986560
-        max: 1986560
-        avg: 1986560
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 868352
-        max: 872448
-        avg: 871437.0053584798
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/subsystem_ramdump"
-    total_counters {
-      anon_rss {
-        min: 663552
-        max: 663552
-        avg: 663552
-      }
-      file_rss {
-        min: 1441792
-        max: 1441792
-        avg: 1441792
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 663552
-        max: 663552
-        avg: 663552
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/tftp_server"
-    total_counters {
-      anon_rss {
-        min: 565248
-        max: 565248
-        avg: 565248
-      }
-      file_rss {
-        min: 1703936
-        max: 1703936
-        avg: 1703936
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 565248
-        max: 565248
-        avg: 565248
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/thermal-engine"
-    total_counters {
-      anon_rss {
-        min: 1912832
-        max: 1912832
-        avg: 1912832
-      }
-      file_rss {
-        min: 2813952
-        max: 2813952
-        avg: 2813952
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1912832
-        max: 1912832
-        avg: 1912832
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/time_daemon"
-    total_counters {
-      anon_rss {
-        min: 1130496
-        max: 1130496
-        avg: 1130496
-      }
-      file_rss {
-        min: 1802240
-        max: 1802240
-        avg: 1802240
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1130496
-        max: 1130496
-        avg: 1130496
-      }
-    }
-  }
-  process_metrics {
-    process_name: "/vendor/bin/vndservicemanager"
-    total_counters {
-      anon_rss {
-        min: 749568
-        max: 749568
-        avg: 749568
-      }
-      file_rss {
-        min: 1716224
-        max: 1716224
-        avg: 1716224
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 749568
-        max: 749568
-        avg: 749568
-      }
-    }
-  }
-  process_metrics {
-    process_name: "android.ext.services"
-    total_counters {
-      anon_rss {
-        min: 30580736
-        max: 30580736
-        avg: 30580736
-      }
-      file_rss {
-        min: 24633344
-        max: 24633344
-        avg: 24633344
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 30580736
-        max: 30580736
-        avg: 30580736
-      }
-    }
-  }
-  process_metrics {
-    process_name: "android.process.acore"
-    total_counters {
-      anon_rss {
-        min: 32718848
-        max: 32796672
-        avg: 32765771.09452733
-      }
-      file_rss {
-        min: 31182848
-        max: 31232000
-        avg: 31213957.855388246
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 32718848
-        max: 32796672
-        avg: 32765771.09452733
-      }
-      java_heap {
-        min: 1374208
-        max: 1427456
-        avg: 1419596.8920014114
-      }
-    }
-  }
-  process_metrics {
-    process_name: "android.process.media"
-    total_counters {
-      anon_rss {
-        min: 30797824
-        max: 31100928
-        avg: 30828073.014492534
-      }
-      file_rss {
-        min: 27017216
-        max: 27131904
-        avg: 27028661.573051229
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 30797824
-        max: 31100928
-        avg: 30828073.014492534
-      }
-      java_heap {
-        min: 1193984
-        max: 1193984
-        avg: 1193984
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.android.calculator2"
-    total_counters {
-      anon_rss {
-        min: 30457856
-        max: 38170624
-        avg: 37379428.70679906
-      }
-      file_rss {
-        min: 15327232
-        max: 46215168
-        avg: 44927669.371485837
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 30457856
-        max: 38170624
-        avg: 37379428.70679906
-      }
-      java_heap {
-        min: 1499136
-        max: 4316160
-        avg: 2972808.7655181894
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.android.calendar"
-    total_counters {
-      anon_rss {
-        min: 30556160
-        max: 30556160
-        avg: 30556160
-      }
-      file_rss {
-        min: 25948160
-        max: 25948160
-        avg: 25948160
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 30556160
-        max: 30556160
-        avg: 30556160
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.android.camera2"
-    total_counters {
-      anon_rss {
-        min: 32026624
-        max: 43556864
-        avg: 37778954.5579197
-      }
-      file_rss {
-        min: 27398144
-        max: 42573824
-        avg: 35737674.626115516
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 32026624
-        max: 43556864
-        avg: 37778954.5579197
-      }
-      java_heap {
-        min: 3152896
-        max: 7367680
-        avg: 5624331.5376309063
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.android.deskclock"
-    total_counters {
-      anon_rss {
-        min: 30760960
-        max: 30760960
-        avg: 30760960
-      }
-      file_rss {
-        min: 26918912
-        max: 26918912
-        avg: 26918912
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 30760960
-        max: 30760960
-        avg: 30760960
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.android.dialer"
-    total_counters {
-      anon_rss {
-        min: 30515200
-        max: 30515200
-        avg: 30515200
-      }
-      file_rss {
-        min: 26562560
-        max: 26562560
-        avg: 26562560
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 30515200
-        max: 30515200
-        avg: 30515200
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.android.inputmethod.latin"
-    total_counters {
-      anon_rss {
-        min: 32301056
-        max: 32333824
-        avg: 32312115.023602
-      }
-      file_rss {
-        min: 32784384
-        max: 32784384
-        avg: 32784384
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 32301056
-        max: 32333824
-        avg: 32312115.023602
-      }
-      java_heap {
-        min: 1345536
-        max: 1395712
-        avg: 1378703.0378377116
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.android.keychain"
-    total_counters {
-      anon_rss {
-        min: 29995008
-        max: 29995008
-        avg: 29995008
-      }
-      file_rss {
-        min: 20553728
-        max: 20553728
-        avg: 20553728
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 29995008
-        max: 29995008
-        avg: 29995008
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.android.launcher3"
-    total_counters {
-      anon_rss {
-        min: 50225152
-        max: 51023872
-        avg: 50602448.04672049
-      }
-      file_rss {
-        min: 61640704
-        max: 65015808
-        avg: 63338514.4484315
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 50225152
-        max: 51023872
-        avg: 50602448.04672049
-      }
-      java_heap {
-        min: 2658304
-        max: 3159040
-        avg: 2933014.4999347096
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.android.messaging"
-    total_counters {
-      anon_rss {
-        min: 33431552
-        max: 39768064
-        avg: 38817213.791344121
-      }
-      file_rss {
-        min: 31301632
-        max: 50712576
-        avg: 50276775.478137366
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 33431552
-        max: 39768064
-        avg: 38817213.791344121
-      }
-      java_heap {
-        min: 1519616
-        max: 4826112
-        avg: 2558538.0852529262
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.android.nfc"
-    total_counters {
-      anon_rss {
-        min: 33431552
-        max: 33431552
-        avg: 33431552
-      }
-      file_rss {
-        min: 32583680
-        max: 32583680
-        avg: 32583680
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 33431552
-        max: 33431552
-        avg: 33431552
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.android.packageinstaller"
-    total_counters {
-      anon_rss {
-        min: 34000896
-        max: 36679680
-        avg: 36364002.255620666
-      }
-      file_rss {
-        min: 47640576
-        max: 56872960
-        avg: 55784981.963561147
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 34000896
-        max: 36679680
-        avg: 36364002.255620666
-      }
-      java_heap {
-        min: 3202048
-        max: 4088832
-        avg: 4043650.9270121339
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.android.phone"
-    total_counters {
-      anon_rss {
-        min: 34975744
-        max: 35635200
-        avg: 35418527.859008193
-      }
-      file_rss {
-        min: 41607168
-        max: 41644032
-        avg: 41631930.862992339
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 34975744
-        max: 35635200
-        avg: 35418527.859008193
-      }
-      java_heap {
-        min: 3026944
-        max: 3207168
-        avg: 3204534.0849129637
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.android.printspooler"
-    total_counters {
-      anon_rss {
-        min: 30093312
-        max: 30093312
-        avg: 30093312
-      }
-      file_rss {
-        min: 22540288
-        max: 22540288
-        avg: 22540288
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 30093312
-        max: 30093312
-        avg: 30093312
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.android.providers.calendar"
-    total_counters {
-      anon_rss {
-        min: 30814208
-        max: 30814208
-        avg: 30814208
-      }
-      file_rss {
-        min: 27041792
-        max: 27041792
-        avg: 27041792
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 30814208
-        max: 30814208
-        avg: 30814208
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.android.se"
-    total_counters {
-      anon_rss {
-        min: 30208000
-        max: 30208000
-        avg: 30208000
-      }
-      file_rss {
-        min: 20955136
-        max: 20955136
-        avg: 20955136
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 30208000
-        max: 30208000
-        avg: 30208000
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.android.settings"
-    total_counters {
-      anon_rss {
-        min: 34762752
-        max: 34762752
-        avg: 34762752
-      }
-      file_rss {
-        min: 43851776
-        max: 43851776
-        avg: 43851776
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 34762752
-        max: 34762752
-        avg: 34762752
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.android.smspush"
-    total_counters {
-      anon_rss {
-        min: 30130176
-        max: 30130176
-        avg: 30130176
-      }
-      file_rss {
-        min: 20025344
-        max: 20025344
-        avg: 20025344
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 30130176
-        max: 30130176
-        avg: 30130176
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.android.systemui"
-    total_counters {
-      anon_rss {
-        min: 66408448
-        max: 71012352
-        avg: 68351542.715876162
-      }
-      file_rss {
-        min: 84123648
-        max: 84856832
-        avg: 84582561.858931765
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 66408448
-        max: 71012352
-        avg: 68351542.715876162
-      }
-      java_heap {
-        min: 6224896
-        max: 10747904
-        avg: 6949136.10971856
-      }
-    }
-  }
-  process_metrics {
-    process_name: "com.qualcomm.qti.telephonyservice"
-    total_counters {
-      anon_rss {
-        min: 30720000
-        max: 30720000
-        avg: 30720000
-      }
-      file_rss {
-        min: 23228416
-        max: 23228416
-        avg: 23228416
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 30720000
-        max: 30720000
-        avg: 30720000
-      }
-    }
-  }
-  process_metrics {
-    process_name: "lowi-server"
-    total_counters {
-      anon_rss {
-        min: 1445888
-        max: 1449984
-        avg: 1447415.3064999864
-      }
-      file_rss {
-        min: 2252800
-        max: 2252800
-        avg: 2252800
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1445888
-        max: 1449984
-        avg: 1447415.3064999864
-      }
-    }
-  }
-  process_metrics {
-    process_name: "media.codec"
-    total_counters {
-      anon_rss {
-        min: 5189632
-        max: 5210112
-        avg: 5206347.9833998242
-      }
-      file_rss {
-        min: 15314944
-        max: 15314944
-        avg: 15314944
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 5189632
-        max: 5210112
-        avg: 5206347.9833998242
-      }
-    }
-  }
-  process_metrics {
-    process_name: "media.extractor"
-    total_counters {
-      anon_rss {
-        min: 4214784
-        max: 4296704
-        avg: 4225535.91987478
-      }
-      file_rss {
-        min: 7778304
-        max: 7778304
-        avg: 7778304
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 4214784
-        max: 4296704
-        avg: 4225535.91987478
-      }
-    }
-  }
-  process_metrics {
-    process_name: "media.metrics"
-    total_counters {
-      anon_rss {
-        min: 2465792
-        max: 2465792
-        avg: 2465792
-      }
-      file_rss {
-        min: 5373952
-        max: 5373952
-        avg: 5373952
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 2465792
-        max: 2465792
-        avg: 2465792
-      }
-    }
-  }
-  process_metrics {
-    process_name: "perfetto"
-    total_counters {
-      anon_rss {
-        min: 3489792
-        max: 3489792
-        avg: 3489792
-      }
-      file_rss {
-        min: 9125888
-        max: 9125888
-        avg: 9125888
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 3489792
-        max: 3489792
-        avg: 3489792
-      }
-    }
-  }
-  process_metrics {
-    process_name: "system_server"
-    total_counters {
-      anon_rss {
-        min: 57307136
-        max: 82853888
-        avg: 68519057.186817423
-      }
-      file_rss {
-        min: 215744512
-        max: 225366016
-        avg: 221489764.25049949
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 57307136
-        max: 82853888
-        avg: 68519057.186817423
-      }
-      java_heap {
-        min: 8163328
-        max: 14021632
-        avg: 11450919.918936323
-      }
-    }
-  }
-  process_metrics {
-    process_name: "webview_zygote"
-    total_counters {
-      anon_rss {
-        min: 23068672
-        max: 23068672
-        avg: 23068672
-      }
-      file_rss {
-        min: 10244096
-        max: 10244096
-        avg: 10244096
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 23068672
-        max: 23068672
-        avg: 23068672
-      }
-    }
-  }
-  process_metrics {
-    process_name: "xtra-daemon"
-    total_counters {
-      anon_rss {
-        min: 1748992
-        max: 1748992
-        avg: 1748992
-      }
-      file_rss {
-        min: 3473408
-        max: 3473408
-        avg: 3473408
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 1748992
-        max: 1748992
-        avg: 1748992
-      }
-    }
-  }
-  process_metrics {
-    process_name: "zygote"
-    total_counters {
-      anon_rss {
-        min: 22667264
-        max: 22667264
-        avg: 22667264
-      }
-      file_rss {
-        min: 53350400
-        max: 53350400
-        avg: 53350400
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 22667264
-        max: 22667264
-        avg: 22667264
-      }
-    }
-  }
-  process_metrics {
-    process_name: "zygote64"
-    total_counters {
-      anon_rss {
-        min: 30040064
-        max: 30109696
-        avg: 30068614.768896315
-      }
-      file_rss {
-        min: 56365056
-        max: 56365056
-        avg: 56365056
-      }
-      swap {
-        min: 0
-        max: 0
-        avg: 0
-      }
-      anon_and_swap {
-        min: 30040064
-        max: 30109696
-        avg: 30068614.768896315
-      }
-    }
-  }
-}
diff --git a/test/metrics/android_mem_lmk.out b/test/metrics/android_mem_lmk.out
deleted file mode 100644
index 5a14e3d..0000000
--- a/test/metrics/android_mem_lmk.out
+++ /dev/null
@@ -1,7 +0,0 @@
-android_lmk {
-  total_count: 1
-    by_oom_score {
-    oom_score_adj: 900
-    count: 1
-  }
-}
diff --git a/test/metrics/android_package_list.out b/test/metrics/android_package_list.out
deleted file mode 100644
index d14f35b..0000000
--- a/test/metrics/android_package_list.out
+++ /dev/null
@@ -1,7 +0,0 @@
-android_package_list {
-  packages {
-    package_name: "com.my.pkg"
-    uid: 123
-    version_code: 456000
-  }
-}
diff --git a/test/metrics/android_package_list.py b/test/metrics/android_package_list.py
deleted file mode 100644
index e8dd0ae..0000000
--- a/test/metrics/android_package_list.py
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/python
-# 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.
-
-from os import sys, path
-
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_package_list(1, 'com.my.pkg', 123, 456000)
-
-print(trace.trace.SerializeToString())
diff --git a/test/metrics/android_process_growth.out b/test/metrics/android_process_growth.out
deleted file mode 100644
index e108056..0000000
--- a/test/metrics/android_process_growth.out
+++ /dev/null
@@ -1,14 +0,0 @@
-android_process_growth {
-  instance_metrics {
-    pid: 3
-    process_name: "com.google.android.calendar"
-    anon_and_swap_start_value: 2000
-    anon_and_swap_change_bytes: 4000
-  }
-  instance_metrics {
-    pid: 4
-    process_name: "com.google.android.calendar"
-    anon_and_swap_start_value: 150
-    anon_and_swap_change_bytes: 0
-  }
-}
diff --git a/test/metrics/android_process_growth.py b/test/metrics/android_process_growth.py
deleted file mode 100644
index 75bdece..0000000
--- a/test/metrics/android_process_growth.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/python
-# 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.
-
-from os import sys, path
-
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-anon_member = 1
-swap_member = 2
-
-trace = synth_common.create_trace()
-trace.add_process_tree_packet()
-trace.add_process(1, 0, 'init')
-trace.add_process(2, 1, 'system_server')
-trace.add_process(3, 1, 'com.google.android.calendar')
-trace.add_process(4, 1, 'com.google.android.calendar')
-
-trace.add_ftrace_packet(cpu=0)
-trace.add_rss_stat(100, 3, anon_member, 1000)
-trace.add_rss_stat(100, 3, swap_member, 1000)
-trace.add_rss_stat(100, 4, anon_member, 100)
-trace.add_rss_stat(100, 4, swap_member, 50)
-
-trace.add_rss_stat(200, 3, anon_member, 2000)
-trace.add_rss_stat(200, 3, swap_member, 2000)
-trace.add_rss_stat(200, 4, anon_member, 1000)
-trace.add_rss_stat(200, 4, swap_member, 100)
-
-trace.add_rss_stat(300, 3, anon_member, 3000)
-trace.add_rss_stat(300, 3, swap_member, 3000)
-trace.add_rss_stat(300, 4, anon_member, 50)
-trace.add_rss_stat(300, 4, swap_member, 100)
-
-print(trace.trace.SerializeToString())
diff --git a/test/metrics/android_startup.out b/test/metrics/android_startup.out
deleted file mode 100644
index 5e60861..0000000
--- a/test/metrics/android_startup.out
+++ /dev/null
@@ -1,23 +0,0 @@
-android_startup {
-  startup {
-    startup_id: 2
-    package_name: "com.google.android.calendar"
-    process_name: "com.google.android.calendar"
-    zygote_new_process: false
-    activity_hosting_process_count: 2
-    to_first_frame {
-      dur_ns: 108
-      main_thread_by_task_state {
-        running_dur_ns: 41
-        runnable_dur_ns: 49
-        uninterruptible_sleep_dur_ns: 0
-        interruptible_sleep_dur_ns: 10
-      }
-      other_processes_spawned_count: 1
-      time_activity_manager {
-        dur_ns: 8
-      }
-      other_process_to_activity_cpu_ratio: 0.975609756098
-    }
-  }
-}
diff --git a/test/metrics/android_startup.py b/test/metrics/android_startup.py
deleted file mode 100644
index c3c180e..0000000
--- a/test/metrics/android_startup.py
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/usr/bin/python
-# 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.
-
-from os import sys, path
-
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_process_tree_packet()
-trace.add_process(1, 0, 'init')
-trace.add_process(2, 1, 'system_server')
-trace.add_process(3, 1, 'com.google.android.calendar')
-trace.add_process(4, 1, 'com.google.android.calendar')
-
-trace.add_ftrace_packet(cpu=0)
-# Intent without any corresponding end state, will be ignored
-trace.add_atrace_begin(
-    ts=100, tid=2, pid=2, buf='MetricsLogger:launchObserverNotifyIntentStarted')
-trace.add_atrace_end(ts=101, tid=2, pid=2)
-
-# Start intent for a successful launch of calendar
-trace.add_atrace_begin(
-    ts=102, tid=2, pid=2, buf='MetricsLogger:launchObserverNotifyIntentStarted')
-trace.add_atrace_end(ts=103, tid=2, pid=2)
-
-trace.add_atrace_async_begin(
-    ts=110, tid=2, pid=2, buf='launching: com.google.android.calendar')
-
-trace.add_sched(ts=110, prev_pid=0, next_pid=3)
-# P1: 10ns running
-trace.add_sched(ts=120, prev_pid=3, next_pid=0, prev_state='S')
-# P1: 10ns sleep
-trace.add_sched(ts=130, prev_pid=0, next_pid=3)
-
-trace.add_sched(ts=130, prev_pid=3, next_pid=4)
-
-# Create an unrelated task
-trace.add_newtask(ts=155, tid=1, new_tid=5, new_comm='', flags=0)
-
-# P2: 30ns running
-trace.add_sched(ts=160, prev_pid=4, next_pid=0, prev_state='R')
-# P2: 49ns runnable
-trace.add_sched(ts=209, prev_pid=0, next_pid=4)
-# P2: 1ns running
-trace.add_sched(ts=210, prev_pid=4, next_pid=0)
-
-trace.add_atrace_async_end(
-    ts=210, tid=2, pid=2, buf='launching: com.google.android.calendar')
-trace.add_atrace_begin(
-    ts=211,
-    tid=2,
-    pid=2,
-    buf='MetricsLogger:launchObserverNotifyActivityLaunchFinished')
-trace.add_atrace_end(ts=212, tid=2, pid=2)
-
-# Start intent for calendar, we failed to launch the activity.
-trace.add_atrace_begin(
-    ts=402, tid=2, pid=2, buf='MetricsLogger:launchObserverNotifyIntentStarted')
-trace.add_atrace_end(ts=403, tid=2, pid=2)
-
-trace.add_atrace_async_begin(
-    ts=410, tid=2, pid=2, buf='launching: com.google.android.calendar')
-
-trace.add_atrace_async_end(
-    ts=510,
-    tid=2,
-    pid=2,
-    buf='launching: com.google.android.apps.nexuslauncher')
-
-trace.add_ftrace_packet(cpu=1)
-trace.add_sched(ts=160, prev_pid=0, next_pid=1)
-trace.add_sched(ts=200, prev_pid=1, next_pid=0)
-
-print(trace.trace.SerializeToString())
diff --git a/test/metrics/android_startup_battery.py b/test/metrics/android_startup_battery.py
deleted file mode 100644
index 507fe12..0000000
--- a/test/metrics/android_startup_battery.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/python
-# 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.
-
-from os import sys, path
-
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_battery_counters(20, 52, 0.2, 10, 12)
-trace.add_battery_counters(52, 32, 0.8, 8, 93)
-trace.add_battery_counters(80, 15, 0.5, 9, 5)
-trace.add_battery_counters_no_curr_ua(92, 21, 0.3, 25)
-
-print(trace.trace.SerializeToString())
diff --git a/test/metrics/android_startup_breakdown.out b/test/metrics/android_startup_breakdown.out
deleted file mode 100644
index 2dc19cd..0000000
--- a/test/metrics/android_startup_breakdown.out
+++ /dev/null
@@ -1,31 +0,0 @@
-android_startup {
-  startup {
-    startup_id: 1
-    package_name: "com.google.android.calendar"
-    process_name: "com.google.android.calendar"
-    zygote_new_process: true
-    to_first_frame {
-      dur_ns: 108
-      main_thread_by_task_state {
-        running_dur_ns: 0
-        runnable_dur_ns: 0
-        uninterruptible_sleep_dur_ns: 0
-        interruptible_sleep_dur_ns: 0
-      }
-      other_processes_spawned_count: 0
-      time_activity_manager {
-        dur_ns: 8
-      }
-      time_bind_application {
-        dur_ns: 10
-      }
-      time_before_start_process {
-        dur_ns: 18
-      }
-      time_during_start_process {
-        dur_ns: 35
-      }
-    }
-    activity_hosting_process_count: 1
-  }
-}
diff --git a/test/metrics/android_startup_breakdown.py b/test/metrics/android_startup_breakdown.py
deleted file mode 100644
index fe30239..0000000
--- a/test/metrics/android_startup_breakdown.py
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/usr/bin/python
-# 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.
-
-from os import sys, path
-
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_process_tree_packet()
-trace.add_process(1, 0, 'init')
-trace.add_process(2, 1, 'system_server')
-trace.add_process(3, 1, 'com.google.android.calendar')
-
-trace.add_ftrace_packet(cpu=0)
-
-# Start intent for a successful launch of calendar
-trace.add_atrace_begin(
-    ts=102, tid=2, pid=2, buf='MetricsLogger:launchObserverNotifyIntentStarted')
-trace.add_atrace_end(ts=103, tid=2, pid=2)
-
-trace.add_atrace_async_begin(
-    ts=110, tid=2, pid=2, buf='launching: com.google.android.calendar')
-
-trace.add_atrace_begin(
-    ts=120, tid=2, pid=2, buf='Start proc: com.google.android.calendar')
-trace.add_atrace_end(ts=155, tid=2, pid=2)
-
-# Unrelated process binding, ignored
-trace.add_atrace_begin(ts=125, tid=1, pid=1, buf='bindApplication')
-trace.add_atrace_end(ts=195, tid=1, pid=1)
-
-trace.add_atrace_begin(ts=185, tid=3, pid=3, buf='bindApplication')
-trace.add_atrace_end(ts=195, tid=3, pid=3)
-
-trace.add_atrace_async_end(
-    ts=210, tid=2, pid=2, buf='launching: com.google.android.calendar')
-trace.add_atrace_begin(
-    ts=211,
-    tid=2,
-    pid=2,
-    buf='MetricsLogger:launchObserverNotifyActivityLaunchFinished')
-trace.add_atrace_end(ts=212, tid=2, pid=2)
-
-print(trace.trace.SerializeToString())
diff --git a/test/metrics/android_startup_cpu.out b/test/metrics/android_startup_cpu.out
deleted file mode 100644
index 2654ba5..0000000
--- a/test/metrics/android_startup_cpu.out
+++ /dev/null
@@ -1,87 +0,0 @@
-android_cpu {
-      process_info {
-        name:"Process1"
-        threads {
-          name : "Process1"
-          cpu {
-            id: 0
-            max_freq_khz: 500000
-            min_freq_khz: 500000
-            avg_freq_khz: 500000
-            duration_ns: 2
-          }
-          normalized_cpu_cycles: 1
-        }
-        threads {
-          name: "p1-t2"
-          cpu {
-            id: 0
-            max_freq_khz: 1400000
-            min_freq_khz: 1400000
-            avg_freq_khz: 1400000
-            duration_ns: 1
-          }
-          normalized_cpu_cycles: 1
-        }
-        normalized_cpu_cycles: 2
-      }
-      process_info {
-        name: "Process2"
-        threads {
-          name: "p2-t2"
-          cpu {
-            id: 1
-            max_freq_khz: 2000000
-            min_freq_khz: 2000000
-            avg_freq_khz: 2000000
-            duration_ns: 2
-          }
-          normalized_cpu_cycles: 4
-        }
-        threads {
-          name: "p2-t3"
-          cpu {
-            id: 1
-            max_freq_khz: 8000000
-            min_freq_khz: 2000000
-            avg_freq_khz: 4000000
-            duration_ns: 3
-          }
-          normalized_cpu_cycles: 12
-        }
-        threads {
-          name: "Process2"
-          cpu {
-            id: 0
-            max_freq_khz: 2500000
-            min_freq_khz: 2500000
-            avg_freq_khz: 2500000
-            duration_ns: 2
-          }
-          normalized_cpu_cycles: 5
-        }
-        normalized_cpu_cycles: 21
-      }
-      process_info {
-        name: "Process3"
-        threads {
-          name: "Process3"
-          cpu {
-            id: 0
-            max_freq_khz: 1400000
-            min_freq_khz: 500000
-            avg_freq_khz: 725000
-            duration_ns: 4
-          }
-          cpu {
-            id: 1
-            max_freq_khz: 8000000
-            min_freq_khz: 8000000
-            avg_freq_khz: 8000000
-            duration_ns: 2
-          }
-          normalized_cpu_cycles: 18
-        }
-        normalized_cpu_cycles: 18
-      }
-}
diff --git a/test/metrics/android_startup_cpu.py b/test/metrics/android_startup_cpu.py
deleted file mode 100644
index e450767..0000000
--- a/test/metrics/android_startup_cpu.py
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/python
-# 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.
-
-from os import sys, path
-
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_ftrace_packet(cpu=0)
-
-# CPU counters for CPU 0.
-trace.add_cpufreq(ts=9, freq=500000, cpu=0)
-trace.add_cpufreq(ts=15, freq=1400000, cpu=0)
-trace.add_cpufreq(ts=17, freq=2500000, cpu=0)
-
-# CPU counters for CPU 1.
-trace.add_cpufreq(ts=11, freq=2000000, cpu=1)
-trace.add_cpufreq(ts=15, freq=8000000, cpu=1)
-
-# Add 3 processes. This also adds one main thread per process.
-trace.add_process_tree_packet()
-trace.add_process(pid=1, ppid=0, cmdline="Process1")
-trace.add_process(pid=2, ppid=0, cmdline="Process2")
-trace.add_process(pid=3, ppid=0, cmdline="Process3")
-
-# Add 3 additional threads.
-trace.add_thread(tid=4, tgid=1, cmdline="p1-t2")
-trace.add_thread(tid=5, tgid=2, cmdline="p2-t2")
-trace.add_thread(tid=6, tgid=2, cmdline="p2-t3")
-
-# Schedule threads in CPU 0.
-trace.add_ftrace_packet(cpu=0)
-trace.add_sched(ts=10, prev_pid=0, next_pid=1)
-trace.add_sched(ts=12, prev_pid=1, next_pid=3)
-trace.add_sched(ts=16, prev_pid=3, next_pid=4)
-trace.add_sched(ts=17, prev_pid=4, next_pid=2)
-trace.add_sched(ts=19, prev_pid=2, next_pid=0)
-
-# Schedule threads in CPU 1.
-trace.add_ftrace_packet(cpu=1)
-trace.add_sched(ts=11, prev_pid=0, next_pid=5)
-trace.add_sched(ts=13, prev_pid=5, next_pid=6)
-trace.add_sched(ts=16, prev_pid=6, next_pid=3)
-trace.add_sched(ts=18, prev_pid=3, next_pid=0)
-
-print(trace.trace.SerializeToString())
diff --git a/test/metrics/android_startup_powrails.out b/test/metrics/android_startup_powrails.out
deleted file mode 100644
index 67d5677..0000000
--- a/test/metrics/android_startup_powrails.out
+++ /dev/null
@@ -1,35 +0,0 @@
-android_powrails{
-   power_rails{
-      name: "power.PR_1_uws"
-      energy_data {
-        timestamp_ms: 5
-        energy_uws: 12
-      }
-      energy_data {
-        timestamp_ms: 6
-        energy_uws: 50
-      }
-    }
-   power_rails{
-      name: "power.PR_2_uws"
-      energy_data {
-        timestamp_ms: 5
-        energy_uws: 10
-      }
-      energy_data {
-        timestamp_ms: 6
-        energy_uws: 70
-      }
-    }
-    power_rails{
-      name: "power.PR_3_uws"
-      energy_data {
-        timestamp_ms: 5
-        energy_uws: 8
-      }
-      energy_data {
-        timestamp_ms: 6
-        energy_uws: 15
-      }
-    }
-}
\ No newline at end of file
diff --git a/test/metrics/android_startup_powrails.py b/test/metrics/android_startup_powrails.py
deleted file mode 100644
index f729ebd..0000000
--- a/test/metrics/android_startup_powrails.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/python
-# 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.
-
-from os import sys, path
-
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_packet()
-
-# Add Power Rails description for 3 rails.
-trace.add_power_rails_desc(1, 'PR_1')
-trace.add_power_rails_desc(2, 'PR_2')
-trace.add_power_rails_desc(3, 'PR_3')
-
-# Add data at ts = 5 ms.
-trace.add_power_rails_data(5, 1, 12)
-trace.add_power_rails_data(5, 2, 10)
-trace.add_power_rails_data(5, 3, 8)
-
-# Add data at ts = 6 ms.
-trace.add_power_rails_data(6, 1, 50)
-trace.add_power_rails_data(6, 2, 70)
-trace.add_power_rails_data(6, 3, 15)
-
-print(trace.trace.SerializeToString())
diff --git a/test/metrics/android_startup_process_track.out b/test/metrics/android_startup_process_track.out
deleted file mode 100644
index 22f6066..0000000
--- a/test/metrics/android_startup_process_track.out
+++ /dev/null
@@ -1,42 +0,0 @@
-android_startup {
-  startup {
-    startup_id: 1
-    package_name: "com.google.android.calendar"
-    process_name: "com.google.android.calendar"
-    zygote_new_process: false
-    to_first_frame {
-      dur_ns: 4
-      main_thread_by_task_state {
-        running_dur_ns: 0
-        runnable_dur_ns: 0
-        uninterruptible_sleep_dur_ns: 0
-        interruptible_sleep_dur_ns: 0
-      }
-      other_processes_spawned_count: 0
-      time_activity_manager {
-        dur_ns: 2
-      }
-    }
-    activity_hosting_process_count: 1
-  }
-  startup {
-    startup_id: 2
-    package_name: "com.google.android.calendar"
-    process_name: "com.google.android.calendar"
-    zygote_new_process: false
-    to_first_frame {
-      dur_ns: 4
-      main_thread_by_task_state {
-        running_dur_ns: 0
-        runnable_dur_ns: 0
-        uninterruptible_sleep_dur_ns: 0
-        interruptible_sleep_dur_ns: 0
-      }
-      other_processes_spawned_count: 0
-      time_activity_manager {
-        dur_ns: 2
-      }
-    }
-    activity_hosting_process_count: 1
-  }
-}
diff --git a/test/metrics/android_startup_process_track.py b/test/metrics/android_startup_process_track.py
deleted file mode 100644
index 4d927b1..0000000
--- a/test/metrics/android_startup_process_track.py
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/python
-# 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.
-
-from os import sys, path
-
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-
-def add_startup(trace, ts, pid):
-  trace.add_ftrace_packet(cpu=0)
-  trace.add_atrace_begin(
-      ts=ts,
-      tid=2,
-      pid=2,
-      buf='MetricsLogger:launchObserverNotifyIntentStarted')
-  trace.add_atrace_end(ts=ts + 1, tid=2, pid=2)
-  trace.add_atrace_async_begin(
-      ts=ts + 2, tid=2, pid=2, buf='launching: com.google.android.calendar')
-  trace.add_newtask(
-      ts=ts + 3,
-      tid=1,
-      new_tid=pid,
-      new_comm='com.google.android.calendar',
-      flags=0)
-  trace.add_atrace_async_end(
-      ts=ts + 4, tid=2, pid=2, buf='launching: com.google.android.calendar')
-  trace.add_atrace_begin(
-      ts=ts + 5,
-      tid=2,
-      pid=2,
-      buf='MetricsLogger:launchObserverNotifyActivityLaunchFinished')
-  trace.add_atrace_end(ts=ts + 6, tid=2, pid=2)
-
-
-# Build a trace where calendar starts, exits and restarts.
-# Verify that each startup is only associated with a single process
-# (i.e. process exit is taken into account).
-trace = synth_common.create_trace()
-trace.add_process_tree_packet()
-trace.add_process(1, 0, 'init')
-trace.add_process(2, 1, 'system_server')
-add_startup(trace, ts=100, pid=3)
-trace.add_process_free(ts=150, tid=3, comm='', prio=0)
-add_startup(trace, ts=200, pid=4)
-
-print(trace.trace.SerializeToString())
diff --git a/test/metrics/heap_profile.textproto b/test/metrics/heap_profile.textproto
deleted file mode 100644
index 831b002..0000000
--- a/test/metrics/heap_profile.textproto
+++ /dev/null
@@ -1,135 +0,0 @@
-packet {
-  process_tree {
-    processes {
-      pid: 1
-      ppid: 0
-      cmdline: "init"
-    }
-    processes {
-      pid: 2
-      ppid: 1
-      cmdline: "system_server"
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 999
-  previous_packet_dropped: true
-  incremental_state_cleared: true
-  timestamp: 10
-  profile_packet {
-    strings {
-      iid: 1
-      str: "f1"
-    }
-    strings {
-      iid: 2
-      str: "f2"
-    }
-    strings {
-      iid: 3
-      str: "f3"
-    }
-    strings {
-      iid: 4
-      str: "liblib.so"
-    }
-    strings {
-      iid: 5
-      str: "build-id"
-    }
-    frames {
-      iid: 1
-      function_name_id: 1
-      mapping_id: 1
-      rel_pc: 0x1000
-    }
-    frames {
-      iid: 2
-      function_name_id: 2
-      mapping_id: 1
-      rel_pc: 0x2000
-    }
-    frames {
-      iid: 3
-      function_name_id: 3
-      mapping_id: 1
-      rel_pc: 0x3000
-    }
-    frames {
-      iid: 4
-      function_name_id: 2
-      mapping_id: 2
-      rel_pc: 0x4000
-    }
-    callstacks {
-      iid: 1
-      frame_ids: 1
-      frame_ids: 2
-      frame_ids: 3
-    }
-    callstacks {
-      iid: 2
-      frame_ids: 1
-      frame_ids: 4
-    }
-    mappings {
-      iid: 1
-      path_string_ids: 4
-      build_id: 5
-    }
-    mappings {
-      iid: 2
-      path_string_ids: 4
-      build_id: 5
-    }
-    process_dumps {
-      pid: 2
-      samples {
-        callstack_id: 1
-        self_allocated: 2000
-        self_freed: 1000
-        alloc_count: 2
-        free_count: 1
-      }
-      samples {
-        callstack_id: 2
-        self_allocated: 100
-        self_freed: 10
-        alloc_count: 10
-        free_count: 1
-      }
-    }
-  }
-}
-# Add some symbolization packets
-packet {
-  module_symbols {
-    path: "/liblib.so"
-    build_id: "build-id"
-    address_symbols {
-      address: 0x3000
-      lines {
-        function_name: "symbolized f3"
-        source_file_name: "f3.cc"
-        line_number: 33
-      }
-    }
-    address_symbols {
-      address: 0x2000
-      lines {
-        function_name: "symbolized f2"
-        source_file_name: "f2.cc"
-        line_number: 22
-      }
-    }
-    address_symbols {
-      address: 0x4000
-      lines {
-        function_name: "symbolized f2"
-        source_file_name: "f2.cc"
-        line_number: 23
-      }
-    }
-  }
-}
diff --git a/test/metrics/heap_profile_callsites.out b/test/metrics/heap_profile_callsites.out
deleted file mode 100644
index 5f8c14c..0000000
--- a/test/metrics/heap_profile_callsites.out
+++ /dev/null
@@ -1,64 +0,0 @@
-heap_profile_callsites {
-  instance_stats {
-    pid: 2
-    process_name: "system_server"
-    callsites {
-      hash: -2067767828047084124
-      parent_hash: 3061552492032359760
-
-      frame {
-        name: "symbolized f3"
-        mapping_name: "/liblib.so"
-      }
-      self_allocs {
-        total_count: 2
-        total_bytes: 2000
-        delta_count: 1
-        delta_bytes: 1000
-      }
-      child_allocs {
-        total_count: 2
-        total_bytes: 2000
-        delta_count: 1
-        delta_bytes: 1000
-      }
-    }
-    callsites {
-      hash: 3061552492032359760
-      parent_hash: 6947621464292123521
-
-      frame {
-        name: "symbolized f2"
-        mapping_name: "/liblib.so"
-      }
-      self_allocs {
-        total_count: 10
-        total_bytes: 100
-        delta_count: 9
-        delta_bytes: 90
-      }
-      child_allocs {
-        total_count: 12
-        total_bytes: 2100
-        delta_count: 10
-        delta_bytes: 1090
-      }
-    }
-    callsites {
-      hash: 6947621464292123521
-      parent_hash: -1
-      frame {
-        name: "f1"
-        mapping_name: "/liblib.so"
-      }
-      child_allocs {
-        total_count: 12
-        total_bytes: 2100
-        delta_count: 10
-        delta_bytes: 1090
-      }
-    }
-    profile_delta_bytes: 1090
-    profile_total_bytes: 2100
-  }
-}
diff --git a/test/metrics/heap_profile_no_symbols.textproto b/test/metrics/heap_profile_no_symbols.textproto
deleted file mode 100644
index d18c8c9..0000000
--- a/test/metrics/heap_profile_no_symbols.textproto
+++ /dev/null
@@ -1,54 +0,0 @@
-packet {
-  trusted_packet_sequence_id: 999
-  timestamp: 10
-  profile_packet {
-    strings {
-      iid: 1
-      str: "f1"
-    }
-    strings {
-      iid: 2
-      str: "f2"
-    }
-    strings {
-      iid: 4
-      str: "liblib.so"
-    }
-    strings {
-      iid: 5
-      str: "build-id"
-    }
-    frames {
-      iid: 1
-      function_name_id: 1
-      mapping_id: 1
-      rel_pc: 0x1000
-    }
-    frames {
-      iid: 2
-      function_name_id: 2
-      mapping_id: 1
-      rel_pc: 0x2000
-    }
-    callstacks {
-      iid: 1
-      frame_ids: 1
-      frame_ids: 2
-    }
-    mappings {
-      iid: 1
-      path_string_ids: 4
-      build_id: 5
-    }
-    process_dumps {
-      pid: 2
-      samples {
-        callstack_id: 1
-        self_allocated: 2000
-        self_freed: 1000
-        alloc_count: 2
-        free_count: 1
-      }
-    }
-  }
-}
diff --git a/test/metrics/index b/test/metrics/index
deleted file mode 100644
index 8f29693..0000000
--- a/test/metrics/index
+++ /dev/null
@@ -1,27 +0,0 @@
-# Real traces
-../data/memory_counters.pb android_mem android_mem_counters.out
-../data/memory_counters.pb trace_metadata trace_metadata.out
-
-# Synthetic traces
-android_mem_by_priority.py android_mem android_mem_by_priority.out
-android_process_growth.py android_process_growth android_process_growth.out
-android_lmk.py android_lmk android_mem_lmk.out
-android_ion.py android_ion android_ion.out
-
-android_startup.py android_startup android_startup.out
-android_startup_breakdown.py android_startup android_startup_breakdown.out
-android_startup_process_track.py android_startup android_startup_process_track.out
-
-android_startup_battery.py android_batt android_batt_counters.out
-android_startup_cpu.py android_cpu android_startup_cpu.out
-android_startup_powrails.py android_powrails android_startup_powrails.out
-
-android_package_list.py android_package_list android_package_list.out
-
-heap_profile.textproto heap_profile_callsites heap_profile_callsites.out
-heap_profile_no_symbols.textproto unsymbolized_frames unsymbolized_frames.out
-
-../trace_processor/heap_graph.textproto java_heap_stats java_heap_stats.out
-
-# Json output
-../data/memory_counters.pb trace_metadata trace_metadata.json.out
diff --git a/test/metrics/java_heap_stats.out b/test/metrics/java_heap_stats.out
deleted file mode 100644
index 64db708..0000000
--- a/test/metrics/java_heap_stats.out
+++ /dev/null
@@ -1,11 +0,0 @@
-java_heap_stats {
-  instance_stats {
-    upid: 2
-    process_name: "system_server"
-    samples {
-      ts: 10
-      heap_size: 224
-      reachable_heap_size: 96
-    }
-  }
-}
diff --git a/test/metrics/trace_metadata.json.out b/test/metrics/trace_metadata.json.out
deleted file mode 100644
index c961b9e..0000000
--- a/test/metrics/trace_metadata.json.out
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "trace_metadata": {
-    "error_stats_entry": [
-      {
-        "name": "mismatched_sched_switch_tids",
-        "value": 5
-      }
-    ],
-    "trace_duration_ns": 9519159074
-  }
-}
diff --git a/test/metrics/trace_metadata.out b/test/metrics/trace_metadata.out
deleted file mode 100644
index c5ca0d8..0000000
--- a/test/metrics/trace_metadata.out
+++ /dev/null
@@ -1,7 +0,0 @@
-trace_metadata {
-  error_stats_entry {
-    name: "mismatched_sched_switch_tids"
-    value: 5
-  }
-  trace_duration_ns: 9519159074
-}
diff --git a/test/metrics/unsymbolized_frames.out b/test/metrics/unsymbolized_frames.out
deleted file mode 100644
index a587f46..0000000
--- a/test/metrics/unsymbolized_frames.out
+++ /dev/null
@@ -1,12 +0,0 @@
-unsymbolized_frames {
-  frames {
-    module: "/liblib.so"
-    build_id: "6275696c642d6964"
-    address: 4096
-  }
-  frames {
-    module: "/liblib.so"
-    build_id: "6275696c642d6964"
-    address: 8192
-  }
-}
diff --git a/test/producer_socket_fuzzer.cc b/test/producer_socket_fuzzer.cc
deleted file mode 100644
index ac7227f..0000000
--- a/test/producer_socket_fuzzer.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/base/build_config.h"
-#include "perfetto/ext/base/unix_socket.h"
-#include "src/base/test/test_task_runner.h"
-#include "test/test_helper.h"
-
-namespace perfetto {
-namespace socket_fuzz {
-namespace {
-
-class FakeEventListener : public base::UnixSocket::EventListener {
- public:
-  FakeEventListener(const uint8_t* data,
-                    size_t size,
-                    std::function<void()> data_sent_callback)
-      : data_(data), size_(size), data_sent_(data_sent_callback) {}
-
-  void OnNewIncomingConnection(base::UnixSocket*,
-                               std::unique_ptr<base::UnixSocket>) override {
-    PERFETTO_CHECK(false);
-  }
-
-  void OnConnect(base::UnixSocket* self, bool connected) override {
-    PERFETTO_CHECK(connected && self->is_connected());
-    PERFETTO_CHECK(self->Send(data_, size_, self->fd(),
-                              base::UnixSocket::BlockingMode::kBlocking));
-    data_sent_();
-  }
-
-  void OnDisconnect(base::UnixSocket*) override { PERFETTO_CHECK(false); }
-  void OnDataAvailable(base::UnixSocket*) override { PERFETTO_CHECK(false); }
-
- private:
-  const uint8_t* data_;
-  const size_t size_;
-  std::function<void()> data_sent_;
-};
-
-int FuzzSharedMemory(const uint8_t* data, size_t size) {
-  if (!data)
-    return 0;
-  base::TestTaskRunner task_runner;
-
-  TestHelper helper(&task_runner);
-  helper.StartServiceIfRequired();
-
-  FakeEventListener fake_event_listener(
-      data, size, task_runner.CreateCheckpoint("data_sent"));
-
-  std::unique_ptr<base::UnixSocket> sock = base::UnixSocket::Connect(
-      helper.GetProducerSocketName(), &fake_event_listener, &task_runner,
-      base::SockFamily::kUnix, base::SockType::kStream);
-
-  task_runner.RunUntilCheckpoint("data_sent");
-  return 0;
-}
-}  // namespace
-}  // namespace socket_fuzz
-}  // namespace perfetto
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  return perfetto::socket_fuzz::FuzzSharedMemory(data, size);
-}
diff --git a/test/synth_common.py b/test/synth_common.py
deleted file mode 100644
index 3383b81..0000000
--- a/test/synth_common.py
+++ /dev/null
@@ -1,352 +0,0 @@
-#!/usr/bin/python
-# 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.
-
-import argparse
-
-from google.protobuf import descriptor, descriptor_pb2, message_factory, reflection
-from google.protobuf.pyext import _message
-
-CLONE_THREAD = 0x00010000
-
-
-class Trace(object):
-
-  def __init__(self, trace):
-    self.trace = trace
-    self.proc_map = {}
-    self.proc_map[0] = 'idle_thread'
-
-  def add_system_info(self, arch=None):
-    self.packet = self.trace.packet.add()
-    self.packet.system_info.utsname.machine = arch
-
-  def add_ftrace_packet(self, cpu):
-    self.packet = self.trace.packet.add()
-    self.packet.ftrace_events.cpu = cpu
-
-  def add_packet(self):
-    self.packet = self.trace.packet.add()
-    return self.packet
-
-  def __add_ftrace_event(self, ts, tid):
-    ftrace = self.packet.ftrace_events.event.add()
-    ftrace.timestamp = ts
-    ftrace.pid = tid
-    return ftrace
-
-  def add_rss_stat(self, ts, tid, member, size):
-    ftrace = self.__add_ftrace_event(ts, tid)
-    rss_stat = ftrace.rss_stat
-    rss_stat.member = member
-    rss_stat.size = size
-
-  def add_ion_event(self, ts, tid, heap_name, size):
-    ftrace = self.__add_ftrace_event(ts, tid)
-    ion = ftrace.ion_heap_grow
-    ion.heap_name = heap_name
-    ion.total_allocated = size
-
-  def add_oom_score_update(self, ts, oom_score_adj, pid):
-    ftrace = self.__add_ftrace_event(ts, pid)
-    oom_score = ftrace.oom_score_adj_update
-    oom_score.comm = self.proc_map[pid]
-    oom_score.oom_score_adj = oom_score_adj
-    oom_score.pid = pid
-
-  def add_sched(self,
-                ts,
-                prev_pid,
-                next_pid,
-                prev_comm=None,
-                next_comm=None,
-                prev_state=None):
-    ftrace = self.__add_ftrace_event(ts, 0)
-    ss = ftrace.sched_switch
-    ss.prev_comm = prev_comm or self.proc_map[prev_pid]
-    ss.prev_pid = prev_pid
-    ss.next_pid = next_pid
-    ss.next_comm = next_comm or self.proc_map[next_pid]
-    if prev_state:
-      if prev_state == 'R':
-        ss.prev_state = 0
-      elif prev_state == 'S':
-        ss.prev_state = 1
-      elif prev_state == 'U':
-        ss.prev_state = 2
-      else:
-        raise Exception('Invalid prev state {}'.format(prev_state))
-
-  def add_cpufreq(self, ts, freq, cpu):
-    ftrace = self.__add_ftrace_event(ts, 0)
-    cpufreq = ftrace.cpu_frequency
-    cpufreq.state = freq
-    cpufreq.cpu_id = cpu
-
-  def add_kernel_lmk(self, ts, tid):
-    ftrace = self.__add_ftrace_event(ts, tid)
-    lowmemory_kill = ftrace.lowmemory_kill
-    lowmemory_kill.pid = tid
-
-  def add_sys_enter(self, ts, tid, id):
-    ftrace = self.__add_ftrace_event(ts, tid)
-    sys_enter = ftrace.sys_enter
-    sys_enter.id = id
-
-  def add_sys_exit(self, ts, tid, id, ret):
-    ftrace = self.__add_ftrace_event(ts, tid)
-    sys_exit = ftrace.sys_exit
-    sys_exit.id = id
-    sys_exit.ret = ret
-
-  def add_newtask(self, ts, tid, new_tid, new_comm, flags):
-    ftrace = self.__add_ftrace_event(ts, tid)
-    newtask = ftrace.task_newtask
-    newtask.pid = new_tid
-    newtask.comm = new_comm
-    newtask.clone_flags = flags
-
-  def add_process_free(self, ts, tid, comm, prio):
-    ftrace = self.__add_ftrace_event(ts, tid)
-    sched_process_free = ftrace.sched_process_free
-    sched_process_free.pid = tid
-    sched_process_free.comm = comm
-    sched_process_free.prio = prio
-
-  def add_rename(self, ts, tid, old_comm, new_comm, oom_score_adj):
-    ftrace = self.__add_ftrace_event(ts, tid)
-    task_rename = ftrace.task_rename
-    task_rename.pid = tid
-    task_rename.oldcomm = old_comm
-    task_rename.newcomm = new_comm
-    task_rename.oom_score_adj = oom_score_adj
-
-  def add_print(self, ts, tid, buf):
-    ftrace = self.__add_ftrace_event(ts, tid)
-    print_event = getattr(ftrace, 'print')
-    print_event.buf = buf
-
-  def add_kmalloc(self, ts, tid, bytes_alloc, bytes_req, call_site, gfp_flags,
-                  ptr):
-    ftrace = self.__add_ftrace_event(ts, tid)
-    kmalloc = ftrace.kmalloc
-    kmalloc.bytes_alloc = bytes_alloc
-    kmalloc.bytes_req = bytes_req
-    kmalloc.call_site = call_site
-    kmalloc.gfp_flags = gfp_flags
-    kmalloc.ptr = ptr
-
-  def add_kfree(self, ts, tid, call_site, ptr):
-    ftrace = self.__add_ftrace_event(ts, tid)
-    kfree = ftrace.kfree
-    kfree.call_site = call_site
-    kfree.ptr = ptr
-
-  def add_atrace_counter(self, ts, pid, tid, buf, cnt):
-    self.add_print(ts, tid, 'C|{}|{}|{}'.format(pid, buf, cnt))
-
-  def add_atrace_begin(self, ts, tid, pid, buf):
-    self.add_print(ts, tid, 'B|{}|{}'.format(pid, buf))
-
-  def add_atrace_end(self, ts, tid, pid):
-    self.add_print(ts, tid, 'E|{}'.format(pid))
-
-  def add_atrace_async_begin(self, ts, tid, pid, buf):
-    self.add_print(ts, tid, 'S|{}|{}|0'.format(pid, buf))
-
-  def add_atrace_async_end(self, ts, tid, pid, buf):
-    self.add_print(ts, tid, 'F|{}|{}|0'.format(pid, buf))
-
-  def add_process_tree_packet(self, ts=None):
-    self.packet = self.trace.packet.add()
-    if ts is not None:
-      self.packet.timestamp = ts
-
-  def add_process(self, pid, ppid, cmdline):
-    process = self.packet.process_tree.processes.add()
-    process.pid = pid
-    process.ppid = ppid
-    process.cmdline.append(cmdline)
-    self.proc_map[pid] = cmdline
-
-  def add_thread(self, tid, tgid, cmdline):
-    thread = self.packet.process_tree.threads.add()
-    thread.tid = tid
-    thread.tgid = tgid
-    self.proc_map[tid] = cmdline
-
-  def add_battery_counters(self, ts, charge_uah, cap_prct, curr_ua,
-                           curr_avg_ua):
-    self.packet = self.trace.packet.add()
-    self.packet.timestamp = ts
-    battery_count = self.packet.battery
-    battery_count.charge_counter_uah = charge_uah
-    battery_count.capacity_percent = cap_prct
-    battery_count.current_ua = curr_ua
-    battery_count.current_avg_ua = curr_avg_ua
-
-  def add_battery_counters_no_curr_ua(self, ts, charge_uah, cap_prct,
-                                      curr_avg_ua):
-    self.packet = self.trace.packet.add()
-    self.packet.timestamp = ts
-    battery_count = self.packet.battery
-    battery_count.charge_counter_uah = charge_uah
-    battery_count.capacity_percent = cap_prct
-    battery_count.current_avg_ua = curr_avg_ua
-
-  def add_power_rails_desc(self, index_val, name):
-    power_rails = self.packet.power_rails
-    descriptor = power_rails.rail_descriptor.add()
-    descriptor.index = index_val
-    descriptor.rail_name = name
-
-  def add_power_rails_data(self, ts, index_val, value):
-    power_rails = self.packet.power_rails
-    energy_data = power_rails.energy_data.add()
-    energy_data.index = index_val
-    energy_data.timestamp_ms = ts
-    energy_data.energy = value
-
-  def add_package_list(self, ts, name, uid, version_code):
-    packet = self.add_packet()
-    packet.timestamp = ts
-    plist = packet.packages_list
-    pinfo = plist.packages.add()
-    pinfo.name = name
-    pinfo.uid = uid
-    pinfo.version_code = version_code
-
-  def add_profile_packet(self, ts):
-    packet = self.add_packet()
-    packet.timestamp = ts
-    return packet.profile_packet
-
-  def add_clock_snapshot(self, clocks, seq_id=None):
-    packet = self.add_packet()
-    if seq_id is not None:
-      packet.trusted_packet_sequence_id = seq_id
-    snap = self.packet.clock_snapshot
-    for k, v in clocks.iteritems():
-      clock = snap.clocks.add()
-      clock.clock_id = k
-      clock.timestamp = v
-
-  def add_gpu_counter_spec(self,
-                           ts,
-                           counter_id,
-                           name,
-                           description=None,
-                           unit_numerators=[],
-                           unit_denominators=[]):
-    packet = self.add_packet()
-    packet.timestamp = ts
-    gpu_counters = packet.gpu_counter_event
-    counter_desc = gpu_counters.counter_descriptor
-    spec = counter_desc.specs.add()
-    spec.counter_id = counter_id
-    spec.name = name
-    if description is not None:
-      spec.description = description
-    spec.numerator_units.extend(unit_numerators)
-    spec.denominator_units.extend(unit_denominators)
-
-  def add_gpu_counter(self, ts, counter_id, value, clock_id=None, seq_id=None):
-    packet = self.add_packet()
-    packet.timestamp = ts
-    if clock_id is not None:
-      packet.timestamp_clock_id = clock_id
-    if seq_id is not None:
-      packet.trusted_packet_sequence_id = seq_id
-    gpu_counters = self.packet.gpu_counter_event
-    gpu_counter = gpu_counters.counters.add()
-    gpu_counter.counter_id = counter_id
-    gpu_counter.int_value = value
-
-  def add_gpu_log(self, ts, severity, tag, message):
-    packet = self.add_packet()
-    packet.timestamp = ts
-    gpu_log = self.packet.gpu_log
-    gpu_log.severity = severity
-    gpu_log.tag = tag
-    gpu_log.log_message = message
-
-  def add_buffer_event_packet(self, ts, buffer_id, layer_name, frame_number,
-                              event_type, duration):
-    packet = self.add_packet()
-    packet.timestamp = ts
-    buffer_event = packet.graphics_frame_event.buffer_event
-    if buffer_id >= 0:
-      buffer_event.buffer_id = buffer_id
-    buffer_event.layer_name = layer_name
-    buffer_event.frame_number = frame_number
-    if event_type >= 0:
-      buffer_event.type = event_type
-    buffer_event.duration_ns = duration
-
-  def add_thread_track_descriptor(self,
-                                  ps,
-                                  ts,
-                                  uuid,
-                                  pid,
-                                  tid,
-                                  thread_name,
-                                  inc_state_cleared=False):
-    packet = self.add_packet()
-    packet.trusted_packet_sequence_id = ps
-    packet.timestamp = ts
-    if inc_state_cleared:
-      packet.incremental_state_cleared = True
-    track = packet.track_descriptor
-    track.uuid = uuid
-    track.thread.pid = pid
-    track.thread.tid = tid
-    track.thread.thread_name = thread_name
-
-  def add_track_event(self, ps, ts, track_uuid, cat, name, type):
-    packet = self.add_packet()
-    packet.trusted_packet_sequence_id = ps
-    packet.timestamp = ts
-    event = packet.track_event
-    event.track_uuid = track_uuid
-    event.categories.append(cat)
-    event.name = name
-    event.type = type
-
-
-def create_trace():
-  parser = argparse.ArgumentParser()
-  parser.add_argument(
-      'trace_descriptor', type=str, help='location of trace descriptor')
-  args = parser.parse_args()
-
-  with open(args.trace_descriptor, 'rb') as t:
-    fileContent = t.read()
-
-  file_desc_set_pb2 = descriptor_pb2.FileDescriptorSet()
-  file_desc_set_pb2.MergeFromString(fileContent)
-
-  desc_by_path = {}
-  for f_desc_pb2 in file_desc_set_pb2.file:
-    f_desc_pb2_encode = f_desc_pb2.SerializeToString()
-    f_desc = descriptor.FileDescriptor(
-        name=f_desc_pb2.name,
-        package=f_desc_pb2.package,
-        serialized_pb=f_desc_pb2_encode)
-
-    for desc in f_desc.message_types_by_name.values():
-      desc_by_path[desc.full_name] = desc
-
-  trace = message_factory.MessageFactory().GetPrototype(
-      desc_by_path['perfetto.protos.Trace'])()
-  return Trace(trace)
diff --git a/test/task_runner_thread.cc b/test/task_runner_thread.cc
index c625078..dc9e4ac 100644
--- a/test/task_runner_thread.cc
+++ b/test/task_runner_thread.cc
@@ -23,9 +23,9 @@
 #include <condition_variable>
 #include <thread>
 
+#include "perfetto/base/file_utils.h"
+#include "perfetto/base/string_splitter.h"
 #include "perfetto/base/time.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/string_splitter.h"
 #include "test/task_runner_thread.h"
 
 namespace perfetto {
@@ -85,7 +85,7 @@
 #endif
 
   // Create the task runner and execute the specicalised code.
-  base::UnixTaskRunner task_runner;
+  base::PlatformTaskRunner task_runner;
   delegate->Initialize(&task_runner);
 
   // Pass the runner back to the main thread.
diff --git a/test/task_runner_thread.h b/test/task_runner_thread.h
index 354c308..078d978 100644
--- a/test/task_runner_thread.h
+++ b/test/task_runner_thread.h
@@ -61,7 +61,7 @@
 
   // All variables below this point are protected by |mutex_|.
   std::mutex mutex_;
-  base::UnixTaskRunner* runner_ = nullptr;
+  base::PlatformTaskRunner* runner_ = nullptr;
 };
 
 }  // namespace perfetto
diff --git a/test/task_runner_thread_delegates.cc b/test/task_runner_thread_delegates.cc
deleted file mode 100644
index 291482f..0000000
--- a/test/task_runner_thread_delegates.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2019 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 "test/task_runner_thread_delegates.h"
-
-namespace perfetto {
-
-ServiceDelegate::~ServiceDelegate() = default;
-ProbesProducerDelegate::~ProbesProducerDelegate() = default;
-FakeProducerDelegate::~FakeProducerDelegate() = default;
-
-}  // namespace perfetto
diff --git a/test/task_runner_thread_delegates.h b/test/task_runner_thread_delegates.h
index bea384a..8eecbba 100644
--- a/test/task_runner_thread_delegates.h
+++ b/test/task_runner_thread_delegates.h
@@ -17,7 +17,7 @@
 #ifndef TEST_TASK_RUNNER_THREAD_DELEGATES_H_
 #define TEST_TASK_RUNNER_THREAD_DELEGATES_H_
 
-#include "perfetto/ext/tracing/ipc/service_ipc_host.h"
+#include "perfetto/tracing/ipc/service_ipc_host.h"
 #include "src/traced/probes/probes_producer.h"
 #include "test/fake_producer.h"
 #include "test/task_runner_thread.h"
@@ -29,7 +29,7 @@
   ServiceDelegate(const std::string& producer_socket,
                   const std::string& consumer_socket)
       : producer_socket_(producer_socket), consumer_socket_(consumer_socket) {}
-  ~ServiceDelegate() override;
+  ~ServiceDelegate() override = default;
 
   void Initialize(base::TaskRunner* task_runner) override {
     svc_ = ServiceIPCHost::CreateInstance(task_runner);
@@ -49,7 +49,7 @@
  public:
   ProbesProducerDelegate(const std::string& producer_socket)
       : producer_socket_(producer_socket) {}
-  ~ProbesProducerDelegate() override;
+  ~ProbesProducerDelegate() override = default;
 
   void Initialize(base::TaskRunner* task_runner) override {
     producer_.reset(new ProbesProducer);
@@ -69,7 +69,7 @@
       : producer_socket_(producer_socket),
         setup_callback_(std::move(setup_callback)),
         connect_callback_(std::move(connect_callback)) {}
-  ~FakeProducerDelegate() override;
+  ~FakeProducerDelegate() override = default;
 
   void Initialize(base::TaskRunner* task_runner) override {
     producer_.reset(new FakeProducer("android.perfetto.FakeProducer"));
diff --git a/test/test_helper.cc b/test/test_helper.cc
index 57e8b10..bcacda3 100644
--- a/test/test_helper.cc
+++ b/test/test_helper.cc
@@ -16,14 +16,15 @@
 
 #include "test/test_helper.h"
 
-#include "perfetto/ext/traced/traced.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
+#include "gtest/gtest.h"
+#include "perfetto/traced/traced.h"
+#include "perfetto/tracing/core/trace_packet.h"
 #include "test/task_runner_thread_delegates.h"
 
-#include "perfetto/ext/tracing/ipc/default_socket.h"
+#include "src/tracing/ipc/default_socket.h"
 
-#include "protos/perfetto/trace/trace_packet.pb.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "perfetto/trace/trace_packet.pb.h"
+#include "perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto {
 
@@ -51,7 +52,7 @@
 }
 
 void TestHelper::OnDisconnect() {
-  PERFETTO_FATAL("Consumer unexpectedly disconnected from the service");
+  FAIL() << "Consumer unexpectedly disconnected from the service";
 }
 
 void TestHelper::OnTracingDisabled() {
@@ -61,15 +62,14 @@
 void TestHelper::OnTraceData(std::vector<TracePacket> packets, bool has_more) {
   for (auto& encoded_packet : packets) {
     protos::TracePacket packet;
-    PERFETTO_CHECK(
-        packet.ParseFromString(encoded_packet.GetRawBytesForTesting()));
+    ASSERT_TRUE(encoded_packet.Decode(&packet));
     if (packet.has_clock_snapshot() || packet.has_trace_config() ||
         packet.has_trace_stats() || !packet.synchronization_marker().empty() ||
         packet.has_system_info()) {
       continue;
     }
-    PERFETTO_CHECK(packet.optional_trusted_uid_case() ==
-                   protos::TracePacket::kTrustedUid);
+    ASSERT_EQ(protos::TracePacket::kTrustedUid,
+              packet.optional_trusted_uid_case());
     trace_.push_back(std::move(packet));
   }
 
@@ -163,9 +163,8 @@
   RunUntilCheckpoint("stop.tracing", timeout_ms);
 }
 
-void TestHelper::WaitForReadData(uint32_t read_count, uint32_t timeout_ms) {
-  RunUntilCheckpoint("readback.complete." + std::to_string(read_count),
-                     timeout_ms);
+void TestHelper::WaitForReadData(uint32_t read_count) {
+  RunUntilCheckpoint("readback.complete." + std::to_string(read_count));
 }
 
 std::function<void()> TestHelper::WrapTask(
diff --git a/test/test_helper.h b/test/test_helper.h
index f20c206..8b2ae2d 100644
--- a/test/test_helper.h
+++ b/test/test_helper.h
@@ -17,16 +17,16 @@
 #ifndef TEST_TEST_HELPER_H_
 #define TEST_TEST_HELPER_H_
 
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/tracing/core/consumer.h"
-#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "perfetto/ext/tracing/ipc/consumer_ipc_client.h"
+#include "perfetto/base/scoped_file.h"
+#include "perfetto/tracing/core/consumer.h"
 #include "perfetto/tracing/core/trace_config.h"
+#include "perfetto/tracing/core/trace_packet.h"
+#include "perfetto/tracing/ipc/consumer_ipc_client.h"
 #include "src/base/test/test_task_runner.h"
 #include "test/fake_producer.h"
 #include "test/task_runner_thread.h"
 
-#include "protos/perfetto/trace/trace_packet.pb.h"
+#include "perfetto/trace/trace_packet.pb.h"
 
 namespace perfetto {
 
@@ -62,7 +62,7 @@
   void WaitForProducerSetup();
   void WaitForProducerEnabled();
   void WaitForTracingDisabled(uint32_t timeout_ms = 5000);
-  void WaitForReadData(uint32_t read_count = 0, uint32_t timeout_ms = 5000);
+  void WaitForReadData(uint32_t read_count = 0);
 
   std::string AddID(const std::string& checkpoint) {
     return checkpoint + "." + std::to_string(instance_num_);
diff --git a/test/trace_processor/android_async_slice.textproto b/test/trace_processor/android_async_slice.textproto
deleted file mode 100644
index 787d929..0000000
--- a/test/trace_processor/android_async_slice.textproto
+++ /dev/null
@@ -1,26 +0,0 @@
-packet {
-  ftrace_events {
-    cpu: 3
-    event {
-      timestamp: 74289018336
-      pid: 4064
-      print {
-        ip: 18446743562018522420
-        buf: "S|1204|launching: com.android.chrome|0\n"
-      }
-    }
-  }
-}
-packet {
-  ftrace_events {
-    cpu: 2
-    event {
-      timestamp: 74662603008
-      pid: 1257
-      print {
-        ip: 18446743562018522420
-        buf: "F|1204|launching: com.android.chrome|0\n"
-      }
-    }
-  }
-}
diff --git a/test/trace_processor/android_sched_and_ps_b119301023.out b/test/trace_processor/android_sched_and_ps_b119301023.out
index 99ee147..9dd5d48 100644
--- a/test/trace_processor/android_sched_and_ps_b119301023.out
+++ b/test/trace_processor/android_sched_and_ps_b119301023.out
@@ -1,11 +1,11 @@
-"ts"
-81473010031230
-81473010109251
-81473010121751
-81473010179772
-81473010203886
-81473010234720
-81473010278522
-81473010308470
-81473010341386
-81473010352792
+"ts","cpu","dur","ts_end","utid","end_state","priority","row_id"
+81473010031230,2,78021,81473010109251,3,"S",120,17179869184
+81473010109251,2,12500,81473010121751,0,"R",120,17179869185
+81473010121751,2,58021,81473010179772,4,"S",120,17179869186
+81473010179772,2,24114,81473010203886,0,"R",120,17179869187
+81473010203886,2,30834,81473010234720,5,"S",120,17179869188
+81473010234720,2,43802,81473010278522,0,"R",120,17179869189
+81473010278522,2,29948,81473010308470,6,"S",120,17179869190
+81473010308470,2,44322,81473010352792,0,"R",120,17179869191
+81473010341386,1,158854,81473010500240,7,"S",116,17179869192
+81473010352792,2,32917,81473010385709,8,"S",120,17179869193
diff --git a/test/trace_processor/android_sched_and_ps_smoke.out b/test/trace_processor/android_sched_and_ps_smoke.out
index cd948f0..9dd5d48 100644
--- a/test/trace_processor/android_sched_and_ps_smoke.out
+++ b/test/trace_processor/android_sched_and_ps_smoke.out
@@ -1,11 +1,11 @@
-"ts","cpu","dur","end_state","priority","tid"
-81473010031230,2,78021,"S",120,26204
-81473010109251,2,12500,"R",120,0
-81473010121751,2,58021,"S",120,26205
-81473010179772,2,24114,"R",120,0
-81473010203886,2,30834,"S",120,26206
-81473010234720,2,43802,"R",120,0
-81473010278522,2,29948,"S",120,26207
-81473010308470,2,44322,"R",120,0
-81473010341386,1,158854,"S",116,23912
-81473010352792,2,32917,"S",120,26208
+"ts","cpu","dur","ts_end","utid","end_state","priority","row_id"
+81473010031230,2,78021,81473010109251,3,"S",120,17179869184
+81473010109251,2,12500,81473010121751,0,"R",120,17179869185
+81473010121751,2,58021,81473010179772,4,"S",120,17179869186
+81473010179772,2,24114,81473010203886,0,"R",120,17179869187
+81473010203886,2,30834,81473010234720,5,"S",120,17179869188
+81473010234720,2,43802,81473010278522,0,"R",120,17179869189
+81473010278522,2,29948,81473010308470,6,"S",120,17179869190
+81473010308470,2,44322,81473010352792,0,"R",120,17179869191
+81473010341386,1,158854,81473010500240,7,"S",116,17179869192
+81473010352792,2,32917,81473010385709,8,"S",120,17179869193
diff --git a/test/trace_processor/android_sched_and_ps_stats.out b/test/trace_processor/android_sched_and_ps_stats.out
index 6bd5507..bb00882 100644
--- a/test/trace_processor/android_sched_and_ps_stats.out
+++ b/test/trace_processor/android_sched_and_ps_stats.out
@@ -95,22 +95,22 @@
 "ftrace_cpu_oldest_event_ts_end",5,"info","trace",81492487245000
 "ftrace_cpu_oldest_event_ts_end",6,"info","trace",81492578784000
 "ftrace_cpu_oldest_event_ts_end",7,"info","trace",81492798356000
-"ftrace_cpu_overrun_begin",0,"info","trace",0
-"ftrace_cpu_overrun_begin",1,"info","trace",0
-"ftrace_cpu_overrun_begin",2,"info","trace",0
-"ftrace_cpu_overrun_begin",3,"info","trace",0
-"ftrace_cpu_overrun_begin",4,"info","trace",0
-"ftrace_cpu_overrun_begin",5,"info","trace",0
-"ftrace_cpu_overrun_begin",6,"info","trace",0
-"ftrace_cpu_overrun_begin",7,"info","trace",0
-"ftrace_cpu_overrun_end",0,"data_loss","trace",0
-"ftrace_cpu_overrun_end",1,"data_loss","trace",0
-"ftrace_cpu_overrun_end",2,"data_loss","trace",0
-"ftrace_cpu_overrun_end",3,"data_loss","trace",0
-"ftrace_cpu_overrun_end",4,"data_loss","trace",0
-"ftrace_cpu_overrun_end",5,"data_loss","trace",0
-"ftrace_cpu_overrun_end",6,"data_loss","trace",0
-"ftrace_cpu_overrun_end",7,"data_loss","trace",0
+"ftrace_cpu_overrun_begin",0,"error","trace",0
+"ftrace_cpu_overrun_begin",1,"error","trace",0
+"ftrace_cpu_overrun_begin",2,"error","trace",0
+"ftrace_cpu_overrun_begin",3,"error","trace",0
+"ftrace_cpu_overrun_begin",4,"error","trace",0
+"ftrace_cpu_overrun_begin",5,"error","trace",0
+"ftrace_cpu_overrun_begin",6,"error","trace",0
+"ftrace_cpu_overrun_begin",7,"error","trace",0
+"ftrace_cpu_overrun_end",0,"error","trace",0
+"ftrace_cpu_overrun_end",1,"error","trace",0
+"ftrace_cpu_overrun_end",2,"error","trace",0
+"ftrace_cpu_overrun_end",3,"error","trace",0
+"ftrace_cpu_overrun_end",4,"error","trace",0
+"ftrace_cpu_overrun_end",5,"error","trace",0
+"ftrace_cpu_overrun_end",6,"error","trace",0
+"ftrace_cpu_overrun_end",7,"error","trace",0
 "ftrace_cpu_read_events_begin",0,"info","trace",0
 "ftrace_cpu_read_events_begin",1,"info","trace",0
 "ftrace_cpu_read_events_begin",2,"info","trace",0
@@ -128,11 +128,11 @@
 "ftrace_cpu_read_events_end",6,"info","trace",36733
 "ftrace_cpu_read_events_end",7,"info","trace",39240
 "traced_buf_buffer_size",0,"info","trace",0
-"traced_buf_bytes_overwritten",0,"data_loss","trace",0
+"traced_buf_bytes_overwritten",0,"info","trace",0
 "traced_buf_bytes_read",0,"info","trace",0
 "traced_buf_bytes_written",0,"info","trace",18780240
 "traced_buf_chunks_discarded",0,"info","trace",0
-"traced_buf_chunks_overwritten",0,"data_loss","trace",0
+"traced_buf_chunks_overwritten",0,"info","trace",0
 "traced_buf_chunks_read",0,"info","trace",0
 "traced_buf_chunks_rewritten",0,"info","trace",0
 "traced_buf_chunks_written",0,"info","trace",4603
@@ -143,5 +143,4 @@
 "traced_buf_patches_succeeded",0,"info","trace",8215
 "traced_buf_readaheads_failed",0,"info","trace",0
 "traced_buf_readaheads_succeeded",0,"info","trace",0
-"traced_buf_trace_writer_packet_loss",0,"info","trace",0
 "traced_buf_write_wrap_count",0,"info","trace",0
diff --git a/test/trace_processor/b119301023.sql b/test/trace_processor/b119301023.sql
index e751239..41f7ea1 100644
--- a/test/trace_processor/b119301023.sql
+++ b/test/trace_processor/b119301023.sql
@@ -1,3 +1,3 @@
-select ts from sched
+select * from sched
 where ts > 0.1 + 1e9
 limit 10;
diff --git a/test/trace_processor/clock_sync.out b/test/trace_processor/clock_sync.out
deleted file mode 100644
index 77ee53f..0000000
--- a/test/trace_processor/clock_sync.out
+++ /dev/null
@@ -1,7 +0,0 @@
-"ts","int_value"
-1,3
-102,5
-1003,7
-1005,9
-2006,11
-3007,13
diff --git a/test/trace_processor/clock_sync.py b/test/trace_processor/clock_sync.py
deleted file mode 100644
index 9dded25..0000000
--- a/test/trace_processor/clock_sync.py
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/python
-# Copyright (C) 2019 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 synthetic trace tests the clock-sync logic. It synthesizes a trace with
-# (i) builtin clocks, (ii) custom global clocks, (iii) sequence-scoped clocks.
-# It uses gpu counters because that is a quite simple packet and doesn't have
-# special treatement. We can't use ftrace because ftrace events use nested
-# per-event timestamps and they are assumed to be in the CLOCK_MONOTONIC
-# domains regardless of the TracePacket's timestamp_clock_id.
-
-from os import sys, path
-
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-from synth_common import CLONE_THREAD
-
-# Clock IDs in the range [64, 128) are sequence-scoped. See comments in
-# clock_snapshot.proto.
-CLOCK_MONOTONIC = 3  # Builtin clock, see clock_snapshot.proto.
-CLOCK_BOOTTIME = 6  # Builtin clock, see clock_snapshot.proto.
-GLOBAL_CLK1 = 128
-GLOBAL_CLK2 = 129
-SEQ_CLOCK1 = 64
-
-trace = synth_common.create_trace()
-
-# The default trace clock domain is CLOCK_BOOTTIME.
-trace.add_gpu_counter(ts=1, counter_id=42, value=3)
-
-# Emit a ClockSnapshot that sets BOOTTIME = MONOTONIC + 100.
-trace.add_clock_snapshot(clocks={CLOCK_MONOTONIC: 1, CLOCK_BOOTTIME: 101})
-
-# Emit a counter synced against the global built-in clock CLOCK_MONOTONIC.
-# This should be translated, at import time, to BOOTTIME = 2 + 100 = 102.
-trace.add_gpu_counter(ts=2, clock_id=CLOCK_MONOTONIC, counter_id=42, value=5)
-
-# Use two global custom clocks. We sync them as follows:
-# BOOTTIME = GLOBAL_CLK1 + 1000
-# GLOBAL_CLK1 = GLOBAL_CLK2 + 1
-# Hence, recursively:
-# BOOTTIME = GLOBAL_CLK2 + 1000 + 1
-trace.add_clock_snapshot(clocks={GLOBAL_CLK1: 1, CLOCK_BOOTTIME: 1001})
-trace.add_clock_snapshot(clocks={GLOBAL_CLK1: 2, GLOBAL_CLK2: 1})
-
-# This counter should be translated, at import time, to BOOTTIME = 3 + 1000
-trace.add_gpu_counter(ts=3, clock_id=GLOBAL_CLK1, counter_id=42, value=7)
-
-# This one instead to BOOTTIME = 4 + 1000 + 1 = 1005
-trace.add_gpu_counter(ts=4, clock_id=GLOBAL_CLK2, counter_id=42, value=9)
-
-# Use a sequence-scoped clock on two differents sequences.
-# On seq 2, BOOTTIME = SEQ_CLOCK1 + 2000
-# On seq 3, BOOTTIME = SEQ_CLOCK1 + 3000
-trace.add_clock_snapshot(seq_id=2, clocks={SEQ_CLOCK1: 1, CLOCK_BOOTTIME: 2001})
-trace.add_clock_snapshot(seq_id=3, clocks={SEQ_CLOCK1: 1, CLOCK_BOOTTIME: 3001})
-
-# This counter should be translated @ BOOTTIME : 3000 + 7
-trace.add_gpu_counter(
-    ts=7, clock_id=SEQ_CLOCK1, counter_id=42, value=13, seq_id=3)
-
-# This counter should be translated @ BOOTTIME : 2000 + 6
-trace.add_gpu_counter(
-    ts=6, clock_id=SEQ_CLOCK1, seq_id=2, counter_id=42, value=11)
-
-print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/clock_sync.sql b/test/trace_processor/clock_sync.sql
deleted file mode 100644
index 73d5d2a..0000000
--- a/test/trace_processor/clock_sync.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-select ts, cast(value as integer) as int_value
-from counters
-where name like 'gpu_counter%'
\ No newline at end of file
diff --git a/test/trace_processor/compressed_smoke.out b/test/trace_processor/compressed_smoke.out
deleted file mode 100644
index 422aaec..0000000
--- a/test/trace_processor/compressed_smoke.out
+++ /dev/null
@@ -1,11 +0,0 @@
-"ts","cpu","dur","end_state","priority","tid"
-170601497673450,2,53646,"DK",120,6790
-170601497691210,7,22917,"R",120,0
-170601497714127,7,29167,"D",120,6732
-170601497727096,2,55156,"S",120,62
-170601497743294,7,862656,"R",120,0
-170601497766106,3,13594,"S",120,8
-170601497779700,3,31094,"D",120,6790
-170601497782252,2,875313,"R",120,0
-170601497810794,3,824635,"R",120,0
-170601498605950,7,158333,"D",120,6732
diff --git a/test/trace_processor/config.textproto b/test/trace_processor/config.textproto
deleted file mode 100644
index d8b7e46..0000000
--- a/test/trace_processor/config.textproto
+++ /dev/null
@@ -1,19 +0,0 @@
-packet {
-  clock_snapshot {
-    clocks {
-      clock_id: 6
-      timestamp: 101000002
-    }
-    clocks {
-      clock_id: 128
-      timestamp: 2
-    }
-  }
-  timestamp: 101000002
-}
-packet {
-  trace_config {
-    trace_uuid: "abcde\0ghijklmnop"
-  }
-}
-
diff --git a/test/trace_processor/config_metadata.out b/test/trace_processor/config_metadata.out
deleted file mode 100644
index d558719..0000000
--- a/test/trace_processor/config_metadata.out
+++ /dev/null
@@ -1,2 +0,0 @@
-"name","str_value"
-"trace_uuid","61626364-6500-6768-696a-6b6c6d6e6f70"
diff --git a/test/trace_processor/counter_args_join.sql b/test/trace_processor/counter_args_join.sql
new file mode 100644
index 0000000..a082b64
--- /dev/null
+++ b/test/trace_processor/counter_args_join.sql
@@ -0,0 +1,13 @@
+select ts,
+       dur,
+       counters.name as counters_name,
+       value,
+       ref,
+       ref_type,
+       id,
+       args.key as args_key,
+       int_value as utid
+from counters
+inner join args using(arg_set_id)
+where ref = 1
+limit 10;
diff --git a/test/trace_processor/counters_group_by_freq.py b/test/trace_processor/counters_group_by_freq.py
index e39b922..d30f3e3 100644
--- a/test/trace_processor/counters_group_by_freq.py
+++ b/test/trace_processor/counters_group_by_freq.py
@@ -14,7 +14,8 @@
 # limitations under the License.
 
 from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
+
+sys.path.append(path.dirname(path.abspath(__file__)))
 import synth_common
 
 trace = synth_common.create_trace()
diff --git a/test/trace_processor/counters_order_ref.py b/test/trace_processor/counters_order_ref.py
index 0652a34..4cfc2b0 100644
--- a/test/trace_processor/counters_order_ref.py
+++ b/test/trace_processor/counters_order_ref.py
@@ -14,7 +14,8 @@
 # limitations under the License.
 
 from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
+
+sys.path.append(path.dirname(path.abspath(__file__)))
 import synth_common
 
 trace = synth_common.create_trace()
diff --git a/test/trace_processor/counters_ref_type_null.sql b/test/trace_processor/counters_ref_type_null.sql
index 557b933..9cd3aad 100644
--- a/test/trace_processor/counters_ref_type_null.sql
+++ b/test/trace_processor/counters_ref_type_null.sql
@@ -1,3 +1,3 @@
-select id, counter_id, ts, value, arg_set_id, name, ref, ref_type from counters
+select * from counters
 where name = 'MemAvailable' and ref_type is null
 limit 10
diff --git a/test/trace_processor/counters_where_cpu.py b/test/trace_processor/counters_where_cpu.py
index 0f2b1f5..0089289 100644
--- a/test/trace_processor/counters_where_cpu.py
+++ b/test/trace_processor/counters_where_cpu.py
@@ -14,7 +14,8 @@
 # limitations under the License.
 
 from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
+
+sys.path.append(path.dirname(path.abspath(__file__)))
 import synth_common
 
 trace = synth_common.create_trace()
diff --git a/test/trace_processor/filter_row_vector.sql b/test/trace_processor/filter_row_vector.sql
deleted file mode 100644
index 81a2a36..0000000
--- a/test/trace_processor/filter_row_vector.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-SELECT ts FROM counter_values
-WHERE
-  ts > 72563651549 AND
-  counter_id = (
-    SELECT d.counter_id
-    FROM counter_definitions d
-    INNER JOIN process p on d.ref = p.upid
-    WHERE
-      d.name = 'Heap size (KB)'
-      AND d.ref_type = 'upid'
-      AND p.pid = 1204
-  ) AND
-  value != 17952.000000
-LIMIT 20
diff --git a/test/trace_processor/filter_row_vector_example_android_trace_30s.out b/test/trace_processor/filter_row_vector_example_android_trace_30s.out
deleted file mode 100644
index 937091d..0000000
--- a/test/trace_processor/filter_row_vector_example_android_trace_30s.out
+++ /dev/null
@@ -1,21 +0,0 @@
-"ts"
-72688754739
-72688833280
-72688842812
-72688849478
-72688854530
-72688862499
-72688866770
-72688871301
-72706000522
-72706468074
-72706827293
-72706865678
-72706939220
-72707490886
-72707510418
-72707557814
-72707569480
-72707698647
-72707767501
-72722626305
diff --git a/test/trace_processor/fuchsia_smoke.out b/test/trace_processor/fuchsia_smoke.out
index a62db85..cee4586 100644
--- a/test/trace_processor/fuchsia_smoke.out
+++ b/test/trace_processor/fuchsia_smoke.out
@@ -1,11 +1,11 @@
-"ts","cpu","dur","end_state","priority","tid"
-19675868967,2,79022,"S",20,4344
-19676000188,3,504797,"S",20,6547
-19676504985,3,42877,"S",20,6525
-19676582005,0,48467,"S",20,11566
-19676989045,2,138116,"S",20,9949
-19677162311,3,48655,"S",20,6525
-19677305405,3,48814,"S",20,6525
-19677412330,0,177220,"S",20,4344
-19677680485,2,91422,"S",20,6537
-19677791779,3,96082,"S",20,1680
+"ts","cpu","dur","ts_end","utid","end_state","priority","row_id"
+1201809046,3,250854,1202059900,3,"S",16,17179869184
+1202907193,1,56855,1202964048,119,"S",16,17179869185
+1203046904,3,377251,1203424155,60,"S",16,17179869186
+1203449236,0,434524,1203883760,177,"S",16,17179869187
+1203909052,1,589540,1204498592,62,"S",16,17179869188
+1202988568,2,1701153,1204689721,193,"S",16,17179869189
+1206542401,0,57859,1206600260,119,"S",16,17179869190
+1206633498,1,79630,1206713128,68,"S",16,17179869191
+1206737488,2,111620,1206849108,193,"S",16,17179869192
+1207235648,0,54309,1207289957,119,"S",16,17179869193
diff --git a/test/trace_processor/fuchsia_smoke_counters.out b/test/trace_processor/fuchsia_smoke_counters.out
deleted file mode 100644
index a825b25..0000000
--- a/test/trace_processor/fuchsia_smoke_counters.out
+++ /dev/null
@@ -1,6 +0,0 @@
-"ts","value","name","ref_type"
-20329439768,30.331177,"cpu_usage:average_cpu_percentage","utid"
-21331281870,7.829745,"cpu_usage:average_cpu_percentage","utid"
-22332302017,9.669818,"cpu_usage:average_cpu_percentage","utid"
-23332974162,6.421237,"cpu_usage:average_cpu_percentage","utid"
-24333405767,12.079849,"cpu_usage:average_cpu_percentage","utid"
diff --git a/test/trace_processor/fuchsia_smoke_instants.out b/test/trace_processor/fuchsia_smoke_instants.out
deleted file mode 100644
index ea9df77..0000000
--- a/test/trace_processor/fuchsia_smoke_instants.out
+++ /dev/null
@@ -1,11 +0,0 @@
-"ts","name","value","ref_type"
-21442756010,"task_start",0.000000,"utid"
-21446583438,"task_end",0.000000,"utid"
-21448366538,"task_start",0.000000,"utid"
-21450363277,"task_end",0.000000,"utid"
-21454255741,"task_start",0.000000,"utid"
-21457834528,"task_end",0.000000,"utid"
-21459006408,"task_start",0.000000,"utid"
-21460601866,"task_end",0.000000,"utid"
-21461282720,"task_start",0.000000,"utid"
-21462998487,"task_end",0.000000,"utid"
diff --git a/test/trace_processor/fuchsia_smoke_slices.out b/test/trace_processor/fuchsia_smoke_slices.out
index 45dc8fa..7277f95 100644
--- a/test/trace_processor/fuchsia_smoke_slices.out
+++ b/test/trace_processor/fuchsia_smoke_slices.out
@@ -1,3 +1,2 @@
-"ref_type","depth","count"
-"utid",0,1153
-"utid",1,5
+"depth","count"
+0,1000
diff --git a/test/trace_processor/fuchsia_workstation_smoke_slices.out b/test/trace_processor/fuchsia_workstation_smoke_slices.out
deleted file mode 100644
index aef0d43..0000000
--- a/test/trace_processor/fuchsia_workstation_smoke_slices.out
+++ /dev/null
@@ -1,24 +0,0 @@
-"ref_type","depth","count"
-"track",0,84
-"track",1,14
-"track",2,2
-"utid",0,13379
-"utid",1,11548
-"utid",2,10181
-"utid",3,1927
-"utid",4,4001
-"utid",5,2543
-"utid",6,1856
-"utid",7,2209
-"utid",8,2200
-"utid",9,1672
-"utid",10,353
-"utid",11,331
-"utid",12,304
-"utid",13,246
-"utid",14,207
-"utid",15,175
-"utid",16,114
-"utid",17,38
-"utid",18,12
-"utid",19,1
diff --git a/test/trace_processor/gpu_counters.out b/test/trace_processor/gpu_counters.out
deleted file mode 100644
index e630e54..0000000
--- a/test/trace_processor/gpu_counters.out
+++ /dev/null
@@ -1,13 +0,0 @@
-"counter_id","ts","value","name","ref","ref_type","description","unit"
-0,11,5.000000,"Vertex / Second",0,"gpu","Number of vertices per second","25/22"
-1,12,7.000000,"Fragment / Second",0,"gpu","Number of fragments per second","26/22"
-3,13,8.000000,"gpu_counter(33)",0,"gpu","[NULL]","[NULL]"
-2,14,0.000000,"Triangle Acceleration",0,"gpu","Number of triangles per ms-ms","27/21:21"
-0,21,10.000000,"Vertex / Second",0,"gpu","Number of vertices per second","25/22"
-1,22,14.000000,"Fragment / Second",0,"gpu","Number of fragments per second","26/22"
-3,23,16.000000,"gpu_counter(33)",0,"gpu","[NULL]","[NULL]"
-2,24,9.000000,"Triangle Acceleration",0,"gpu","Number of triangles per ms-ms","27/21:21"
-0,31,15.000000,"Vertex / Second",0,"gpu","Number of vertices per second","25/22"
-1,32,21.000000,"Fragment / Second",0,"gpu","Number of fragments per second","26/22"
-3,33,25.000000,"gpu_counter(33)",0,"gpu","[NULL]","[NULL]"
-2,34,7.000000,"Triangle Acceleration",0,"gpu","Number of triangles per ms-ms","27/21:21"
diff --git a/test/trace_processor/gpu_counters.py b/test/trace_processor/gpu_counters.py
deleted file mode 100644
index 4882167..0000000
--- a/test/trace_processor/gpu_counters.py
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/python
-# Copyright (C) 2019 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.
-
-from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-# See gpu_counter_descriptor.proto
-MILLISECOND = 21
-SECOND = 22
-VERTEX = 25
-PIXEL = 26
-TRIANGLE = 27
-
-trace = synth_common.create_trace()
-
-# Add 3 counter specs.
-trace.add_gpu_counter_spec(
-    ts=1,
-    counter_id=31,
-    name="Vertex / Second",
-    description="Number of vertices per second",
-    unit_numerators=[VERTEX],
-    unit_denominators=[SECOND])
-trace.add_gpu_counter_spec(
-    ts=2,
-    counter_id=32,
-    name="Fragment / Second",
-    description="Number of fragments per second",
-    unit_numerators=[PIXEL],
-    unit_denominators=[SECOND])
-trace.add_gpu_counter_spec(
-    ts=3,
-    counter_id=34,
-    name="Triangle Acceleration",
-    description="Number of triangles per ms-ms",
-    unit_numerators=[TRIANGLE],
-    unit_denominators=[MILLISECOND, MILLISECOND])
-
-# Add some counter value events.
-trace.add_gpu_counter(11, 31, 5)
-trace.add_gpu_counter(21, 31, 10)
-trace.add_gpu_counter(31, 31, 15)
-
-trace.add_gpu_counter(12, 32, 7)
-trace.add_gpu_counter(22, 32, 14)
-trace.add_gpu_counter(32, 32, 21)
-
-# Counter without a spec.
-trace.add_gpu_counter(13, 33, 8)
-trace.add_gpu_counter(23, 33, 16)
-trace.add_gpu_counter(33, 33, 25)
-
-trace.add_gpu_counter(14, 34, 0)
-trace.add_gpu_counter(24, 34, 9)
-trace.add_gpu_counter(34, 34, 7)
-
-print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/gpu_counters.sql b/test/trace_processor/gpu_counters.sql
deleted file mode 100644
index 40bdf06..0000000
--- a/test/trace_processor/gpu_counters.sql
+++ /dev/null
@@ -1 +0,0 @@
-select "counter_id","ts","value","name","ref","ref_type","description","unit" from counters order by "ts";
diff --git a/test/trace_processor/gpu_log.out b/test/trace_processor/gpu_log.out
deleted file mode 100644
index 61b1c09..0000000
--- a/test/trace_processor/gpu_log.out
+++ /dev/null
@@ -1,13 +0,0 @@
-"scope","track_name","ts","dur","slice_name","key","value"
-"gpu_log","GPU Log",1,0,"VERBOSE","message","message0"
-"gpu_log","GPU Log",1,0,"VERBOSE","tag","tag0"
-"gpu_log","GPU Log",2,0,"DEBUG","message","message1"
-"gpu_log","GPU Log",2,0,"DEBUG","tag","tag0"
-"gpu_log","GPU Log",3,0,"INFO","message","message2"
-"gpu_log","GPU Log",3,0,"INFO","tag","tag0"
-"gpu_log","GPU Log",4,0,"ERROR","message","message4"
-"gpu_log","GPU Log",4,0,"ERROR","tag","tag0"
-"gpu_log","GPU Log",4,0,"WARNING","message","message3"
-"gpu_log","GPU Log",4,0,"WARNING","tag","tag0"
-"gpu_log","GPU Log",5,0,"VERBOSE","message","message5"
-"gpu_log","GPU Log",5,0,"VERBOSE","tag","tag1"
diff --git a/test/trace_processor/gpu_log.py b/test/trace_processor/gpu_log.py
deleted file mode 100644
index b4b0369..0000000
--- a/test/trace_processor/gpu_log.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/python
-# Copyright (C) 2019 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.
-
-from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-trace = synth_common.create_trace()
-trace.add_gpu_log(ts=1, severity=1, tag="tag0", message="message0")
-trace.add_gpu_log(ts=2, severity=2, tag="tag0", message="message1")
-trace.add_gpu_log(ts=3, severity=3, tag="tag0", message="message2")
-trace.add_gpu_log(ts=4, severity=4, tag="tag0", message="message3")
-trace.add_gpu_log(ts=4, severity=5, tag="tag0", message="message4")
-trace.add_gpu_log(ts=5, severity=1, tag="tag1", message="message5")
-
-print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/gpu_log.sql b/test/trace_processor/gpu_log.sql
deleted file mode 100644
index dd846e3..0000000
--- a/test/trace_processor/gpu_log.sql
+++ /dev/null
@@ -1,7 +0,0 @@
-select scope, track.name as track_name, ts, dur, gpu_slice.name as slice_name,
-    key, string_value as value
-from gpu_track
-left join track using (id)
-left join gpu_slice on gpu_track.id=gpu_slice.track_id
-left join args using (arg_set_id)
-order by ts, slice_name, key
diff --git a/test/trace_processor/gpu_render_stages.out b/test/trace_processor/gpu_render_stages.out
deleted file mode 100644
index 4eaa783..0000000
--- a/test/trace_processor/gpu_render_stages.out
+++ /dev/null
@@ -1,19 +0,0 @@
-"track_name","ts","dur","slice_name","depth","arg_set_id","flat_key","string_value","context_id","render_target","submission_id","hw_queue_id"
-"queue 1",10,5,"stage 1",0,1,"keyOnlyTest","[NULL]",42,0,0,1
-"queue 1",10,5,"stage 1",0,1,"stencilBPP","1",42,0,0,1
-"queue 1",10,5,"stage 1",0,1,"height","1.000000",42,0,0,1
-"queue 0",20,5,"stage 2",0,2,"keyOnlyTest","[NULL]",42,0,0,0
-"queue 0",20,5,"stage 2",0,2,"height","4.000000",42,0,0,0
-"queue 1",30,5,"stage 0",0,3,"keyOnlyTest","[NULL]",42,0,0,1
-"queue 1",30,5,"stage 0",0,3,"stencilBPP","1",42,0,0,1
-"queue 1",30,5,"stage 0",0,3,"height","9.000000",42,0,0,1
-"queue 0",40,5,"stage 1",0,0,"[NULL]","[NULL]",42,0,0,0
-"queue 1",50,5,"stage 2",0,4,"keyOnlyTest","[NULL]",42,0,0,1
-"queue 1",50,5,"stage 2",0,4,"stencilBPP","1",42,0,0,1
-"queue 1",50,5,"stage 2",0,4,"height","25.000000",42,0,0,1
-"queue 0",60,5,"stage 0",0,5,"keyOnlyTest","[NULL]",42,0,0,0
-"queue 0",60,5,"stage 0",0,5,"height","36.000000",42,0,0,0
-"queue 1",70,5,"stage 1",0,6,"keyOnlyTest","[NULL]",42,0,0,1
-"queue 1",70,5,"stage 1",0,6,"stencilBPP","1",42,0,0,1
-"queue 1",70,5,"stage 1",0,6,"height","49.000000",42,0,0,1
-"queue 0",80,5,"stage 2",0,0,"[NULL]","[NULL]",42,0,0,0
diff --git a/test/trace_processor/gpu_render_stages.sql b/test/trace_processor/gpu_render_stages.sql
deleted file mode 100644
index e534e99..0000000
--- a/test/trace_processor/gpu_render_stages.sql
+++ /dev/null
@@ -1,8 +0,0 @@
-SELECT track.name AS track_name, ts,dur, gpu_slice.name AS slice_name,
-    depth, gpu_slice.arg_set_id, flat_key, string_value, gpu_slice.context_id,
-    render_target, submission_id, hw_queue_id
-FROM gpu_track
-LEFT JOIN track USING (id)
-INNER JOIN gpu_slice on gpu_track.id=gpu_slice.track_id
-LEFT JOIN args ON gpu_slice.arg_set_id = args.arg_set_id
-ORDER BY ts;
diff --git a/test/trace_processor/graphics_frame_events.out b/test/trace_processor/graphics_frame_events.out
deleted file mode 100644
index c6fa313..0000000
--- a/test/trace_processor/graphics_frame_events.out
+++ /dev/null
@@ -1,13 +0,0 @@
-"scope","track_name","ts","dur","slice_name","frame_id","key","layer_name"
-"graphics_frame_event","layer1[buffer:1]",1,6,"Dequeue",11,"layer_name","layer1"
-"graphics_frame_event","layer1[buffer:1]",6,11,"Dequeue",12,"layer_name","layer1"
-"graphics_frame_event","layer2[buffer:2]",2,7,"Queue",11,"layer_name","layer2"
-"graphics_frame_event","layer2[buffer:2]",7,12,"Queue",12,"layer_name","layer2"
-"graphics_frame_event","layer2[buffer:2]",8,2,"Detach",14,"layer_name","layer2"
-"graphics_frame_event","layer3[buffer:3]",3,8,"Post",11,"layer_name","layer3"
-"graphics_frame_event","layer3[buffer:3]",8,13,"Post",12,"layer_name","layer3"
-"graphics_frame_event","layer3[buffer:3]",9,5,"Attach",15,"layer_name","layer3"
-"graphics_frame_event","layer3[buffer:3]",10,10,"Cancel",16,"layer_name","layer3"
-"graphics_frame_event","layer4[buffer:4]",4,9,"AcquireFenceSignaled",11,"layer_name","layer4"
-"graphics_frame_event","layer5[buffer:5]",5,10,"Latch",11,"layer_name","layer5"
-"graphics_frame_event","layer7[buffer:7]",7,12,"unknown_event",13,"layer_name","layer7"
diff --git a/test/trace_processor/graphics_frame_events.py b/test/trace_processor/graphics_frame_events.py
deleted file mode 100755
index 2eeb7bd..0000000
--- a/test/trace_processor/graphics_frame_events.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/python
-# Copyright (C) 2019 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.
-
-from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-class BufferEvent:
-  UNSPECIFIED = 0
-  DEQUEUE = 1
-  QUEUE = 2
-  POST = 3
-  ACQUIRE_FENCE = 4
-  LATCH = 5
-  HWC_COMPOSITION_QUEUED = 6
-  FALLBACK_COMPOSITION = 7
-  PRESENT_FENCE = 8
-  RELEASE_FENCE = 9
-  MODIFY = 10
-  DETACH = 11
-  ATTACH = 12
-  CANCEL = 13
-
-trace = synth_common.create_trace()
-trace.add_buffer_event_packet(ts=1, buffer_id=1, layer_name="layer1", frame_number=11, event_type=BufferEvent.DEQUEUE, duration=6)
-trace.add_buffer_event_packet(ts=2, buffer_id=2, layer_name="layer2", frame_number=11, event_type=BufferEvent.QUEUE, duration=7)
-trace.add_buffer_event_packet(ts=3, buffer_id=3, layer_name="layer3", frame_number=11, event_type=BufferEvent.POST, duration=8)
-trace.add_buffer_event_packet(ts=4, buffer_id=4, layer_name="layer4", frame_number=11, event_type=BufferEvent.ACQUIRE_FENCE, duration=9)
-trace.add_buffer_event_packet(ts=5, buffer_id=5, layer_name="layer5", frame_number=11, event_type=BufferEvent.LATCH, duration=10)
-# Repeat some layers
-trace.add_buffer_event_packet(ts=6, buffer_id=1, layer_name="layer1", frame_number=12, event_type=BufferEvent.DEQUEUE, duration=11)
-trace.add_buffer_event_packet(ts=7, buffer_id=2, layer_name="layer2", frame_number=12, event_type=BufferEvent.QUEUE, duration=12)
-trace.add_buffer_event_packet(ts=8, buffer_id=3, layer_name="layer3", frame_number=12, event_type=BufferEvent.POST, duration=13)
-# Missing id.
-trace.add_buffer_event_packet(ts=6, buffer_id=-1, layer_name="layer6", frame_number=13, event_type=BufferEvent.HWC_COMPOSITION_QUEUED, duration=11)
-# Missing type.
-trace.add_buffer_event_packet(ts=7, buffer_id=7, layer_name="layer7", frame_number=13, event_type=-1, duration=12)
-# Add some more events
-trace.add_buffer_event_packet(ts=8, buffer_id=2, layer_name="layer2", frame_number=14, event_type=BufferEvent.DETACH, duration=2)
-trace.add_buffer_event_packet(ts=9, buffer_id=3, layer_name="layer3", frame_number=15, event_type=BufferEvent.ATTACH, duration=5)
-trace.add_buffer_event_packet(ts=10, buffer_id=3, layer_name="layer3", frame_number=16, event_type=BufferEvent.CANCEL, duration=10)
-print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/graphics_frame_events.sql b/test/trace_processor/graphics_frame_events.sql
deleted file mode 100644
index 2c51484..0000000
--- a/test/trace_processor/graphics_frame_events.sql
+++ /dev/null
@@ -1,6 +0,0 @@
-select scope, track.name as track_name, ts, dur, gpu_slice.name as slice_name,
-    frame_id, key, string_value as layer_name
-from gpu_track
-left join track using (id)
-left join gpu_slice on gpu_track.id=gpu_slice.track_id
-left join args on gpu_slice.arg_set_id=args.arg_set_id and args.key='layer_name'
diff --git a/test/trace_processor/heap_graph.textproto b/test/trace_processor/heap_graph.textproto
deleted file mode 100644
index b785578..0000000
--- a/test/trace_processor/heap_graph.textproto
+++ /dev/null
@@ -1,63 +0,0 @@
-packet {
-  process_tree {
-    processes {
-      pid: 1
-      ppid: 0
-      cmdline: "init"
-    }
-    processes {
-      pid: 2
-      ppid: 1
-      cmdline: "system_server"
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 999
-  timestamp: 10
-  heap_graph {
-    pid: 2
-    roots {
-      root_type: ROOT_JAVA_FRAME
-      object_ids: 0x01
-    }
-    objects {
-      id: 0x01
-      type_id: 1
-      self_size: 64
-      reference_field_id: 1
-      reference_object_id: 2
-    }
-    objects {
-      id: 0x02
-      type_id: 2
-      self_size: 32
-    }
-    objects {
-      id: 0x03
-      type_id: 2
-      self_size: 128
-    }
-    continued: true
-    index: 1
-  }
-}
-packet {
-  heap_graph {
-    pid: 2
-    type_names {
-      iid: 1
-      str: "FactoryProducerDelegateImplActor"
-    }
-    type_names {
-      iid: 2
-      str: "Foo"
-    }
-    field_names {
-      iid: 1
-      str: "FactoryProducerDelegateImplActor.foo"
-    }
-    continued: false
-    index: 2
-  }
-}
diff --git a/test/trace_processor/heap_graph_object.out b/test/trace_processor/heap_graph_object.out
deleted file mode 100644
index b0f9e43..0000000
--- a/test/trace_processor/heap_graph_object.out
+++ /dev/null
@@ -1,4 +0,0 @@
-"id","type","upid","graph_sample_ts","object_id","self_size","retained_size","unique_retained_size","reference_set_id","reachable","type_name","root_type"
-0,"heap_graph_object",2,10,1,64,96,96,0,1,"FactoryProducerDelegateImplActor","ROOT_JAVA_FRAME"
-1,"heap_graph_object",2,10,2,32,32,32,1,1,"Foo","[NULL]"
-2,"heap_graph_object",2,10,3,128,-1,0,1,0,"Foo","[NULL]"
diff --git a/test/trace_processor/heap_graph_object.sql b/test/trace_processor/heap_graph_object.sql
deleted file mode 100644
index 2c4866f..0000000
--- a/test/trace_processor/heap_graph_object.sql
+++ /dev/null
@@ -1 +0,0 @@
-select * from heap_graph_object
diff --git a/test/trace_processor/heap_graph_reference.out b/test/trace_processor/heap_graph_reference.out
deleted file mode 100644
index 3be9676..0000000
--- a/test/trace_processor/heap_graph_reference.out
+++ /dev/null
@@ -1,2 +0,0 @@
-"id","type","reference_set_id","owner_id","owned_id","field_name"
-0,"heap_graph_reference",0,0,1,"FactoryProducerDelegateImplActor.foo"
diff --git a/test/trace_processor/heap_graph_reference.sql b/test/trace_processor/heap_graph_reference.sql
deleted file mode 100644
index e0fe907..0000000
--- a/test/trace_processor/heap_graph_reference.sql
+++ /dev/null
@@ -1 +0,0 @@
-select * from heap_graph_reference
diff --git a/test/trace_processor/heap_profile_frames.sql b/test/trace_processor/heap_profile_frames.sql
deleted file mode 100644
index 9aa5b81..0000000
--- a/test/trace_processor/heap_profile_frames.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT name, mapping, rel_pc FROM stack_profile_frame ORDER BY name;
diff --git a/test/trace_processor/heap_profile_jit.out b/test/trace_processor/heap_profile_jit.out
deleted file mode 100644
index 1235280..0000000
--- a/test/trace_processor/heap_profile_jit.out
+++ /dev/null
@@ -1,3 +0,0 @@
-"name","mapping","rel_pc"
-"java_frame_1",0,4096
-"java_frame_2",0,4096
diff --git a/test/trace_processor/heap_profile_jit.textproto b/test/trace_processor/heap_profile_jit.textproto
deleted file mode 100644
index 338fbbf..0000000
--- a/test/trace_processor/heap_profile_jit.textproto
+++ /dev/null
@@ -1,81 +0,0 @@
-packet {
-  process_tree {
-    processes {
-      pid: 1
-      ppid: 0
-      cmdline: "init"
-    }
-    processes {
-      pid: 2
-      ppid: 1
-      cmdline: "system_server"
-    }
-  }
-}
-packet {
-  trusted_packet_sequence_id: 999
-  previous_packet_dropped: true
-  incremental_state_cleared: true
-  timestamp: 10
-  profile_packet {
-    strings {
-      iid: 1
-      str: "java_frame_1"
-    }
-    strings {
-      iid: 2
-      str: "java_frame_2"
-    }
-    strings {
-      iid: 3
-      str: "jit-mapping"
-    }
-    strings {
-      iid: 4
-      str: "buildid"
-    }
-    frames {
-      iid: 1
-      function_name_id: 1
-      mapping_id: 1
-      rel_pc: 0x1000
-    }
-    frames {
-      iid: 2
-      function_name_id: 2
-      mapping_id: 1
-      rel_pc: 0x1000
-    }
-    callstacks {
-      iid: 1
-      frame_ids: 1
-    }
-    callstacks {
-      iid: 2
-      frame_ids: 2
-    }
-    mappings {
-      iid: 1
-      path_string_ids: 3
-      build_id: 4
-    }
-    process_dumps {
-      pid: 2
-      samples {
-        callstack_id: 1
-        self_allocated: 2000
-        self_freed: 1000
-        alloc_count: 2
-        free_count: 1
-      }
-      samples {
-        callstack_id: 2
-        self_allocated: 100
-        self_freed: 10
-        alloc_count: 10
-        free_count: 1
-      }
-    }
-  }
-}
-
diff --git a/test/trace_processor/index b/test/trace_processor/index
index 958b11e..395b602 100644
--- a/test/trace_processor/index
+++ b/test/trace_processor/index
@@ -2,21 +2,12 @@
 ../data/sfgate.json smoke.sql sfgate_smoke.out
 ../data/sfgate.json smoke_slices.sql sfgate_smoke_slices.out
 ../data/android_sched_and_ps.pb smoke.sql android_sched_and_ps_smoke.out
-../data/compressed.pb smoke.sql compressed_smoke.out
 synth_1.py smoke.sql synth_1_smoke.out
 ../data/fuchsia_trace.fxt smoke.sql fuchsia_smoke.out
 ../data/fuchsia_trace.fxt smoke_slices.sql fuchsia_smoke_slices.out
-../data/fuchsia_trace.fxt smoke_instants.sql fuchsia_smoke_instants.out
-../data/fuchsia_trace.fxt smoke_counters.sql fuchsia_smoke_counters.out
-../data/fuchsia_workstation.fxt smoke_slices.sql fuchsia_workstation_smoke_slices.out
 
 # Test for the process<>thread tracking logic.
 synth_process_tracking.py process_tracking.sql process_tracking.out
-process_tracking_short_lived_1.py process_tracking.sql process_tracking_process_tracking_short_lived_1.out
-process_tracking_short_lived_2.py process_tracking.sql process_tracking_process_tracking_short_lived_2.out
-process_tracking_exec.py process_tracking.sql process_tracking_process_tracking_exec.out
-process_parent_pid_tracking_1.py process_parent_pid.sql process_parent_pid_process_parent_pid_tracking_1.out
-process_parent_pid_tracking_2.py process_parent_pid.sql process_parent_pid_process_parent_pid_tracking_2.out
 
 # Test for computing CPU time from sched events for threads.
 ../data/example_android_trace_30s.pb thread_cpu_time.sql thread_cpu_time_example_android_trace_30s.out
@@ -57,6 +48,10 @@
 ../data/memory_counters.pb args_string_filter_null.sql memory_counters_args_string_filter_null.out
 ../data/memory_counters.pb args_string_is_null.sql memory_counters_args_string_is_null.out
 ../data/memory_counters.pb args_string_is_not_null.sql memory_counters_args_string_is_not_null.out
+# TODO(lalitm): this still doesn't work because we no longer add utid
+# args for memory counters (because they are keyed by upid).
+# ../data/memory_counters.pb smoke_args.sql memory_counters_smoke_args.out
+# ../data/memory_counters.pb counter_args_join.sql memory_counters_counter_args_join.out
 ../data/memory_counters.pb b120605557.sql memory_counters_b120605557.out
 ../data/memory_counters.pb counters_ref_type_null.sql counters_ref_type_null_memory_counters.out
 
@@ -68,11 +63,6 @@
 
 # Power rails
 ../data/power_rails.pb power_rails.sql power_rails_power_rails.out
-power_rail_custom_clock.textproto power_rail_event.sql power_rail_event_power_rail_custom_clock.out
-
-
-# Android userspace async slices
-android_async_slice.textproto process_track_slices.sql process_track_slices_android_async_slice.out
 
 
 # The below tests check the autogenerated tables.
@@ -85,7 +75,6 @@
 ../data/android_sched_and_ps.pb span_left_join_left_unpartitioned.sql span_left_join_left_unpartitioned.out
 ../data/android_sched_and_ps.pb span_left_join_left_partitioned.sql span_left_join_left_partitioned.out
 ../data/android_sched_and_ps.pb span_outer_join.sql span_outer_join.out
-../data/android_sched_and_ps.pb span_left_join_empty_right.sql span_left_join_empty_right.out
 
 # Window table
 ../data/android_sched_and_ps.pb smoke_window.sql android_sched_and_ps_smoke_window.out
@@ -104,7 +93,6 @@
 counters_where_cpu.py counters_where_cpu.sql counters_where_cpu_counters_where_cpu.out
 counters_group_by_freq.py counters_group_by_freq.sql counters_group_by_freq_counters_group_by_freq.out
 counters_order_ref.py counters_order_ref.sql counters_order_ref_counters_order_ref.out
-../data/example_android_trace_30s.pb filter_row_vector.sql filter_row_vector_example_android_trace_30s.out
 
 # Null printing
 synth_1.py nulls.sql nulls.out
@@ -113,44 +101,3 @@
 # The below tests check the systrace conversion code in the raw table.
 # Print events
 ../data/lmk_userspace.pb print_systrace.sql print_systrace_lmk_userspace.out
-# Unsigned integers
-print_systrace_unsigned.py print_systrace.sql print_systrace_unsigned.out
-
-# GPU trace tests.
-gpu_counters.py gpu_counters.sql gpu_counters.out
-../data/gpu_trace.pb gpu_render_stages.sql gpu_render_stages.out
-gpu_log.py gpu_log.sql gpu_log.out
-
-# Clock sync
-clock_sync.py clock_sync.sql clock_sync.out
-
-# Graphics frame event trace tests.
-graphics_frame_events.py graphics_frame_events.sql graphics_frame_events.out
-
-# Scheduling slices from sched_switch events. There are two tests, one for the
-# typical encoding of sched_switch events, and one for the same trace
-# re-encoded in the compact format. The output should be identical apart from
-# the latter having one slice fewer for each cpu (the first compact
-# sched_switch event doesn't start a slice). Six slices in this case.
-../data/sched_switch_original.pb sched_slices.sql sched_slices_sched_switch_original.out
-../data/sched_switch_compact.pb sched_slices.sql sched_slices_sched_switch_compact.out
-
-heap_profile_jit.textproto heap_profile_frames.sql heap_profile_jit.out
-
-heap_graph.textproto heap_graph_object.sql heap_graph_object.out
-heap_graph.textproto heap_graph_reference.sql heap_graph_reference.out
-
-# TrackEvent tests.
-track_event_same_tids.py process_tracking.sql track_event_same_tids_threads.out
-track_event_same_tids.py track_event_slices.sql track_event_same_tids_slices.out
-
-# Parsing of an html file with systrace data inside
-../data/systrace.html systrace_html.sql systrace_html.out
-
-# Config
-config.textproto metadata.sql config_metadata.out
-
-# Decoding of sched_waking events from a trace with compact scheduling events.
-# Verifies the contents of raw & instants tables.
-../data/compact_sched.pb sched_waking_raw.sql sched_waking_raw_compact_sched.out
-../data/compact_sched.pb sched_waking_instants.sql sched_waking_instants_compact_sched.out
diff --git a/test/trace_processor/kernel_lmk.py b/test/trace_processor/kernel_lmk.py
index 98681f5..6269f4e 100644
--- a/test/trace_processor/kernel_lmk.py
+++ b/test/trace_processor/kernel_lmk.py
@@ -14,7 +14,8 @@
 # limitations under the License.
 
 from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
+
+sys.path.append(path.dirname(path.abspath(__file__)))
 import synth_common
 
 trace = synth_common.create_trace()
diff --git a/test/trace_processor/memory_counters_counter_args_join.out b/test/trace_processor/memory_counters_counter_args_join.out
new file mode 100644
index 0000000..d66d86b
--- /dev/null
+++ b/test/trace_processor/memory_counters_counter_args_join.out
@@ -0,0 +1,11 @@
+"ts","dur","counters_name","value","ref","ref_type","id","args_key","utid"
+22240238407793,97669645,"mem.virt",36487168.000000,1,"upid",4294967296,"utid",7
+22240238407793,97669645,"mem.rss",6008832.000000,1,"upid",4294967297,"utid",7
+22240238407793,97669645,"mem.rss.anon",2281472.000000,1,"upid",4294967298,"utid",7
+22240238407793,97669645,"mem.rss.file",3047424.000000,1,"upid",4294967299,"utid",7
+22240238407793,97669645,"mem.rss.shmem",679936.000000,1,"upid",4294967300,"utid",7
+22240238407793,97669645,"mem.swap",0.000000,1,"upid",4294967301,"utid",7
+22240238407793,97669645,"mem.locked",0.000000,1,"upid",4294967302,"utid",7
+22240238407793,97669645,"mem.rss.watermark",6008832.000000,1,"upid",4294967303,"utid",7
+22240336077438,75130528,"mem.virt",36487168.000000,1,"upid",4294968284,"utid",7
+22240336077438,75130528,"mem.rss",6008832.000000,1,"upid",4294968285,"utid",7
diff --git a/test/trace_processor/memory_counters_smoke_args.out b/test/trace_processor/memory_counters_smoke_args.out
new file mode 100644
index 0000000..f8afa6b
--- /dev/null
+++ b/test/trace_processor/memory_counters_smoke_args.out
@@ -0,0 +1,11 @@
+"id","flat_key","key","int_value","string_value","real_value"
+4294967296,"utid","utid",7,"[NULL]","[NULL]"
+4294967297,"utid","utid",7,"[NULL]","[NULL]"
+4294967298,"utid","utid",7,"[NULL]","[NULL]"
+4294967299,"utid","utid",7,"[NULL]","[NULL]"
+4294967300,"utid","utid",7,"[NULL]","[NULL]"
+4294967301,"utid","utid",7,"[NULL]","[NULL]"
+4294967302,"utid","utid",7,"[NULL]","[NULL]"
+4294967303,"utid","utid",7,"[NULL]","[NULL]"
+4294967304,"utid","utid",8,"[NULL]","[NULL]"
+4294967305,"utid","utid",8,"[NULL]","[NULL]"
diff --git a/test/trace_processor/metadata.sql b/test/trace_processor/metadata.sql
deleted file mode 100644
index 34eddee..0000000
--- a/test/trace_processor/metadata.sql
+++ /dev/null
@@ -1 +0,0 @@
-select name, str_value from metadata where name = "trace_uuid";
diff --git a/test/trace_processor/power_rail_custom_clock.textproto b/test/trace_processor/power_rail_custom_clock.textproto
deleted file mode 100644
index c7eeb09..0000000
--- a/test/trace_processor/power_rail_custom_clock.textproto
+++ /dev/null
@@ -1,57 +0,0 @@
-packet {
-  clock_snapshot {
-    clocks {
-      clock_id: 6
-      timestamp: 101000002
-    }
-    clocks {
-      clock_id: 128
-      timestamp: 2
-    }
-  }
-  timestamp: 101000002
-}
-packet {
-  power_rails {
-    rail_descriptor {
-      index: 4
-      rail_name: "test_rail"
-      subsys_name: "test_subsys"
-      sampling_rate: 1023
-    }
-  }
-}
-packet {
-  timestamp: 3000000
-  power_rails {
-    energy_data {
-      index: 4
-      energy: 333
-    }
-  }
-  timestamp_clock_id: 128
-}
-packet {
-  timestamp: 5000000
-  power_rails {
-    energy_data {
-      index: 4
-      energy: 666
-    }
-  }
-  timestamp_clock_id: 128
-}
-packet {
-  power_rails {
-    energy_data {
-      index: 4
-      timestamp_ms: 106
-      energy: 999
-    }
-    energy_data {
-      index: 4
-      timestamp_ms: 109
-      energy: 0
-    }
-  }
-}
diff --git a/test/trace_processor/power_rail_event.sql b/test/trace_processor/power_rail_event.sql
deleted file mode 100644
index 0082ac3..0000000
--- a/test/trace_processor/power_rail_event.sql
+++ /dev/null
@@ -1,4 +0,0 @@
-select ts, value
-from counters
-where name like "power.%"
-limit 20
diff --git a/test/trace_processor/power_rail_event_power_rail_custom_clock.out b/test/trace_processor/power_rail_event_power_rail_custom_clock.out
deleted file mode 100644
index 4c222eb..0000000
--- a/test/trace_processor/power_rail_event_power_rail_custom_clock.out
+++ /dev/null
@@ -1,5 +0,0 @@
-"ts","value"
-104000000,333.000000
-106000000,666.000000
-106000000,999.000000
-109000000,0.000000
diff --git a/test/trace_processor/print_systrace_lmk_userspace.out b/test/trace_processor/print_systrace_lmk_userspace.out
index c947de8..24b9e57 100644
--- a/test/trace_processor/print_systrace_lmk_userspace.out
+++ b/test/trace_processor/print_systrace_lmk_userspace.out
@@ -1,9 +1,9 @@
 "to_ftrace(id)"
-"       <unknown>-937   (  937) [002] .... 732246.100696: tracing_mark_write: C|937|kill_one_process|17924"
-"       <unknown>-937   (  937) [002] .... 732246.101048: tracing_mark_write: C|937|kill_one_process|0"
-"       <unknown>-937   (  937) [002] .... 732246.180149: tracing_mark_write: C|937|kill_one_process|21090"
-"       <unknown>-937   (  937) [002] .... 732246.180405: tracing_mark_write: C|937|kill_one_process|0"
-"       <unknown>-937   (  937) [001] .... 732246.388596: tracing_mark_write: C|937|kill_one_process|21120"
-"       <unknown>-937   (  937) [001] .... 732246.388961: tracing_mark_write: C|937|kill_one_process|0"
-"       <unknown>-937   (  937) [002] .... 732246.415955: tracing_mark_write: C|937|kill_one_process|21151"
-"       <unknown>-937   (  937) [002] .... 732246.416207: tracing_mark_write: C|937|kill_one_process|0"
+"                -937   (  937) [002] .... 732246.100696: tracing_mark_write: C|937|kill_one_process|17924"
+"                -937   (  937) [002] .... 732246.101048: tracing_mark_write: C|937|kill_one_process|0"
+"                -937   (  937) [002] .... 732246.180149: tracing_mark_write: C|937|kill_one_process|21090"
+"                -937   (  937) [002] .... 732246.180405: tracing_mark_write: C|937|kill_one_process|0"
+"                -937   (  937) [001] .... 732246.388596: tracing_mark_write: C|937|kill_one_process|21120"
+"                -937   (  937) [001] .... 732246.388961: tracing_mark_write: C|937|kill_one_process|0"
+"                -937   (  937) [002] .... 732246.415955: tracing_mark_write: C|937|kill_one_process|21151"
+"                -937   (  937) [002] .... 732246.416207: tracing_mark_write: C|937|kill_one_process|0"
diff --git a/test/trace_processor/print_systrace_unsigned.out b/test/trace_processor/print_systrace_unsigned.out
deleted file mode 100644
index c12c888..0000000
--- a/test/trace_processor/print_systrace_unsigned.out
+++ /dev/null
@@ -1,4 +0,0 @@
-"to_ftrace(id)"
-"       <unknown>-10    (   10) [000] .... 0.000000: kfree: call_site=16 ptr=32"
-"       <unknown>-10    (   10) [000] .... 0.000000: kfree: call_site=18446744073709551600 ptr=18446744073709551584"
-"       <unknown>-10    (   10) [000] .... 0.000000: kmalloc: bytes_alloc=32 bytes_req=16 call_site=18446744073709551600 gfp_flags=0 ptr=18446744073709551584"
diff --git a/test/trace_processor/print_systrace_unsigned.py b/test/trace_processor/print_systrace_unsigned.py
deleted file mode 100644
index e3e5d56..0000000
--- a/test/trace_processor/print_systrace_unsigned.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/python
-# Copyright (C) 2019 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.
-
-from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-trace = synth_common.create_trace()
-
-# kfree:
-# field:unsigned long call_site;        offset:8;       size:8; signed:0;
-# field:const void * ptr;               offset:16;      size:8; signed:0;
-
-# kmalloc:
-# field:unsigned long call_site;        offset:8;       size:8; signed:0;
-# field:const void * ptr;               offset:16;      size:8; signed:0;
-# field:size_t bytes_req;               offset:24;      size:8; signed:0;
-# field:size_t bytes_alloc;             offset:32;      size:8; signed:0;
-# field:gfp_t gfp_flags;                offset:40;      size:4; signed:0;
-
-# Without special-casing, we print everything as unsigned decimal.
-
-trace.add_process_tree_packet()
-trace.add_process(pid=10, ppid=1, cmdline="perfetto")
-
-trace.add_ftrace_packet(cpu=0)
-trace.add_kfree(ts=100, tid=10, call_site=16, ptr=32)
-trace.add_kfree(ts=101, tid=10, call_site=(1 << 64) - 16, ptr=(1 << 64) - 32)
-trace.add_kmalloc(
-    ts=102,
-    tid=10,
-    bytes_alloc=32,
-    bytes_req=16,
-    call_site=(1 << 64) - 16,
-    gfp_flags=0,
-    ptr=(1 << 64) - 32)
-
-print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_parent_pid.sql b/test/trace_processor/process_parent_pid.sql
deleted file mode 100644
index 8a50cc5..0000000
--- a/test/trace_processor/process_parent_pid.sql
+++ /dev/null
@@ -1,7 +0,0 @@
-SELECT
-  child.pid as child_pid,
-  parent.pid as parent_pid
-FROM process as child
-INNER JOIN process as parent
-ON child.parent_upid = parent.upid
-ORDER BY child_pid
diff --git a/test/trace_processor/process_parent_pid_process_parent_pid_tracking_1.out b/test/trace_processor/process_parent_pid_process_parent_pid_tracking_1.out
deleted file mode 100644
index 31f525e..0000000
--- a/test/trace_processor/process_parent_pid_process_parent_pid_tracking_1.out
+++ /dev/null
@@ -1,3 +0,0 @@
-"child_pid","parent_pid"
-10,0
-20,10
diff --git a/test/trace_processor/process_parent_pid_process_parent_pid_tracking_2.out b/test/trace_processor/process_parent_pid_process_parent_pid_tracking_2.out
deleted file mode 100644
index 31f525e..0000000
--- a/test/trace_processor/process_parent_pid_process_parent_pid_tracking_2.out
+++ /dev/null
@@ -1,3 +0,0 @@
-"child_pid","parent_pid"
-10,0
-20,10
diff --git a/test/trace_processor/process_parent_pid_tracking_1.py b/test/trace_processor/process_parent_pid_tracking_1.py
deleted file mode 100644
index 08db19c..0000000
--- a/test/trace_processor/process_parent_pid_tracking_1.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/python
-# Copyright (C) 2019 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 synthetic trace tests a multi-threaded process which forks in one of the
-# non-main threads when the tgid for that thread is known.
-
-from os import sys, path
-
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-from synth_common import CLONE_THREAD
-import synth_common
-
-trace = synth_common.create_trace()
-
-# Create a multi-threaded process which will be forked below.
-trace.add_process_tree_packet(ts=1)
-trace.add_process(10, 0, "main_thread")
-trace.add_thread(11, 10, "worker_thread")
-
-# Fork off the new process from the worker thread.
-trace.add_ftrace_packet(0)
-trace.add_newtask(ts=15, tid=11, new_tid=20, new_comm='child', flags=0)
-
-print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_parent_pid_tracking_2.py b/test/trace_processor/process_parent_pid_tracking_2.py
deleted file mode 100644
index 1685d59..0000000
--- a/test/trace_processor/process_parent_pid_tracking_2.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/python
-# Copyright (C) 2019 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 synthetic trace tests a multi-threaded process which forks in one of the
-# non-main threads when the tgid for that thread is not known but resolved
-# later.
-
-from os import sys, path
-
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-from synth_common import CLONE_THREAD
-import synth_common
-
-trace = synth_common.create_trace()
-
-# Fork off the new process from the worker thread.
-trace.add_ftrace_packet(0)
-trace.add_newtask(ts=15, tid=11, new_tid=20, new_comm='child', flags=0)
-
-# Create a multi-threaded process which will be forked below.
-trace.add_process_tree_packet(ts=25)
-trace.add_process(10, 0, "main_thread")
-trace.add_thread(11, 10, "worker_thread")
-
-print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_track_slices.sql b/test/trace_processor/process_track_slices.sql
deleted file mode 100644
index b84557f..0000000
--- a/test/trace_processor/process_track_slices.sql
+++ /dev/null
@@ -1,9 +0,0 @@
-SELECT
-  ts,
-  dur,
-  pid,
-  slice.name as slice_name,
-  process_track.name as track_name
-FROM slice
-INNER JOIN process_track ON slice.ref = process_track.id
-INNER JOIN process USING (upid)
diff --git a/test/trace_processor/process_track_slices_android_async_slice.out b/test/trace_processor/process_track_slices_android_async_slice.out
deleted file mode 100644
index a30a8f0..0000000
--- a/test/trace_processor/process_track_slices_android_async_slice.out
+++ /dev/null
@@ -1,2 +0,0 @@
-"ts","dur","pid","slice_name","track_name"
-74289018336,373584672,1204,"launching: com.android.chrome","launching: com.android.chrome"
diff --git a/test/trace_processor/process_tracking.out b/test/trace_processor/process_tracking.out
index ab7ff90..6c05815 100644
--- a/test/trace_processor/process_tracking.out
+++ b/test/trace_processor/process_tracking.out
@@ -7,8 +7,8 @@
 22,20,"process_2","p2-t2"
 30,30,"process_3","p3-t0"
 31,30,"process_3","p3-t1"
-31,40,"process_4","p4-t1"
 32,30,"process_3","p3-t2"
 33,30,"process_3","p3-t3"
 34,30,"process_3","p3-t4"
 40,40,"process_4","p4-t0"
+31,40,"process_4","p4-t1"
diff --git a/test/trace_processor/process_tracking.sql b/test/trace_processor/process_tracking.sql
index 922cb7f..3c2bbe6 100644
--- a/test/trace_processor/process_tracking.sql
+++ b/test/trace_processor/process_tracking.sql
@@ -2,4 +2,4 @@
 from thread
 left join process using(upid)
 where tid > 0
-order by tid
+order by utid
\ No newline at end of file
diff --git a/test/trace_processor/process_tracking_exec.py b/test/trace_processor/process_tracking_exec.py
deleted file mode 100644
index 672ce79..0000000
--- a/test/trace_processor/process_tracking_exec.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/python
-# Copyright (C) 2019 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 synthetic trace tests a process which forks and then execs.
-
-from os import sys, path
-
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-from synth_common import CLONE_THREAD
-import synth_common
-
-trace = synth_common.create_trace()
-
-# Create a parent process which  will be forked below.
-trace.add_process_tree_packet(ts=1)
-trace.add_process(10, 0, "parent")
-
-# Fork off the new process and then kill it 5ns later.
-trace.add_ftrace_packet(0)
-trace.add_newtask(ts=15, tid=10, new_tid=11, new_comm='child', flags=0)
-trace.add_sched(ts=16, prev_pid=10, next_pid=11, next_comm='child')
-
-# Create a parent process which  will be forked below.
-trace.add_process_tree_packet(ts=20)
-trace.add_process(11, 0, "child_process")
-
-trace.add_ftrace_packet(0)
-trace.add_rename(
-    ts=25, tid=11, old_comm='child', new_comm='true_name', oom_score_adj=1000)
-
-# Create a parent process which  will be forked below.
-trace.add_process_tree_packet(ts=30)
-trace.add_process(11, 10, "true_process_name")
-
-print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_tracking_process_tracking_exec.out b/test/trace_processor/process_tracking_process_tracking_exec.out
deleted file mode 100644
index 6890b54..0000000
--- a/test/trace_processor/process_tracking_process_tracking_exec.out
+++ /dev/null
@@ -1,3 +0,0 @@
-"tid","pid","pname","tname"
-10,10,"parent","parent"
-11,11,"true_process_name","true_name"
diff --git a/test/trace_processor/process_tracking_process_tracking_short_lived_1.out b/test/trace_processor/process_tracking_process_tracking_short_lived_1.out
deleted file mode 100644
index 3719aaa..0000000
--- a/test/trace_processor/process_tracking_process_tracking_short_lived_1.out
+++ /dev/null
@@ -1,3 +0,0 @@
-"tid","pid","pname","tname"
-10,10,"parent","parent"
-11,11,"child","child"
diff --git a/test/trace_processor/process_tracking_process_tracking_short_lived_2.out b/test/trace_processor/process_tracking_process_tracking_short_lived_2.out
deleted file mode 100644
index 6f128de..0000000
--- a/test/trace_processor/process_tracking_process_tracking_short_lived_2.out
+++ /dev/null
@@ -1,3 +0,0 @@
-"tid","pid","pname","tname"
-10,10,"parent","parent"
-11,11,"true_name","true_name"
diff --git a/test/trace_processor/process_tracking_short_lived_1.py b/test/trace_processor/process_tracking_short_lived_1.py
deleted file mode 100644
index a147a53..0000000
--- a/test/trace_processor/process_tracking_short_lived_1.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/python
-# Copyright (C) 2019 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 synthetic trace tests a short lived process which is forked and dies
-# before the /proc scraper is able to find its true name.
-
-from os import sys, path
-
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-from synth_common import CLONE_THREAD
-import synth_common
-
-trace = synth_common.create_trace()
-
-# Create a parent process which  will be forked below.
-trace.add_process_tree_packet(ts=1)
-trace.add_process(10, 0, "parent")
-
-# Fork off the new process and then kill it 5ns later.
-trace.add_ftrace_packet(0)
-trace.add_newtask(ts=15, tid=10, new_tid=11, new_comm='child', flags=0)
-trace.add_sched(ts=16, prev_pid=10, next_pid=11, next_comm='child')
-trace.add_process_free(ts=20, tid=11, comm='child', prio=0)
-
-print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/process_tracking_short_lived_2.py b/test/trace_processor/process_tracking_short_lived_2.py
deleted file mode 100644
index 957b8c4..0000000
--- a/test/trace_processor/process_tracking_short_lived_2.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/python
-# Copyright (C) 2019 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 synthetic trace tests a short lived process which is forked, performs
-# a rename (to simulate an exec) then dies before the /proc scraper finds the
-# real process name
-
-from os import sys, path
-
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-from synth_common import CLONE_THREAD
-import synth_common
-
-trace = synth_common.create_trace()
-
-# Create a parent process which  will be forked below.
-trace.add_process_tree_packet(ts=1)
-trace.add_process(10, 0, "parent")
-
-# Fork off the new process and then kill it 5ns later.
-trace.add_ftrace_packet(0)
-trace.add_newtask(ts=15, tid=10, new_tid=11, new_comm='child', flags=0)
-trace.add_sched(ts=16, prev_pid=10, next_pid=11, next_comm='child')
-trace.add_rename(
-    ts=17, tid=11, old_comm='child', new_comm='true_name', oom_score_adj=1000)
-
-print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/sched_slices.sql b/test/trace_processor/sched_slices.sql
deleted file mode 100644
index 1e808d5..0000000
--- a/test/trace_processor/sched_slices.sql
+++ /dev/null
@@ -1,3 +0,0 @@
-SELECT ts, cpu, dur, ts_end, end_state, priority, tid, name
-FROM sched JOIN thread ON sched.utid == thread.utid
-ORDER BY cpu, sched.ts ASC;
diff --git a/test/trace_processor/sched_slices_sched_switch_compact.out b/test/trace_processor/sched_slices_sched_switch_compact.out
deleted file mode 100644
index c570299..0000000
--- a/test/trace_processor/sched_slices_sched_switch_compact.out
+++ /dev/null
@@ -1,77 +0,0 @@
-"ts","cpu","dur","ts_end","end_state","priority","tid","name"
-807082865097350,0,6629324,807082871726674,"R",120,0,"swapper/1"
-807082871726674,0,38229,807082871764903,"S",120,7,"rcu_preempt"
-807082871764903,0,40521,807082871805424,"S",120,45,"rcuop/4"
-807082871805424,0,29896,807082871835320,"S",120,7,"rcu_preempt"
-807082871835320,0,6778282,807082878613602,"R",120,0,"swapper/1"
-807082878613602,0,35781,807082878649383,"S",120,7,"rcu_preempt"
-807082878649383,0,216562,807082878865945,"S",120,45,"rcuop/4"
-807082878865945,0,135625,807082879001570,"D",120,22367,"kworker/u16:9"
-807082879001570,0,57917,807082879059487,"R",120,0,"swapper/1"
-807082879059487,0,120052,807082879179539,"S",120,22367,"kworker/u16:9"
-807082879179539,0,68398757,807082947578296,"R",120,0,"swapper/1"
-807082947578296,0,49271,807082947627567,"S",120,28673,"kworker/0:0"
-807082947627567,0,11515782,807082959143349,"R",120,0,"swapper/1"
-807082959143349,0,119167,807082959262516,"S",120,6,"ksoftirqd/0"
-807082959262516,0,126094,807082959388610,"S",120,22367,"kworker/u16:9"
-807082959388610,0,71435840,807083030824450,"R",120,0,"swapper/1"
-807083030824450,0,1662865,807083032487315,"S",120,29206,"traced"
-807083032487315,0,593281,807083033080596,"R",120,29207,"traced_probes"
-807082863108704,1,42240,807082863150944,"R",120,0,"swapper/1"
-807082863150944,1,42760,807082863193704,"S",49,4454,"irq/80-1436400."
-807082863193704,1,1931823,807082865125527,"R",120,0,"swapper/1"
-807082865125527,1,159532,807082865285059,"D",49,4458,"irq/81-114a000."
-807082865285059,1,34375,807082865319434,"R",120,0,"swapper/1"
-807082865319434,1,38333,807082865357767,"S",49,4458,"irq/81-114a000."
-807082865357767,1,82176415,807082947534182,"R",120,0,"swapper/1"
-807082947534182,1,56875,807082947591057,"S",120,28610,"kworker/1:0"
-807082947591057,1,15142918,807082962733975,"R",120,0,"swapper/1"
-807082962733975,1,77448,807082962811423,"S",120,18,"ksoftirqd/1"
-807082962811423,1,5196563,807082968007986,"R",120,0,"swapper/1"
-807082968007986,1,268437,807082968276423,"S",98,4009,"bluetooth@1.0-s"
-807082968276423,1,134688,807082968411111,"R",120,0,"swapper/1"
-807082968411111,1,116718,807082968527829,"S",120,22367,"kworker/u16:9"
-807082968527829,1,62510684,807083031038513,"R",120,0,"swapper/1"
-807083031038513,1,840416,807083031878929,"R+",120,22367,"kworker/u16:9"
-807083031878929,1,147032,807083032025961,"S",120,10,"rcuop/0"
-807083032025961,1,54218,807083032080179,"S",120,7,"rcu_preempt"
-807083032080179,1,455834,807083032536013,"D",120,22367,"kworker/u16:9"
-807083032536013,1,162604,807083032698617,"R",120,0,"swapper/1"
-807083032698617,1,276146,807083032974763,"D",120,22367,"kworker/u16:9"
-807083032974763,1,62396,807083033037159,"R",120,0,"swapper/1"
-807083033037159,1,43437,807083033080596,"S",120,22367,"kworker/u16:9"
-807083033080596,1,0,807083033080596,"R",120,0,"swapper/1"
-807082865061361,2,399583,807082865460944,"D",120,22367,"kworker/u16:9"
-807082865460944,2,46771,807082865507715,"R",120,0,"swapper/1"
-807082865507715,2,30312,807082865538027,"S",120,22367,"kworker/u16:9"
-807082865538027,2,2811459,807082868349486,"R",120,0,"swapper/1"
-807082868349486,2,60417,807082868409903,"S",120,8,"rcu_sched"
-807082868409903,2,31302,807082868441205,"S",120,46,"rcuos/4"
-807082868441205,2,78727456,807082947168661,"R",120,0,"swapper/1"
-807082947168661,2,296771,807082947465432,"S",49,627,"sugov:0"
-807082947465432,2,30989,807082947496421,"S",120,28887,"kworker/2:2"
-807082947496421,2,96927,807082947593348,"S",120,45,"rcuop/4"
-807082947593348,2,692344,807082948285692,"D",120,22367,"kworker/u16:9"
-807082948285692,2,363438,807082948649130,"R",120,0,"swapper/1"
-807082948649130,2,185052,807082948834182,"D",120,22367,"kworker/u16:9"
-807082948834182,2,357239,807082949191421,"R",120,0,"swapper/1"
-807082949191421,2,55677,807082949247098,"S",120,22367,"kworker/u16:9"
-807082949247098,2,83833498,807083033080596,"R",120,0,"swapper/1"
-807082947555119,3,37083,807082947592202,"R",120,0,"swapper/1"
-807082947592202,3,38177,807082947630379,"S",120,7,"rcu_preempt"
-807082947630379,3,4172813,807082951803192,"R",120,0,"swapper/1"
-807082951803192,3,83698,807082951886890,"S",120,7,"rcu_preempt"
-807082951886890,3,40000,807082951926890,"S",120,45,"rcuop/4"
-807082951926890,3,81153706,807083033080596,"R",120,0,"swapper/1"
-807082862976152,4,14792,807082862990944,"S",120,29207,"traced_probes"
-807082862990944,4,83901102,807082946892046,"R",120,0,"swapper/1"
-807082946892046,4,327500,807082947219546,"S",120,29207,"traced_probes"
-807082947219546,4,15052,807082947234598,"R",120,0,"swapper/1"
-807082947234598,4,68698,807082947303296,"S",120,42,"ksoftirqd/4"
-807082947303296,4,28958,807082947332254,"S",120,21092,"kworker/4:1"
-807082947332254,4,83363707,807083030695961,"R",120,0,"swapper/1"
-807083030695961,4,104895,807083030800856,"S",120,42,"ksoftirqd/4"
-807083030800856,4,2279740,807083033080596,"R",120,0,"swapper/1"
-807082952627307,7,1534375,807082954161682,"R",120,0,"swapper/1"
-807082954161682,7,43490,807082954205172,"S",49,628,"sugov:4"
-807082954205172,7,78875424,807083033080596,"R",120,0,"swapper/1"
diff --git a/test/trace_processor/sched_slices_sched_switch_original.out b/test/trace_processor/sched_slices_sched_switch_original.out
deleted file mode 100644
index fe6f0c5..0000000
--- a/test/trace_processor/sched_slices_sched_switch_original.out
+++ /dev/null
@@ -1,83 +0,0 @@
-"ts","cpu","dur","ts_end","end_state","priority","tid","name"
-807082865062402,0,34948,807082865097350,"S",120,7,"rcu_preempt"
-807082865097350,0,6629324,807082871726674,"R",120,0,"swapper/1"
-807082871726674,0,38229,807082871764903,"S",120,7,"rcu_preempt"
-807082871764903,0,40521,807082871805424,"S",120,45,"rcuop/4"
-807082871805424,0,29896,807082871835320,"S",120,7,"rcu_preempt"
-807082871835320,0,6778282,807082878613602,"R",120,0,"swapper/1"
-807082878613602,0,35781,807082878649383,"S",120,7,"rcu_preempt"
-807082878649383,0,216562,807082878865945,"S",120,45,"rcuop/4"
-807082878865945,0,135625,807082879001570,"D",120,22367,"kworker/u16:9"
-807082879001570,0,57917,807082879059487,"R",120,0,"swapper/1"
-807082879059487,0,120052,807082879179539,"S",120,22367,"kworker/u16:9"
-807082879179539,0,68398757,807082947578296,"R",120,0,"swapper/1"
-807082947578296,0,49271,807082947627567,"S",120,28673,"kworker/0:0"
-807082947627567,0,11515782,807082959143349,"R",120,0,"swapper/1"
-807082959143349,0,119167,807082959262516,"S",120,6,"ksoftirqd/0"
-807082959262516,0,126094,807082959388610,"S",120,22367,"kworker/u16:9"
-807082959388610,0,71435840,807083030824450,"R",120,0,"swapper/1"
-807083030824450,0,1662865,807083032487315,"S",120,29206,"traced"
-807083032487315,0,593281,807083033080596,"R",120,29207,"traced_probes"
-807082862950996,1,157708,807082863108704,"D",49,4454,"irq/80-1436400."
-807082863108704,1,42240,807082863150944,"R",120,0,"swapper/1"
-807082863150944,1,42760,807082863193704,"S",49,4454,"irq/80-1436400."
-807082863193704,1,1931823,807082865125527,"R",120,0,"swapper/1"
-807082865125527,1,159532,807082865285059,"D",49,4458,"irq/81-114a000."
-807082865285059,1,34375,807082865319434,"R",120,0,"swapper/1"
-807082865319434,1,38333,807082865357767,"S",49,4458,"irq/81-114a000."
-807082865357767,1,82176415,807082947534182,"R",120,0,"swapper/1"
-807082947534182,1,56875,807082947591057,"S",120,28610,"kworker/1:0"
-807082947591057,1,15142918,807082962733975,"R",120,0,"swapper/1"
-807082962733975,1,77448,807082962811423,"S",120,18,"ksoftirqd/1"
-807082962811423,1,5196563,807082968007986,"R",120,0,"swapper/1"
-807082968007986,1,268437,807082968276423,"S",98,4009,"bluetooth@1.0-s"
-807082968276423,1,134688,807082968411111,"R",120,0,"swapper/1"
-807082968411111,1,116718,807082968527829,"S",120,22367,"kworker/u16:9"
-807082968527829,1,62510684,807083031038513,"R",120,0,"swapper/1"
-807083031038513,1,840416,807083031878929,"R+",120,22367,"kworker/u16:9"
-807083031878929,1,147032,807083032025961,"S",120,10,"rcuop/0"
-807083032025961,1,54218,807083032080179,"S",120,7,"rcu_preempt"
-807083032080179,1,455834,807083032536013,"D",120,22367,"kworker/u16:9"
-807083032536013,1,162604,807083032698617,"R",120,0,"swapper/1"
-807083032698617,1,276146,807083032974763,"D",120,22367,"kworker/u16:9"
-807083032974763,1,62396,807083033037159,"R",120,0,"swapper/1"
-807083033037159,1,43437,807083033080596,"S",120,22367,"kworker/u16:9"
-807083033080596,1,0,807083033080596,"R",120,0,"swapper/1"
-807082862645371,2,2415990,807082865061361,"R",120,0,"swapper/1"
-807082865061361,2,399583,807082865460944,"D",120,22367,"kworker/u16:9"
-807082865460944,2,46771,807082865507715,"R",120,0,"swapper/1"
-807082865507715,2,30312,807082865538027,"S",120,22367,"kworker/u16:9"
-807082865538027,2,2811459,807082868349486,"R",120,0,"swapper/1"
-807082868349486,2,60417,807082868409903,"S",120,8,"rcu_sched"
-807082868409903,2,31302,807082868441205,"S",120,46,"rcuos/4"
-807082868441205,2,78727456,807082947168661,"R",120,0,"swapper/1"
-807082947168661,2,296771,807082947465432,"S",49,627,"sugov:0"
-807082947465432,2,30989,807082947496421,"S",120,28887,"kworker/2:2"
-807082947496421,2,96927,807082947593348,"S",120,45,"rcuop/4"
-807082947593348,2,692344,807082948285692,"D",120,22367,"kworker/u16:9"
-807082948285692,2,363438,807082948649130,"R",120,0,"swapper/1"
-807082948649130,2,185052,807082948834182,"D",120,22367,"kworker/u16:9"
-807082948834182,2,357239,807082949191421,"R",120,0,"swapper/1"
-807082949191421,2,55677,807082949247098,"S",120,22367,"kworker/u16:9"
-807082949247098,2,83833498,807083033080596,"R",120,0,"swapper/1"
-807082947493504,3,61615,807082947555119,"S",120,28905,"kworker/3:0"
-807082947555119,3,37083,807082947592202,"R",120,0,"swapper/1"
-807082947592202,3,38177,807082947630379,"S",120,7,"rcu_preempt"
-807082947630379,3,4172813,807082951803192,"R",120,0,"swapper/1"
-807082951803192,3,83698,807082951886890,"S",120,7,"rcu_preempt"
-807082951886890,3,40000,807082951926890,"S",120,45,"rcuop/4"
-807082951926890,3,81153706,807083033080596,"R",120,0,"swapper/1"
-807082862918652,4,57500,807082862976152,"S",120,29206,"traced"
-807082862976152,4,14792,807082862990944,"S",120,29207,"traced_probes"
-807082862990944,4,83901102,807082946892046,"R",120,0,"swapper/1"
-807082946892046,4,327500,807082947219546,"S",120,29207,"traced_probes"
-807082947219546,4,15052,807082947234598,"R",120,0,"swapper/1"
-807082947234598,4,68698,807082947303296,"S",120,42,"ksoftirqd/4"
-807082947303296,4,28958,807082947332254,"S",120,21092,"kworker/4:1"
-807082947332254,4,83363707,807083030695961,"R",120,0,"swapper/1"
-807083030695961,4,104895,807083030800856,"S",120,42,"ksoftirqd/4"
-807083030800856,4,2279740,807083033080596,"R",120,0,"swapper/1"
-807082952486057,7,141250,807082952627307,"D",49,628,"sugov:4"
-807082952627307,7,1534375,807082954161682,"R",120,0,"swapper/1"
-807082954161682,7,43490,807082954205172,"S",49,628,"sugov:4"
-807082954205172,7,78875424,807083033080596,"R",120,0,"swapper/1"
diff --git a/test/trace_processor/sched_waking_instants.sql b/test/trace_processor/sched_waking_instants.sql
deleted file mode 100644
index 1fe4a76..0000000
--- a/test/trace_processor/sched_waking_instants.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT ts, instants.name, thread.name, thread.tid FROM instants JOIN thread ON instants.ref == thread.utid WHERE instants.name == "sched_waking" ORDER BY ts ASC
diff --git a/test/trace_processor/sched_waking_instants_compact_sched.out b/test/trace_processor/sched_waking_instants_compact_sched.out
deleted file mode 100644
index 201d48b..0000000
--- a/test/trace_processor/sched_waking_instants_compact_sched.out
+++ /dev/null
@@ -1,82 +0,0 @@
-"ts","name","name","tid"
-250978439491994,"sched_waking","rcu_sched",8
-250978441664547,"sched_waking","ksoftirqd/1",18
-250978441702515,"sched_waking","kworker/u16:18",17473
-250978444958245,"sched_waking","rcuop/0",10
-250978444974443,"sched_waking","rcuop/1",21
-250978444984234,"sched_waking","rcu_preempt",7
-250978445783141,"sched_waking","rcu_sched",8
-250978451590173,"sched_waking","rcu_preempt",7
-250978451591891,"sched_waking","rcu_sched",8
-250978451609131,"sched_waking","kworker/u16:18",17473
-250978451646579,"sched_waking","rcuos/0",11
-250978451716891,"sched_waking","rcuos/1",22
-250978452047048,"sched_waking","kworker/u16:18",17473
-250978458337725,"sched_waking","sugov:0",625
-250978458362100,"sched_waking","rcu_preempt",7
-250978458398455,"sched_waking","rcuop/0",10
-250978458419496,"sched_waking","rcuop/1",21
-250978459118038,"sched_waking","sugov:0",625
-250978465172309,"sched_waking","ksoftirqd/3",34
-250978465266789,"sched_waking","kworker/u16:18",17473
-250978593466697,"sched_waking","kworker/2:0",17438
-250978593734510,"sched_waking","kworker/u16:18",17473
-250978595521125,"sched_waking","kworker/2:3",17754
-250978595696645,"sched_waking","kworker/2:0",17438
-250978596068468,"sched_waking","kworker/2:3",17754
-250978596565656,"sched_waking","kworker/2:0",17438
-250978600598417,"sched_waking","kworker/2:0",17438
-250978600639042,"sched_waking","ksoftirqd/0",6
-250978604651907,"sched_waking","ksoftirqd/0",6
-250978604739980,"sched_waking","kworker/2:0",17438
-250978605185448,"sched_waking","ksoftirqd/2",26
-250978605260240,"sched_waking","kworker/u16:18",17473
-250978608903886,"sched_waking","kworker/2:0",17438
-250978608942220,"sched_waking","ksoftirqd/0",6
-250978612887272,"sched_waking","ksoftirqd/0",6
-250978612971283,"sched_waking","kworker/2:0",17438
-250978616876595,"sched_waking","kworker/2:0",17438
-250978616921700,"sched_waking","ksoftirqd/0",6
-250978617016804,"sched_waking","kworker/u16:18",17473
-250978620859669,"sched_waking","ksoftirqd/0",6
-250978620939148,"sched_waking","kworker/2:0",17438
-250978624836805,"sched_waking","kworker/2:0",17438
-250978624875398,"sched_waking","ksoftirqd/0",6
-250978624978003,"sched_waking","kworker/u16:18",17473
-250978628278107,"sched_waking","logd.klogd",651
-250978629289722,"sched_waking","rcuop/2",29
-250978629405763,"sched_waking","rcu_preempt",7
-250978635024462,"sched_waking","rcu_preempt",7
-250978635060191,"sched_waking","kworker/u16:18",17473
-250978635219514,"sched_waking","rcuop/2",29
-250978683441081,"sched_waking","kworker/2:0",17438
-250978683732331,"sched_waking","kworker/u16:18",17473
-250978685694259,"sched_waking","kworker/u16:18",17473
-250978740127441,"sched_waking","kworker/2:0",17438
-250978740425410,"sched_waking","kworker/u16:18",17473
-250978743210358,"sched_waking","kworker/u16:18",17473
-250978744945567,"sched_waking","logd.klogd",651
-250978746028431,"sched_waking","rcuop/2",29
-250978746173171,"sched_waking","rcu_preempt",7
-250978751622494,"sched_waking","rcu_preempt",7
-250978751661348,"sched_waking","kworker/u16:18",17473
-250978751792859,"sched_waking","rcuop/2",29
-250978751971817,"sched_waking","rcu_preempt",7
-250978758784578,"sched_waking","rcu_preempt",7
-250978758873745,"sched_waking","rcuop/2",29
-250978805144375,"sched_waking","traced_probes",17772
-250978806359896,"sched_waking","kworker/5:1",17667
-250978806428646,"sched_waking","kworker/u16:18",17473
-250978808058698,"sched_waking","rcuop/0",10
-250978808519271,"sched_waking","rcu_preempt",7
-250978815488490,"sched_waking","rcu_preempt",7
-250978815535678,"sched_waking","kworker/u16:18",17473
-250978815675782,"sched_waking","rcuop/0",10
-250978815738022,"sched_waking","rcuop/1",21
-250978860203182,"sched_waking","kworker/u16:18",17473
-250978880151205,"sched_waking","kworker/2:0",17438
-250978880432143,"sched_waking","kworker/u16:18",17473
-250978884120216,"sched_waking","traced",17771
-250978885260685,"sched_waking","rcuop/0",10
-250978885784018,"sched_waking","rcu_preempt",7
-250978885786674,"sched_waking","traced_probes",17772
diff --git a/test/trace_processor/sched_waking_raw.sql b/test/trace_processor/sched_waking_raw.sql
deleted file mode 100644
index 259e2fe..0000000
--- a/test/trace_processor/sched_waking_raw.sql
+++ /dev/null
@@ -1 +0,0 @@
-SELECT ts, name, cpu, key, int_value, string_value FROM raw JOIN args ON raw.arg_set_id == args.arg_set_id WHERE name == "sched_waking" ORDER BY cpu ASC, ts ASC;
diff --git a/test/trace_processor/sched_waking_raw_compact_sched.out b/test/trace_processor/sched_waking_raw_compact_sched.out
deleted file mode 100644
index 7067a25..0000000
--- a/test/trace_processor/sched_waking_raw_compact_sched.out
+++ /dev/null
@@ -1,406 +0,0 @@
-"ts","name","cpu","key","int_value","string_value"
-250978451591891,"sched_waking",0,"comm","[NULL]","rcu_sched"
-250978451591891,"sched_waking",0,"pid",8,"[NULL]"
-250978451591891,"sched_waking",0,"prio",120,"[NULL]"
-250978451591891,"sched_waking",0,"success",1,"[NULL]"
-250978451591891,"sched_waking",0,"target_cpu",0,"[NULL]"
-250978451609131,"sched_waking",0,"comm","[NULL]","kworker/u16:18"
-250978451609131,"sched_waking",0,"pid",17473,"[NULL]"
-250978451609131,"sched_waking",0,"prio",120,"[NULL]"
-250978451609131,"sched_waking",0,"success",1,"[NULL]"
-250978451609131,"sched_waking",0,"target_cpu",0,"[NULL]"
-250978596565656,"sched_waking",0,"comm","[NULL]","kworker/2:0"
-250978596565656,"sched_waking",0,"pid",17438,"[NULL]"
-250978596565656,"sched_waking",0,"prio",120,"[NULL]"
-250978596565656,"sched_waking",0,"success",1,"[NULL]"
-250978596565656,"sched_waking",0,"target_cpu",2,"[NULL]"
-250978600598417,"sched_waking",0,"comm","[NULL]","kworker/2:0"
-250978600598417,"sched_waking",0,"pid",17438,"[NULL]"
-250978600598417,"sched_waking",0,"prio",120,"[NULL]"
-250978600598417,"sched_waking",0,"success",1,"[NULL]"
-250978600598417,"sched_waking",0,"target_cpu",2,"[NULL]"
-250978600639042,"sched_waking",0,"comm","[NULL]","ksoftirqd/0"
-250978600639042,"sched_waking",0,"pid",6,"[NULL]"
-250978600639042,"sched_waking",0,"prio",120,"[NULL]"
-250978600639042,"sched_waking",0,"success",1,"[NULL]"
-250978600639042,"sched_waking",0,"target_cpu",0,"[NULL]"
-250978604651907,"sched_waking",0,"comm","[NULL]","ksoftirqd/0"
-250978604651907,"sched_waking",0,"pid",6,"[NULL]"
-250978604651907,"sched_waking",0,"prio",120,"[NULL]"
-250978604651907,"sched_waking",0,"success",1,"[NULL]"
-250978604651907,"sched_waking",0,"target_cpu",0,"[NULL]"
-250978604739980,"sched_waking",0,"comm","[NULL]","kworker/2:0"
-250978604739980,"sched_waking",0,"pid",17438,"[NULL]"
-250978604739980,"sched_waking",0,"prio",120,"[NULL]"
-250978604739980,"sched_waking",0,"success",1,"[NULL]"
-250978604739980,"sched_waking",0,"target_cpu",2,"[NULL]"
-250978608903886,"sched_waking",0,"comm","[NULL]","kworker/2:0"
-250978608903886,"sched_waking",0,"pid",17438,"[NULL]"
-250978608903886,"sched_waking",0,"prio",120,"[NULL]"
-250978608903886,"sched_waking",0,"success",1,"[NULL]"
-250978608903886,"sched_waking",0,"target_cpu",2,"[NULL]"
-250978608942220,"sched_waking",0,"comm","[NULL]","ksoftirqd/0"
-250978608942220,"sched_waking",0,"pid",6,"[NULL]"
-250978608942220,"sched_waking",0,"prio",120,"[NULL]"
-250978608942220,"sched_waking",0,"success",1,"[NULL]"
-250978608942220,"sched_waking",0,"target_cpu",0,"[NULL]"
-250978612887272,"sched_waking",0,"comm","[NULL]","ksoftirqd/0"
-250978612887272,"sched_waking",0,"pid",6,"[NULL]"
-250978612887272,"sched_waking",0,"prio",120,"[NULL]"
-250978612887272,"sched_waking",0,"success",1,"[NULL]"
-250978612887272,"sched_waking",0,"target_cpu",0,"[NULL]"
-250978612971283,"sched_waking",0,"comm","[NULL]","kworker/2:0"
-250978612971283,"sched_waking",0,"pid",17438,"[NULL]"
-250978612971283,"sched_waking",0,"prio",120,"[NULL]"
-250978612971283,"sched_waking",0,"success",1,"[NULL]"
-250978612971283,"sched_waking",0,"target_cpu",2,"[NULL]"
-250978616876595,"sched_waking",0,"comm","[NULL]","kworker/2:0"
-250978616876595,"sched_waking",0,"pid",17438,"[NULL]"
-250978616876595,"sched_waking",0,"prio",120,"[NULL]"
-250978616876595,"sched_waking",0,"success",1,"[NULL]"
-250978616876595,"sched_waking",0,"target_cpu",2,"[NULL]"
-250978616921700,"sched_waking",0,"comm","[NULL]","ksoftirqd/0"
-250978616921700,"sched_waking",0,"pid",6,"[NULL]"
-250978616921700,"sched_waking",0,"prio",120,"[NULL]"
-250978616921700,"sched_waking",0,"success",1,"[NULL]"
-250978616921700,"sched_waking",0,"target_cpu",0,"[NULL]"
-250978617016804,"sched_waking",0,"comm","[NULL]","kworker/u16:18"
-250978617016804,"sched_waking",0,"pid",17473,"[NULL]"
-250978617016804,"sched_waking",0,"prio",120,"[NULL]"
-250978617016804,"sched_waking",0,"success",1,"[NULL]"
-250978617016804,"sched_waking",0,"target_cpu",2,"[NULL]"
-250978620859669,"sched_waking",0,"comm","[NULL]","ksoftirqd/0"
-250978620859669,"sched_waking",0,"pid",6,"[NULL]"
-250978620859669,"sched_waking",0,"prio",120,"[NULL]"
-250978620859669,"sched_waking",0,"success",1,"[NULL]"
-250978620859669,"sched_waking",0,"target_cpu",0,"[NULL]"
-250978620939148,"sched_waking",0,"comm","[NULL]","kworker/2:0"
-250978620939148,"sched_waking",0,"pid",17438,"[NULL]"
-250978620939148,"sched_waking",0,"prio",120,"[NULL]"
-250978620939148,"sched_waking",0,"success",1,"[NULL]"
-250978620939148,"sched_waking",0,"target_cpu",2,"[NULL]"
-250978624836805,"sched_waking",0,"comm","[NULL]","kworker/2:0"
-250978624836805,"sched_waking",0,"pid",17438,"[NULL]"
-250978624836805,"sched_waking",0,"prio",120,"[NULL]"
-250978624836805,"sched_waking",0,"success",1,"[NULL]"
-250978624836805,"sched_waking",0,"target_cpu",2,"[NULL]"
-250978624875398,"sched_waking",0,"comm","[NULL]","ksoftirqd/0"
-250978624875398,"sched_waking",0,"pid",6,"[NULL]"
-250978624875398,"sched_waking",0,"prio",120,"[NULL]"
-250978624875398,"sched_waking",0,"success",1,"[NULL]"
-250978624875398,"sched_waking",0,"target_cpu",0,"[NULL]"
-250978624978003,"sched_waking",0,"comm","[NULL]","kworker/u16:18"
-250978624978003,"sched_waking",0,"pid",17473,"[NULL]"
-250978624978003,"sched_waking",0,"prio",120,"[NULL]"
-250978624978003,"sched_waking",0,"success",1,"[NULL]"
-250978624978003,"sched_waking",0,"target_cpu",0,"[NULL]"
-250978441664547,"sched_waking",1,"comm","[NULL]","ksoftirqd/1"
-250978441664547,"sched_waking",1,"pid",18,"[NULL]"
-250978441664547,"sched_waking",1,"prio",120,"[NULL]"
-250978441664547,"sched_waking",1,"success",1,"[NULL]"
-250978441664547,"sched_waking",1,"target_cpu",1,"[NULL]"
-250978441702515,"sched_waking",1,"comm","[NULL]","kworker/u16:18"
-250978441702515,"sched_waking",1,"pid",17473,"[NULL]"
-250978441702515,"sched_waking",1,"prio",120,"[NULL]"
-250978441702515,"sched_waking",1,"success",1,"[NULL]"
-250978441702515,"sched_waking",1,"target_cpu",2,"[NULL]"
-250978805144375,"sched_waking",1,"comm","[NULL]","traced_probes"
-250978805144375,"sched_waking",1,"pid",17772,"[NULL]"
-250978805144375,"sched_waking",1,"prio",120,"[NULL]"
-250978805144375,"sched_waking",1,"success",1,"[NULL]"
-250978805144375,"sched_waking",1,"target_cpu",1,"[NULL]"
-250978808058698,"sched_waking",1,"comm","[NULL]","rcuop/0"
-250978808058698,"sched_waking",1,"pid",10,"[NULL]"
-250978808058698,"sched_waking",1,"prio",120,"[NULL]"
-250978808058698,"sched_waking",1,"success",1,"[NULL]"
-250978808058698,"sched_waking",1,"target_cpu",2,"[NULL]"
-250978884120216,"sched_waking",1,"comm","[NULL]","traced"
-250978884120216,"sched_waking",1,"pid",17771,"[NULL]"
-250978884120216,"sched_waking",1,"prio",120,"[NULL]"
-250978884120216,"sched_waking",1,"success",1,"[NULL]"
-250978884120216,"sched_waking",1,"target_cpu",1,"[NULL]"
-250978885260685,"sched_waking",1,"comm","[NULL]","rcuop/0"
-250978885260685,"sched_waking",1,"pid",10,"[NULL]"
-250978885260685,"sched_waking",1,"prio",120,"[NULL]"
-250978885260685,"sched_waking",1,"success",1,"[NULL]"
-250978885260685,"sched_waking",1,"target_cpu",2,"[NULL]"
-250978885786674,"sched_waking",1,"comm","[NULL]","traced_probes"
-250978885786674,"sched_waking",1,"pid",17772,"[NULL]"
-250978885786674,"sched_waking",1,"prio",120,"[NULL]"
-250978885786674,"sched_waking",1,"success",1,"[NULL]"
-250978885786674,"sched_waking",1,"target_cpu",1,"[NULL]"
-250978444958245,"sched_waking",2,"comm","[NULL]","rcuop/0"
-250978444958245,"sched_waking",2,"pid",10,"[NULL]"
-250978444958245,"sched_waking",2,"prio",120,"[NULL]"
-250978444958245,"sched_waking",2,"success",1,"[NULL]"
-250978444958245,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978444974443,"sched_waking",2,"comm","[NULL]","rcuop/1"
-250978444974443,"sched_waking",2,"pid",21,"[NULL]"
-250978444974443,"sched_waking",2,"prio",120,"[NULL]"
-250978444974443,"sched_waking",2,"success",1,"[NULL]"
-250978444974443,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978444984234,"sched_waking",2,"comm","[NULL]","rcu_preempt"
-250978444984234,"sched_waking",2,"pid",7,"[NULL]"
-250978444984234,"sched_waking",2,"prio",120,"[NULL]"
-250978444984234,"sched_waking",2,"success",1,"[NULL]"
-250978444984234,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978451590173,"sched_waking",2,"comm","[NULL]","rcu_preempt"
-250978451590173,"sched_waking",2,"pid",7,"[NULL]"
-250978451590173,"sched_waking",2,"prio",120,"[NULL]"
-250978451590173,"sched_waking",2,"success",1,"[NULL]"
-250978451590173,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978451646579,"sched_waking",2,"comm","[NULL]","rcuos/0"
-250978451646579,"sched_waking",2,"pid",11,"[NULL]"
-250978451646579,"sched_waking",2,"prio",120,"[NULL]"
-250978451646579,"sched_waking",2,"success",1,"[NULL]"
-250978451646579,"sched_waking",2,"target_cpu",4,"[NULL]"
-250978451716891,"sched_waking",2,"comm","[NULL]","rcuos/1"
-250978451716891,"sched_waking",2,"pid",22,"[NULL]"
-250978451716891,"sched_waking",2,"prio",120,"[NULL]"
-250978451716891,"sched_waking",2,"success",1,"[NULL]"
-250978451716891,"sched_waking",2,"target_cpu",1,"[NULL]"
-250978452047048,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
-250978452047048,"sched_waking",2,"pid",17473,"[NULL]"
-250978452047048,"sched_waking",2,"prio",120,"[NULL]"
-250978452047048,"sched_waking",2,"success",1,"[NULL]"
-250978452047048,"sched_waking",2,"target_cpu",0,"[NULL]"
-250978458337725,"sched_waking",2,"comm","[NULL]","sugov:0"
-250978458337725,"sched_waking",2,"pid",625,"[NULL]"
-250978458337725,"sched_waking",2,"prio",49,"[NULL]"
-250978458337725,"sched_waking",2,"success",1,"[NULL]"
-250978458337725,"sched_waking",2,"target_cpu",3,"[NULL]"
-250978458362100,"sched_waking",2,"comm","[NULL]","rcu_preempt"
-250978458362100,"sched_waking",2,"pid",7,"[NULL]"
-250978458362100,"sched_waking",2,"prio",120,"[NULL]"
-250978458362100,"sched_waking",2,"success",1,"[NULL]"
-250978458362100,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978458398455,"sched_waking",2,"comm","[NULL]","rcuop/0"
-250978458398455,"sched_waking",2,"pid",10,"[NULL]"
-250978458398455,"sched_waking",2,"prio",120,"[NULL]"
-250978458398455,"sched_waking",2,"success",1,"[NULL]"
-250978458398455,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978458419496,"sched_waking",2,"comm","[NULL]","rcuop/1"
-250978458419496,"sched_waking",2,"pid",21,"[NULL]"
-250978458419496,"sched_waking",2,"prio",120,"[NULL]"
-250978458419496,"sched_waking",2,"success",1,"[NULL]"
-250978458419496,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978459118038,"sched_waking",2,"comm","[NULL]","sugov:0"
-250978459118038,"sched_waking",2,"pid",625,"[NULL]"
-250978459118038,"sched_waking",2,"prio",49,"[NULL]"
-250978459118038,"sched_waking",2,"success",1,"[NULL]"
-250978459118038,"sched_waking",2,"target_cpu",3,"[NULL]"
-250978593466697,"sched_waking",2,"comm","[NULL]","kworker/2:0"
-250978593466697,"sched_waking",2,"pid",17438,"[NULL]"
-250978593466697,"sched_waking",2,"prio",120,"[NULL]"
-250978593466697,"sched_waking",2,"success",1,"[NULL]"
-250978593466697,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978593734510,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
-250978593734510,"sched_waking",2,"pid",17473,"[NULL]"
-250978593734510,"sched_waking",2,"prio",120,"[NULL]"
-250978593734510,"sched_waking",2,"success",1,"[NULL]"
-250978593734510,"sched_waking",2,"target_cpu",3,"[NULL]"
-250978595521125,"sched_waking",2,"comm","[NULL]","kworker/2:3"
-250978595521125,"sched_waking",2,"pid",17754,"[NULL]"
-250978595521125,"sched_waking",2,"prio",120,"[NULL]"
-250978595521125,"sched_waking",2,"success",1,"[NULL]"
-250978595521125,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978595696645,"sched_waking",2,"comm","[NULL]","kworker/2:0"
-250978595696645,"sched_waking",2,"pid",17438,"[NULL]"
-250978595696645,"sched_waking",2,"prio",120,"[NULL]"
-250978595696645,"sched_waking",2,"success",1,"[NULL]"
-250978595696645,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978596068468,"sched_waking",2,"comm","[NULL]","kworker/2:3"
-250978596068468,"sched_waking",2,"pid",17754,"[NULL]"
-250978596068468,"sched_waking",2,"prio",120,"[NULL]"
-250978596068468,"sched_waking",2,"success",1,"[NULL]"
-250978596068468,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978605185448,"sched_waking",2,"comm","[NULL]","ksoftirqd/2"
-250978605185448,"sched_waking",2,"pid",26,"[NULL]"
-250978605185448,"sched_waking",2,"prio",120,"[NULL]"
-250978605185448,"sched_waking",2,"success",1,"[NULL]"
-250978605185448,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978605260240,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
-250978605260240,"sched_waking",2,"pid",17473,"[NULL]"
-250978605260240,"sched_waking",2,"prio",120,"[NULL]"
-250978605260240,"sched_waking",2,"success",1,"[NULL]"
-250978605260240,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978628278107,"sched_waking",2,"comm","[NULL]","logd.klogd"
-250978628278107,"sched_waking",2,"pid",651,"[NULL]"
-250978628278107,"sched_waking",2,"prio",130,"[NULL]"
-250978628278107,"sched_waking",2,"success",1,"[NULL]"
-250978628278107,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978629289722,"sched_waking",2,"comm","[NULL]","rcuop/2"
-250978629289722,"sched_waking",2,"pid",29,"[NULL]"
-250978629289722,"sched_waking",2,"prio",120,"[NULL]"
-250978629289722,"sched_waking",2,"success",1,"[NULL]"
-250978629289722,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978629405763,"sched_waking",2,"comm","[NULL]","rcu_preempt"
-250978629405763,"sched_waking",2,"pid",7,"[NULL]"
-250978629405763,"sched_waking",2,"prio",120,"[NULL]"
-250978629405763,"sched_waking",2,"success",1,"[NULL]"
-250978629405763,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978635024462,"sched_waking",2,"comm","[NULL]","rcu_preempt"
-250978635024462,"sched_waking",2,"pid",7,"[NULL]"
-250978635024462,"sched_waking",2,"prio",120,"[NULL]"
-250978635024462,"sched_waking",2,"success",1,"[NULL]"
-250978635024462,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978635060191,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
-250978635060191,"sched_waking",2,"pid",17473,"[NULL]"
-250978635060191,"sched_waking",2,"prio",120,"[NULL]"
-250978635060191,"sched_waking",2,"success",1,"[NULL]"
-250978635060191,"sched_waking",2,"target_cpu",0,"[NULL]"
-250978635219514,"sched_waking",2,"comm","[NULL]","rcuop/2"
-250978635219514,"sched_waking",2,"pid",29,"[NULL]"
-250978635219514,"sched_waking",2,"prio",120,"[NULL]"
-250978635219514,"sched_waking",2,"success",1,"[NULL]"
-250978635219514,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978683441081,"sched_waking",2,"comm","[NULL]","kworker/2:0"
-250978683441081,"sched_waking",2,"pid",17438,"[NULL]"
-250978683441081,"sched_waking",2,"prio",120,"[NULL]"
-250978683441081,"sched_waking",2,"success",1,"[NULL]"
-250978683441081,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978683732331,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
-250978683732331,"sched_waking",2,"pid",17473,"[NULL]"
-250978683732331,"sched_waking",2,"prio",120,"[NULL]"
-250978683732331,"sched_waking",2,"success",1,"[NULL]"
-250978683732331,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978685694259,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
-250978685694259,"sched_waking",2,"pid",17473,"[NULL]"
-250978685694259,"sched_waking",2,"prio",120,"[NULL]"
-250978685694259,"sched_waking",2,"success",1,"[NULL]"
-250978685694259,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978740127441,"sched_waking",2,"comm","[NULL]","kworker/2:0"
-250978740127441,"sched_waking",2,"pid",17438,"[NULL]"
-250978740127441,"sched_waking",2,"prio",120,"[NULL]"
-250978740127441,"sched_waking",2,"success",1,"[NULL]"
-250978740127441,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978740425410,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
-250978740425410,"sched_waking",2,"pid",17473,"[NULL]"
-250978740425410,"sched_waking",2,"prio",120,"[NULL]"
-250978740425410,"sched_waking",2,"success",1,"[NULL]"
-250978740425410,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978743210358,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
-250978743210358,"sched_waking",2,"pid",17473,"[NULL]"
-250978743210358,"sched_waking",2,"prio",120,"[NULL]"
-250978743210358,"sched_waking",2,"success",1,"[NULL]"
-250978743210358,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978744945567,"sched_waking",2,"comm","[NULL]","logd.klogd"
-250978744945567,"sched_waking",2,"pid",651,"[NULL]"
-250978744945567,"sched_waking",2,"prio",130,"[NULL]"
-250978744945567,"sched_waking",2,"success",1,"[NULL]"
-250978744945567,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978746028431,"sched_waking",2,"comm","[NULL]","rcuop/2"
-250978746028431,"sched_waking",2,"pid",29,"[NULL]"
-250978746028431,"sched_waking",2,"prio",120,"[NULL]"
-250978746028431,"sched_waking",2,"success",1,"[NULL]"
-250978746028431,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978746173171,"sched_waking",2,"comm","[NULL]","rcu_preempt"
-250978746173171,"sched_waking",2,"pid",7,"[NULL]"
-250978746173171,"sched_waking",2,"prio",120,"[NULL]"
-250978746173171,"sched_waking",2,"success",1,"[NULL]"
-250978746173171,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978751622494,"sched_waking",2,"comm","[NULL]","rcu_preempt"
-250978751622494,"sched_waking",2,"pid",7,"[NULL]"
-250978751622494,"sched_waking",2,"prio",120,"[NULL]"
-250978751622494,"sched_waking",2,"success",1,"[NULL]"
-250978751622494,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978751661348,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
-250978751661348,"sched_waking",2,"pid",17473,"[NULL]"
-250978751661348,"sched_waking",2,"prio",120,"[NULL]"
-250978751661348,"sched_waking",2,"success",1,"[NULL]"
-250978751661348,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978751792859,"sched_waking",2,"comm","[NULL]","rcuop/2"
-250978751792859,"sched_waking",2,"pid",29,"[NULL]"
-250978751792859,"sched_waking",2,"prio",120,"[NULL]"
-250978751792859,"sched_waking",2,"success",1,"[NULL]"
-250978751792859,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978751971817,"sched_waking",2,"comm","[NULL]","rcu_preempt"
-250978751971817,"sched_waking",2,"pid",7,"[NULL]"
-250978751971817,"sched_waking",2,"prio",120,"[NULL]"
-250978751971817,"sched_waking",2,"success",1,"[NULL]"
-250978751971817,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978758784578,"sched_waking",2,"comm","[NULL]","rcu_preempt"
-250978758784578,"sched_waking",2,"pid",7,"[NULL]"
-250978758784578,"sched_waking",2,"prio",120,"[NULL]"
-250978758784578,"sched_waking",2,"success",1,"[NULL]"
-250978758784578,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978758873745,"sched_waking",2,"comm","[NULL]","rcuop/2"
-250978758873745,"sched_waking",2,"pid",29,"[NULL]"
-250978758873745,"sched_waking",2,"prio",120,"[NULL]"
-250978758873745,"sched_waking",2,"success",1,"[NULL]"
-250978758873745,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978808519271,"sched_waking",2,"comm","[NULL]","rcu_preempt"
-250978808519271,"sched_waking",2,"pid",7,"[NULL]"
-250978808519271,"sched_waking",2,"prio",120,"[NULL]"
-250978808519271,"sched_waking",2,"success",1,"[NULL]"
-250978808519271,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978815488490,"sched_waking",2,"comm","[NULL]","rcu_preempt"
-250978815488490,"sched_waking",2,"pid",7,"[NULL]"
-250978815488490,"sched_waking",2,"prio",120,"[NULL]"
-250978815488490,"sched_waking",2,"success",1,"[NULL]"
-250978815488490,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978815535678,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
-250978815535678,"sched_waking",2,"pid",17473,"[NULL]"
-250978815535678,"sched_waking",2,"prio",120,"[NULL]"
-250978815535678,"sched_waking",2,"success",1,"[NULL]"
-250978815535678,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978815675782,"sched_waking",2,"comm","[NULL]","rcuop/0"
-250978815675782,"sched_waking",2,"pid",10,"[NULL]"
-250978815675782,"sched_waking",2,"prio",120,"[NULL]"
-250978815675782,"sched_waking",2,"success",1,"[NULL]"
-250978815675782,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978815738022,"sched_waking",2,"comm","[NULL]","rcuop/1"
-250978815738022,"sched_waking",2,"pid",21,"[NULL]"
-250978815738022,"sched_waking",2,"prio",120,"[NULL]"
-250978815738022,"sched_waking",2,"success",1,"[NULL]"
-250978815738022,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978860203182,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
-250978860203182,"sched_waking",2,"pid",17473,"[NULL]"
-250978860203182,"sched_waking",2,"prio",120,"[NULL]"
-250978860203182,"sched_waking",2,"success",1,"[NULL]"
-250978860203182,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978880151205,"sched_waking",2,"comm","[NULL]","kworker/2:0"
-250978880151205,"sched_waking",2,"pid",17438,"[NULL]"
-250978880151205,"sched_waking",2,"prio",120,"[NULL]"
-250978880151205,"sched_waking",2,"success",1,"[NULL]"
-250978880151205,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978880432143,"sched_waking",2,"comm","[NULL]","kworker/u16:18"
-250978880432143,"sched_waking",2,"pid",17473,"[NULL]"
-250978880432143,"sched_waking",2,"prio",120,"[NULL]"
-250978880432143,"sched_waking",2,"success",1,"[NULL]"
-250978880432143,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978885784018,"sched_waking",2,"comm","[NULL]","rcu_preempt"
-250978885784018,"sched_waking",2,"pid",7,"[NULL]"
-250978885784018,"sched_waking",2,"prio",120,"[NULL]"
-250978885784018,"sched_waking",2,"success",1,"[NULL]"
-250978885784018,"sched_waking",2,"target_cpu",2,"[NULL]"
-250978465172309,"sched_waking",3,"comm","[NULL]","ksoftirqd/3"
-250978465172309,"sched_waking",3,"pid",34,"[NULL]"
-250978465172309,"sched_waking",3,"prio",120,"[NULL]"
-250978465172309,"sched_waking",3,"success",1,"[NULL]"
-250978465172309,"sched_waking",3,"target_cpu",3,"[NULL]"
-250978465266789,"sched_waking",3,"comm","[NULL]","kworker/u16:18"
-250978465266789,"sched_waking",3,"pid",17473,"[NULL]"
-250978465266789,"sched_waking",3,"prio",120,"[NULL]"
-250978465266789,"sched_waking",3,"success",1,"[NULL]"
-250978465266789,"sched_waking",3,"target_cpu",0,"[NULL]"
-250978439491994,"sched_waking",4,"comm","[NULL]","rcu_sched"
-250978439491994,"sched_waking",4,"pid",8,"[NULL]"
-250978439491994,"sched_waking",4,"prio",120,"[NULL]"
-250978439491994,"sched_waking",4,"success",1,"[NULL]"
-250978439491994,"sched_waking",4,"target_cpu",1,"[NULL]"
-250978445783141,"sched_waking",5,"comm","[NULL]","rcu_sched"
-250978445783141,"sched_waking",5,"pid",8,"[NULL]"
-250978445783141,"sched_waking",5,"prio",120,"[NULL]"
-250978445783141,"sched_waking",5,"success",1,"[NULL]"
-250978445783141,"sched_waking",5,"target_cpu",5,"[NULL]"
-250978806359896,"sched_waking",5,"comm","[NULL]","kworker/5:1"
-250978806359896,"sched_waking",5,"pid",17667,"[NULL]"
-250978806359896,"sched_waking",5,"prio",120,"[NULL]"
-250978806359896,"sched_waking",5,"success",1,"[NULL]"
-250978806359896,"sched_waking",5,"target_cpu",5,"[NULL]"
-250978806428646,"sched_waking",5,"comm","[NULL]","kworker/u16:18"
-250978806428646,"sched_waking",5,"pid",17473,"[NULL]"
-250978806428646,"sched_waking",5,"prio",120,"[NULL]"
-250978806428646,"sched_waking",5,"success",1,"[NULL]"
-250978806428646,"sched_waking",5,"target_cpu",2,"[NULL]"
diff --git a/test/trace_processor/sfgate_smoke.out b/test/trace_processor/sfgate_smoke.out
index 580e3d9..72fd6a8 100644
--- a/test/trace_processor/sfgate_smoke.out
+++ b/test/trace_processor/sfgate_smoke.out
@@ -1 +1 @@
-"ts","cpu","dur","end_state","priority","tid"
+"ts","cpu","dur","ts_end","utid","end_state","priority","row_id"
diff --git a/test/trace_processor/sfgate_smoke_slices.out b/test/trace_processor/sfgate_smoke_slices.out
index 0991789..9f6ba8c 100644
--- a/test/trace_processor/sfgate_smoke_slices.out
+++ b/test/trace_processor/sfgate_smoke_slices.out
@@ -1,11 +1,11 @@
-"ref_type","depth","count"
-"utid",0,13359
-"utid",1,19447
-"utid",2,5816
-"utid",3,829
-"utid",4,191
-"utid",5,94
-"utid",6,57
-"utid",7,19
-"utid",8,14
-"utid",9,2
+"depth","count"
+0,13359
+1,19447
+2,5816
+3,829
+4,191
+5,94
+6,57
+7,19
+8,14
+9,2
diff --git a/test/trace_processor/smoke.sql b/test/trace_processor/smoke.sql
index a54ba35..e8de32a 100644
--- a/test/trace_processor/smoke.sql
+++ b/test/trace_processor/smoke.sql
@@ -1,11 +1 @@
-SELECT
-  ts,
-  cpu,
-  dur,
-  end_state,
-  priority,
-  tid
-FROM sched
-JOIN thread USING(utid)
-ORDER BY ts
-LIMIT 10;
+SELECT * from sched limit 10;
diff --git a/test/trace_processor/smoke_args.sql b/test/trace_processor/smoke_args.sql
new file mode 100644
index 0000000..2ec9d5e
--- /dev/null
+++ b/test/trace_processor/smoke_args.sql
@@ -0,0 +1 @@
+select * from args where key = "utid" limit 10;
diff --git a/test/trace_processor/smoke_counters.sql b/test/trace_processor/smoke_counters.sql
deleted file mode 100644
index 2f5b695..0000000
--- a/test/trace_processor/smoke_counters.sql
+++ /dev/null
@@ -1,7 +0,0 @@
-select 
-  ts,
-  value,
-  name,
-  ref_type
-from counters
-limit 10;
diff --git a/test/trace_processor/smoke_instants.sql b/test/trace_processor/smoke_instants.sql
deleted file mode 100644
index 2d5e005..0000000
--- a/test/trace_processor/smoke_instants.sql
+++ /dev/null
@@ -1,7 +0,0 @@
-select
-  ts,
-  name,
-  value,
-  ref_type
-from instants
-limit 10;
diff --git a/test/trace_processor/smoke_slices.sql b/test/trace_processor/smoke_slices.sql
index 6e31454..9f8dce2 100644
--- a/test/trace_processor/smoke_slices.sql
+++ b/test/trace_processor/smoke_slices.sql
@@ -1 +1 @@
-select ref_type, depth, count(*) as count from slices group by ref_type, depth order by ref_type, depth;
+select depth, count(*) as count from slices group by depth order by depth;
diff --git a/test/trace_processor/span_left_join_empty_right.out b/test/trace_processor/span_left_join_empty_right.out
deleted file mode 100644
index de527a7..0000000
--- a/test/trace_processor/span_left_join_empty_right.out
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-"ts","dur","part"
-500,500,100
diff --git a/test/trace_processor/span_left_join_empty_right.sql b/test/trace_processor/span_left_join_empty_right.sql
deleted file mode 100644
index 011fb5f..0000000
--- a/test/trace_processor/span_left_join_empty_right.sql
+++ /dev/null
@@ -1,22 +0,0 @@
-create table t1(
-  ts BIG INT,
-  dur BIG INT,
-  part BIG INT,
-  PRIMARY KEY (part, ts)
-) without rowid;
-
-create table t2(
-  ts BIG INT,
-  dur BIG INT,
-  part BIG INT,
-  PRIMARY KEY (part, ts)
-) without rowid;
-
-INSERT INTO t1(ts, dur, part)
-VALUES
-(500, 500, 100);
-
-create virtual table sp using span_left_join(t1 PARTITIONED part, 
-                                             t2 PARTITIONED part);
-
-select * from sp;
diff --git a/test/trace_processor/synth_1.py b/test/trace_processor/synth_1.py
index dbead5c..b42db14 100644
--- a/test/trace_processor/synth_1.py
+++ b/test/trace_processor/synth_1.py
@@ -15,7 +15,7 @@
 
 from os import sys, path
 
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
+sys.path.append(path.dirname(path.abspath(__file__)))
 import synth_common
 
 trace = synth_common.create_trace()
diff --git a/test/trace_processor/synth_1_smoke.out b/test/trace_processor/synth_1_smoke.out
index ac16d31..8c33245 100644
--- a/test/trace_processor/synth_1_smoke.out
+++ b/test/trace_processor/synth_1_smoke.out
@@ -1,9 +1,9 @@
-"ts","cpu","dur","end_state","priority","tid"
-1,0,99,"R",0,3
-50,1,70,"R",0,1
-100,0,15,"R",0,2
-115,0,285,"R",0,3
-120,1,50,"R",0,2
-170,1,80,"R",0,0
-250,1,140,"R",0,2
-390,1,10,"R",0,4
+"ts","cpu","dur","ts_end","utid","end_state","priority","row_id"
+1,0,99,100,4,"R",0,17179869184
+50,1,70,120,1,"R",0,17179869185
+100,0,15,115,2,"R",0,17179869186
+115,0,285,400,4,"R",0,17179869187
+120,1,50,170,2,"R",0,17179869188
+170,1,80,250,0,"R",0,17179869189
+250,1,140,390,2,"R",0,17179869190
+390,1,10,400,3,"R",0,17179869191
diff --git a/test/trace_processor/synth_common.py b/test/trace_processor/synth_common.py
new file mode 100644
index 0000000..c454b69
--- /dev/null
+++ b/test/trace_processor/synth_common.py
@@ -0,0 +1,138 @@
+#!/usr/bin/python
+# 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.
+
+import argparse
+
+from google.protobuf import descriptor, descriptor_pb2, message_factory, reflection
+from google.protobuf.pyext import _message
+
+CLONE_THREAD = 0x00010000
+
+
+class Trace(object):
+  def __init__(self, trace):
+    self.trace = trace
+    self.proc_map = {}
+    self.proc_map[0] = "idle_thread"
+
+  def add_system_info(self, arch=None):
+    self.packet = self.trace.packet.add()
+    self.packet.system_info.utsname.machine = arch
+
+  def add_ftrace_packet(self, cpu):
+    self.packet = self.trace.packet.add()
+    self.packet.ftrace_events.cpu = cpu
+
+  def __add_ftrace_event(self, ts, tid):
+    ftrace = self.packet.ftrace_events.event.add()
+    ftrace.timestamp = ts
+    ftrace.pid = tid
+    return ftrace
+
+  def add_rss_stat(self, ts, tid, member, size):
+    ftrace = self.__add_ftrace_event(ts, tid)
+    rss_stat = ftrace.rss_stat
+    rss_stat.member = member
+    rss_stat.size = size
+
+  def add_oom_score_update(self, ts, oom_score_adj, pid):
+    ftrace = self.__add_ftrace_event(ts, pid)
+    oom_score = ftrace.oom_score_adj_update
+    oom_score.comm = self.proc_map[pid]
+    oom_score.oom_score_adj = oom_score_adj
+    oom_score.pid = pid
+
+  def add_sched(self, ts, prev_pid, next_pid, prev_comm=None, next_comm=None):
+    ftrace = self.__add_ftrace_event(ts, 0)
+    ss = ftrace.sched_switch
+    ss.prev_comm = prev_comm or self.proc_map[prev_pid]
+    ss.prev_pid = prev_pid
+    ss.next_pid = next_pid
+    ss.next_comm = next_comm or self.proc_map[next_pid]
+
+  def add_cpufreq(self, ts, freq, cpu):
+    ftrace = self.__add_ftrace_event(ts, 0)
+    cpufreq = ftrace.cpu_frequency
+    cpufreq.state = freq
+    cpufreq.cpu_id = cpu
+
+  def add_kernel_lmk(self, ts, tid):
+    ftrace = self.__add_ftrace_event(ts, tid)
+    lowmemory_kill = ftrace.lowmemory_kill
+    lowmemory_kill.pid = tid
+
+  def add_sys_enter(self, ts, tid, id):
+    ftrace = self.__add_ftrace_event(ts, tid)
+    sys_enter = ftrace.sys_enter
+    sys_enter.id = id
+
+  def add_sys_exit(self, ts, tid, id, ret):
+    ftrace = self.__add_ftrace_event(ts, tid)
+    sys_exit = ftrace.sys_exit
+    sys_exit.id = id
+    sys_exit.ret = ret
+
+  def add_newtask(self, ts, tid, new_tid, new_comm, flags):
+    ftrace = self.__add_ftrace_event(ts, tid)
+    newtask = ftrace.task_newtask
+    newtask.pid = new_tid
+    newtask.comm = new_comm
+    newtask.clone_flags = flags
+
+  def add_process_tree_packet(self, ts=None):
+    self.packet = self.trace.packet.add()
+    if ts is not None:
+      self.packet.timestamp = ts
+
+  def add_process(self, pid, ppid, cmdline):
+    process = self.packet.process_tree.processes.add()
+    process.pid = pid
+    process.ppid = ppid
+    process.cmdline.append(cmdline)
+    self.proc_map[pid] = cmdline
+
+  def add_thread(self, tid, tgid, cmdline):
+    thread = self.packet.process_tree.threads.add()
+    thread.tid = tid
+    thread.tgid = tgid
+    self.proc_map[tid] = cmdline
+
+
+def create_trace():
+  parser = argparse.ArgumentParser()
+  parser.add_argument(
+      'trace_descriptor', type=str, help='location of trace descriptor')
+  args = parser.parse_args()
+
+  with open(args.trace_descriptor, "rb") as t:
+    fileContent = t.read()
+
+  file_desc_set_pb2 = descriptor_pb2.FileDescriptorSet()
+  file_desc_set_pb2.MergeFromString(fileContent)
+
+  desc_by_path = {}
+  for f_desc_pb2 in file_desc_set_pb2.file:
+    f_desc_pb2_encode = f_desc_pb2.SerializeToString()
+    f_desc = descriptor.FileDescriptor(
+        name=f_desc_pb2.name,
+        package=f_desc_pb2.package,
+        serialized_pb=f_desc_pb2_encode)
+
+    for desc in f_desc.message_types_by_name.values():
+      desc_by_path[desc.full_name] = desc
+
+  trace = message_factory.MessageFactory().GetPrototype(
+      desc_by_path["perfetto.protos.Trace"])()
+  return Trace(trace)
diff --git a/test/trace_processor/synth_oom.py b/test/trace_processor/synth_oom.py
index cc29268..648eece 100644
--- a/test/trace_processor/synth_oom.py
+++ b/test/trace_processor/synth_oom.py
@@ -14,7 +14,8 @@
 # limitations under the License.
 
 from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
+
+sys.path.append(path.dirname(path.abspath(__file__)))
 import synth_common
 
 file_member = 0
@@ -60,4 +61,5 @@
 trace.add_rss_stat(130, 2, file_member, 0)
 trace.add_rss_stat(130, 2, anon_member, 0)
 
+
 print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/synth_process_tracking.py b/test/trace_processor/synth_process_tracking.py
index 6686d89..3c2bb76 100644
--- a/test/trace_processor/synth_process_tracking.py
+++ b/test/trace_processor/synth_process_tracking.py
@@ -13,27 +13,30 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+
 # This synthetic trace is designed to test the process tracking logic. It
 # synthesizes a combination of sched_switch, task_newtask, and process tree
 # packets (i.e. the result of the userspace /proc/pid scraper).
 
-from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
 from synth_common import CLONE_THREAD
 import synth_common
+from os import sys, path
+
+sys.path.append(path.dirname(path.abspath(__file__)))
 
 trace = synth_common.create_trace()
 
+
 # Create the first process (pid=10) with three threads(tids=10,11,12).
 # In this synthetic trace we will pretend we never saw the start of this threads
 # (i.e. the task_newtask event). Process association for these threads will
 # leverage only the /proc/pid scraper.
 trace.add_ftrace_packet(0)
 trace.add_sched(ts=1, prev_pid=0, next_pid=10, next_comm='p1-t0')
-trace.add_sched(
-    ts=2, prev_pid=10, next_pid=11, prev_comm='p1-t0', next_comm='p1-t1')
-trace.add_sched(
-    ts=3, prev_pid=11, next_pid=12, prev_comm='p1-t1', next_comm='p1-t2')
+trace.add_sched(ts=2, prev_pid=10, next_pid=11,
+                prev_comm='p1-t0', next_comm='p1-t1')
+trace.add_sched(ts=3, prev_pid=11, next_pid=12,
+                prev_comm='p1-t1', next_comm='p1-t2')
 trace.add_sched(ts=4, prev_pid=12, next_pid=0, prev_comm='p1-t2')
 
 # In the synthetic /proc/pic scraper packet, we pretend we missed p1-1. At the
@@ -48,12 +51,12 @@
 # created before the start of the trace, and 22 is created only later.
 trace.add_ftrace_packet(0)
 trace.add_sched(ts=10, prev_pid=0, next_pid=20, next_comm='p2-t0')
-trace.add_sched(
-    ts=11, prev_pid=20, next_pid=21, prev_comm='p2-t0', next_comm='p2-t1')
-trace.add_newtask(
-    ts=12, tid=21, new_tid=22, new_comm='p2-t2', flags=CLONE_THREAD)
-trace.add_sched(
-    ts=13, prev_pid=21, next_pid=22, prev_comm='p2-t1', next_comm='p2-t2')
+trace.add_sched(ts=11, prev_pid=20, next_pid=21,
+                prev_comm='p2-t0', next_comm='p2-t1')
+trace.add_newtask(ts=12, tid=21, new_tid=22,
+                  new_comm='p2-t2', flags=CLONE_THREAD)
+trace.add_sched(ts=13, prev_pid=21, next_pid=22,
+                prev_comm='p2-t1', next_comm='p2-t2')
 trace.add_sched(ts=14, prev_pid=22, next_pid=0, prev_comm='p2-t2')
 
 # From the process tracker viewpoint we pretend we only scraped tids=20,21.
@@ -68,16 +71,16 @@
 # which, unluckily, recycles TID=34. We expect a new UTID for TID=34 then.
 trace.add_ftrace_packet(0)
 trace.add_sched(ts=20, prev_pid=0, next_pid=30, next_comm='p3-t0')
-trace.add_sched(
-    ts=21, prev_pid=30, next_pid=31, prev_comm='p3-t0', next_comm='p3-t1')
-trace.add_newtask(
-    ts=22, tid=31, new_tid=32, new_comm='p3-t2', flags=CLONE_THREAD)
-trace.add_newtask(
-    ts=23, tid=31, new_tid=33, new_comm='p3-t3', flags=CLONE_THREAD)
-trace.add_sched(
-    ts=24, prev_pid=31, next_pid=32, prev_comm='p3-t1', next_comm='p3-t2')
-trace.add_newtask(
-    ts=25, tid=32, new_tid=34, new_comm='p3-t4', flags=CLONE_THREAD)
+trace.add_sched(ts=21, prev_pid=30, next_pid=31,
+                prev_comm='p3-t0', next_comm='p3-t1')
+trace.add_newtask(ts=22, tid=31, new_tid=32,
+                  new_comm='p3-t2', flags=CLONE_THREAD)
+trace.add_newtask(ts=23, tid=31, new_tid=33,
+                  new_comm='p3-t3', flags=CLONE_THREAD)
+trace.add_sched(ts=24, prev_pid=31, next_pid=32,
+                prev_comm='p3-t1', next_comm='p3-t2')
+trace.add_newtask(ts=25, tid=32, new_tid=34,
+                  new_comm='p3-t4', flags=CLONE_THREAD)
 trace.add_process_tree_packet(ts=26)
 trace.add_process(30, 0, "process_3")
 trace.add_thread(31, 30, "p3-t1")
@@ -86,8 +89,8 @@
 # CLONE_THREAD in the add_newtask flags).
 trace.add_ftrace_packet(0)
 trace.add_newtask(ts=27, tid=32, new_tid=40, new_comm='p4-t0', flags=0)
-trace.add_sched(
-    ts=28, prev_pid=32, next_pid=40, prev_comm='p3-t2', next_comm='p4-t0')
+trace.add_sched(ts=28, prev_pid=32, next_pid=40,
+                prev_comm='p3-t2', next_comm='p4-t0')
 
 trace.add_process_tree_packet(ts=29)
 trace.add_process(40, 0, "process_4")
@@ -95,9 +98,10 @@
 # And now, this new process starts a new thread that recycles TID=31 (previously
 # used as p3-t1, now becomes p4-t1).
 trace.add_ftrace_packet(0)
-trace.add_newtask(
-    ts=30, tid=40, new_tid=31, new_comm='p4-t1', flags=CLONE_THREAD)
-trace.add_sched(
-    ts=31, prev_pid=40, next_pid=31, prev_comm='p4-t0', next_comm='p4-t1')
+trace.add_newtask(ts=30, tid=40, new_tid=31,
+                  new_comm='p4-t1', flags=CLONE_THREAD)
+trace.add_sched(ts=31, prev_pid=40, next_pid=31,
+                prev_comm='p4-t0', next_comm='p4-t1')
+
 
 print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/syscall.py b/test/trace_processor/syscall.py
index dd823b3..64bde87 100644
--- a/test/trace_processor/syscall.py
+++ b/test/trace_processor/syscall.py
@@ -14,7 +14,8 @@
 # limitations under the License.
 
 from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
+
+sys.path.append(path.dirname(path.abspath(__file__)))
 import synth_common
 
 trace = synth_common.create_trace()
@@ -26,6 +27,7 @@
 trace.add_process(pid=4, ppid=1, cmdline="single_thread_process")
 trace.add_thread(tid=3, tgid=2, cmdline="two_thread_process")
 
+
 trace.add_ftrace_packet(cpu=0)
 trace.add_sys_enter(ts=100, tid=1, id=0)
 trace.add_sys_enter(ts=105, tid=2, id=1)
diff --git a/test/trace_processor/systrace_html.out b/test/trace_processor/systrace_html.out
deleted file mode 100644
index 9f6a165..0000000
--- a/test/trace_processor/systrace_html.out
+++ /dev/null
@@ -1,3700 +0,0 @@
-"ts","cpu","dur","ts_end","utid","end_state","priority","upid","name","tid"
-6824711826499000,6,20000,6824711826519000,2,"S",100,2,"kworker/u17:1",1134
-6824711826519000,6,69000,6824711826588000,3,"S",120,3,"kworker/6:1",14833
-6824711826574000,2,133000,6824711826707000,4,"S",120,5,"UsbFfs-worker",20308
-6824711826588000,6,32000,6824711826620000,6,"S",120,4,"rcu_preempt",7
-6824711826620000,6,72000,6824711826692000,9,"S",120,6,"rcuop/4",44
-6824711826692000,6,16000,6824711826708000,5,"S",120,7,"rcu_sched",8
-6824711826707000,2,81000,6824711826788000,8,"S",120,8,"rcuop/6",60
-6824711826708000,6,352000,6824711827060000,0,"R",120,"[NULL]","swapper/5",0
-6824711826730000,0,80000,6824711826810000,11,"S",120,9,"rcuop/0",10
-6824711826788000,2,81000,6824711826869000,10,"S",120,11,"rcuop/5",52
-6824711826810000,0,15054000,6824711841864000,0,"R",120,"[NULL]","swapper/5",0
-6824711826820000,3,33000,6824711826853000,14,"S",120,10,"rcuos/0",11
-6824711826853000,3,54000,6824711826907000,13,"S",120,12,"rcuop/1",20
-6824711826869000,2,165000,6824711827034000,7,"S",120,5,"adbd",20305
-6824711826907000,3,380000,6824711827287000,0,"R",120,"[NULL]","swapper/5",0
-6824711826997000,1,21000,6824711827018000,15,"S",120,13,"rcuos/1",21
-6824711827018000,1,27430000,6824711854448000,0,"R",120,"[NULL]","swapper/5",0
-6824711827034000,2,51000,6824711827085000,12,"S",120,15,"rcuop/7",68
-6824711827060000,6,8000,6824711827068000,16,"S",120,14,"kworker/u16:7",19422
-6824711827068000,6,32000,6824711827100000,0,"R",120,"[NULL]","swapper/5",0
-6824711827085000,2,1808000,6824711828893000,0,"R",120,"[NULL]","swapper/5",0
-6824711827100000,6,4000,6824711827104000,16,"S",120,14,"kworker/u16:7",19422
-6824711827104000,6,9000,6824711827113000,0,"R",120,"[NULL]","swapper/5",0
-6824711827113000,6,31000,6824711827144000,16,"S",120,14,"kworker/u16:7",19422
-6824711827138000,7,5000,6824711827143000,17,"S",120,16,"kworker/u16:2",19725
-6824711827143000,7,13961000,6824711841104000,0,"R",120,"[NULL]","swapper/5",0
-6824711827144000,6,1680000,6824711828824000,0,"R",120,"[NULL]","swapper/5",0
-6824711827183000,4,899199000,6824712726382000,0,"R",120,"[NULL]","swapper/5",0
-6824711827287000,3,999000,6824711828286000,18,"x",120,17,"sh",20447
-6824711828286000,3,281000,6824711828567000,19,"x",120,5,"shell",20448
-6824711828567000,3,8000,6824711828575000,20,"S",120,18,"rcuos/2",29
-6824711828575000,3,250000,6824711828825000,7,"S",120,5,"adbd",20305
-6824711828824000,6,43000,6824711828867000,2,"S",100,2,"kworker/u17:1",1134
-6824711828825000,3,15722000,6824711844547000,0,"R",120,"[NULL]","swapper/5",0
-6824711828867000,6,19000,6824711828886000,3,"S",120,3,"kworker/6:1",14833
-6824711828886000,6,64000,6824711828950000,0,"R",120,"[NULL]","swapper/5",0
-6824711828893000,2,28000,6824711828921000,4,"S",120,5,"UsbFfs-worker",20308
-6824711828921000,2,72000,6824711828993000,0,"R",120,"[NULL]","swapper/5",0
-6824711828950000,6,14000,6824711828964000,2,"S",100,2,"kworker/u17:1",1134
-6824711828964000,6,21000,6824711828985000,3,"S",120,3,"kworker/6:1",14833
-6824711828985000,6,4000,6824711828989000,0,"R",120,"[NULL]","swapper/5",0
-6824711828989000,6,9000,6824711828998000,2,"S",100,2,"kworker/u17:1",1134
-6824711828993000,2,26000,6824711829019000,4,"S",120,5,"UsbFfs-worker",20308
-6824711828998000,6,102000,6824711829100000,0,"R",120,"[NULL]","swapper/5",0
-6824711829019000,2,208000,6824711829227000,0,"R",120,"[NULL]","swapper/5",0
-6824711829100000,6,34000,6824711829134000,2,"S",100,2,"kworker/u17:1",1134
-6824711829134000,6,38000,6824711829172000,0,"R",120,"[NULL]","swapper/5",0
-6824711829172000,6,16000,6824711829188000,2,"S",100,2,"kworker/u17:1",1134
-6824711829188000,6,23000,6824711829211000,3,"S",120,3,"kworker/6:1",14833
-6824711829211000,6,11000,6824711829222000,0,"R",120,"[NULL]","swapper/5",0
-6824711829222000,6,33000,6824711829255000,2,"S",100,2,"kworker/u17:1",1134
-6824711829227000,2,70000,6824711829297000,4,"S",120,5,"UsbFfs-worker",20308
-6824711829255000,6,40000,6824711829295000,0,"R",120,"[NULL]","swapper/5",0
-6824711829295000,6,13000,6824711829308000,2,"S",100,2,"kworker/u17:1",1134
-6824711829297000,2,153000,6824711829450000,7,"S",120,5,"adbd",20305
-6824711829308000,6,19000,6824711829327000,3,"S",120,3,"kworker/6:1",14833
-6824711829327000,6,75000,6824711829402000,0,"R",120,"[NULL]","swapper/5",0
-6824711829402000,6,12000,6824711829414000,2,"S",100,2,"kworker/u17:1",1134
-6824711829414000,6,7000,6824711829421000,3,"S",120,3,"kworker/6:1",14833
-6824711829421000,6,16000,6824711829437000,0,"R",120,"[NULL]","swapper/5",0
-6824711829437000,6,7000,6824711829444000,2,"S",100,2,"kworker/u17:1",1134
-6824711829444000,6,452000,6824711829896000,0,"R",120,"[NULL]","swapper/5",0
-6824711829450000,2,41000,6824711829491000,4,"S",120,5,"UsbFfs-worker",20308
-6824711829491000,2,68000,6824711829559000,7,"S",120,5,"adbd",20305
-6824711829559000,2,4671000,6824711834230000,0,"R",120,"[NULL]","swapper/5",0
-6824711829896000,6,16000,6824711829912000,3,"S",120,3,"kworker/6:1",14833
-6824711829912000,6,3511000,6824711833423000,0,"R",120,"[NULL]","swapper/5",0
-6824711833250000,5,36000,6824711833286000,22,"S",49,20,"sugov:4",606
-6824711833286000,5,153000,6824711833439000,21,"R+",120,19,"kswapd0",150
-6824711833423000,6,19000,6824711833442000,6,"S",120,4,"rcu_preempt",7
-6824711833439000,5,74000,6824711833513000,23,"S",120,21,"rcuop/2",28
-6824711833442000,6,8000,6824711833450000,5,"S",120,7,"rcu_sched",8
-6824711833450000,6,7442000,6824711840892000,0,"R",120,"[NULL]","swapper/5",0
-6824711833513000,5,994000,6824711834507000,21,"S",120,19,"kswapd0",150
-6824711834230000,2,26000,6824711834256000,24,"S",120,22,"rcuop/3",36
-6824711834256000,2,5778000,6824711840034000,0,"R",120,"[NULL]","swapper/5",0
-6824711834507000,5,6564000,6824711841071000,0,"R",120,"[NULL]","swapper/5",0
-6824711840034000,2,108000,6824711840142000,26,"S",49,23,"sugov:0",605
-6824711840142000,2,74000,6824711840216000,25,"S",120,24,"ksoftirqd/2",25
-6824711840216000,2,1649000,6824711841865000,0,"R",120,"[NULL]","swapper/5",0
-6824711840892000,6,39000,6824711840931000,6,"S",120,4,"rcu_preempt",7
-6824711840931000,6,24000,6824711840955000,5,"S",120,7,"rcu_sched",8
-6824711840955000,6,143000,6824711841098000,9,"S",120,6,"rcuop/4",44
-6824711841071000,5,11000,6824711841082000,27,"S",120,25,"rcuos/4",45
-6824711841082000,5,5691000,6824711846773000,0,"R",120,"[NULL]","swapper/5",0
-6824711841098000,6,3082000,6824711844180000,0,"R",120,"[NULL]","swapper/5",0
-6824711841104000,7,11000,6824711841115000,28,"S",120,26,"rcuos/6",61
-6824711841115000,7,12000,6824711841127000,29,"S",120,27,"rcuos/7",69
-6824711841127000,7,10000,6824711841137000,30,"S",120,28,"kworker/7:2",14813
-6824711841137000,7,290852000,6824712131989000,0,"R",120,"[NULL]","swapper/5",0
-6824711841864000,0,161000,6824711842025000,11,"S",120,9,"rcuop/0",10
-6824711841865000,2,1300000,6824711843165000,10,"S",120,11,"rcuop/5",52
-6824711842025000,0,12144000,6824711854169000,0,"R",120,"[NULL]","swapper/5",0
-6824711843165000,2,225000,6824711843390000,8,"R",120,8,"rcuop/6",60
-6824711843390000,2,108000,6824711843498000,26,"S",49,23,"sugov:0",605
-6824711843498000,2,131000,6824711843629000,13,"S",120,12,"rcuop/1",20
-6824711843629000,2,152000,6824711843781000,8,"S",120,8,"rcuop/6",60
-6824711843781000,2,441000,6824711844222000,12,"S",120,15,"rcuop/7",68
-6824711844180000,6,95000,6824711844275000,16,"D",120,14,"kworker/u16:7",19422
-6824711844222000,2,48000,6824711844270000,31,"S",120,29,"kworker/2:0",18823
-6824711844270000,2,2752000,6824711847022000,0,"R",120,"[NULL]","swapper/5",0
-6824711844275000,6,572000,6824711844847000,0,"R",120,"[NULL]","swapper/5",0
-6824711844547000,3,172000,6824711844719000,32,"S",120,30,"smem_native_rpm",87
-6824711844719000,3,2190000,6824711846909000,0,"R",120,"[NULL]","swapper/5",0
-6824711844847000,6,13000,6824711844860000,16,"S",120,14,"kworker/u16:7",19422
-6824711844860000,6,1757000,6824711846617000,0,"R",120,"[NULL]","swapper/5",0
-6824711846617000,6,22000,6824711846639000,6,"S",120,4,"rcu_preempt",7
-6824711846639000,6,16000,6824711846655000,5,"S",120,7,"rcu_sched",8
-6824711846655000,6,11000,6824711846666000,3,"S",120,3,"kworker/6:1",14833
-6824711846666000,6,149000,6824711846815000,16,"S",120,14,"kworker/u16:7",19422
-6824711846773000,5,35000,6824711846808000,23,"S",120,21,"rcuop/2",28
-6824711846808000,5,88282000,6824711935090000,0,"R",120,"[NULL]","swapper/5",0
-6824711846815000,6,7290000,6824711854105000,0,"R",120,"[NULL]","swapper/5",0
-6824711846909000,3,64000,6824711846973000,20,"S",120,18,"rcuos/2",29
-6824711846973000,3,63000,6824711847036000,33,"S",120,31,"rcuos/3",37
-6824711847022000,2,328000,6824711847350000,24,"S",120,22,"rcuop/3",36
-6824711847036000,3,3496000,6824711850532000,0,"R",120,"[NULL]","swapper/5",0
-6824711847350000,2,8611000,6824711855961000,0,"R",120,"[NULL]","swapper/5",0
-6824711850532000,3,50000,6824711850582000,34,"S",120,32,"ksoftirqd/3",33
-6824711850582000,3,24018000,6824711874600000,0,"R",120,"[NULL]","swapper/5",0
-6824711854105000,6,13000,6824711854118000,6,"S",120,4,"rcu_preempt",7
-6824711854118000,6,7000,6824711854125000,5,"S",120,7,"rcu_sched",8
-6824711854125000,6,6654000,6824711860779000,0,"R",120,"[NULL]","swapper/5",0
-6824711854169000,0,120000,6824711854289000,35,"S",120,33,"kworker/0:5",20371
-6824711854289000,0,462000,6824711854751000,0,"R",120,"[NULL]","swapper/5",0
-6824711854448000,1,404000,6824711854852000,36,"S",111,34,"SDM_EventThread",685
-6824711854751000,0,327000,6824711855078000,38,"S",120,35,"HwBinder:640_1",721
-6824711854852000,1,326000,6824711855178000,0,"R",120,"[NULL]","swapper/5",0
-6824711855078000,0,471000,6824711855549000,0,"R",120,"[NULL]","swapper/5",0
-6824711855178000,1,179000,6824711855357000,40,"S",97,35,"DispSync",676
-6824711855357000,1,545000,6824711855902000,0,"R",120,"[NULL]","swapper/5",0
-6824711855549000,0,272000,6824711855821000,41,"S",97,35,"app",678
-6824711855821000,0,1794000,6824711857615000,0,"R",120,"[NULL]","swapper/5",0
-6824711855902000,1,1771000,6824711857673000,42,"S",120,36,"ndroid.systemui",1664
-6824711855961000,2,72000,6824711856033000,40,"S",97,35,"DispSync",676
-6824711856033000,2,5351000,6824711861384000,0,"R",120,"[NULL]","swapper/5",0
-6824711857615000,0,250000,6824711857865000,43,"S",120,35,"Binder:640_2",675
-6824711857673000,1,347000,6824711858020000,0,"R",120,"[NULL]","swapper/5",0
-6824711857865000,0,426000,6824711858291000,0,"R",120,"[NULL]","swapper/5",0
-6824711858020000,1,151000,6824711858171000,41,"S",97,35,"app",678
-6824711858171000,1,29595000,6824711887766000,0,"R",120,"[NULL]","swapper/5",0
-6824711858291000,0,79000,6824711858370000,40,"S",97,35,"DispSync",676
-6824711858370000,0,1693000,6824711860063000,0,"R",120,"[NULL]","swapper/5",0
-6824711860063000,0,48000,6824711860111000,44,"S",120,37,"ksoftirqd/0",3
-6824711860111000,0,5836000,6824711865947000,0,"R",120,"[NULL]","swapper/5",0
-6824711860779000,6,128000,6824711860907000,22,"S",49,20,"sugov:4",606
-6824711860907000,6,78000,6824711860985000,6,"S",120,4,"rcu_preempt",7
-6824711860985000,6,67000,6824711861052000,5,"S",120,7,"rcu_sched",8
-6824711861052000,6,50000,6824711861102000,27,"S",120,25,"rcuos/4",45
-6824711861102000,6,168000,6824711861270000,9,"S",120,6,"rcuop/4",44
-6824711861270000,6,32000,6824711861302000,8,"S",120,8,"rcuop/6",60
-6824711861302000,6,12006000,6824711873308000,0,"R",120,"[NULL]","swapper/5",0
-6824711861384000,2,457000,6824711861841000,10,"S",120,11,"rcuop/5",52
-6824711861841000,2,27907000,6824711889748000,0,"R",120,"[NULL]","swapper/5",0
-6824711865947000,0,139000,6824711866086000,26,"S",49,23,"sugov:0",605
-6824711866086000,0,46000,6824711866132000,44,"S",120,37,"ksoftirqd/0",3
-6824711866132000,0,889000,6824711867021000,0,"R",120,"[NULL]","swapper/5",0
-6824711867021000,0,47000,6824711867068000,44,"S",120,37,"ksoftirqd/0",3
-6824711867068000,0,702000,6824711867770000,0,"R",120,"[NULL]","swapper/5",0
-6824711867770000,0,70000,6824711867840000,6,"S",120,4,"rcu_preempt",7
-6824711867840000,0,4623000,6824711872463000,0,"R",120,"[NULL]","swapper/5",0
-6824711872463000,0,52000,6824711872515000,44,"S",120,37,"ksoftirqd/0",3
-6824711872515000,0,868000,6824711873383000,0,"R",120,"[NULL]","swapper/5",0
-6824711873308000,6,68000,6824711873376000,16,"D",120,14,"kworker/u16:7",19422
-6824711873376000,6,665000,6824711874041000,0,"R",120,"[NULL]","swapper/5",0
-6824711873383000,0,136000,6824711873519000,6,"S",120,4,"rcu_preempt",7
-6824711873519000,0,76000,6824711873595000,23,"S",120,21,"rcuop/2",28
-6824711873595000,0,115000,6824711873710000,35,"S",120,33,"kworker/0:5",20371
-6824711873710000,0,46000,6824711873756000,11,"S",120,9,"rcuop/0",10
-6824711873756000,0,6329000,6824711880085000,0,"R",120,"[NULL]","swapper/5",0
-6824711874041000,6,477000,6824711874518000,16,"D",120,14,"kworker/u16:7",19422
-6824711874518000,6,672000,6824711875190000,0,"R",120,"[NULL]","swapper/5",0
-6824711874600000,3,138000,6824711874738000,32,"S",120,30,"smem_native_rpm",87
-6824711874738000,3,920000,6824711875658000,0,"R",120,"[NULL]","swapper/5",0
-6824711875190000,6,207000,6824711875397000,16,"D",120,14,"kworker/u16:7",19422
-6824711875397000,6,667000,6824711876064000,0,"R",120,"[NULL]","swapper/5",0
-6824711875658000,3,86000,6824711875744000,32,"S",120,30,"smem_native_rpm",87
-6824711875744000,3,729000,6824711876473000,0,"R",120,"[NULL]","swapper/5",0
-6824711876064000,6,202000,6824711876266000,16,"D",120,14,"kworker/u16:7",19422
-6824711876266000,6,110000,6824711876376000,0,"R",120,"[NULL]","swapper/5",0
-6824711876376000,6,96000,6824711876472000,16,"D",120,14,"kworker/u16:7",19422
-6824711876472000,6,704000,6824711877176000,0,"R",120,"[NULL]","swapper/5",0
-6824711876473000,3,71000,6824711876544000,32,"S",120,30,"smem_native_rpm",87
-6824711876544000,3,783000,6824711877327000,0,"R",120,"[NULL]","swapper/5",0
-6824711877176000,6,125000,6824711877301000,16,"D",120,14,"kworker/u16:7",19422
-6824711877301000,6,678000,6824711877979000,0,"R",120,"[NULL]","swapper/5",0
-6824711877327000,3,143000,6824711877470000,32,"S",120,30,"smem_native_rpm",87
-6824711877470000,3,716000,6824711878186000,0,"R",120,"[NULL]","swapper/5",0
-6824711877979000,6,198000,6824711878177000,16,"D",120,14,"kworker/u16:7",19422
-6824711878177000,6,472000,6824711878649000,0,"R",120,"[NULL]","swapper/5",0
-6824711878186000,3,193000,6824711878379000,32,"S",120,30,"smem_native_rpm",87
-6824711878379000,3,469000,6824711878848000,0,"R",120,"[NULL]","swapper/5",0
-6824711878649000,6,182000,6824711878831000,16,"D",120,14,"kworker/u16:7",19422
-6824711878831000,6,446000,6824711879277000,0,"R",120,"[NULL]","swapper/5",0
-6824711878848000,3,140000,6824711878988000,32,"S",120,30,"smem_native_rpm",87
-6824711878988000,3,666000,6824711879654000,0,"R",120,"[NULL]","swapper/5",0
-6824711879277000,6,161000,6824711879438000,16,"D",120,14,"kworker/u16:7",19422
-6824711879438000,6,112000,6824711879550000,0,"R",120,"[NULL]","swapper/5",0
-6824711879550000,6,82000,6824711879632000,16,"D",120,14,"kworker/u16:7",19422
-6824711879632000,6,169000,6824711879801000,0,"R",120,"[NULL]","swapper/5",0
-6824711879654000,3,182000,6824711879836000,32,"S",120,30,"smem_native_rpm",87
-6824711879801000,6,192000,6824711879993000,16,"D",120,14,"kworker/u16:7",19422
-6824711879836000,3,398000,6824711880234000,0,"R",120,"[NULL]","swapper/5",0
-6824711879993000,6,231000,6824711880224000,0,"R",120,"[NULL]","swapper/5",0
-6824711880085000,0,155000,6824711880240000,44,"S",120,37,"ksoftirqd/0",3
-6824711880224000,6,143000,6824711880367000,16,"D",120,14,"kworker/u16:7",19422
-6824711880234000,3,64000,6824711880298000,32,"S",120,30,"smem_native_rpm",87
-6824711880240000,0,57000,6824711880297000,6,"S",120,4,"rcu_preempt",7
-6824711880297000,0,6382000,6824711886679000,0,"R",120,"[NULL]","swapper/5",0
-6824711880298000,3,94000,6824711880392000,0,"R",120,"[NULL]","swapper/5",0
-6824711880367000,6,186000,6824711880553000,0,"R",120,"[NULL]","swapper/5",0
-6824711880392000,3,202000,6824711880594000,32,"S",120,30,"smem_native_rpm",87
-6824711880553000,6,58000,6824711880611000,16,"S",120,14,"kworker/u16:7",19422
-6824711880594000,3,14276000,6824711894870000,0,"R",120,"[NULL]","swapper/5",0
-6824711880611000,6,5024000,6824711885635000,0,"R",120,"[NULL]","swapper/5",0
-6824711885635000,6,44000,6824711885679000,45,"S",120,38,"ksoftirqd/6",57
-6824711885679000,6,8649000,6824711894328000,0,"R",120,"[NULL]","swapper/5",0
-6824711886679000,0,139000,6824711886818000,6,"S",120,4,"rcu_preempt",7
-6824711886818000,0,59000,6824711886877000,8,"S",120,8,"rcuop/6",60
-6824711886877000,0,585000,6824711887462000,0,"R",120,"[NULL]","swapper/5",0
-6824711887462000,0,118000,6824711887580000,35,"S",120,33,"kworker/0:5",20371
-6824711887580000,0,455000,6824711888035000,0,"R",120,"[NULL]","swapper/5",0
-6824711887766000,1,377000,6824711888143000,36,"S",111,34,"SDM_EventThread",685
-6824711888035000,0,327000,6824711888362000,38,"S",120,35,"HwBinder:640_1",721
-6824711888143000,1,88000,6824711888231000,0,"R",120,"[NULL]","swapper/5",0
-6824711888231000,1,85000,6824711888316000,40,"S",97,35,"DispSync",676
-6824711888316000,1,979000,6824711889295000,0,"R",120,"[NULL]","swapper/5",0
-6824711888362000,0,604000,6824711888966000,0,"R",120,"[NULL]","swapper/5",0
-6824711888966000,0,178000,6824711889144000,40,"S",97,35,"DispSync",676
-6824711889144000,0,532000,6824711889676000,0,"R",120,"[NULL]","swapper/5",0
-6824711889295000,1,275000,6824711889570000,41,"S",97,35,"app",678
-6824711889570000,1,1823000,6824711891393000,0,"R",120,"[NULL]","swapper/5",0
-6824711889676000,0,1753000,6824711891429000,42,"S",120,36,"ndroid.systemui",1664
-6824711889748000,2,86000,6824711889834000,40,"S",97,35,"DispSync",676
-6824711889834000,2,34646000,6824711924480000,0,"R",120,"[NULL]","swapper/5",0
-6824711891393000,1,280000,6824711891673000,43,"S",120,35,"Binder:640_2",675
-6824711891429000,0,393000,6824711891822000,0,"R",120,"[NULL]","swapper/5",0
-6824711891673000,1,472000,6824711892145000,0,"R",120,"[NULL]","swapper/5",0
-6824711891822000,0,178000,6824711892000000,41,"S",97,35,"app",678
-6824711892000000,0,1451000,6824711893451000,0,"R",120,"[NULL]","swapper/5",0
-6824711892145000,1,95000,6824711892240000,40,"S",97,35,"DispSync",676
-6824711892240000,1,12180000,6824711904420000,0,"R",120,"[NULL]","swapper/5",0
-6824711893451000,0,109000,6824711893560000,6,"S",120,4,"rcu_preempt",7
-6824711893560000,0,38000,6824711893598000,23,"S",120,21,"rcuop/2",28
-6824711893598000,0,52000,6824711893650000,11,"S",120,9,"rcuop/0",10
-6824711893650000,0,78000,6824711893728000,35,"D",120,33,"kworker/0:5",20371
-6824711893728000,0,65000,6824711893793000,46,"S",120,39,"kworker/0:1",19511
-6824711893793000,0,59000,6824711893852000,35,"S",120,33,"kworker/0:5",20371
-6824711893852000,0,27555000,6824711921407000,0,"R",120,"[NULL]","swapper/5",0
-6824711894328000,6,300000,6824711894628000,16,"D",120,14,"kworker/u16:7",19422
-6824711894628000,6,2368000,6824711896996000,0,"R",120,"[NULL]","swapper/5",0
-6824711894870000,3,77000,6824711894947000,32,"S",120,30,"smem_native_rpm",87
-6824711894947000,3,4289000,6824711899236000,0,"R",120,"[NULL]","swapper/5",0
-6824711896996000,6,306000,6824711897302000,16,"D",120,14,"kworker/u16:7",19422
-6824711897302000,6,48000,6824711897350000,0,"R",120,"[NULL]","swapper/5",0
-6824711897350000,6,43000,6824711897393000,45,"S",120,38,"ksoftirqd/6",57
-6824711897393000,6,3585000,6824711900978000,0,"R",120,"[NULL]","swapper/5",0
-6824711899236000,3,257000,6824711899493000,32,"S",120,30,"smem_native_rpm",87
-6824711899493000,3,4694000,6824711904187000,0,"R",120,"[NULL]","swapper/5",0
-6824711900978000,6,122000,6824711901100000,16,"S",120,14,"kworker/u16:7",19422
-6824711901100000,6,50000,6824711901150000,0,"R",120,"[NULL]","swapper/5",0
-6824711901150000,6,40000,6824711901190000,45,"S",120,38,"ksoftirqd/6",57
-6824711901190000,6,826872000,6824712728062000,0,"R",120,"[NULL]","swapper/5",0
-6824711904187000,3,212000,6824711904399000,32,"S",120,30,"smem_native_rpm",87
-6824711904399000,3,55334000,6824711959733000,0,"R",120,"[NULL]","swapper/5",0
-6824711904420000,1,72000,6824711904492000,47,"S",120,40,"ksoftirqd/1",17
-6824711904492000,1,14769000,6824711919261000,0,"R",120,"[NULL]","swapper/5",0
-6824711919261000,1,145000,6824711919406000,47,"S",120,40,"ksoftirqd/1",17
-6824711919406000,1,3219000,6824711922625000,0,"R",120,"[NULL]","swapper/5",0
-6824711921407000,0,185000,6824711921592000,35,"S",120,33,"kworker/0:5",20371
-6824711921592000,0,726000,6824711922318000,36,"S",111,34,"SDM_EventThread",685
-6824711922318000,0,65000,6824711922383000,0,"R",120,"[NULL]","swapper/5",0
-6824711922383000,0,57000,6824711922440000,44,"S",120,37,"ksoftirqd/0",3
-6824711922440000,0,585000,6824711923025000,0,"R",120,"[NULL]","swapper/5",0
-6824711922625000,1,477000,6824711923102000,38,"S",120,35,"HwBinder:640_1",721
-6824711923025000,0,239000,6824711923264000,40,"S",97,35,"DispSync",676
-6824711923102000,1,584000,6824711923686000,0,"R",120,"[NULL]","swapper/5",0
-6824711923264000,0,1073000,6824711924337000,0,"R",120,"[NULL]","swapper/5",0
-6824711923686000,1,409000,6824711924095000,41,"S",97,35,"app",678
-6824711924095000,1,2591000,6824711926686000,0,"R",120,"[NULL]","swapper/5",0
-6824711924337000,0,2416000,6824711926753000,42,"S",120,36,"ndroid.systemui",1664
-6824711924480000,2,93000,6824711924573000,40,"S",97,35,"DispSync",676
-6824711924573000,2,34369000,6824711958942000,0,"R",120,"[NULL]","swapper/5",0
-6824711926686000,1,341000,6824711927027000,43,"S",120,35,"Binder:640_2",675
-6824711926753000,0,601000,6824711927354000,0,"R",120,"[NULL]","swapper/5",0
-6824711927027000,1,795000,6824711927822000,0,"R",120,"[NULL]","swapper/5",0
-6824711927354000,0,186000,6824711927540000,41,"S",97,35,"app",678
-6824711927540000,0,30747000,6824711958287000,0,"R",120,"[NULL]","swapper/5",0
-6824711927822000,1,86000,6824711927908000,40,"S",97,35,"DispSync",676
-6824711927908000,1,30404000,6824711958312000,0,"R",120,"[NULL]","swapper/5",0
-6824711935090000,5,59000,6824711935149000,21,"S",120,19,"kswapd0",150
-6824711935149000,5,791709000,6824712726858000,0,"R",120,"[NULL]","swapper/5",0
-6824711958287000,0,325000,6824711958612000,40,"S",97,35,"DispSync",676
-6824711958312000,1,275000,6824711958587000,47,"S",120,40,"ksoftirqd/1",17
-6824711958587000,1,120000,6824711958707000,48,"S",120,41,"kworker/1:1",18800
-6824711958612000,0,107000,6824711958719000,35,"S",120,33,"kworker/0:5",20371
-6824711958707000,1,827000,6824711959534000,0,"R",120,"[NULL]","swapper/5",0
-6824711958719000,0,580000,6824711959299000,36,"S",111,34,"SDM_EventThread",685
-6824711958942000,2,402000,6824711959344000,41,"S",97,35,"app",678
-6824711959299000,0,1274000,6824711960573000,16,"R+",120,14,"kworker/u16:7",19422
-6824711959344000,2,862000,6824711960206000,0,"R",120,"[NULL]","swapper/5",0
-6824711959534000,1,579000,6824711960113000,38,"S",120,35,"HwBinder:640_1",721
-6824711959733000,3,66000,6824711959799000,40,"S",97,35,"DispSync",676
-6824711959799000,3,2784000,6824711962583000,42,"S",120,36,"ndroid.systemui",1664
-6824711960113000,1,3163000,6824711963276000,0,"R",120,"[NULL]","swapper/5",0
-6824711960206000,2,86000,6824711960292000,40,"S",97,35,"DispSync",676
-6824711960292000,2,31867000,6824711992159000,0,"R",120,"[NULL]","swapper/5",0
-6824711960573000,0,54000,6824711960627000,32,"S",120,30,"smem_native_rpm",87
-6824711960627000,0,52000,6824711960679000,16,"D",120,14,"kworker/u16:7",19422
-6824711960679000,0,1939000,6824711962618000,0,"R",120,"[NULL]","swapper/5",0
-6824711962583000,3,212000,6824711962795000,16,"D",120,14,"kworker/u16:7",19422
-6824711962618000,0,399000,6824711963017000,43,"S",120,35,"Binder:640_2",675
-6824711962795000,3,29662000,6824711992457000,0,"R",120,"[NULL]","swapper/5",0
-6824711963017000,0,225000,6824711963242000,32,"S",120,30,"smem_native_rpm",87
-6824711963242000,0,720000,6824711963962000,0,"R",120,"[NULL]","swapper/5",0
-6824711963276000,1,193000,6824711963469000,41,"S",97,35,"app",678
-6824711963469000,1,75000,6824711963544000,16,"S",120,14,"kworker/u16:7",19422
-6824711963544000,1,27817000,6824711991361000,0,"R",120,"[NULL]","swapper/5",0
-6824711963962000,0,93000,6824711964055000,40,"S",97,35,"DispSync",676
-6824711964055000,0,26981000,6824711991036000,0,"R",120,"[NULL]","swapper/5",0
-6824711991036000,0,265000,6824711991301000,35,"S",120,33,"kworker/0:5",20371
-6824711991301000,0,902000,6824711992203000,36,"S",111,34,"SDM_EventThread",685
-6824711991361000,1,512000,6824711991873000,40,"S",97,35,"DispSync",676
-6824711991873000,1,90000,6824711991963000,0,"R",120,"[NULL]","swapper/5",0
-6824711991963000,1,86000,6824711992049000,47,"S",120,40,"ksoftirqd/1",17
-6824711992049000,1,1109000,6824711993158000,0,"R",120,"[NULL]","swapper/5",0
-6824711992159000,2,539000,6824711992698000,41,"S",97,35,"app",678
-6824711992203000,0,811000,6824711993014000,0,"R",120,"[NULL]","swapper/5",0
-6824711992457000,3,561000,6824711993018000,38,"S",120,35,"HwBinder:640_1",721
-6824711992698000,2,31632000,6824712024330000,0,"R",120,"[NULL]","swapper/5",0
-6824711993014000,0,3047000,6824711996061000,42,"S",120,36,"ndroid.systemui",1664
-6824711993018000,3,29607000,6824712022625000,0,"R",120,"[NULL]","swapper/5",0
-6824711993158000,1,88000,6824711993246000,40,"S",97,35,"DispSync",676
-6824711993246000,1,2846000,6824711996092000,0,"R",120,"[NULL]","swapper/5",0
-6824711996061000,0,723000,6824711996784000,0,"R",120,"[NULL]","swapper/5",0
-6824711996092000,1,399000,6824711996491000,43,"S",120,35,"Binder:640_2",675
-6824711996491000,1,795000,6824711997286000,0,"R",120,"[NULL]","swapper/5",0
-6824711996784000,0,206000,6824711996990000,41,"S",97,35,"app",678
-6824711996990000,0,72000,6824711997062000,0,"R",120,"[NULL]","swapper/5",0
-6824711997062000,0,65000,6824711997127000,44,"S",120,37,"ksoftirqd/0",3
-6824711997127000,0,25255000,6824712022382000,0,"R",120,"[NULL]","swapper/5",0
-6824711997286000,1,89000,6824711997375000,40,"S",97,35,"DispSync",676
-6824711997375000,1,26567000,6824712023942000,0,"R",120,"[NULL]","swapper/5",0
-6824712022382000,0,182000,6824712022564000,35,"S",120,33,"kworker/0:5",20371
-6824712022564000,0,1155000,6824712023719000,36,"S",111,34,"SDM_EventThread",685
-6824712022625000,3,91000,6824712022716000,49,"S",120,42,"kworker/3:1",17791
-6824712022716000,3,37690000,6824712060406000,0,"R",120,"[NULL]","swapper/5",0
-6824712023719000,0,311000,6824712024030000,16,"S",120,14,"kworker/u16:7",19422
-6824712023942000,1,639000,6824712024581000,38,"S",120,35,"HwBinder:640_1",721
-6824712024030000,0,921000,6824712024951000,0,"R",120,"[NULL]","swapper/5",0
-6824712024330000,2,324000,6824712024654000,40,"S",97,35,"DispSync",676
-6824712024581000,1,1190000,6824712025771000,0,"R",120,"[NULL]","swapper/5",0
-6824712024654000,2,1208000,6824712025862000,0,"R",120,"[NULL]","swapper/5",0
-6824712024951000,0,531000,6824712025482000,41,"S",97,35,"app",678
-6824712025482000,0,3497000,6824712028979000,0,"R",120,"[NULL]","swapper/5",0
-6824712025771000,1,3163000,6824712028934000,42,"S",120,36,"ndroid.systemui",1664
-6824712025862000,2,83000,6824712025945000,40,"S",97,35,"DispSync",676
-6824712025945000,2,34179000,6824712060124000,0,"R",120,"[NULL]","swapper/5",0
-6824712028934000,1,717000,6824712029651000,0,"R",120,"[NULL]","swapper/5",0
-6824712028979000,0,393000,6824712029372000,43,"S",120,35,"Binder:640_2",675
-6824712029372000,0,798000,6824712030170000,0,"R",120,"[NULL]","swapper/5",0
-6824712029651000,1,204000,6824712029855000,41,"S",97,35,"app",678
-6824712029855000,1,29454000,6824712059309000,0,"R",120,"[NULL]","swapper/5",0
-6824712030170000,0,89000,6824712030259000,40,"S",97,35,"DispSync",676
-6824712030259000,0,70000,6824712030329000,0,"R",120,"[NULL]","swapper/5",0
-6824712030329000,0,70000,6824712030399000,44,"S",120,37,"ksoftirqd/0",3
-6824712030399000,0,28593000,6824712058992000,0,"R",120,"[NULL]","swapper/5",0
-6824712058992000,0,265000,6824712059257000,35,"S",120,33,"kworker/0:5",20371
-6824712059257000,0,1001000,6824712060258000,36,"S",111,34,"SDM_EventThread",685
-6824712059309000,1,519000,6824712059828000,40,"S",97,35,"DispSync",676
-6824712059828000,1,364000,6824712060192000,0,"R",120,"[NULL]","swapper/5",0
-6824712060124000,2,513000,6824712060637000,41,"S",97,35,"app",678
-6824712060192000,1,37000,6824712060229000,47,"S",120,40,"ksoftirqd/1",17
-6824712060229000,1,111000,6824712060340000,48,"S",120,41,"kworker/1:1",18800
-6824712060258000,0,735000,6824712060993000,16,"R+",120,14,"kworker/u16:7",19422
-6824712060340000,1,928000,6824712061268000,0,"R",120,"[NULL]","swapper/5",0
-6824712060406000,3,546000,6824712060952000,38,"S",120,35,"HwBinder:640_1",721
-6824712060637000,2,31702000,6824712092339000,0,"R",120,"[NULL]","swapper/5",0
-6824712060952000,3,31540000,6824712092492000,0,"R",120,"[NULL]","swapper/5",0
-6824712060993000,0,65000,6824712061058000,40,"S",97,35,"DispSync",676
-6824712061058000,0,280000,6824712061338000,16,"S",120,14,"kworker/u16:7",19422
-6824712061268000,1,3172000,6824712064440000,42,"S",120,36,"ndroid.systemui",1664
-6824712061338000,0,3134000,6824712064472000,0,"R",120,"[NULL]","swapper/5",0
-6824712064440000,1,710000,6824712065150000,0,"R",120,"[NULL]","swapper/5",0
-6824712064472000,0,400000,6824712064872000,43,"S",120,35,"Binder:640_2",675
-6824712064872000,0,780000,6824712065652000,0,"R",120,"[NULL]","swapper/5",0
-6824712065150000,1,201000,6824712065351000,41,"S",97,35,"app",678
-6824712065351000,1,10437000,6824712075788000,0,"R",120,"[NULL]","swapper/5",0
-6824712065652000,0,89000,6824712065741000,40,"S",97,35,"DispSync",676
-6824712065741000,0,24857000,6824712090598000,0,"R",120,"[NULL]","swapper/5",0
-6824712075788000,1,292000,6824712076080000,50,"S",120,43,"Executor-7",14762
-6824712076080000,1,88000,6824712076168000,0,"R",120,"[NULL]","swapper/5",0
-6824712076168000,1,225000,6824712076393000,47,"S",120,40,"ksoftirqd/1",17
-6824712076393000,1,162000,6824712076555000,16,"S",120,14,"kworker/u16:7",19422
-6824712076555000,1,15181000,6824712091736000,0,"R",120,"[NULL]","swapper/5",0
-6824712090598000,0,224000,6824712090822000,35,"S",120,33,"kworker/0:5",20371
-6824712090822000,0,1321000,6824712092143000,36,"S",111,34,"SDM_EventThread",685
-6824712091736000,1,410000,6824712092146000,40,"S",97,35,"DispSync",676
-6824712092143000,0,90000,6824712092233000,0,"R",120,"[NULL]","swapper/5",0
-6824712092146000,1,1144000,6824712093290000,0,"R",120,"[NULL]","swapper/5",0
-6824712092233000,0,79000,6824712092312000,44,"S",120,37,"ksoftirqd/0",3
-6824712092312000,0,820000,6824712093132000,0,"R",120,"[NULL]","swapper/5",0
-6824712092339000,2,602000,6824712092941000,38,"S",120,35,"HwBinder:640_1",721
-6824712092492000,3,487000,6824712092979000,41,"S",97,35,"app",678
-6824712092941000,2,4352000,6824712097293000,0,"R",120,"[NULL]","swapper/5",0
-6824712092979000,3,33505000,6824712126484000,0,"R",120,"[NULL]","swapper/5",0
-6824712093132000,0,90000,6824712093222000,40,"S",97,35,"DispSync",676
-6824712093222000,0,3125000,6824712096347000,0,"R",120,"[NULL]","swapper/5",0
-6824712093290000,1,3028000,6824712096318000,42,"S",120,36,"ndroid.systemui",1664
-6824712096318000,1,443000,6824712096761000,0,"R",120,"[NULL]","swapper/5",0
-6824712096347000,0,516000,6824712096863000,43,"S",120,35,"Binder:640_2",675
-6824712096761000,1,208000,6824712096969000,41,"S",97,35,"app",678
-6824712096863000,0,27799000,6824712124662000,0,"R",120,"[NULL]","swapper/5",0
-6824712096969000,1,28547000,6824712125516000,0,"R",120,"[NULL]","swapper/5",0
-6824712097293000,2,94000,6824712097387000,40,"S",97,35,"DispSync",676
-6824712097387000,2,27295000,6824712124682000,0,"R",120,"[NULL]","swapper/5",0
-6824712124662000,0,474000,6824712125136000,40,"S",97,35,"DispSync",676
-6824712124682000,2,304000,6824712124986000,25,"S",120,24,"ksoftirqd/2",25
-6824712124986000,2,1342000,6824712126328000,0,"R",120,"[NULL]","swapper/5",0
-6824712125136000,0,150000,6824712125286000,35,"S",120,33,"kworker/0:5",20371
-6824712125286000,0,705000,6824712125991000,36,"R+",111,34,"SDM_EventThread",685
-6824712125516000,1,532000,6824712126048000,41,"S",97,35,"app",678
-6824712125991000,0,50000,6824712126041000,40,"S",97,35,"DispSync",676
-6824712126041000,0,199000,6824712126240000,36,"S",111,34,"SDM_EventThread",685
-6824712126048000,1,3632000,6824712129680000,0,"R",120,"[NULL]","swapper/5",0
-6824712126240000,0,149000,6824712126389000,16,"S",120,14,"kworker/u16:7",19422
-6824712126328000,2,2927000,6824712129255000,42,"S",120,36,"ndroid.systemui",1664
-6824712126389000,0,970000,6824712127359000,0,"R",120,"[NULL]","swapper/5",0
-6824712126484000,3,712000,6824712127196000,38,"S",120,35,"HwBinder:640_1",721
-6824712127196000,3,32061000,6824712159257000,0,"R",120,"[NULL]","swapper/5",0
-6824712127359000,0,84000,6824712127443000,40,"S",97,35,"DispSync",676
-6824712127443000,0,1769000,6824712129212000,0,"R",120,"[NULL]","swapper/5",0
-6824712129212000,0,299000,6824712129511000,43,"S",120,35,"Binder:640_2",675
-6824712129255000,2,29843000,6824712159098000,0,"R",120,"[NULL]","swapper/5",0
-6824712129511000,0,530000,6824712130041000,0,"R",120,"[NULL]","swapper/5",0
-6824712129680000,1,177000,6824712129857000,41,"S",97,35,"app",678
-6824712129857000,1,28493000,6824712158350000,0,"R",120,"[NULL]","swapper/5",0
-6824712130041000,0,88000,6824712130129000,40,"S",97,35,"DispSync",676
-6824712130129000,0,64000,6824712130193000,0,"R",120,"[NULL]","swapper/5",0
-6824712130193000,0,56000,6824712130249000,44,"S",120,37,"ksoftirqd/0",3
-6824712130249000,0,496000,6824712130745000,0,"R",120,"[NULL]","swapper/5",0
-6824712130745000,0,331000,6824712131076000,16,"R+",120,14,"kworker/u16:7",19422
-6824712131076000,0,202000,6824712131278000,52,"D",120,44,"rild",1339
-6824712131278000,0,65000,6824712131343000,16,"R+",120,14,"kworker/u16:7",19422
-6824712131343000,0,671000,6824712132014000,52,"S",120,44,"rild",1339
-6824712131989000,7,56000,6824712132045000,17,"S",120,16,"kworker/u16:2",19725
-6824712132014000,0,442000,6824712132456000,54,"S",120,44,"rild",1260
-6824712132045000,7,62353000,6824712194398000,0,"R",120,"[NULL]","swapper/5",0
-6824712132456000,0,749000,6824712133205000,55,"S",120,45,"suspend@1.0-ser",796
-6824712133205000,0,1823000,6824712135028000,54,"S",120,44,"rild",1260
-6824712135028000,0,81000,6824712135109000,11,"S",120,9,"rcuop/0",10
-6824712135109000,0,37000,6824712135146000,6,"S",120,4,"rcu_preempt",7
-6824712135146000,0,240000,6824712135386000,55,"S",120,45,"suspend@1.0-ser",796
-6824712135386000,0,65000,6824712135451000,16,"S",120,14,"kworker/u16:7",19422
-6824712135451000,0,5153000,6824712140604000,0,"R",120,"[NULL]","swapper/5",0
-6824712140604000,0,103000,6824712140707000,6,"S",120,4,"rcu_preempt",7
-6824712140707000,0,133000,6824712140840000,11,"S",120,9,"rcuop/0",10
-6824712140840000,0,16732000,6824712157572000,0,"R",120,"[NULL]","swapper/5",0
-6824712157572000,0,451000,6824712158023000,35,"S",120,33,"kworker/0:5",20371
-6824712158023000,0,992000,6824712159015000,36,"S",111,34,"SDM_EventThread",685
-6824712158350000,1,452000,6824712158802000,40,"S",97,35,"DispSync",676
-6824712158802000,1,87000,6824712158889000,0,"R",120,"[NULL]","swapper/5",0
-6824712158889000,1,87000,6824712158976000,47,"S",120,40,"ksoftirqd/1",17
-6824712158976000,1,981000,6824712159957000,0,"R",120,"[NULL]","swapper/5",0
-6824712159015000,0,478000,6824712159493000,0,"R",120,"[NULL]","swapper/5",0
-6824712159098000,2,521000,6824712159619000,41,"S",97,35,"app",678
-6824712159257000,3,559000,6824712159816000,38,"S",120,35,"HwBinder:640_1",721
-6824712159493000,0,708000,6824712160201000,42,"R",120,36,"ndroid.systemui",1664
-6824712159619000,2,33324000,6824712192943000,0,"R",120,"[NULL]","swapper/5",0
-6824712159816000,3,33271000,6824712193087000,0,"R",120,"[NULL]","swapper/5",0
-6824712159957000,1,87000,6824712160044000,40,"S",97,35,"DispSync",676
-6824712160044000,1,3767000,6824712163811000,0,"R",120,"[NULL]","swapper/5",0
-6824712160201000,0,878000,6824712161079000,16,"S",120,14,"kworker/u16:7",19422
-6824712161079000,0,86000,6824712161165000,35,"S",120,33,"kworker/0:5",20371
-6824712161165000,0,2618000,6824712163783000,42,"S",120,36,"ndroid.systemui",1664
-6824712163783000,0,718000,6824712164501000,0,"R",120,"[NULL]","swapper/5",0
-6824712163811000,1,405000,6824712164216000,43,"S",120,35,"Binder:640_2",675
-6824712164216000,1,792000,6824712165008000,0,"R",120,"[NULL]","swapper/5",0
-6824712164501000,0,203000,6824712164704000,41,"S",97,35,"app",678
-6824712164704000,0,26926000,6824712191630000,0,"R",120,"[NULL]","swapper/5",0
-6824712165008000,1,88000,6824712165096000,40,"S",97,35,"DispSync",676
-6824712165096000,1,26545000,6824712191641000,0,"R",120,"[NULL]","swapper/5",0
-6824712191630000,0,479000,6824712192109000,40,"S",97,35,"DispSync",676
-6824712191641000,1,258000,6824712191899000,47,"S",120,40,"ksoftirqd/1",17
-6824712191899000,1,160000,6824712192059000,0,"R",120,"[NULL]","swapper/5",0
-6824712192059000,1,615000,6824712192674000,41,"S",97,35,"app",678
-6824712192109000,0,139000,6824712192248000,35,"S",120,33,"kworker/0:5",20371
-6824712192248000,0,299000,6824712192547000,16,"S",120,14,"kworker/u16:7",19422
-6824712192547000,0,966000,6824712193513000,36,"S",111,34,"SDM_EventThread",685
-6824712192674000,1,1433000,6824712194107000,0,"R",120,"[NULL]","swapper/5",0
-6824712192943000,2,3173000,6824712196116000,42,"S",120,36,"ndroid.systemui",1664
-6824712193087000,3,109000,6824712193196000,40,"S",97,35,"DispSync",676
-6824712193196000,3,33652000,6824712226848000,0,"R",120,"[NULL]","swapper/5",0
-6824712193513000,0,1329000,6824712194842000,0,"R",120,"[NULL]","swapper/5",0
-6824712194107000,1,556000,6824712194663000,38,"S",120,35,"HwBinder:640_1",721
-6824712194398000,7,72000,6824712194470000,17,"S",120,16,"kworker/u16:2",19725
-6824712194470000,7,52792000,6824712247262000,0,"R",120,"[NULL]","swapper/5",0
-6824712194663000,1,2149000,6824712196812000,0,"R",120,"[NULL]","swapper/5",0
-6824712194842000,0,89000,6824712194931000,40,"S",97,35,"DispSync",676
-6824712194931000,0,1217000,6824712196148000,0,"R",120,"[NULL]","swapper/5",0
-6824712196116000,2,30414000,6824712226530000,0,"R",120,"[NULL]","swapper/5",0
-6824712196148000,0,385000,6824712196533000,43,"S",120,35,"Binder:640_2",675
-6824712196533000,0,781000,6824712197314000,0,"R",120,"[NULL]","swapper/5",0
-6824712196812000,1,200000,6824712197012000,41,"S",97,35,"app",678
-6824712197012000,1,28707000,6824712225719000,0,"R",120,"[NULL]","swapper/5",0
-6824712197314000,0,88000,6824712197402000,40,"S",97,35,"DispSync",676
-6824712197402000,0,28073000,6824712225475000,0,"R",120,"[NULL]","swapper/5",0
-6824712225475000,0,204000,6824712225679000,35,"S",120,33,"kworker/0:5",20371
-6824712225679000,0,916000,6824712226595000,36,"S",111,34,"SDM_EventThread",685
-6824712225719000,1,521000,6824712226240000,40,"S",97,35,"DispSync",676
-6824712226240000,1,81000,6824712226321000,0,"R",120,"[NULL]","swapper/5",0
-6824712226321000,1,87000,6824712226408000,47,"S",120,40,"ksoftirqd/1",17
-6824712226408000,1,1183000,6824712227591000,0,"R",120,"[NULL]","swapper/5",0
-6824712226530000,2,669000,6824712227199000,41,"S",97,35,"app",678
-6824712226595000,0,894000,6824712227489000,0,"R",120,"[NULL]","swapper/5",0
-6824712226848000,3,546000,6824712227394000,38,"S",120,35,"HwBinder:640_1",721
-6824712227199000,2,32486000,6824712259685000,0,"R",120,"[NULL]","swapper/5",0
-6824712227394000,3,101387000,6824712328781000,0,"R",120,"[NULL]","swapper/5",0
-6824712227489000,0,3161000,6824712230650000,42,"S",120,36,"ndroid.systemui",1664
-6824712227591000,1,88000,6824712227679000,40,"S",97,35,"DispSync",676
-6824712227679000,1,3014000,6824712230693000,0,"R",120,"[NULL]","swapper/5",0
-6824712230650000,0,717000,6824712231367000,0,"R",120,"[NULL]","swapper/5",0
-6824712230693000,1,394000,6824712231087000,43,"S",120,35,"Binder:640_2",675
-6824712231087000,1,782000,6824712231869000,0,"R",120,"[NULL]","swapper/5",0
-6824712231367000,0,200000,6824712231567000,41,"S",97,35,"app",678
-6824712231567000,0,13149000,6824712244716000,0,"R",120,"[NULL]","swapper/5",0
-6824712231869000,1,87000,6824712231956000,40,"S",97,35,"DispSync",676
-6824712231956000,1,12891000,6824712244847000,0,"R",120,"[NULL]","swapper/5",0
-6824712244716000,0,324000,6824712245040000,56,"S",120,46,"ogle.android.as",15167
-6824712244847000,1,193000,6824712245040000,57,"S",120,46,"ogle.android.as",15166
-6824712245040000,0,87000,6824712245127000,0,"R",120,"[NULL]","swapper/5",0
-6824712245040000,1,14256000,6824712259296000,0,"R",120,"[NULL]","swapper/5",0
-6824712245127000,0,258000,6824712245385000,44,"S",120,37,"ksoftirqd/0",3
-6824712245385000,0,12652000,6824712258037000,0,"R",120,"[NULL]","swapper/5",0
-6824712247262000,7,203000,6824712247465000,17,"S",120,16,"kworker/u16:2",19725
-6824712247465000,7,71000,6824712247536000,0,"R",120,"[NULL]","swapper/5",0
-6824712247536000,7,62000,6824712247598000,59,"S",120,47,"ksoftirqd/7",65
-6824712247598000,7,14402000,6824712262000000,0,"R",120,"[NULL]","swapper/5",0
-6824712258037000,0,225000,6824712258262000,35,"S",120,33,"kworker/0:5",20371
-6824712258262000,0,1133000,6824712259395000,36,"S",111,34,"SDM_EventThread",685
-6824712259296000,1,626000,6824712259922000,38,"S",120,35,"HwBinder:640_1",721
-6824712259395000,0,83000,6824712259478000,0,"R",120,"[NULL]","swapper/5",0
-6824712259478000,0,86000,6824712259564000,44,"S",120,37,"ksoftirqd/0",3
-6824712259564000,0,904000,6824712260468000,0,"R",120,"[NULL]","swapper/5",0
-6824712259685000,2,648000,6824712260333000,40,"S",97,35,"DispSync",676
-6824712259922000,1,1420000,6824712261342000,0,"R",120,"[NULL]","swapper/5",0
-6824712260333000,2,128000,6824712260461000,31,"S",120,29,"kworker/2:0",18823
-6824712260461000,2,979000,6824712261440000,0,"R",120,"[NULL]","swapper/5",0
-6824712260468000,0,523000,6824712260991000,41,"S",97,35,"app",678
-6824712260991000,0,3489000,6824712264480000,0,"R",120,"[NULL]","swapper/5",0
-6824712261342000,1,3074000,6824712264416000,42,"S",120,36,"ndroid.systemui",1664
-6824712261440000,2,98000,6824712261538000,40,"S",97,35,"DispSync",676
-6824712261538000,2,31144000,6824712292682000,0,"R",120,"[NULL]","swapper/5",0
-6824712262000000,7,773000,6824712262773000,17,"S",120,16,"kworker/u16:2",19725
-6824712262773000,7,467225000,6824712729998000,0,"R",120,"[NULL]","swapper/5",0
-6824712264416000,1,745000,6824712265161000,0,"R",120,"[NULL]","swapper/5",0
-6824712264480000,0,399000,6824712264879000,43,"S",120,35,"Binder:640_2",675
-6824712264879000,0,791000,6824712265670000,0,"R",120,"[NULL]","swapper/5",0
-6824712265161000,1,209000,6824712265370000,41,"S",97,35,"app",678
-6824712265370000,1,26002000,6824712291372000,0,"R",120,"[NULL]","swapper/5",0
-6824712265670000,0,96000,6824712265766000,40,"S",97,35,"DispSync",676
-6824712265766000,0,19023000,6824712284789000,0,"R",120,"[NULL]","swapper/5",0
-6824712284789000,0,487000,6824712285276000,60,"D",100,48,"thermal-engine",2490
-6824712285276000,0,89000,6824712285365000,0,"R",120,"[NULL]","swapper/5",0
-6824712285365000,0,85000,6824712285450000,44,"S",120,37,"ksoftirqd/0",3
-6824712285450000,0,2460000,6824712287910000,0,"R",120,"[NULL]","swapper/5",0
-6824712287910000,0,209000,6824712288119000,35,"R+",120,33,"kworker/0:5",20371
-6824712288119000,0,555000,6824712288674000,60,"S",100,48,"thermal-engine",2490
-6824712288674000,0,111000,6824712288785000,35,"S",120,33,"kworker/0:5",20371
-6824712288785000,0,83000,6824712288868000,0,"R",120,"[NULL]","swapper/5",0
-6824712288868000,0,79000,6824712288947000,44,"S",120,37,"ksoftirqd/0",3
-6824712288947000,0,1078000,6824712290025000,0,"R",120,"[NULL]","swapper/5",0
-6824712290025000,0,115000,6824712290140000,35,"S",120,33,"kworker/0:5",20371
-6824712290140000,0,986000,6824712291126000,36,"S",111,34,"SDM_EventThread",685
-6824712291126000,0,55000,6824712291181000,0,"R",120,"[NULL]","swapper/5",0
-6824712291181000,0,48000,6824712291229000,44,"S",120,37,"ksoftirqd/0",3
-6824712291229000,0,733000,6824712291962000,0,"R",120,"[NULL]","swapper/5",0
-6824712291372000,1,758000,6824712292130000,38,"S",120,35,"HwBinder:640_1",721
-6824712291962000,0,316000,6824712292278000,40,"S",97,35,"DispSync",676
-6824712292130000,1,1482000,6824712293612000,0,"R",120,"[NULL]","swapper/5",0
-6824712292278000,0,1237000,6824712293515000,0,"R",120,"[NULL]","swapper/5",0
-6824712292682000,2,555000,6824712293237000,41,"S",97,35,"app",678
-6824712293237000,2,4208000,6824712297445000,0,"R",120,"[NULL]","swapper/5",0
-6824712293515000,0,3069000,6824712296584000,42,"S",120,36,"ndroid.systemui",1664
-6824712293612000,1,83000,6824712293695000,40,"S",97,35,"DispSync",676
-6824712293695000,1,2925000,6824712296620000,0,"R",120,"[NULL]","swapper/5",0
-6824712296584000,0,315000,6824712296899000,0,"R",120,"[NULL]","swapper/5",0
-6824712296620000,1,373000,6824712296993000,43,"S",120,35,"Binder:640_2",675
-6824712296899000,0,235000,6824712297134000,41,"S",97,35,"app",678
-6824712296993000,1,153000,6824712297146000,17,"S",120,16,"kworker/u16:2",19725
-6824712297134000,0,29796000,6824712326930000,0,"R",120,"[NULL]","swapper/5",0
-6824712297146000,1,30662000,6824712327808000,0,"R",120,"[NULL]","swapper/5",0
-6824712297445000,2,91000,6824712297536000,40,"S",97,35,"DispSync",676
-6824712297536000,2,29403000,6824712326939000,0,"R",120,"[NULL]","swapper/5",0
-6824712326930000,0,479000,6824712327409000,40,"S",97,35,"DispSync",676
-6824712326939000,2,165000,6824712327104000,25,"S",120,24,"ksoftirqd/2",25
-6824712327104000,2,1506000,6824712328610000,0,"R",120,"[NULL]","swapper/5",0
-6824712327409000,0,171000,6824712327580000,35,"S",120,33,"kworker/0:5",20371
-6824712327580000,0,701000,6824712328281000,36,"R+",111,34,"SDM_EventThread",685
-6824712327808000,1,528000,6824712328336000,41,"S",97,35,"app",678
-6824712328281000,0,52000,6824712328333000,40,"S",97,35,"DispSync",676
-6824712328333000,0,226000,6824712328559000,36,"S",111,34,"SDM_EventThread",685
-6824712328336000,1,4173000,6824712332509000,0,"R",120,"[NULL]","swapper/5",0
-6824712328559000,0,938000,6824712329497000,0,"R",120,"[NULL]","swapper/5",0
-6824712328610000,2,3183000,6824712331793000,42,"S",120,36,"ndroid.systemui",1664
-6824712328781000,3,574000,6824712329355000,38,"S",120,35,"HwBinder:640_1",721
-6824712329355000,3,32279000,6824712361634000,0,"R",120,"[NULL]","swapper/5",0
-6824712329497000,0,87000,6824712329584000,40,"S",97,35,"DispSync",676
-6824712329584000,0,2242000,6824712331826000,0,"R",120,"[NULL]","swapper/5",0
-6824712331793000,2,29260000,6824712361053000,0,"R",120,"[NULL]","swapper/5",0
-6824712331826000,0,394000,6824712332220000,43,"S",120,35,"Binder:640_2",675
-6824712332220000,0,790000,6824712333010000,0,"R",120,"[NULL]","swapper/5",0
-6824712332509000,1,202000,6824712332711000,41,"S",97,35,"app",678
-6824712332711000,1,27609000,6824712360320000,0,"R",120,"[NULL]","swapper/5",0
-6824712333010000,0,85000,6824712333095000,40,"S",97,35,"DispSync",676
-6824712333095000,0,26074000,6824712359169000,0,"R",120,"[NULL]","swapper/5",0
-6824712359169000,0,225000,6824712359394000,35,"S",120,33,"kworker/0:5",20371
-6824712359394000,0,1615000,6824712361009000,36,"S",111,34,"SDM_EventThread",685
-6824712360320000,1,440000,6824712360760000,40,"S",97,35,"DispSync",676
-6824712360760000,1,80000,6824712360840000,0,"R",120,"[NULL]","swapper/5",0
-6824712360840000,1,552000,6824712361392000,38,"S",120,35,"HwBinder:640_1",721
-6824712361009000,0,85000,6824712361094000,35,"S",120,33,"kworker/0:5",20371
-6824712361053000,2,490000,6824712361543000,41,"S",97,35,"app",678
-6824712361094000,0,1024000,6824712362118000,17,"S",120,16,"kworker/u16:2",19725
-6824712361392000,1,52000,6824712361444000,0,"R",120,"[NULL]","swapper/5",0
-6824712361444000,1,3028000,6824712364472000,42,"S",120,36,"ndroid.systemui",1664
-6824712361543000,2,32596000,6824712394139000,0,"R",120,"[NULL]","swapper/5",0
-6824712361634000,3,102000,6824712361736000,40,"S",97,35,"DispSync",676
-6824712361736000,3,33366000,6824712395102000,0,"R",120,"[NULL]","swapper/5",0
-6824712362118000,0,2398000,6824712364516000,0,"R",120,"[NULL]","swapper/5",0
-6824712364472000,1,724000,6824712365196000,0,"R",120,"[NULL]","swapper/5",0
-6824712364516000,0,394000,6824712364910000,43,"S",120,35,"Binder:640_2",675
-6824712364910000,0,797000,6824712365707000,0,"R",120,"[NULL]","swapper/5",0
-6824712365196000,1,209000,6824712365405000,41,"S",97,35,"app",678
-6824712365405000,1,27749000,6824712393154000,0,"R",120,"[NULL]","swapper/5",0
-6824712365707000,0,88000,6824712365795000,40,"S",97,35,"DispSync",676
-6824712365795000,0,27098000,6824712392893000,0,"R",120,"[NULL]","swapper/5",0
-6824712392893000,0,266000,6824712393159000,35,"S",120,33,"kworker/0:5",20371
-6824712393154000,1,677000,6824712393831000,40,"S",97,35,"DispSync",676
-6824712393159000,0,1045000,6824712394204000,36,"S",111,34,"SDM_EventThread",685
-6824712393831000,1,936000,6824712394767000,0,"R",120,"[NULL]","swapper/5",0
-6824712394139000,2,561000,6824712394700000,41,"S",97,35,"app",678
-6824712394204000,0,745000,6824712394949000,0,"R",120,"[NULL]","swapper/5",0
-6824712394700000,2,32976000,6824712427676000,0,"R",120,"[NULL]","swapper/5",0
-6824712394767000,1,525000,6824712395292000,38,"S",120,35,"HwBinder:640_1",721
-6824712394949000,0,3133000,6824712398082000,42,"S",120,36,"ndroid.systemui",1664
-6824712395102000,3,102000,6824712395204000,40,"S",97,35,"DispSync",676
-6824712395204000,3,33047000,6824712428251000,0,"R",120,"[NULL]","swapper/5",0
-6824712395292000,1,2827000,6824712398119000,0,"R",120,"[NULL]","swapper/5",0
-6824712398082000,0,723000,6824712398805000,0,"R",120,"[NULL]","swapper/5",0
-6824712398119000,1,404000,6824712398523000,43,"S",120,35,"Binder:640_2",675
-6824712398523000,1,782000,6824712399305000,0,"R",120,"[NULL]","swapper/5",0
-6824712398805000,0,206000,6824712399011000,41,"S",97,35,"app",678
-6824712399011000,0,27138000,6824712426149000,0,"R",120,"[NULL]","swapper/5",0
-6824712399305000,1,88000,6824712399393000,40,"S",97,35,"DispSync",676
-6824712399393000,1,27547000,6824712426940000,0,"R",120,"[NULL]","swapper/5",0
-6824712426149000,0,223000,6824712426372000,35,"S",120,33,"kworker/0:5",20371
-6824712426372000,0,1235000,6824712427607000,36,"S",111,34,"SDM_EventThread",685
-6824712426940000,1,447000,6824712427387000,40,"S",97,35,"DispSync",676
-6824712427387000,1,62000,6824712427449000,0,"R",120,"[NULL]","swapper/5",0
-6824712427449000,1,556000,6824712428005000,38,"S",120,35,"HwBinder:640_1",721
-6824712427607000,0,142000,6824712427749000,17,"S",120,16,"kworker/u16:2",19725
-6824712427676000,2,485000,6824712428161000,41,"S",97,35,"app",678
-6824712427749000,0,1055000,6824712428804000,0,"R",120,"[NULL]","swapper/5",0
-6824712428005000,1,3964000,6824712431969000,0,"R",120,"[NULL]","swapper/5",0
-6824712428161000,2,33130000,6824712461291000,0,"R",120,"[NULL]","swapper/5",0
-6824712428251000,3,103000,6824712428354000,40,"S",97,35,"DispSync",676
-6824712428354000,3,33090000,6824712461444000,0,"R",120,"[NULL]","swapper/5",0
-6824712428804000,0,3132000,6824712431936000,42,"S",120,36,"ndroid.systemui",1664
-6824712431936000,0,704000,6824712432640000,0,"R",120,"[NULL]","swapper/5",0
-6824712431969000,1,397000,6824712432366000,43,"S",120,35,"Binder:640_2",675
-6824712432366000,1,792000,6824712433158000,0,"R",120,"[NULL]","swapper/5",0
-6824712432640000,0,216000,6824712432856000,41,"S",97,35,"app",678
-6824712432856000,0,26763000,6824712459619000,0,"R",120,"[NULL]","swapper/5",0
-6824712433158000,1,88000,6824712433246000,40,"S",97,35,"DispSync",676
-6824712433246000,1,27279000,6824712460525000,0,"R",120,"[NULL]","swapper/5",0
-6824712459619000,0,225000,6824712459844000,35,"S",120,33,"kworker/0:5",20371
-6824712459844000,0,1326000,6824712461170000,36,"S",111,34,"SDM_EventThread",685
-6824712460525000,1,447000,6824712460972000,40,"S",97,35,"DispSync",676
-6824712460972000,1,1100000,6824712462072000,0,"R",120,"[NULL]","swapper/5",0
-6824712461170000,0,668000,6824712461838000,17,"R+",120,16,"kworker/u16:2",19725
-6824712461291000,2,529000,6824712461820000,41,"S",97,35,"app",678
-6824712461444000,3,570000,6824712462014000,38,"S",120,35,"HwBinder:640_1",721
-6824712461820000,2,32964000,6824712494784000,0,"R",120,"[NULL]","swapper/5",0
-6824712461838000,0,60000,6824712461898000,40,"S",97,35,"DispSync",676
-6824712461898000,0,133000,6824712462031000,35,"S",120,33,"kworker/0:5",20371
-6824712462014000,3,33363000,6824712495377000,0,"R",120,"[NULL]","swapper/5",0
-6824712462031000,0,281000,6824712462312000,17,"S",120,16,"kworker/u16:2",19725
-6824712462072000,1,3236000,6824712465308000,42,"S",120,36,"ndroid.systemui",1664
-6824712462312000,0,3049000,6824712465361000,0,"R",120,"[NULL]","swapper/5",0
-6824712465308000,1,737000,6824712466045000,0,"R",120,"[NULL]","swapper/5",0
-6824712465361000,0,404000,6824712465765000,43,"S",120,35,"Binder:640_2",675
-6824712465765000,0,787000,6824712466552000,0,"R",120,"[NULL]","swapper/5",0
-6824712466045000,1,204000,6824712466249000,41,"S",97,35,"app",678
-6824712466249000,1,27754000,6824712494003000,0,"R",120,"[NULL]","swapper/5",0
-6824712466552000,0,174000,6824712466726000,40,"S",97,35,"DispSync",676
-6824712466726000,0,26386000,6824712493112000,0,"R",120,"[NULL]","swapper/5",0
-6824712493112000,0,746000,6824712493858000,35,"S",120,33,"kworker/0:5",20371
-6824712493858000,0,917000,6824712494775000,36,"S",111,34,"SDM_EventThread",685
-6824712494003000,1,505000,6824712494508000,40,"S",97,35,"DispSync",676
-6824712494508000,1,79000,6824712494587000,0,"R",120,"[NULL]","swapper/5",0
-6824712494587000,1,558000,6824712495145000,38,"S",120,35,"HwBinder:640_1",721
-6824712494775000,0,149000,6824712494924000,17,"S",120,16,"kworker/u16:2",19725
-6824712494784000,2,486000,6824712495270000,41,"S",97,35,"app",678
-6824712494924000,0,989000,6824712495913000,0,"R",120,"[NULL]","swapper/5",0
-6824712495145000,1,3951000,6824712499096000,0,"R",120,"[NULL]","swapper/5",0
-6824712495270000,2,33176000,6824712528446000,0,"R",120,"[NULL]","swapper/5",0
-6824712495377000,3,105000,6824712495482000,40,"S",97,35,"DispSync",676
-6824712495482000,3,33062000,6824712528544000,0,"R",120,"[NULL]","swapper/5",0
-6824712495913000,0,3157000,6824712499070000,42,"S",120,36,"ndroid.systemui",1664
-6824712499070000,0,712000,6824712499782000,0,"R",120,"[NULL]","swapper/5",0
-6824712499096000,1,408000,6824712499504000,43,"S",120,35,"Binder:640_2",675
-6824712499504000,1,790000,6824712500294000,0,"R",120,"[NULL]","swapper/5",0
-6824712499782000,0,306000,6824712500088000,41,"S",97,35,"app",678
-6824712500088000,0,26796000,6824712526884000,0,"R",120,"[NULL]","swapper/5",0
-6824712500294000,1,92000,6824712500386000,40,"S",97,35,"DispSync",676
-6824712500386000,1,27266000,6824712527652000,0,"R",120,"[NULL]","swapper/5",0
-6824712526884000,0,181000,6824712527065000,35,"S",120,33,"kworker/0:5",20371
-6824712527065000,0,125000,6824712527190000,17,"S",120,16,"kworker/u16:2",19725
-6824712527190000,0,978000,6824712528168000,36,"S",111,34,"SDM_EventThread",685
-6824712527652000,1,437000,6824712528089000,40,"S",97,35,"DispSync",676
-6824712528089000,1,1245000,6824712529334000,0,"R",120,"[NULL]","swapper/5",0
-6824712528168000,0,70000,6824712528238000,16,"S",120,14,"kworker/u16:7",19422
-6824712528238000,0,994000,6824712529232000,0,"R",120,"[NULL]","swapper/5",0
-6824712528446000,2,487000,6824712528933000,41,"S",97,35,"app",678
-6824712528544000,3,620000,6824712529164000,38,"S",120,35,"HwBinder:640_1",721
-6824712528933000,2,52000,6824712528985000,0,"R",120,"[NULL]","swapper/5",0
-6824712528985000,2,78000,6824712529063000,41,"S",97,35,"app",678
-6824712529063000,2,32595000,6824712561658000,0,"R",120,"[NULL]","swapper/5",0
-6824712529164000,3,33240000,6824712562404000,0,"R",120,"[NULL]","swapper/5",0
-6824712529232000,0,835000,6824712530067000,42,"R",120,36,"ndroid.systemui",1664
-6824712529334000,1,86000,6824712529420000,40,"S",97,35,"DispSync",676
-6824712529420000,1,3171000,6824712532591000,0,"R",120,"[NULL]","swapper/5",0
-6824712530067000,0,157000,6824712530224000,62,"S",120,43,"Executor-7",14763
-6824712530224000,0,2349000,6824712532573000,42,"S",120,36,"ndroid.systemui",1664
-6824712532573000,0,701000,6824712533274000,0,"R",120,"[NULL]","swapper/5",0
-6824712532591000,1,395000,6824712532986000,43,"S",120,35,"Binder:640_2",675
-6824712532986000,1,786000,6824712533772000,0,"R",120,"[NULL]","swapper/5",0
-6824712533274000,0,198000,6824712533472000,41,"S",97,35,"app",678
-6824712533472000,0,70000,6824712533542000,0,"R",120,"[NULL]","swapper/5",0
-6824712533542000,0,67000,6824712533609000,44,"S",120,37,"ksoftirqd/0",3
-6824712533609000,0,26476000,6824712560085000,0,"R",120,"[NULL]","swapper/5",0
-6824712533772000,1,89000,6824712533861000,40,"S",97,35,"DispSync",676
-6824712533861000,1,27413000,6824712561274000,0,"R",120,"[NULL]","swapper/5",0
-6824712560085000,0,224000,6824712560309000,35,"S",120,33,"kworker/0:5",20371
-6824712560309000,0,1129000,6824712561438000,36,"S",111,34,"SDM_EventThread",685
-6824712561274000,1,622000,6824712561896000,38,"S",120,35,"HwBinder:640_1",721
-6824712561438000,0,79000,6824712561517000,0,"R",120,"[NULL]","swapper/5",0
-6824712561517000,0,189000,6824712561706000,44,"S",120,37,"ksoftirqd/0",3
-6824712561658000,2,329000,6824712561987000,40,"S",97,35,"DispSync",676
-6824712561706000,0,1079000,6824712562785000,16,"S",120,14,"kworker/u16:7",19422
-6824712561896000,1,1355000,6824712563251000,0,"R",120,"[NULL]","swapper/5",0
-6824712561987000,2,1400000,6824712563387000,0,"R",120,"[NULL]","swapper/5",0
-6824712562404000,3,576000,6824712562980000,41,"S",97,35,"app",678
-6824712562785000,0,106000,6824712562891000,35,"S",120,33,"kworker/0:5",20371
-6824712562891000,0,3455000,6824712566346000,0,"R",120,"[NULL]","swapper/5",0
-6824712562980000,3,66067000,6824712629047000,0,"R",120,"[NULL]","swapper/5",0
-6824712563251000,1,3044000,6824712566295000,42,"S",120,36,"ndroid.systemui",1664
-6824712563387000,2,84000,6824712563471000,40,"S",97,35,"DispSync",676
-6824712563471000,2,66000,6824712563537000,0,"R",120,"[NULL]","swapper/5",0
-6824712563537000,2,61000,6824712563598000,25,"S",120,24,"ksoftirqd/2",25
-6824712563598000,2,28176000,6824712591774000,0,"R",120,"[NULL]","swapper/5",0
-6824712566295000,1,912000,6824712567207000,0,"R",120,"[NULL]","swapper/5",0
-6824712566346000,0,580000,6824712566926000,43,"S",120,35,"Binder:640_2",675
-6824712566926000,0,798000,6824712567724000,0,"R",120,"[NULL]","swapper/5",0
-6824712567207000,1,209000,6824712567416000,41,"S",97,35,"app",678
-6824712567416000,1,25855000,6824712593271000,0,"R",120,"[NULL]","swapper/5",0
-6824712567724000,0,90000,6824712567814000,40,"S",97,35,"DispSync",676
-6824712567814000,0,23951000,6824712591765000,0,"R",120,"[NULL]","swapper/5",0
-6824712591765000,0,69000,6824712591834000,44,"S",120,37,"ksoftirqd/0",3
-6824712591774000,2,643000,6824712592417000,63,"S",120,49,"hwservicemanage",602
-6824712591834000,0,141000,6824712591975000,35,"S",120,33,"kworker/0:5",20371
-6824712591975000,0,943000,6824712592918000,36,"S",111,34,"SDM_EventThread",685
-6824712592417000,2,1974000,6824712594391000,0,"R",120,"[NULL]","swapper/5",0
-6824712592918000,0,855000,6824712593773000,0,"R",120,"[NULL]","swapper/5",0
-6824712593271000,1,748000,6824712594019000,38,"S",120,35,"HwBinder:640_1",721
-6824712593773000,0,313000,6824712594086000,40,"S",97,35,"DispSync",676
-6824712594019000,1,75000,6824712594094000,0,"R",120,"[NULL]","swapper/5",0
-6824712594086000,0,1123000,6824712595209000,0,"R",120,"[NULL]","swapper/5",0
-6824712594094000,1,73000,6824712594167000,47,"S",120,40,"ksoftirqd/1",17
-6824712594167000,1,1145000,6824712595312000,0,"R",120,"[NULL]","swapper/5",0
-6824712594391000,2,543000,6824712594934000,41,"S",97,35,"app",678
-6824712594934000,2,33189000,6824712628123000,0,"R",120,"[NULL]","swapper/5",0
-6824712595209000,0,3193000,6824712598402000,42,"S",120,36,"ndroid.systemui",1664
-6824712595312000,1,84000,6824712595396000,40,"S",97,35,"DispSync",676
-6824712595396000,1,3046000,6824712598442000,0,"R",120,"[NULL]","swapper/5",0
-6824712598402000,0,638000,6824712599040000,0,"R",120,"[NULL]","swapper/5",0
-6824712598442000,1,395000,6824712598837000,43,"S",120,35,"Binder:640_2",675
-6824712598837000,1,566000,6824712599403000,0,"R",120,"[NULL]","swapper/5",0
-6824712599040000,0,182000,6824712599222000,41,"S",97,35,"app",678
-6824712599222000,0,27826000,6824712627048000,0,"R",120,"[NULL]","swapper/5",0
-6824712599403000,1,87000,6824712599490000,40,"S",97,35,"DispSync",676
-6824712599490000,1,27821000,6824712627311000,0,"R",120,"[NULL]","swapper/5",0
-6824712627048000,0,215000,6824712627263000,35,"S",120,33,"kworker/0:5",20371
-6824712627263000,0,865000,6824712628128000,36,"S",111,34,"SDM_EventThread",685
-6824712627311000,1,535000,6824712627846000,40,"S",97,35,"DispSync",676
-6824712627846000,1,97000,6824712627943000,0,"R",120,"[NULL]","swapper/5",0
-6824712627943000,1,143000,6824712628086000,47,"S",120,40,"ksoftirqd/1",17
-6824712628086000,1,559000,6824712628645000,38,"S",120,35,"HwBinder:640_1",721
-6824712628123000,2,487000,6824712628610000,41,"S",97,35,"app",678
-6824712628128000,0,134000,6824712628262000,16,"S",120,14,"kworker/u16:7",19422
-6824712628262000,0,1140000,6824712629402000,0,"R",120,"[NULL]","swapper/5",0
-6824712628610000,2,29797000,6824712658407000,0,"R",120,"[NULL]","swapper/5",0
-6824712628645000,1,4458000,6824712633103000,0,"R",120,"[NULL]","swapper/5",0
-6824712629047000,3,3339000,6824712632386000,42,"S",120,36,"ndroid.systemui",1664
-6824712629402000,0,86000,6824712629488000,40,"S",97,35,"DispSync",676
-6824712629488000,0,2932000,6824712632420000,0,"R",120,"[NULL]","swapper/5",0
-6824712632386000,3,20618000,6824712653004000,0,"R",120,"[NULL]","swapper/5",0
-6824712632420000,0,405000,6824712632825000,43,"S",120,35,"Binder:640_2",675
-6824712632825000,0,777000,6824712633602000,0,"R",120,"[NULL]","swapper/5",0
-6824712633103000,1,300000,6824712633403000,41,"S",97,35,"app",678
-6824712633403000,1,24713000,6824712658116000,0,"R",120,"[NULL]","swapper/5",0
-6824712633602000,0,89000,6824712633691000,40,"S",97,35,"DispSync",676
-6824712633691000,0,8761000,6824712642452000,0,"R",120,"[NULL]","swapper/5",0
-6824712642452000,0,1867000,6824712644319000,16,"R+",120,14,"kworker/u16:7",19422
-6824712644319000,0,91000,6824712644410000,64,"S",100,50,"kworker/0:1H",558
-6824712644410000,0,777000,6824712645187000,17,"D",120,16,"kworker/u16:2",19725
-6824712645187000,0,70000,6824712645257000,32,"S",120,30,"smem_native_rpm",87
-6824712645257000,0,107000,6824712645364000,16,"S",120,14,"kworker/u16:7",19422
-6824712645364000,0,605000,6824712645969000,0,"R",120,"[NULL]","swapper/5",0
-6824712645969000,0,204000,6824712646173000,17,"D",120,16,"kworker/u16:2",19725
-6824712646173000,0,123000,6824712646296000,32,"S",120,30,"smem_native_rpm",87
-6824712646296000,0,140000,6824712646436000,17,"D",120,16,"kworker/u16:2",19725
-6824712646436000,0,48000,6824712646484000,32,"S",120,30,"smem_native_rpm",87
-6824712646484000,0,171000,6824712646655000,0,"R",120,"[NULL]","swapper/5",0
-6824712646655000,0,46000,6824712646701000,64,"S",100,50,"kworker/0:1H",558
-6824712646701000,0,144000,6824712646845000,17,"D",120,16,"kworker/u16:2",19725
-6824712646845000,0,124000,6824712646969000,32,"S",120,30,"smem_native_rpm",87
-6824712646969000,0,167000,6824712647136000,17,"D",120,16,"kworker/u16:2",19725
-6824712647136000,0,49000,6824712647185000,32,"S",120,30,"smem_native_rpm",87
-6824712647185000,0,104000,6824712647289000,0,"R",120,"[NULL]","swapper/5",0
-6824712647289000,0,146000,6824712647435000,17,"D",120,16,"kworker/u16:2",19725
-6824712647435000,0,48000,6824712647483000,32,"S",120,30,"smem_native_rpm",87
-6824712647483000,0,945000,6824712648428000,0,"R",120,"[NULL]","swapper/5",0
-6824712648428000,0,169000,6824712648597000,17,"D",120,16,"kworker/u16:2",19725
-6824712648597000,0,119000,6824712648716000,32,"S",120,30,"smem_native_rpm",87
-6824712648716000,0,149000,6824712648865000,17,"D",120,16,"kworker/u16:2",19725
-6824712648865000,0,54000,6824712648919000,32,"S",120,30,"smem_native_rpm",87
-6824712648919000,0,62000,6824712648981000,0,"R",120,"[NULL]","swapper/5",0
-6824712648981000,0,150000,6824712649131000,17,"D",120,16,"kworker/u16:2",19725
-6824712649131000,0,113000,6824712649244000,32,"S",120,30,"smem_native_rpm",87
-6824712649244000,0,139000,6824712649383000,17,"D",120,16,"kworker/u16:2",19725
-6824712649383000,0,48000,6824712649431000,32,"S",120,30,"smem_native_rpm",87
-6824712649431000,0,72000,6824712649503000,0,"R",120,"[NULL]","swapper/5",0
-6824712649503000,0,130000,6824712649633000,17,"R+",120,16,"kworker/u16:2",19725
-6824712649633000,0,28000,6824712649661000,32,"S",120,30,"smem_native_rpm",87
-6824712649661000,0,41000,6824712649702000,17,"D",120,16,"kworker/u16:2",19725
-6824712649702000,0,58000,6824712649760000,0,"R",120,"[NULL]","swapper/5",0
-6824712649760000,0,262000,6824712650022000,17,"R+",120,16,"kworker/u16:2",19725
-6824712650022000,0,45000,6824712650067000,64,"S",100,50,"kworker/0:1H",558
-6824712650067000,0,34000,6824712650101000,32,"S",120,30,"smem_native_rpm",87
-6824712650101000,0,134000,6824712650235000,17,"R+",120,16,"kworker/u16:2",19725
-6824712650235000,0,27000,6824712650262000,32,"S",120,30,"smem_native_rpm",87
-6824712650262000,0,42000,6824712650304000,17,"D",120,16,"kworker/u16:2",19725
-6824712650304000,0,91000,6824712650395000,0,"R",120,"[NULL]","swapper/5",0
-6824712650395000,0,177000,6824712650572000,17,"R+",120,16,"kworker/u16:2",19725
-6824712650572000,0,63000,6824712650635000,32,"S",120,30,"smem_native_rpm",87
-6824712650635000,0,222000,6824712650857000,17,"D",120,16,"kworker/u16:2",19725
-6824712650857000,0,1177000,6824712652034000,0,"R",120,"[NULL]","swapper/5",0
-6824712652034000,0,108000,6824712652142000,17,"R+",120,16,"kworker/u16:2",19725
-6824712652142000,0,349000,6824712652491000,16,"S",120,14,"kworker/u16:7",19422
-6824712652491000,0,379000,6824712652870000,17,"S",120,16,"kworker/u16:2",19725
-6824712652870000,0,45000,6824712652915000,16,"S",120,14,"kworker/u16:7",19422
-6824712652915000,0,447000,6824712653362000,0,"R",120,"[NULL]","swapper/5",0
-6824712653004000,3,59000,6824712653063000,65,"S",100,51,"kworker/3:1H",578
-6824712653063000,3,70763000,6824712723826000,0,"R",120,"[NULL]","swapper/5",0
-6824712653362000,0,46000,6824712653408000,64,"S",100,50,"kworker/0:1H",558
-6824712653408000,0,4244000,6824712657652000,0,"R",120,"[NULL]","swapper/5",0
-6824712657652000,0,93000,6824712657745000,35,"S",120,33,"kworker/0:5",20371
-6824712657745000,0,488000,6824712658233000,36,"S",111,34,"SDM_EventThread",685
-6824712658116000,1,447000,6824712658563000,38,"S",120,35,"HwBinder:640_1",721
-6824712658233000,0,57000,6824712658290000,0,"R",120,"[NULL]","swapper/5",0
-6824712658290000,0,53000,6824712658343000,44,"S",120,37,"ksoftirqd/0",3
-6824712658343000,0,1697000,6824712660040000,0,"R",120,"[NULL]","swapper/5",0
-6824712658407000,2,117000,6824712658524000,40,"S",97,35,"DispSync",676
-6824712658524000,2,2025000,6824712660549000,0,"R",120,"[NULL]","swapper/5",0
-6824712658563000,1,1537000,6824712660100000,0,"R",120,"[NULL]","swapper/5",0
-6824712660040000,0,97000,6824712660137000,35,"S",120,33,"kworker/0:5",20371
-6824712660100000,1,184000,6824712660284000,40,"S",97,35,"DispSync",676
-6824712660137000,0,391000,6824712660528000,16,"S",120,14,"kworker/u16:7",19422
-6824712660284000,1,748000,6824712661032000,0,"R",120,"[NULL]","swapper/5",0
-6824712660528000,0,434000,6824712660962000,0,"R",120,"[NULL]","swapper/5",0
-6824712660549000,2,334000,6824712660883000,41,"S",97,35,"app",678
-6824712660883000,2,33798000,6824712694681000,0,"R",120,"[NULL]","swapper/5",0
-6824712660962000,0,1928000,6824712662890000,42,"S",120,36,"ndroid.systemui",1664
-6824712661032000,1,82000,6824712661114000,40,"S",97,35,"DispSync",676
-6824712661114000,1,1692000,6824712662806000,0,"R",120,"[NULL]","swapper/5",0
-6824712662806000,1,304000,6824712663110000,43,"S",120,35,"Binder:640_2",675
-6824712662890000,0,402000,6824712663292000,0,"R",120,"[NULL]","swapper/5",0
-6824712663110000,1,497000,6824712663607000,0,"R",120,"[NULL]","swapper/5",0
-6824712663292000,0,190000,6824712663482000,41,"S",97,35,"app",678
-6824712663482000,0,57000,6824712663539000,0,"R",120,"[NULL]","swapper/5",0
-6824712663539000,0,53000,6824712663592000,44,"S",120,37,"ksoftirqd/0",3
-6824712663592000,0,2553000,6824712666145000,0,"R",120,"[NULL]","swapper/5",0
-6824712663607000,1,90000,6824712663697000,40,"S",97,35,"DispSync",676
-6824712663697000,1,25560000,6824712689257000,0,"R",120,"[NULL]","swapper/5",0
-6824712666145000,0,109000,6824712666254000,32,"S",120,30,"smem_native_rpm",87
-6824712666254000,0,23413000,6824712689667000,0,"R",120,"[NULL]","swapper/5",0
-6824712689257000,1,201000,6824712689458000,47,"S",120,40,"ksoftirqd/1",17
-6824712689458000,1,81000,6824712689539000,48,"D",120,41,"kworker/1:1",18800
-6824712689539000,1,2472000,6824712692011000,0,"R",120,"[NULL]","swapper/5",0
-6824712689667000,0,99000,6824712689766000,16,"S",120,14,"kworker/u16:7",19422
-6824712689766000,0,1565000,6824712691331000,0,"R",120,"[NULL]","swapper/5",0
-6824712691331000,0,95000,6824712691426000,35,"S",120,33,"kworker/0:5",20371
-6824712691426000,0,518000,6824712691944000,36,"S",111,34,"SDM_EventThread",685
-6824712691944000,0,66000,6824712692010000,0,"R",120,"[NULL]","swapper/5",0
-6824712692010000,0,52000,6824712692062000,44,"S",120,37,"ksoftirqd/0",3
-6824712692011000,1,436000,6824712692447000,38,"S",120,35,"HwBinder:640_1",721
-6824712692062000,0,412000,6824712692474000,0,"R",120,"[NULL]","swapper/5",0
-6824712692447000,1,1171000,6824712693618000,0,"R",120,"[NULL]","swapper/5",0
-6824712692474000,0,113000,6824712692587000,40,"S",97,35,"DispSync",676
-6824712692587000,0,1292000,6824712693879000,0,"R",120,"[NULL]","swapper/5",0
-6824712693618000,1,43000,6824712693661000,47,"S",120,40,"ksoftirqd/1",17
-6824712693661000,1,535000,6824712694196000,0,"R",120,"[NULL]","swapper/5",0
-6824712693879000,0,175000,6824712694054000,40,"S",97,35,"DispSync",676
-6824712694054000,0,541000,6824712694595000,0,"R",120,"[NULL]","swapper/5",0
-6824712694196000,1,322000,6824712694518000,41,"S",97,35,"app",678
-6824712694518000,1,1868000,6824712696386000,0,"R",120,"[NULL]","swapper/5",0
-6824712694595000,0,1875000,6824712696470000,42,"S",120,36,"ndroid.systemui",1664
-6824712694681000,2,92000,6824712694773000,40,"S",97,35,"DispSync",676
-6824712694773000,2,2264000,6824712697037000,0,"R",120,"[NULL]","swapper/5",0
-6824712696386000,1,443000,6824712696829000,43,"S",120,35,"Binder:640_2",675
-6824712696470000,0,141000,6824712696611000,0,"R",120,"[NULL]","swapper/5",0
-6824712696611000,0,78000,6824712696689000,41,"S",97,35,"app",678
-6824712696689000,0,44000,6824712696733000,0,"R",120,"[NULL]","swapper/5",0
-6824712696733000,0,164000,6824712696897000,41,"S",97,35,"app",678
-6824712696829000,1,10308000,6824712707137000,0,"R",120,"[NULL]","swapper/5",0
-6824712696897000,0,6225000,6824712703122000,0,"R",120,"[NULL]","swapper/5",0
-6824712697037000,2,91000,6824712697128000,40,"S",97,35,"DispSync",676
-6824712697128000,2,25635000,6824712722763000,0,"R",120,"[NULL]","swapper/5",0
-6824712703122000,0,62000,6824712703184000,16,"D",120,14,"kworker/u16:7",19422
-6824712703184000,0,133000,6824712703317000,0,"R",120,"[NULL]","swapper/5",0
-6824712703317000,0,21000,6824712703338000,44,"S",120,37,"ksoftirqd/0",3
-6824712703338000,0,51000,6824712703389000,35,"D",120,33,"kworker/0:5",20371
-6824712703389000,0,49000,6824712703438000,0,"R",120,"[NULL]","swapper/5",0
-6824712703438000,0,613000,6824712704051000,16,"D",120,14,"kworker/u16:7",19422
-6824712704051000,0,129000,6824712704180000,32,"S",120,30,"smem_native_rpm",87
-6824712704180000,0,129000,6824712704309000,16,"D",120,14,"kworker/u16:7",19422
-6824712704309000,0,114000,6824712704423000,32,"S",120,30,"smem_native_rpm",87
-6824712704423000,0,123000,6824712704546000,16,"D",120,14,"kworker/u16:7",19422
-6824712704546000,0,107000,6824712704653000,32,"S",120,30,"smem_native_rpm",87
-6824712704653000,0,136000,6824712704789000,16,"D",120,14,"kworker/u16:7",19422
-6824712704789000,0,50000,6824712704839000,32,"S",120,30,"smem_native_rpm",87
-6824712704839000,0,628000,6824712705467000,0,"R",120,"[NULL]","swapper/5",0
-6824712705467000,0,160000,6824712705627000,16,"D",120,14,"kworker/u16:7",19422
-6824712705627000,0,121000,6824712705748000,32,"S",120,30,"smem_native_rpm",87
-6824712705748000,0,124000,6824712705872000,16,"D",120,14,"kworker/u16:7",19422
-6824712705872000,0,136000,6824712706008000,32,"S",120,30,"smem_native_rpm",87
-6824712706008000,0,152000,6824712706160000,16,"D",120,14,"kworker/u16:7",19422
-6824712706160000,0,114000,6824712706274000,32,"S",120,30,"smem_native_rpm",87
-6824712706274000,0,125000,6824712706399000,16,"D",120,14,"kworker/u16:7",19422
-6824712706399000,0,48000,6824712706447000,32,"S",120,30,"smem_native_rpm",87
-6824712706447000,0,873000,6824712707320000,0,"R",120,"[NULL]","swapper/5",0
-6824712707137000,1,57000,6824712707194000,47,"S",120,40,"ksoftirqd/1",17
-6824712707194000,1,15412000,6824712722606000,0,"R",120,"[NULL]","swapper/5",0
-6824712707320000,0,162000,6824712707482000,16,"D",120,14,"kworker/u16:7",19422
-6824712707482000,0,105000,6824712707587000,32,"S",120,30,"smem_native_rpm",87
-6824712707587000,0,128000,6824712707715000,16,"D",120,14,"kworker/u16:7",19422
-6824712707715000,0,115000,6824712707830000,32,"S",120,30,"smem_native_rpm",87
-6824712707830000,0,124000,6824712707954000,16,"D",120,14,"kworker/u16:7",19422
-6824712707954000,0,110000,6824712708064000,32,"S",120,30,"smem_native_rpm",87
-6824712708064000,0,140000,6824712708204000,16,"D",120,14,"kworker/u16:7",19422
-6824712708204000,0,114000,6824712708318000,32,"S",120,30,"smem_native_rpm",87
-6824712708318000,0,82000,6824712708400000,16,"S",120,14,"kworker/u16:7",19422
-6824712708400000,0,15285000,6824712723685000,0,"R",120,"[NULL]","swapper/5",0
-6824712722606000,1,109000,6824712722715000,66,"S",0,52,"watchdog/1",15
-6824712722715000,1,79000,6824712722794000,0,"R",120,"[NULL]","swapper/5",0
-6824712722763000,2,73000,6824712722836000,67,"S",0,53,"watchdog/2",23
-6824712722794000,1,64000,6824712722858000,47,"S",120,40,"ksoftirqd/1",17
-6824712722836000,2,5437000,6824712728273000,0,"R",120,"[NULL]","swapper/5",0
-6824712722858000,1,2789000,6824712725647000,0,"R",120,"[NULL]","swapper/5",0
-6824712723685000,0,148000,6824712723833000,46,"D",120,39,"kworker/0:1",19511
-6824712723826000,3,72000,6824712723898000,68,"S",0,54,"watchdog/3",31
-6824712723833000,0,828000,6824712724661000,0,"R",120,"[NULL]","swapper/5",0
-6824712723898000,3,34414000,6824712758312000,0,"R",120,"[NULL]","swapper/5",0
-6824712724661000,0,78000,6824712724739000,69,"S",120,55,"kworker/0:3",19397
-6824712724739000,0,236000,6824712724975000,46,"R+",120,39,"kworker/0:1",19511
-6824712724975000,0,544000,6824712725519000,36,"S",111,34,"SDM_EventThread",685
-6824712725519000,0,64000,6824712725583000,46,"S",120,39,"kworker/0:1",19511
-6824712725583000,0,365000,6824712725948000,0,"R",120,"[NULL]","swapper/5",0
-6824712725647000,1,483000,6824712726130000,38,"S",120,35,"HwBinder:640_1",721
-6824712725948000,0,129000,6824712726077000,40,"S",97,35,"DispSync",676
-6824712726077000,0,1250000,6824712727327000,0,"R",120,"[NULL]","swapper/5",0
-6824712726130000,1,1587000,6824712727717000,0,"R",120,"[NULL]","swapper/5",0
-6824712726382000,4,67000,6824712726449000,70,"S",0,56,"watchdog/4",39
-6824712726449000,4,657913000,6824713384362000,0,"R",120,"[NULL]","swapper/5",0
-6824712726858000,5,46000,6824712726904000,71,"S",0,57,"watchdog/5",47
-6824712726904000,5,48000,6824712726952000,0,"R",120,"[NULL]","swapper/5",0
-6824712726952000,5,38000,6824712726990000,72,"S",120,58,"ksoftirqd/5",49
-6824712726990000,5,678798000,6824713405788000,0,"R",120,"[NULL]","swapper/5",0
-6824712727327000,0,178000,6824712727505000,40,"S",97,35,"DispSync",676
-6824712727505000,0,702000,6824712728207000,0,"R",120,"[NULL]","swapper/5",0
-6824712727717000,1,350000,6824712728067000,41,"S",97,35,"app",678
-6824712728062000,6,48000,6824712728110000,73,"S",0,59,"watchdog/6",55
-6824712728067000,1,2263000,6824712730330000,0,"R",120,"[NULL]","swapper/5",0
-6824712728110000,6,110547000,6824712838657000,0,"R",120,"[NULL]","swapper/5",0
-6824712728207000,0,2150000,6824712730357000,42,"S",120,36,"ndroid.systemui",1664
-6824712728273000,2,88000,6824712728361000,40,"S",97,35,"DispSync",676
-6824712728361000,2,33537000,6824712761898000,0,"R",120,"[NULL]","swapper/5",0
-6824712729998000,7,46000,6824712730044000,74,"S",0,60,"watchdog/7",63
-6824712730044000,7,136266000,6824712866310000,0,"R",120,"[NULL]","swapper/5",0
-6824712730330000,1,314000,6824712730644000,43,"S",120,35,"Binder:640_2",675
-6824712730357000,0,484000,6824712730841000,0,"R",120,"[NULL]","swapper/5",0
-6824712730644000,1,567000,6824712731211000,0,"R",120,"[NULL]","swapper/5",0
-6824712730841000,0,182000,6824712731023000,41,"S",97,35,"app",678
-6824712731023000,0,2119000,6824712733142000,0,"R",120,"[NULL]","swapper/5",0
-6824712731211000,1,95000,6824712731306000,40,"S",97,35,"DispSync",676
-6824712731306000,1,27902000,6824712759208000,0,"R",120,"[NULL]","swapper/5",0
-6824712733142000,0,190000,6824712733332000,32,"S",120,30,"smem_native_rpm",87
-6824712733332000,0,25059000,6824712758391000,0,"R",120,"[NULL]","swapper/5",0
-6824712758312000,3,37000,6824712758349000,34,"S",120,32,"ksoftirqd/3",33
-6824712758349000,3,119000,6824712758468000,16,"S",120,14,"kworker/u16:7",19422
-6824712758391000,0,96000,6824712758487000,46,"S",120,39,"kworker/0:1",19511
-6824712758468000,3,38802000,6824712797270000,0,"R",120,"[NULL]","swapper/5",0
-6824712758487000,0,574000,6824712759061000,36,"S",111,34,"SDM_EventThread",685
-6824712759061000,0,699000,6824712759760000,0,"R",120,"[NULL]","swapper/5",0
-6824712759208000,1,489000,6824712759697000,38,"S",120,35,"HwBinder:640_1",721
-6824712759697000,1,1610000,6824712761307000,0,"R",120,"[NULL]","swapper/5",0
-6824712759760000,0,131000,6824712759891000,40,"S",97,35,"DispSync",676
-6824712759891000,0,227000,6824712760118000,0,"R",120,"[NULL]","swapper/5",0
-6824712760118000,0,54000,6824712760172000,46,"S",120,39,"kworker/0:1",19511
-6824712760172000,0,509000,6824712760681000,16,"S",120,14,"kworker/u16:7",19422
-6824712760681000,0,231000,6824712760912000,0,"R",120,"[NULL]","swapper/5",0
-6824712760912000,0,182000,6824712761094000,40,"S",97,35,"DispSync",676
-6824712761094000,0,708000,6824712761802000,0,"R",120,"[NULL]","swapper/5",0
-6824712761307000,1,363000,6824712761670000,41,"S",97,35,"app",678
-6824712761670000,1,2291000,6824712763961000,0,"R",120,"[NULL]","swapper/5",0
-6824712761802000,0,2190000,6824712763992000,42,"S",120,36,"ndroid.systemui",1664
-6824712761898000,2,92000,6824712761990000,40,"S",97,35,"DispSync",676
-6824712761990000,2,35024000,6824712797014000,0,"R",120,"[NULL]","swapper/5",0
-6824712763961000,1,312000,6824712764273000,43,"S",120,35,"Binder:640_2",675
-6824712763992000,0,457000,6824712764449000,0,"R",120,"[NULL]","swapper/5",0
-6824712764273000,1,539000,6824712764812000,0,"R",120,"[NULL]","swapper/5",0
-6824712764449000,0,182000,6824712764631000,41,"S",97,35,"app",678
-6824712764631000,0,30567000,6824712795198000,0,"R",120,"[NULL]","swapper/5",0
-6824712764812000,1,95000,6824712764907000,40,"S",97,35,"DispSync",676
-6824712764907000,1,30302000,6824712795209000,0,"R",120,"[NULL]","swapper/5",0
-6824712795198000,0,480000,6824712795678000,40,"S",97,35,"DispSync",676
-6824712795209000,1,163000,6824712795372000,47,"S",120,40,"ksoftirqd/1",17
-6824712795372000,1,877000,6824712796249000,0,"R",120,"[NULL]","swapper/5",0
-6824712795678000,0,171000,6824712795849000,46,"S",120,39,"kworker/0:1",19511
-6824712795849000,0,1068000,6824712796917000,36,"S",111,34,"SDM_EventThread",685
-6824712796249000,1,683000,6824712796932000,41,"S",97,35,"app",678
-6824712796917000,0,862000,6824712797779000,0,"R",120,"[NULL]","swapper/5",0
-6824712796932000,1,4294000,6824712801226000,0,"R",120,"[NULL]","swapper/5",0
-6824712797014000,2,615000,6824712797629000,38,"S",120,35,"HwBinder:640_1",721
-6824712797270000,3,69000,6824712797339000,40,"S",97,35,"DispSync",676
-6824712797339000,3,3182000,6824712800521000,42,"S",120,36,"ndroid.systemui",1664
-6824712797629000,2,32555000,6824712830184000,0,"R",120,"[NULL]","swapper/5",0
-6824712797779000,0,87000,6824712797866000,40,"S",97,35,"DispSync",676
-6824712797866000,0,2676000,6824712800542000,0,"R",120,"[NULL]","swapper/5",0
-6824712800521000,3,61041000,6824712861562000,0,"R",120,"[NULL]","swapper/5",0
-6824712800542000,0,397000,6824712800939000,43,"S",120,35,"Binder:640_2",675
-6824712800939000,0,790000,6824712801729000,0,"R",120,"[NULL]","swapper/5",0
-6824712801226000,1,203000,6824712801429000,41,"S",97,35,"app",678
-6824712801429000,1,28175000,6824712829604000,0,"R",120,"[NULL]","swapper/5",0
-6824712801729000,0,88000,6824712801817000,40,"S",97,35,"DispSync",676
-6824712801817000,0,26133000,6824712827950000,0,"R",120,"[NULL]","swapper/5",0
-6824712827950000,0,303000,6824712828253000,46,"S",120,39,"kworker/0:1",19511
-6824712828253000,0,1174000,6824712829427000,36,"S",111,34,"SDM_EventThread",685
-6824712829427000,0,87000,6824712829514000,0,"R",120,"[NULL]","swapper/5",0
-6824712829514000,0,249000,6824712829763000,44,"S",120,37,"ksoftirqd/0",3
-6824712829604000,1,771000,6824712830375000,38,"S",120,35,"HwBinder:640_1",721
-6824712829763000,0,134000,6824712829897000,16,"S",120,14,"kworker/u16:7",19422
-6824712829897000,0,1050000,6824712830947000,0,"R",120,"[NULL]","swapper/5",0
-6824712830184000,2,302000,6824712830486000,40,"S",97,35,"DispSync",676
-6824712830375000,1,1386000,6824712831761000,0,"R",120,"[NULL]","swapper/5",0
-6824712830486000,2,1407000,6824712831893000,0,"R",120,"[NULL]","swapper/5",0
-6824712830947000,0,531000,6824712831478000,41,"S",97,35,"app",678
-6824712831478000,0,3444000,6824712834922000,0,"R",120,"[NULL]","swapper/5",0
-6824712831761000,1,3128000,6824712834889000,42,"S",120,36,"ndroid.systemui",1664
-6824712831893000,2,86000,6824712831979000,40,"S",97,35,"DispSync",676
-6824712831979000,2,9415000,6824712841394000,0,"R",120,"[NULL]","swapper/5",0
-6824712834889000,1,707000,6824712835596000,0,"R",120,"[NULL]","swapper/5",0
-6824712834922000,0,398000,6824712835320000,43,"S",120,35,"Binder:640_2",675
-6824712835320000,0,775000,6824712836095000,0,"R",120,"[NULL]","swapper/5",0
-6824712835596000,1,201000,6824712835797000,41,"S",97,35,"app",678
-6824712835797000,1,24848000,6824712860645000,0,"R",120,"[NULL]","swapper/5",0
-6824712836095000,0,93000,6824712836188000,40,"S",97,35,"DispSync",676
-6824712836188000,0,23047000,6824712859235000,0,"R",120,"[NULL]","swapper/5",0
-6824712838657000,6,193000,6824712838850000,2,"S",100,2,"kworker/u17:1",1134
-6824712838850000,6,70000,6824712838920000,0,"R",120,"[NULL]","swapper/5",0
-6824712838920000,6,49000,6824712838969000,45,"S",120,38,"ksoftirqd/6",57
-6824712838969000,6,3751000,6824712842720000,0,"R",120,"[NULL]","swapper/5",0
-6824712841394000,2,165000,6824712841559000,25,"S",120,24,"ksoftirqd/2",25
-6824712841559000,2,3497000,6824712845056000,0,"R",120,"[NULL]","swapper/5",0
-6824712842720000,6,303000,6824712843023000,2,"S",100,2,"kworker/u17:1",1134
-6824712843023000,6,564000,6824712843587000,3,"S",120,3,"kworker/6:1",14833
-6824712843587000,6,2780000,6824712846367000,0,"R",120,"[NULL]","swapper/5",0
-6824712845056000,2,686000,6824712845742000,4,"S",120,5,"UsbFfs-worker",20308
-6824712845742000,2,3405000,6824712849147000,0,"R",120,"[NULL]","swapper/5",0
-6824712846367000,6,406000,6824712846773000,2,"S",100,2,"kworker/u17:1",1134
-6824712846773000,6,355000,6824712847128000,3,"S",120,3,"kworker/6:1",14833
-6824712847128000,6,206037000,6824713053165000,0,"R",120,"[NULL]","swapper/5",0
-6824712849147000,2,1203000,6824712850350000,4,"S",120,5,"UsbFfs-worker",20308
-6824712850350000,2,3128000,6824712853478000,7,"R+",120,5,"adbd",20305
-6824712853478000,2,128000,6824712853606000,23,"S",120,21,"rcuop/2",28
-6824712853606000,2,62000,6824712853668000,6,"S",120,4,"rcu_preempt",7
-6824712853668000,2,3944000,6824712857612000,7,"S",120,5,"adbd",20305
-6824712857612000,2,2594000,6824712860206000,75,"R+",120,61,"sh",20457
-6824712859235000,0,137000,6824712859372000,46,"S",120,39,"kworker/0:1",19511
-6824712859372000,0,965000,6824712860337000,36,"S",111,34,"SDM_EventThread",685
-6824712860206000,2,85000,6824712860291000,31,"S",120,29,"kworker/2:0",18823
-6824712860291000,2,57000,6824712860348000,6,"S",120,4,"rcu_preempt",7
-6824712860337000,0,922000,6824712861259000,16,"S",120,14,"kworker/u16:7",19422
-6824712860348000,2,3024000,6824712863372000,75,"R+",120,61,"sh",20457
-6824712860645000,1,709000,6824712861354000,38,"S",120,35,"HwBinder:640_1",721
-6824712861259000,0,553000,6824712861812000,0,"R",120,"[NULL]","swapper/5",0
-6824712861354000,1,1038000,6824712862392000,0,"R",120,"[NULL]","swapper/5",0
-6824712861562000,3,169000,6824712861731000,40,"S",97,35,"DispSync",676
-6824712861731000,3,1521000,6824712863252000,0,"R",120,"[NULL]","swapper/5",0
-6824712861812000,0,223000,6824712862035000,40,"S",97,35,"DispSync",676
-6824712862035000,0,716000,6824712862751000,0,"R",120,"[NULL]","swapper/5",0
-6824712862392000,1,491000,6824712862883000,41,"S",97,35,"app",678
-6824712862751000,0,3243000,6824712865994000,42,"S",120,36,"ndroid.systemui",1664
-6824712862883000,1,3367000,6824712866250000,0,"R",120,"[NULL]","swapper/5",0
-6824712863252000,3,63000,6824712863315000,40,"S",97,35,"DispSync",676
-6824712863315000,3,230000,6824712863545000,20,"S",120,18,"rcuos/2",29
-6824712863372000,2,95000,6824712863467000,6,"S",120,4,"rcu_preempt",7
-6824712863467000,2,80000,6824712863547000,23,"S",120,21,"rcuop/2",28
-6824712863545000,3,13874000,6824712877419000,0,"R",120,"[NULL]","swapper/5",0
-6824712863547000,2,40000,6824712863587000,5,"S",120,7,"rcu_sched",8
-6824712863587000,2,24000,6824712863611000,6,"S",120,4,"rcu_preempt",7
-6824712863611000,2,1548000,6824712865159000,75,"R+",120,61,"sh",20457
-6824712865159000,2,3064000,6824712868223000,7,"R+",120,5,"adbd",20305
-6824712865994000,0,1047000,6824712867041000,0,"R",120,"[NULL]","swapper/5",0
-6824712866250000,1,587000,6824712866837000,43,"S",120,35,"Binder:640_2",675
-6824712866310000,7,74000,6824712866384000,76,"S",120,62,"hwrng",215
-6824712866384000,7,6718000,6824712873102000,0,"R",120,"[NULL]","swapper/5",0
-6824712866837000,1,771000,6824712867608000,0,"R",120,"[NULL]","swapper/5",0
-6824712867041000,0,285000,6824712867326000,41,"S",97,35,"app",678
-6824712867326000,0,9974000,6824712877300000,0,"R",120,"[NULL]","swapper/5",0
-6824712867608000,1,76000,6824712867684000,40,"S",97,35,"DispSync",676
-6824712867684000,1,110000,6824712867794000,2,"S",100,2,"kworker/u17:1",1134
-6824712867794000,1,62000,6824712867856000,0,"R",120,"[NULL]","swapper/5",0
-6824712867856000,1,140000,6824712867996000,2,"S",100,2,"kworker/u17:1",1134
-6824712867996000,1,60000,6824712868056000,77,"R+",120,63,"kworker/1:0",19220
-6824712868056000,1,59000,6824712868115000,2,"S",100,2,"kworker/u17:1",1134
-6824712868115000,1,111000,6824712868226000,77,"R+",120,63,"kworker/1:0",19220
-6824712868223000,2,292000,6824712868515000,4,"S",120,5,"UsbFfs-worker",20308
-6824712868226000,1,78000,6824712868304000,2,"S",100,2,"kworker/u17:1",1134
-6824712868304000,1,48000,6824712868352000,77,"R+",120,63,"kworker/1:0",19220
-6824712868352000,1,57000,6824712868409000,2,"S",100,2,"kworker/u17:1",1134
-6824712868409000,1,45000,6824712868454000,77,"R+",120,63,"kworker/1:0",19220
-6824712868454000,1,72000,6824712868526000,2,"S",100,2,"kworker/u17:1",1134
-6824712868515000,2,145000,6824712868660000,7,"S",120,5,"adbd",20305
-6824712868526000,1,257000,6824712868783000,77,"S",120,63,"kworker/1:0",19220
-6824712868660000,2,454000,6824712869114000,4,"S",120,5,"UsbFfs-worker",20308
-6824712868783000,1,1322000,6824712870105000,0,"R",120,"[NULL]","swapper/5",0
-6824712869114000,2,770000,6824712869884000,7,"S",120,5,"adbd",20305
-6824712869884000,2,197000,6824712870081000,75,"R+",120,61,"sh",20457
-6824712870081000,2,56000,6824712870137000,6,"S",120,4,"rcu_preempt",7
-6824712870105000,1,117000,6824712870222000,2,"S",100,2,"kworker/u17:1",1134
-6824712870137000,2,41000,6824712870178000,5,"S",120,7,"rcu_sched",8
-6824712870178000,2,153000,6824712870331000,75,"R+",120,61,"sh",20457
-6824712870222000,1,113000,6824712870335000,77,"R+",120,63,"kworker/1:0",19220
-6824712870331000,2,69000,6824712870400000,4,"S",120,5,"UsbFfs-worker",20308
-6824712870335000,1,43000,6824712870378000,2,"S",100,2,"kworker/u17:1",1134
-6824712870378000,1,66000,6824712870444000,77,"S",120,63,"kworker/1:0",19220
-6824712870400000,2,6436000,6824712876836000,75,"R+",120,61,"sh",20457
-6824712870444000,1,20085000,6824712890529000,0,"R",120,"[NULL]","swapper/5",0
-6824712873102000,7,72000,6824712873174000,76,"S",120,62,"hwrng",215
-6824712873174000,7,5793000,6824712878967000,0,"R",120,"[NULL]","swapper/5",0
-6824712876836000,2,146000,6824712876982000,5,"S",120,7,"rcu_sched",8
-6824712876982000,2,88000,6824712877070000,6,"S",120,4,"rcu_preempt",7
-6824712877070000,2,86000,6824712877156000,23,"S",120,21,"rcuop/2",28
-6824712877156000,2,40000,6824712877196000,6,"S",120,4,"rcu_preempt",7
-6824712877196000,2,374000,6824712877570000,78,"R",120,5,"shell",20458
-6824712877300000,0,156000,6824712877456000,16,"S",120,14,"kworker/u16:7",19422
-6824712877419000,3,189000,6824712877608000,20,"S",120,18,"rcuos/2",29
-6824712877456000,0,6419000,6824712883875000,0,"R",120,"[NULL]","swapper/5",0
-6824712877570000,2,32000,6824712877602000,5,"S",120,7,"rcu_sched",8
-6824712877602000,2,441000,6824712878043000,78,"S",120,5,"shell",20458
-6824712877608000,3,13785000,6824712891393000,0,"R",120,"[NULL]","swapper/5",0
-6824712878043000,2,5493000,6824712883536000,75,"R+",120,61,"sh",20457
-6824712878967000,7,74000,6824712879041000,76,"S",120,62,"hwrng",215
-6824712879041000,7,22599000,6824712901640000,0,"R",120,"[NULL]","swapper/5",0
-6824712883536000,2,224000,6824712883760000,26,"S",49,23,"sugov:0",605
-6824712883760000,2,7130000,6824712890890000,75,"R",120,61,"sh",20457
-6824712883875000,0,37000,6824712883912000,5,"S",120,7,"rcu_sched",8
-6824712883912000,0,38000,6824712883950000,6,"S",120,4,"rcu_preempt",7
-6824712883950000,0,6876000,6824712890826000,0,"R",120,"[NULL]","swapper/5",0
-6824712890529000,1,61000,6824712890590000,48,"S",120,41,"kworker/1:1",18800
-6824712890590000,1,2884000,6824712893474000,0,"R",120,"[NULL]","swapper/5",0
-6824712890826000,0,72000,6824712890898000,6,"S",120,4,"rcu_preempt",7
-6824712890890000,2,188000,6824712891078000,23,"S",120,21,"rcuop/2",28
-6824712890898000,0,80000,6824712890978000,5,"S",120,7,"rcu_sched",8
-6824712890978000,0,595000,6824712891573000,0,"R",120,"[NULL]","swapper/5",0
-6824712891078000,2,5651000,6824712896729000,75,"R",120,61,"sh",20457
-6824712891393000,3,58000,6824712891451000,20,"S",120,18,"rcuos/2",29
-6824712891451000,3,4407000,6824712895858000,0,"R",120,"[NULL]","swapper/5",0
-6824712891573000,0,40000,6824712891613000,6,"S",120,4,"rcu_preempt",7
-6824712891613000,0,803000,6824712892416000,0,"R",120,"[NULL]","swapper/5",0
-6824712892416000,0,105000,6824712892521000,46,"S",120,39,"kworker/0:1",19511
-6824712892521000,0,800000,6824712893321000,36,"S",111,34,"SDM_EventThread",685
-6824712893321000,0,850000,6824712894171000,0,"R",120,"[NULL]","swapper/5",0
-6824712893474000,1,566000,6824712894040000,38,"S",120,35,"HwBinder:640_1",721
-6824712894040000,1,1068000,6824712895108000,0,"R",120,"[NULL]","swapper/5",0
-6824712894171000,0,111000,6824712894282000,40,"S",97,35,"DispSync",676
-6824712894282000,0,714000,6824712894996000,0,"R",120,"[NULL]","swapper/5",0
-6824712894996000,0,140000,6824712895136000,40,"S",97,35,"DispSync",676
-6824712895108000,1,410000,6824712895518000,41,"S",97,35,"app",678
-6824712895136000,0,301000,6824712895437000,0,"R",120,"[NULL]","swapper/5",0
-6824712895437000,0,1223000,6824712896660000,42,"R",120,36,"ndroid.systemui",1664
-6824712895518000,1,2511000,6824712898029000,0,"R",120,"[NULL]","swapper/5",0
-6824712895858000,3,55000,6824712895913000,40,"S",97,35,"DispSync",676
-6824712895913000,3,20866000,6824712916779000,0,"R",120,"[NULL]","swapper/5",0
-6824712896660000,0,76000,6824712896736000,6,"S",120,4,"rcu_preempt",7
-6824712896729000,2,38000,6824712896767000,23,"S",120,21,"rcuop/2",28
-6824712896736000,0,1181000,6824712897917000,42,"S",120,36,"ndroid.systemui",1664
-6824712896767000,2,3122000,6824712899889000,75,"R",120,61,"sh",20457
-6824712897917000,0,362000,6824712898279000,0,"R",120,"[NULL]","swapper/5",0
-6824712898029000,1,330000,6824712898359000,43,"S",120,35,"Binder:640_2",675
-6824712898279000,0,181000,6824712898460000,41,"S",97,35,"app",678
-6824712898359000,1,40000,6824712898399000,0,"R",120,"[NULL]","swapper/5",0
-6824712898399000,1,53000,6824712898452000,40,"S",97,35,"DispSync",676
-6824712898452000,1,28312000,6824712926764000,0,"R",120,"[NULL]","swapper/5",0
-6824712898460000,0,1923000,6824712900383000,0,"R",120,"[NULL]","swapper/5",0
-6824712899889000,2,124000,6824712900013000,23,"S",120,21,"rcuop/2",28
-6824712900013000,2,3333000,6824712903346000,75,"R",120,61,"sh",20457
-6824712900383000,0,51000,6824712900434000,6,"S",120,4,"rcu_preempt",7
-6824712900434000,0,6845000,6824712907279000,0,"R",120,"[NULL]","swapper/5",0
-6824712901640000,7,72000,6824712901712000,76,"S",120,62,"hwrng",215
-6824712901712000,7,80781000,6824712982493000,0,"R",120,"[NULL]","swapper/5",0
-6824712903346000,2,197000,6824712903543000,26,"S",49,23,"sugov:0",605
-6824712903543000,2,3857000,6824712907400000,75,"R",120,61,"sh",20457
-6824712907279000,0,57000,6824712907336000,35,"S",120,33,"kworker/0:5",20371
-6824712907336000,0,77000,6824712907413000,6,"S",120,4,"rcu_preempt",7
-6824712907400000,2,66000,6824712907466000,23,"S",120,21,"rcuop/2",28
-6824712907413000,0,51000,6824712907464000,0,"R",120,"[NULL]","swapper/5",0
-6824712907464000,0,27000,6824712907491000,6,"S",120,4,"rcu_preempt",7
-6824712907466000,2,180000,6824712907646000,75,"R+",120,61,"sh",20457
-6824712907491000,0,6442000,6824712913933000,0,"R",120,"[NULL]","swapper/5",0
-6824712907646000,2,198000,6824712907844000,78,"S",120,5,"shell",20458
-6824712907844000,2,962000,6824712908806000,7,"R+",120,5,"adbd",20305
-6824712908806000,2,188000,6824712908994000,2,"S",100,2,"kworker/u17:1",1134
-6824712908994000,2,81000,6824712909075000,31,"S",120,29,"kworker/2:0",18823
-6824712909075000,2,25000,6824712909100000,79,"S",100,64,"kworker/u17:2",14944
-6824712909100000,2,79000,6824712909179000,4,"S",120,5,"UsbFfs-worker",20308
-6824712909179000,2,99000,6824712909278000,7,"R+",120,5,"adbd",20305
-6824712909278000,2,50000,6824712909328000,79,"S",100,64,"kworker/u17:2",14944
-6824712909328000,2,49000,6824712909377000,31,"R+",120,29,"kworker/2:0",18823
-6824712909377000,2,21000,6824712909398000,79,"S",100,64,"kworker/u17:2",14944
-6824712909398000,2,10000,6824712909408000,31,"S",120,29,"kworker/2:0",18823
-6824712909408000,2,164000,6824712909572000,7,"R+",120,5,"adbd",20305
-6824712909572000,2,42000,6824712909614000,79,"S",100,64,"kworker/u17:2",14944
-6824712909614000,2,53000,6824712909667000,7,"R+",120,5,"adbd",20305
-6824712909667000,2,62000,6824712909729000,79,"S",100,64,"kworker/u17:2",14944
-6824712909729000,2,88000,6824712909817000,7,"S",120,5,"adbd",20305
-6824712909817000,2,183000,6824712910000000,4,"S",120,5,"UsbFfs-worker",20308
-6824712910000000,2,101000,6824712910101000,31,"S",120,29,"kworker/2:0",18823
-6824712910101000,2,40000,6824712910141000,4,"R",120,5,"UsbFfs-worker",20308
-6824712910141000,2,36000,6824712910177000,79,"S",100,64,"kworker/u17:2",14944
-6824712910177000,2,35000,6824712910212000,4,"R",120,5,"UsbFfs-worker",20308
-6824712910212000,2,56000,6824712910268000,79,"S",100,64,"kworker/u17:2",14944
-6824712910268000,2,37000,6824712910305000,31,"R",120,29,"kworker/2:0",18823
-6824712910305000,2,35000,6824712910340000,79,"S",100,64,"kworker/u17:2",14944
-6824712910340000,2,34000,6824712910374000,31,"R",120,29,"kworker/2:0",18823
-6824712910374000,2,46000,6824712910420000,79,"S",100,64,"kworker/u17:2",14944
-6824712910420000,2,78000,6824712910498000,31,"S",120,29,"kworker/2:0",18823
-6824712910498000,2,292000,6824712910790000,4,"S",120,5,"UsbFfs-worker",20308
-6824712910790000,2,280000,6824712911070000,7,"R+",120,5,"adbd",20305
-6824712911070000,2,92000,6824712911162000,79,"S",100,64,"kworker/u17:2",14944
-6824712911162000,2,10000,6824712911172000,2,"S",100,2,"kworker/u17:1",1134
-6824712911172000,2,47000,6824712911219000,7,"R",120,5,"adbd",20305
-6824712911219000,2,22000,6824712911241000,2,"S",100,2,"kworker/u17:1",1134
-6824712911241000,2,85000,6824712911326000,7,"S",120,5,"adbd",20305
-6824712911326000,2,112000,6824712911438000,78,"S",120,5,"shell",20458
-6824712911438000,2,42000,6824712911480000,31,"S",120,29,"kworker/2:0",18823
-6824712911480000,2,22000,6824712911502000,4,"S",120,5,"UsbFfs-worker",20308
-6824712911502000,2,2059000,6824712913561000,75,"S",120,61,"sh",20457
-6824712913561000,2,431000,6824712913992000,80,"R+",120,65,"sh",20459
-6824712913933000,0,84000,6824712914017000,6,"S",120,4,"rcu_preempt",7
-6824712913992000,2,65000,6824712914057000,23,"S",120,21,"rcuop/2",28
-6824712914017000,0,1135000,6824712915152000,0,"R",120,"[NULL]","swapper/5",0
-6824712914057000,2,670000,6824712914727000,80,"R+",120,65,"sh",20459
-6824712914727000,2,46000,6824712914773000,23,"S",120,21,"rcuop/2",28
-6824712914773000,2,1850000,6824712916623000,80,"R+",120,65,"sh",20459
-6824712915152000,0,39000,6824712915191000,6,"S",120,4,"rcu_preempt",7
-6824712915191000,0,2005000,6824712917196000,0,"R",120,"[NULL]","swapper/5",0
-6824712916623000,2,1909000,6824712918532000,75,"x",120,61,"sh",20457
-6824712916779000,3,89000,6824712916868000,20,"S",120,18,"rcuos/2",29
-6824712916868000,3,6871000,6824712923739000,0,"R",120,"[NULL]","swapper/5",0
-6824712917196000,0,38000,6824712917234000,5,"S",120,7,"rcu_sched",8
-6824712917234000,0,3105000,6824712920339000,0,"R",120,"[NULL]","swapper/5",0
-6824712918532000,2,938000,6824712919470000,78,"x",120,5,"shell",20458
-6824712919470000,2,1271000,6824712920741000,7,"S",120,5,"adbd",20305
-6824712920339000,0,118000,6824712920457000,2,"S",100,2,"kworker/u17:1",1134
-6824712920457000,0,98000,6824712920555000,35,"S",120,33,"kworker/0:5",20371
-6824712920555000,0,67000,6824712920622000,4,"S",120,5,"UsbFfs-worker",20308
-6824712920622000,0,44000,6824712920666000,2,"S",100,2,"kworker/u17:1",1134
-6824712920666000,0,83000,6824712920749000,6,"S",120,4,"rcu_preempt",7
-6824712920741000,2,90000,6824712920831000,23,"S",120,21,"rcuop/2",28
-6824712920749000,0,63000,6824712920812000,0,"R",120,"[NULL]","swapper/5",0
-6824712920812000,0,59000,6824712920871000,2,"S",100,2,"kworker/u17:1",1134
-6824712920831000,2,100000,6824712920931000,80,"R+",120,65,"sh",20459
-6824712920871000,0,56000,6824712920927000,35,"R+",120,33,"kworker/0:5",20371
-6824712920927000,0,28000,6824712920955000,2,"S",100,2,"kworker/u17:1",1134
-6824712920931000,2,327000,6824712921258000,26,"S",49,23,"sugov:0",605
-6824712920955000,0,8000,6824712920963000,35,"S",120,33,"kworker/0:5",20371
-6824712920963000,0,23000,6824712920986000,4,"R",120,5,"UsbFfs-worker",20308
-6824712920986000,0,40000,6824712921026000,2,"S",100,2,"kworker/u17:1",1134
-6824712921026000,0,41000,6824712921067000,4,"S",120,5,"UsbFfs-worker",20308
-6824712921067000,0,15000,6824712921082000,6,"R+",120,4,"rcu_preempt",7
-6824712921082000,0,68000,6824712921150000,2,"S",100,2,"kworker/u17:1",1134
-6824712921150000,0,50000,6824712921200000,35,"R+",120,33,"kworker/0:5",20371
-6824712921200000,0,48000,6824712921248000,2,"S",100,2,"kworker/u17:1",1134
-6824712921248000,0,48000,6824712921296000,35,"R+",120,33,"kworker/0:5",20371
-6824712921258000,2,54000,6824712921312000,80,"x",120,65,"sh",20459
-6824712921296000,0,38000,6824712921334000,2,"S",100,2,"kworker/u17:1",1134
-6824712921312000,2,8350000,6824712929662000,0,"R",120,"[NULL]","swapper/5",0
-6824712921334000,0,41000,6824712921375000,35,"S",120,33,"kworker/0:5",20371
-6824712921375000,0,204000,6824712921579000,4,"S",120,5,"UsbFfs-worker",20308
-6824712921579000,0,177000,6824712921756000,7,"S",120,5,"adbd",20305
-6824712921756000,0,15000,6824712921771000,6,"S",120,4,"rcu_preempt",7
-6824712921771000,0,337000,6824712922108000,0,"R",120,"[NULL]","swapper/5",0
-6824712922108000,0,39000,6824712922147000,2,"S",100,2,"kworker/u17:1",1134
-6824712922147000,0,31000,6824712922178000,35,"S",120,33,"kworker/0:5",20371
-6824712922178000,0,23000,6824712922201000,4,"S",120,5,"UsbFfs-worker",20308
-6824712922201000,0,1099000,6824712923300000,0,"R",120,"[NULL]","swapper/5",0
-6824712923300000,0,66000,6824712923366000,5,"S",120,7,"rcu_sched",8
-6824712923366000,0,2472000,6824712925838000,0,"R",120,"[NULL]","swapper/5",0
-6824712923739000,3,108000,6824712923847000,20,"S",120,18,"rcuos/2",29
-6824712923847000,3,21000,6824712923868000,5,"S",120,7,"rcu_sched",8
-6824712923868000,3,6431000,6824712930299000,0,"R",120,"[NULL]","swapper/5",0
-6824712925838000,0,33000,6824712925871000,35,"R+",120,33,"kworker/0:5",20371
-6824712925871000,0,645000,6824712926516000,36,"S",111,34,"SDM_EventThread",685
-6824712926516000,0,30000,6824712926546000,35,"S",120,33,"kworker/0:5",20371
-6824712926546000,0,967000,6824712927513000,0,"R",120,"[NULL]","swapper/5",0
-6824712926764000,1,82000,6824712926846000,16,"S",120,14,"kworker/u16:7",19422
-6824712926846000,1,16000,6824712926862000,6,"S",120,4,"rcu_preempt",7
-6824712926862000,1,489000,6824712927351000,38,"S",120,35,"HwBinder:640_1",721
-6824712927351000,1,1624000,6824712928975000,0,"R",120,"[NULL]","swapper/5",0
-6824712927513000,0,89000,6824712927602000,40,"S",97,35,"DispSync",676
-6824712927602000,0,969000,6824712928571000,0,"R",120,"[NULL]","swapper/5",0
-6824712928571000,0,92000,6824712928663000,40,"S",97,35,"DispSync",676
-6824712928663000,0,909000,6824712929572000,0,"R",120,"[NULL]","swapper/5",0
-6824712928975000,1,295000,6824712929270000,41,"S",97,35,"app",678
-6824712929270000,1,2298000,6824712931568000,0,"R",120,"[NULL]","swapper/5",0
-6824712929572000,0,1853000,6824712931425000,42,"S",120,36,"ndroid.systemui",1664
-6824712929662000,2,29000,6824712929691000,40,"S",97,35,"DispSync",676
-6824712929691000,2,2432000,6824712932123000,0,"R",120,"[NULL]","swapper/5",0
-6824712930299000,3,39000,6824712930338000,5,"S",120,7,"rcu_sched",8
-6824712930338000,3,37000,6824712930375000,20,"S",120,18,"rcuos/2",29
-6824712930375000,3,34073000,6824712964448000,0,"R",120,"[NULL]","swapper/5",0
-6824712931425000,0,319000,6824712931744000,0,"R",120,"[NULL]","swapper/5",0
-6824712931568000,1,223000,6824712931791000,43,"S",120,35,"Binder:640_2",675
-6824712931744000,0,102000,6824712931846000,41,"S",97,35,"app",678
-6824712931791000,1,1518000,6824712933309000,0,"R",120,"[NULL]","swapper/5",0
-6824712931846000,0,29956000,6824712961802000,0,"R",120,"[NULL]","swapper/5",0
-6824712932123000,2,33000,6824712932156000,40,"S",97,35,"DispSync",676
-6824712932156000,2,1529000,6824712933685000,0,"R",120,"[NULL]","swapper/5",0
-6824712933309000,1,55000,6824712933364000,6,"S",120,4,"rcu_preempt",7
-6824712933364000,1,935000,6824712934299000,0,"R",120,"[NULL]","swapper/5",0
-6824712933685000,2,248000,6824712933933000,23,"S",120,21,"rcuop/2",28
-6824712933933000,2,27866000,6824712961799000,0,"R",120,"[NULL]","swapper/5",0
-6824712934299000,1,19000,6824712934318000,6,"S",120,4,"rcu_preempt",7
-6824712934318000,1,7968000,6824712942286000,0,"R",120,"[NULL]","swapper/5",0
-6824712942286000,1,302000,6824712942588000,26,"S",49,23,"sugov:0",605
-6824712942588000,1,197000,6824712942785000,6,"S",120,4,"rcu_preempt",7
-6824712942785000,1,171000,6824712942956000,23,"S",120,21,"rcuop/2",28
-6824712942956000,1,19657000,6824712962613000,0,"R",120,"[NULL]","swapper/5",0
-6824712961799000,2,620000,6824712962419000,25,"S",120,24,"ksoftirqd/2",25
-6824712961802000,0,176000,6824712961978000,35,"S",120,33,"kworker/0:5",20371
-6824712961978000,0,108000,6824712962086000,2,"S",100,2,"kworker/u17:1",1134
-6824712962086000,0,239000,6824712962325000,36,"R+",111,34,"SDM_EventThread",685
-6824712962325000,0,174000,6824712962499000,2,"S",100,2,"kworker/u17:1",1134
-6824712962419000,2,165000,6824712962584000,31,"S",120,29,"kworker/2:0",18823
-6824712962499000,0,997000,6824712963496000,16,"S",120,14,"kworker/u16:7",19422
-6824712962584000,2,967000,6824712963551000,0,"R",120,"[NULL]","swapper/5",0
-6824712962613000,1,435000,6824712963048000,40,"S",97,35,"DispSync",676
-6824712963048000,1,140000,6824712963188000,2,"S",100,2,"kworker/u17:1",1134
-6824712963188000,1,505000,6824712963693000,48,"S",120,41,"kworker/1:1",18800
-6824712963496000,0,688000,6824712964184000,36,"S",111,34,"SDM_EventThread",685
-6824712963551000,2,518000,6824712964069000,41,"S",97,35,"app",678
-6824712963693000,1,156000,6824712963849000,4,"S",120,5,"UsbFfs-worker",20308
-6824712963849000,1,66000,6824712963915000,0,"R",120,"[NULL]","swapper/5",0
-6824712963915000,1,403000,6824712964318000,42,"R",120,36,"ndroid.systemui",1664
-6824712964069000,2,11256000,6824712975325000,0,"R",120,"[NULL]","swapper/5",0
-6824712964184000,0,198000,6824712964382000,35,"S",120,33,"kworker/0:5",20371
-6824712964318000,1,572000,6824712964890000,4,"S",120,5,"UsbFfs-worker",20308
-6824712964382000,0,882000,6824712965264000,0,"R",120,"[NULL]","swapper/5",0
-6824712964448000,3,67000,6824712964515000,40,"S",97,35,"DispSync",676
-6824712964515000,3,578000,6824712965093000,38,"S",120,35,"HwBinder:640_1",721
-6824712964890000,1,6507000,6824712971397000,7,"S",120,5,"adbd",20305
-6824712965093000,3,29801000,6824712994894000,0,"R",120,"[NULL]","swapper/5",0
-6824712965264000,0,98000,6824712965362000,40,"S",97,35,"DispSync",676
-6824712965362000,0,9149000,6824712974511000,0,"R",120,"[NULL]","swapper/5",0
-6824712971397000,1,2878000,6824712974275000,42,"S",120,36,"ndroid.systemui",1664
-6824712974275000,1,2508000,6824712976783000,81,"R+",120,66,"sh",20460
-6824712974511000,0,515000,6824712975026000,43,"S",120,35,"Binder:640_2",675
-6824712975026000,0,904000,6824712975930000,0,"R",120,"[NULL]","swapper/5",0
-6824712975325000,2,324000,6824712975649000,41,"S",97,35,"app",678
-6824712975649000,2,11143000,6824712986792000,0,"R",120,"[NULL]","swapper/5",0
-6824712975930000,0,113000,6824712976043000,40,"S",97,35,"DispSync",676
-6824712976043000,0,5748000,6824712981791000,0,"R",120,"[NULL]","swapper/5",0
-6824712976783000,1,140000,6824712976923000,16,"S",120,14,"kworker/u16:7",19422
-6824712976923000,1,2388000,6824712979311000,81,"R+",120,66,"sh",20460
-6824712979311000,1,127000,6824712979438000,14,"S",120,10,"rcuos/0",11
-6824712979438000,1,54000,6824712979492000,5,"S",120,7,"rcu_sched",8
-6824712979492000,1,1949000,6824712981441000,81,"R+",120,66,"sh",20460
-6824712981441000,1,88000,6824712981529000,11,"S",120,9,"rcuop/0",10
-6824712981529000,1,40000,6824712981569000,6,"S",120,4,"rcu_preempt",7
-6824712981569000,1,1127000,6824712982696000,81,"R+",120,66,"sh",20460
-6824712981791000,0,2438000,6824712984229000,7,"S",120,5,"adbd",20305
-6824712982493000,7,74000,6824712982567000,76,"S",120,62,"hwrng",215
-6824712982567000,7,268581000,6824713251148000,0,"R",120,"[NULL]","swapper/5",0
-6824712982696000,1,31000,6824712982727000,76,"S",120,62,"hwrng",215
-6824712982727000,1,630000,6824712983357000,81,"R",120,66,"sh",20460
-6824712983357000,1,58000,6824712983415000,5,"S",120,7,"rcu_sched",8
-6824712983415000,1,820000,6824712984235000,81,"R+",120,66,"sh",20460
-6824712984229000,0,571000,6824712984800000,82,"S",120,5,"shell",20461
-6824712984235000,1,175000,6824712984410000,2,"S",100,2,"kworker/u17:1",1134
-6824712984410000,1,138000,6824712984548000,48,"S",120,41,"kworker/1:1",18800
-6824712984548000,1,27000,6824712984575000,76,"S",120,62,"hwrng",215
-6824712984575000,1,155000,6824712984730000,4,"S",120,5,"UsbFfs-worker",20308
-6824712984730000,1,290000,6824712985020000,81,"R+",120,66,"sh",20460
-6824712984800000,0,3033000,6824712987833000,0,"R",120,"[NULL]","swapper/5",0
-6824712985020000,1,73000,6824712985093000,2,"S",100,2,"kworker/u17:1",1134
-6824712985093000,1,600000,6824712985693000,81,"R+",120,66,"sh",20460
-6824712985693000,1,141000,6824712985834000,2,"S",100,2,"kworker/u17:1",1134
-6824712985834000,1,51000,6824712985885000,48,"R+",120,41,"kworker/1:1",18800
-6824712985885000,1,79000,6824712985964000,2,"S",100,2,"kworker/u17:1",1134
-6824712985964000,1,186000,6824712986150000,48,"S",120,41,"kworker/1:1",18800
-6824712986150000,1,639000,6824712986789000,4,"R+",120,5,"UsbFfs-worker",20308
-6824712986789000,1,238000,6824712987027000,26,"S",49,23,"sugov:0",605
-6824712986792000,2,82000,6824712986874000,6,"S",120,4,"rcu_preempt",7
-6824712986874000,2,6897000,6824712993771000,0,"R",120,"[NULL]","swapper/5",0
-6824712987027000,1,358000,6824712987385000,7,"S",120,5,"adbd",20305
-6824712987385000,1,192000,6824712987577000,4,"S",120,5,"UsbFfs-worker",20308
-6824712987577000,1,951000,6824712988528000,81,"R+",120,66,"sh",20460
-6824712987833000,0,421000,6824712988254000,7,"S",120,5,"adbd",20305
-6824712988254000,0,185000,6824712988439000,82,"S",120,5,"shell",20461
-6824712988439000,0,4499000,6824712992938000,0,"R",120,"[NULL]","swapper/5",0
-6824712988528000,1,87000,6824712988615000,2,"S",100,2,"kworker/u17:1",1134
-6824712988615000,1,69000,6824712988684000,48,"S",120,41,"kworker/1:1",18800
-6824712988684000,1,65000,6824712988749000,4,"S",120,5,"UsbFfs-worker",20308
-6824712988749000,1,1248000,6824712989997000,81,"R",120,66,"sh",20460
-6824712989997000,1,90000,6824712990087000,5,"S",120,7,"rcu_sched",8
-6824712990087000,1,92000,6824712990179000,14,"S",120,10,"rcuos/0",11
-6824712990179000,1,76000,6824712990255000,15,"S",120,13,"rcuos/1",21
-6824712990255000,1,24000,6824712990279000,5,"S",120,7,"rcu_sched",8
-6824712990279000,1,2760000,6824712993039000,81,"R+",120,66,"sh",20460
-6824712992938000,0,152000,6824712993090000,35,"S",120,33,"kworker/0:5",20371
-6824712993039000,1,804000,6824712993843000,36,"S",111,34,"SDM_EventThread",685
-6824712993090000,0,998000,6824712994088000,0,"R",120,"[NULL]","swapper/5",0
-6824712993771000,2,89000,6824712993860000,6,"S",120,4,"rcu_preempt",7
-6824712993843000,1,145000,6824712993988000,11,"S",120,9,"rcuop/0",10
-6824712993860000,2,587000,6824712994447000,0,"R",120,"[NULL]","swapper/5",0
-6824712993988000,1,34000,6824712994022000,13,"S",120,12,"rcuop/1",20
-6824712994022000,1,2637000,6824712996659000,81,"R",120,66,"sh",20460
-6824712994088000,0,576000,6824712994664000,38,"S",120,35,"HwBinder:640_1",721
-6824712994447000,2,41000,6824712994488000,6,"S",120,4,"rcu_preempt",7
-6824712994488000,2,1596000,6824712996084000,0,"R",120,"[NULL]","swapper/5",0
-6824712994664000,0,752000,6824712995416000,0,"R",120,"[NULL]","swapper/5",0
-6824712994894000,3,230000,6824712995124000,40,"S",97,35,"DispSync",676
-6824712995124000,3,1089000,6824712996213000,0,"R",120,"[NULL]","swapper/5",0
-6824712995416000,0,388000,6824712995804000,41,"S",97,35,"app",678
-6824712995804000,0,2854000,6824712998658000,0,"R",120,"[NULL]","swapper/5",0
-6824712996084000,2,2507000,6824712998591000,42,"S",120,36,"ndroid.systemui",1664
-6824712996213000,3,61000,6824712996274000,40,"S",97,35,"DispSync",676
-6824712996274000,3,31193000,6824713027467000,0,"R",120,"[NULL]","swapper/5",0
-6824712996659000,1,76000,6824712996735000,5,"S",120,7,"rcu_sched",8
-6824712996735000,1,52000,6824712996787000,14,"S",120,10,"rcuos/0",11
-6824712996787000,1,28000,6824712996815000,15,"S",120,13,"rcuos/1",21
-6824712996815000,1,3192000,6824713000007000,81,"R+",120,66,"sh",20460
-6824712998591000,2,346000,6824712998937000,0,"R",120,"[NULL]","swapper/5",0
-6824712998658000,0,379000,6824712999037000,43,"S",120,35,"Binder:640_2",675
-6824712998937000,2,202000,6824712999139000,41,"S",97,35,"app",678
-6824712999037000,0,34000,6824712999071000,0,"R",120,"[NULL]","swapper/5",0
-6824712999071000,0,62000,6824712999133000,40,"S",97,35,"DispSync",676
-6824712999133000,0,22793000,6824713021926000,0,"R",120,"[NULL]","swapper/5",0
-6824712999139000,2,28073000,6824713027212000,0,"R",120,"[NULL]","swapper/5",0
-6824713000007000,1,107000,6824713000114000,6,"S",120,4,"rcu_preempt",7
-6824713000114000,1,92000,6824713000206000,11,"S",120,9,"rcuop/0",10
-6824713000206000,1,61000,6824713000267000,13,"S",120,12,"rcuop/1",20
-6824713000267000,1,3074000,6824713003341000,81,"R",120,66,"sh",20460
-6824713003341000,1,209000,6824713003550000,26,"S",49,23,"sugov:0",605
-6824713003550000,1,7239000,6824713010789000,81,"R",120,66,"sh",20460
-6824713010789000,1,52000,6824713010841000,11,"S",120,9,"rcuop/0",10
-6824713010841000,1,35000,6824713010876000,6,"S",120,4,"rcu_preempt",7
-6824713010876000,1,95000,6824713010971000,81,"R+",120,66,"sh",20460
-6824713010971000,1,26000,6824713010997000,76,"S",120,62,"hwrng",215
-6824713010997000,1,5636000,6824713016633000,81,"R",120,66,"sh",20460
-6824713016633000,1,67000,6824713016700000,6,"S",120,4,"rcu_preempt",7
-6824713016700000,1,66000,6824713016766000,11,"S",120,9,"rcuop/0",10
-6824713016766000,1,36000,6824713016802000,13,"S",120,12,"rcuop/1",20
-6824713016802000,1,12000,6824713016814000,6,"S",120,4,"rcu_preempt",7
-6824713016814000,1,1724000,6824713018538000,81,"S",120,66,"sh",20460
-6824713018538000,1,2161000,6824713020699000,83,"R+",120,67,"sh",20462
-6824713020699000,1,225000,6824713020924000,26,"S",49,23,"sugov:0",605
-6824713020924000,1,273000,6824713021197000,83,"S",120,67,"sh",20462
-6824713021197000,1,5881000,6824713027078000,0,"R",120,"[NULL]","swapper/5",0
-6824713021926000,0,1729000,6824713023655000,84,"R+",120,68,"ps",20463
-6824713023655000,0,62000,6824713023717000,14,"S",120,10,"rcuos/0",11
-6824713023717000,0,29000,6824713023746000,5,"S",120,7,"rcu_sched",8
-6824713023746000,0,29000,6824713023775000,84,"R+",120,68,"ps",20463
-6824713023775000,0,30000,6824713023805000,6,"S",120,4,"rcu_preempt",7
-6824713023805000,0,413000,6824713024218000,84,"R+",120,68,"ps",20463
-6824713024218000,0,23000,6824713024241000,76,"S",120,62,"hwrng",215
-6824713024241000,0,556000,6824713024797000,84,"R+",120,68,"ps",20463
-6824713024797000,0,9000,6824713024806000,76,"S",120,62,"hwrng",215
-6824713024806000,0,1217000,6824713026023000,84,"R+",120,68,"ps",20463
-6824713026023000,0,91000,6824713026114000,35,"S",120,33,"kworker/0:5",20371
-6824713026114000,0,814000,6824713026928000,36,"S",111,34,"SDM_EventThread",685
-6824713026928000,0,45000,6824713026973000,6,"S",120,4,"rcu_preempt",7
-6824713026973000,0,263000,6824713027236000,84,"R+",120,68,"ps",20463
-6824713027078000,1,93000,6824713027171000,16,"S",120,14,"kworker/u16:7",19422
-6824713027171000,1,67000,6824713027238000,11,"S",120,9,"rcuop/0",10
-6824713027212000,2,447000,6824713027659000,38,"S",120,35,"HwBinder:640_1",721
-6824713027236000,0,14000,6824713027250000,6,"S",120,4,"rcu_preempt",7
-6824713027238000,1,61000,6824713027299000,13,"S",120,12,"rcuop/1",20
-6824713027250000,0,2732000,6824713029982000,84,"R",120,68,"ps",20463
-6824713027299000,1,655000,6824713027954000,0,"R",120,"[NULL]","swapper/5",0
-6824713027467000,3,179000,6824713027646000,40,"S",97,35,"DispSync",676
-6824713027646000,3,1029000,6824713028675000,0,"R",120,"[NULL]","swapper/5",0
-6824713027659000,2,901000,6824713028560000,0,"R",120,"[NULL]","swapper/5",0
-6824713027954000,1,314000,6824713028268000,41,"S",97,35,"app",678
-6824713028268000,1,2352000,6824713030620000,0,"R",120,"[NULL]","swapper/5",0
-6824713028560000,2,1914000,6824713030474000,42,"S",120,36,"ndroid.systemui",1664
-6824713028675000,3,34000,6824713028709000,40,"S",97,35,"DispSync",676
-6824713028709000,3,34349000,6824713063058000,0,"R",120,"[NULL]","swapper/5",0
-6824713029982000,0,33000,6824713030015000,5,"S",120,7,"rcu_sched",8
-6824713030015000,0,3308000,6824713033323000,84,"R+",120,68,"ps",20463
-6824713030474000,2,705000,6824713031179000,0,"R",120,"[NULL]","swapper/5",0
-6824713030620000,1,274000,6824713030894000,43,"S",120,35,"Binder:640_2",675
-6824713030894000,1,696000,6824713031590000,0,"R",120,"[NULL]","swapper/5",0
-6824713031179000,2,137000,6824713031316000,41,"S",97,35,"app",678
-6824713031316000,2,29313000,6824713060629000,0,"R",120,"[NULL]","swapper/5",0
-6824713031590000,1,43000,6824713031633000,40,"S",97,35,"DispSync",676
-6824713031633000,1,2153000,6824713033786000,0,"R",120,"[NULL]","swapper/5",0
-6824713033323000,0,89000,6824713033412000,6,"S",120,4,"rcu_preempt",7
-6824713033412000,0,86000,6824713033498000,11,"S",120,9,"rcuop/0",10
-6824713033498000,0,13000,6824713033511000,6,"S",120,4,"rcu_preempt",7
-6824713033511000,0,3137000,6824713036648000,84,"R",120,68,"ps",20463
-6824713033786000,1,36000,6824713033822000,13,"S",120,12,"rcuop/1",20
-6824713033822000,1,6659000,6824713040481000,0,"R",120,"[NULL]","swapper/5",0
-6824713036648000,0,56000,6824713036704000,5,"S",120,7,"rcu_sched",8
-6824713036704000,0,54000,6824713036758000,14,"S",120,10,"rcuos/0",11
-6824713036758000,0,10000,6824713036768000,5,"S",120,7,"rcu_sched",8
-6824713036768000,0,6593000,6824713043361000,84,"R",120,68,"ps",20463
-6824713040481000,1,46000,6824713040527000,6,"S",120,4,"rcu_preempt",7
-6824713040527000,1,3210000,6824713043737000,0,"R",120,"[NULL]","swapper/5",0
-6824713043361000,0,195000,6824713043556000,26,"S",49,23,"sugov:0",605
-6824713043556000,0,3032000,6824713046588000,84,"R",120,68,"ps",20463
-6824713043737000,1,36000,6824713043773000,5,"S",120,7,"rcu_sched",8
-6824713043773000,1,3242000,6824713047015000,0,"R",120,"[NULL]","swapper/5",0
-6824713046588000,0,37000,6824713046625000,26,"S",49,23,"sugov:0",605
-6824713046625000,0,431000,6824713047056000,84,"R",120,68,"ps",20463
-6824713047015000,1,48000,6824713047063000,6,"S",120,4,"rcu_preempt",7
-6824713047056000,0,43000,6824713047099000,11,"S",120,9,"rcuop/0",10
-6824713047063000,1,3191000,6824713050254000,0,"R",120,"[NULL]","swapper/5",0
-6824713047099000,0,3188000,6824713050287000,84,"R",120,68,"ps",20463
-6824713050254000,1,42000,6824713050296000,5,"S",120,7,"rcu_sched",8
-6824713050287000,0,36000,6824713050323000,14,"S",120,10,"rcuos/0",11
-6824713050296000,1,4103000,6824713054399000,0,"R",120,"[NULL]","swapper/5",0
-6824713050323000,0,3621000,6824713053944000,84,"R",120,68,"ps",20463
-6824713053165000,6,647000,6824713053812000,85,"S",120,69,"m.android.phone",1702
-6824713053812000,6,196550000,6824713250362000,0,"R",120,"[NULL]","swapper/5",0
-6824713053944000,0,46000,6824713053990000,11,"S",120,9,"rcuop/0",10
-6824713053990000,0,65000,6824713054055000,84,"R+",120,68,"ps",20463
-6824713054055000,0,22000,6824713054077000,76,"S",120,62,"hwrng",215
-6824713054077000,0,5450000,6824713059527000,84,"R",120,68,"ps",20463
-6824713054399000,1,30000,6824713054429000,6,"S",120,4,"rcu_preempt",7
-6824713054429000,1,6141000,6824713060570000,0,"R",120,"[NULL]","swapper/5",0
-6824713059527000,0,91000,6824713059618000,35,"S",120,33,"kworker/0:5",20371
-6824713059618000,0,735000,6824713060353000,36,"S",111,34,"SDM_EventThread",685
-6824713060353000,0,48000,6824713060401000,35,"S",120,33,"kworker/0:5",20371
-6824713060401000,0,2914000,6824713063315000,84,"R+",120,68,"ps",20463
-6824713060570000,1,23000,6824713060593000,47,"S",120,40,"ksoftirqd/1",17
-6824713060593000,1,54000,6824713060647000,6,"S",120,4,"rcu_preempt",7
-6824713060629000,2,431000,6824713061060000,38,"S",120,35,"HwBinder:640_1",721
-6824713060647000,1,274000,6824713060921000,0,"R",120,"[NULL]","swapper/5",0
-6824713060921000,1,103000,6824713061024000,40,"S",97,35,"DispSync",676
-6824713061024000,1,915000,6824713061939000,0,"R",120,"[NULL]","swapper/5",0
-6824713061060000,2,1313000,6824713062373000,0,"R",120,"[NULL]","swapper/5",0
-6824713061939000,1,85000,6824713062024000,40,"S",97,35,"DispSync",676
-6824713062024000,1,1073000,6824713063097000,0,"R",120,"[NULL]","swapper/5",0
-6824713062373000,2,326000,6824713062699000,41,"S",97,35,"app",678
-6824713062699000,2,2701000,6824713065400000,0,"R",120,"[NULL]","swapper/5",0
-6824713063058000,3,1709000,6824713064767000,42,"S",120,36,"ndroid.systemui",1664
-6824713063097000,1,28000,6824713063125000,40,"S",97,35,"DispSync",676
-6824713063125000,1,518000,6824713063643000,0,"R",120,"[NULL]","swapper/5",0
-6824713063315000,0,161000,6824713063476000,26,"S",49,23,"sugov:0",605
-6824713063476000,0,29511000,6824713092987000,84,"R+",120,68,"ps",20463
-6824713063643000,1,682000,6824713064325000,16,"S",120,14,"kworker/u16:7",19422
-6824713064325000,1,588000,6824713064913000,0,"R",120,"[NULL]","swapper/5",0
-6824713064767000,3,15375000,6824713080142000,0,"R",120,"[NULL]","swapper/5",0
-6824713064913000,1,237000,6824713065150000,43,"S",120,35,"Binder:640_2",675
-6824713065150000,1,321000,6824713065471000,0,"R",120,"[NULL]","swapper/5",0
-6824713065400000,2,110000,6824713065510000,41,"S",97,35,"app",678
-6824713065471000,1,26000,6824713065497000,40,"S",97,35,"DispSync",676
-6824713065497000,1,1148000,6824713066645000,0,"R",120,"[NULL]","swapper/5",0
-6824713065510000,2,1194000,6824713066704000,0,"R",120,"[NULL]","swapper/5",0
-6824713066645000,1,64000,6824713066709000,6,"S",120,4,"rcu_preempt",7
-6824713066704000,2,53000,6824713066757000,11,"S",120,9,"rcuop/0",10
-6824713066709000,1,41000,6824713066750000,0,"R",120,"[NULL]","swapper/5",0
-6824713066750000,1,18000,6824713066768000,6,"S",120,4,"rcu_preempt",7
-6824713066757000,2,4703000,6824713071460000,0,"R",120,"[NULL]","swapper/5",0
-6824713066768000,1,4421000,6824713071189000,0,"R",120,"[NULL]","swapper/5",0
-6824713071189000,1,109000,6824713071298000,82,"S",120,5,"shell",20461
-6824713071298000,1,679000,6824713071977000,0,"R",120,"[NULL]","swapper/5",0
-6824713071460000,2,412000,6824713071872000,7,"S",120,5,"adbd",20305
-6824713071872000,2,322000,6824713072194000,0,"R",120,"[NULL]","swapper/5",0
-6824713071977000,1,50000,6824713072027000,2,"S",100,2,"kworker/u17:1",1134
-6824713072027000,1,34000,6824713072061000,48,"S",120,41,"kworker/1:1",18800
-6824713072061000,1,129000,6824713072190000,0,"R",120,"[NULL]","swapper/5",0
-6824713072190000,1,20000,6824713072210000,2,"S",100,2,"kworker/u17:1",1134
-6824713072194000,2,45000,6824713072239000,4,"S",120,5,"UsbFfs-worker",20308
-6824713072210000,1,337000,6824713072547000,0,"R",120,"[NULL]","swapper/5",0
-6824713072239000,2,259000,6824713072498000,0,"R",120,"[NULL]","swapper/5",0
-6824713072498000,2,31000,6824713072529000,2,"S",100,2,"kworker/u17:1",1134
-6824713072529000,2,26000,6824713072555000,31,"S",120,29,"kworker/2:0",18823
-6824713072547000,1,36000,6824713072583000,4,"S",120,5,"UsbFfs-worker",20308
-6824713072555000,2,85000,6824713072640000,0,"R",120,"[NULL]","swapper/5",0
-6824713072583000,1,374000,6824713072957000,0,"R",120,"[NULL]","swapper/5",0
-6824713072640000,2,21000,6824713072661000,2,"S",100,2,"kworker/u17:1",1134
-6824713072661000,2,249000,6824713072910000,0,"R",120,"[NULL]","swapper/5",0
-6824713072910000,2,25000,6824713072935000,2,"S",100,2,"kworker/u17:1",1134
-6824713072935000,2,32000,6824713072967000,31,"S",120,29,"kworker/2:0",18823
-6824713072957000,1,71000,6824713073028000,4,"S",120,5,"UsbFfs-worker",20308
-6824713072967000,2,23000,6824713072990000,0,"R",120,"[NULL]","swapper/5",0
-6824713072990000,2,99000,6824713073089000,7,"S",120,5,"adbd",20305
-6824713073028000,1,235000,6824713073263000,0,"R",120,"[NULL]","swapper/5",0
-6824713073089000,2,196000,6824713073285000,0,"R",120,"[NULL]","swapper/5",0
-6824713073263000,1,25000,6824713073288000,6,"S",120,4,"rcu_preempt",7
-6824713073285000,2,117000,6824713073402000,11,"S",120,9,"rcuop/0",10
-6824713073288000,1,270000,6824713073558000,0,"R",120,"[NULL]","swapper/5",0
-6824713073402000,2,3701000,6824713077103000,0,"R",120,"[NULL]","swapper/5",0
-6824713073558000,1,15000,6824713073573000,6,"S",120,4,"rcu_preempt",7
-6824713073573000,1,3170000,6824713076743000,0,"R",120,"[NULL]","swapper/5",0
-6824713076743000,1,148000,6824713076891000,16,"D",120,14,"kworker/u16:7",19422
-6824713076891000,1,199000,6824713077090000,0,"R",120,"[NULL]","swapper/5",0
-6824713077090000,1,16000,6824713077106000,16,"S",120,14,"kworker/u16:7",19422
-6824713077103000,2,19000,6824713077122000,32,"S",120,30,"smem_native_rpm",87
-6824713077106000,1,2331000,6824713079437000,0,"R",120,"[NULL]","swapper/5",0
-6824713077122000,2,2542000,6824713079664000,0,"R",120,"[NULL]","swapper/5",0
-6824713079437000,1,81000,6824713079518000,82,"S",120,5,"shell",20461
-6824713079518000,1,417000,6824713079935000,0,"R",120,"[NULL]","swapper/5",0
-6824713079664000,2,293000,6824713079957000,7,"S",120,5,"adbd",20305
-6824713079935000,1,31000,6824713079966000,2,"S",100,2,"kworker/u17:1",1134
-6824713079957000,2,23000,6824713079980000,0,"R",120,"[NULL]","swapper/5",0
-6824713079966000,1,28000,6824713079994000,48,"S",120,41,"kworker/1:1",18800
-6824713079980000,2,20000,6824713080000000,2,"S",100,2,"kworker/u17:1",1134
-6824713079994000,1,24000,6824713080018000,4,"S",120,5,"UsbFfs-worker",20308
-6824713080000000,2,320000,6824713080320000,0,"R",120,"[NULL]","swapper/5",0
-6824713080018000,1,518000,6824713080536000,0,"R",120,"[NULL]","swapper/5",0
-6824713080142000,3,24000,6824713080166000,6,"S",120,4,"rcu_preempt",7
-6824713080166000,3,419000,6824713080585000,0,"R",120,"[NULL]","swapper/5",0
-6824713080320000,2,27000,6824713080347000,2,"S",100,2,"kworker/u17:1",1134
-6824713080347000,2,41000,6824713080388000,31,"S",120,29,"kworker/2:0",18823
-6824713080388000,2,452000,6824713080840000,0,"R",120,"[NULL]","swapper/5",0
-6824713080536000,1,38000,6824713080574000,4,"S",120,5,"UsbFfs-worker",20308
-6824713080574000,1,488000,6824713081062000,0,"R",120,"[NULL]","swapper/5",0
-6824713080585000,3,26000,6824713080611000,2,"S",100,2,"kworker/u17:1",1134
-6824713080611000,3,6419000,6824713087030000,0,"R",120,"[NULL]","swapper/5",0
-6824713080840000,2,23000,6824713080863000,2,"S",100,2,"kworker/u17:1",1134
-6824713080863000,2,43000,6824713080906000,31,"S",120,29,"kworker/2:0",18823
-6824713080906000,2,345000,6824713081251000,0,"R",120,"[NULL]","swapper/5",0
-6824713081062000,1,72000,6824713081134000,4,"S",120,5,"UsbFfs-worker",20308
-6824713081134000,1,6852000,6824713087986000,0,"R",120,"[NULL]","swapper/5",0
-6824713081251000,2,106000,6824713081357000,7,"S",120,5,"adbd",20305
-6824713081357000,2,6049000,6824713087406000,0,"R",120,"[NULL]","swapper/5",0
-6824713087030000,3,62000,6824713087092000,6,"S",120,4,"rcu_preempt",7
-6824713087092000,3,964000,6824713088056000,0,"R",120,"[NULL]","swapper/5",0
-6824713087406000,2,284000,6824713087690000,11,"S",120,9,"rcuop/0",10
-6824713087690000,2,783000,6824713088473000,0,"R",120,"[NULL]","swapper/5",0
-6824713087986000,1,139000,6824713088125000,82,"S",120,5,"shell",20461
-6824713088056000,3,22000,6824713088078000,6,"S",120,4,"rcu_preempt",7
-6824713088078000,3,36000,6824713088114000,0,"R",120,"[NULL]","swapper/5",0
-6824713088114000,3,404000,6824713088518000,7,"S",120,5,"adbd",20305
-6824713088125000,1,464000,6824713088589000,0,"R",120,"[NULL]","swapper/5",0
-6824713088473000,2,53000,6824713088526000,2,"S",100,2,"kworker/u17:1",1134
-6824713088518000,3,43000,6824713088561000,0,"R",120,"[NULL]","swapper/5",0
-6824713088526000,2,74000,6824713088600000,31,"S",120,29,"kworker/2:0",18823
-6824713088561000,3,34000,6824713088595000,2,"S",100,2,"kworker/u17:1",1134
-6824713088589000,1,37000,6824713088626000,4,"S",120,5,"UsbFfs-worker",20308
-6824713088595000,3,122000,6824713088717000,0,"R",120,"[NULL]","swapper/5",0
-6824713088600000,2,1021000,6824713089621000,0,"R",120,"[NULL]","swapper/5",0
-6824713088626000,1,590000,6824713089216000,0,"R",120,"[NULL]","swapper/5",0
-6824713088717000,3,48000,6824713088765000,2,"S",100,2,"kworker/u17:1",1134
-6824713088765000,3,41000,6824713088806000,49,"S",120,42,"kworker/3:1",17791
-6824713088806000,3,14000,6824713088820000,0,"R",120,"[NULL]","swapper/5",0
-6824713088820000,3,17000,6824713088837000,2,"S",100,2,"kworker/u17:1",1134
-6824713088837000,3,135000,6824713088972000,0,"R",120,"[NULL]","swapper/5",0
-6824713088972000,3,44000,6824713089016000,2,"S",100,2,"kworker/u17:1",1134
-6824713089016000,3,47000,6824713089063000,0,"R",120,"[NULL]","swapper/5",0
-6824713089063000,3,35000,6824713089098000,2,"S",100,2,"kworker/u17:1",1134
-6824713089098000,3,89000,6824713089187000,49,"S",120,42,"kworker/3:1",17791
-6824713089187000,3,4413000,6824713093600000,0,"R",120,"[NULL]","swapper/5",0
-6824713089216000,1,154000,6824713089370000,4,"S",120,5,"UsbFfs-worker",20308
-6824713089370000,1,4023000,6824713093393000,0,"R",120,"[NULL]","swapper/5",0
-6824713089621000,2,127000,6824713089748000,7,"S",120,5,"adbd",20305
-6824713089748000,2,4425000,6824713094173000,0,"R",120,"[NULL]","swapper/5",0
-6824713092987000,0,74000,6824713093061000,35,"S",120,33,"kworker/0:5",20371
-6824713093061000,0,3580000,6824713096641000,84,"R+",120,68,"ps",20463
-6824713093393000,1,580000,6824713093973000,36,"S",111,34,"SDM_EventThread",685
-6824713093600000,3,36000,6824713093636000,6,"S",120,4,"rcu_preempt",7
-6824713093636000,3,1371000,6824713095007000,0,"R",120,"[NULL]","swapper/5",0
-6824713093973000,1,507000,6824713094480000,0,"R",120,"[NULL]","swapper/5",0
-6824713094173000,2,367000,6824713094540000,38,"S",120,35,"HwBinder:640_1",721
-6824713094480000,1,99000,6824713094579000,40,"S",97,35,"DispSync",676
-6824713094540000,2,9000,6824713094549000,0,"R",120,"[NULL]","swapper/5",0
-6824713094549000,2,126000,6824713094675000,38,"S",120,35,"HwBinder:640_1",721
-6824713094579000,1,9000,6824713094588000,0,"R",120,"[NULL]","swapper/5",0
-6824713094588000,1,74000,6824713094662000,40,"S",97,35,"DispSync",676
-6824713094662000,1,934000,6824713095596000,0,"R",120,"[NULL]","swapper/5",0
-6824713094675000,2,1004000,6824713095679000,0,"R",120,"[NULL]","swapper/5",0
-6824713095007000,3,267000,6824713095274000,41,"S",97,35,"app",678
-6824713095274000,3,5029000,6824713100303000,0,"R",120,"[NULL]","swapper/5",0
-6824713095596000,1,2136000,6824713097732000,42,"S",120,36,"ndroid.systemui",1664
-6824713095679000,2,17000,6824713095696000,40,"S",97,35,"DispSync",676
-6824713095696000,2,2152000,6824713097848000,0,"R",120,"[NULL]","swapper/5",0
-6824713096641000,0,233000,6824713096874000,26,"S",49,23,"sugov:0",605
-6824713096874000,0,29589000,6824713126463000,84,"R+",120,68,"ps",20463
-6824713097732000,1,701000,6824713098433000,0,"R",120,"[NULL]","swapper/5",0
-6824713097848000,2,321000,6824713098169000,43,"S",120,35,"Binder:640_2",675
-6824713098169000,2,724000,6824713098893000,0,"R",120,"[NULL]","swapper/5",0
-6824713098433000,1,171000,6824713098604000,41,"S",97,35,"app",678
-6824713098604000,1,39000,6824713098643000,0,"R",120,"[NULL]","swapper/5",0
-6824713098643000,1,113000,6824713098756000,26,"S",49,23,"sugov:0",605
-6824713098756000,1,488000,6824713099244000,0,"R",120,"[NULL]","swapper/5",0
-6824713098893000,2,25000,6824713098918000,40,"S",97,35,"DispSync",676
-6824713098918000,2,480000,6824713099398000,0,"R",120,"[NULL]","swapper/5",0
-6824713099244000,1,183000,6824713099427000,82,"S",120,5,"shell",20461
-6824713099398000,2,1576000,6824713100974000,7,"S",120,5,"adbd",20305
-6824713099427000,1,51000,6824713099478000,0,"R",120,"[NULL]","swapper/5",0
-6824713099478000,1,65000,6824713099543000,50,"S",120,43,"Executor-7",14762
-6824713099543000,1,1075000,6824713100618000,0,"R",120,"[NULL]","swapper/5",0
-6824713100303000,3,67000,6824713100370000,2,"S",100,2,"kworker/u17:1",1134
-6824713100370000,3,9000,6824713100379000,0,"R",120,"[NULL]","swapper/5",0
-6824713100379000,3,72000,6824713100451000,2,"S",100,2,"kworker/u17:1",1134
-6824713100451000,3,97000,6824713100548000,49,"S",120,42,"kworker/3:1",17791
-6824713100548000,3,59000,6824713100607000,4,"S",120,5,"UsbFfs-worker",20308
-6824713100607000,3,31000,6824713100638000,2,"S",100,2,"kworker/u17:1",1134
-6824713100618000,1,54000,6824713100672000,6,"S",120,4,"rcu_preempt",7
-6824713100638000,3,17000,6824713100655000,49,"S",120,42,"kworker/3:1",17791
-6824713100655000,3,15000,6824713100670000,4,"R",120,5,"UsbFfs-worker",20308
-6824713100670000,3,12000,6824713100682000,2,"S",100,2,"kworker/u17:1",1134
-6824713100672000,1,561000,6824713101233000,11,"S",120,9,"rcuop/0",10
-6824713100682000,3,60000,6824713100742000,4,"S",120,5,"UsbFfs-worker",20308
-6824713100742000,3,513000,6824713101255000,0,"R",120,"[NULL]","swapper/5",0
-6824713100974000,2,632000,6824713101606000,0,"R",120,"[NULL]","swapper/5",0
-6824713101233000,1,787000,6824713102020000,0,"R",120,"[NULL]","swapper/5",0
-6824713101255000,3,47000,6824713101302000,2,"S",100,2,"kworker/u17:1",1134
-6824713101302000,3,605000,6824713101907000,0,"R",120,"[NULL]","swapper/5",0
-6824713101606000,2,31000,6824713101637000,6,"S",120,4,"rcu_preempt",7
-6824713101637000,2,471000,6824713102108000,0,"R",120,"[NULL]","swapper/5",0
-6824713101907000,3,54000,6824713101961000,2,"S",100,2,"kworker/u17:1",1134
-6824713101961000,3,73000,6824713102034000,49,"S",120,42,"kworker/3:1",17791
-6824713102020000,1,177000,6824713102197000,4,"S",120,5,"UsbFfs-worker",20308
-6824713102034000,3,8819000,6824713110853000,0,"R",120,"[NULL]","swapper/5",0
-6824713102108000,2,177000,6824713102285000,7,"S",120,5,"adbd",20305
-6824713102197000,1,5230000,6824713107427000,0,"R",120,"[NULL]","swapper/5",0
-6824713102285000,2,4714000,6824713106999000,0,"R",120,"[NULL]","swapper/5",0
-6824713106999000,2,46000,6824713107045000,6,"S",120,4,"rcu_preempt",7
-6824713107045000,2,1111000,6824713108156000,0,"R",120,"[NULL]","swapper/5",0
-6824713107427000,1,382000,6824713107809000,11,"S",120,9,"rcuop/0",10
-6824713107809000,1,1784000,6824713109593000,0,"R",120,"[NULL]","swapper/5",0
-6824713108156000,2,24000,6824713108180000,6,"S",120,4,"rcu_preempt",7
-6824713108180000,2,1871000,6824713110051000,0,"R",120,"[NULL]","swapper/5",0
-6824713109593000,1,155000,6824713109748000,82,"S",120,5,"shell",20461
-6824713109748000,1,1604000,6824713111352000,0,"R",120,"[NULL]","swapper/5",0
-6824713110051000,2,506000,6824713110557000,7,"S",120,5,"adbd",20305
-6824713110557000,2,728000,6824713111285000,0,"R",120,"[NULL]","swapper/5",0
-6824713110853000,3,66000,6824713110919000,2,"S",100,2,"kworker/u17:1",1134
-6824713110919000,3,54000,6824713110973000,49,"S",120,42,"kworker/3:1",17791
-6824713110973000,3,1252000,6824713112225000,0,"R",120,"[NULL]","swapper/5",0
-6824713111285000,2,35000,6824713111320000,2,"S",100,2,"kworker/u17:1",1134
-6824713111320000,2,474000,6824713111794000,0,"R",120,"[NULL]","swapper/5",0
-6824713111352000,1,75000,6824713111427000,4,"S",120,5,"UsbFfs-worker",20308
-6824713111427000,1,882000,6824713112309000,0,"R",120,"[NULL]","swapper/5",0
-6824713111794000,2,71000,6824713111865000,2,"S",100,2,"kworker/u17:1",1134
-6824713111865000,2,64000,6824713111929000,31,"S",120,29,"kworker/2:0",18823
-6824713111929000,2,466000,6824713112395000,0,"R",120,"[NULL]","swapper/5",0
-6824713112225000,3,47000,6824713112272000,2,"S",100,2,"kworker/u17:1",1134
-6824713112272000,3,72000,6824713112344000,49,"S",120,42,"kworker/3:1",17791
-6824713112309000,1,168000,6824713112477000,4,"S",120,5,"UsbFfs-worker",20308
-6824713112344000,3,10051000,6824713122395000,0,"R",120,"[NULL]","swapper/5",0
-6824713112395000,2,142000,6824713112537000,7,"S",120,5,"adbd",20305
-6824713112477000,1,4894000,6824713117371000,0,"R",120,"[NULL]","swapper/5",0
-6824713112537000,2,766000,6824713113303000,0,"R",120,"[NULL]","swapper/5",0
-6824713113303000,2,30000,6824713113333000,6,"S",120,4,"rcu_preempt",7
-6824713113333000,2,3671000,6824713117004000,0,"R",120,"[NULL]","swapper/5",0
-6824713117004000,2,42000,6824713117046000,6,"S",120,4,"rcu_preempt",7
-6824713117046000,2,851000,6824713117897000,0,"R",120,"[NULL]","swapper/5",0
-6824713117371000,1,213000,6824713117584000,11,"S",120,9,"rcuop/0",10
-6824713117584000,1,3602000,6824713121186000,0,"R",120,"[NULL]","swapper/5",0
-6824713117897000,2,22000,6824713117919000,6,"S",120,4,"rcu_preempt",7
-6824713117919000,2,3713000,6824713121632000,0,"R",120,"[NULL]","swapper/5",0
-6824713121186000,1,154000,6824713121340000,82,"S",120,5,"shell",20461
-6824713121340000,1,1525000,6824713122865000,0,"R",120,"[NULL]","swapper/5",0
-6824713121632000,2,519000,6824713122151000,7,"S",120,5,"adbd",20305
-6824713122151000,2,341000,6824713122492000,0,"R",120,"[NULL]","swapper/5",0
-6824713122395000,3,74000,6824713122469000,2,"S",100,2,"kworker/u17:1",1134
-6824713122469000,3,51000,6824713122520000,49,"S",120,42,"kworker/3:1",17791
-6824713122492000,2,31000,6824713122523000,2,"S",100,2,"kworker/u17:1",1134
-6824713122520000,3,1113000,6824713123633000,0,"R",120,"[NULL]","swapper/5",0
-6824713122523000,2,120000,6824713122643000,0,"R",120,"[NULL]","swapper/5",0
-6824713122643000,2,45000,6824713122688000,2,"S",100,2,"kworker/u17:1",1134
-6824713122688000,2,30000,6824713122718000,31,"S",120,29,"kworker/2:0",18823
-6824713122718000,2,23000,6824713122741000,0,"R",120,"[NULL]","swapper/5",0
-6824713122741000,2,16000,6824713122757000,2,"S",100,2,"kworker/u17:1",1134
-6824713122757000,2,136000,6824713122893000,0,"R",120,"[NULL]","swapper/5",0
-6824713122865000,1,95000,6824713122960000,4,"S",120,5,"UsbFfs-worker",20308
-6824713122893000,2,34000,6824713122927000,2,"S",100,2,"kworker/u17:1",1134
-6824713122927000,2,101000,6824713123028000,0,"R",120,"[NULL]","swapper/5",0
-6824713122960000,1,168000,6824713123128000,0,"R",120,"[NULL]","swapper/5",0
-6824713123028000,2,42000,6824713123070000,2,"S",100,2,"kworker/u17:1",1134
-6824713123070000,2,76000,6824713123146000,31,"S",120,29,"kworker/2:0",18823
-6824713123128000,1,152000,6824713123280000,4,"S",120,5,"UsbFfs-worker",20308
-6824713123146000,2,29000,6824713123175000,0,"R",120,"[NULL]","swapper/5",0
-6824713123175000,2,190000,6824713123365000,7,"S",120,5,"adbd",20305
-6824713123280000,1,3559000,6824713126839000,0,"R",120,"[NULL]","swapper/5",0
-6824713123365000,2,3548000,6824713126913000,0,"R",120,"[NULL]","swapper/5",0
-6824713123633000,3,30000,6824713123663000,6,"S",120,4,"rcu_preempt",7
-6824713123663000,3,3867000,6824713127530000,0,"R",120,"[NULL]","swapper/5",0
-6824713126463000,0,72000,6824713126535000,35,"S",120,33,"kworker/0:5",20371
-6824713126535000,0,3430000,6824713129965000,84,"R+",120,68,"ps",20463
-6824713126839000,1,582000,6824713127421000,36,"S",111,34,"SDM_EventThread",685
-6824713126913000,2,467000,6824713127380000,16,"R+",120,14,"kworker/u16:7",19422
-6824713127380000,2,198000,6824713127578000,40,"S",97,35,"DispSync",676
-6824713127421000,1,507000,6824713127928000,0,"R",120,"[NULL]","swapper/5",0
-6824713127530000,3,44000,6824713127574000,32,"S",120,30,"smem_native_rpm",87
-6824713127574000,3,559000,6824713128133000,0,"R",120,"[NULL]","swapper/5",0
-6824713127578000,2,33000,6824713127611000,16,"S",120,14,"kworker/u16:7",19422
-6824713127611000,2,338000,6824713127949000,38,"S",120,35,"HwBinder:640_1",721
-6824713127928000,1,258000,6824713128186000,41,"S",97,35,"app",678
-6824713127949000,2,518000,6824713128467000,0,"R",120,"[NULL]","swapper/5",0
-6824713128133000,3,26000,6824713128159000,40,"S",97,35,"DispSync",676
-6824713128159000,3,8000,6824713128167000,0,"R",120,"[NULL]","swapper/5",0
-6824713128167000,3,13000,6824713128180000,40,"S",97,35,"DispSync",676
-6824713128180000,3,1804000,6824713129984000,0,"R",120,"[NULL]","swapper/5",0
-6824713128186000,1,2334000,6824713130520000,0,"R",120,"[NULL]","swapper/5",0
-6824713128467000,2,1954000,6824713130421000,42,"S",120,36,"ndroid.systemui",1664
-6824713129965000,0,223000,6824713130188000,26,"S",49,23,"sugov:0",605
-6824713129984000,3,64000,6824713130048000,6,"S",120,4,"rcu_preempt",7
-6824713130048000,3,1593000,6824713131641000,0,"R",120,"[NULL]","swapper/5",0
-6824713130188000,0,29833000,6824713160021000,84,"R",120,68,"ps",20463
-6824713130421000,2,758000,6824713131179000,0,"R",120,"[NULL]","swapper/5",0
-6824713130520000,1,356000,6824713130876000,43,"S",120,35,"Binder:640_2",675
-6824713130876000,1,61000,6824713130937000,11,"R",120,9,"rcuop/0",10
-6824713130937000,1,114000,6824713131051000,26,"S",49,23,"sugov:0",605
-6824713131051000,1,355000,6824713131406000,11,"S",120,9,"rcuop/0",10
-6824713131179000,2,114000,6824713131293000,41,"S",97,35,"app",678
-6824713131293000,2,593000,6824713131886000,0,"R",120,"[NULL]","swapper/5",0
-6824713131406000,1,828000,6824713132234000,0,"R",120,"[NULL]","swapper/5",0
-6824713131641000,3,30000,6824713131671000,40,"S",97,35,"DispSync",676
-6824713131671000,3,95000,6824713131766000,0,"R",120,"[NULL]","swapper/5",0
-6824713131766000,3,183000,6824713131949000,82,"S",120,5,"shell",20461
-6824713131886000,2,26000,6824713131912000,6,"S",120,4,"rcu_preempt",7
-6824713131912000,2,1066000,6824713132978000,0,"R",120,"[NULL]","swapper/5",0
-6824713131949000,3,1543000,6824713133492000,0,"R",120,"[NULL]","swapper/5",0
-6824713132234000,1,838000,6824713133072000,7,"S",120,5,"adbd",20305
-6824713132978000,2,164000,6824713133142000,2,"S",100,2,"kworker/u17:1",1134
-6824713133072000,1,496000,6824713133568000,0,"R",120,"[NULL]","swapper/5",0
-6824713133142000,2,65000,6824713133207000,31,"S",120,29,"kworker/2:0",18823
-6824713133207000,2,70000,6824713133277000,0,"R",120,"[NULL]","swapper/5",0
-6824713133277000,2,50000,6824713133327000,2,"S",100,2,"kworker/u17:1",1134
-6824713133327000,2,20000,6824713133347000,31,"S",120,29,"kworker/2:0",18823
-6824713133347000,2,160000,6824713133507000,0,"R",120,"[NULL]","swapper/5",0
-6824713133492000,3,53000,6824713133545000,79,"S",100,64,"kworker/u17:2",14944
-6824713133507000,2,8000,6824713133515000,2,"S",100,2,"kworker/u17:1",1134
-6824713133515000,2,65000,6824713133580000,0,"R",120,"[NULL]","swapper/5",0
-6824713133545000,3,9733000,6824713143278000,0,"R",120,"[NULL]","swapper/5",0
-6824713133568000,1,104000,6824713133672000,4,"S",120,5,"UsbFfs-worker",20308
-6824713133580000,2,40000,6824713133620000,79,"S",100,64,"kworker/u17:2",14944
-6824713133620000,2,86000,6824713133706000,31,"S",120,29,"kworker/2:0",18823
-6824713133672000,1,11000,6824713133683000,0,"R",120,"[NULL]","swapper/5",0
-6824713133683000,1,142000,6824713133825000,4,"S",120,5,"UsbFfs-worker",20308
-6824713133706000,2,37000,6824713133743000,0,"R",120,"[NULL]","swapper/5",0
-6824713133743000,2,140000,6824713133883000,7,"S",120,5,"adbd",20305
-6824713133825000,1,6827000,6824713140652000,0,"R",120,"[NULL]","swapper/5",0
-6824713133883000,2,3063000,6824713136946000,0,"R",120,"[NULL]","swapper/5",0
-6824713136946000,2,41000,6824713136987000,6,"S",120,4,"rcu_preempt",7
-6824713136987000,2,3274000,6824713140261000,0,"R",120,"[NULL]","swapper/5",0
-6824713140261000,2,37000,6824713140298000,6,"S",120,4,"rcu_preempt",7
-6824713140298000,2,1112000,6824713141410000,0,"R",120,"[NULL]","swapper/5",0
-6824713140652000,1,423000,6824713141075000,11,"S",120,9,"rcuop/0",10
-6824713141075000,1,1022000,6824713142097000,0,"R",120,"[NULL]","swapper/5",0
-6824713141410000,2,18000,6824713141428000,6,"S",120,4,"rcu_preempt",7
-6824713141428000,2,1111000,6824713142539000,0,"R",120,"[NULL]","swapper/5",0
-6824713142097000,1,152000,6824713142249000,82,"S",120,5,"shell",20461
-6824713142249000,1,2185000,6824713144434000,0,"R",120,"[NULL]","swapper/5",0
-6824713142539000,2,518000,6824713143057000,7,"S",120,5,"adbd",20305
-6824713143057000,2,1528000,6824713144585000,0,"R",120,"[NULL]","swapper/5",0
-6824713143278000,3,57000,6824713143335000,79,"S",100,64,"kworker/u17:2",14944
-6824713143335000,3,606000,6824713143941000,0,"R",120,"[NULL]","swapper/5",0
-6824713143941000,3,76000,6824713144017000,79,"S",100,64,"kworker/u17:2",14944
-6824713144017000,3,60000,6824713144077000,49,"S",120,42,"kworker/3:1",17791
-6824713144077000,3,438000,6824713144515000,0,"R",120,"[NULL]","swapper/5",0
-6824713144434000,1,56000,6824713144490000,4,"S",120,5,"UsbFfs-worker",20308
-6824713144490000,1,687000,6824713145177000,0,"R",120,"[NULL]","swapper/5",0
-6824713144515000,3,36000,6824713144551000,79,"S",100,64,"kworker/u17:2",14944
-6824713144551000,3,44000,6824713144595000,49,"S",120,42,"kworker/3:1",17791
-6824713144585000,2,61000,6824713144646000,4,"S",120,5,"UsbFfs-worker",20308
-6824713144595000,3,37000,6824713144632000,79,"S",100,64,"kworker/u17:2",14944
-6824713144632000,3,139000,6824713144771000,0,"R",120,"[NULL]","swapper/5",0
-6824713144646000,2,26000,6824713144672000,0,"R",120,"[NULL]","swapper/5",0
-6824713144672000,2,58000,6824713144730000,79,"S",100,64,"kworker/u17:2",14944
-6824713144730000,2,57000,6824713144787000,31,"S",120,29,"kworker/2:0",18823
-6824713144771000,3,137000,6824713144908000,4,"S",120,5,"UsbFfs-worker",20308
-6824713144787000,2,2129000,6824713146916000,0,"R",120,"[NULL]","swapper/5",0
-6824713144908000,3,9292000,6824713154200000,0,"R",120,"[NULL]","swapper/5",0
-6824713145177000,1,151000,6824713145328000,7,"S",120,5,"adbd",20305
-6824713145328000,1,1971000,6824713147299000,0,"R",120,"[NULL]","swapper/5",0
-6824713146916000,2,42000,6824713146958000,6,"S",120,4,"rcu_preempt",7
-6824713146958000,2,950000,6824713147908000,0,"R",120,"[NULL]","swapper/5",0
-6824713147299000,1,265000,6824713147564000,11,"S",120,9,"rcuop/0",10
-6824713147564000,1,6404000,6824713153968000,0,"R",120,"[NULL]","swapper/5",0
-6824713147908000,2,20000,6824713147928000,6,"S",120,4,"rcu_preempt",7
-6824713147928000,2,5718000,6824713153646000,0,"R",120,"[NULL]","swapper/5",0
-6824713153646000,2,49000,6824713153695000,6,"S",120,4,"rcu_preempt",7
-6824713153695000,2,724000,6824713154419000,0,"R",120,"[NULL]","swapper/5",0
-6824713153968000,1,154000,6824713154122000,82,"S",120,5,"shell",20461
-6824713154122000,1,591000,6824713154713000,0,"R",120,"[NULL]","swapper/5",0
-6824713154200000,3,176000,6824713154376000,11,"S",120,9,"rcuop/0",10
-6824713154376000,3,873000,6824713155249000,0,"R",120,"[NULL]","swapper/5",0
-6824713154419000,2,564000,6824713154983000,7,"S",120,5,"adbd",20305
-6824713154713000,1,18000,6824713154731000,6,"S",120,4,"rcu_preempt",7
-6824713154731000,1,1001000,6824713155732000,0,"R",120,"[NULL]","swapper/5",0
-6824713154983000,2,683000,6824713155666000,0,"R",120,"[NULL]","swapper/5",0
-6824713155249000,3,83000,6824713155332000,79,"S",100,64,"kworker/u17:2",14944
-6824713155332000,3,55000,6824713155387000,49,"S",120,42,"kworker/3:1",17791
-6824713155387000,3,344000,6824713155731000,0,"R",120,"[NULL]","swapper/5",0
-6824713155666000,2,78000,6824713155744000,79,"S",100,64,"kworker/u17:2",14944
-6824713155731000,3,19000,6824713155750000,2,"S",100,2,"kworker/u17:1",1134
-6824713155732000,1,85000,6824713155817000,4,"S",120,5,"UsbFfs-worker",20308
-6824713155744000,2,88000,6824713155832000,0,"R",120,"[NULL]","swapper/5",0
-6824713155750000,3,177000,6824713155927000,0,"R",120,"[NULL]","swapper/5",0
-6824713155817000,1,92000,6824713155909000,0,"R",120,"[NULL]","swapper/5",0
-6824713155832000,2,47000,6824713155879000,2,"S",100,2,"kworker/u17:1",1134
-6824713155879000,2,58000,6824713155937000,31,"S",120,29,"kworker/2:0",18823
-6824713155909000,1,37000,6824713155946000,4,"S",120,5,"UsbFfs-worker",20308
-6824713155927000,3,16000,6824713155943000,2,"S",100,2,"kworker/u17:1",1134
-6824713155937000,2,171000,6824713156108000,0,"R",120,"[NULL]","swapper/5",0
-6824713155943000,3,6823000,6824713162766000,0,"R",120,"[NULL]","swapper/5",0
-6824713155946000,1,615000,6824713156561000,0,"R",120,"[NULL]","swapper/5",0
-6824713156108000,2,34000,6824713156142000,2,"S",100,2,"kworker/u17:1",1134
-6824713156142000,2,27000,6824713156169000,0,"R",120,"[NULL]","swapper/5",0
-6824713156169000,2,40000,6824713156209000,2,"S",100,2,"kworker/u17:1",1134
-6824713156209000,2,45000,6824713156254000,31,"S",120,29,"kworker/2:0",18823
-6824713156254000,2,364000,6824713156618000,0,"R",120,"[NULL]","swapper/5",0
-6824713156561000,1,142000,6824713156703000,4,"S",120,5,"UsbFfs-worker",20308
-6824713156618000,2,133000,6824713156751000,7,"S",120,5,"adbd",20305
-6824713156703000,1,3760000,6824713160463000,0,"R",120,"[NULL]","swapper/5",0
-6824713156751000,2,4509000,6824713161260000,0,"R",120,"[NULL]","swapper/5",0
-6824713160021000,0,109000,6824713160130000,35,"S",120,33,"kworker/0:5",20371
-6824713160130000,0,33314000,6824713193444000,84,"R+",120,68,"ps",20463
-6824713160463000,1,578000,6824713161041000,36,"S",111,34,"SDM_EventThread",685
-6824713161041000,1,887000,6824713161928000,0,"R",120,"[NULL]","swapper/5",0
-6824713161260000,2,459000,6824713161719000,38,"S",120,35,"HwBinder:640_1",721
-6824713161719000,2,304000,6824713162023000,0,"R",120,"[NULL]","swapper/5",0
-6824713161928000,1,140000,6824713162068000,40,"S",97,35,"DispSync",676
-6824713162023000,2,447000,6824713162470000,41,"S",97,35,"app",678
-6824713162068000,1,358000,6824713162426000,0,"R",120,"[NULL]","swapper/5",0
-6824713162426000,1,1725000,6824713164151000,42,"S",120,36,"ndroid.systemui",1664
-6824713162470000,2,1183000,6824713163653000,0,"R",120,"[NULL]","swapper/5",0
-6824713162766000,3,32000,6824713162798000,40,"S",97,35,"DispSync",676
-6824713162798000,3,917000,6824713163715000,0,"R",120,"[NULL]","swapper/5",0
-6824713163653000,2,751000,6824713164404000,16,"S",120,14,"kworker/u16:7",19422
-6824713163715000,3,56000,6824713163771000,6,"S",120,4,"rcu_preempt",7
-6824713163771000,3,581000,6824713164352000,0,"R",120,"[NULL]","swapper/5",0
-6824713164151000,1,689000,6824713164840000,0,"R",120,"[NULL]","swapper/5",0
-6824713164352000,3,251000,6824713164603000,43,"S",120,35,"Binder:640_2",675
-6824713164404000,2,820000,6824713165224000,0,"R",120,"[NULL]","swapper/5",0
-6824713164603000,3,1967000,6824713166570000,0,"R",120,"[NULL]","swapper/5",0
-6824713164840000,1,120000,6824713164960000,41,"S",97,35,"app",678
-6824713164960000,1,408000,6824713165368000,0,"R",120,"[NULL]","swapper/5",0
-6824713165224000,2,31000,6824713165255000,40,"S",97,35,"DispSync",676
-6824713165255000,2,581000,6824713165836000,0,"R",120,"[NULL]","swapper/5",0
-6824713165368000,1,186000,6824713165554000,82,"S",120,5,"shell",20461
-6824713165554000,1,1573000,6824713167127000,0,"R",120,"[NULL]","swapper/5",0
-6824713165836000,2,847000,6824713166683000,7,"R+",120,5,"adbd",20305
-6824713166570000,3,92000,6824713166662000,2,"S",100,2,"kworker/u17:1",1134
-6824713166662000,3,58000,6824713166720000,49,"S",120,42,"kworker/3:1",17791
-6824713166683000,2,227000,6824713166910000,26,"S",49,23,"sugov:0",605
-6824713166720000,3,109000,6824713166829000,4,"S",120,5,"UsbFfs-worker",20308
-6824713166829000,3,636000,6824713167465000,0,"R",120,"[NULL]","swapper/5",0
-6824713166910000,2,644000,6824713167554000,7,"S",120,5,"adbd",20305
-6824713167127000,1,100000,6824713167227000,2,"S",100,2,"kworker/u17:1",1134
-6824713167227000,1,42000,6824713167269000,0,"R",120,"[NULL]","swapper/5",0
-6824713167269000,1,51000,6824713167320000,2,"S",100,2,"kworker/u17:1",1134
-6824713167320000,1,35000,6824713167355000,0,"R",120,"[NULL]","swapper/5",0
-6824713167355000,1,100000,6824713167455000,2,"S",100,2,"kworker/u17:1",1134
-6824713167455000,1,63000,6824713167518000,48,"S",120,41,"kworker/1:1",18800
-6824713167465000,3,195000,6824713167660000,4,"S",120,5,"UsbFfs-worker",20308
-6824713167518000,1,54000,6824713167572000,2,"S",100,2,"kworker/u17:1",1134
-6824713167554000,2,634000,6824713168188000,0,"R",120,"[NULL]","swapper/5",0
-6824713167572000,1,42000,6824713167614000,0,"R",120,"[NULL]","swapper/5",0
-6824713167614000,1,71000,6824713167685000,2,"S",100,2,"kworker/u17:1",1134
-6824713167660000,3,456000,6824713168116000,0,"R",120,"[NULL]","swapper/5",0
-6824713167685000,1,45000,6824713167730000,0,"R",120,"[NULL]","swapper/5",0
-6824713167730000,1,100000,6824713167830000,2,"S",100,2,"kworker/u17:1",1134
-6824713167830000,1,52000,6824713167882000,48,"R",120,41,"kworker/1:1",18800
-6824713167882000,1,132000,6824713168014000,26,"S",49,23,"sugov:0",605
-6824713168014000,1,125000,6824713168139000,48,"S",120,41,"kworker/1:1",18800
-6824713168116000,3,145000,6824713168261000,4,"S",120,5,"UsbFfs-worker",20308
-6824713168139000,1,2254000,6824713170393000,0,"R",120,"[NULL]","swapper/5",0
-6824713168188000,2,118000,6824713168306000,7,"S",120,5,"adbd",20305
-6824713168261000,3,1720000,6824713169981000,0,"R",120,"[NULL]","swapper/5",0
-6824713168306000,2,8737000,6824713177043000,0,"R",120,"[NULL]","swapper/5",0
-6824713169981000,3,63000,6824713170044000,6,"S",120,4,"rcu_preempt",7
-6824713170044000,3,912000,6824713170956000,0,"R",120,"[NULL]","swapper/5",0
-6824713170393000,1,203000,6824713170596000,11,"S",120,9,"rcuop/0",10
-6824713170596000,1,7765000,6824713178361000,0,"R",120,"[NULL]","swapper/5",0
-6824713170956000,3,31000,6824713170987000,6,"S",120,4,"rcu_preempt",7
-6824713170987000,3,6024000,6824713177011000,0,"R",120,"[NULL]","swapper/5",0
-6824713177011000,3,31000,6824713177042000,6,"S",120,4,"rcu_preempt",7
-6824713177042000,3,653000,6824713177695000,0,"R",120,"[NULL]","swapper/5",0
-6824713177043000,2,352000,6824713177395000,16,"D",120,14,"kworker/u16:7",19422
-6824713177395000,2,498000,6824713177893000,0,"R",120,"[NULL]","swapper/5",0
-6824713177695000,3,144000,6824713177839000,32,"S",120,30,"smem_native_rpm",87
-6824713177839000,3,5798000,6824713183637000,0,"R",120,"[NULL]","swapper/5",0
-6824713177893000,2,35000,6824713177928000,16,"S",120,14,"kworker/u16:7",19422
-6824713177928000,2,920000,6824713178848000,0,"R",120,"[NULL]","swapper/5",0
-6824713178361000,1,204000,6824713178565000,82,"S",120,5,"shell",20461
-6824713178565000,1,1277000,6824713179842000,0,"R",120,"[NULL]","swapper/5",0
-6824713178848000,2,801000,6824713179649000,7,"S",120,5,"adbd",20305
-6824713179649000,2,622000,6824713180271000,0,"R",120,"[NULL]","swapper/5",0
-6824713179842000,1,126000,6824713179968000,2,"S",100,2,"kworker/u17:1",1134
-6824713179968000,1,67000,6824713180035000,48,"S",120,41,"kworker/1:1",18800
-6824713180035000,1,535000,6824713180570000,0,"R",120,"[NULL]","swapper/5",0
-6824713180271000,2,74000,6824713180345000,4,"S",120,5,"UsbFfs-worker",20308
-6824713180345000,2,438000,6824713180783000,0,"R",120,"[NULL]","swapper/5",0
-6824713180570000,1,46000,6824713180616000,2,"S",100,2,"kworker/u17:1",1134
-6824713180616000,1,116000,6824713180732000,0,"R",120,"[NULL]","swapper/5",0
-6824713180732000,1,31000,6824713180763000,2,"S",100,2,"kworker/u17:1",1134
-6824713180763000,1,28000,6824713180791000,48,"S",120,41,"kworker/1:1",18800
-6824713180783000,2,71000,6824713180854000,4,"S",120,5,"UsbFfs-worker",20308
-6824713180791000,1,34000,6824713180825000,0,"R",120,"[NULL]","swapper/5",0
-6824713180825000,1,17000,6824713180842000,2,"S",100,2,"kworker/u17:1",1134
-6824713180842000,1,170000,6824713181012000,0,"R",120,"[NULL]","swapper/5",0
-6824713180854000,2,1030000,6824713181884000,0,"R",120,"[NULL]","swapper/5",0
-6824713181012000,1,44000,6824713181056000,2,"S",100,2,"kworker/u17:1",1134
-6824713181056000,1,406000,6824713181462000,0,"R",120,"[NULL]","swapper/5",0
-6824713181462000,1,39000,6824713181501000,2,"S",100,2,"kworker/u17:1",1134
-6824713181501000,1,44000,6824713181545000,48,"S",120,41,"kworker/1:1",18800
-6824713181545000,1,414000,6824713181959000,0,"R",120,"[NULL]","swapper/5",0
-6824713181884000,2,150000,6824713182034000,4,"S",120,5,"UsbFfs-worker",20308
-6824713181959000,1,179000,6824713182138000,7,"S",120,5,"adbd",20305
-6824713182034000,2,6995000,6824713189029000,0,"R",120,"[NULL]","swapper/5",0
-6824713182138000,1,1920000,6824713184058000,0,"R",120,"[NULL]","swapper/5",0
-6824713183637000,3,58000,6824713183695000,6,"S",120,4,"rcu_preempt",7
-6824713183695000,3,1423000,6824713185118000,0,"R",120,"[NULL]","swapper/5",0
-6824713184058000,1,700000,6824713184758000,11,"S",120,9,"rcuop/0",10
-6824713184758000,1,3775000,6824713188533000,0,"R",120,"[NULL]","swapper/5",0
-6824713185118000,3,22000,6824713185140000,6,"S",120,4,"rcu_preempt",7
-6824713185140000,3,5295000,6824713190435000,0,"R",120,"[NULL]","swapper/5",0
-6824713188533000,1,169000,6824713188702000,82,"S",120,5,"shell",20461
-6824713188702000,1,1106000,6824713189808000,0,"R",120,"[NULL]","swapper/5",0
-6824713189029000,2,560000,6824713189589000,7,"S",120,5,"adbd",20305
-6824713189589000,2,668000,6824713190257000,0,"R",120,"[NULL]","swapper/5",0
-6824713189808000,1,118000,6824713189926000,2,"S",100,2,"kworker/u17:1",1134
-6824713189926000,1,53000,6824713189979000,48,"S",120,41,"kworker/1:1",18800
-6824713189979000,1,588000,6824713190567000,0,"R",120,"[NULL]","swapper/5",0
-6824713190257000,2,67000,6824713190324000,4,"S",120,5,"UsbFfs-worker",20308
-6824713190324000,2,156000,6824713190480000,0,"R",120,"[NULL]","swapper/5",0
-6824713190435000,3,53000,6824713190488000,6,"S",120,4,"rcu_preempt",7
-6824713190480000,2,615000,6824713191095000,11,"S",120,9,"rcuop/0",10
-6824713190488000,3,904000,6824713191392000,0,"R",120,"[NULL]","swapper/5",0
-6824713190567000,1,41000,6824713190608000,2,"S",100,2,"kworker/u17:1",1134
-6824713190608000,1,445000,6824713191053000,0,"R",120,"[NULL]","swapper/5",0
-6824713191053000,1,39000,6824713191092000,2,"S",100,2,"kworker/u17:1",1134
-6824713191092000,1,23000,6824713191115000,48,"R+",120,41,"kworker/1:1",18800
-6824713191095000,2,22000,6824713191117000,0,"R",120,"[NULL]","swapper/5",0
-6824713191115000,1,33000,6824713191148000,2,"S",100,2,"kworker/u17:1",1134
-6824713191117000,2,95000,6824713191212000,4,"S",120,5,"UsbFfs-worker",20308
-6824713191148000,1,15000,6824713191163000,48,"S",120,41,"kworker/1:1",18800
-6824713191163000,1,41000,6824713191204000,0,"R",120,"[NULL]","swapper/5",0
-6824713191204000,1,40000,6824713191244000,2,"S",100,2,"kworker/u17:1",1134
-6824713191212000,2,58000,6824713191270000,0,"R",120,"[NULL]","swapper/5",0
-6824713191244000,1,41000,6824713191285000,48,"S",120,41,"kworker/1:1",18800
-6824713191270000,2,141000,6824713191411000,4,"S",120,5,"UsbFfs-worker",20308
-6824713191285000,1,50000,6824713191335000,0,"R",120,"[NULL]","swapper/5",0
-6824713191335000,1,184000,6824713191519000,7,"S",120,5,"adbd",20305
-6824713191392000,3,26000,6824713191418000,6,"S",120,4,"rcu_preempt",7
-6824713191411000,2,3384000,6824713194795000,0,"R",120,"[NULL]","swapper/5",0
-6824713191418000,3,4124000,6824713195542000,0,"R",120,"[NULL]","swapper/5",0
-6824713191519000,1,2312000,6824713193831000,0,"R",120,"[NULL]","swapper/5",0
-6824713193444000,0,76000,6824713193520000,35,"S",120,33,"kworker/0:5",20371
-6824713193520000,0,3109000,6824713196629000,84,"R+",120,68,"ps",20463
-6824713193831000,1,657000,6824713194488000,36,"S",111,34,"SDM_EventThread",685
-6824713194488000,1,600000,6824713195088000,0,"R",120,"[NULL]","swapper/5",0
-6824713194795000,2,411000,6824713195206000,38,"S",120,35,"HwBinder:640_1",721
-6824713195088000,1,141000,6824713195229000,40,"S",97,35,"DispSync",676
-6824713195206000,2,990000,6824713196196000,0,"R",120,"[NULL]","swapper/5",0
-6824713195229000,1,889000,6824713196118000,0,"R",120,"[NULL]","swapper/5",0
-6824713195542000,3,272000,6824713195814000,41,"S",97,35,"app",678
-6824713195814000,3,811000,6824713196625000,0,"R",120,"[NULL]","swapper/5",0
-6824713196118000,1,2042000,6824713198160000,42,"S",120,36,"ndroid.systemui",1664
-6824713196196000,2,19000,6824713196215000,40,"S",97,35,"DispSync",676
-6824713196215000,2,3119000,6824713199334000,0,"R",120,"[NULL]","swapper/5",0
-6824713196625000,3,44000,6824713196669000,6,"S",120,4,"rcu_preempt",7
-6824713196629000,0,168000,6824713196797000,26,"S",49,23,"sugov:0",605
-6824713196669000,3,1654000,6824713198323000,0,"R",120,"[NULL]","swapper/5",0
-6824713196797000,0,30115000,6824713226912000,84,"R+",120,68,"ps",20463
-6824713198160000,1,730000,6824713198890000,0,"R",120,"[NULL]","swapper/5",0
-6824713198323000,3,309000,6824713198632000,43,"S",120,35,"Binder:640_2",675
-6824713198632000,3,5040000,6824713203672000,0,"R",120,"[NULL]","swapper/5",0
-6824713198890000,1,161000,6824713199051000,41,"S",97,35,"app",678
-6824713199051000,1,29000,6824713199080000,0,"R",120,"[NULL]","swapper/5",0
-6824713199080000,1,118000,6824713199198000,26,"S",49,23,"sugov:0",605
-6824713199198000,1,5504000,6824713204702000,0,"R",120,"[NULL]","swapper/5",0
-6824713199334000,2,29000,6824713199363000,40,"S",97,35,"DispSync",676
-6824713199363000,2,4705000,6824713204068000,0,"R",120,"[NULL]","swapper/5",0
-6824713203672000,3,74000,6824713203746000,6,"S",120,4,"rcu_preempt",7
-6824713203746000,3,1079000,6824713204825000,0,"R",120,"[NULL]","swapper/5",0
-6824713204068000,2,436000,6824713204504000,11,"S",120,9,"rcuop/0",10
-6824713204504000,2,743000,6824713205247000,0,"R",120,"[NULL]","swapper/5",0
-6824713204702000,1,215000,6824713204917000,82,"S",120,5,"shell",20461
-6824713204825000,3,28000,6824713204853000,6,"S",120,4,"rcu_preempt",7
-6824713204853000,3,1654000,6824713206507000,0,"R",120,"[NULL]","swapper/5",0
-6824713204917000,1,1067000,6824713205984000,0,"R",120,"[NULL]","swapper/5",0
-6824713205247000,2,966000,6824713206213000,7,"S",120,5,"adbd",20305
-6824713205984000,1,70000,6824713206054000,2,"S",100,2,"kworker/u17:1",1134
-6824713206054000,1,9000,6824713206063000,0,"R",120,"[NULL]","swapper/5",0
-6824713206063000,1,59000,6824713206122000,2,"S",100,2,"kworker/u17:1",1134
-6824713206122000,1,57000,6824713206179000,48,"S",120,41,"kworker/1:1",18800
-6824713206179000,1,100000,6824713206279000,4,"S",120,5,"UsbFfs-worker",20308
-6824713206213000,2,904000,6824713207117000,0,"R",120,"[NULL]","swapper/5",0
-6824713206279000,1,1131000,6824713207410000,0,"R",120,"[NULL]","swapper/5",0
-6824713206507000,3,43000,6824713206550000,2,"S",100,2,"kworker/u17:1",1134
-6824713206550000,3,436000,6824713206986000,0,"R",120,"[NULL]","swapper/5",0
-6824713206986000,3,67000,6824713207053000,2,"S",100,2,"kworker/u17:1",1134
-6824713207053000,3,47000,6824713207100000,49,"S",120,42,"kworker/3:1",17791
-6824713207100000,3,2871000,6824713209971000,0,"R",120,"[NULL]","swapper/5",0
-6824713207117000,2,57000,6824713207174000,2,"S",100,2,"kworker/u17:1",1134
-6824713207174000,2,56000,6824713207230000,31,"S",120,29,"kworker/2:0",18823
-6824713207230000,2,623000,6824713207853000,0,"R",120,"[NULL]","swapper/5",0
-6824713207410000,1,204000,6824713207614000,4,"S",120,5,"UsbFfs-worker",20308
-6824713207614000,1,16701000,6824713224315000,0,"R",120,"[NULL]","swapper/5",0
-6824713207853000,2,179000,6824713208032000,7,"S",120,5,"adbd",20305
-6824713208032000,2,2366000,6824713210398000,0,"R",120,"[NULL]","swapper/5",0
-6824713209971000,3,55000,6824713210026000,6,"S",120,4,"rcu_preempt",7
-6824713210026000,3,1318000,6824713211344000,0,"R",120,"[NULL]","swapper/5",0
-6824713210398000,2,635000,6824713211033000,11,"S",120,9,"rcuop/0",10
-6824713211033000,2,6391000,6824713217424000,0,"R",120,"[NULL]","swapper/5",0
-6824713211344000,3,26000,6824713211370000,6,"S",120,4,"rcu_preempt",7
-6824713211370000,3,5656000,6824713217026000,0,"R",120,"[NULL]","swapper/5",0
-6824713217026000,3,51000,6824713217077000,6,"S",120,4,"rcu_preempt",7
-6824713217077000,3,770000,6824713217847000,0,"R",120,"[NULL]","swapper/5",0
-6824713217424000,2,75000,6824713217499000,11,"S",120,9,"rcuop/0",10
-6824713217499000,2,6882000,6824713224381000,0,"R",120,"[NULL]","swapper/5",0
-6824713217847000,3,19000,6824713217866000,6,"S",120,4,"rcu_preempt",7
-6824713217866000,3,6087000,6824713223953000,0,"R",120,"[NULL]","swapper/5",0
-6824713223953000,3,87000,6824713224040000,6,"S",120,4,"rcu_preempt",7
-6824713224040000,3,879000,6824713224919000,0,"R",120,"[NULL]","swapper/5",0
-6824713224315000,1,256000,6824713224571000,82,"S",120,5,"shell",20461
-6824713224381000,2,258000,6824713224639000,11,"S",120,9,"rcuop/0",10
-6824713224571000,1,589000,6824713225160000,0,"R",120,"[NULL]","swapper/5",0
-6824713224639000,2,1469000,6824713226108000,0,"R",120,"[NULL]","swapper/5",0
-6824713224919000,3,932000,6824713225851000,7,"S",120,5,"adbd",20305
-6824713225160000,1,33000,6824713225193000,6,"S",120,4,"rcu_preempt",7
-6824713225193000,1,2096000,6824713227289000,0,"R",120,"[NULL]","swapper/5",0
-6824713225851000,3,755000,6824713226606000,0,"R",120,"[NULL]","swapper/5",0
-6824713226108000,2,128000,6824713226236000,2,"S",100,2,"kworker/u17:1",1134
-6824713226236000,2,76000,6824713226312000,31,"S",120,29,"kworker/2:0",18823
-6824713226312000,2,35000,6824713226347000,0,"R",120,"[NULL]","swapper/5",0
-6824713226347000,2,23000,6824713226370000,2,"S",100,2,"kworker/u17:1",1134
-6824713226370000,2,20000,6824713226390000,31,"S",120,29,"kworker/2:0",18823
-6824713226390000,2,562000,6824713226952000,0,"R",120,"[NULL]","swapper/5",0
-6824713226606000,3,144000,6824713226750000,4,"S",120,5,"UsbFfs-worker",20308
-6824713226750000,3,199000,6824713226949000,0,"R",120,"[NULL]","swapper/5",0
-6824713226912000,0,65000,6824713226977000,35,"S",120,33,"kworker/0:5",20371
-6824713226949000,3,43000,6824713226992000,2,"S",100,2,"kworker/u17:1",1134
-6824713226952000,2,113000,6824713227065000,16,"S",120,14,"kworker/u16:7",19422
-6824713226977000,0,23808000,6824713250785000,84,"R",120,68,"ps",20463
-6824713226992000,3,43000,6824713227035000,0,"R",120,"[NULL]","swapper/5",0
-6824713227035000,3,61000,6824713227096000,2,"S",100,2,"kworker/u17:1",1134
-6824713227065000,2,78000,6824713227143000,0,"R",120,"[NULL]","swapper/5",0
-6824713227096000,3,66000,6824713227162000,49,"S",120,42,"kworker/3:1",17791
-6824713227143000,2,162000,6824713227305000,4,"S",120,5,"UsbFfs-worker",20308
-6824713227162000,3,446000,6824713227608000,0,"R",120,"[NULL]","swapper/5",0
-6824713227289000,1,566000,6824713227855000,36,"S",111,34,"SDM_EventThread",685
-6824713227305000,2,440000,6824713227745000,0,"R",120,"[NULL]","swapper/5",0
-6824713227608000,3,224000,6824713227832000,7,"S",120,5,"adbd",20305
-6824713227745000,2,443000,6824713228188000,38,"S",120,35,"HwBinder:640_1",721
-6824713227832000,3,1635000,6824713229467000,0,"R",120,"[NULL]","swapper/5",0
-6824713227855000,1,548000,6824713228403000,0,"R",120,"[NULL]","swapper/5",0
-6824713228188000,2,681000,6824713228869000,0,"R",120,"[NULL]","swapper/5",0
-6824713228403000,1,135000,6824713228538000,40,"S",97,35,"DispSync",676
-6824713228538000,1,565000,6824713229103000,0,"R",120,"[NULL]","swapper/5",0
-6824713228869000,2,274000,6824713229143000,41,"S",97,35,"app",678
-6824713229103000,1,1753000,6824713230856000,42,"S",120,36,"ndroid.systemui",1664
-6824713229143000,2,1167000,6824713230310000,0,"R",120,"[NULL]","swapper/5",0
-6824713229467000,3,23000,6824713229490000,40,"S",97,35,"DispSync",676
-6824713229490000,3,1513000,6824713231003000,0,"R",120,"[NULL]","swapper/5",0
-6824713230310000,2,45000,6824713230355000,6,"S",120,4,"rcu_preempt",7
-6824713230355000,2,1542000,6824713231897000,0,"R",120,"[NULL]","swapper/5",0
-6824713230856000,1,642000,6824713231498000,0,"R",120,"[NULL]","swapper/5",0
-6824713231003000,3,258000,6824713231261000,43,"S",120,35,"Binder:640_2",675
-6824713231261000,3,5466000,6824713236727000,0,"R",120,"[NULL]","swapper/5",0
-6824713231498000,1,138000,6824713231636000,41,"S",97,35,"app",678
-6824713231636000,1,6415000,6824713238051000,0,"R",120,"[NULL]","swapper/5",0
-6824713231897000,2,28000,6824713231925000,40,"S",97,35,"DispSync",676
-6824713231925000,2,4745000,6824713236670000,0,"R",120,"[NULL]","swapper/5",0
-6824713236670000,2,70000,6824713236740000,6,"S",120,4,"rcu_preempt",7
-6824713236727000,3,267000,6824713236994000,11,"S",120,9,"rcuop/0",10
-6824713236740000,2,246000,6824713236986000,0,"R",120,"[NULL]","swapper/5",0
-6824713236986000,2,17000,6824713237003000,6,"S",120,4,"rcu_preempt",7
-6824713236994000,3,1550000,6824713238544000,0,"R",120,"[NULL]","swapper/5",0
-6824713237003000,2,3473000,6824713240476000,0,"R",120,"[NULL]","swapper/5",0
-6824713238051000,1,210000,6824713238261000,82,"S",120,5,"shell",20461
-6824713238261000,1,7678000,6824713245939000,0,"R",120,"[NULL]","swapper/5",0
-6824713238544000,3,824000,6824713239368000,7,"S",120,5,"adbd",20305
-6824713239368000,3,631000,6824713239999000,0,"R",120,"[NULL]","swapper/5",0
-6824713239999000,3,127000,6824713240126000,2,"S",100,2,"kworker/u17:1",1134
-6824713240126000,3,61000,6824713240187000,49,"S",120,42,"kworker/3:1",17791
-6824713240187000,3,594000,6824713240781000,0,"R",120,"[NULL]","swapper/5",0
-6824713240476000,2,102000,6824713240578000,4,"S",120,5,"UsbFfs-worker",20308
-6824713240578000,2,560000,6824713241138000,0,"R",120,"[NULL]","swapper/5",0
-6824713240781000,3,38000,6824713240819000,2,"S",100,2,"kworker/u17:1",1134
-6824713240819000,3,32000,6824713240851000,49,"S",120,42,"kworker/3:1",17791
-6824713240851000,3,284000,6824713241135000,0,"R",120,"[NULL]","swapper/5",0
-6824713241135000,3,35000,6824713241170000,2,"S",100,2,"kworker/u17:1",1134
-6824713241138000,2,73000,6824713241211000,4,"S",120,5,"UsbFfs-worker",20308
-6824713241170000,3,27000,6824713241197000,0,"R",120,"[NULL]","swapper/5",0
-6824713241197000,3,40000,6824713241237000,2,"S",100,2,"kworker/u17:1",1134
-6824713241211000,2,447000,6824713241658000,0,"R",120,"[NULL]","swapper/5",0
-6824713241237000,3,43000,6824713241280000,49,"S",120,42,"kworker/3:1",17791
-6824713241280000,3,763000,6824713242043000,0,"R",120,"[NULL]","swapper/5",0
-6824713241658000,2,183000,6824713241841000,4,"S",120,5,"UsbFfs-worker",20308
-6824713241841000,2,1454000,6824713243295000,0,"R",120,"[NULL]","swapper/5",0
-6824713242043000,3,215000,6824713242258000,7,"S",120,5,"adbd",20305
-6824713242258000,3,5163000,6824713247421000,0,"R",120,"[NULL]","swapper/5",0
-6824713243295000,2,43000,6824713243338000,6,"S",120,4,"rcu_preempt",7
-6824713243338000,2,3652000,6824713246990000,0,"R",120,"[NULL]","swapper/5",0
-6824713245939000,1,86000,6824713246025000,57,"S",120,46,"ogle.android.as",15166
-6824713246025000,1,64000,6824713246089000,56,"S",120,46,"ogle.android.as",15167
-6824713246089000,1,9699000,6824713255788000,0,"R",120,"[NULL]","swapper/5",0
-6824713246990000,2,51000,6824713247041000,6,"S",120,4,"rcu_preempt",7
-6824713247041000,2,1235000,6824713248276000,0,"R",120,"[NULL]","swapper/5",0
-6824713247421000,3,487000,6824713247908000,11,"S",120,9,"rcuop/0",10
-6824713247908000,3,4863000,6824713252771000,0,"R",120,"[NULL]","swapper/5",0
-6824713248276000,2,25000,6824713248301000,6,"S",120,4,"rcu_preempt",7
-6824713248301000,2,4882000,6824713253183000,0,"R",120,"[NULL]","swapper/5",0
-6824713250362000,6,413000,6824713250775000,82,"S",120,5,"shell",20461
-6824713250775000,6,72000,6824713250847000,0,"R",120,"[NULL]","swapper/5",0
-6824713250785000,0,74000,6824713250859000,86,"S",0,70,"migration/0",13
-6824713250847000,6,2556000,6824713253403000,84,"R",120,68,"ps",20463
-6824713250859000,0,61000,6824713250920000,0,"R",120,"[NULL]","swapper/5",0
-6824713250920000,0,247000,6824713251167000,26,"S",49,23,"sugov:0",605
-6824713251148000,7,902000,6824713252050000,7,"S",120,5,"adbd",20305
-6824713251167000,0,342000,6824713251509000,0,"R",120,"[NULL]","swapper/5",0
-6824713251509000,0,58000,6824713251567000,8,"S",120,8,"rcuop/6",60
-6824713251567000,0,7123000,6824713258690000,0,"R",120,"[NULL]","swapper/5",0
-6824713252050000,7,3110000,6824713255160000,0,"R",120,"[NULL]","swapper/5",0
-6824713252771000,3,197000,6824713252968000,2,"S",100,2,"kworker/u17:1",1134
-6824713252968000,3,186000,6824713253154000,49,"S",120,42,"kworker/3:1",17791
-6824713253154000,3,188000,6824713253342000,2,"S",100,2,"kworker/u17:1",1134
-6824713253183000,2,568000,6824713253751000,4,"S",120,5,"UsbFfs-worker",20308
-6824713253342000,3,68000,6824713253410000,49,"S",120,42,"kworker/3:1",17791
-6824713253403000,6,156000,6824713253559000,22,"S",49,20,"sugov:4",606
-6824713253410000,3,69000,6824713253479000,2,"S",100,2,"kworker/u17:1",1134
-6824713253479000,3,642000,6824713254121000,0,"R",120,"[NULL]","swapper/5",0
-6824713253559000,6,223000,6824713253782000,84,"R+",120,68,"ps",20463
-6824713253751000,2,72000,6824713253823000,6,"S",120,4,"rcu_preempt",7
-6824713253782000,6,16000,6824713253798000,82,"S",120,5,"shell",20461
-6824713253798000,6,1208000,6824713255006000,84,"x",120,68,"ps",20463
-6824713253823000,2,1690000,6824713255513000,0,"R",120,"[NULL]","swapper/5",0
-6824713254121000,3,94000,6824713254215000,2,"S",100,2,"kworker/u17:1",1134
-6824713254215000,3,534000,6824713254749000,0,"R",120,"[NULL]","swapper/5",0
-6824713254749000,3,113000,6824713254862000,2,"S",100,2,"kworker/u17:1",1134
-6824713254862000,3,213000,6824713255075000,49,"S",120,42,"kworker/3:1",17791
-6824713255006000,6,74037000,6824713329043000,0,"R",120,"[NULL]","swapper/5",0
-6824713255075000,3,5496000,6824713260571000,0,"R",120,"[NULL]","swapper/5",0
-6824713255160000,7,39000,6824713255199000,28,"S",120,26,"rcuos/6",61
-6824713255199000,7,23000,6824713255222000,5,"S",120,7,"rcu_sched",8
-6824713255222000,7,6211000,6824713261433000,0,"R",120,"[NULL]","swapper/5",0
-6824713255513000,2,403000,6824713255916000,4,"S",120,5,"UsbFfs-worker",20308
-6824713255788000,1,140000,6824713255928000,26,"S",49,23,"sugov:0",605
-6824713255916000,2,1029000,6824713256945000,7,"R",120,5,"adbd",20305
-6824713255928000,1,733000,6824713256661000,83,"R+",120,67,"sh",20462
-6824713256661000,1,87000,6824713256748000,26,"S",49,23,"sugov:0",605
-6824713256748000,1,2388000,6824713259136000,83,"S",120,67,"sh",20462
-6824713256945000,2,173000,6824713257118000,2,"S",100,2,"kworker/u17:1",1134
-6824713257118000,2,59000,6824713257177000,31,"R+",120,29,"kworker/2:0",18823
-6824713257177000,2,41000,6824713257218000,2,"S",100,2,"kworker/u17:1",1134
-6824713257218000,2,23000,6824713257241000,79,"S",100,64,"kworker/u17:2",14944
-6824713257241000,2,60000,6824713257301000,31,"R+",120,29,"kworker/2:0",18823
-6824713257301000,2,26000,6824713257327000,79,"S",100,64,"kworker/u17:2",14944
-6824713257327000,2,72000,6824713257399000,31,"S",120,29,"kworker/2:0",18823
-6824713257399000,2,76000,6824713257475000,4,"R",120,5,"UsbFfs-worker",20308
-6824713257475000,2,44000,6824713257519000,79,"S",100,64,"kworker/u17:2",14944
-6824713257519000,2,62000,6824713257581000,4,"R",120,5,"UsbFfs-worker",20308
-6824713257581000,2,65000,6824713257646000,79,"S",100,64,"kworker/u17:2",14944
-6824713257646000,2,44000,6824713257690000,31,"S",120,29,"kworker/2:0",18823
-6824713257690000,2,127000,6824713257817000,7,"S",120,5,"adbd",20305
-6824713257817000,2,122000,6824713257939000,4,"R+",120,5,"UsbFfs-worker",20308
-6824713257939000,2,73000,6824713258012000,26,"S",49,23,"sugov:0",605
-6824713258012000,2,131000,6824713258143000,7,"S",120,5,"adbd",20305
-6824713258143000,2,148000,6824713258291000,4,"S",120,5,"UsbFfs-worker",20308
-6824713258291000,2,1744000,6824713260035000,0,"R",120,"[NULL]","swapper/5",0
-6824713258690000,0,164000,6824713258854000,7,"S",120,5,"adbd",20305
-6824713258854000,0,1935000,6824713260789000,0,"R",120,"[NULL]","swapper/5",0
-6824713259136000,1,895000,6824713260031000,87,"R+",120,71,"ps",20464
-6824713260031000,1,69000,6824713260100000,48,"S",120,41,"kworker/1:1",18800
-6824713260035000,2,103000,6824713260138000,6,"S",120,4,"rcu_preempt",7
-6824713260100000,1,747000,6824713260847000,87,"R+",120,71,"ps",20464
-6824713260138000,2,1298000,6824713261436000,0,"R",120,"[NULL]","swapper/5",0
-6824713260571000,3,513000,6824713261084000,11,"S",120,9,"rcuop/0",10
-6824713260789000,0,106000,6824713260895000,35,"S",120,33,"kworker/0:5",20371
-6824713260847000,1,692000,6824713261539000,36,"S",111,34,"SDM_EventThread",685
-6824713260895000,0,931000,6824713261826000,0,"R",120,"[NULL]","swapper/5",0
-6824713261084000,3,994000,6824713262078000,0,"R",120,"[NULL]","swapper/5",0
-6824713261433000,7,52000,6824713261485000,5,"S",120,7,"rcu_sched",8
-6824713261436000,2,254000,6824713261690000,40,"S",97,35,"DispSync",676
-6824713261485000,7,50000,6824713261535000,28,"S",120,26,"rcuos/6",61
-6824713261535000,7,2709000,6824713264244000,0,"R",120,"[NULL]","swapper/5",0
-6824713261539000,1,1177000,6824713262716000,87,"R+",120,71,"ps",20464
-6824713261690000,2,748000,6824713262438000,0,"R",120,"[NULL]","swapper/5",0
-6824713261826000,0,412000,6824713262238000,38,"S",120,35,"HwBinder:640_1",721
-6824713262078000,3,319000,6824713262397000,41,"S",97,35,"app",678
-6824713262238000,0,529000,6824713262767000,0,"R",120,"[NULL]","swapper/5",0
-6824713262397000,3,11856000,6824713274253000,0,"R",120,"[NULL]","swapper/5",0
-6824713262438000,2,46000,6824713262484000,40,"S",97,35,"DispSync",676
-6824713262484000,2,2645000,6824713265129000,0,"R",120,"[NULL]","swapper/5",0
-6824713262716000,1,92000,6824713262808000,14,"S",120,10,"rcuos/0",11
-6824713262767000,0,2217000,6824713264984000,42,"S",120,36,"ndroid.systemui",1664
-6824713262808000,1,549000,6824713263357000,87,"R+",120,71,"ps",20464
-6824713263357000,1,1008000,6824713264365000,16,"S",120,14,"kworker/u16:7",19422
-6824713264244000,7,55000,6824713264299000,5,"S",120,7,"rcu_sched",8
-6824713264299000,7,7113000,6824713271412000,0,"R",120,"[NULL]","swapper/5",0
-6824713264365000,1,230000,6824713264595000,87,"R+",120,71,"ps",20464
-6824713264595000,1,23000,6824713264618000,76,"S",120,62,"hwrng",215
-6824713264618000,1,6871000,6824713271489000,87,"R+",120,71,"ps",20464
-6824713264984000,0,719000,6824713265703000,0,"R",120,"[NULL]","swapper/5",0
-6824713265129000,2,305000,6824713265434000,43,"S",120,35,"Binder:640_2",675
-6824713265434000,2,29000,6824713265463000,76,"S",120,62,"hwrng",215
-6824713265463000,2,364000,6824713265827000,0,"R",120,"[NULL]","swapper/5",0
-6824713265703000,0,185000,6824713265888000,41,"S",97,35,"app",678
-6824713265827000,2,52000,6824713265879000,40,"S",97,35,"DispSync",676
-6824713265879000,2,818000,6824713266697000,0,"R",120,"[NULL]","swapper/5",0
-6824713265888000,0,23236000,6824713289124000,0,"R",120,"[NULL]","swapper/5",0
-6824713266697000,2,86000,6824713266783000,6,"R+",120,4,"rcu_preempt",7
-6824713266783000,2,33000,6824713266816000,8,"S",120,8,"rcuop/6",60
-6824713266816000,2,36000,6824713266852000,6,"S",120,4,"rcu_preempt",7
-6824713266852000,2,6898000,6824713273750000,0,"R",120,"[NULL]","swapper/5",0
-6824713271412000,7,52000,6824713271464000,5,"S",120,7,"rcu_sched",8
-6824713271464000,7,1149000,6824713272613000,0,"R",120,"[NULL]","swapper/5",0
-6824713271489000,1,125000,6824713271614000,14,"S",120,10,"rcuos/0",11
-6824713271614000,1,43000,6824713271657000,15,"S",120,13,"rcuos/1",21
-6824713271657000,1,2660000,6824713274317000,87,"R+",120,71,"ps",20464
-6824713272613000,7,50000,6824713272663000,5,"S",120,7,"rcu_sched",8
-6824713272663000,7,4324000,6824713276987000,0,"R",120,"[NULL]","swapper/5",0
-6824713273750000,2,109000,6824713273859000,6,"R+",120,4,"rcu_preempt",7
-6824713273859000,2,152000,6824713274011000,8,"S",120,8,"rcuop/6",60
-6824713274011000,2,24000,6824713274035000,23,"S",120,21,"rcuop/2",28
-6824713274035000,2,26000,6824713274061000,6,"S",120,4,"rcu_preempt",7
-6824713274061000,2,6571000,6824713280632000,0,"R",120,"[NULL]","swapper/5",0
-6824713274253000,3,160000,6824713274413000,11,"S",120,9,"rcuop/0",10
-6824713274317000,1,223000,6824713274540000,13,"S",120,12,"rcuop/1",20
-6824713274413000,3,13234000,6824713287647000,0,"R",120,"[NULL]","swapper/5",0
-6824713274540000,1,2103000,6824713276643000,87,"R+",120,71,"ps",20464
-6824713276643000,1,103000,6824713276746000,16,"S",120,14,"kworker/u16:7",19422
-6824713276746000,1,294000,6824713277040000,87,"R+",120,71,"ps",20464
-6824713276987000,7,34000,6824713277021000,5,"S",120,7,"rcu_sched",8
-6824713277021000,7,53046000,6824713330067000,0,"R",120,"[NULL]","swapper/5",0
-6824713277040000,1,41000,6824713277081000,14,"S",120,10,"rcuos/0",11
-6824713277081000,1,23000,6824713277104000,15,"S",120,13,"rcuos/1",21
-6824713277104000,1,2914000,6824713280018000,87,"R+",120,71,"ps",20464
-6824713280018000,1,235000,6824713280253000,26,"S",49,23,"sugov:0",605
-6824713280253000,1,7441000,6824713287694000,87,"R",120,71,"ps",20464
-6824713280632000,2,120000,6824713280752000,26,"S",49,23,"sugov:0",605
-6824713280752000,2,55000,6824713280807000,6,"R+",120,4,"rcu_preempt",7
-6824713280807000,2,27000,6824713280834000,23,"S",120,21,"rcuop/2",28
-6824713280834000,2,20000,6824713280854000,6,"S",120,4,"rcu_preempt",7
-6824713280854000,2,6307000,6824713287161000,0,"R",120,"[NULL]","swapper/5",0
-6824713287161000,2,80000,6824713287241000,6,"S",120,4,"rcu_preempt",7
-6824713287241000,2,805000,6824713288046000,0,"R",120,"[NULL]","swapper/5",0
-6824713287647000,3,85000,6824713287732000,11,"S",120,9,"rcuop/0",10
-6824713287694000,1,49000,6824713287743000,13,"S",120,12,"rcuop/1",20
-6824713287732000,3,6253000,6824713293985000,0,"R",120,"[NULL]","swapper/5",0
-6824713287743000,1,6273000,6824713294016000,87,"R+",120,71,"ps",20464
-6824713288046000,2,19000,6824713288065000,6,"S",120,4,"rcu_preempt",7
-6824713288065000,2,5544000,6824713293609000,0,"R",120,"[NULL]","swapper/5",0
-6824713289124000,0,238000,6824713289362000,60,"D",100,48,"thermal-engine",2490
-6824713289362000,0,803000,6824713290165000,0,"R",120,"[NULL]","swapper/5",0
-6824713290165000,0,67000,6824713290232000,35,"S",120,33,"kworker/0:5",20371
-6824713290232000,0,256000,6824713290488000,60,"S",100,48,"thermal-engine",2490
-6824713290488000,0,3702000,6824713294190000,0,"R",120,"[NULL]","swapper/5",0
-6824713293609000,2,45000,6824713293654000,6,"S",120,4,"rcu_preempt",7
-6824713293654000,2,1390000,6824713295044000,0,"R",120,"[NULL]","swapper/5",0
-6824713293985000,3,43000,6824713294028000,11,"S",120,9,"rcuop/0",10
-6824713294016000,1,29000,6824713294045000,13,"S",120,12,"rcuop/1",20
-6824713294028000,3,1525000,6824713295553000,0,"R",120,"[NULL]","swapper/5",0
-6824713294045000,1,182000,6824713294227000,87,"R",120,71,"ps",20464
-6824713294190000,0,70000,6824713294260000,35,"S",120,33,"kworker/0:5",20371
-6824713294227000,1,650000,6824713294877000,36,"S",111,34,"SDM_EventThread",685
-6824713294260000,0,501000,6824713294761000,0,"R",120,"[NULL]","swapper/5",0
-6824713294761000,0,350000,6824713295111000,38,"S",120,35,"HwBinder:640_1",721
-6824713294877000,1,8453000,6824713303330000,87,"R+",120,71,"ps",20464
-6824713295044000,2,186000,6824713295230000,40,"S",97,35,"DispSync",676
-6824713295111000,0,16000,6824713295127000,0,"R",120,"[NULL]","swapper/5",0
-6824713295127000,0,113000,6824713295240000,38,"S",120,35,"HwBinder:640_1",721
-6824713295230000,2,1013000,6824713296243000,0,"R",120,"[NULL]","swapper/5",0
-6824713295240000,0,922000,6824713296162000,0,"R",120,"[NULL]","swapper/5",0
-6824713295553000,3,326000,6824713295879000,41,"S",97,35,"app",678
-6824713295879000,3,4297000,6824713300176000,0,"R",120,"[NULL]","swapper/5",0
-6824713296162000,0,1958000,6824713298120000,42,"S",120,36,"ndroid.systemui",1664
-6824713296243000,2,31000,6824713296274000,40,"S",97,35,"DispSync",676
-6824713296274000,2,1983000,6824713298257000,0,"R",120,"[NULL]","swapper/5",0
-6824713298120000,0,672000,6824713298792000,0,"R",120,"[NULL]","swapper/5",0
-6824713298257000,2,260000,6824713298517000,43,"S",120,35,"Binder:640_2",675
-6824713298517000,2,708000,6824713299225000,0,"R",120,"[NULL]","swapper/5",0
-6824713298792000,0,153000,6824713298945000,41,"S",97,35,"app",678
-6824713298945000,0,25615000,6824713324560000,0,"R",120,"[NULL]","swapper/5",0
-6824713299225000,2,37000,6824713299262000,40,"S",97,35,"DispSync",676
-6824713299262000,2,1065000,6824713300327000,0,"R",120,"[NULL]","swapper/5",0
-6824713300176000,3,48000,6824713300224000,11,"S",120,9,"rcuop/0",10
-6824713300224000,3,7418000,6824713307642000,0,"R",120,"[NULL]","swapper/5",0
-6824713300327000,2,21000,6824713300348000,76,"S",120,62,"hwrng",215
-6824713300348000,2,36000,6824713300384000,6,"S",120,4,"rcu_preempt",7
-6824713300384000,2,6852000,6824713307236000,0,"R",120,"[NULL]","swapper/5",0
-6824713303330000,1,176000,6824713303506000,26,"S",49,23,"sugov:0",605
-6824713303506000,1,3115000,6824713306621000,87,"R+",120,71,"ps",20464
-6824713306621000,1,71000,6824713306692000,26,"S",49,23,"sugov:0",605
-6824713306692000,1,994000,6824713307686000,87,"R+",120,71,"ps",20464
-6824713307236000,2,69000,6824713307305000,6,"S",120,4,"rcu_preempt",7
-6824713307305000,2,404000,6824713307709000,0,"R",120,"[NULL]","swapper/5",0
-6824713307642000,3,72000,6824713307714000,11,"S",120,9,"rcuop/0",10
-6824713307686000,1,32000,6824713307718000,13,"S",120,12,"rcuop/1",20
-6824713307709000,2,17000,6824713307726000,6,"S",120,4,"rcu_preempt",7
-6824713307714000,3,9638000,6824713317352000,0,"R",120,"[NULL]","swapper/5",0
-6824713307718000,1,9664000,6824713317382000,87,"R+",120,71,"ps",20464
-6824713307726000,2,5944000,6824713313670000,0,"R",120,"[NULL]","swapper/5",0
-6824713313670000,2,31000,6824713313701000,6,"S",120,4,"rcu_preempt",7
-6824713313701000,2,3234000,6824713316935000,0,"R",120,"[NULL]","swapper/5",0
-6824713316935000,2,46000,6824713316981000,6,"S",120,4,"rcu_preempt",7
-6824713316981000,2,773000,6824713317754000,0,"R",120,"[NULL]","swapper/5",0
-6824713317352000,3,56000,6824713317408000,11,"S",120,9,"rcuop/0",10
-6824713317382000,1,116000,6824713317498000,13,"S",120,12,"rcuop/1",20
-6824713317408000,3,6640000,6824713324048000,0,"R",120,"[NULL]","swapper/5",0
-6824713317498000,1,5825000,6824713323323000,87,"R+",120,71,"ps",20464
-6824713317754000,2,15000,6824713317769000,6,"S",120,4,"rcu_preempt",7
-6824713317769000,2,5877000,6824713323646000,0,"R",120,"[NULL]","swapper/5",0
-6824713323323000,1,140000,6824713323463000,26,"S",49,23,"sugov:0",605
-6824713323463000,1,4344000,6824713327807000,87,"R+",120,71,"ps",20464
-6824713323646000,2,54000,6824713323700000,6,"S",120,4,"rcu_preempt",7
-6824713323700000,2,893000,6824713324593000,0,"R",120,"[NULL]","swapper/5",0
-6824713324048000,3,59000,6824713324107000,11,"S",120,9,"rcuop/0",10
-6824713324107000,3,3572000,6824713327679000,0,"R",120,"[NULL]","swapper/5",0
-6824713324560000,0,209000,6824713324769000,13,"S",120,12,"rcuop/1",20
-6824713324593000,2,17000,6824713324610000,6,"S",120,4,"rcu_preempt",7
-6824713324610000,2,2330000,6824713326940000,0,"R",120,"[NULL]","swapper/5",0
-6824713324769000,0,2944000,6824713327713000,0,"R",120,"[NULL]","swapper/5",0
-6824713326940000,2,357000,6824713327297000,16,"D",120,14,"kworker/u16:7",19422
-6824713327297000,2,154000,6824713327451000,0,"R",120,"[NULL]","swapper/5",0
-6824713327451000,2,31000,6824713327482000,16,"S",120,14,"kworker/u16:7",19422
-6824713327482000,2,276000,6824713327758000,0,"R",120,"[NULL]","swapper/5",0
-6824713327679000,3,43000,6824713327722000,32,"S",120,30,"smem_native_rpm",87
-6824713327713000,0,92000,6824713327805000,35,"S",120,33,"kworker/0:5",20371
-6824713327722000,3,1218000,6824713328940000,0,"R",120,"[NULL]","swapper/5",0
-6824713327758000,2,602000,6824713328360000,36,"S",111,34,"SDM_EventThread",685
-6824713327805000,0,570000,6824713328375000,0,"R",120,"[NULL]","swapper/5",0
-6824713327807000,1,48000,6824713327855000,88,"S",0,72,"migration/1",16
-6824713327855000,1,1280000,6824713329135000,0,"R",120,"[NULL]","swapper/5",0
-6824713328360000,2,884000,6824713329244000,0,"R",120,"[NULL]","swapper/5",0
-6824713328375000,0,1267000,6824713329642000,87,"R",120,71,"ps",20464
-6824713328940000,3,397000,6824713329337000,38,"S",120,35,"HwBinder:640_1",721
-6824713329043000,6,147000,6824713329190000,22,"S",49,20,"sugov:4",606
-6824713329135000,1,153000,6824713329288000,40,"S",97,35,"DispSync",676
-6824713329190000,6,433000,6824713329623000,82,"S",120,5,"shell",20461
-6824713329244000,2,244000,6824713329488000,41,"S",97,35,"app",678
-6824713329288000,1,523000,6824713329811000,0,"R",120,"[NULL]","swapper/5",0
-6824713329337000,3,722000,6824713330059000,0,"R",120,"[NULL]","swapper/5",0
-6824713329488000,2,470000,6824713329958000,0,"R",120,"[NULL]","swapper/5",0
-6824713329623000,6,113000,6824713329736000,0,"R",120,"[NULL]","swapper/5",0
-6824713329642000,0,49000,6824713329691000,86,"S",0,70,"migration/0",13
-6824713329691000,0,2040000,6824713331731000,0,"R",120,"[NULL]","swapper/5",0
-6824713329736000,6,3595000,6824713333331000,87,"R+",120,71,"ps",20464
-6824713329811000,1,17000,6824713329828000,40,"S",97,35,"DispSync",676
-6824713329828000,1,2390000,6824713332218000,0,"R",120,"[NULL]","swapper/5",0
-6824713329958000,2,20000,6824713329978000,8,"S",120,8,"rcuop/6",60
-6824713329978000,2,29000,6824713330007000,6,"S",120,4,"rcu_preempt",7
-6824713330007000,2,1145000,6824713331152000,0,"R",120,"[NULL]","swapper/5",0
-6824713330059000,3,1520000,6824713331579000,42,"S",120,36,"ndroid.systemui",1664
-6824713330067000,7,915000,6824713330982000,7,"S",120,5,"adbd",20305
-6824713330982000,7,71506000,6824713402488000,0,"R",120,"[NULL]","swapper/5",0
-6824713331152000,2,172000,6824713331324000,79,"S",100,64,"kworker/u17:2",14944
-6824713331324000,2,62000,6824713331386000,31,"S",120,29,"kworker/2:0",18823
-6824713331386000,2,66000,6824713331452000,2,"S",100,2,"kworker/u17:1",1134
-6824713331452000,2,4000,6824713331456000,79,"S",100,64,"kworker/u17:2",14944
-6824713331456000,2,12000,6824713331468000,31,"S",120,29,"kworker/2:0",18823
-6824713331468000,2,57000,6824713331525000,4,"R",120,5,"UsbFfs-worker",20308
-6824713331525000,2,14000,6824713331539000,79,"S",100,64,"kworker/u17:2",14944
-6824713331539000,2,119000,6824713331658000,4,"S",120,5,"UsbFfs-worker",20308
-6824713331579000,3,5762000,6824713337341000,0,"R",120,"[NULL]","swapper/5",0
-6824713331658000,2,60000,6824713331718000,0,"R",120,"[NULL]","swapper/5",0
-6824713331718000,2,33000,6824713331751000,79,"S",100,64,"kworker/u17:2",14944
-6824713331731000,0,215000,6824713331946000,43,"S",120,35,"Binder:640_2",675
-6824713331751000,2,33000,6824713331784000,0,"R",120,"[NULL]","swapper/5",0
-6824713331784000,2,39000,6824713331823000,79,"S",100,64,"kworker/u17:2",14944
-6824713331823000,2,43000,6824713331866000,31,"S",120,29,"kworker/2:0",18823
-6824713331866000,2,172000,6824713332038000,4,"S",120,5,"UsbFfs-worker",20308
-6824713331946000,0,667000,6824713332613000,0,"R",120,"[NULL]","swapper/5",0
-6824713332038000,2,397000,6824713332435000,7,"S",120,5,"adbd",20305
-6824713332218000,1,104000,6824713332322000,41,"S",97,35,"app",678
-6824713332322000,1,30785000,6824713363107000,0,"R",120,"[NULL]","swapper/5",0
-6824713332435000,2,4516000,6824713336951000,0,"R",120,"[NULL]","swapper/5",0
-6824713332613000,0,24000,6824713332637000,40,"S",97,35,"DispSync",676
-6824713332637000,0,5094000,6824713337731000,0,"R",120,"[NULL]","swapper/5",0
-6824713333331000,6,103000,6824713333434000,22,"S",49,20,"sugov:4",606
-6824713333434000,6,9802000,6824713343236000,87,"R+",120,71,"ps",20464
-6824713336951000,2,72000,6824713337023000,6,"S",120,4,"rcu_preempt",7
-6824713337023000,2,6609000,6824713343632000,0,"R",120,"[NULL]","swapper/5",0
-6824713337341000,3,53000,6824713337394000,11,"S",120,9,"rcuop/0",10
-6824713337394000,3,14884000,6824713352278000,0,"R",120,"[NULL]","swapper/5",0
-6824713337731000,0,167000,6824713337898000,13,"S",120,12,"rcuop/1",20
-6824713337898000,0,14895000,6824713352793000,0,"R",120,"[NULL]","swapper/5",0
-6824713343236000,6,17000,6824713343253000,22,"S",49,20,"sugov:4",606
-6824713343253000,6,797000,6824713344050000,87,"R+",120,71,"ps",20464
-6824713343632000,2,147000,6824713343779000,26,"S",49,23,"sugov:0",605
-6824713343779000,2,140000,6824713343919000,6,"R+",120,4,"rcu_preempt",7
-6824713343919000,2,29000,6824713343948000,8,"S",120,8,"rcuop/6",60
-6824713343948000,2,28000,6824713343976000,6,"S",120,4,"rcu_preempt",7
-6824713343976000,2,7683000,6824713351659000,0,"R",120,"[NULL]","swapper/5",0
-6824713344050000,6,47000,6824713344097000,82,"R+",120,5,"shell",20461
-6824713344097000,6,32000,6824713344129000,22,"S",49,20,"sugov:4",606
-6824713344129000,6,10000,6824713344139000,82,"S",120,5,"shell",20461
-6824713344139000,6,5756000,6824713349895000,87,"R+",120,71,"ps",20464
-6824713349895000,6,389000,6824713350284000,7,"S",120,5,"adbd",20305
-6824713350284000,6,1235000,6824713351519000,87,"R+",120,71,"ps",20464
-6824713351519000,6,22000,6824713351541000,22,"S",49,20,"sugov:4",606
-6824713351541000,6,108000,6824713351649000,79,"S",100,64,"kworker/u17:2",14944
-6824713351649000,6,56000,6824713351705000,3,"S",120,3,"kworker/6:1",14833
-6824713351659000,2,259000,6824713351918000,6,"R+",120,4,"rcu_preempt",7
-6824713351705000,6,212000,6824713351917000,87,"R+",120,71,"ps",20464
-6824713351917000,6,39000,6824713351956000,79,"S",100,64,"kworker/u17:2",14944
-6824713351918000,2,591000,6824713352509000,8,"S",120,8,"rcuop/6",60
-6824713351956000,6,11000,6824713351967000,3,"S",120,3,"kworker/6:1",14833
-6824713351967000,6,121000,6824713352088000,87,"R",120,71,"ps",20464
-6824713352088000,6,38000,6824713352126000,79,"S",100,64,"kworker/u17:2",14944
-6824713352126000,6,58000,6824713352184000,87,"R+",120,71,"ps",20464
-6824713352184000,6,60000,6824713352244000,79,"S",100,64,"kworker/u17:2",14944
-6824713352244000,6,24000,6824713352268000,3,"S",120,3,"kworker/6:1",14833
-6824713352268000,6,6413000,6824713358681000,87,"R+",120,71,"ps",20464
-6824713352278000,3,219000,6824713352497000,11,"S",120,9,"rcuop/0",10
-6824713352497000,3,11953000,6824713364450000,0,"R",120,"[NULL]","swapper/5",0
-6824713352509000,2,289000,6824713352798000,4,"R+",120,5,"UsbFfs-worker",20308
-6824713352793000,0,205000,6824713352998000,13,"S",120,12,"rcuop/1",20
-6824713352798000,2,418000,6824713353216000,7,"S",120,5,"adbd",20305
-6824713352998000,0,8273000,6824713361271000,0,"R",120,"[NULL]","swapper/5",0
-6824713353216000,2,150000,6824713353366000,4,"R+",120,5,"UsbFfs-worker",20308
-6824713353366000,2,154000,6824713353520000,7,"S",120,5,"adbd",20305
-6824713353520000,2,163000,6824713353683000,4,"S",120,5,"UsbFfs-worker",20308
-6824713353683000,2,57000,6824713353740000,6,"S",120,4,"rcu_preempt",7
-6824713353740000,2,7167000,6824713360907000,0,"R",120,"[NULL]","swapper/5",0
-6824713358681000,6,60000,6824713358741000,82,"S",120,5,"shell",20461
-6824713358741000,6,311000,6824713359052000,7,"S",120,5,"adbd",20305
-6824713359052000,6,875000,6824713359927000,87,"R+",120,71,"ps",20464
-6824713359927000,6,41000,6824713359968000,3,"S",120,3,"kworker/6:1",14833
-6824713359968000,6,3312000,6824713363280000,87,"R",120,71,"ps",20464
-6824713360907000,2,128000,6824713361035000,6,"R+",120,4,"rcu_preempt",7
-6824713361035000,2,355000,6824713361390000,8,"S",120,8,"rcuop/6",60
-6824713361271000,0,118000,6824713361389000,79,"S",100,64,"kworker/u17:2",14944
-6824713361389000,0,127000,6824713361516000,35,"R+",120,33,"kworker/0:5",20371
-6824713361390000,2,51000,6824713361441000,6,"S",120,4,"rcu_preempt",7
-6824713361441000,2,95000,6824713361536000,0,"R",120,"[NULL]","swapper/5",0
-6824713361516000,0,44000,6824713361560000,79,"S",100,64,"kworker/u17:2",14944
-6824713361536000,2,952000,6824713362488000,36,"S",111,34,"SDM_EventThread",685
-6824713361560000,0,61000,6824713361621000,35,"R+",120,33,"kworker/0:5",20371
-6824713361621000,0,33000,6824713361654000,79,"S",100,64,"kworker/u17:2",14944
-6824713361654000,0,67000,6824713361721000,35,"S",120,33,"kworker/0:5",20371
-6824713361721000,0,80000,6824713361801000,0,"R",120,"[NULL]","swapper/5",0
-6824713361801000,0,57000,6824713361858000,79,"S",100,64,"kworker/u17:2",14944
-6824713361858000,0,46000,6824713361904000,0,"R",120,"[NULL]","swapper/5",0
-6824713361904000,0,39000,6824713361943000,79,"S",100,64,"kworker/u17:2",14944
-6824713361943000,0,43000,6824713361986000,0,"R",120,"[NULL]","swapper/5",0
-6824713361986000,0,70000,6824713362056000,79,"S",100,64,"kworker/u17:2",14944
-6824713362056000,0,69000,6824713362125000,35,"S",120,33,"kworker/0:5",20371
-6824713362125000,0,232000,6824713362357000,0,"R",120,"[NULL]","swapper/5",0
-6824713362357000,0,537000,6824713362894000,38,"S",120,35,"HwBinder:640_1",721
-6824713362488000,2,279000,6824713362767000,4,"R+",120,5,"UsbFfs-worker",20308
-6824713362767000,2,401000,6824713363168000,7,"S",120,5,"adbd",20305
-6824713362894000,0,738000,6824713363632000,0,"R",120,"[NULL]","swapper/5",0
-6824713363107000,1,274000,6824713363381000,40,"S",97,35,"DispSync",676
-6824713363168000,2,157000,6824713363325000,4,"R+",120,5,"UsbFfs-worker",20308
-6824713363280000,6,49000,6824713363329000,22,"S",49,20,"sugov:4",606
-6824713363325000,2,157000,6824713363482000,7,"S",120,5,"adbd",20305
-6824713363329000,6,6630000,6824713369959000,87,"R+",120,71,"ps",20464
-6824713363381000,1,919000,6824713364300000,0,"R",120,"[NULL]","swapper/5",0
-6824713363482000,2,776000,6824713364258000,16,"S",120,14,"kworker/u16:7",19422
-6824713363632000,0,355000,6824713363987000,41,"S",97,35,"app",678
-6824713363987000,0,2520000,6824713366507000,0,"R",120,"[NULL]","swapper/5",0
-6824713364258000,2,164000,6824713364422000,4,"S",120,5,"UsbFfs-worker",20308
-6824713364300000,1,2117000,6824713366417000,42,"S",120,36,"ndroid.systemui",1664
-6824713364422000,2,2600000,6824713367022000,0,"R",120,"[NULL]","swapper/5",0
-6824713364450000,3,65000,6824713364515000,40,"S",97,35,"DispSync",676
-6824713364515000,3,13500000,6824713378015000,0,"R",120,"[NULL]","swapper/5",0
-6824713366417000,1,380000,6824713366797000,0,"R",120,"[NULL]","swapper/5",0
-6824713366507000,0,360000,6824713366867000,43,"S",120,35,"Binder:640_2",675
-6824713366797000,1,143000,6824713366940000,41,"S",97,35,"app",678
-6824713366867000,0,5605000,6824713372472000,0,"R",120,"[NULL]","swapper/5",0
-6824713366940000,1,28138000,6824713395078000,0,"R",120,"[NULL]","swapper/5",0
-6824713367022000,2,33000,6824713367055000,40,"S",97,35,"DispSync",676
-6824713367055000,2,85000,6824713367140000,6,"R+",120,4,"rcu_preempt",7
-6824713367140000,2,409000,6824713367549000,8,"S",120,8,"rcuop/6",60
-6824713367549000,2,34000,6824713367583000,6,"S",120,4,"rcu_preempt",7
-6824713367583000,2,5336000,6824713372919000,0,"R",120,"[NULL]","swapper/5",0
-6824713369959000,6,65000,6824713370024000,82,"R+",120,5,"shell",20461
-6824713370024000,6,36000,6824713370060000,22,"S",49,20,"sugov:4",606
-6824713370060000,6,15000,6824713370075000,82,"S",120,5,"shell",20461
-6824713370075000,6,299000,6824713370374000,7,"S",120,5,"adbd",20305
-6824713370374000,6,10921000,6824713381295000,87,"R+",120,71,"ps",20464
-6824713372472000,0,237000,6824713372709000,79,"R+",100,64,"kworker/u17:2",14944
-6824713372709000,0,188000,6824713372897000,26,"S",49,23,"sugov:0",605
-6824713372897000,0,74000,6824713372971000,79,"S",100,64,"kworker/u17:2",14944
-6824713372919000,2,89000,6824713373008000,2,"S",100,2,"kworker/u17:1",1134
-6824713372971000,0,177000,6824713373148000,35,"R+",120,33,"kworker/0:5",20371
-6824713373008000,2,144000,6824713373152000,0,"R",120,"[NULL]","swapper/5",0
-6824713373148000,0,64000,6824713373212000,79,"S",100,64,"kworker/u17:2",14944
-6824713373152000,2,734000,6824713373886000,4,"R+",120,5,"UsbFfs-worker",20308
-6824713373212000,0,142000,6824713373354000,35,"R+",120,33,"kworker/0:5",20371
-6824713373354000,0,79000,6824713373433000,79,"S",100,64,"kworker/u17:2",14944
-6824713373433000,0,170000,6824713373603000,35,"S",120,33,"kworker/0:5",20371
-6824713373603000,0,8922000,6824713382525000,0,"R",120,"[NULL]","swapper/5",0
-6824713373886000,2,518000,6824713374404000,7,"S",120,5,"adbd",20305
-6824713374404000,2,168000,6824713374572000,6,"R+",120,4,"rcu_preempt",7
-6824713374572000,2,494000,6824713375066000,8,"S",120,8,"rcuop/6",60
-6824713375066000,2,44000,6824713375110000,6,"S",120,4,"rcu_preempt",7
-6824713375110000,2,127000,6824713375237000,4,"R+",120,5,"UsbFfs-worker",20308
-6824713375237000,2,235000,6824713375472000,7,"S",120,5,"adbd",20305
-6824713375472000,2,230000,6824713375702000,4,"S",120,5,"UsbFfs-worker",20308
-6824713375702000,2,1343000,6824713377045000,0,"R",120,"[NULL]","swapper/5",0
-6824713377045000,2,741000,6824713377786000,16,"S",120,14,"kworker/u16:7",19422
-6824713377786000,2,2753000,6824713380539000,0,"R",120,"[NULL]","swapper/5",0
-6824713378015000,3,111000,6824713378126000,32,"S",120,30,"smem_native_rpm",87
-6824713378126000,3,5664000,6824713383790000,0,"R",120,"[NULL]","swapper/5",0
-6824713380539000,2,133000,6824713380672000,26,"S",49,23,"sugov:0",605
-6824713380672000,2,103000,6824713380775000,6,"R+",120,4,"rcu_preempt",7
-6824713380775000,2,390000,6824713381165000,8,"S",120,8,"rcuop/6",60
-6824713381165000,2,41000,6824713381206000,6,"R+",120,4,"rcu_preempt",7
-6824713381206000,2,75000,6824713381281000,26,"S",49,23,"sugov:0",605
-6824713381281000,2,45000,6824713381326000,6,"S",120,4,"rcu_preempt",7
-6824713381295000,6,45000,6824713381340000,22,"S",49,20,"sugov:4",606
-6824713381326000,2,1876000,6824713383202000,0,"R",120,"[NULL]","swapper/5",0
-6824713381340000,6,66000,6824713381406000,82,"S",120,5,"shell",20461
-6824713381406000,6,288000,6824713381694000,7,"S",120,5,"adbd",20305
-6824713381694000,6,1546000,6824713383240000,87,"R+",120,71,"ps",20464
-6824713382525000,0,114000,6824713382639000,79,"S",100,64,"kworker/u17:2",14944
-6824713382639000,0,173000,6824713382812000,35,"S",120,33,"kworker/0:5",20371
-6824713382812000,0,744000,6824713383556000,0,"R",120,"[NULL]","swapper/5",0
-6824713383202000,2,136000,6824713383338000,4,"S",120,5,"UsbFfs-worker",20308
-6824713383240000,6,170000,6824713383410000,22,"D",49,20,"sugov:4",606
-6824713383338000,2,443000,6824713383781000,0,"R",120,"[NULL]","swapper/5",0
-6824713383410000,6,5051000,6824713388461000,87,"R+",120,71,"ps",20464
-6824713383556000,0,102000,6824713383658000,79,"S",100,64,"kworker/u17:2",14944
-6824713383658000,0,115000,6824713383773000,35,"R+",120,33,"kworker/0:5",20371
-6824713383773000,0,53000,6824713383826000,79,"S",100,64,"kworker/u17:2",14944
-6824713383781000,2,83000,6824713383864000,4,"S",120,5,"UsbFfs-worker",20308
-6824713383790000,3,60000,6824713383850000,32,"S",120,30,"smem_native_rpm",87
-6824713383826000,0,167000,6824713383993000,35,"S",120,33,"kworker/0:5",20371
-6824713383850000,3,11312000,6824713395162000,0,"R",120,"[NULL]","swapper/5",0
-6824713383864000,2,90000,6824713383954000,0,"R",120,"[NULL]","swapper/5",0
-6824713383954000,2,184000,6824713384138000,4,"R+",120,5,"UsbFfs-worker",20308
-6824713383993000,0,6047000,6824713390040000,0,"R",120,"[NULL]","swapper/5",0
-6824713384138000,2,253000,6824713384391000,7,"S",120,5,"adbd",20305
-6824713384362000,4,24000,6824713384386000,22,"S",49,20,"sugov:4",606
-6824713384386000,4,18375000,6824713402761000,0,"R",120,"[NULL]","swapper/5",0
-6824713384391000,2,105000,6824713384496000,4,"R+",120,5,"UsbFfs-worker",20308
-6824713384496000,2,149000,6824713384645000,7,"S",120,5,"adbd",20305
-6824713384645000,2,120000,6824713384765000,4,"S",120,5,"UsbFfs-worker",20308
-6824713384765000,2,2176000,6824713386941000,0,"R",120,"[NULL]","swapper/5",0
-6824713386941000,2,96000,6824713387037000,6,"R+",120,4,"rcu_preempt",7
-6824713387037000,2,340000,6824713387377000,8,"S",120,8,"rcuop/6",60
-6824713387377000,2,41000,6824713387418000,6,"S",120,4,"rcu_preempt",7
-6824713387418000,2,3209000,6824713390627000,0,"R",120,"[NULL]","swapper/5",0
-6824713388461000,6,29000,6824713388490000,82,"S",120,5,"shell",20461
-6824713388490000,6,145000,6824713388635000,7,"S",120,5,"adbd",20305
-6824713388635000,6,3783000,6824713392418000,87,"R+",120,71,"ps",20464
-6824713390040000,0,142000,6824713390182000,79,"S",100,64,"kworker/u17:2",14944
-6824713390182000,0,178000,6824713390360000,35,"S",120,33,"kworker/0:5",20371
-6824713390360000,0,476000,6824713390836000,0,"R",120,"[NULL]","swapper/5",0
-6824713390627000,2,119000,6824713390746000,4,"S",120,5,"UsbFfs-worker",20308
-6824713390746000,2,516000,6824713391262000,0,"R",120,"[NULL]","swapper/5",0
-6824713390836000,0,87000,6824713390923000,79,"S",100,64,"kworker/u17:2",14944
-6824713390923000,0,144000,6824713391067000,35,"S",120,33,"kworker/0:5",20371
-6824713391067000,0,424000,6824713391491000,0,"R",120,"[NULL]","swapper/5",0
-6824713391262000,2,94000,6824713391356000,4,"S",120,5,"UsbFfs-worker",20308
-6824713391356000,2,737000,6824713392093000,0,"R",120,"[NULL]","swapper/5",0
-6824713391491000,0,76000,6824713391567000,79,"S",100,64,"kworker/u17:2",14944
-6824713391567000,0,314000,6824713391881000,0,"R",120,"[NULL]","swapper/5",0
-6824713391881000,0,87000,6824713391968000,79,"S",100,64,"kworker/u17:2",14944
-6824713391968000,0,163000,6824713392131000,35,"S",120,33,"kworker/0:5",20371
-6824713392093000,2,134000,6824713392227000,4,"R+",120,5,"UsbFfs-worker",20308
-6824713392131000,0,1225000,6824713393356000,0,"R",120,"[NULL]","swapper/5",0
-6824713392227000,2,294000,6824713392521000,7,"S",120,5,"adbd",20305
-6824713392418000,6,21000,6824713392439000,82,"S",120,5,"shell",20461
-6824713392439000,6,7047000,6824713399486000,87,"R+",120,71,"ps",20464
-6824713392521000,2,105000,6824713392626000,4,"R+",120,5,"UsbFfs-worker",20308
-6824713392626000,2,812000,6824713393438000,7,"S",120,5,"adbd",20305
-6824713393356000,0,90000,6824713393446000,79,"S",100,64,"kworker/u17:2",14944
-6824713393438000,2,137000,6824713393575000,6,"S",120,4,"rcu_preempt",7
-6824713393446000,0,64000,6824713393510000,35,"S",120,33,"kworker/0:5",20371
-6824713393510000,0,41000,6824713393551000,0,"R",120,"[NULL]","swapper/5",0
-6824713393551000,0,67000,6824713393618000,79,"S",100,64,"kworker/u17:2",14944
-6824713393575000,2,258000,6824713393833000,4,"S",120,5,"UsbFfs-worker",20308
-6824713393618000,0,173000,6824713393791000,0,"R",120,"[NULL]","swapper/5",0
-6824713393791000,0,72000,6824713393863000,79,"S",100,64,"kworker/u17:2",14944
-6824713393833000,2,136000,6824713393969000,0,"R",120,"[NULL]","swapper/5",0
-6824713393863000,0,110000,6824713393973000,35,"R+",120,33,"kworker/0:5",20371
-6824713393969000,2,167000,6824713394136000,4,"S",120,5,"UsbFfs-worker",20308
-6824713393973000,0,35000,6824713394008000,79,"S",100,64,"kworker/u17:2",14944
-6824713394008000,0,46000,6824713394054000,35,"S",120,33,"kworker/0:5",20371
-6824713394054000,0,41000,6824713394095000,0,"R",120,"[NULL]","swapper/5",0
-6824713394095000,0,67000,6824713394162000,79,"S",100,64,"kworker/u17:2",14944
-6824713394136000,2,347000,6824713394483000,0,"R",120,"[NULL]","swapper/5",0
-6824713394162000,0,179000,6824713394341000,0,"R",120,"[NULL]","swapper/5",0
-6824713394341000,0,59000,6824713394400000,79,"S",100,64,"kworker/u17:2",14944
-6824713394400000,0,224000,6824713394624000,35,"S",120,33,"kworker/0:5",20371
-6824713394483000,2,486000,6824713394969000,36,"S",111,34,"SDM_EventThread",685
-6824713394624000,0,46000,6824713394670000,0,"R",120,"[NULL]","swapper/5",0
-6824713394670000,0,199000,6824713394869000,40,"S",97,35,"DispSync",676
-6824713394869000,0,625000,6824713395494000,0,"R",120,"[NULL]","swapper/5",0
-6824713394969000,2,86000,6824713395055000,4,"R+",120,5,"UsbFfs-worker",20308
-6824713395055000,2,184000,6824713395239000,7,"S",120,5,"adbd",20305
-6824713395078000,1,283000,6824713395361000,41,"S",97,35,"app",678
-6824713395162000,3,322000,6824713395484000,38,"S",120,35,"HwBinder:640_1",721
-6824713395239000,2,104000,6824713395343000,4,"R+",120,5,"UsbFfs-worker",20308
-6824713395343000,2,155000,6824713395498000,7,"S",120,5,"adbd",20305
-6824713395361000,1,1958000,6824713397319000,0,"R",120,"[NULL]","swapper/5",0
-6824713395484000,3,8157000,6824713403641000,0,"R",120,"[NULL]","swapper/5",0
-6824713395494000,0,49000,6824713395543000,40,"S",97,35,"DispSync",676
-6824713395498000,2,120000,6824713395618000,4,"S",120,5,"UsbFfs-worker",20308
-6824713395543000,0,1769000,6824713397312000,42,"S",120,36,"ndroid.systemui",1664
-6824713395618000,2,7707000,6824713403325000,0,"R",120,"[NULL]","swapper/5",0
-6824713397312000,0,423000,6824713397735000,0,"R",120,"[NULL]","swapper/5",0
-6824713397319000,1,268000,6824713397587000,43,"S",120,35,"Binder:640_2",675
-6824713397587000,1,483000,6824713398070000,0,"R",120,"[NULL]","swapper/5",0
-6824713397735000,0,162000,6824713397897000,41,"S",97,35,"app",678
-6824713397897000,0,2323000,6824713400220000,0,"R",120,"[NULL]","swapper/5",0
-6824713398070000,1,74000,6824713398144000,40,"S",97,35,"DispSync",676
-6824713398144000,1,3426000,6824713401570000,0,"R",120,"[NULL]","swapper/5",0
-6824713399486000,6,30000,6824713399516000,82,"S",120,5,"shell",20461
-6824713399516000,6,162000,6824713399678000,7,"S",120,5,"adbd",20305
-6824713399678000,6,3250000,6824713402928000,87,"R+",120,71,"ps",20464
-6824713400220000,0,111000,6824713400331000,79,"S",100,64,"kworker/u17:2",14944
-6824713400331000,0,120000,6824713400451000,35,"S",120,33,"kworker/0:5",20371
-6824713400451000,0,43000,6824713400494000,4,"R",120,5,"UsbFfs-worker",20308
-6824713400494000,0,70000,6824713400564000,79,"S",100,64,"kworker/u17:2",14944
-6824713400564000,0,40000,6824713400604000,35,"R+",120,33,"kworker/0:5",20371
-6824713400604000,0,34000,6824713400638000,79,"S",100,64,"kworker/u17:2",14944
-6824713400638000,0,17000,6824713400655000,35,"S",120,33,"kworker/0:5",20371
-6824713400655000,0,97000,6824713400752000,4,"S",120,5,"UsbFfs-worker",20308
-6824713400752000,0,71000,6824713400823000,79,"S",100,64,"kworker/u17:2",14944
-6824713400823000,0,363000,6824713401186000,0,"R",120,"[NULL]","swapper/5",0
-6824713401186000,0,78000,6824713401264000,79,"S",100,64,"kworker/u17:2",14944
-6824713401264000,0,103000,6824713401367000,35,"S",120,33,"kworker/0:5",20371
-6824713401367000,0,329000,6824713401696000,0,"R",120,"[NULL]","swapper/5",0
-6824713401570000,1,237000,6824713401807000,4,"S",120,5,"UsbFfs-worker",20308
-6824713401696000,0,372000,6824713402068000,7,"S",120,5,"adbd",20305
-6824713401807000,1,2137000,6824713403944000,0,"R",120,"[NULL]","swapper/5",0
-6824713402068000,0,1411000,6824713403479000,0,"R",120,"[NULL]","swapper/5",0
-6824713402488000,7,51000,6824713402539000,82,"S",120,5,"shell",20461
-6824713402539000,7,4230000,6824713406769000,0,"R",120,"[NULL]","swapper/5",0
-6824713402761000,4,165000,6824713402926000,7,"S",120,5,"adbd",20305
-6824713402926000,4,350000,6824713403276000,0,"R",120,"[NULL]","swapper/5",0
-6824713402928000,6,24000,6824713402952000,89,"S",0,73,"migration/6",56
-6824713402952000,6,43000,6824713402995000,22,"S",49,20,"sugov:4",606
-6824713402995000,6,4234000,6824713407229000,0,"R",120,"[NULL]","swapper/5",0
-6824713403276000,4,53289000,6824713456565000,87,"R",120,71,"ps",20464
-6824713403325000,2,97000,6824713403422000,25,"S",120,24,"ksoftirqd/2",25
-6824713403422000,2,498000,6824713403920000,0,"R",120,"[NULL]","swapper/5",0
-6824713403479000,0,104000,6824713403583000,79,"S",100,64,"kworker/u17:2",14944
-6824713403583000,0,99000,6824713403682000,35,"S",120,33,"kworker/0:5",20371
-6824713403641000,3,96000,6824713403737000,6,"S",120,4,"rcu_preempt",7
-6824713403682000,0,507000,6824713404189000,0,"R",120,"[NULL]","swapper/5",0
-6824713403737000,3,885000,6824713404622000,0,"R",120,"[NULL]","swapper/5",0
-6824713403920000,2,530000,6824713404450000,8,"S",120,8,"rcuop/6",60
-6824713403944000,1,83000,6824713404027000,4,"S",120,5,"UsbFfs-worker",20308
-6824713404027000,1,662000,6824713404689000,0,"R",120,"[NULL]","swapper/5",0
-6824713404189000,0,132000,6824713404321000,79,"R+",100,64,"kworker/u17:2",14944
-6824713404321000,0,140000,6824713404461000,26,"S",49,23,"sugov:0",605
-6824713404450000,2,572000,6824713405022000,0,"R",120,"[NULL]","swapper/5",0
-6824713404461000,0,55000,6824713404516000,79,"S",100,64,"kworker/u17:2",14944
-6824713404516000,0,125000,6824713404641000,35,"S",120,33,"kworker/0:5",20371
-6824713404622000,3,59000,6824713404681000,2,"S",100,2,"kworker/u17:1",1134
-6824713404641000,0,3779000,6824713408420000,0,"R",120,"[NULL]","swapper/5",0
-6824713404681000,3,582000,6824713405263000,0,"R",120,"[NULL]","swapper/5",0
-6824713404689000,1,62000,6824713404751000,6,"S",120,4,"rcu_preempt",7
-6824713404751000,1,4130000,6824713408881000,0,"R",120,"[NULL]","swapper/5",0
-6824713405022000,2,120000,6824713405142000,4,"S",120,5,"UsbFfs-worker",20308
-6824713405142000,2,330000,6824713405472000,0,"R",120,"[NULL]","swapper/5",0
-6824713405263000,3,117000,6824713405380000,2,"S",100,2,"kworker/u17:1",1134
-6824713405380000,3,138000,6824713405518000,49,"S",120,42,"kworker/3:1",17791
-6824713405472000,2,245000,6824713405717000,4,"S",120,5,"UsbFfs-worker",20308
-6824713405518000,3,2372000,6824713407890000,0,"R",120,"[NULL]","swapper/5",0
-6824713405717000,2,2451000,6824713408168000,0,"R",120,"[NULL]","swapper/5",0
-6824713405788000,5,62000,6824713405850000,7,"S",120,5,"adbd",20305
-6824713405850000,5,1152000,6824713407002000,0,"R",120,"[NULL]","swapper/5",0
-6824713406769000,7,10000,6824713406779000,9,"S",120,6,"rcuop/4",44
-6824713406779000,7,26544000,6824713433323000,0,"R",120,"[NULL]","swapper/5",0
-6824713407002000,5,29000,6824713407031000,82,"S",120,5,"shell",20461
-6824713407031000,5,7986000,6824713415017000,0,"R",120,"[NULL]","swapper/5",0
-6824713407229000,6,96000,6824713407325000,7,"S",120,5,"adbd",20305
-6824713407325000,6,1876000,6824713409201000,0,"R",120,"[NULL]","swapper/5",0
-6824713407890000,3,127000,6824713408017000,2,"S",100,2,"kworker/u17:1",1134
-6824713408017000,3,114000,6824713408131000,49,"S",120,42,"kworker/3:1",17791
-6824713408131000,3,8216000,6824713416347000,0,"R",120,"[NULL]","swapper/5",0
-6824713408168000,2,97000,6824713408265000,4,"S",120,5,"UsbFfs-worker",20308
-6824713408265000,2,326000,6824713408591000,0,"R",120,"[NULL]","swapper/5",0
-6824713408420000,0,106000,6824713408526000,2,"S",100,2,"kworker/u17:1",1134
-6824713408526000,0,129000,6824713408655000,35,"S",120,33,"kworker/0:5",20371
-6824713408591000,2,198000,6824713408789000,2,"S",100,2,"kworker/u17:1",1134
-6824713408655000,0,53000,6824713408708000,0,"R",120,"[NULL]","swapper/5",0
-6824713408708000,0,44000,6824713408752000,79,"S",100,64,"kworker/u17:2",14944
-6824713408752000,0,7418000,6824713416170000,0,"R",120,"[NULL]","swapper/5",0
-6824713408789000,2,105000,6824713408894000,31,"S",120,29,"kworker/2:0",18823
-6824713408881000,1,261000,6824713409142000,4,"S",120,5,"UsbFfs-worker",20308
-6824713408894000,2,1471000,6824713410365000,0,"R",120,"[NULL]","swapper/5",0
-6824713409142000,1,888000,6824713410030000,0,"R",120,"[NULL]","swapper/5",0
-6824713409201000,6,60000,6824713409261000,7,"S",120,5,"adbd",20305
-6824713409261000,6,6003000,6824713415264000,0,"R",120,"[NULL]","swapper/5",0
-6824713410030000,1,92000,6824713410122000,6,"S",120,4,"rcu_preempt",7
-6824713410122000,1,6146000,6824713416268000,0,"R",120,"[NULL]","swapper/5",0
-6824713410365000,2,1409000,6824713411774000,8,"S",120,8,"rcuop/6",60
-6824713411774000,2,3953000,6824713415727000,0,"R",120,"[NULL]","swapper/5",0
-6824713415017000,5,41000,6824713415058000,82,"S",120,5,"shell",20461
-6824713415058000,5,871000,6824713415929000,0,"R",120,"[NULL]","swapper/5",0
-6824713415264000,6,114000,6824713415378000,7,"S",120,5,"adbd",20305
-6824713415378000,6,2157000,6824713417535000,0,"R",120,"[NULL]","swapper/5",0
-6824713415727000,2,177000,6824713415904000,2,"S",100,2,"kworker/u17:1",1134
-6824713415904000,2,176000,6824713416080000,31,"S",120,29,"kworker/2:0",18823
-6824713415929000,5,22000,6824713415951000,82,"S",120,5,"shell",20461
-6824713415951000,5,4014000,6824713419965000,0,"R",120,"[NULL]","swapper/5",0
-6824713416080000,2,579000,6824713416659000,0,"R",120,"[NULL]","swapper/5",0
-6824713416170000,0,101000,6824713416271000,79,"S",100,64,"kworker/u17:2",14944
-6824713416268000,1,135000,6824713416403000,4,"S",120,5,"UsbFfs-worker",20308
-6824713416271000,0,81000,6824713416352000,35,"S",120,33,"kworker/0:5",20371
-6824713416347000,3,56000,6824713416403000,2,"S",100,2,"kworker/u17:1",1134
-6824713416352000,0,4993000,6824713421345000,0,"R",120,"[NULL]","swapper/5",0
-6824713416403000,3,2160000,6824713418563000,0,"R",120,"[NULL]","swapper/5",0
-6824713416403000,1,272000,6824713416675000,0,"R",120,"[NULL]","swapper/5",0
-6824713416659000,2,84000,6824713416743000,2,"S",100,2,"kworker/u17:1",1134
-6824713416675000,1,57000,6824713416732000,6,"S",120,4,"rcu_preempt",7
-6824713416732000,1,521000,6824713417253000,0,"R",120,"[NULL]","swapper/5",0
-6824713416743000,2,74000,6824713416817000,0,"R",120,"[NULL]","swapper/5",0
-6824713416817000,2,91000,6824713416908000,2,"S",100,2,"kworker/u17:1",1134
-6824713416908000,2,119000,6824713417027000,31,"S",120,29,"kworker/2:0",18823
-6824713417027000,2,1013000,6824713418040000,0,"R",120,"[NULL]","swapper/5",0
-6824713417253000,1,234000,6824713417487000,4,"S",120,5,"UsbFfs-worker",20308
-6824713417487000,1,1008000,6824713418495000,0,"R",120,"[NULL]","swapper/5",0
-6824713417535000,6,118000,6824713417653000,7,"S",120,5,"adbd",20305
-6824713417653000,6,1707000,6824713419360000,0,"R",120,"[NULL]","swapper/5",0
-6824713418040000,2,115000,6824713418155000,2,"S",100,2,"kworker/u17:1",1134
-6824713418155000,2,178000,6824713418333000,31,"S",120,29,"kworker/2:0",18823
-6824713418333000,2,395000,6824713418728000,0,"R",120,"[NULL]","swapper/5",0
-6824713418495000,1,107000,6824713418602000,4,"S",120,5,"UsbFfs-worker",20308
-6824713418563000,3,106000,6824713418669000,2,"S",100,2,"kworker/u17:1",1134
-6824713418602000,1,455000,6824713419057000,0,"R",120,"[NULL]","swapper/5",0
-6824713418669000,3,117000,6824713418786000,49,"S",120,42,"kworker/3:1",17791
-6824713418728000,2,76000,6824713418804000,2,"S",100,2,"kworker/u17:1",1134
-6824713418786000,3,2669000,6824713421455000,0,"R",120,"[NULL]","swapper/5",0
-6824713418804000,2,62000,6824713418866000,0,"R",120,"[NULL]","swapper/5",0
-6824713418866000,2,86000,6824713418952000,2,"S",100,2,"kworker/u17:1",1134
-6824713418952000,2,87000,6824713419039000,31,"S",120,29,"kworker/2:0",18823
-6824713419039000,2,1615000,6824713420654000,0,"R",120,"[NULL]","swapper/5",0
-6824713419057000,1,251000,6824713419308000,4,"S",120,5,"UsbFfs-worker",20308
-6824713419308000,1,1797000,6824713421105000,0,"R",120,"[NULL]","swapper/5",0
-6824713419360000,6,50000,6824713419410000,7,"S",120,5,"adbd",20305
-6824713419410000,6,798000,6824713420208000,0,"R",120,"[NULL]","swapper/5",0
-6824713419965000,5,29000,6824713419994000,82,"S",120,5,"shell",20461
-6824713419994000,5,3214000,6824713423208000,0,"R",120,"[NULL]","swapper/5",0
-6824713420208000,6,90000,6824713420298000,7,"S",120,5,"adbd",20305
-6824713420298000,6,1655000,6824713421953000,0,"R",120,"[NULL]","swapper/5",0
-6824713420654000,2,115000,6824713420769000,2,"S",100,2,"kworker/u17:1",1134
-6824713420769000,2,111000,6824713420880000,31,"S",120,29,"kworker/2:0",18823
-6824713420880000,2,66000,6824713420946000,0,"R",120,"[NULL]","swapper/5",0
-6824713420946000,2,147000,6824713421093000,2,"S",100,2,"kworker/u17:1",1134
-6824713421093000,2,133000,6824713421226000,31,"S",120,29,"kworker/2:0",18823
-6824713421105000,1,129000,6824713421234000,4,"S",120,5,"UsbFfs-worker",20308
-6824713421226000,2,3867000,6824713425093000,0,"R",120,"[NULL]","swapper/5",0
-6824713421234000,1,424000,6824713421658000,0,"R",120,"[NULL]","swapper/5",0
-6824713421345000,0,93000,6824713421438000,79,"S",100,64,"kworker/u17:2",14944
-6824713421438000,0,49000,6824713421487000,0,"R",120,"[NULL]","swapper/5",0
-6824713421455000,3,119000,6824713421574000,2,"S",100,2,"kworker/u17:1",1134
-6824713421487000,0,43000,6824713421530000,79,"S",100,64,"kworker/u17:2",14944
-6824713421530000,0,6608000,6824713428138000,0,"R",120,"[NULL]","swapper/5",0
-6824713421574000,3,130000,6824713421704000,49,"S",120,42,"kworker/3:1",17791
-6824713421658000,1,224000,6824713421882000,4,"S",120,5,"UsbFfs-worker",20308
-6824713421704000,3,2240000,6824713423944000,0,"R",120,"[NULL]","swapper/5",0
-6824713421882000,1,1476000,6824713423358000,0,"R",120,"[NULL]","swapper/5",0
-6824713421953000,6,52000,6824713422005000,7,"S",120,5,"adbd",20305
-6824713422005000,6,1245000,6824713423250000,0,"R",120,"[NULL]","swapper/5",0
-6824713423208000,5,44000,6824713423252000,82,"S",120,5,"shell",20461
-6824713423250000,6,81000,6824713423331000,7,"S",120,5,"adbd",20305
-6824713423252000,5,4584000,6824713427836000,0,"R",120,"[NULL]","swapper/5",0
-6824713423331000,6,90000,6824713423421000,0,"R",120,"[NULL]","swapper/5",0
-6824713423358000,1,94000,6824713423452000,6,"S",120,4,"rcu_preempt",7
-6824713423421000,6,90000,6824713423511000,9,"S",120,6,"rcuop/4",44
-6824713423452000,1,101000,6824713423553000,0,"R",120,"[NULL]","swapper/5",0
-6824713423511000,6,2065000,6824713425576000,0,"R",120,"[NULL]","swapper/5",0
-6824713423553000,1,47000,6824713423600000,6,"S",120,4,"rcu_preempt",7
-6824713423600000,1,800000,6824713424400000,0,"R",120,"[NULL]","swapper/5",0
-6824713423944000,3,121000,6824713424065000,2,"S",100,2,"kworker/u17:1",1134
-6824713424065000,3,113000,6824713424178000,49,"S",120,42,"kworker/3:1",17791
-6824713424178000,3,631000,6824713424809000,0,"R",120,"[NULL]","swapper/5",0
-6824713424400000,1,98000,6824713424498000,4,"S",120,5,"UsbFfs-worker",20308
-6824713424498000,1,773000,6824713425271000,0,"R",120,"[NULL]","swapper/5",0
-6824713424809000,3,127000,6824713424936000,2,"S",100,2,"kworker/u17:1",1134
-6824713424936000,3,111000,6824713425047000,49,"S",120,42,"kworker/3:1",17791
-6824713425047000,3,3858000,6824713428905000,0,"R",120,"[NULL]","swapper/5",0
-6824713425093000,2,105000,6824713425198000,2,"S",100,2,"kworker/u17:1",1134
-6824713425198000,2,89000,6824713425287000,31,"S",120,29,"kworker/2:0",18823
-6824713425271000,1,260000,6824713425531000,4,"S",120,5,"UsbFfs-worker",20308
-6824713425287000,2,1587000,6824713426874000,0,"R",120,"[NULL]","swapper/5",0
-6824713425531000,1,3451000,6824713428982000,0,"R",120,"[NULL]","swapper/5",0
-6824713425576000,6,50000,6824713425626000,7,"S",120,5,"adbd",20305
-6824713425626000,6,2459000,6824713428085000,0,"R",120,"[NULL]","swapper/5",0
-6824713426874000,2,103000,6824713426977000,16,"S",120,14,"kworker/u16:7",19422
-6824713426977000,2,1675000,6824713428652000,0,"R",120,"[NULL]","swapper/5",0
-6824713427836000,5,29000,6824713427865000,82,"S",120,5,"shell",20461
-6824713427865000,5,2265000,6824713430130000,0,"R",120,"[NULL]","swapper/5",0
-6824713428085000,6,99000,6824713428184000,7,"S",120,5,"adbd",20305
-6824713428138000,0,104000,6824713428242000,35,"S",120,33,"kworker/0:5",20371
-6824713428184000,6,2870000,6824713431054000,0,"R",120,"[NULL]","swapper/5",0
-6824713428242000,0,898000,6824713429140000,0,"R",120,"[NULL]","swapper/5",0
-6824713428652000,2,437000,6824713429089000,36,"S",111,34,"SDM_EventThread",685
-6824713428905000,3,123000,6824713429028000,2,"S",100,2,"kworker/u17:1",1134
-6824713428982000,1,322000,6824713429304000,38,"S",120,35,"HwBinder:640_1",721
-6824713429028000,3,118000,6824713429146000,49,"S",120,42,"kworker/3:1",17791
-6824713429089000,2,544000,6824713429633000,0,"R",120,"[NULL]","swapper/5",0
-6824713429140000,0,196000,6824713429336000,40,"S",97,35,"DispSync",676
-6824713429146000,3,734000,6824713429880000,0,"R",120,"[NULL]","swapper/5",0
-6824713429304000,1,93000,6824713429397000,4,"S",120,5,"UsbFfs-worker",20308
-6824713429336000,0,735000,6824713430071000,0,"R",120,"[NULL]","swapper/5",0
-6824713429397000,1,470000,6824713429867000,0,"R",120,"[NULL]","swapper/5",0
-6824713429633000,2,287000,6824713429920000,41,"S",97,35,"app",678
-6824713429867000,1,193000,6824713430060000,40,"S",97,35,"DispSync",676
-6824713429880000,3,203000,6824713430083000,2,"S",100,2,"kworker/u17:1",1134
-6824713429920000,2,86000,6824713430006000,0,"R",120,"[NULL]","swapper/5",0
-6824713430006000,2,61000,6824713430067000,6,"S",120,4,"rcu_preempt",7
-6824713430060000,1,492000,6824713430552000,0,"R",120,"[NULL]","swapper/5",0
-6824713430067000,2,113000,6824713430180000,0,"R",120,"[NULL]","swapper/5",0
-6824713430071000,0,1790000,6824713431861000,42,"S",120,36,"ndroid.systemui",1664
-6824713430083000,3,143000,6824713430226000,49,"S",120,42,"kworker/3:1",17791
-6824713430130000,5,24000,6824713430154000,82,"S",120,5,"shell",20461
-6824713430154000,5,3393000,6824713433547000,0,"R",120,"[NULL]","swapper/5",0
-6824713430180000,2,112000,6824713430292000,4,"S",120,5,"UsbFfs-worker",20308
-6824713430226000,3,1706000,6824713431932000,0,"R",120,"[NULL]","swapper/5",0
-6824713430292000,2,469000,6824713430761000,0,"R",120,"[NULL]","swapper/5",0
-6824713430552000,1,120000,6824713430672000,2,"S",100,2,"kworker/u17:1",1134
-6824713430672000,1,134000,6824713430806000,48,"S",120,41,"kworker/1:1",18800
-6824713430761000,2,222000,6824713430983000,4,"S",120,5,"UsbFfs-worker",20308
-6824713430806000,1,695000,6824713431501000,0,"R",120,"[NULL]","swapper/5",0
-6824713430983000,2,607000,6824713431590000,0,"R",120,"[NULL]","swapper/5",0
-6824713431054000,6,118000,6824713431172000,7,"S",120,5,"adbd",20305
-6824713431172000,6,1852000,6824713433024000,0,"R",120,"[NULL]","swapper/5",0
-6824713431501000,1,118000,6824713431619000,2,"S",100,2,"kworker/u17:1",1134
-6824713431590000,2,264000,6824713431854000,43,"R+",120,35,"Binder:640_2",675
-6824713431619000,1,101000,6824713431720000,48,"S",120,41,"kworker/1:1",18800
-6824713431720000,1,103000,6824713431823000,4,"S",120,5,"UsbFfs-worker",20308
-6824713431823000,1,758000,6824713432581000,0,"R",120,"[NULL]","swapper/5",0
-6824713431854000,2,46000,6824713431900000,41,"S",97,35,"app",678
-6824713431861000,0,492000,6824713432353000,0,"R",120,"[NULL]","swapper/5",0
-6824713431900000,2,159000,6824713432059000,43,"S",120,35,"Binder:640_2",675
-6824713431932000,3,91000,6824713432023000,2,"S",100,2,"kworker/u17:1",1134
-6824713432023000,3,128000,6824713432151000,0,"R",120,"[NULL]","swapper/5",0
-6824713432059000,2,655000,6824713432714000,0,"R",120,"[NULL]","swapper/5",0
-6824713432151000,3,92000,6824713432243000,2,"S",100,2,"kworker/u17:1",1134
-6824713432243000,3,110000,6824713432353000,49,"S",120,42,"kworker/3:1",17791
-6824713432353000,3,349000,6824713432702000,0,"R",120,"[NULL]","swapper/5",0
-6824713432353000,0,196000,6824713432549000,41,"S",97,35,"app",678
-6824713432549000,0,28791000,6824713461340000,0,"R",120,"[NULL]","swapper/5",0
-6824713432581000,1,110000,6824713432691000,4,"S",120,5,"UsbFfs-worker",20308
-6824713432691000,1,29017000,6824713461708000,0,"R",120,"[NULL]","swapper/5",0
-6824713432702000,3,77000,6824713432779000,2,"S",100,2,"kworker/u17:1",1134
-6824713432714000,2,166000,6824713432880000,40,"S",97,35,"DispSync",676
-6824713432779000,3,31370000,6824713464149000,0,"R",120,"[NULL]","swapper/5",0
-6824713432880000,2,3801000,6824713436681000,0,"R",120,"[NULL]","swapper/5",0
-6824713433024000,6,46000,6824713433070000,2,"S",100,2,"kworker/u17:1",1134
-6824713433070000,6,31000,6824713433101000,3,"S",120,3,"kworker/6:1",14833
-6824713433101000,6,1961000,6824713435062000,0,"R",120,"[NULL]","swapper/5",0
-6824713433323000,7,68000,6824713433391000,4,"S",120,5,"UsbFfs-worker",20308
-6824713433391000,7,2508000,6824713435899000,0,"R",120,"[NULL]","swapper/5",0
-6824713433547000,5,47000,6824713433594000,7,"S",120,5,"adbd",20305
-6824713433594000,5,1241000,6824713434835000,0,"R",120,"[NULL]","swapper/5",0
-6824713434835000,5,30000,6824713434865000,82,"S",120,5,"shell",20461
-6824713434865000,5,2740000,6824713437605000,0,"R",120,"[NULL]","swapper/5",0
-6824713435062000,6,101000,6824713435163000,7,"S",120,5,"adbd",20305
-6824713435163000,6,471000,6824713435634000,0,"R",120,"[NULL]","swapper/5",0
-6824713435634000,6,36000,6824713435670000,2,"S",100,2,"kworker/u17:1",1134
-6824713435670000,6,13000,6824713435683000,3,"S",120,3,"kworker/6:1",14833
-6824713435683000,6,316000,6824713435999000,0,"R",120,"[NULL]","swapper/5",0
-6824713435899000,7,15000,6824713435914000,4,"S",120,5,"UsbFfs-worker",20308
-6824713435914000,7,346000,6824713436260000,0,"R",120,"[NULL]","swapper/5",0
-6824713435999000,6,24000,6824713436023000,2,"S",100,2,"kworker/u17:1",1134
-6824713436023000,6,13000,6824713436036000,3,"S",120,3,"kworker/6:1",14833
-6824713436036000,6,273000,6824713436309000,0,"R",120,"[NULL]","swapper/5",0
-6824713436260000,7,20000,6824713436280000,4,"S",120,5,"UsbFfs-worker",20308
-6824713436280000,7,302000,6824713436582000,0,"R",120,"[NULL]","swapper/5",0
-6824713436309000,6,29000,6824713436338000,2,"S",100,2,"kworker/u17:1",1134
-6824713436338000,6,35000,6824713436373000,0,"R",120,"[NULL]","swapper/5",0
-6824713436373000,6,29000,6824713436402000,2,"S",100,2,"kworker/u17:1",1134
-6824713436402000,6,14000,6824713436416000,3,"S",120,3,"kworker/6:1",14833
-6824713436416000,6,184000,6824713436600000,0,"R",120,"[NULL]","swapper/5",0
-6824713436582000,7,40000,6824713436622000,4,"S",120,5,"UsbFfs-worker",20308
-6824713436600000,6,53000,6824713436653000,7,"S",120,5,"adbd",20305
-6824713436622000,7,1360000,6824713437982000,0,"R",120,"[NULL]","swapper/5",0
-6824713436653000,6,83000,6824713436736000,0,"R",120,"[NULL]","swapper/5",0
-6824713436681000,2,89000,6824713436770000,6,"S",120,4,"rcu_preempt",7
-6824713436736000,6,216000,6824713436952000,9,"S",120,6,"rcuop/4",44
-6824713436770000,2,222000,6824713436992000,0,"R",120,"[NULL]","swapper/5",0
-6824713436952000,6,678000,6824713437630000,0,"R",120,"[NULL]","swapper/5",0
-6824713436992000,2,48000,6824713437040000,6,"S",120,4,"rcu_preempt",7
-6824713437040000,2,6321000,6824713443361000,0,"R",120,"[NULL]","swapper/5",0
-6824713437605000,5,30000,6824713437635000,82,"S",120,5,"shell",20461
-6824713437630000,6,82000,6824713437712000,7,"S",120,5,"adbd",20305
-6824713437635000,5,3002000,6824713440637000,0,"R",120,"[NULL]","swapper/5",0
-6824713437712000,6,15000,6824713437727000,0,"R",120,"[NULL]","swapper/5",0
-6824713437727000,6,14000,6824713437741000,2,"S",100,2,"kworker/u17:1",1134
-6824713437741000,6,40000,6824713437781000,0,"R",120,"[NULL]","swapper/5",0
-6824713437781000,6,19000,6824713437800000,2,"S",100,2,"kworker/u17:1",1134
-6824713437800000,6,9000,6824713437809000,3,"S",120,3,"kworker/6:1",14833
-6824713437809000,6,39000,6824713437848000,0,"R",120,"[NULL]","swapper/5",0
-6824713437848000,6,25000,6824713437873000,2,"S",100,2,"kworker/u17:1",1134
-6824713437873000,6,136000,6824713438009000,0,"R",120,"[NULL]","swapper/5",0
-6824713437982000,7,13000,6824713437995000,4,"S",120,5,"UsbFfs-worker",20308
-6824713437995000,7,43000,6824713438038000,0,"R",120,"[NULL]","swapper/5",0
-6824713438009000,6,19000,6824713438028000,2,"S",100,2,"kworker/u17:1",1134
-6824713438028000,6,10000,6824713438038000,3,"S",120,3,"kworker/6:1",14833
-6824713438038000,6,283000,6824713438321000,0,"R",120,"[NULL]","swapper/5",0
-6824713438038000,7,7000,6824713438045000,4,"S",120,5,"UsbFfs-worker",20308
-6824713438045000,7,470000,6824713438515000,0,"R",120,"[NULL]","swapper/5",0
-6824713438321000,6,20000,6824713438341000,2,"S",100,2,"kworker/u17:1",1134
-6824713438341000,6,34000,6824713438375000,0,"R",120,"[NULL]","swapper/5",0
-6824713438375000,6,29000,6824713438404000,2,"S",100,2,"kworker/u17:1",1134
-6824713438404000,6,71000,6824713438475000,0,"R",120,"[NULL]","swapper/5",0
-6824713438475000,6,29000,6824713438504000,2,"S",100,2,"kworker/u17:1",1134
-6824713438504000,6,14000,6824713438518000,3,"S",120,3,"kworker/6:1",14833
-6824713438515000,7,34000,6824713438549000,4,"S",120,5,"UsbFfs-worker",20308
-6824713438518000,6,10000,6824713438528000,0,"R",120,"[NULL]","swapper/5",0
-6824713438528000,6,43000,6824713438571000,7,"S",120,5,"adbd",20305
-6824713438549000,7,3192000,6824713441741000,0,"R",120,"[NULL]","swapper/5",0
-6824713438571000,6,2294000,6824713440865000,0,"R",120,"[NULL]","swapper/5",0
-6824713440637000,5,30000,6824713440667000,82,"S",120,5,"shell",20461
-6824713440667000,5,2936000,6824713443603000,0,"R",120,"[NULL]","swapper/5",0
-6824713440865000,6,84000,6824713440949000,7,"S",120,5,"adbd",20305
-6824713440949000,6,533000,6824713441482000,0,"R",120,"[NULL]","swapper/5",0
-6824713441482000,6,36000,6824713441518000,2,"S",100,2,"kworker/u17:1",1134
-6824713441518000,6,12000,6824713441530000,3,"S",120,3,"kworker/6:1",14833
-6824713441530000,6,315000,6824713441845000,0,"R",120,"[NULL]","swapper/5",0
-6824713441741000,7,12000,6824713441753000,4,"S",120,5,"UsbFfs-worker",20308
-6824713441753000,7,349000,6824713442102000,0,"R",120,"[NULL]","swapper/5",0
-6824713441845000,6,22000,6824713441867000,2,"S",100,2,"kworker/u17:1",1134
-6824713441867000,6,11000,6824713441878000,3,"S",120,3,"kworker/6:1",14833
-6824713441878000,6,270000,6824713442148000,0,"R",120,"[NULL]","swapper/5",0
-6824713442102000,7,15000,6824713442117000,4,"S",120,5,"UsbFfs-worker",20308
-6824713442117000,7,369000,6824713442486000,0,"R",120,"[NULL]","swapper/5",0
-6824713442148000,6,16000,6824713442164000,2,"S",100,2,"kworker/u17:1",1134
-6824713442164000,6,35000,6824713442199000,0,"R",120,"[NULL]","swapper/5",0
-6824713442199000,6,26000,6824713442225000,2,"S",100,2,"kworker/u17:1",1134
-6824713442225000,6,51000,6824713442276000,0,"R",120,"[NULL]","swapper/5",0
-6824713442276000,6,29000,6824713442305000,2,"S",100,2,"kworker/u17:1",1134
-6824713442305000,6,15000,6824713442320000,3,"S",120,3,"kworker/6:1",14833
-6824713442320000,6,184000,6824713442504000,0,"R",120,"[NULL]","swapper/5",0
-6824713442486000,7,38000,6824713442524000,4,"S",120,5,"UsbFfs-worker",20308
-6824713442504000,6,45000,6824713442549000,7,"S",120,5,"adbd",20305
-6824713442524000,7,2361000,6824713444885000,0,"R",120,"[NULL]","swapper/5",0
-6824713442549000,6,1704000,6824713444253000,0,"R",120,"[NULL]","swapper/5",0
-6824713443361000,2,92000,6824713443453000,6,"S",120,4,"rcu_preempt",7
-6824713443453000,2,362000,6824713443815000,0,"R",120,"[NULL]","swapper/5",0
-6824713443603000,5,161000,6824713443764000,9,"S",120,6,"rcuop/4",44
-6824713443764000,5,254000,6824713444018000,0,"R",120,"[NULL]","swapper/5",0
-6824713443815000,2,49000,6824713443864000,6,"S",120,4,"rcu_preempt",7
-6824713443864000,2,6152000,6824713450016000,0,"R",120,"[NULL]","swapper/5",0
-6824713444018000,5,29000,6824713444047000,82,"S",120,5,"shell",20461
-6824713444047000,5,6341000,6824713450388000,0,"R",120,"[NULL]","swapper/5",0
-6824713444253000,6,82000,6824713444335000,7,"S",120,5,"adbd",20305
-6824713444335000,6,323000,6824713444658000,0,"R",120,"[NULL]","swapper/5",0
-6824713444658000,6,36000,6824713444694000,2,"S",100,2,"kworker/u17:1",1134
-6824713444694000,6,11000,6824713444705000,3,"S",120,3,"kworker/6:1",14833
-6824713444705000,6,416000,6824713445121000,0,"R",120,"[NULL]","swapper/5",0
-6824713444885000,7,14000,6824713444899000,4,"S",120,5,"UsbFfs-worker",20308
-6824713444899000,7,439000,6824713445338000,0,"R",120,"[NULL]","swapper/5",0
-6824713445121000,6,35000,6824713445156000,2,"S",100,2,"kworker/u17:1",1134
-6824713445156000,6,9000,6824713445165000,3,"S",120,3,"kworker/6:1",14833
-6824713445165000,6,50000,6824713445215000,0,"R",120,"[NULL]","swapper/5",0
-6824713445215000,6,27000,6824713445242000,2,"S",100,2,"kworker/u17:1",1134
-6824713445242000,6,9000,6824713445251000,3,"S",120,3,"kworker/6:1",14833
-6824713445251000,6,106000,6824713445357000,0,"R",120,"[NULL]","swapper/5",0
-6824713445338000,7,42000,6824713445380000,4,"S",120,5,"UsbFfs-worker",20308
-6824713445357000,6,38000,6824713445395000,7,"S",120,5,"adbd",20305
-6824713445380000,7,2465000,6824713447845000,0,"R",120,"[NULL]","swapper/5",0
-6824713445395000,6,2679000,6824713448074000,0,"R",120,"[NULL]","swapper/5",0
-6824713447845000,7,24000,6824713447869000,82,"S",120,5,"shell",20461
-6824713447869000,7,782000,6824713448651000,0,"R",120,"[NULL]","swapper/5",0
-6824713448074000,6,85000,6824713448159000,7,"S",120,5,"adbd",20305
-6824713448159000,6,279000,6824713448438000,0,"R",120,"[NULL]","swapper/5",0
-6824713448438000,6,36000,6824713448474000,2,"S",100,2,"kworker/u17:1",1134
-6824713448474000,6,11000,6824713448485000,3,"S",120,3,"kworker/6:1",14833
-6824713448485000,6,380000,6824713448865000,0,"R",120,"[NULL]","swapper/5",0
-6824713448651000,7,12000,6824713448663000,4,"S",120,5,"UsbFfs-worker",20308
-6824713448663000,7,456000,6824713449119000,0,"R",120,"[NULL]","swapper/5",0
-6824713448865000,6,23000,6824713448888000,2,"S",100,2,"kworker/u17:1",1134
-6824713448888000,6,11000,6824713448899000,3,"S",120,3,"kworker/6:1",14833
-6824713448899000,6,269000,6824713449168000,0,"R",120,"[NULL]","swapper/5",0
-6824713449119000,7,15000,6824713449134000,4,"S",120,5,"UsbFfs-worker",20308
-6824713449134000,7,353000,6824713449487000,0,"R",120,"[NULL]","swapper/5",0
-6824713449168000,6,27000,6824713449195000,2,"S",100,2,"kworker/u17:1",1134
-6824713449195000,6,48000,6824713449243000,0,"R",120,"[NULL]","swapper/5",0
-6824713449243000,6,29000,6824713449272000,2,"S",100,2,"kworker/u17:1",1134
-6824713449272000,6,15000,6824713449287000,3,"S",120,3,"kworker/6:1",14833
-6824713449287000,6,389000,6824713449676000,0,"R",120,"[NULL]","swapper/5",0
-6824713449487000,7,38000,6824713449525000,4,"S",120,5,"UsbFfs-worker",20308
-6824713449525000,7,2642000,6824713452167000,0,"R",120,"[NULL]","swapper/5",0
-6824713449676000,6,51000,6824713449727000,7,"S",120,5,"adbd",20305
-6824713449727000,6,349000,6824713450076000,0,"R",120,"[NULL]","swapper/5",0
-6824713450016000,2,95000,6824713450111000,6,"S",120,4,"rcu_preempt",7
-6824713450076000,6,87000,6824713450163000,9,"S",120,6,"rcuop/4",44
-6824713450111000,2,11329000,6824713461440000,0,"R",120,"[NULL]","swapper/5",0
-6824713450163000,6,2199000,6824713452362000,0,"R",120,"[NULL]","swapper/5",0
-6824713450388000,5,13000,6824713450401000,6,"S",120,4,"rcu_preempt",7
-6824713450401000,5,6481000,6824713456882000,0,"R",120,"[NULL]","swapper/5",0
-6824713452167000,7,26000,6824713452193000,82,"S",120,5,"shell",20461
-6824713452193000,7,989000,6824713453182000,0,"R",120,"[NULL]","swapper/5",0
-6824713452362000,6,87000,6824713452449000,7,"S",120,5,"adbd",20305
-6824713452449000,6,485000,6824713452934000,0,"R",120,"[NULL]","swapper/5",0
-6824713452934000,6,35000,6824713452969000,2,"S",100,2,"kworker/u17:1",1134
-6824713452969000,6,12000,6824713452981000,3,"S",120,3,"kworker/6:1",14833
-6824713452981000,6,601000,6824713453582000,0,"R",120,"[NULL]","swapper/5",0
-6824713453182000,7,12000,6824713453194000,4,"S",120,5,"UsbFfs-worker",20308
-6824713453194000,7,648000,6824713453842000,0,"R",120,"[NULL]","swapper/5",0
-6824713453582000,6,35000,6824713453617000,2,"S",100,2,"kworker/u17:1",1134
-6824713453617000,6,11000,6824713453628000,3,"S",120,3,"kworker/6:1",14833
-6824713453628000,6,571000,6824713454199000,0,"R",120,"[NULL]","swapper/5",0
-6824713453842000,7,15000,6824713453857000,4,"S",120,5,"UsbFfs-worker",20308
-6824713453857000,7,551000,6824713454408000,0,"R",120,"[NULL]","swapper/5",0
-6824713454199000,6,30000,6824713454229000,2,"S",100,2,"kworker/u17:1",1134
-6824713454229000,6,15000,6824713454244000,3,"S",120,3,"kworker/6:1",14833
-6824713454244000,6,182000,6824713454426000,0,"R",120,"[NULL]","swapper/5",0
-6824713454408000,7,40000,6824713454448000,4,"S",120,5,"UsbFfs-worker",20308
-6824713454426000,6,45000,6824713454471000,7,"S",120,5,"adbd",20305
-6824713454448000,7,1495000,6824713455943000,0,"R",120,"[NULL]","swapper/5",0
-6824713454471000,6,1697000,6824713456168000,0,"R",120,"[NULL]","swapper/5",0
-6824713455943000,7,21000,6824713455964000,82,"S",120,5,"shell",20461
-6824713455964000,7,1116000,6824713457080000,0,"R",120,"[NULL]","swapper/5",0
-6824713456168000,6,83000,6824713456251000,7,"S",120,5,"adbd",20305
-6824713456251000,6,535000,6824713456786000,0,"R",120,"[NULL]","swapper/5",0
-6824713456565000,4,16000,6824713456581000,90,"S",120,74,"kworker/4:1",19875
-6824713456581000,4,3324000,6824713459905000,87,"R",120,71,"ps",20464
-6824713456786000,6,36000,6824713456822000,2,"S",100,2,"kworker/u17:1",1134
-6824713456822000,6,11000,6824713456833000,3,"S",120,3,"kworker/6:1",14833
-6824713456833000,6,411000,6824713457244000,0,"R",120,"[NULL]","swapper/5",0
-6824713456882000,5,15000,6824713456897000,6,"S",120,4,"rcu_preempt",7
-6824713456897000,5,644000,6824713457541000,0,"R",120,"[NULL]","swapper/5",0
-6824713457080000,7,12000,6824713457092000,4,"S",120,5,"UsbFfs-worker",20308
-6824713457092000,7,408000,6824713457500000,0,"R",120,"[NULL]","swapper/5",0
-6824713457244000,6,70000,6824713457314000,9,"S",120,6,"rcuop/4",44
-6824713457314000,6,585000,6824713457899000,0,"R",120,"[NULL]","swapper/5",0
-6824713457500000,7,44000,6824713457544000,2,"S",100,2,"kworker/u17:1",1134
-6824713457541000,5,8000,6824713457549000,6,"S",120,4,"rcu_preempt",7
-6824713457544000,7,12000,6824713457556000,30,"S",120,28,"kworker/7:2",14813
-6824713457549000,5,2749000,6824713460298000,0,"R",120,"[NULL]","swapper/5",0
-6824713457556000,7,13000,6824713457569000,4,"S",120,5,"UsbFfs-worker",20308
-6824713457569000,7,270000,6824713457839000,0,"R",120,"[NULL]","swapper/5",0
-6824713457839000,7,32000,6824713457871000,2,"S",100,2,"kworker/u17:1",1134
-6824713457871000,7,12000,6824713457883000,30,"S",120,28,"kworker/7:2",14813
-6824713457883000,7,36000,6824713457919000,4,"S",120,5,"UsbFfs-worker",20308
-6824713457899000,6,46000,6824713457945000,7,"S",120,5,"adbd",20305
-6824713457919000,7,2183000,6824713460102000,0,"R",120,"[NULL]","swapper/5",0
-6824713457945000,6,5819000,6824713463764000,0,"R",120,"[NULL]","swapper/5",0
-6824713459905000,4,14000,6824713459919000,90,"S",120,74,"kworker/4:1",19875
-6824713459919000,4,6161000,6824713466080000,87,"x",120,71,"ps",20464
-6824713460102000,7,30000,6824713460132000,82,"S",120,5,"shell",20461
-6824713460132000,7,539000,6824713460671000,0,"R",120,"[NULL]","swapper/5",0
-6824713460298000,5,97000,6824713460395000,7,"S",120,5,"adbd",20305
-6824713460395000,5,1447000,6824713461842000,0,"R",120,"[NULL]","swapper/5",0
-6824713460671000,7,35000,6824713460706000,2,"S",100,2,"kworker/u17:1",1134
-6824713460706000,7,8000,6824713460714000,30,"S",120,28,"kworker/7:2",14813
-6824713460714000,7,9000,6824713460723000,4,"S",120,5,"UsbFfs-worker",20308
-6824713460723000,7,306000,6824713461029000,0,"R",120,"[NULL]","swapper/5",0
-6824713461029000,7,22000,6824713461051000,2,"S",100,2,"kworker/u17:1",1134
-6824713461051000,7,8000,6824713461059000,30,"S",120,28,"kworker/7:2",14813
-6824713461059000,7,11000,6824713461070000,4,"S",120,5,"UsbFfs-worker",20308
-6824713461070000,7,261000,6824713461331000,0,"R",120,"[NULL]","swapper/5",0
-6824713461331000,7,30000,6824713461361000,2,"S",100,2,"kworker/u17:1",1134
-6824713461340000,0,109000,6824713461449000,35,"S",120,33,"kworker/0:5",20371
-6824713461361000,7,250000,6824713461611000,0,"R",120,"[NULL]","swapper/5",0
-6824713461440000,2,373000,6824713461813000,36,"S",111,34,"SDM_EventThread",685
-6824713461449000,0,460000,6824713461909000,0,"R",120,"[NULL]","swapper/5",0
-6824713461611000,7,30000,6824713461641000,2,"S",100,2,"kworker/u17:1",1134
-6824713461641000,7,13000,6824713461654000,30,"S",120,28,"kworker/7:2",14813
-6824713461654000,7,36000,6824713461690000,4,"S",120,5,"UsbFfs-worker",20308
-6824713461690000,7,2930000,6824713464620000,0,"R",120,"[NULL]","swapper/5",0
-6824713461708000,1,421000,6824713462129000,38,"S",120,35,"HwBinder:640_1",721
-6824713461813000,2,364000,6824713462177000,0,"R",120,"[NULL]","swapper/5",0
-6824713461842000,5,49000,6824713461891000,7,"S",120,5,"adbd",20305
-6824713461891000,5,1341000,6824713463232000,0,"R",120,"[NULL]","swapper/5",0
-6824713461909000,0,68000,6824713461977000,40,"S",97,35,"DispSync",676
-6824713461977000,0,38000,6824713462015000,0,"R",120,"[NULL]","swapper/5",0
-6824713462015000,0,162000,6824713462177000,40,"S",97,35,"DispSync",676
-6824713462129000,1,262000,6824713462391000,0,"R",120,"[NULL]","swapper/5",0
-6824713462177000,0,142000,6824713462319000,0,"R",120,"[NULL]","swapper/5",0
-6824713462177000,2,255000,6824713462432000,41,"S",97,35,"app",678
-6824713462319000,0,1790000,6824713464109000,42,"S",120,36,"ndroid.systemui",1664
-6824713462391000,1,75000,6824713462466000,40,"S",97,35,"DispSync",676
-6824713462432000,2,1186000,6824713463618000,0,"R",120,"[NULL]","swapper/5",0
-6824713462466000,1,2550000,6824713465016000,0,"R",120,"[NULL]","swapper/5",0
-6824713463232000,5,9000,6824713463241000,6,"S",120,4,"rcu_preempt",7
-6824713463241000,5,334000,6824713463575000,0,"R",120,"[NULL]","swapper/5",0
-6824713463575000,5,14000,6824713463589000,6,"S",120,4,"rcu_preempt",7
-6824713463589000,5,243000,6824713463832000,0,"R",120,"[NULL]","swapper/5",0
-6824713463618000,2,521000,6824713464139000,16,"S",120,14,"kworker/u16:7",19422
-6824713463764000,6,70000,6824713463834000,9,"S",120,6,"rcuop/4",44
-6824713463832000,5,5000,6824713463837000,6,"S",120,4,"rcu_preempt",7
-6824713463834000,6,2237000,6824713466071000,0,"R",120,"[NULL]","swapper/5",0
-6824713463837000,5,1034000,6824713464871000,0,"R",120,"[NULL]","swapper/5",0
-6824713464109000,0,488000,6824713464597000,0,"R",120,"[NULL]","swapper/5",0
-6824713464139000,2,5608000,6824713469747000,0,"R",120,"[NULL]","swapper/5",0
-6824713464149000,3,282000,6824713464431000,43,"S",120,35,"Binder:640_2",675
-6824713464431000,3,3478000,6824713467909000,0,"R",120,"[NULL]","swapper/5",0
-6824713464597000,0,172000,6824713464769000,41,"S",97,35,"app",678
-6824713464620000,7,27000,6824713464647000,82,"S",120,5,"shell",20461
-6824713464647000,7,582000,6824713465229000,0,"R",120,"[NULL]","swapper/5",0
-6824713464769000,0,2190000,6824713466959000,0,"R",120,"[NULL]","swapper/5",0
-6824713464871000,5,85000,6824713464956000,7,"S",120,5,"adbd",20305
-6824713464956000,5,693000,6824713465649000,0,"R",120,"[NULL]","swapper/5",0
-6824713465016000,1,91000,6824713465107000,40,"S",97,35,"DispSync",676
-6824713465107000,1,1435000,6824713466542000,0,"R",120,"[NULL]","swapper/5",0
-6824713465229000,7,21000,6824713465250000,2,"S",100,2,"kworker/u17:1",1134
-6824713465250000,7,9000,6824713465259000,30,"S",120,28,"kworker/7:2",14813
-6824713465259000,7,10000,6824713465269000,4,"S",120,5,"UsbFfs-worker",20308
-6824713465269000,7,284000,6824713465553000,0,"R",120,"[NULL]","swapper/5",0
-6824713465553000,7,29000,6824713465582000,2,"S",100,2,"kworker/u17:1",1134
-6824713465582000,7,689000,6824713466271000,0,"R",120,"[NULL]","swapper/5",0
-6824713465649000,5,20000,6824713465669000,82,"S",120,5,"shell",20461
-6824713465669000,5,418000,6824713466087000,0,"R",120,"[NULL]","swapper/5",0
-6824713466071000,6,16000,6824713466087000,27,"S",120,25,"rcuos/4",45
-6824713466080000,4,812000,6824713466892000,0,"R",120,"[NULL]","swapper/5",0
-6824713466087000,6,4893000,6824713470980000,0,"R",120,"[NULL]","swapper/5",0
-6824713466087000,5,8000,6824713466095000,5,"S",120,7,"rcu_sched",8
-6824713466095000,5,2929000,6824713469024000,0,"R",120,"[NULL]","swapper/5",0
-6824713466271000,7,37000,6824713466308000,2,"S",100,2,"kworker/u17:1",1134
-6824713466308000,7,8000,6824713466316000,30,"S",120,28,"kworker/7:2",14813
-6824713466316000,7,14000,6824713466330000,4,"S",120,5,"UsbFfs-worker",20308
-6824713466330000,7,308000,6824713466638000,0,"R",120,"[NULL]","swapper/5",0
-6824713466542000,1,3584000,6824713470126000,83,"x",120,67,"sh",20462
-6824713466638000,7,28000,6824713466666000,2,"S",100,2,"kworker/u17:1",1134
-6824713466666000,7,11000,6824713466677000,30,"S",120,28,"kworker/7:2",14813
-6824713466677000,7,39000,6824713466716000,4,"S",120,5,"UsbFfs-worker",20308
-6824713466716000,7,622000,6824713467338000,0,"R",120,"[NULL]","swapper/5",0
-6824713466892000,4,113000,6824713467005000,7,"S",120,5,"adbd",20305
-6824713466959000,0,61000,6824713467020000,11,"S",120,9,"rcuop/0",10
-6824713467005000,4,1148000,6824713468153000,0,"R",120,"[NULL]","swapper/5",0
-6824713467020000,0,1748000,6824713468768000,0,"R",120,"[NULL]","swapper/5",0
-6824713467338000,7,249000,6824713467587000,22,"D",49,20,"sugov:4",606
-6824713467587000,7,70000,6824713467657000,2,"S",100,2,"kworker/u17:1",1134
-6824713467657000,7,50000,6824713467707000,30,"S",120,28,"kworker/7:2",14813
-6824713467707000,7,60000,6824713467767000,4,"S",120,5,"UsbFfs-worker",20308
-6824713467767000,7,9375000,6824713477142000,0,"R",120,"[NULL]","swapper/5",0
-6824713467909000,3,104000,6824713468013000,32,"S",120,30,"smem_native_rpm",87
-6824713468013000,3,1027000,6824713469040000,0,"R",120,"[NULL]","swapper/5",0
-6824713468153000,4,109000,6824713468262000,2,"R+",100,2,"kworker/u17:1",1134
-6824713468262000,4,82000,6824713468344000,22,"S",49,20,"sugov:4",606
-6824713468344000,4,36000,6824713468380000,90,"R",120,74,"kworker/4:1",19875
-6824713468380000,4,232000,6824713468612000,22,"D",49,20,"sugov:4",606
-6824713468612000,4,48000,6824713468660000,2,"S",100,2,"kworker/u17:1",1134
-6824713468660000,4,23000,6824713468683000,90,"S",120,74,"kworker/4:1",19875
-6824713468683000,4,29000,6824713468712000,0,"R",120,"[NULL]","swapper/5",0
-6824713468712000,4,53000,6824713468765000,2,"S",100,2,"kworker/u17:1",1134
-6824713468765000,4,18000,6824713468783000,90,"S",120,74,"kworker/4:1",19875
-6824713468768000,0,71000,6824713468839000,79,"S",100,64,"kworker/u17:2",14944
-6824713468783000,4,263000,6824713469046000,0,"R",120,"[NULL]","swapper/5",0
-6824713468839000,0,3202000,6824713472041000,0,"R",120,"[NULL]","swapper/5",0
-6824713469024000,5,45000,6824713469069000,4,"S",120,5,"UsbFfs-worker",20308
-6824713469040000,3,71000,6824713469111000,32,"S",120,30,"smem_native_rpm",87
-6824713469046000,4,43000,6824713469089000,7,"S",120,5,"adbd",20305
-6824713469069000,5,850000,6824713469919000,0,"R",120,"[NULL]","swapper/5",0
-6824713469089000,4,153000,6824713469242000,0,"R",120,"[NULL]","swapper/5",0
-6824713469111000,3,1771000,6824713470882000,0,"R",120,"[NULL]","swapper/5",0
-6824713469242000,4,14000,6824713469256000,22,"S",49,20,"sugov:4",606
-6824713469256000,4,2174000,6824713471430000,0,"R",120,"[NULL]","swapper/5",0
-6824713469747000,2,68000,6824713469815000,14,"S",120,10,"rcuos/0",11
-6824713469815000,2,281000,6824713470096000,0,"R",120,"[NULL]","swapper/5",0
-6824713469919000,5,7000,6824713469926000,5,"S",120,7,"rcu_sched",8
-6824713469926000,5,6000,6824713469932000,6,"S",120,4,"rcu_preempt",7
-6824713469932000,5,770000,6824713470702000,0,"R",120,"[NULL]","swapper/5",0
-6824713470096000,2,3770000,6824713473866000,81,"x",120,66,"sh",20460
-6824713470126000,1,2368000,6824713472494000,0,"R",120,"[NULL]","swapper/5",0
-6824713470702000,5,43000,6824713470745000,6,"S",120,4,"rcu_preempt",7
-6824713470745000,5,381000,6824713471126000,0,"R",120,"[NULL]","swapper/5",0
-6824713470882000,3,62000,6824713470944000,23,"S",120,21,"rcuop/2",28
-6824713470944000,3,15328000,6824713486272000,0,"R",120,"[NULL]","swapper/5",0
-6824713470980000,6,109000,6824713471089000,9,"S",120,6,"rcuop/4",44
-6824713471089000,6,2971000,6824713474060000,0,"R",120,"[NULL]","swapper/5",0
-6824713471126000,5,89000,6824713471215000,82,"S",120,5,"shell",20461
-6824713471215000,5,687000,6824713471902000,0,"R",120,"[NULL]","swapper/5",0
-6824713471430000,4,246000,6824713471676000,7,"S",120,5,"adbd",20305
-6824713471676000,4,2529000,6824713474205000,0,"R",120,"[NULL]","swapper/5",0
-6824713471902000,5,68000,6824713471970000,82,"S",120,5,"shell",20461
-6824713471970000,5,263000,6824713472233000,0,"R",120,"[NULL]","swapper/5",0
-6824713472041000,0,131000,6824713472172000,79,"S",100,64,"kworker/u17:2",14944
-6824713472172000,0,119000,6824713472291000,35,"S",120,33,"kworker/0:5",20371
-6824713472233000,5,23000,6824713472256000,4,"S",120,5,"UsbFfs-worker",20308
-6824713472256000,5,537000,6824713472793000,0,"R",120,"[NULL]","swapper/5",0
-6824713472291000,0,508000,6824713472799000,0,"R",120,"[NULL]","swapper/5",0
-6824713472494000,1,96000,6824713472590000,79,"S",100,64,"kworker/u17:2",14944
-6824713472590000,1,47000,6824713472637000,0,"R",120,"[NULL]","swapper/5",0
-6824713472637000,1,100000,6824713472737000,79,"S",100,64,"kworker/u17:2",14944
-6824713472737000,1,105000,6824713472842000,48,"S",120,41,"kworker/1:1",18800
-6824713472793000,5,17000,6824713472810000,4,"S",120,5,"UsbFfs-worker",20308
-6824713472799000,0,61000,6824713472860000,79,"S",100,64,"kworker/u17:2",14944
-6824713472810000,5,299000,6824713473109000,0,"R",120,"[NULL]","swapper/5",0
-6824713472842000,1,2946000,6824713475788000,0,"R",120,"[NULL]","swapper/5",0
-6824713472860000,0,44000,6824713472904000,0,"R",120,"[NULL]","swapper/5",0
-6824713472904000,0,75000,6824713472979000,79,"S",100,64,"kworker/u17:2",14944
-6824713472979000,0,453000,6824713473432000,0,"R",120,"[NULL]","swapper/5",0
-6824713473109000,5,8000,6824713473117000,20,"S",120,18,"rcuos/2",29
-6824713473117000,5,861000,6824713473978000,0,"R",120,"[NULL]","swapper/5",0
-6824713473432000,0,106000,6824713473538000,79,"S",100,64,"kworker/u17:2",14944
-6824713473538000,0,135000,6824713473673000,35,"S",120,33,"kworker/0:5",20371
-6824713473673000,0,946000,6824713474619000,0,"R",120,"[NULL]","swapper/5",0
-6824713473866000,2,283000,6824713474149000,0,"R",120,"[NULL]","swapper/5",0
-6824713473978000,5,75000,6824713474053000,4,"S",120,5,"UsbFfs-worker",20308
-6824713474053000,5,975000,6824713475028000,0,"R",120,"[NULL]","swapper/5",0
-6824713474060000,6,244000,6824713474304000,82,"x",120,5,"shell",20461
-6824713474149000,2,49000,6824713474198000,8,"S",120,8,"rcuop/6",60
-6824713474198000,2,596000,6824713474794000,0,"R",120,"[NULL]","swapper/5",0
-6824713474205000,4,149000,6824713474354000,7,"S",120,5,"adbd",20305
-6824713474304000,6,2488000,6824713476792000,0,"R",120,"[NULL]","swapper/5",0
-6824713474354000,4,1066000,6824713475420000,0,"R",120,"[NULL]","swapper/5",0
-6824713474619000,0,108000,6824713474727000,79,"S",100,64,"kworker/u17:2",14944
-6824713474727000,0,110000,6824713474837000,35,"S",120,33,"kworker/0:5",20371
-6824713474794000,2,81000,6824713474875000,79,"S",100,64,"kworker/u17:2",14944
-6824713474837000,0,521000,6824713475358000,0,"R",120,"[NULL]","swapper/5",0
-6824713474875000,2,189000,6824713475064000,0,"R",120,"[NULL]","swapper/5",0
-6824713475028000,5,13000,6824713475041000,4,"S",120,5,"UsbFfs-worker",20308
-6824713475041000,5,348000,6824713475389000,0,"R",120,"[NULL]","swapper/5",0
-6824713475064000,2,217000,6824713475281000,79,"S",100,64,"kworker/u17:2",14944
-6824713475281000,2,288000,6824713475569000,31,"S",120,29,"kworker/2:0",18823
-6824713475358000,0,96000,6824713475454000,79,"S",100,64,"kworker/u17:2",14944
-6824713475389000,5,10000,6824713475399000,4,"S",120,5,"UsbFfs-worker",20308
-6824713475399000,5,31000,6824713475430000,0,"R",120,"[NULL]","swapper/5",0
-6824713475420000,4,11000,6824713475431000,2,"S",100,2,"kworker/u17:1",1134
-6824713475430000,5,7000,6824713475437000,4,"S",120,5,"UsbFfs-worker",20308
-6824713475431000,4,340000,6824713475771000,0,"R",120,"[NULL]","swapper/5",0
-6824713475437000,5,75000,6824713475512000,0,"R",120,"[NULL]","swapper/5",0
-6824713475454000,0,114000,6824713475568000,35,"S",120,33,"kworker/0:5",20371
-6824713475512000,5,39000,6824713475551000,4,"S",120,5,"UsbFfs-worker",20308
-6824713475551000,5,1067000,6824713476618000,0,"R",120,"[NULL]","swapper/5",0
-6824713475568000,0,10190000,6824713485758000,0,"R",120,"[NULL]","swapper/5",0
-6824713475569000,2,10187000,6824713485756000,0,"R",120,"[NULL]","swapper/5",0
-6824713475771000,4,98000,6824713475869000,7,"S",120,5,"adbd",20305
-6824713475788000,1,89000,6824713475877000,79,"S",100,64,"kworker/u17:2",14944
-6824713475869000,4,1395000,6824713477264000,0,"R",120,"[NULL]","swapper/5",0
-6824713475877000,1,621000,6824713476498000,0,"R",120,"[NULL]","swapper/5",0
-6824713476498000,1,200000,6824713476698000,79,"S",100,64,"kworker/u17:2",14944
-6824713476618000,5,8000,6824713476626000,6,"S",120,4,"rcu_preempt",7
-6824713476626000,5,41000,6824713476667000,16,"S",120,14,"kworker/u16:7",19422
-6824713476667000,5,361000,6824713477028000,0,"R",120,"[NULL]","swapper/5",0
-6824713476698000,1,154000,6824713476852000,48,"S",120,41,"kworker/1:1",18800
-6824713476792000,6,30000,6824713476822000,5,"S",120,7,"rcu_sched",8
-6824713476822000,6,7677000,6824713484499000,0,"R",120,"[NULL]","swapper/5",0
-6824713476852000,1,9339000,6824713486191000,0,"R",120,"[NULL]","swapper/5",0
-6824713477028000,5,42000,6824713477070000,4,"S",120,5,"UsbFfs-worker",20308
-6824713477070000,5,7334000,6824713484404000,0,"R",120,"[NULL]","swapper/5",0
-6824713477142000,7,19000,6824713477161000,27,"S",120,25,"rcuos/4",45
-6824713477161000,7,61280000,6824713538441000,0,"R",120,"[NULL]","swapper/5",0
-6824713477264000,4,40000,6824713477304000,7,"S",120,5,"adbd",20305
-6824713477304000,4,31231000,6824713508535000,0,"R",120,"[NULL]","swapper/5",0
-6824713484404000,5,44000,6824713484448000,6,"S",120,4,"rcu_preempt",7
-6824713484448000,5,365000,6824713484813000,0,"R",120,"[NULL]","swapper/5",0
-6824713484499000,6,23000,6824713484522000,5,"S",120,7,"rcu_sched",8
-6824713484522000,6,6802000,6824713491324000,0,"R",120,"[NULL]","swapper/5",0
-6824713484813000,5,36000,6824713484849000,20,"S",120,18,"rcuos/2",29
-6824713484849000,5,6226000,6824713491075000,0,"R",120,"[NULL]","swapper/5",0
-6824713485756000,2,159000,6824713485915000,14,"S",120,10,"rcuos/0",11
-6824713485758000,0,157000,6824713485915000,11,"S",120,9,"rcuop/0",10
-6824713485915000,2,6523000,6824713492438000,0,"R",120,"[NULL]","swapper/5",0
-6824713485915000,0,9244000,6824713495159000,0,"R",120,"[NULL]","swapper/5",0
-6824713486191000,1,100000,6824713486291000,13,"S",120,12,"rcuop/1",20
-6824713486272000,3,94000,6824713486366000,15,"S",120,13,"rcuos/1",21
-6824713486291000,1,9985000,6824713496276000,0,"R",120,"[NULL]","swapper/5",0
-6824713486366000,3,6074000,6824713492440000,0,"R",120,"[NULL]","swapper/5",0
-6824713491075000,5,58000,6824713491133000,6,"S",120,4,"rcu_preempt",7
-6824713491133000,5,6463000,6824713497596000,0,"R",120,"[NULL]","swapper/5",0
-6824713491324000,6,54000,6824713491378000,9,"S",120,6,"rcuop/4",44
-6824713491378000,6,47434000,6824713538812000,0,"R",120,"[NULL]","swapper/5",0
-6824713492438000,2,218000,6824713492656000,8,"S",120,8,"rcuop/6",60
-6824713492440000,3,215000,6824713492655000,23,"S",120,21,"rcuop/2",28
-6824713492655000,3,6627000,6824713499282000,0,"R",120,"[NULL]","swapper/5",0
-6824713492656000,2,2845000,6824713495501000,0,"R",120,"[NULL]","swapper/5",0
-6824713495159000,0,143000,6824713495302000,35,"S",120,33,"kworker/0:5",20371
-6824713495302000,0,61000,6824713495363000,0,"R",120,"[NULL]","swapper/5",0
-6824713495363000,0,62000,6824713495425000,44,"S",120,37,"ksoftirqd/0",3
-6824713495425000,0,586000,6824713496011000,0,"R",120,"[NULL]","swapper/5",0
-6824713495501000,2,575000,6824713496076000,36,"S",111,34,"SDM_EventThread",685
-6824713496011000,0,264000,6824713496275000,40,"S",97,35,"DispSync",676
-6824713496076000,2,458000,6824713496534000,0,"R",120,"[NULL]","swapper/5",0
-6824713496275000,0,505000,6824713496780000,0,"R",120,"[NULL]","swapper/5",0
-6824713496276000,1,516000,6824713496792000,38,"S",120,35,"HwBinder:640_1",721
-6824713496534000,2,458000,6824713496992000,41,"S",97,35,"app",678
-6824713496780000,0,101000,6824713496881000,40,"S",97,35,"DispSync",676
-6824713496792000,1,472000,6824713497264000,0,"R",120,"[NULL]","swapper/5",0
-6824713496881000,0,83000,6824713496964000,0,"R",120,"[NULL]","swapper/5",0
-6824713496964000,0,65000,6824713497029000,40,"S",97,35,"DispSync",676
-6824713496992000,2,10168000,6824713507160000,0,"R",120,"[NULL]","swapper/5",0
-6824713497029000,0,2730000,6824713499759000,0,"R",120,"[NULL]","swapper/5",0
-6824713497264000,1,2038000,6824713499302000,42,"S",120,36,"ndroid.systemui",1664
-6824713497596000,5,25000,6824713497621000,6,"S",120,4,"rcu_preempt",7
-6824713497621000,5,6805000,6824713504426000,0,"R",120,"[NULL]","swapper/5",0
-6824713499282000,3,328000,6824713499610000,43,"S",120,35,"Binder:640_2",675
-6824713499302000,1,572000,6824713499874000,0,"R",120,"[NULL]","swapper/5",0
-6824713499610000,3,7250000,6824713506860000,0,"R",120,"[NULL]","swapper/5",0
-6824713499759000,0,267000,6824713500026000,41,"S",97,35,"app",678
-6824713499874000,1,154000,6824713500028000,40,"S",97,35,"DispSync",676
-6824713500026000,0,6835000,6824713506861000,0,"R",120,"[NULL]","swapper/5",0
-6824713500028000,1,7524000,6824713507552000,0,"R",120,"[NULL]","swapper/5",0
-6824713504426000,5,314000,6824713504740000,22,"D",49,20,"sugov:4",606
-6824713504740000,5,82000,6824713504822000,6,"S",120,4,"rcu_preempt",7
-6824713504822000,5,26596000,6824713531418000,0,"R",120,"[NULL]","swapper/5",0
-6824713506860000,3,291000,6824713507151000,32,"S",120,30,"smem_native_rpm",87
-6824713506861000,0,290000,6824713507151000,11,"S",120,9,"rcuop/0",10
-6824713507151000,3,22498000,6824713529649000,0,"R",120,"[NULL]","swapper/5",0
-6824713507151000,0,1456000,6824713508607000,0,"R",120,"[NULL]","swapper/5",0
-6824713507160000,2,99000,6824713507259000,25,"S",120,24,"ksoftirqd/2",25
-6824713507259000,2,10658000,6824713517917000,0,"R",120,"[NULL]","swapper/5",0
-6824713507552000,1,436000,6824713507988000,13,"S",120,12,"rcuop/1",20
-6824713507988000,1,16424000,6824713524412000,0,"R",120,"[NULL]","swapper/5",0
-6824713508535000,4,250000,6824713508785000,22,"S",49,20,"sugov:4",606
-6824713508607000,0,56000,6824713508663000,11,"S",120,9,"rcuop/0",10
-6824713508663000,0,4135000,6824713512798000,0,"R",120,"[NULL]","swapper/5",0
-6824713508785000,4,35595000,6824713544380000,0,"R",120,"[NULL]","swapper/5",0
-6824713512798000,0,237000,6824713513035000,6,"S",120,4,"rcu_preempt",7
-6824713513035000,0,4264000,6824713517299000,0,"R",120,"[NULL]","swapper/5",0
-6824713517299000,0,410000,6824713517709000,6,"S",120,4,"rcu_preempt",7
-6824713517709000,0,229000,6824713517938000,23,"S",120,21,"rcuop/2",28
-6824713517917000,2,73000,6824713517990000,24,"S",120,22,"rcuop/3",36
-6824713517938000,0,144000,6824713518082000,9,"S",120,6,"rcuop/4",44
-6824713517990000,2,147000,6824713518137000,8,"S",120,8,"rcuop/6",60
-6824713518082000,0,5664000,6824713523746000,0,"R",120,"[NULL]","swapper/5",0
-6824713518137000,2,83000,6824713518220000,10,"S",120,11,"rcuop/5",52
-6824713518220000,2,10550000,6824713528770000,0,"R",120,"[NULL]","swapper/5",0
-6824713523746000,0,88000,6824713523834000,6,"S",120,4,"rcu_preempt",7
-6824713523834000,0,154000,6824713523988000,11,"R+",120,9,"rcuop/0",10
-6824713523988000,0,28000,6824713524016000,6,"S",120,4,"rcu_preempt",7
-6824713524016000,0,43000,6824713524059000,11,"S",120,9,"rcuop/0",10
-6824713524059000,0,4757000,6824713528816000,0,"R",120,"[NULL]","swapper/5",0
-6824713524412000,1,87000,6824713524499000,13,"S",120,12,"rcuop/1",20
-6824713524499000,1,4727000,6824713529226000,0,"R",120,"[NULL]","swapper/5",0
-6824713528770000,2,179000,6824713528949000,25,"S",120,24,"ksoftirqd/2",25
-6824713528816000,0,175000,6824713528991000,35,"S",120,33,"kworker/0:5",20371
-6824713528949000,2,1466000,6824713530415000,36,"S",111,34,"SDM_EventThread",685
-6824713528991000,0,531000,6824713529522000,16,"R+",120,14,"kworker/u16:7",19422
-6824713529226000,1,134000,6824713529360000,79,"S",100,64,"kworker/u17:2",14944
-6824713529360000,1,961000,6824713530321000,0,"R",120,"[NULL]","swapper/5",0
-6824713529522000,0,135000,6824713529657000,79,"S",100,64,"kworker/u17:2",14944
-6824713529649000,3,475000,6824713530124000,40,"S",97,35,"DispSync",676
-6824713529657000,0,56000,6824713529713000,35,"R+",120,33,"kworker/0:5",20371
-6824713529713000,0,55000,6824713529768000,79,"S",100,64,"kworker/u17:2",14944
-6824713529768000,0,119000,6824713529887000,35,"R+",120,33,"kworker/0:5",20371
-6824713529887000,0,214000,6824713530101000,79,"S",100,64,"kworker/u17:2",14944
-6824713530101000,0,105000,6824713530206000,35,"S",120,33,"kworker/0:5",20371
-6824713530124000,3,93000,6824713530217000,32,"S",120,30,"smem_native_rpm",87
-6824713530206000,0,40000,6824713530246000,6,"S",120,4,"rcu_preempt",7
-6824713530217000,3,33925000,6824713564142000,0,"R",120,"[NULL]","swapper/5",0
-6824713530246000,0,81000,6824713530327000,16,"S",120,14,"kworker/u16:7",19422
-6824713530321000,1,505000,6824713530826000,41,"S",97,35,"app",678
-6824713530327000,0,1013000,6824713531340000,0,"R",120,"[NULL]","swapper/5",0
-6824713530415000,2,1002000,6824713531417000,0,"R",120,"[NULL]","swapper/5",0
-6824713530826000,1,558000,6824713531384000,38,"S",120,35,"HwBinder:640_1",721
-6824713531340000,0,2759000,6824713534099000,42,"S",120,36,"ndroid.systemui",1664
-6824713531384000,1,2683000,6824713534067000,0,"R",120,"[NULL]","swapper/5",0
-6824713531417000,2,89000,6824713531506000,40,"S",97,35,"DispSync",676
-6824713531418000,5,849000,6824713532267000,4,"S",120,5,"UsbFfs-worker",20308
-6824713531506000,2,8373000,6824713539879000,0,"R",120,"[NULL]","swapper/5",0
-6824713532267000,5,3668000,6824713535935000,7,"S",120,5,"adbd",20305
-6824713534067000,1,310000,6824713534377000,43,"S",120,35,"Binder:640_2",675
-6824713534099000,0,433000,6824713534532000,0,"R",120,"[NULL]","swapper/5",0
-6824713534377000,1,510000,6824713534887000,0,"R",120,"[NULL]","swapper/5",0
-6824713534532000,0,188000,6824713534720000,41,"S",97,35,"app",678
-6824713534720000,0,2286000,6824713537006000,0,"R",120,"[NULL]","swapper/5",0
-6824713534887000,1,85000,6824713534972000,40,"S",97,35,"DispSync",676
-6824713534972000,1,29038000,6824713564010000,0,"R",120,"[NULL]","swapper/5",0
-6824713535935000,5,3107000,6824713539042000,91,"R+",120,75,"sh",20465
-6824713537006000,0,74000,6824713537080000,6,"S",120,4,"rcu_preempt",7
-6824713537080000,0,59000,6824713537139000,11,"S",120,9,"rcuop/0",10
-6824713537139000,0,2739000,6824713539878000,0,"R",120,"[NULL]","swapper/5",0
-6824713538441000,7,113000,6824713538554000,27,"S",120,25,"rcuos/4",45
-6824713538554000,7,5437000,6824713543991000,0,"R",120,"[NULL]","swapper/5",0
-6824713538812000,6,55000,6824713538867000,5,"S",120,7,"rcu_sched",8
-6824713538867000,6,4782000,6824713543649000,0,"R",120,"[NULL]","swapper/5",0
-6824713539042000,5,1123000,6824713540165000,7,"S",120,5,"adbd",20305
-6824713539878000,0,278000,6824713540156000,9,"R+",120,6,"rcuop/4",44
-6824713539879000,2,332000,6824713540211000,76,"S",120,62,"hwrng",215
-6824713540156000,0,139000,6824713540295000,79,"S",100,64,"kworker/u17:2",14944
-6824713540165000,5,271000,6824713540436000,91,"R+",120,75,"sh",20465
-6824713540211000,2,1202000,6824713541413000,0,"R",120,"[NULL]","swapper/5",0
-6824713540295000,0,37000,6824713540332000,6,"S",120,4,"rcu_preempt",7
-6824713540332000,0,118000,6824713540450000,35,"S",120,33,"kworker/0:5",20371
-6824713540436000,5,70000,6824713540506000,4,"S",120,5,"UsbFfs-worker",20308
-6824713540450000,0,46000,6824713540496000,9,"S",120,6,"rcuop/4",44
-6824713540496000,0,316000,6824713540812000,0,"R",120,"[NULL]","swapper/5",0
-6824713540506000,5,886000,6824713541392000,91,"R",120,75,"sh",20465
-6824713540812000,0,76000,6824713540888000,79,"S",100,64,"kworker/u17:2",14944
-6824713540888000,0,6183000,6824713547071000,0,"R",120,"[NULL]","swapper/5",0
-6824713541392000,5,115000,6824713541507000,79,"S",100,64,"kworker/u17:2",14944
-6824713541413000,2,46000,6824713541459000,76,"S",120,62,"hwrng",215
-6824713541459000,2,6115000,6824713547574000,0,"R",120,"[NULL]","swapper/5",0
-6824713541507000,5,68000,6824713541575000,92,"R+",120,76,"kworker/5:2",19092
-6824713541575000,5,59000,6824713541634000,79,"S",100,64,"kworker/u17:2",14944
-6824713541634000,5,105000,6824713541739000,92,"S",120,76,"kworker/5:2",19092
-6824713541739000,5,246000,6824713541985000,4,"S",120,5,"UsbFfs-worker",20308
-6824713541985000,5,354000,6824713542339000,7,"R+",120,5,"adbd",20305
-6824713542339000,5,29000,6824713542368000,79,"S",100,64,"kworker/u17:2",14944
-6824713542368000,5,84000,6824713542452000,7,"S",120,5,"adbd",20305
-6824713542452000,5,329000,6824713542781000,91,"R+",120,75,"sh",20465
-6824713542781000,5,61000,6824713542842000,79,"S",100,64,"kworker/u17:2",14944
-6824713542842000,5,68000,6824713542910000,92,"S",120,76,"kworker/5:2",19092
-6824713542910000,5,36000,6824713542946000,4,"S",120,5,"UsbFfs-worker",20308
-6824713542946000,5,4105000,6824713547051000,91,"R",120,75,"sh",20465
-6824713543649000,6,83000,6824713543732000,5,"S",120,7,"rcu_sched",8
-6824713543732000,6,730000,6824713544462000,0,"R",120,"[NULL]","swapper/5",0
-6824713543991000,7,134000,6824713544125000,27,"S",120,25,"rcuos/4",45
-6824713544125000,7,6499000,6824713550624000,0,"R",120,"[NULL]","swapper/5",0
-6824713544380000,4,97000,6824713544477000,93,"S",120,77,"rcuos/5",53
-6824713544462000,6,45000,6824713544507000,5,"S",120,7,"rcu_sched",8
-6824713544477000,4,6494000,6824713550971000,0,"R",120,"[NULL]","swapper/5",0
-6824713544507000,6,5784000,6824713550291000,0,"R",120,"[NULL]","swapper/5",0
-6824713547051000,5,95000,6824713547146000,6,"S",120,4,"rcu_preempt",7
-6824713547071000,0,137000,6824713547208000,62,"S",120,43,"Executor-7",14763
-6824713547146000,5,228000,6824713547374000,94,"R",120,5,"shell",20466
-6824713547208000,0,181000,6824713547389000,9,"S",120,6,"rcuop/4",44
-6824713547374000,5,21000,6824713547395000,6,"S",120,4,"rcu_preempt",7
-6824713547389000,0,13607000,6824713560996000,0,"R",120,"[NULL]","swapper/5",0
-6824713547395000,5,225000,6824713547620000,94,"S",120,5,"shell",20466
-6824713547574000,2,56000,6824713547630000,10,"S",120,11,"rcuop/5",52
-6824713547620000,5,5690000,6824713553310000,91,"R",120,75,"sh",20465
-6824713547630000,2,46000,6824713547676000,76,"S",120,62,"hwrng",215
-6824713547676000,2,15043000,6824713562719000,0,"R",120,"[NULL]","swapper/5",0
-6824713550291000,6,80000,6824713550371000,5,"S",120,7,"rcu_sched",8
-6824713550371000,6,24532000,6824713574903000,0,"R",120,"[NULL]","swapper/5",0
-6824713550624000,7,88000,6824713550712000,27,"S",120,25,"rcuos/4",45
-6824713550712000,7,23645000,6824713574357000,0,"R",120,"[NULL]","swapper/5",0
-6824713550971000,4,48000,6824713551019000,93,"S",120,77,"rcuos/5",53
-6824713551019000,4,14066000,6824713565085000,0,"R",120,"[NULL]","swapper/5",0
-6824713553310000,5,86000,6824713553396000,6,"S",120,4,"rcu_preempt",7
-6824713553396000,5,69000,6824713553465000,9,"S",120,6,"rcuop/4",44
-6824713553465000,5,36000,6824713553501000,10,"S",120,11,"rcuop/5",52
-6824713553501000,5,6486000,6824713559987000,91,"R",120,75,"sh",20465
-6824713559987000,5,57000,6824713560044000,92,"S",120,76,"kworker/5:2",19092
-6824713560044000,5,2577000,6824713562621000,91,"R+",120,75,"sh",20465
-6824713560996000,0,1098000,6824713562094000,95,"D",100,78,"FileWatcherThre",908
-6824713562094000,0,235000,6824713562329000,35,"S",120,33,"kworker/0:5",20371
-6824713562329000,0,966000,6824713563295000,0,"R",120,"[NULL]","swapper/5",0
-6824713562621000,5,180000,6824713562801000,22,"S",49,20,"sugov:4",606
-6824713562719000,2,997000,6824713563716000,36,"S",111,34,"SDM_EventThread",685
-6824713562801000,5,33000,6824713562834000,9,"S",120,6,"rcuop/4",44
-6824713562834000,5,14000,6824713562848000,6,"S",120,4,"rcu_preempt",7
-6824713562848000,5,3776000,6824713566624000,91,"R",120,75,"sh",20465
-6824713563295000,0,346000,6824713563641000,40,"S",97,35,"DispSync",676
-6824713563641000,0,888000,6824713564529000,16,"S",120,14,"kworker/u16:7",19422
-6824713563716000,2,72000,6824713563788000,76,"S",120,62,"hwrng",215
-6824713563788000,2,972000,6824713564760000,0,"R",120,"[NULL]","swapper/5",0
-6824713564010000,1,574000,6824713564584000,38,"S",120,35,"HwBinder:640_1",721
-6824713564142000,3,453000,6824713564595000,41,"S",97,35,"app",678
-6824713564529000,0,91000,6824713564620000,35,"S",120,33,"kworker/0:5",20371
-6824713564584000,1,2497000,6824713567081000,0,"R",120,"[NULL]","swapper/5",0
-6824713564595000,3,3222000,6824713567817000,42,"S",120,36,"ndroid.systemui",1664
-6824713564620000,0,1978000,6824713566598000,0,"R",120,"[NULL]","swapper/5",0
-6824713564760000,2,90000,6824713564850000,40,"S",97,35,"DispSync",676
-6824713564850000,2,3091000,6824713567941000,0,"R",120,"[NULL]","swapper/5",0
-6824713565085000,4,514000,6824713565599000,95,"D",100,78,"FileWatcherThre",908
-6824713565599000,4,22373000,6824713587972000,0,"R",120,"[NULL]","swapper/5",0
-6824713566598000,0,117000,6824713566715000,35,"S",120,33,"kworker/0:5",20371
-6824713566624000,5,23000,6824713566647000,6,"S",120,4,"rcu_preempt",7
-6824713566647000,5,2458000,6824713569105000,91,"S",120,75,"sh",20465
-6824713566715000,0,1121000,6824713567836000,0,"R",120,"[NULL]","swapper/5",0
-6824713567081000,1,530000,6824713567611000,95,"S",100,78,"FileWatcherThre",908
-6824713567611000,1,1518000,6824713569129000,0,"R",120,"[NULL]","swapper/5",0
-6824713567817000,3,13943000,6824713581760000,0,"R",120,"[NULL]","swapper/5",0
-6824713567836000,0,68000,6824713567904000,11,"S",120,9,"rcuop/0",10
-6824713567904000,0,700000,6824713568604000,0,"R",120,"[NULL]","swapper/5",0
-6824713567941000,2,390000,6824713568331000,43,"S",120,35,"Binder:640_2",675
-6824713568331000,2,4718000,6824713573049000,0,"R",120,"[NULL]","swapper/5",0
-6824713568604000,0,218000,6824713568822000,41,"S",97,35,"app",678
-6824713568822000,0,11756000,6824713580578000,0,"R",120,"[NULL]","swapper/5",0
-6824713569105000,5,4189000,6824713573294000,97,"R+",120,79,"atrace",20467
-6824713569129000,1,107000,6824713569236000,40,"S",97,35,"DispSync",676
-6824713569236000,1,12634000,6824713581870000,0,"R",120,"[NULL]","swapper/5",0
-6824713573049000,2,113000,6824713573162000,76,"S",120,62,"hwrng",215
-6824713573162000,2,2555000,6824713575717000,0,"R",120,"[NULL]","swapper/5",0
-6824713573294000,5,49000,6824713573343000,6,"S",120,4,"rcu_preempt",7
-6824713573343000,5,37000,6824713573380000,9,"S",120,6,"rcuop/4",44
-6824713573380000,5,23000,6824713573403000,10,"S",120,11,"rcuop/5",52
-6824713573403000,5,6607000,6824713580010000,97,"R+",120,79,"atrace",20467
-6824713574357000,7,104000,6824713574461000,27,"S",120,25,"rcuos/4",45
-6824713574461000,7,12988000,6824713587449000,0,"R",120,"[NULL]","swapper/5",0
-6824713574903000,6,48000,6824713574951000,5,"S",120,7,"rcu_sched",8
-6824713574951000,6,5495000,6824713580446000,0,"R",120,"[NULL]","swapper/5",0
-6824713575717000,2,111000,6824713575828000,76,"S",120,62,"hwrng",215
-6824713575828000,2,22002000,6824713597830000,0,"R",120,"[NULL]","swapper/5",0
-6824713580010000,5,60000,6824713580070000,6,"S",120,4,"rcu_preempt",7
-6824713580070000,5,3250000,6824713583320000,97,"R+",120,79,"atrace",20467
-6824713580446000,6,32000,6824713580478000,5,"S",120,7,"rcu_sched",8
-6824713580478000,6,6544000,6824713587022000,0,"R",120,"[NULL]","swapper/5",0
-6824713580578000,0,647000,6824713581225000,16,"D",120,14,"kworker/u16:7",19422
-6824713581225000,0,158000,6824713581383000,11,"S",120,9,"rcuop/0",10
-6824713581383000,0,892000,6824713582275000,0,"R",120,"[NULL]","swapper/5",0
-6824713581760000,3,187000,6824713581947000,32,"S",120,30,"smem_native_rpm",87
-6824713581870000,1,91000,6824713581961000,13,"S",120,12,"rcuop/1",20
-6824713581947000,3,16557000,6824713598504000,0,"R",120,"[NULL]","swapper/5",0
-6824713581961000,1,15601000,6824713597562000,0,"R",120,"[NULL]","swapper/5",0
-6824713582275000,0,89000,6824713582364000,16,"S",120,14,"kworker/u16:7",19422
-6824713582364000,0,14442000,6824713596806000,0,"R",120,"[NULL]","swapper/5",0
-6824713583320000,5,148000,6824713583468000,22,"S",49,20,"sugov:4",606
-6824713583468000,5,3138000,6824713586606000,97,"R",120,79,"atrace",20467
-6824713586606000,5,29000,6824713586635000,6,"S",120,4,"rcu_preempt",7
-6824713586635000,5,43000,6824713586678000,9,"S",120,6,"rcuop/4",44
-6824713586678000,5,94000,6824713586772000,10,"S",120,11,"rcuop/5",52
-6824713586772000,5,8000,6824713586780000,6,"S",120,4,"rcu_preempt",7
-6824713586780000,5,6480000,6824713593260000,97,"R",120,79,"atrace",20467
-6824713587022000,6,46000,6824713587068000,5,"S",120,7,"rcu_sched",8
-6824713587068000,6,1013000,6824713588081000,0,"R",120,"[NULL]","swapper/5",0
-6824713587449000,7,83000,6824713587532000,27,"S",120,25,"rcuos/4",45
-6824713587532000,7,6610000,6824713594142000,0,"R",120,"[NULL]","swapper/5",0
-6824713587972000,4,51000,6824713588023000,93,"S",120,77,"rcuos/5",53
-6824713588023000,4,6549000,6824713594572000,0,"R",120,"[NULL]","swapper/5",0
-6824713588081000,6,24000,6824713588105000,5,"S",120,7,"rcu_sched",8
-6824713588105000,6,5555000,6824713593660000,0,"R",120,"[NULL]","swapper/5",0
-6824713593260000,5,24000,6824713593284000,6,"S",120,4,"rcu_preempt",7
-6824713593284000,5,18000,6824713593302000,9,"S",120,6,"rcuop/4",44
-6824713593302000,5,19000,6824713593321000,10,"S",120,11,"rcuop/5",52
-6824713593321000,5,9953000,6824713603274000,97,"R",120,79,"atrace",20467
-6824713593660000,6,42000,6824713593702000,5,"S",120,7,"rcu_sched",8
-6824713593702000,6,41271000,6824713634973000,0,"R",120,"[NULL]","swapper/5",0
-6824713594142000,7,54000,6824713594196000,27,"S",120,25,"rcuos/4",45
-6824713594196000,7,40777000,6824713634973000,0,"R",120,"[NULL]","swapper/5",0
-6824713594572000,4,31000,6824713594603000,93,"S",120,77,"rcuos/5",53
-6824713594603000,4,40370000,6824713634973000,0,"R",120,"[NULL]","swapper/5",0
-6824713596806000,0,434000,6824713597240000,40,"S",97,35,"DispSync",676
-6824713597240000,0,240000,6824713597480000,35,"S",120,33,"kworker/0:5",20371
-6824713597480000,0,864000,6824713598344000,0,"R",120,"[NULL]","swapper/5",0
-6824713597562000,1,518000,6824713598080000,41,"S",97,35,"app",678
-6824713597830000,2,805000,6824713598635000,36,"S",111,34,"SDM_EventThread",685
-6824713598080000,1,765000,6824713598845000,0,"R",120,"[NULL]","swapper/5",0
-6824713598344000,0,3217000,6824713601561000,42,"S",120,36,"ndroid.systemui",1664
-6824713598504000,3,105000,6824713598609000,40,"S",97,35,"DispSync",676
-6824713598609000,3,32422000,6824713631031000,0,"R",120,"[NULL]","swapper/5",0
-6824713598635000,2,932000,6824713599567000,0,"R",120,"[NULL]","swapper/5",0
-6824713598845000,1,556000,6824713599401000,38,"S",120,35,"HwBinder:640_1",721
-6824713599401000,1,2173000,6824713601574000,0,"R",120,"[NULL]","swapper/5",0
-6824713599567000,2,90000,6824713599657000,40,"S",97,35,"DispSync",676
-6824713599657000,2,23565000,6824713623222000,0,"R",120,"[NULL]","swapper/5",0
-6824713601561000,0,678000,6824713602239000,0,"R",120,"[NULL]","swapper/5",0
-6824713601574000,1,395000,6824713601969000,43,"S",120,35,"Binder:640_2",675
-6824713601969000,1,395000,6824713602364000,0,"R",120,"[NULL]","swapper/5",0
-6824713602239000,0,209000,6824713602448000,41,"S",97,35,"app",678
-6824713602364000,1,79000,6824713602443000,40,"S",97,35,"DispSync",676
-6824713602443000,1,27933000,6824713630376000,0,"R",120,"[NULL]","swapper/5",0
-6824713602448000,0,26982000,6824713629430000,0,"R",120,"[NULL]","swapper/5",0
-6824713603274000,5,115000,6824713603389000,22,"S",49,20,"sugov:4",606
-6824713603389000,5,17861000,6824713621250000,97,"R+",120,79,"atrace",20467
-6824713621250000,5,138000,6824713621388000,22,"S",49,20,"sugov:4",606
-6824713621388000,5,35000,6824713621423000,9,"S",120,6,"rcuop/4",44
-6824713621423000,5,19000,6824713621442000,6,"S",120,4,"rcu_preempt",7
-6824713621442000,5,5171000,6824713626613000,97,"R",120,79,"atrace",20467
-6824713623222000,2,232000,6824713623454000,76,"S",120,62,"hwrng",215
-6824713623454000,2,5577000,6824713629031000,0,"R",120,"[NULL]","swapper/5",0
-6824713626613000,5,45000,6824713626658000,6,"S",120,4,"rcu_preempt",7
-6824713626658000,5,26000,6824713626684000,9,"S",120,6,"rcuop/4",44
-6824713626684000,5,21000,6824713626705000,10,"S",120,11,"rcuop/5",52
-6824713626705000,5,6000,6824713626711000,6,"S",120,4,"rcu_preempt",7
-6824713626711000,5,282000,6824713626993000,97,"S",120,79,"atrace",20467
-6824713626993000,5,7817000,6824713634810000,0,"R",120,"[NULL]","swapper/5",0
-6824713629031000,2,2744000,6824713631775000,63,"R+",120,49,"hwservicemanage",602
-6824713629430000,0,258000,6824713629688000,35,"S",120,33,"kworker/0:5",20371
-6824713629688000,0,932000,6824713630620000,36,"R+",111,34,"SDM_EventThread",685
-6824713630376000,1,388000,6824713630764000,40,"S",97,35,"DispSync",676
-6824713630620000,0,466000,6824713631086000,41,"S",97,35,"app",678
-6824713630764000,1,886000,6824713631650000,0,"R",120,"[NULL]","swapper/5",0
-6824713631031000,3,505000,6824713631536000,38,"S",120,35,"HwBinder:640_1",721
-6824713631086000,0,116000,6824713631202000,16,"S",120,14,"kworker/u16:7",19422
-6824713631202000,0,181000,6824713631383000,36,"S",111,34,"SDM_EventThread",685
-6824713631383000,0,2291000,6824713633674000,0,"R",120,"[NULL]","swapper/5",0
-6824713631536000,3,3437000,6824713634973000,0,"R",120,"[NULL]","swapper/5",0
-6824713631650000,1,63000,6824713631713000,40,"S",97,35,"DispSync",676
-6824713631713000,1,1737000,6824713633450000,42,"S",120,36,"ndroid.systemui",1664
-6824713631775000,2,255000,6824713632030000,26,"S",49,23,"sugov:0",605
-6824713632030000,2,108000,6824713632138000,63,"S",120,49,"hwservicemanage",602
-6824713632138000,2,437000,6824713632575000,97,"R+",120,79,"atrace",20467
-6824713632575000,2,334000,6824713632909000,63,"S",120,49,"hwservicemanage",602
-6824713632909000,2,263000,6824713633172000,97,"R+",120,79,"atrace",20467
-6824713633172000,2,340000,6824713633512000,98,"S",120,80,"atrace@1.0-serv",635
-6824713633450000,1,1179000,6824713634629000,0,"R",120,"[NULL]","swapper/5",0
-6824713633512000,2,169000,6824713633681000,97,"R+",120,79,"atrace",20467
-6824713633674000,0,213000,6824713633887000,43,"S",120,35,"Binder:640_2",675
-6824713633681000,2,75000,6824713633756000,98,"S",120,80,"atrace@1.0-serv",635
-6824713633756000,2,1217000,6824713634973000,97,"R",120,79,"atrace",20467
-6824713633887000,0,1086000,6824713634973000,0,"R",120,"[NULL]","swapper/5",0
-6824713634629000,1,131000,6824713634760000,41,"S",97,35,"app",678
-6824713634760000,1,213000,6824713634973000,0,"R",120,"[NULL]","swapper/5",0
-6824713634810000,5,70000,6824713634880000,6,"S",120,4,"rcu_preempt",7
-6824713634880000,5,39000,6824713634919000,9,"S",120,6,"rcuop/4",44
-6824713634919000,5,54000,6824713634973000,10,"S",120,11,"rcuop/5",52
-6824713634973000,5,0,6824713634973000,0,"R",120,"[NULL]","swapper/5",0
diff --git a/test/trace_processor/systrace_html.sql b/test/trace_processor/systrace_html.sql
deleted file mode 100644
index 2251793..0000000
--- a/test/trace_processor/systrace_html.sql
+++ /dev/null
@@ -1 +0,0 @@
-select ts, cpu, dur, ts_end, utid, end_state, priority, upid, name, tid  from sched join thread using(utid) order by ts
\ No newline at end of file
diff --git a/test/trace_processor/thread_cpu_time.sql b/test/trace_processor/thread_cpu_time.sql
index b487fe0..88425a3 100644
--- a/test/trace_processor/thread_cpu_time.sql
+++ b/test/trace_processor/thread_cpu_time.sql
@@ -1,5 +1,7 @@
 select
+  utid,
   tid,
+  upid,
   pid,
   thread.name as threadName,
   process.name as processName,
@@ -10,6 +12,5 @@
   left join (select upid, sum(dur) as total_dur
       from sched join thread using(utid)
       group by upid
-    ) using(upid)
-group by utid, upid
-order by total_dur desc, pid, tid
+    ) using(upid) group by utid, upid
+order by total_dur desc, upid, utid
diff --git a/test/trace_processor/thread_cpu_time_example_android_trace_30s.out b/test/trace_processor/thread_cpu_time_example_android_trace_30s.out
index ed48018..c037674 100644
--- a/test/trace_processor/thread_cpu_time_example_android_trace_30s.out
+++ b/test/trace_processor/thread_cpu_time_example_android_trace_30s.out
@@ -1,1655 +1,1655 @@
-"tid","pid","threadName","processName","totalDur"
-2,2,"kthreadd","kthreadd",22857974895
-3,2,"ksoftirqd/0","kthreadd",22857974895
-4,2,"kworker/0:0","kthreadd",22857974895
-6,2,"kworker/u16:0","kthreadd",22857974895
-7,2,"rcu_preempt","kthreadd",22857974895
-8,2,"rcu_sched","kthreadd",22857974895
-10,2,"rcuop/0","kthreadd",22857974895
-11,2,"rcuos/0","kthreadd",22857974895
-13,2,"migration/0","kthreadd",22857974895
-14,2,"watchdog/0","kthreadd",22857974895
-15,2,"watchdog/1","kthreadd",22857974895
-16,2,"migration/1","kthreadd",22857974895
-17,2,"ksoftirqd/1","kthreadd",22857974895
-18,2,"kworker/1:0","kthreadd",22857974895
-20,2,"rcuop/1","kthreadd",22857974895
-21,2,"rcuos/1","kthreadd",22857974895
-23,2,"watchdog/2","kthreadd",22857974895
-24,2,"migration/2","kthreadd",22857974895
-25,2,"ksoftirqd/2","kthreadd",22857974895
-28,2,"rcuop/2","kthreadd",22857974895
-29,2,"rcuos/2","kthreadd",22857974895
-31,2,"watchdog/3","kthreadd",22857974895
-32,2,"migration/3","kthreadd",22857974895
-33,2,"ksoftirqd/3","kthreadd",22857974895
-34,2,"kworker/3:0","kthreadd",22857974895
-36,2,"rcuop/3","kthreadd",22857974895
-37,2,"rcuos/3","kthreadd",22857974895
-39,2,"watchdog/4","kthreadd",22857974895
-40,2,"migration/4","kthreadd",22857974895
-41,2,"ksoftirqd/4","kthreadd",22857974895
-42,2,"kworker/4:0","kthreadd",22857974895
-44,2,"rcuop/4","kthreadd",22857974895
-45,2,"rcuos/4","kthreadd",22857974895
-47,2,"watchdog/5","kthreadd",22857974895
-48,2,"migration/5","kthreadd",22857974895
-49,2,"ksoftirqd/5","kthreadd",22857974895
-52,2,"rcuop/5","kthreadd",22857974895
-53,2,"rcuos/5","kthreadd",22857974895
-55,2,"watchdog/6","kthreadd",22857974895
-56,2,"migration/6","kthreadd",22857974895
-57,2,"ksoftirqd/6","kthreadd",22857974895
-60,2,"rcuop/6","kthreadd",22857974895
-61,2,"rcuos/6","kthreadd",22857974895
-63,2,"watchdog/7","kthreadd",22857974895
-64,2,"migration/7","kthreadd",22857974895
-65,2,"ksoftirqd/7","kthreadd",22857974895
-66,2,"kworker/7:0","kthreadd",22857974895
-68,2,"rcuop/7","kthreadd",22857974895
-69,2,"rcuos/7","kthreadd",22857974895
-80,2,"kworker/0:1","kthreadd",22857974895
-81,2,"smem_native_mps","kthreadd",22857974895
-82,2,"mpss_smem_glink","kthreadd",22857974895
-83,2,"smem_native_lpa","kthreadd",22857974895
-84,2,"lpass_smem_glin","kthreadd",22857974895
-85,2,"smem_native_dsp","kthreadd",22857974895
-86,2,"dsps_smem_glink","kthreadd",22857974895
-87,2,"smem_native_rpm","kthreadd",22857974895
-91,2,"msm_watchdog","kthreadd",22857974895
-93,2,"kworker/u16:1","kthreadd",22857974895
-94,2,"irq/126-cpr3","kthreadd",22857974895
-105,2,"system","kthreadd",22857974895
-150,2,"kswapd0","kthreadd",22857974895
-188,2,"vsync_retire_wo","kthreadd",22857974895
-193,2,"spi_wdsp","kthreadd",22857974895
-194,2,"wdsp_spi_glink_","kthreadd",22857974895
-201,2,"kworker/4:1","kthreadd",22857974895
-215,2,"hwrng","kthreadd",22857974895
-217,2,"kworker/2:1","kthreadd",22857974895
-253,2,"kworker/3:1","kthreadd",22857974895
-292,2,"kgsl_worker_thr","kthreadd",22857974895
-321,2,"irq/286-soc:fp_","kthreadd",22857974895
-329,2,"kworker/5:1","kthreadd",22857974895
-330,2,"spi2","kthreadd",22857974895
-345,2,"irq/262-vl53l0_","kthreadd",22857974895
-360,2,"kworker/u16:6","kthreadd",22857974895
-368,2,"rot_commitq_0_0","kthreadd",22857974895
-370,2,"rot_doneq_0_0","kthreadd",22857974895
-372,2,"kworker/4:3","kthreadd",22857974895
-411,2,"kworker/1:1","kthreadd",22857974895
-415,2,"kworker/6:2","kthreadd",22857974895
-459,2,"irq/226-bcm1560","kthreadd",22857974895
-462,2,"kworker/u16:8","kthreadd",22857974895
-492,2,"irq/747-ima-rdy","kthreadd",22857974895
-520,2,"kworker/5:2","kthreadd",22857974895
-521,2,"set_state_work","kthreadd",22857974895
-522,2,"irq/227-mnh-rea","kthreadd",22857974895
-523,2,"irq/751-mnh_pci","kthreadd",22857974895
-524,2,"irq/752-mnh_pci","kthreadd",22857974895
-526,2,"irq/754-mnh_pci","kthreadd",22857974895
-528,2,"irq/758-mnh_pci","kthreadd",22857974895
-545,2,"kworker/6:1H","kthreadd",22857974895
-546,2,"kworker/4:1H","kthreadd",22857974895
-547,2,"kworker/7:1H","kthreadd",22857974895
-549,2,"kworker/5:1H","kthreadd",22857974895
-559,2,"kworker/0:1H","kthreadd",22857974895
-561,2,"kworker/u16:10","kthreadd",22857974895
-568,2,"irq/760-synapti","kthreadd",22857974895
-592,2,"sugov:0","kthreadd",22857974895
-593,2,"sugov:4","kthreadd",22857974895
-597,2,"kauditd","kthreadd",22857974895
-610,2,"wlan_logging_th","kthreadd",22857974895
-634,2,"kworker/1:3","kthreadd",22857974895
-640,2,"kworker/7:2","kthreadd",22857974895
-641,2,"jbd2/sda45-8","kthreadd",22857974895
-665,2,"kworker/0:3","kthreadd",22857974895
-667,2,"kworker/0:4","kthreadd",22857974895
-695,2,"msm_slim_qmi_cl","kthreadd",22857974895
-704,2,"kworker/5:3","kthreadd",22857974895
-737,2,"kworker/2:1H","kthreadd",22857974895
-738,2,"kworker/u16:11","kthreadd",22857974895
-739,2,"kworker/u16:12","kthreadd",22857974895
-756,2,"kworker/1:1H","kthreadd",22857974895
-807,2,"irq/254-wcd9xxx","kthreadd",22857974895
-829,2,"kworker/u16:13","kthreadd",22857974895
-860,2,"kworker/u16:14","kthreadd",22857974895
-872,2,"kworker/3:2","kthreadd",22857974895
-877,2,"kworker/u16:15","kthreadd",22857974895
-926,2,"kworker/3:1H","kthreadd",22857974895
-1055,2,"kworker/7:3","kthreadd",22857974895
-1084,2,"kworker/u17:1","kthreadd",22857974895
-1948,2,"kworker/2:2","kthreadd",22857974895
-2188,2,"cds_mc_thread","kthreadd",22857974895
-2189,2,"cds_ol_rx_threa","kthreadd",22857974895
-2287,2,"irq/35-1008000.","kthreadd",22857974895
-3776,2,"kworker/3:3","kthreadd",22857974895
-4494,2,"mdss_fb0","kthreadd",22857974895
-4795,2,"kworker/2:3","kthreadd",22857974895
-5492,2,"kworker/3:4","kthreadd",22857974895
-5745,2,"irq/163-arm-smm","kthreadd",22857974895
-5759,2,"irq/164-arm-smm","kthreadd",22857974895
-5778,2,"irq/165-arm-smm","kthreadd",22857974895
-5780,2,"ois_wq","kthreadd",22857974895
-5798,2,"rot_fenceq_0_0","kthreadd",22857974895
-5799,2,"irq/166-arm-smm","kthreadd",22857974895
-5800,2,"irq/167-arm-smm","kthreadd",22857974895
-5932,2,"mdss_fb0","kthreadd",22857974895
-5506,5506,"id.GoogleCamera","com.google.android.GoogleCamera",15154766434
-5511,5506,"Jit thread pool","com.google.android.GoogleCamera",15154766434
-5512,5506,"Signal Catcher","com.google.android.GoogleCamera",15154766434
-5513,5506,"ADB-JDWP Connec","com.google.android.GoogleCamera",15154766434
-5514,5506,"ReferenceQueueD","com.google.android.GoogleCamera",15154766434
-5515,5506,"FinalizerDaemon","com.google.android.GoogleCamera",15154766434
-5516,5506,"FinalizerWatchd","com.google.android.GoogleCamera",15154766434
-5517,5506,"HeapTaskDaemon","com.google.android.GoogleCamera",15154766434
-5518,5506,"Binder:5506_1","com.google.android.GoogleCamera",15154766434
-5519,5506,"Binder:5506_2","com.google.android.GoogleCamera",15154766434
-5520,5506,"Profile Saver","com.google.android.GoogleCamera",15154766434
-5522,5506,"GoogleApiHandle","com.google.android.GoogleCamera",15154766434
-5524,5506,"queued-work-loo","com.google.android.GoogleCamera",15154766434
-5525,5506,"Executor-1","com.google.android.GoogleCamera",15154766434
-5526,5506,"Executor-2","com.google.android.GoogleCamera",15154766434
-5527,5506,"Executor-3","com.google.android.GoogleCamera",15154766434
-5528,5506,"Executor-4","com.google.android.GoogleCamera",15154766434
-5529,5506,"IOExecutor-1","com.google.android.GoogleCamera",15154766434
-5530,5506,"IndicatorUpdate","com.google.android.GoogleCamera",15154766434
-5531,5506,"CamcorderCamera","com.google.android.GoogleCamera",15154766434
-5532,5506,"Thread-11","com.google.android.GoogleCamera",15154766434
-5533,5506,"Thread-12","com.google.android.GoogleCamera",15154766434
-5534,5506,"Thread-92","com.google.android.GoogleCamera",15154766434
-5536,5506,"Executor-5","com.google.android.GoogleCamera",15154766434
-5537,5506,"Executor-6","com.google.android.GoogleCamera",15154766434
-5538,5506,"RenderThread","com.google.android.GoogleCamera",15154766434
-5541,5506,"Executor-7","com.google.android.GoogleCamera",15154766434
-5557,5506,"RenderThread","com.google.android.GoogleCamera",15154766434
-5559,5506,"RenderThread","com.google.android.GoogleCamera",15154766434
-5595,5506,"Executor-8","com.google.android.GoogleCamera",15154766434
-5596,5506,"Camera-Hndlr","com.google.android.GoogleCamera",15154766434
-5597,5506,"SoundPool","com.google.android.GoogleCamera",15154766434
-5598,5506,"SoundPoolThread","com.google.android.GoogleCamera",15154766434
-5599,5506,"UsageStatEx","com.google.android.GoogleCamera",15154766434
-5600,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
-5601,5506,"HwBinder:5506_1","com.google.android.GoogleCamera",15154766434
-5604,5506,"Camera-Ex","com.google.android.GoogleCamera",15154766434
-5626,5506,"Camera Handler ","com.google.android.GoogleCamera",15154766434
-5632,5506,"Camera Job Disp","com.google.android.GoogleCamera",15154766434
-5634,5506,"Binder:5506_3","com.google.android.GoogleCamera",15154766434
-5641,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
-5648,5506,"camera.wearable","com.google.android.GoogleCamera",15154766434
-5649,5506,"CamcorderCamera","com.google.android.GoogleCamera",15154766434
-5650,5506,"Binder:5506_4","com.google.android.GoogleCamera",15154766434
-5651,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
-5654,5506,"IR-RAW10w4032","com.google.android.GoogleCamera",15154766434
-5655,5506,"Binder:5506_5","com.google.android.GoogleCamera",15154766434
-5657,5506,"MicrovideoFrame","com.google.android.GoogleCamera",15154766434
-5658,5506,"AsyncTask #1","com.google.android.GoogleCamera",15154766434
-5673,5506,"IR-YUV_420_888w","com.google.android.GoogleCamera",15154766434
-5674,5506,"IR-JPEGw4032","com.google.android.GoogleCamera",15154766434
-5675,5506,"reproc-write","com.google.android.GoogleCamera",15154766434
-5676,5506,"reproc-read","com.google.android.GoogleCamera",15154766434
-5679,5506,"CameraEx-1","com.google.android.GoogleCamera",15154766434
-5680,5506,"CameraEx-2","com.google.android.GoogleCamera",15154766434
-5681,5506,"MicrovideoQShar","com.google.android.GoogleCamera",15154766434
-5682,5506,"n.StateCallback","com.google.android.GoogleCamera",15154766434
-5684,5506,"mv-vid-encoder","com.google.android.GoogleCamera",15154766434
-5686,5506,"SharedPreferenc","com.google.android.GoogleCamera",15154766434
-5696,5506,"AsyncTask #2","com.google.android.GoogleCamera",15154766434
-5701,5506,"GcaMetadataHand","com.google.android.GoogleCamera",15154766434
-5702,5506,"r.ImageListener","com.google.android.GoogleCamera",15154766434
-5703,5506,"Binder:5506_6","com.google.android.GoogleCamera",15154766434
-5706,5506,"OnDemandLoader","com.google.android.GoogleCamera",15154766434
-5713,5506,"NotificationDot","com.google.android.GoogleCamera",15154766434
-5722,5506,"GAC_Executor[0]","com.google.android.GoogleCamera",15154766434
-5729,5506,"Timer-0","com.google.android.GoogleCamera",15154766434
-5732,5506,"GAC_Executor[1]","com.google.android.GoogleCamera",15154766434
-5733,5506,"Timer-1","com.google.android.GoogleCamera",15154766434
-5734,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
-5743,5506,"AsyncTask #3","com.google.android.GoogleCamera",15154766434
-5760,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
-5769,5506,"hwuiTask1","com.google.android.GoogleCamera",15154766434
-5772,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
-5775,5506,"Timer-2","com.google.android.GoogleCamera",15154766434
-5781,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
-5793,5506,"mv-ctrl-exec","com.google.android.GoogleCamera",15154766434
-5794,5506,"ois-exec","com.google.android.GoogleCamera",15154766434
-5795,5506,"mv-meta-exec","com.google.android.GoogleCamera",15154766434
-5796,5506,"mv-gyro-exec-0","com.google.android.GoogleCamera",15154766434
-5797,5506,"DelHDR+Ind","com.google.android.GoogleCamera",15154766434
-5801,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
-5804,5506,"FilterHDR+Ind","com.google.android.GoogleCamera",15154766434
-5805,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
-5808,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
-5811,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
-5814,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
-5817,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
-5824,5506,"CameraProcessin","com.google.android.GoogleCamera",15154766434
-5825,5506,"ProcServ","com.google.android.GoogleCamera",15154766434
-5826,5506,"MediaCodec_loop","com.google.android.GoogleCamera",15154766434
-5827,5506,"CodecLooper","com.google.android.GoogleCamera",15154766434
-5829,5506,"Binder:5506_7","com.google.android.GoogleCamera",15154766434
-5834,5506,"IOExecutor-2","com.google.android.GoogleCamera",15154766434
-5839,5506,"AudioTrack","com.google.android.GoogleCamera",15154766434
-5845,5506,"Thread-38","com.google.android.GoogleCamera",15154766434
-5847,5506,"Capture tasks: ","com.google.android.GoogleCamera",15154766434
-5848,5506,"Capture tasks: ","com.google.android.GoogleCamera",15154766434
-5849,5506,"Capture tasks: ","com.google.android.GoogleCamera",15154766434
-5850,5506,"Capture tasks: ","com.google.android.GoogleCamera",15154766434
-5851,5506,"Capture tasks: ","com.google.android.GoogleCamera",15154766434
-5852,5506,"Capture tasks: ","com.google.android.GoogleCamera",15154766434
-5853,5506,"Capture tasks: ","com.google.android.GoogleCamera",15154766434
-5865,5506,"AsyncTask #4","com.google.android.GoogleCamera",15154766434
-5869,5506,"glide-source-th","com.google.android.GoogleCamera",15154766434
-5870,5506,"Thread-72","com.google.android.GoogleCamera",15154766434
-5872,5506,"Thread-56","com.google.android.GoogleCamera",15154766434
-5873,5506,"Thread-49","com.google.android.GoogleCamera",15154766434
-5875,5506,"Thread-52","com.google.android.GoogleCamera",15154766434
-5876,5506,"Thread-66","com.google.android.GoogleCamera",15154766434
-5877,5506,"Thread-65","com.google.android.GoogleCamera",15154766434
-5878,5506,"Thread-61","com.google.android.GoogleCamera",15154766434
-5879,5506,"Thread-58","com.google.android.GoogleCamera",15154766434
-5923,5506,"DelLifetime","com.google.android.GoogleCamera",15154766434
-5938,5506,"Thread-91","com.google.android.GoogleCamera",15154766434
-5940,5506,"Finish Thread","com.google.android.GoogleCamera",15154766434
-5941,5506,"Finish Thread","com.google.android.GoogleCamera",15154766434
-5943,5506,"Thread-85","com.google.android.GoogleCamera",15154766434
-5944,5506,"Thread-80","com.google.android.GoogleCamera",15154766434
-5945,5506,"Thread-84","com.google.android.GoogleCamera",15154766434
-5946,5506,"Thread-79","com.google.android.GoogleCamera",15154766434
-5947,5506,"Thread-81","com.google.android.GoogleCamera",15154766434
-5948,5506,"Thread-83","com.google.android.GoogleCamera",15154766434
-5949,5506,"Thread-82","com.google.android.GoogleCamera",15154766434
-6011,5506,"mv-disk-writer","com.google.android.GoogleCamera",15154766434
-1204,1204,"system_server","system_server",6809850362
-1211,1204,"ReferenceQueueD","system_server",6809850362
-1212,1204,"FinalizerDaemon","system_server",6809850362
-1213,1204,"FinalizerWatchd","system_server",6809850362
-1214,1204,"HeapTaskDaemon","system_server",6809850362
-1216,1204,"Binder:1204_1","system_server",6809850362
-1246,1204,"android.io","system_server",6809850362
-1249,1204,"android.bg","system_server",6809850362
-1250,1204,"ActivityManager","system_server",6809850362
-1251,1204,"android.ui","system_server",6809850362
-1252,1204,"ActivityManager","system_server",6809850362
-1253,1204,"ActivityManager","system_server",6809850362
-1254,1204,"batterystats-wo","system_server",6809850362
-1255,1204,"FileObserver","system_server",6809850362
-1256,1204,"android.fg","system_server",6809850362
-1257,1204,"android.display","system_server",6809850362
-1259,1204,"PowerManagerSer","system_server",6809850362
-1260,1204,"HwBinder:1204_1","system_server",6809850362
-1363,1204,"android.anim","system_server",6809850362
-1364,1204,"android.anim.lf","system_server",6809850362
-1373,1204,"SensorEventAckR","system_server",6809850362
-1374,1204,"SensorService","system_server",6809850362
-1383,1204,"SettingsProvide","system_server",6809850362
-1396,1204,"AlarmManager","system_server",6809850362
-1419,1204,"UEventObserver","system_server",6809850362
-1420,1204,"InputDispatcher","system_server",6809850362
-1421,1204,"InputReader","system_server",6809850362
-1423,1204,"NetworkWatchlis","system_server",6809850362
-1441,1204,"NetdConnector","system_server",6809850362
-1444,1204,"NetworkStats","system_server",6809850362
-1445,1204,"NetworkPolicy","system_server",6809850362
-1446,1204,"tworkPolicy.uid","system_server",6809850362
-1453,1204,"WifiService","system_server",6809850362
-1454,1204,"ClientModeImpl","system_server",6809850362
-1460,1204,"WifiScanningSer","system_server",6809850362
-1463,1204,"ConnectivitySer","system_server",6809850362
-1468,1204,"notification-sq","system_server",6809850362
-1469,1204,"ranker","system_server",6809850362
-1480,1204,"AudioService","system_server",6809850362
-1489,1204,"HwBinder:1204_3","system_server",6809850362
-1492,1204,"ConnectivityThr","system_server",6809850362
-1516,1204,"wifiAwareServic","system_server",6809850362
-1517,1204,"EthernetService","system_server",6809850362
-1519,1204,"TaskSnapshotPer","system_server",6809850362
-1525,1204,"PhotonicModulat","system_server",6809850362
-1529,1204,"LazyTaskWriterT","system_server",6809850362
-1581,1204,"NetworkStatsObs","system_server",6809850362
-1597,1204,"watchdog","system_server",6809850362
-1648,1204,"NetworkTimeUpda","system_server",6809850362
-1699,1204,"Binder:1204_4","system_server",6809850362
-1700,1204,"Binder:1204_5","system_server",6809850362
-1739,1204,"hidl_ssvc_poll","system_server",6809850362
-2274,1204,"IpClient.wlan0","system_server",6809850362
-2381,1204,"backup","system_server",6809850362
-2483,1204,"Binder:1204_A","system_server",6809850362
-2688,1204,"Binder:1204_10","system_server",6809850362
-2692,1204,"Binder:1204_12","system_server",6809850362
-2695,1204,"Binder:1204_15","system_server",6809850362
-2697,1204,"Binder:1204_16","system_server",6809850362
-3342,1204,"pool-4-thread-1","system_server",6809850362
-3482,1204,"Binder:1204_17","system_server",6809850362
-4064,1204,"Binder:1204_18","system_server",6809850362
-4743,1204,"Binder:1204_1A","system_server",6809850362
-5332,1204,"GrallocUploadTh","system_server",6809850362
-5498,1204,"RenderThread","system_server",6809850362
-5499,1204,"RenderThread","system_server",6809850362
-5313,5313,".android.chrome","com.android.chrome",5125412570
-5318,5313,"Jit thread pool","com.android.chrome",5125412570
-5319,5313,"Signal Catcher","com.android.chrome",5125412570
-5320,5313,"ADB-JDWP Connec","com.android.chrome",5125412570
-5321,5313,"ReferenceQueueD","com.android.chrome",5125412570
-5322,5313,"FinalizerDaemon","com.android.chrome",5125412570
-5323,5313,"FinalizerWatchd","com.android.chrome",5125412570
-5324,5313,"HeapTaskDaemon","com.android.chrome",5125412570
-5325,5313,"Binder:5313_1","com.android.chrome",5125412570
-5326,5313,"Binder:5313_2","com.android.chrome",5125412570
-5327,5313,"Profile Saver","com.android.chrome",5125412570
-5333,5313,"CrAsyncTask #1","com.android.chrome",5125412570
-5334,5313,"CrAsyncTask #2","com.android.chrome",5125412570
-5335,5313,"CrAsyncTask #3","com.android.chrome",5125412570
-5336,5313,"SharedPreferenc","com.android.chrome",5125412570
-5339,5313,"Thread-2","com.android.chrome",5125412570
-5342,5313,"Thread-3","com.android.chrome",5125412570
-5343,5313,"CrAsyncTask #4","com.android.chrome",5125412570
-5344,5313,"magnifier pixel","com.android.chrome",5125412570
-5345,5313,"RenderThread","com.android.chrome",5125412570
-5346,5313,"Gservices","com.android.chrome",5125412570
-5347,5313,"Chrome_ProcessL","com.android.chrome",5125412570
-5364,5313,"Binder:5313_3","com.android.chrome",5125412570
-5365,5313,"Chrome_IOThread","com.android.chrome",5125412570
-5366,5313,"TaskSchedulerSe","com.android.chrome",5125412570
-5367,5313,"TaskSchedulerFo","com.android.chrome",5125412570
-5368,5313,"TaskSchedulerFo","com.android.chrome",5125412570
-5369,5313,"DnsConfigServic","com.android.chrome",5125412570
-5370,5313,"TaskSchedulerFo","com.android.chrome",5125412570
-5371,5313,"TaskSchedulerFo","com.android.chrome",5125412570
-5372,5313,"TaskSchedulerSi","com.android.chrome",5125412570
-5373,5313,"queued-work-loo","com.android.chrome",5125412570
-5374,5313,"AudioThread","com.android.chrome",5125412570
-5375,5313,"BrowserWatchdog","com.android.chrome",5125412570
-5376,5313,"Chrome_HistoryT","com.android.chrome",5125412570
-5380,5313,"TaskSchedulerSi","com.android.chrome",5125412570
-5396,5313,"CompositorTileW","com.android.chrome",5125412570
-5399,5313,"hwuiTask1","com.android.chrome",5125412570
-5415,5313,"TaskSchedulerFo","com.android.chrome",5125412570
-5443,5313,"SAFE_BROWSING_U","com.android.chrome",5125412570
-5444,5313,"GoogleApiHandle","com.android.chrome",5125412570
-5461,5313,"SensorsHandlerT","com.android.chrome",5125412570
-5471,5313,"Binder:5313_4","com.android.chrome",5125412570
-5473,5313,"AudioTrack","com.android.chrome",5125412570
-5482,5313,"Chrome_DevTools","com.android.chrome",5125412570
-5496,5313,"TaskSchedulerFo","com.android.chrome",5125412570
-5502,5313,"TaskSchedulerFo","com.android.chrome",5125412570
-5503,5313,"TaskSchedulerFo","com.android.chrome",5125412570
-5935,5313,"Binder:5313_5","com.android.chrome",5125412570
-5348,5348,"dboxed_process0","com.android.chrome:sandboxed_process0",3569713072
-5353,5348,"Jit thread pool","com.android.chrome:sandboxed_process0",3569713072
-5354,5348,"Signal Catcher","com.android.chrome:sandboxed_process0",3569713072
-5355,5348,"ADB-JDWP Connec","com.android.chrome:sandboxed_process0",3569713072
-5356,5348,"ReferenceQueueD","com.android.chrome:sandboxed_process0",3569713072
-5357,5348,"FinalizerDaemon","com.android.chrome:sandboxed_process0",3569713072
-5358,5348,"FinalizerWatchd","com.android.chrome:sandboxed_process0",3569713072
-5359,5348,"HeapTaskDaemon","com.android.chrome:sandboxed_process0",3569713072
-5360,5348,"Binder:5348_1","com.android.chrome:sandboxed_process0",3569713072
-5361,5348,"Binder:5348_2","com.android.chrome:sandboxed_process0",3569713072
-5362,5348,"Binder:5348_3","com.android.chrome:sandboxed_process0",3569713072
-5363,5348,"CrRendererMain","com.android.chrome:sandboxed_process0",3569713072
-5402,5348,"TaskSchedulerSe","com.android.chrome:sandboxed_process0",3569713072
-5403,5348,"TaskSchedulerFo","com.android.chrome:sandboxed_process0",3569713072
-5404,5348,"TaskSchedulerFo","com.android.chrome:sandboxed_process0",3569713072
-5405,5348,"Chrome_ChildIOT","com.android.chrome:sandboxed_process0",3569713072
-5406,5348,"GpuMemoryThread","com.android.chrome:sandboxed_process0",3569713072
-5408,5348,"Compositor","com.android.chrome:sandboxed_process0",3569713072
-5413,5348,"CompositorTileW","com.android.chrome:sandboxed_process0",3569713072
-5414,5348,"CompositorTileW","com.android.chrome:sandboxed_process0",3569713072
-5447,5348,"TaskSchedulerFo","com.android.chrome:sandboxed_process0",3569713072
-5448,5348,"TaskSchedulerFo","com.android.chrome:sandboxed_process0",3569713072
-5449,5348,"TaskSchedulerFo","com.android.chrome:sandboxed_process0",3569713072
-5450,5348,"TaskSchedulerFo","com.android.chrome:sandboxed_process0",3569713072
-5451,5348,"TaskSchedulerFo","com.android.chrome:sandboxed_process0",3569713072
-5452,5348,"TaskSchedulerFo","com.android.chrome:sandboxed_process0",3569713072
-5455,5348,"ScriptStreamer ","com.android.chrome:sandboxed_process0",3569713072
-5462,5348,"Media","com.android.chrome:sandboxed_process0",3569713072
-5475,5348,"AudioOutputDevi","com.android.chrome:sandboxed_process0",3569713072
-759,759,"provider@2.4-se","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-1543,759,"CAM_imgTh","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-1696,759,"provider@2.4-se","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-1926,759,"HwBinder:759_1","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5606,759,"HwBinder:759_1","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5607,759,"HwBinder:759_1","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5608,759,"HwBinder:759_1","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5609,759,"QCamera3HdrPlus","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5610,759,"CAM_MctServ","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5611,759,"CAM_MctBus","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5614,759,"CAM_sensor","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5617,759,"CAM_iface_ses","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5620,759,"CAM_img_msg","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5621,759,"CAM_img_msg","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5622,759,"CAM_cpp","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5623,759,"CAM_isp_trigger","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5624,759,"CAM_c2d","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5625,759,"CAM_hw_update","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5627,759,"CAM_isp_parser","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5628,759,"CAM_startsensor","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5629,759,"CAM_gyro_sens","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5630,759,"CAM_startsensor","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5631,759,"CAM_startsensor","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5633,759,"CAM_img_msg","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5635,759,"CAM_AECAWB","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5636,759,"CAM_AF","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5637,759,"CAM_AFD","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5638,759,"CAM_ASD","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5639,759,"CAM_Dispatch","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5640,759,"CAM_evntPoll","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5644,759,"CAM_dataPoll","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5704,759,"cam_data_proc","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5705,759,"cam_data_proc","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5707,759,"mm_jpeg_thread","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5708,759,"OMX_ImgEnc","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5709,759,"cam_data_proc","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5710,759,"cam_data_proc","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5711,759,"cam_data_proc","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5719,759,"CAM_img","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5720,759,"CAM_img","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5721,759,"CAM_METADATA","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5723,759,"CAM_ANALYSISCAM","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5724,759,"CAM_PREVIEW","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5725,759,"CAM_SNAPSHOT","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5726,759,"CAM_CALLBACK","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5727,759,"CAM_CALLBACK","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5728,759,"CAM_RAW","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5730,759,"CAM_StrmAppDat","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5731,759,"CAM_StrmAppDat","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5742,759,"CAM_iface_poll","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5744,759,"CAM_iface_hw","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5752,759,"HwBinder:759_2","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5756,759,"HwBinder:759_1","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5757,759,"HwBinder:759_1","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5758,759,"CAM_laser_sens","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5762,759,"CAM_StrmAppDat","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5765,759,"CAM_StrmAppDat","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5766,759,"CAM_StrmAppDat","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5767,759,"CAM_StrmAppDat","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5768,759,"CAM_StrmAppDat","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5770,759,"HwBinder:759_3","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5776,759,"CAM_sof_timer","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-5862,759,"HwBinder:759_4","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
-1572,1572,"ndroid.systemui","com.android.systemui",3072242745
-1580,1572,"Jit thread pool","com.android.systemui",3072242745
-1584,1572,"ReferenceQueueD","com.android.systemui",3072242745
-1585,1572,"FinalizerDaemon","com.android.systemui",3072242745
-1586,1572,"FinalizerWatchd","com.android.systemui",3072242745
-1587,1572,"HeapTaskDaemon","com.android.systemui",3072242745
-1589,1572,"Binder:1572_1","com.android.systemui",3072242745
-1593,1572,"Binder:1572_2","com.android.systemui",3072242745
-1876,1572,"pool-1-thread-1","com.android.systemui",3072242745
-1932,1572,"VolumeDialogCon","com.android.systemui",3072242745
-1934,1572,"SysUiBg","com.android.systemui",3072242745
-1981,1572,"RenderThread","com.android.systemui",3072242745
-1994,1572,"ConnectivityThr","com.android.systemui",3072242745
-2002,1572,"AsyncTask #1","com.android.systemui",3072242745
-2021,1572,"async_sensor","com.android.systemui",3072242745
-2044,1572,"Binder:1572_5","com.android.systemui",3072242745
-2059,1572,"FlashlightContr","com.android.systemui",3072242745
-2079,1572,"Binder:1572_7","com.android.systemui",3072242745
-2090,1572,"recents.fg","com.android.systemui",3072242745
-2121,1572,"ScreenDecoratio","com.android.systemui",3072242745
-2256,1572,"GrallocUploadTh","com.android.systemui",3072242745
-2270,1572,"hwuiTask1","com.android.systemui",3072242745
-2275,1572,"Thread-2","com.android.systemui",3072242745
-2285,1572,"Binder:1572_8","com.android.systemui",3072242745
-5155,1572,"AsyncTask #6","com.android.systemui",3072242745
-5486,1572,"AsyncTask #7","com.android.systemui",3072242745
-5487,1572,"AsyncTask #8","com.android.systemui",3072242745
-5488,1572,"InflaterThread ","com.android.systemui",3072242745
-5489,1572,"InflaterThread ","com.android.systemui",3072242745
-5490,1572,"InflaterThread ","com.android.systemui",3072242745
-5493,1572,"InflaterThread ","com.android.systemui",3072242745
-2400,2400,"earchbox:search","com.google.android.googlequicksearchbox:search",2487567838
-2428,2400,"Jit thread pool","com.google.android.googlequicksearchbox:search",2487567838
-2442,2400,"ReferenceQueueD","com.google.android.googlequicksearchbox:search",2487567838
-2444,2400,"FinalizerDaemon","com.google.android.googlequicksearchbox:search",2487567838
-2446,2400,"FinalizerWatchd","com.google.android.googlequicksearchbox:search",2487567838
-2448,2400,"HeapTaskDaemon","com.google.android.googlequicksearchbox:search",2487567838
-2451,2400,"Binder:2400_1","com.google.android.googlequicksearchbox:search",2487567838
-2522,2400,"Profile Saver","com.google.android.googlequicksearchbox:search",2487567838
-2690,2400,"SearchSettings_","com.google.android.googlequicksearchbox:search",2487567838
-2778,2400,"NonUserFacing0","com.google.android.googlequicksearchbox:search",2487567838
-2798,2400,"TimerThread0","com.google.android.googlequicksearchbox:search",2487567838
-2799,2400,"UserFacing0","com.google.android.googlequicksearchbox:search",2487567838
-2834,2400,"queued-work-loo","com.google.android.googlequicksearchbox:search",2487567838
-2846,2400,"NonUserFacing1","com.google.android.googlequicksearchbox:search",2487567838
-2848,2400,"UserFacing1","com.google.android.googlequicksearchbox:search",2487567838
-2854,2400,"UserFacing2","com.google.android.googlequicksearchbox:search",2487567838
-2921,2400,"ConnectivityThr","com.google.android.googlequicksearchbox:search",2487567838
-2961,2400,"Binder:2400_4","com.google.android.googlequicksearchbox:search",2487567838
-3004,2400,"UserFacing3","com.google.android.googlequicksearchbox:search",2487567838
-3841,2400,"GoogleApiHandle","com.google.android.googlequicksearchbox:search",2487567838
-4039,2400,"NonUserFacing3","com.google.android.googlequicksearchbox:search",2487567838
-4040,2400,"NonUserFacing4","com.google.android.googlequicksearchbox:search",2487567838
-4041,2400,"NonUserFacing5","com.google.android.googlequicksearchbox:search",2487567838
-4075,2400,"CronetInit","com.google.android.googlequicksearchbox:search",2487567838
-4118,2400,"UserFacing5","com.google.android.googlequicksearchbox:search",2487567838
-4155,2400,"TaskSchedulerSe","com.google.android.googlequicksearchbox:search",2487567838
-4156,2400,"TaskSchedulerBa","com.google.android.googlequicksearchbox:search",2487567838
-4157,2400,"TaskSchedulerBa","com.google.android.googlequicksearchbox:search",2487567838
-4161,2400,"TaskSchedulerFo","com.google.android.googlequicksearchbox:search",2487567838
-4162,2400,"TaskSchedulerFo","com.google.android.googlequicksearchbox:search",2487567838
-4163,2400,"ChromiumNet","com.google.android.googlequicksearchbox:search",2487567838
-4164,2400,"DnsConfigServic","com.google.android.googlequicksearchbox:search",2487567838
-4165,2400,"TaskSchedulerFo","com.google.android.googlequicksearchbox:search",2487567838
-4167,2400,"Network File Th","com.google.android.googlequicksearchbox:search",2487567838
-4306,2400,"GAC_Executor[0]","com.google.android.googlequicksearchbox:search",2487567838
-4807,2400,"Binder:2400_6","com.google.android.googlequicksearchbox:search",2487567838
-4910,2400,"TaskSchedulerFo","com.google.android.googlequicksearchbox:search",2487567838
-5189,2400,"Binder:2400_7","com.google.android.googlequicksearchbox:search",2487567838
-5271,2400,"magnifier pixel","com.google.android.googlequicksearchbox:search",2487567838
-5281,2400,"RenderThread","com.google.android.googlequicksearchbox:search",2487567838
-5308,2400,"IcingConnection","com.google.android.googlequicksearchbox:search",2487567838
-5310,2400,"GcoreGoogleApiC","com.google.android.googlequicksearchbox:search",2487567838
-5311,2400,"GAC_Executor[1]","com.google.android.googlequicksearchbox:search",2487567838
-5491,2400,"TaskSchedulerFo","com.google.android.googlequicksearchbox:search",2487567838
-5539,2400,"TaskSchedulerBa","com.google.android.googlequicksearchbox:search",2487567838
-5540,2400,"TaskSchedulerFo","com.google.android.googlequicksearchbox:search",2487567838
-5377,5377,"ileged_process0","com.android.chrome:privileged_process0",2338957110
-5384,5377,"Jit thread pool","com.android.chrome:privileged_process0",2338957110
-5385,5377,"Signal Catcher","com.android.chrome:privileged_process0",2338957110
-5386,5377,"ADB-JDWP Connec","com.android.chrome:privileged_process0",2338957110
-5387,5377,"ReferenceQueueD","com.android.chrome:privileged_process0",2338957110
-5388,5377,"FinalizerDaemon","com.android.chrome:privileged_process0",2338957110
-5389,5377,"FinalizerWatchd","com.android.chrome:privileged_process0",2338957110
-5390,5377,"HeapTaskDaemon","com.android.chrome:privileged_process0",2338957110
-5391,5377,"Binder:5377_1","com.android.chrome:privileged_process0",2338957110
-5392,5377,"Binder:5377_2","com.android.chrome:privileged_process0",2338957110
-5393,5377,"Binder:5377_3","com.android.chrome:privileged_process0",2338957110
-5394,5377,"Profile Saver","com.android.chrome:privileged_process0",2338957110
-5395,5377,"CrGpuMain","com.android.chrome:privileged_process0",2338957110
-5397,5377,"Watchdog","com.android.chrome:privileged_process0",2338957110
-5409,5377,"TaskSchedulerSe","com.android.chrome:privileged_process0",2338957110
-5410,5377,"TaskSchedulerFo","com.android.chrome:privileged_process0",2338957110
-5411,5377,"TaskSchedulerFo","com.android.chrome:privileged_process0",2338957110
-5412,5377,"Chrome_ChildIOT","com.android.chrome:privileged_process0",2338957110
-5463,5377,"CrGpuMain","com.android.chrome:privileged_process0",2338957110
-5464,5377,"TaskSchedulerSi","com.android.chrome:privileged_process0",2338957110
-5476,5377,"AVDAAutoThread","com.android.chrome:privileged_process0",2338957110
-5477,5377,"AVDASWThread","com.android.chrome:privileged_process0",2338957110
-5478,5377,"MediaCodec_loop","com.android.chrome:privileged_process0",2338957110
-5479,5377,"JNISurfaceTextu","com.android.chrome:privileged_process0",2338957110
-5480,5377,"HwBinder:5377_1","com.android.chrome:privileged_process0",2338957110
-622,622,"surfaceflinger","/system/bin/surfaceflinger",2155181851
-651,622,"Binder:622_1","/system/bin/surfaceflinger",2155181851
-652,622,"Binder:622_2","/system/bin/surfaceflinger",2155181851
-654,622,"DispSync","/system/bin/surfaceflinger",2155181851
-655,622,"appEventThread","/system/bin/surfaceflinger",2155181851
-656,622,"sfEventThread","/system/bin/surfaceflinger",2155181851
-688,622,"HwBinder:622_1","/system/bin/surfaceflinger",2155181851
-692,622,"surfaceflinger","/system/bin/surfaceflinger",2155181851
-1221,622,"Binder:622_3","/system/bin/surfaceflinger",2155181851
-1438,622,"Binder:622_4","/system/bin/surfaceflinger",2155181851
-4032,622,"Binder:622_5","/system/bin/surfaceflinger",2155181851
-5497,622,"surfaceflinger","/system/bin/surfaceflinger",2155181851
-834,834,"wifi@1.0-servic","/vendor/bin/hw/android.hardware.wifi@1.0-service",2046147338
-2265,834,"wifi@1.0-servic","/vendor/bin/hw/android.hardware.wifi@1.0-service",2046147338
-2523,2523,"s.nexuslauncher","com.google.android.apps.nexuslauncher",1639085587
-2531,2523,"Jit thread pool","com.google.android.apps.nexuslauncher",1639085587
-2545,2523,"ReferenceQueueD","com.google.android.apps.nexuslauncher",1639085587
-2546,2523,"FinalizerDaemon","com.google.android.apps.nexuslauncher",1639085587
-2547,2523,"FinalizerWatchd","com.google.android.apps.nexuslauncher",1639085587
-2548,2523,"HeapTaskDaemon","com.google.android.apps.nexuslauncher",1639085587
-2551,2523,"Binder:2523_1","com.google.android.apps.nexuslauncher",1639085587
-2562,2523,"Binder:2523_2","com.google.android.apps.nexuslauncher",1639085587
-2582,2523,"Binder:2523_3","com.google.android.apps.nexuslauncher",1639085587
-2629,2523,"Profile Saver","com.google.android.apps.nexuslauncher",1639085587
-2639,2523,"launcher-loader","com.google.android.apps.nexuslauncher",1639085587
-2705,2523,"GoogleApiHandle","com.google.android.apps.nexuslauncher",1639085587
-2745,2523,"UiThreadHelper","com.google.android.apps.nexuslauncher",1639085587
-2838,2523,"queued-work-loo","com.google.android.apps.nexuslauncher",1639085587
-2886,2523,"TaskThumbnailIc","com.google.android.apps.nexuslauncher",1639085587
-2988,2523,"GrallocUploadTh","com.google.android.apps.nexuslauncher",1639085587
-3017,2523,"RenderThread","com.google.android.apps.nexuslauncher",1639085587
-3107,2523,"reflection-thre","com.google.android.apps.nexuslauncher",1639085587
-4571,2523,"Binder:2523_4","com.google.android.apps.nexuslauncher",1639085587
-5328,2523,"hwuiTask1","com.google.android.apps.nexuslauncher",1639085587
-5330,2523,"pool-3-thread-1","com.google.android.apps.nexuslauncher",1639085587
-5495,2523,"pool-3-thread-2","com.google.android.apps.nexuslauncher",1639085587
-5500,2523,"Binder:2523_5","com.google.android.apps.nexuslauncher",1639085587
-906,906,"traced_probes","/system/bin/traced_probes",1598981574
-916,906,"traced_probes","/system/bin/traced_probes",1598981574
-5244,906,"traced_probes0","/system/bin/traced_probes",1598981574
-5245,906,"traced_probes1","/system/bin/traced_probes",1598981574
-5246,906,"traced_probes2","/system/bin/traced_probes",1598981574
-5247,906,"traced_probes3","/system/bin/traced_probes",1598981574
-5248,906,"traced_probes4","/system/bin/traced_probes",1598981574
-5249,906,"traced_probes5","/system/bin/traced_probes",1598981574
-5250,906,"traced_probes6","/system/bin/traced_probes",1598981574
-5251,906,"traced_probes7","/system/bin/traced_probes",1598981574
-2139,2139,".gms.persistent","com.google.android.gms.persistent",1577881906
-2144,2139,"Jit thread pool","com.google.android.gms.persistent",1577881906
-2151,2139,"Binder:2139_1","com.google.android.gms.persistent",1577881906
-2154,2139,"Binder:2139_2","com.google.android.gms.persistent",1577881906
-2158,2139,"Binder:2139_3","com.google.android.gms.persistent",1577881906
-2159,2139,"Binder:2139_4","com.google.android.gms.persistent",1577881906
-2176,2139,"Profile Saver","com.google.android.gms.persistent",1577881906
-2227,2139,"GlobalDispatchi","com.google.android.gms.persistent",1577881906
-2236,2139,"peration loader","com.google.android.gms.persistent",1577881906
-2237,2139,"queued-work-loo","com.google.android.gms.persistent",1577881906
-2660,2139,"Binder:2139_5","com.google.android.gms.persistent",1577881906
-2666,2139,"Binder:2139_6","com.google.android.gms.persistent",1577881906
-2682,2139,"GoogleApiHandle","com.google.android.gms.persistent",1577881906
-2685,2139,"GlobalScheduler","com.google.android.gms.persistent",1577881906
-2740,2139,"netscheduler-qu","com.google.android.gms.persistent",1577881906
-2946,2139,"Binder:2139_7","com.google.android.gms.persistent",1577881906
-2955,2139,"lowpool[2]","com.google.android.gms.persistent",1577881906
-2999,2139,"Binder:2139_8","com.google.android.gms.persistent",1577881906
-3005,2139,"lowpool[4]","com.google.android.gms.persistent",1577881906
-3054,2139,"highpool[2]","com.google.android.gms.persistent",1577881906
-3063,2139,"Binder:2139_9","com.google.android.gms.persistent",1577881906
-3135,2139,"Binder:2139_A","com.google.android.gms.persistent",1577881906
-3200,2139,"Binder:2139_B","com.google.android.gms.persistent",1577881906
-3255,2139,"GeofencerStateM","com.google.android.gms.persistent",1577881906
-3279,2139,"FlpThread","com.google.android.gms.persistent",1577881906
-3517,2139,"GoogleLocationS","com.google.android.gms.persistent",1577881906
-3635,2139,"lowpool[8]","com.google.android.gms.persistent",1577881906
-3653,2139,"Places","com.google.android.gms.persistent",1577881906
-3745,2139,"Okio Watchdog","com.google.android.gms.persistent",1577881906
-4114,2139,"OkHttp Connecti","com.google.android.gms.persistent",1577881906
-4201,2139,"Binder:2139_C","com.google.android.gms.persistent",1577881906
-4203,2139,"Binder:2139_D","com.google.android.gms.persistent",1577881906
-4474,2139,"Binder:2139_E","com.google.android.gms.persistent",1577881906
-4772,2139,"raService] idle","com.google.android.gms.persistent",1577881906
-5300,2139,"raService] idle","com.google.android.gms.persistent",1577881906
-5453,2139,"Thread-26","com.google.android.gms.persistent",1577881906
-6019,2139,"Binder:2139_F","com.google.android.gms.persistent",1577881906
-2238,2238,"gle.android.gms","com.google.android.gms",1130387110
-2243,2238,"Jit thread pool","com.google.android.gms",1130387110
-2246,2238,"ReferenceQueueD","com.google.android.gms",1130387110
-2247,2238,"FinalizerDaemon","com.google.android.gms",1130387110
-2248,2238,"FinalizerWatchd","com.google.android.gms",1130387110
-2249,2238,"HeapTaskDaemon","com.google.android.gms",1130387110
-2254,2238,"Profile Saver","com.google.android.gms",1130387110
-2396,2238,"Binder:2238_4","com.google.android.gms",1130387110
-2640,2238,"GoogleApiHandle","com.google.android.gms",1130387110
-2755,2238,"Binder:2238_5","com.google.android.gms",1130387110
-2757,2238,"lowpool[2]","com.google.android.gms",1130387110
-2761,2238,"Binder:2238_6","com.google.android.gms",1130387110
-2772,2238,"lowpool[3]","com.google.android.gms",1130387110
-2827,2238,"GlobalScheduler","com.google.android.gms",1130387110
-2831,2238,"Binder:2238_8","com.google.android.gms",1130387110
-2895,2238,"GAC_Executor[0]","com.google.android.gms",1130387110
-3098,2238,"GAC_Executor[1]","com.google.android.gms",1130387110
-3749,2238,"Binder:2238_A","com.google.android.gms",1130387110
-3750,2238,"Binder:2238_B","com.google.android.gms",1130387110
-3905,2238,"highpool[2]","com.google.android.gms",1130387110
-3925,2238,"lowpool[7]","com.google.android.gms",1130387110
-4038,2238,"Okio Watchdog","com.google.android.gms",1130387110
-4257,2238,"Binder:2238_D","com.google.android.gms",1130387110
-4264,2238,"Binder:2238_E","com.google.android.gms",1130387110
-4475,2238,"Binder:2238_F","com.google.android.gms",1130387110
-5275,2238,"peration loader","com.google.android.gms",1130387110
-5276,2238,"raService] idle","com.google.android.gms",1130387110
-5277,2238,"raService] idle","com.google.android.gms",1130387110
-5278,2238,"raService] idle","com.google.android.gms",1130387110
-5279,2238,"raService] idle","com.google.android.gms",1130387110
-5282,2238,"raService] idle","com.google.android.gms",1130387110
-5458,2238,"IntentService[D","com.google.android.gms",1130387110
-5465,2238,"mdns-send","com.google.android.gms",1130387110
-5466,2238,"MdnsSocketClien","com.google.android.gms",1130387110
-5467,2238,"mdns-multicast-","com.google.android.gms",1130387110
-5468,2238,"lowpool[8]","com.google.android.gms",1130387110
-5910,2238,"peration loader","com.google.android.gms",1130387110
-5911,2238,"raService] idle","com.google.android.gms",1130387110
-6013,2238,"IntentService[M","com.google.android.gms",1130387110
-6014,2238,"MediaTracker bu","com.google.android.gms",1130387110
-943,943,"omx@1.0-service","media.codec",930299908
-1107,943,"HwBinder:943_1","media.codec",930299908
-1110,943,"HwBinder:943_2","media.codec",930299908
-2165,943,"HwBinder:943_3","media.codec",930299908
-2184,943,"HwBinder:943_4","media.codec",930299908
-2229,943,"HwBinder:943_5","media.codec",930299908
-5481,943,"VideoDecCallBac","media.codec",930299908
-5483,943,"VideoDecMsgThre","media.codec",930299908
-5484,943,"OMXCallbackDisp","media.codec",930299908
-5835,943,"VideoEncMsgThre","media.codec",930299908
-5836,943,"VideoEncCallBac","media.codec",930299908
-5837,943,"OMXCallbackDisp","media.codec",930299908
-5841,943,"HwBinder:943_6","media.codec",930299908
-5854,943,"VideoEncMsgThre","media.codec",930299908
-5855,943,"VideoEncMsgThre","media.codec",930299908
-5737,5737,"oid.apps.photos","com.google.android.apps.photos",748904789
-5746,5737,"Jit thread pool","com.google.android.apps.photos",748904789
-5747,5737,"Signal Catcher","com.google.android.apps.photos",748904789
-5748,5737,"ADB-JDWP Connec","com.google.android.apps.photos",748904789
-5749,5737,"ReferenceQueueD","com.google.android.apps.photos",748904789
-5750,5737,"FinalizerDaemon","com.google.android.apps.photos",748904789
-5751,5737,"FinalizerWatchd","com.google.android.apps.photos",748904789
-5753,5737,"HeapTaskDaemon","com.google.android.apps.photos",748904789
-5754,5737,"Binder:5737_1","com.google.android.apps.photos",748904789
-5755,5737,"Binder:5737_2","com.google.android.apps.photos",748904789
-5761,5737,"Binder:5737_3","com.google.android.apps.photos",748904789
-5771,5737,"Profile Saver","com.google.android.apps.photos",748904789
-5777,5737,"default_backgro","com.google.android.apps.photos",748904789
-5779,5737,"Primes-init-1","com.google.android.apps.photos",748904789
-5787,5737,"queued-work-loo","com.google.android.apps.photos",748904789
-5788,5737,"MediaPageFetche","com.google.android.apps.photos",748904789
-5832,5737,"glide-source-th","com.google.android.apps.photos",748904789
-5866,5737,"glide-source-th","com.google.android.apps.photos",748904789
-6012,5737,"glide-source-th","com.google.android.apps.photos",748904789
-6017,5737,"Binder:5737_4","com.google.android.apps.photos",748904789
-6021,5737,"GrallocUploadTh","com.google.android.apps.photos",748904789
-6022,5737,"glide-active-re","com.google.android.apps.photos",748904789
-6025,5737,"BackgroundTask ","com.google.android.apps.photos",748904789
-1657,1657,"reel.wallpapers","com.breel.wallpapers",638226980
-1663,1657,"Jit thread pool","com.breel.wallpapers",638226980
-1774,1657,"Binder:1657_3","com.breel.wallpapers",638226980
-1801,1657,"Profile Saver","com.breel.wallpapers",638226980
-2060,1657,"GLThread 35","com.breel.wallpapers",638226980
-2371,1657,"Binder:1657_4","com.breel.wallpapers",638226980
-624,624,"[NULL]","/vendor/bin/hw/android.hardware.graphics.composer@2.1-service",617056001
-639,624,"Binder:624_2","/vendor/bin/hw/android.hardware.graphics.composer@2.1-service",617056001
-664,624,"SDM_EventThread","/vendor/bin/hw/android.hardware.graphics.composer@2.1-service",617056001
-686,624,"HWC_UeventThrea","/vendor/bin/hw/android.hardware.graphics.composer@2.1-service",617056001
-687,624,"HwBinder:624_1","/vendor/bin/hw/android.hardware.graphics.composer@2.1-service",617056001
-741,624,"HwBinder:624_2","/vendor/bin/hw/android.hardware.graphics.composer@2.1-service",617056001
-804,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-955,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-959,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-975,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-976,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-977,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1015,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1016,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1040,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1041,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1046,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1047,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1050,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1051,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1069,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1070,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1075,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1076,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1082,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1083,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1085,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1368,804,"HwBinder:804_1","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1391,804,"HwBinder:804_1","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1392,804,"HwBinder:804_1","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-1393,804,"HwBinder:804_1","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-5694,804,"HwBinder:804_1","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-5695,804,"HwBinder:804_1","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
-5542,5542,"ssioncontroller","com.google.android.permissioncontroller",521893072
-5547,5542,"Jit thread pool","com.google.android.permissioncontroller",521893072
-5548,5542,"Signal Catcher","com.google.android.permissioncontroller",521893072
-5549,5542,"ADB-JDWP Connec","com.google.android.permissioncontroller",521893072
-5550,5542,"ReferenceQueueD","com.google.android.permissioncontroller",521893072
-5551,5542,"FinalizerDaemon","com.google.android.permissioncontroller",521893072
-5552,5542,"FinalizerWatchd","com.google.android.permissioncontroller",521893072
-5553,5542,"HeapTaskDaemon","com.google.android.permissioncontroller",521893072
-5554,5542,"Binder:5542_1","com.google.android.permissioncontroller",521893072
-5555,5542,"Binder:5542_2","com.google.android.permissioncontroller",521893072
-5556,5542,"Profile Saver","com.google.android.permissioncontroller",521893072
-5560,5542,"RenderThread","com.google.android.permissioncontroller",521893072
-5561,5542,"RenderThread","com.google.android.permissioncontroller",521893072
-5562,5542,"RenderThread","com.google.android.permissioncontroller",521893072
-5579,5542,"Binder:5542_3","com.google.android.permissioncontroller",521893072
-5605,5542,"queued-work-loo","com.google.android.permissioncontroller",521893072
-5283,5283,"d.process.acore","android.process.acore",388957949
-5288,5283,"Jit thread pool","android.process.acore",388957949
-5289,5283,"Signal Catcher","android.process.acore",388957949
-5290,5283,"ADB-JDWP Connec","android.process.acore",388957949
-5292,5283,"ReferenceQueueD","android.process.acore",388957949
-5293,5283,"FinalizerDaemon","android.process.acore",388957949
-5294,5283,"FinalizerWatchd","android.process.acore",388957949
-5295,5283,"HeapTaskDaemon","android.process.acore",388957949
-5297,5283,"Binder:5283_1","android.process.acore",388957949
-5298,5283,"Binder:5283_2","android.process.acore",388957949
-5299,5283,"Binder:5283_3","android.process.acore",388957949
-5301,5283,"Profile Saver","android.process.acore",388957949
-5302,5283,"Worker-1","android.process.acore",388957949
-5303,5283,"Worker-1","android.process.acore",388957949
-5304,5283,"Worker-1","android.process.acore",388957949
-5306,5283,"Worker-1","android.process.acore",388957949
-5307,5283,"Worker-1","android.process.acore",388957949
-5457,5283,"android.bg","android.process.acore",388957949
-626,626,"allocator@2.0-s","/vendor/bin/hw/android.hardware.graphics.allocator@2.0-service",337948219
-983,626,"HwBinder:626_1","/vendor/bin/hw/android.hardware.graphics.allocator@2.0-service",337948219
-990,626,"HwBinder:626_2","/vendor/bin/hw/android.hardware.graphics.allocator@2.0-service",337948219
-5270,626,"HwBinder:626_3","/vendor/bin/hw/android.hardware.graphics.allocator@2.0-service",337948219
-864,864,"audioserver","/system/bin/audioserver",335741587
-1174,864,"ApmOutput","/system/bin/audioserver",335741587
-1175,864,"Binder:864_1","/system/bin/audioserver",335741587
-1176,864,"Binder:864_2","/system/bin/audioserver",335741587
-1224,864,"FastMixer","/system/bin/audioserver",335741587
-1225,864,"AudioOut_D","/system/bin/audioserver",335741587
-1227,864,"AudioOut_15","/system/bin/audioserver",335741587
-1228,864,"AudioOut_1D","/system/bin/audioserver",335741587
-1230,864,"AudioOut_25","/system/bin/audioserver",335741587
-1231,864,"AudioOut_2D","/system/bin/audioserver",335741587
-1233,864,"AudioOut_35","/system/bin/audioserver",335741587
-1367,864,"soundTrigger cb","/system/bin/audioserver",335741587
-1481,864,"TimeCheckThread","/system/bin/audioserver",335741587
-1482,864,"Binder:864_3","/system/bin/audioserver",335741587
-5712,864,"Binder:864_4","/system/bin/audioserver",335741587
-5133,5133,"d.process.media","android.process.media",299474876
-5138,5133,"Jit thread pool","android.process.media",299474876
-5141,5133,"ReferenceQueueD","android.process.media",299474876
-5142,5133,"FinalizerDaemon","android.process.media",299474876
-5143,5133,"FinalizerWatchd","android.process.media",299474876
-5144,5133,"HeapTaskDaemon","android.process.media",299474876
-5145,5133,"Binder:5133_1","android.process.media",299474876
-5146,5133,"Binder:5133_2","android.process.media",299474876
-5147,5133,"Binder:5133_3","android.process.media",299474876
-5154,5133,"Okio Watchdog","android.process.media",299474876
-5192,5133,"Binder:5133_4","android.process.media",299474876
-5936,5133,"Binder:5133_5","android.process.media",299474876
-6018,5133,"Binder:5133_6","android.process.media",299474876
-920,920,"cameraserver","/system/bin/cameraserver",285767510
-1088,920,"HwBinder:920_1","/system/bin/cameraserver",285767510
-2539,920,"Binder:920_3","/system/bin/cameraserver",285767510
-5645,920,"C3Dev-0-Status","/system/bin/cameraserver",285767510
-5646,920,"C3Dev-0-ReqQueu","/system/bin/cameraserver",285767510
-5647,920,"CDU-0-FrameProc","/system/bin/cameraserver",285767510
-5416,5416,"oogle.vr.vrcore","com.google.vr.vrcore",270533097
-5421,5416,"Jit thread pool","com.google.vr.vrcore",270533097
-5422,5416,"Signal Catcher","com.google.vr.vrcore",270533097
-5423,5416,"ADB-JDWP Connec","com.google.vr.vrcore",270533097
-5425,5416,"ReferenceQueueD","com.google.vr.vrcore",270533097
-5426,5416,"FinalizerDaemon","com.google.vr.vrcore",270533097
-5427,5416,"FinalizerWatchd","com.google.vr.vrcore",270533097
-5428,5416,"HeapTaskDaemon","com.google.vr.vrcore",270533097
-5429,5416,"Binder:5416_1","com.google.vr.vrcore",270533097
-5430,5416,"Binder:5416_2","com.google.vr.vrcore",270533097
-5431,5416,"Binder:5416_3","com.google.vr.vrcore",270533097
-5432,5416,"Profile Saver","com.google.vr.vrcore",270533097
-5436,5416,"queued-work-loo","com.google.vr.vrcore",270533097
-5437,5416,"GAC_Executor[0]","com.google.vr.vrcore",270533097
-5438,5416,"Primes-init-1","com.google.vr.vrcore",270533097
-5440,5416,"AsyncTask #1","com.google.vr.vrcore",270533097
-5441,5416,"GAC_Executor[1]","com.google.vr.vrcore",270533097
-5442,5416,"SharedPreferenc","com.google.vr.vrcore",270533097
-2470,2470,"[NULL]","com.google.process.gservices",248908946
-2489,2470,"ReferenceQueueD","com.google.process.gservices",248908946
-2490,2470,"FinalizerDaemon","com.google.process.gservices",248908946
-2491,2470,"FinalizerWatchd","com.google.process.gservices",248908946
-2492,2470,"HeapTaskDaemon","com.google.process.gservices",248908946
-2493,2470,"Binder:2470_1","com.google.process.gservices",248908946
-2501,2470,"Binder:2470_2","com.google.process.gservices",248908946
-2512,2470,"Binder:2470_3","com.google.process.gservices",248908946
-2633,2470,"Binder:2470_4","com.google.process.gservices",248908946
-2667,2470,"Binder:2470_5","com.google.process.gservices",248908946
-2709,2470,"Binder:2470_6","com.google.process.gservices",248908946
-2750,2470,"Binder:2470_7","com.google.process.gservices",248908946
-2782,2470,"Binder:2470_8","com.google.process.gservices",248908946
-2896,2470,"Binder:2470_9","com.google.process.gservices",248908946
-3075,2470,"Binder:2470_A","com.google.process.gservices",248908946
-3708,2470,"Binder:2470_B","com.google.process.gservices",248908946
-3753,2470,"Binder:2470_C","com.google.process.gservices",248908946
-3878,2470,"Binder:2470_D","com.google.process.gservices",248908946
-4192,2470,"Binder:2470_E","com.google.process.gservices",248908946
-4270,2470,"Binder:2470_F","com.google.process.gservices",248908946
-4358,2470,"Binder:2470_10","com.google.process.gservices",248908946
-757,757,"audio@2.0-servi","/vendor/bin/hw/android.hardware.audio@2.0-service",247532931
-1168,757,"audio@2.0-servi","/vendor/bin/hw/android.hardware.audio@2.0-service",247532931
-1223,757,"HwBinder:757_2","/vendor/bin/hw/android.hardware.audio@2.0-service",247532931
-1483,757,"HwBinder:757_3","/vendor/bin/hw/android.hardware.audio@2.0-service",247532931
-5312,757,"audio@2.0-servi","/vendor/bin/hw/android.hardware.audio@2.0-service",247532931
-5485,757,"writer","/vendor/bin/hw/android.hardware.audio@2.0-service",247532931
-5840,757,"writer","/vendor/bin/hw/android.hardware.audio@2.0-service",247532931
-905,905,"traced","/system/bin/traced",227754138
-909,905,"traced","/system/bin/traced",227754138
-586,586,"[NULL]","/system/bin/logd",215959701
-591,586,"logd.daemon","/system/bin/logd",215959701
-595,586,"logd.writer","/system/bin/logd",215959701
-606,586,"logd.klogd","/system/bin/logd",215959701
-607,586,"logd.auditd","/system/bin/logd",215959701
-5563,5563,"ndroid.contacts","com.google.android.contacts",205871264
-5568,5563,"Jit thread pool","com.google.android.contacts",205871264
-5569,5563,"Signal Catcher","com.google.android.contacts",205871264
-5570,5563,"ADB-JDWP Connec","com.google.android.contacts",205871264
-5571,5563,"ReferenceQueueD","com.google.android.contacts",205871264
-5572,5563,"FinalizerDaemon","com.google.android.contacts",205871264
-5573,5563,"FinalizerWatchd","com.google.android.contacts",205871264
-5574,5563,"HeapTaskDaemon","com.google.android.contacts",205871264
-5575,5563,"Binder:5563_1","com.google.android.contacts",205871264
-5576,5563,"Binder:5563_2","com.google.android.contacts",205871264
-5577,5563,"Binder:5563_3","com.google.android.contacts",205871264
-5578,5563,"Profile Saver","com.google.android.contacts",205871264
-5581,5563,"Primes-init-1","com.google.android.contacts",205871264
-5582,5563,"AsyncTask #1","com.google.android.contacts",205871264
-5585,5563,"AsyncTask #2","com.google.android.contacts",205871264
-5588,5563,"measurement-1","com.google.android.contacts",205871264
-5589,5563,"GoogleApiHandle","com.google.android.contacts",205871264
-5590,5563,"AsyncTask #3","com.google.android.contacts",205871264
-5591,5563,"AsyncTask #4","com.google.android.contacts",205871264
-5592,5563,"queued-work-loo","com.google.android.contacts",205871264
-5656,5563,"Binder:5563_4","com.google.android.contacts",205871264
-2712,2712,"android.vending","com.android.vending",177335230
-2719,2712,"Jit thread pool","com.android.vending",177335230
-2737,2712,"Binder:2712_1","com.android.vending",177335230
-2739,2712,"Binder:2712_2","com.android.vending",177335230
-2744,2712,"Binder:2712_3","com.android.vending",177335230
-2771,2712,"Profile Saver","com.android.vending",177335230
-2796,2712,"Monitor Thread ","com.android.vending",177335230
-2815,2712,"BlockingExecuto","com.android.vending",177335230
-2945,2712,"queued-work-loo","com.android.vending",177335230
-3000,2712,"libraries-threa","com.android.vending",177335230
-3019,2712,"CronetInit","com.android.vending",177335230
-3040,2712,"TaskSchedulerFo","com.android.vending",177335230
-3041,2712,"TaskSchedulerFo","com.android.vending",177335230
-3042,2712,"ChromiumNet","com.android.vending",177335230
-3044,2712,"DnsConfigServic","com.android.vending",177335230
-3177,2712,"Db-scheduler","com.android.vending",177335230
-3394,2712,"ogging_store.db","com.android.vending",177335230
-3887,2712,"Binder:2712_4","com.android.vending",177335230
-4742,2712,"bgExecutor #3","com.android.vending",177335230
-5117,2712,"Binder:2712_5","com.android.vending",177335230
-5120,2712,".lowPriority #1","com.android.vending",177335230
-5124,2712,".lowPriority #2","com.android.vending",177335230
-5125,2712,"Okio Watchdog","com.android.vending",177335230
-5173,2712,"Binder:2712_6","com.android.vending",177335230
-5593,2712,"acquisitions.db","com.android.vending",177335230
-6020,2712,"Binder:2712_7","com.android.vending",177335230
-968,968,"[NULL]","/vendor/bin/hw/android.hardware.biometrics.fingerprint@2.1-service.fpc",154062201
-1165,968,"fingerprint@2.1","/vendor/bin/hw/android.hardware.biometrics.fingerprint@2.1-service.fpc",154062201
-935,935,"[NULL]","/system/bin/statsd",128205711
-1028,935,"statsd.writer","/system/bin/statsd",128205711
-924,924,"[NULL]","/system/bin/installd",125398920
-1354,924,"Binder:924_3","/system/bin/installd",125398920
-1371,924,"Binder:924_4","/system/bin/installd",125398920
-1381,924,"Binder:924_5","/system/bin/installd",125398920
-5659,5659,"e.process.gapps","com.google.process.gapps",116729960
-5664,5659,"Jit thread pool","com.google.process.gapps",116729960
-5665,5659,"Signal Catcher","com.google.process.gapps",116729960
-5666,5659,"ADB-JDWP Connec","com.google.process.gapps",116729960
-5667,5659,"ReferenceQueueD","com.google.process.gapps",116729960
-5668,5659,"FinalizerDaemon","com.google.process.gapps",116729960
-5669,5659,"FinalizerWatchd","com.google.process.gapps",116729960
-5670,5659,"HeapTaskDaemon","com.google.process.gapps",116729960
-5671,5659,"Binder:5659_1","com.google.process.gapps",116729960
-5672,5659,"Binder:5659_2","com.google.process.gapps",116729960
-5677,5659,"Binder:5659_3","com.google.process.gapps",116729960
-5678,5659,"Profile Saver","com.google.process.gapps",116729960
-5692,5659,"RefQueueWorker@","com.google.process.gapps",116729960
-5252,5252,"android.ramdump","com.android.ramdump",88012042
-5257,5252,"Jit thread pool","com.android.ramdump",88012042
-5258,5252,"Signal Catcher","com.android.ramdump",88012042
-5259,5252,"ADB-JDWP Connec","com.android.ramdump",88012042
-5260,5252,"ReferenceQueueD","com.android.ramdump",88012042
-5261,5252,"FinalizerDaemon","com.android.ramdump",88012042
-5262,5252,"FinalizerWatchd","com.android.ramdump",88012042
-5263,5252,"HeapTaskDaemon","com.android.ramdump",88012042
-5264,5252,"Binder:5252_1","com.android.ramdump",88012042
-5265,5252,"Binder:5252_2","com.android.ramdump",88012042
-5266,5252,"Binder:5252_3","com.android.ramdump",88012042
-5267,5252,"Profile Saver","com.android.ramdump",88012042
-5269,5252,"queued-work-loo","com.android.ramdump",88012042
-5400,5252,"android.bg","com.android.ramdump",88012042
-734,734,"main","zygote64",84352921
-5253,734,"ReferenceQueueD","zygote64",84352921
-5254,734,"FinalizerDaemon","zygote64",84352921
-5255,734,"FinalizerWatchd","zygote64",84352921
-5256,734,"HeapTaskDaemon","zygote64",84352921
-5284,734,"ReferenceQueueD","zygote64",84352921
-5285,734,"FinalizerDaemon","zygote64",84352921
-5286,734,"FinalizerWatchd","zygote64",84352921
-5287,734,"HeapTaskDaemon","zygote64",84352921
-5417,734,"ReferenceQueueD","zygote64",84352921
-5418,734,"FinalizerDaemon","zygote64",84352921
-5419,734,"FinalizerWatchd","zygote64",84352921
-5420,734,"HeapTaskDaemon","zygote64",84352921
-5507,734,"ReferenceQueueD","zygote64",84352921
-5508,734,"FinalizerDaemon","zygote64",84352921
-5509,734,"FinalizerWatchd","zygote64",84352921
-5510,734,"HeapTaskDaemon","zygote64",84352921
-5543,734,"ReferenceQueueD","zygote64",84352921
-5544,734,"FinalizerDaemon","zygote64",84352921
-5545,734,"FinalizerWatchd","zygote64",84352921
-5546,734,"HeapTaskDaemon","zygote64",84352921
-5564,734,"ReferenceQueueD","zygote64",84352921
-5565,734,"FinalizerDaemon","zygote64",84352921
-5566,734,"FinalizerWatchd","zygote64",84352921
-5567,734,"HeapTaskDaemon","zygote64",84352921
-5660,734,"ReferenceQueueD","zygote64",84352921
-5661,734,"FinalizerDaemon","zygote64",84352921
-5662,734,"FinalizerWatchd","zygote64",84352921
-5663,734,"HeapTaskDaemon","zygote64",84352921
-5738,734,"ReferenceQueueD","zygote64",84352921
-5739,734,"FinalizerDaemon","zygote64",84352921
-5740,734,"FinalizerWatchd","zygote64",84352921
-5741,734,"HeapTaskDaemon","zygote64",84352921
-587,587,"servicemanager","/system/bin/servicemanager",79206880
-3657,3657,"putmethod.latin","com.google.android.inputmethod.latin",77776147
-3662,3657,"Jit thread pool","com.google.android.inputmethod.latin",77776147
-3671,3657,"Binder:3657_1","com.google.android.inputmethod.latin",77776147
-3672,3657,"Binder:3657_2","com.google.android.inputmethod.latin",77776147
-3673,3657,"Binder:3657_3","com.google.android.inputmethod.latin",77776147
-3674,3657,"Profile Saver","com.google.android.inputmethod.latin",77776147
-3677,3657,"queued-work-loo","com.google.android.inputmethod.latin",77776147
-3688,3657,"MetricsManager","com.google.android.inputmethod.latin",77776147
-3701,3657,"NativeLogger-1","com.google.android.inputmethod.latin",77776147
-4238,3657,"OkHttp Http2Con","com.google.android.inputmethod.latin",77776147
-4239,3657,"Okio Watchdog","com.google.android.inputmethod.latin",77776147
-4287,3657,"OkHttp Dispatch","com.google.android.inputmethod.latin",77776147
-4338,3657,"DFacilitator-1","com.google.android.inputmethod.latin",77776147
-4340,3657,"DecoderWrapper","com.google.android.inputmethod.latin",77776147
-4808,3657,"Binder:3657_5","com.google.android.inputmethod.latin",77776147
-5274,3657,"AsyncTask #1","com.google.android.inputmethod.latin",77776147
-2024,2024,"id.ext.services","com.google.android.ext.services",70194314
-2031,2024,"Jit thread pool","com.google.android.ext.services",70194314
-2040,2024,"Binder:2024_1","com.google.android.ext.services",70194314
-2052,2024,"Profile Saver","com.google.android.ext.services",70194314
-2505,2024,"Binder:2024_3","com.google.android.ext.services",70194314
-930,930,"mediaextractor","media.extractor",65836741
-2195,930,"Binder:930_3","media.extractor",65836741
-588,588,"hwservicemanage","/system/bin/hwservicemanager",63243286
-866,866,"lmkd","/system/bin/lmkd",50165676
-859,859,"rmt_storage","/vendor/bin/rmt_storage",49808599
-1183,859,"rmt_storage","/vendor/bin/rmt_storage",49808599
-849,849,"msm_irqbalance","/vendor/bin/msm_irqbalance",46455318
-749,749,"suspend@1.0-ser","/system/bin/hw/android.system.suspend@1.0-service",43663325
-767,767,"light@2.0-servi","/vendor/bin/hw/android.hardware.light@2.0-service",39666625
-1815,1815,"m.android.phone","com.android.phone",37507869
-1822,1815,"Jit thread pool","com.android.phone",37507869
-1829,1815,"Binder:1815_1","com.android.phone",37507869
-1872,1815,"Profile Saver","com.android.phone",37507869
-2133,1815,"Binder:1815_8","com.android.phone",37507869
-2557,2557,"ps.pixelmigrate","com.google.android.apps.pixelmigrate",35978391
-2565,2557,"Jit thread pool","com.google.android.apps.pixelmigrate",35978391
-2578,2557,"Binder:2557_2","com.google.android.apps.pixelmigrate",35978391
-2585,2557,"Binder:2557_3","com.google.android.apps.pixelmigrate",35978391
-2600,2557,"Profile Saver","com.google.android.apps.pixelmigrate",35978391
-2758,2557,"queued-work-loo","com.google.android.apps.pixelmigrate",35978391
-2383,2383,"hbox:interactor","com.google.android.googlequicksearchbox:interactor",32259686
-2386,2383,"Jit thread pool","com.google.android.googlequicksearchbox:interactor",32259686
-2399,2383,"Binder:2383_3","com.google.android.googlequicksearchbox:interactor",32259686
-4318,2383,"queued-work-loo","com.google.android.googlequicksearchbox:interactor",32259686
-5273,2383,"GELServices0","com.google.android.googlequicksearchbox:interactor",32259686
-795,795,"power@1.2-servi","/vendor/bin/hw/android.hardware.power@1.2-service.wahoo-libperfmgr",29634741
-2330,795,"NodeLooperThrea","/vendor/bin/hw/android.hardware.power@1.2-service.wahoo-libperfmgr",29634741
-2331,795,"power@1.2-servi","/vendor/bin/hw/android.hardware.power@1.2-service.wahoo-libperfmgr",29634741
-933,933,"mediaserver","/system/bin/mediaserver",28837457
-1139,933,"Binder:933_1","/system/bin/mediaserver",28837457
-1930,933,"Binder:933_2","/system/bin/mediaserver",28837457
-1931,933,"Binder:933_3","/system/bin/mediaserver",28837457
-5445,933,"Binder:933_4","/system/bin/mediaserver",28837457
-5446,933,"Binder:933_5","/system/bin/mediaserver",28837457
-707,707,"[NULL]","/system/bin/netd",28341775
-713,707,"netd","/system/bin/netd",28341775
-714,707,"netd","/system/bin/netd",28341775
-715,707,"netd","/system/bin/netd",28341775
-718,707,"netd","/system/bin/netd",28341775
-721,707,"netd","/system/bin/netd",28341775
-723,707,"Binder:707_2","/system/bin/netd",28341775
-724,707,"Binder:707_3","/system/bin/netd",28341775
-5401,707,"netd","/system/bin/netd",28341775
-5424,707,"netd","/system/bin/netd",28341775
-2405,2405,"com.android.nfc","com.android.nfc",17234063
-2427,2405,"Binder:2405_2","com.android.nfc",17234063
-2703,2405,"AsyncTask #1","com.android.nfc",17234063
-2724,2405,"AsyncTask #1","com.android.nfc",17234063
-2736,2405,"HwBinder:2405_1","com.android.nfc",17234063
-2586,2586,"ogle.android.as","com.google.android.as",17085108
-2625,2586,"Binder:2586_2","com.google.android.as",17085108
-2630,2586,"Binder:2586_3","com.google.android.as",17085108
-855,855,"[NULL]","/vendor/bin/sensors.qcom",16853030
-874,855,"sensors.qcom","/vendor/bin/sensors.qcom",16853030
-875,855,"sensors.qcom","/vendor/bin/sensors.qcom",16853030
-884,855,"sensors.qcom","/vendor/bin/sensors.qcom",16853030
-735,735,"main","zygote",16213076
-5314,735,"ReferenceQueueD","zygote",16213076
-5315,735,"FinalizerDaemon","zygote",16213076
-5316,735,"FinalizerWatchd","zygote",16213076
-5317,735,"HeapTaskDaemon","zygote",16213076
-5378,735,"ReferenceQueueD","zygote",16213076
-5379,735,"FinalizerDaemon","zygote",16213076
-5381,735,"FinalizerWatchd","zygote",16213076
-5382,735,"HeapTaskDaemon","zygote",16213076
-4716,4716,"android.youtube","com.google.android.youtube",15832867
-4774,4716,"ConnectivityThr","com.google.android.youtube",15832867
-4813,4716,"CronetInit","com.google.android.youtube",15832867
-4827,4716,"TaskSchedulerSe","com.google.android.youtube",15832867
-4828,4716,"TaskSchedulerBa","com.google.android.youtube",15832867
-4829,4716,"TaskSchedulerBa","com.google.android.youtube",15832867
-4831,4716,"TaskSchedulerFo","com.google.android.youtube",15832867
-4832,4716,"TaskSchedulerFo","com.google.android.youtube",15832867
-4834,4716,"ChromiumNet","com.google.android.youtube",15832867
-4837,4716,"DnsConfigServic","com.google.android.youtube",15832867
-4843,4716,"TaskSchedulerFo","com.google.android.youtube",15832867
-4844,4716,"Network File Th","com.google.android.youtube",15832867
-4858,4716,"RxIoScheduler-1","com.google.android.youtube",15832867
-4992,4716,"TaskSchedulerFo","com.google.android.youtube",15832867
-5031,4716,"Binder:4716_4","com.google.android.youtube",15832867
-5884,4716,"TaskSchedulerBa","com.google.android.youtube",15832867
-5885,4716,"TaskSchedulerFo","com.google.android.youtube",15832867
-5886,4716,"TaskSchedulerFo","com.google.android.youtube",15832867
-748,748,"allocator@1.0-s","/system/bin/hw/android.hidl.allocator@1.0-service",15704215
-937,937,"wificond","/system/bin/wificond",15345262
-5071,5071,"[NULL]","com.android.vending:instant_app_installer",15183338
-5076,5071,"Jit thread pool","com.android.vending:instant_app_installer",15183338
-5098,5071,"RxSchedulerPurg","com.android.vending:instant_app_installer",15183338
-5118,5071,"Binder:5071_5","com.android.vending:instant_app_installer",15183338
-777,777,"memtrack@1.0-se","/vendor/bin/hw/android.hardware.memtrack@1.0-service",12793649
-781,781,"nfc@1.1-service","/vendor/bin/hw/android.hardware.nfc@1.1-service",11324160
-2762,781,"nfc@1.1-service","/vendor/bin/hw/android.hardware.nfc@1.1-service",11324160
-2763,781,"nfc@1.1-service","/vendor/bin/hw/android.hardware.nfc@1.1-service",11324160
-2765,781,"nfc@1.1-service","/vendor/bin/hw/android.hardware.nfc@1.1-service",11324160
-4572,4572,".android.videos","com.google.android.videos",10846095
-4588,4572,"Binder:4572_2","com.google.android.videos",10846095
-2104,2104,"[NULL]","com.google.android.euicc",10600157
-2113,2104,"ReferenceQueueD","com.google.android.euicc",10600157
-2114,2104,"FinalizerDaemon","com.google.android.euicc",10600157
-2115,2104,"FinalizerWatchd","com.google.android.euicc",10600157
-2116,2104,"HeapTaskDaemon","com.google.android.euicc",10600157
-2119,2104,"Binder:2104_2","com.google.android.euicc",10600157
-747,747,"[NULL]","/vendor/bin/thermal-engine",10386569
-768,747,"HwBinder:747_1","/vendor/bin/thermal-engine",10386569
-782,747,"thermal-engine","/vendor/bin/thermal-engine",10386569
-766,766,"health@2.0-serv","/vendor/bin/hw/android.hardware.health@2.0-service.wahoo",8993956
-2232,2232,"wpa_supplicant","/vendor/bin/hw/wpa_supplicant",8946564
-1767,1767,"[NULL]",".dataservices",8929067
-1789,1767,"Binder:1767_1",".dataservices",8929067
-1802,1767,"Binder:1767_3",".dataservices",8929067
-1868,1767,"ConnectivityThr",".dataservices",8929067
-1871,1767,"MainEventThread",".dataservices",8929067
-3215,1767,"Binder:1767_4",".dataservices",8929067
-1603,1603,"webview_zygote","webview_zygote",8038281
-5349,1603,"ReferenceQueueD","webview_zygote",8038281
-5350,1603,"FinalizerDaemon","webview_zygote",8038281
-5351,1603,"FinalizerWatchd","webview_zygote",8038281
-5352,1603,"HeapTaskDaemon","webview_zygote",8038281
-765,765,"gnss@1.0-servic","/vendor/bin/hw/android.hardware.gnss@1.0-service-qti",6572600
-1649,765,"Loc_hal","/vendor/bin/hw/android.hardware.gnss@1.0-service-qti",6572600
-1674,765,"Loc_hal","/vendor/bin/hw/android.hardware.gnss@1.0-service-qti",6572600
-1676,765,"Loc_hal","/vendor/bin/hw/android.hardware.gnss@1.0-service-qti",6572600
-1398,1398,"[NULL]","lowi-server",6218334
-1403,1398,"lowi-server","lowi-server",6218334
-1406,1398,"lowi-server","lowi-server",6218334
-2259,1398,"lowi-server","lowi-server",6218334
-2260,1398,"lowi-server","lowi-server",6218334
-918,918,"[NULL]","/vendor/bin/ipacm",5797711
-1029,918,"ipacm","/vendor/bin/ipacm",5797711
-1030,918,"netlink socket","/vendor/bin/ipacm",5797711
-944,944,"[NULL]","/vendor/bin/hw/rild",5642917
-1188,944,"rild","/vendor/bin/hw/rild",5642917
-1316,944,"rild","/vendor/bin/hw/rild",5642917
-1329,944,"rild","/vendor/bin/hw/rild",5642917
-5232,5232,"adbd","/system/bin/adbd",5559584
-1,1,"init","/system/bin/init",3984013
-921,921,"[NULL]","/system/bin/drmserver",3717808
-1066,921,"Binder:921_1","/system/bin/drmserver",3717808
-4431,4431,"oid.setupwizard","com.google.android.setupwizard",3362133
-5190,4431,"Binder:4431_5","com.google.android.setupwizard",3362133
-931,931,"[NULL]","media.metrics",3343382
-1061,931,"Binder:931_1","media.metrics",3343382
-5193,5193,"roid.apps.turbo","com.google.android.apps.turbo",2687762
-5204,5193,"HeapTaskDaemon","com.google.android.apps.turbo",2687762
-5205,5193,"Binder:5193_1","com.google.android.apps.turbo",2687762
-5207,5193,"Binder:5193_3","com.google.android.apps.turbo",2687762
-5229,5193,"Binder:5193_4","com.google.android.apps.turbo",2687762
-913,913,"cnd","/vendor/bin/cnd",2234739
-1006,913,"HwBinder:913_1","/vendor/bin/cnd",2234739
-711,711,"iptables-restor","/system/bin/iptables-restore",1913334
-806,806,"[NULL]","/vendor/bin/hw/android.hardware.usb@1.1-service.wahoo",1785000
-1490,806,"HwBinder:806_1","/vendor/bin/hw/android.hardware.usb@1.1-service.wahoo",1785000
-914,914,"[NULL]","/vendor/bin/netmgrd",1580886
-1071,914,"netmgrd","/vendor/bin/netmgrd",1580886
-1162,914,"netmgrd","/vendor/bin/netmgrd",1580886
-761,761,"contexthub@1.0-","/vendor/bin/hw/android.hardware.contexthub@1.0-service",1580624
-794,761,"contexthub@1.0-","/vendor/bin/hw/android.hardware.contexthub@1.0-service",1580624
-813,813,"vibrator@1.2-se","/vendor/bin/hw/android.hardware.vibrator@1.2-service.wahoo",1428749
-625,625,"[NULL]","/vendor/bin/hw/android.hardware.configstore@1.2-service",1419479
-1946,625,"HwBinder:625_2","/vendor/bin/hw/android.hardware.configstore@1.2-service",1419479
-3862,3862,"[NULL]","com.google.android.ims",1399063
-3875,3862,"Binder:3862_1","com.google.android.ims",1399063
-3917,3862,"ConnectivityThr","com.google.android.ims",1399063
-4140,3862,"WebRtcVolumeLev","com.google.android.ims",1399063
-4007,4007,"[NULL]","com.google.android.connectivitymonitor",1253492
-4088,4007,"ConnectivityThr","com.google.android.connectivitymonitor",1253492
-4535,4007,"Binder:4007_4","com.google.android.connectivitymonitor",1253492
-604,604,"[NULL]","/system/bin/vold",1173387
-613,604,"Binder:604_2","/system/bin/vold",1173387
-703,604,"Binder:604_4","/system/bin/vold",1173387
-962,962,"chre","/vendor/bin/chre",1097968
-1132,962,"chre","/vendor/bin/chre",1097968
-712,712,"ip6tables-resto","/system/bin/ip6tables-restore",1078437
-589,589,"vndservicemanag","/vendor/bin/vndservicemanager",918385
-3543,3543,"id.gms.unstable","com.google.android.gms.unstable",865106
-3558,3543,"Binder:3543_2","com.google.android.gms.unstable",865106
-927,927,"keystore","/system/bin/keystore",721094
-5035,5035,"[NULL]","com.android.keychain",457189
-5049,5035,"Binder:5035_3","com.android.keychain",457189
-1623,1623,"[NULL]","com.google.modemservice",426041
-1848,1623,"Binder:1623_3","com.google.modemservice",426041
-3526,3526,"[NULL]","com.google.android.apps.messaging",340676
-3890,3526,"Binder:3526_5","com.google.android.apps.messaging",340676
-564,564,"ueventd","/system/bin/ueventd",326822
-1852,1852,"[NULL]","com.qualcomm.qcrilmsgtunnel",316457
-1867,1852,"Binder:1852_1","com.qualcomm.qcrilmsgtunnel",316457
-4995,4995,"[NULL]","com.google.android.apps.messaging:rcs",305835
-5230,4995,"Binder:4995_4","com.google.android.apps.messaging:rcs",305835
-4912,4912,"[NULL]","com.qualcomm.telephony",303488
-4927,4912,"Binder:4912_1","com.qualcomm.telephony",303488
-1796,1796,"[NULL]","com.qualcomm.qti.telephonyservice",303385
-2377,1796,"Binder:1796_3","com.qualcomm.qti.telephonyservice",303385
-2534,2534,"[NULL]","com.google.intelligence.sense",280938
-2579,2534,"Binder:2534_2","com.google.intelligence.sense",280938
-2452,2452,"[NULL]","com.google.SSRestartDetector",272813
-2509,2452,"Binder:2452_3","com.google.SSRestartDetector",272813
-2421,2421,"[NULL]","com.android.se",270469
-2521,2421,"Binder:2421_3","com.android.se",270469
-2439,2439,"[NULL]","com.android.ims.rcsservice",265937
-3280,2439,"Binder:2439_4","com.android.ims.rcsservice",265937
-750,750,"healthd","/system/bin/healthd",250625
-4881,4881,"com.google.mds","com.google.mds",242969
-4896,4881,"Binder:4881_3","com.google.mds",242969
-949,949,"cnss-daemon","/vendor/bin/cnss-daemon",237396
-4964,4964,"le.planprovider","com.tmobile.planprovider",228385
-4976,4964,"Binder:4964_1","com.tmobile.planprovider",228385
-3934,3934,"android.carrier","com.google.android.carrier",228281
-3951,3934,"Binder:3934_2","com.google.android.carrier",228281
-4689,4689,"d.wfcactivation","com.google.android.wfcactivation",215626
-4740,4689,"Binder:4689_4","com.google.android.wfcactivation",215626
-1399,1399,"[NULL]","xtra-daemon",189271
-1409,1399,"pcid-lo","xtra-daemon",189271
-2963,2963,"e.process.gapps","com.google.process.gapps",179740
-5061,2963,"Binder:2963_8","com.google.process.gapps",179740
-4650,4650,"e.android.volta","com.google.android.volta",173594
-4666,4650,"Binder:4650_1","com.google.android.volta",173594
-0,"[NULL]","swapper/0","[NULL]","[NULL]"
-1610,"[NULL]","ReferenceQueueD","[NULL]","[NULL]"
-1611,"[NULL]","FinalizerDaemon","[NULL]","[NULL]"
-1612,"[NULL]","FinalizerWatchd","[NULL]","[NULL]"
-1613,"[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
-2088,"[NULL]","AsyncTask #4","[NULL]","[NULL]"
-2281,"[NULL]","InflaterThread ","[NULL]","[NULL]"
-2282,"[NULL]","InflaterThread ","[NULL]","[NULL]"
-2283,"[NULL]","InflaterThread ","[NULL]","[NULL]"
-2329,"[NULL]","InflaterThread ","[NULL]","[NULL]"
-2817,"[NULL]","BlockingExecuto","[NULL]","[NULL]"
-2968,"[NULL]","Jit thread pool","[NULL]","[NULL]"
-2969,"[NULL]","Signal Catcher","[NULL]","[NULL]"
-2970,"[NULL]","ADB-JDWP Connec","[NULL]","[NULL]"
-2971,"[NULL]","ReferenceQueueD","[NULL]","[NULL]"
-2972,"[NULL]","FinalizerDaemon","[NULL]","[NULL]"
-2973,"[NULL]","FinalizerWatchd","[NULL]","[NULL]"
-2974,"[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
-2982,"[NULL]","Binder:2963_1","[NULL]","[NULL]"
-2985,"[NULL]","Binder:2963_2","[NULL]","[NULL]"
-2986,"[NULL]","Binder:2963_3","[NULL]","[NULL]"
-2992,"[NULL]","Profile Saver","[NULL]","[NULL]"
-3073,"[NULL]","RefQueueWorker@","[NULL]","[NULL]"
-3095,"[NULL]","AsyncTask #1","[NULL]","[NULL]"
-3097,"[NULL]","AsyncTask #2","[NULL]","[NULL]"
-3140,"[NULL]","AsyncTask #3","[NULL]","[NULL]"
-3434,"[NULL]","measurement-1","[NULL]","[NULL]"
-3513,"[NULL]","Binder:2963_4","[NULL]","[NULL]"
-3607,"[NULL]","pool-4-thread-1","[NULL]","[NULL]"
-3941,"[NULL]","Jit thread pool","[NULL]","[NULL]"
-3942,"[NULL]","Signal Catcher","[NULL]","[NULL]"
-3944,"[NULL]","ADB-JDWP Connec","[NULL]","[NULL]"
-3945,"[NULL]","ReferenceQueueD","[NULL]","[NULL]"
-3946,"[NULL]","FinalizerDaemon","[NULL]","[NULL]"
-3947,"[NULL]","FinalizerWatchd","[NULL]","[NULL]"
-3948,"[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
-3949,"[NULL]","Binder:3934_1","[NULL]","[NULL]"
-3954,"[NULL]","Binder:3934_3","[NULL]","[NULL]"
-3960,"[NULL]","Profile Saver","[NULL]","[NULL]"
-4143,"[NULL]","unnerJobService","[NULL]","[NULL]"
-4200,"[NULL]","Binder:2963_5","[NULL]","[NULL]"
-4207,"[NULL]","oundTaskService","[NULL]","[NULL]"
-4230,"[NULL]","OkHttp Dispatch","[NULL]","[NULL]"
-4237,"[NULL]","OkHttp Http2Con","[NULL]","[NULL]"
-4285,"[NULL]","oundTaskService","[NULL]","[NULL]"
-4380,"[NULL]","Binder:2963_6","[NULL]","[NULL]"
-4476,"[NULL]","Binder:2963_7","[NULL]","[NULL]"
-4580,"[NULL]","Jit thread pool","[NULL]","[NULL]"
-4581,"[NULL]","Signal Catcher","[NULL]","[NULL]"
-4582,"[NULL]","ADB-JDWP Connec","[NULL]","[NULL]"
-4583,"[NULL]","ReferenceQueueD","[NULL]","[NULL]"
-4584,"[NULL]","FinalizerDaemon","[NULL]","[NULL]"
-4585,"[NULL]","FinalizerWatchd","[NULL]","[NULL]"
-4586,"[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
-4587,"[NULL]","Binder:4572_1","[NULL]","[NULL]"
-4589,"[NULL]","Binder:4572_3","[NULL]","[NULL]"
-4593,"[NULL]","Profile Saver","[NULL]","[NULL]"
-4600,"[NULL]","queued-work-loo","[NULL]","[NULL]"
-4608,"[NULL]","movies_logging","[NULL]","[NULL]"
-4610,"[NULL]","RefQueueWorker@","[NULL]","[NULL]"
-4611,"[NULL]","Thread-3","[NULL]","[NULL]"
-4612,"[NULL]","Thread-4","[NULL]","[NULL]"
-4613,"[NULL]","Thread-5","[NULL]","[NULL]"
-4614,"[NULL]","RefQueueWorker@","[NULL]","[NULL]"
-4615,"[NULL]","Thread-7","[NULL]","[NULL]"
-4616,"[NULL]","Thread-8","[NULL]","[NULL]"
-4617,"[NULL]","Thread-9","[NULL]","[NULL]"
-4618,"[NULL]","Thread-10","[NULL]","[NULL]"
-4619,"[NULL]","Thread-11","[NULL]","[NULL]"
-4620,"[NULL]","tentative-gc-ru","[NULL]","[NULL]"
-4625,"[NULL]","queued-work-loo","[NULL]","[NULL]"
-4635,"[NULL]","PlayEventLogger","[NULL]","[NULL]"
-4638,"[NULL]","network-1","[NULL]","[NULL]"
-4639,"[NULL]","network-2","[NULL]","[NULL]"
-4640,"[NULL]","network-3","[NULL]","[NULL]"
-4643,"[NULL]","network-4","[NULL]","[NULL]"
-4645,"[NULL]","local-1","[NULL]","[NULL]"
-4653,"[NULL]","local-2","[NULL]","[NULL]"
-4657,"[NULL]","ConnectivityThr","[NULL]","[NULL]"
-4659,"[NULL]","Jit thread pool","[NULL]","[NULL]"
-4660,"[NULL]","Signal Catcher","[NULL]","[NULL]"
-4661,"[NULL]","ADB-JDWP Connec","[NULL]","[NULL]"
-4662,"[NULL]","ReferenceQueueD","[NULL]","[NULL]"
-4663,"[NULL]","FinalizerDaemon","[NULL]","[NULL]"
-4664,"[NULL]","FinalizerWatchd","[NULL]","[NULL]"
-4665,"[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
-4667,"[NULL]","pool-5-thread-1","[NULL]","[NULL]"
-4668,"[NULL]","Binder:4650_2","[NULL]","[NULL]"
-4669,"[NULL]","sync-1","[NULL]","[NULL]"
-4672,"[NULL]","Profile Saver","[NULL]","[NULL]"
-4676,"[NULL]","GoogleApiHandle","[NULL]","[NULL]"
-4683,"[NULL]","GAC_Executor[0]","[NULL]","[NULL]"
-4684,"[NULL]","Binder:4650_3","[NULL]","[NULL]"
-4686,"[NULL]","queued-work-loo","[NULL]","[NULL]"
-4694,"[NULL]","Jit thread pool","[NULL]","[NULL]"
-4695,"[NULL]","Signal Catcher","[NULL]","[NULL]"
-4696,"[NULL]","ADB-JDWP Connec","[NULL]","[NULL]"
-4697,"[NULL]","ReferenceQueueD","[NULL]","[NULL]"
-4698,"[NULL]","FinalizerDaemon","[NULL]","[NULL]"
-4699,"[NULL]","FinalizerWatchd","[NULL]","[NULL]"
-4700,"[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
-4701,"[NULL]","GAC_Executor[1]","[NULL]","[NULL]"
-4702,"[NULL]","Binder:4689_1","[NULL]","[NULL]"
-4703,"[NULL]","Binder:4689_2","[NULL]","[NULL]"
-4709,"[NULL]","Profile Saver","[NULL]","[NULL]"
-4713,"[NULL]","Binder:4689_3","[NULL]","[NULL]"
-4730,"[NULL]","queued-work-loo","[NULL]","[NULL]"
-4872,"[NULL]","pool-17-thread-","[NULL]","[NULL]"
-4873,"[NULL]","pool-17-thread-","[NULL]","[NULL]"
-4874,"[NULL]","pool-17-thread-","[NULL]","[NULL]"
-4876,"[NULL]","pool-17-thread-","[NULL]","[NULL]"
-4887,"[NULL]","Jit thread pool","[NULL]","[NULL]"
-4888,"[NULL]","Signal Catcher","[NULL]","[NULL]"
-4889,"[NULL]","ADB-JDWP Connec","[NULL]","[NULL]"
-4890,"[NULL]","ReferenceQueueD","[NULL]","[NULL]"
-4891,"[NULL]","FinalizerDaemon","[NULL]","[NULL]"
-4892,"[NULL]","FinalizerWatchd","[NULL]","[NULL]"
-4893,"[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
-4894,"[NULL]","Binder:4881_1","[NULL]","[NULL]"
-4895,"[NULL]","Binder:4881_2","[NULL]","[NULL]"
-4900,"[NULL]","Profile Saver","[NULL]","[NULL]"
-4901,"[NULL]","pool-17-thread-","[NULL]","[NULL]"
-4902,"[NULL]","pool-17-thread-","[NULL]","[NULL]"
-4903,"[NULL]","pool-17-thread-","[NULL]","[NULL]"
-4904,"[NULL]","pool-17-thread-","[NULL]","[NULL]"
-4905,"[NULL]","pool-17-thread-","[NULL]","[NULL]"
-4906,"[NULL]","pool-17-thread-","[NULL]","[NULL]"
-4969,"[NULL]","Jit thread pool","[NULL]","[NULL]"
-4970,"[NULL]","Signal Catcher","[NULL]","[NULL]"
-4971,"[NULL]","ADB-JDWP Connec","[NULL]","[NULL]"
-4972,"[NULL]","ReferenceQueueD","[NULL]","[NULL]"
-4973,"[NULL]","FinalizerDaemon","[NULL]","[NULL]"
-4974,"[NULL]","FinalizerWatchd","[NULL]","[NULL]"
-4975,"[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
-4977,"[NULL]","Binder:4964_2","[NULL]","[NULL]"
-4978,"[NULL]","Binder:4964_3","[NULL]","[NULL]"
-4980,"[NULL]","Profile Saver","[NULL]","[NULL]"
-4985,"[NULL]","dScanJobService","[NULL]","[NULL]"
-5064,"[NULL]","AsyncTask #5","[NULL]","[NULL]"
-5072,"[NULL]","ReferenceQueueD","[NULL]","[NULL]"
-5073,"[NULL]","FinalizerDaemon","[NULL]","[NULL]"
-5074,"[NULL]","FinalizerWatchd","[NULL]","[NULL]"
-5075,"[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
-5097,"[NULL]","AsyncTask #5","[NULL]","[NULL]"
-5103,"[NULL]","AsyncTask #1","[NULL]","[NULL]"
-5108,"[NULL]","AsyncTask #2","[NULL]","[NULL]"
-5115,"[NULL]","TaskSchedulerFo","[NULL]","[NULL]"
-5119,"[NULL]",".lowPriority #0","[NULL]","[NULL]"
-5126,"[NULL]",".lowPriority #3","[NULL]","[NULL]"
-5129,"[NULL]","AsyncTask #3","[NULL]","[NULL]"
-5131,"[NULL]","AsyncTask #4","[NULL]","[NULL]"
-5157,"[NULL]","TaskSchedulerBa","[NULL]","[NULL]"
-5158,"[NULL]","TaskSchedulerFo","[NULL]","[NULL]"
-5174,"[NULL]","TaskSchedulerBa","[NULL]","[NULL]"
-5175,"[NULL]","TaskSchedulerFo","[NULL]","[NULL]"
-5176,"[NULL]","TaskSchedulerFo","[NULL]","[NULL]"
-5194,"[NULL]","ReferenceQueueD","[NULL]","[NULL]"
-5195,"[NULL]","FinalizerDaemon","[NULL]","[NULL]"
-5196,"[NULL]","FinalizerWatchd","[NULL]","[NULL]"
-5197,"[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
-5218,"[NULL]","Measurement Wor","[NULL]","[NULL]"
-5228,"[NULL]","Measurement Wor","[NULL]","[NULL]"
-5238,"[NULL]","pool-6-thread-1","[NULL]","[NULL]"
-5239,"[NULL]","pool-7-thread-1","[NULL]","[NULL]"
-5243,"[NULL]","atrace","[NULL]","[NULL]"
-5268,"[NULL]","Thread-2","[NULL]","[NULL]"
-5272,"[NULL]","applyRouting","[NULL]","[NULL]"
-5280,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5291,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5296,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5305,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5309,"[NULL]","gcm-task#1","[NULL]","[NULL]"
-5329,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5331,"[NULL]","EGL Init","[NULL]","[NULL]"
-5337,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5338,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5340,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5341,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5383,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5398,"[NULL]","gcm-task#1","[NULL]","[NULL]"
-5407,"[NULL]","IntentService[D","[NULL]","[NULL]"
-5433,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5434,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5435,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5439,"[NULL]","Thread-25","[NULL]","[NULL]"
-5454,"[NULL]","netd","[NULL]","[NULL]"
-5456,"[NULL]","netd","[NULL]","[NULL]"
-5459,"[NULL]","sensors.qcom","[NULL]","[NULL]"
-5460,"[NULL]","netd","[NULL]","[NULL]"
-5469,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5470,"[NULL]","netd","[NULL]","[NULL]"
-5472,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5474,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5494,"[NULL]","netd","[NULL]","[NULL]"
-5501,"[NULL]","netd","[NULL]","[NULL]"
-5504,"[NULL]","netd","[NULL]","[NULL]"
-5505,"[NULL]","netd","[NULL]","[NULL]"
-5521,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5523,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5535,"[NULL]","EGL Init","[NULL]","[NULL]"
-5558,"[NULL]","EGL Init","[NULL]","[NULL]"
-5580,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5583,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5584,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5586,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5587,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5594,"[NULL]","sensors.qcom","[NULL]","[NULL]"
-5602,"[NULL]",".vorbis.decoder","[NULL]","[NULL]"
-5603,"[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
-5612,"[NULL]","CAM_startsensor","[NULL]","[NULL]"
-5613,"[NULL]","CAM_startiface","[NULL]","[NULL]"
-5615,"[NULL]","CAM_startisp","[NULL]","[NULL]"
-5616,"[NULL]","CAM_startstats","[NULL]","[NULL]"
-5618,"[NULL]","CAM_startpproc","[NULL]","[NULL]"
-5619,"[NULL]","CAM_startimglib","[NULL]","[NULL]"
-5642,"[NULL]",".vorbis.decoder","[NULL]","[NULL]"
-5643,"[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
-5652,"[NULL]",".vorbis.decoder","[NULL]","[NULL]"
-5653,"[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
-5683,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5685,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5687,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5688,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5689,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5690,"[NULL]","cam_data_proc","[NULL]","[NULL]"
-5691,"[NULL]","cam_data_proc","[NULL]","[NULL]"
-5693,"[NULL]","CAM_jpeg_jobmgr","[NULL]","[NULL]"
-5697,"[NULL]","OMX_ImgEnc","[NULL]","[NULL]"
-5698,"[NULL]","cam_data_proc","[NULL]","[NULL]"
-5699,"[NULL]","cam_data_proc","[NULL]","[NULL]"
-5700,"[NULL]","cam_data_proc","[NULL]","[NULL]"
-5714,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5715,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5716,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5717,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5718,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5735,"[NULL]",".vorbis.decoder","[NULL]","[NULL]"
-5736,"[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
-5763,"[NULL]",".vorbis.decoder","[NULL]","[NULL]"
-5764,"[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
-5773,"[NULL]",".vorbis.decoder","[NULL]","[NULL]"
-5774,"[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
-5782,"[NULL]",".vorbis.decoder","[NULL]","[NULL]"
-5783,"[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
-5784,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5785,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5786,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5789,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5790,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5791,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5792,"[NULL]","applyRouting","[NULL]","[NULL]"
-5802,"[NULL]",".vorbis.decoder","[NULL]","[NULL]"
-5803,"[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
-5806,"[NULL]",".vorbis.decoder","[NULL]","[NULL]"
-5807,"[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
-5809,"[NULL]",".vorbis.decoder","[NULL]","[NULL]"
-5810,"[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
-5812,"[NULL]",".vorbis.decoder","[NULL]","[NULL]"
-5813,"[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
-5815,"[NULL]",".vorbis.decoder","[NULL]","[NULL]"
-5816,"[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
-5818,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5819,"[NULL]",".vorbis.decoder","[NULL]","[NULL]"
-5820,"[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
-5821,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5822,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5823,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5828,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5830,"[NULL]","HwBinder:943_4","[NULL]","[NULL]"
-5831,"[NULL]","HwBinder:943_4","[NULL]","[NULL]"
-5833,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5838,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5842,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5843,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5844,"[NULL]","gcm-task#1","[NULL]","[NULL]"
-5846,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5856,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5857,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5858,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5859,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5860,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5861,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5863,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5864,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5867,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5868,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5871,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5874,"[NULL]","gcm-task#1","[NULL]","[NULL]"
-5880,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5881,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5882,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5883,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5887,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5888,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5889,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5890,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5891,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5892,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5893,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5894,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5895,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5896,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5897,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5898,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5899,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5900,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5901,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5902,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5903,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5904,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5905,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5906,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5907,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5908,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5909,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5912,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5913,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-5914,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5915,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5916,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5917,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5918,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5919,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5920,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5921,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5922,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5924,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5925,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5926,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5927,"[NULL]","applyRouting","[NULL]","[NULL]"
-5928,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5929,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5930,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5931,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5933,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5934,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5937,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5939,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5942,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5950,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5951,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5952,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5953,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5954,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5955,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5956,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5957,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5958,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5959,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5960,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5961,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5962,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5963,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5964,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5965,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5966,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5967,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5968,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5969,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5970,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5971,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5972,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5973,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5974,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5975,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5976,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5977,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5978,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5979,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5980,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5981,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5982,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5983,"[NULL]","driver_slow_ae:","[NULL]","[NULL]"
-5984,"[NULL]","CAM_METADATA","[NULL]","[NULL]"
-5985,"[NULL]","CAM_PREVIEW","[NULL]","[NULL]"
-5986,"[NULL]","CAM_SNAPSHOT","[NULL]","[NULL]"
-5987,"[NULL]","CAM_CALLBACK","[NULL]","[NULL]"
-5988,"[NULL]","CAM_CALLBACK","[NULL]","[NULL]"
-5989,"[NULL]","CAM_RAW","[NULL]","[NULL]"
-5990,"[NULL]","CAM_ANALYSISCAM","[NULL]","[NULL]"
-5991,"[NULL]","CAM_StrmAppDat","[NULL]","[NULL]"
-5992,"[NULL]","CAM_StrmAppDat","[NULL]","[NULL]"
-5993,"[NULL]","CAM_iface_poll","[NULL]","[NULL]"
-5994,"[NULL]","CAM_iface_hw","[NULL]","[NULL]"
-5995,"[NULL]","irq/164-arm-smm","[NULL]","[NULL]"
-5996,"[NULL]","CAM_StrmAppDat","[NULL]","[NULL]"
-5997,"[NULL]","CAM_StrmAppDat","[NULL]","[NULL]"
-5998,"[NULL]","CAM_StrmAppDat","[NULL]","[NULL]"
-5999,"[NULL]","CAM_StrmAppDat","[NULL]","[NULL]"
-6000,"[NULL]","CAM_StrmAppDat","[NULL]","[NULL]"
-6001,"[NULL]","irq/165-arm-smm","[NULL]","[NULL]"
-6002,"[NULL]","CAM_sof_timer","[NULL]","[NULL]"
-6003,"[NULL]","HwBinder:759_2","[NULL]","[NULL]"
-6004,"[NULL]","CAM_stopsensor","[NULL]","[NULL]"
-6005,"[NULL]","CAM_stopiface","[NULL]","[NULL]"
-6006,"[NULL]","CAM_stopisp","[NULL]","[NULL]"
-6007,"[NULL]","CAM_stopstats","[NULL]","[NULL]"
-6008,"[NULL]","CAM_stoppproc","[NULL]","[NULL]"
-6009,"[NULL]","CAM_stopimglib","[NULL]","[NULL]"
-6010,"[NULL]","ProPrgsFin","[NULL]","[NULL]"
-6015,"[NULL]","gcm-task#1","[NULL]","[NULL]"
-6016,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-6023,"[NULL]","SharedPreferenc","[NULL]","[NULL]"
-6024,"[NULL]","sensors.qcom","[NULL]","[NULL]"
-950,950,"[NULL]","[NULL]","[NULL]"
+"utid","tid","upid","pid","threadName","processName","totalDur"
+950,5506,31,5506,"id.GoogleCamera","com.google.android.GoogleCamera",15154766434
+954,5511,31,5506,"Jit thread pool","com.google.android.GoogleCamera",15154766434
+955,5512,31,5506,"Signal Catcher","com.google.android.GoogleCamera",15154766434
+957,5517,31,5506,"HeapTaskDaemon","com.google.android.GoogleCamera",15154766434
+958,5516,31,5506,"FinalizerWatchd","com.google.android.GoogleCamera",15154766434
+959,5515,31,5506,"FinalizerDaemon","com.google.android.GoogleCamera",15154766434
+960,5514,31,5506,"ReferenceQueueD","com.google.android.GoogleCamera",15154766434
+961,5513,31,5506,"ADB-JDWP Connec","com.google.android.GoogleCamera",15154766434
+962,5518,31,5506,"Binder:5506_1","com.google.android.GoogleCamera",15154766434
+963,5519,31,5506,"Binder:5506_2","com.google.android.GoogleCamera",15154766434
+973,5520,31,5506,"Profile Saver","com.google.android.GoogleCamera",15154766434
+975,5522,31,5506,"GoogleApiHandle","com.google.android.GoogleCamera",15154766434
+977,5524,31,5506,"queued-work-loo","com.google.android.GoogleCamera",15154766434
+978,5525,31,5506,"Executor-1","com.google.android.GoogleCamera",15154766434
+979,5526,31,5506,"Executor-2","com.google.android.GoogleCamera",15154766434
+980,5527,31,5506,"Executor-3","com.google.android.GoogleCamera",15154766434
+981,5528,31,5506,"Executor-4","com.google.android.GoogleCamera",15154766434
+983,5529,31,5506,"IOExecutor-1","com.google.android.GoogleCamera",15154766434
+984,5530,31,5506,"IndicatorUpdate","com.google.android.GoogleCamera",15154766434
+987,5531,31,5506,"CamcorderCamera","com.google.android.GoogleCamera",15154766434
+988,5532,31,5506,"Thread-11","com.google.android.GoogleCamera",15154766434
+989,5533,31,5506,"Thread-12","com.google.android.GoogleCamera",15154766434
+990,5534,31,5506,"Thread-92","com.google.android.GoogleCamera",15154766434
+993,5536,31,5506,"Executor-5","com.google.android.GoogleCamera",15154766434
+994,5537,31,5506,"Executor-6","com.google.android.GoogleCamera",15154766434
+995,5538,31,5506,"RenderThread","com.google.android.GoogleCamera",15154766434
+998,5541,31,5506,"Executor-7","com.google.android.GoogleCamera",15154766434
+1014,5557,31,5506,"RenderThread","com.google.android.GoogleCamera",15154766434
+1017,5559,31,5506,"RenderThread","com.google.android.GoogleCamera",15154766434
+1085,5595,31,5506,"Executor-8","com.google.android.GoogleCamera",15154766434
+1086,5596,31,5506,"Camera-Hndlr","com.google.android.GoogleCamera",15154766434
+1087,5597,31,5506,"SoundPool","com.google.android.GoogleCamera",15154766434
+1088,5598,31,5506,"SoundPoolThread","com.google.android.GoogleCamera",15154766434
+1090,5599,31,5506,"UsageStatEx","com.google.android.GoogleCamera",15154766434
+1092,5600,31,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
+1093,5601,31,5506,"HwBinder:5506_1","com.google.android.GoogleCamera",15154766434
+1096,5604,31,5506,"Camera-Ex","com.google.android.GoogleCamera",15154766434
+1136,5626,31,5506,"Camera Handler ","com.google.android.GoogleCamera",15154766434
+1143,5632,31,5506,"Camera Job Disp","com.google.android.GoogleCamera",15154766434
+1147,5634,31,5506,"Binder:5506_3","com.google.android.GoogleCamera",15154766434
+1154,5641,31,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
+1164,5648,31,5506,"camera.wearable","com.google.android.GoogleCamera",15154766434
+1165,5649,31,5506,"CamcorderCamera","com.google.android.GoogleCamera",15154766434
+1166,5650,31,5506,"Binder:5506_4","com.google.android.GoogleCamera",15154766434
+1167,5651,31,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
+1170,5654,31,5506,"IR-RAW10w4032","com.google.android.GoogleCamera",15154766434
+1172,5655,31,5506,"Binder:5506_5","com.google.android.GoogleCamera",15154766434
+1180,5657,31,5506,"MicrovideoFrame","com.google.android.GoogleCamera",15154766434
+1181,5658,31,5506,"AsyncTask #1","com.google.android.GoogleCamera",15154766434
+1202,5673,31,5506,"IR-YUV_420_888w","com.google.android.GoogleCamera",15154766434
+1203,5674,31,5506,"IR-JPEGw4032","com.google.android.GoogleCamera",15154766434
+1204,5675,31,5506,"reproc-write","com.google.android.GoogleCamera",15154766434
+1205,5676,31,5506,"reproc-read","com.google.android.GoogleCamera",15154766434
+1208,5680,31,5506,"CameraEx-2","com.google.android.GoogleCamera",15154766434
+1209,5679,31,5506,"CameraEx-1","com.google.android.GoogleCamera",15154766434
+1210,5681,31,5506,"MicrovideoQShar","com.google.android.GoogleCamera",15154766434
+1211,5682,31,5506,"n.StateCallback","com.google.android.GoogleCamera",15154766434
+1213,5684,31,5506,"mv-vid-encoder","com.google.android.GoogleCamera",15154766434
+1215,5686,31,5506,"SharedPreferenc","com.google.android.GoogleCamera",15154766434
+1225,5696,31,5506,"AsyncTask #2","com.google.android.GoogleCamera",15154766434
+1230,5701,31,5506,"GcaMetadataHand","com.google.android.GoogleCamera",15154766434
+1231,5702,31,5506,"r.ImageListener","com.google.android.GoogleCamera",15154766434
+1232,5703,31,5506,"Binder:5506_6","com.google.android.GoogleCamera",15154766434
+1234,5706,31,5506,"OnDemandLoader","com.google.android.GoogleCamera",15154766434
+1243,5713,31,5506,"NotificationDot","com.google.android.GoogleCamera",15154766434
+1253,5722,31,5506,"GAC_Executor[0]","com.google.android.GoogleCamera",15154766434
+1260,5729,31,5506,"Timer-0","com.google.android.GoogleCamera",15154766434
+1264,5733,31,5506,"Timer-1","com.google.android.GoogleCamera",15154766434
+1265,5732,31,5506,"GAC_Executor[1]","com.google.android.GoogleCamera",15154766434
+1267,5734,31,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
+1272,5743,31,5506,"AsyncTask #3","com.google.android.GoogleCamera",15154766434
+1303,5760,31,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
+1312,5769,31,5506,"hwuiTask1","com.google.android.GoogleCamera",15154766434
+1316,5772,31,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
+1317,5775,31,5506,"Timer-2","com.google.android.GoogleCamera",15154766434
+1327,5781,31,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
+1340,5793,31,5506,"mv-ctrl-exec","com.google.android.GoogleCamera",15154766434
+1341,5794,31,5506,"ois-exec","com.google.android.GoogleCamera",15154766434
+1342,5795,31,5506,"mv-meta-exec","com.google.android.GoogleCamera",15154766434
+1343,5796,31,5506,"mv-gyro-exec-0","com.google.android.GoogleCamera",15154766434
+1344,5797,31,5506,"DelHDR+Ind","com.google.android.GoogleCamera",15154766434
+1349,5801,31,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
+1356,5804,31,5506,"FilterHDR+Ind","com.google.android.GoogleCamera",15154766434
+1357,5805,31,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
+1360,5808,31,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
+1363,5811,31,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
+1368,5814,31,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
+1371,5817,31,5506,"NDK MediaCodec_","com.google.android.GoogleCamera",15154766434
+1379,5824,31,5506,"CameraProcessin","com.google.android.GoogleCamera",15154766434
+1381,5825,31,5506,"ProcServ","com.google.android.GoogleCamera",15154766434
+1382,5826,31,5506,"MediaCodec_loop","com.google.android.GoogleCamera",15154766434
+1383,5827,31,5506,"CodecLooper","com.google.android.GoogleCamera",15154766434
+1386,5829,31,5506,"Binder:5506_7","com.google.android.GoogleCamera",15154766434
+1392,5834,31,5506,"IOExecutor-2","com.google.android.GoogleCamera",15154766434
+1398,5839,31,5506,"AudioTrack","com.google.android.GoogleCamera",15154766434
+1409,5845,31,5506,"Thread-38","com.google.android.GoogleCamera",15154766434
+1410,5847,31,5506,"Capture tasks: ","com.google.android.GoogleCamera",15154766434
+1411,5848,31,5506,"Capture tasks: ","com.google.android.GoogleCamera",15154766434
+1412,5849,31,5506,"Capture tasks: ","com.google.android.GoogleCamera",15154766434
+1413,5850,31,5506,"Capture tasks: ","com.google.android.GoogleCamera",15154766434
+1414,5851,31,5506,"Capture tasks: ","com.google.android.GoogleCamera",15154766434
+1415,5852,31,5506,"Capture tasks: ","com.google.android.GoogleCamera",15154766434
+1416,5853,31,5506,"Capture tasks: ","com.google.android.GoogleCamera",15154766434
+1429,5865,31,5506,"AsyncTask #4","com.google.android.GoogleCamera",15154766434
+1432,5869,31,5506,"glide-source-th","com.google.android.GoogleCamera",15154766434
+1433,5870,31,5506,"Thread-72","com.google.android.GoogleCamera",15154766434
+1435,5872,31,5506,"Thread-56","com.google.android.GoogleCamera",15154766434
+1436,5873,31,5506,"Thread-49","com.google.android.GoogleCamera",15154766434
+1441,5875,31,5506,"Thread-52","com.google.android.GoogleCamera",15154766434
+1442,5876,31,5506,"Thread-66","com.google.android.GoogleCamera",15154766434
+1443,5877,31,5506,"Thread-65","com.google.android.GoogleCamera",15154766434
+1444,5879,31,5506,"Thread-58","com.google.android.GoogleCamera",15154766434
+1445,5878,31,5506,"Thread-61","com.google.android.GoogleCamera",15154766434
+1495,5923,31,5506,"DelLifetime","com.google.android.GoogleCamera",15154766434
+1511,5938,31,5506,"Thread-91","com.google.android.GoogleCamera",15154766434
+1513,5941,31,5506,"Finish Thread","com.google.android.GoogleCamera",15154766434
+1514,5940,31,5506,"Finish Thread","com.google.android.GoogleCamera",15154766434
+1516,5944,31,5506,"Thread-80","com.google.android.GoogleCamera",15154766434
+1517,5945,31,5506,"Thread-84","com.google.android.GoogleCamera",15154766434
+1518,5946,31,5506,"Thread-79","com.google.android.GoogleCamera",15154766434
+1519,5943,31,5506,"Thread-85","com.google.android.GoogleCamera",15154766434
+1520,5947,31,5506,"Thread-81","com.google.android.GoogleCamera",15154766434
+1521,5948,31,5506,"Thread-83","com.google.android.GoogleCamera",15154766434
+1522,5949,31,5506,"Thread-82","com.google.android.GoogleCamera",15154766434
+1589,6011,31,5506,"mv-disk-writer","com.google.android.GoogleCamera",15154766434
+103,593,104,593,"sugov:4","sugov:4",6846445779
+76,3482,4,1204,"Binder:1204_17","system_server",6809850362
+78,1421,4,1204,"InputReader","system_server",6809850362
+81,1204,4,1204,"system_server","system_server",6809850362
+82,1259,4,1204,"PowerManagerSer","system_server",6809850362
+84,1251,4,1204,"android.ui","system_server",6809850362
+86,1257,4,1204,"android.display","system_server",6809850362
+87,1250,4,1204,"ActivityManager","system_server",6809850362
+88,1249,4,1204,"android.bg","system_server",6809850362
+101,1420,4,1204,"InputDispatcher","system_server",6809850362
+112,1256,4,1204,"android.fg","system_server",6809850362
+113,1446,4,1204,"tworkPolicy.uid","system_server",6809850362
+115,2692,4,1204,"Binder:1204_12","system_server",6809850362
+118,1254,4,1204,"batterystats-wo","system_server",6809850362
+130,1453,4,1204,"WifiService","system_server",6809850362
+136,1454,4,1204,"ClientModeImpl","system_server",6809850362
+139,4064,4,1204,"Binder:1204_18","system_server",6809850362
+140,1525,4,1204,"PhotonicModulat","system_server",6809850362
+145,1374,4,1204,"SensorService","system_server",6809850362
+148,1419,4,1204,"UEventObserver","system_server",6809850362
+182,1363,4,1204,"android.anim","system_server",6809850362
+183,2697,4,1204,"Binder:1204_16","system_server",6809850362
+185,2483,4,1204,"Binder:1204_A","system_server",6809850362
+207,1460,4,1204,"WifiScanningSer","system_server",6809850362
+210,1516,4,1204,"wifiAwareServic","system_server",6809850362
+217,1463,4,1204,"ConnectivitySer","system_server",6809850362
+218,1492,4,1204,"ConnectivityThr","system_server",6809850362
+223,1648,4,1204,"NetworkTimeUpda","system_server",6809850362
+244,1373,4,1204,"SensorEventAckR","system_server",6809850362
+270,2274,4,1204,"IpClient.wlan0","system_server",6809850362
+272,1396,4,1204,"AlarmManager","system_server",6809850362
+273,1252,4,1204,"ActivityManager","system_server",6809850362
+304,1253,4,1204,"ActivityManager","system_server",6809850362
+342,2688,4,1204,"Binder:1204_10","system_server",6809850362
+343,1699,4,1204,"Binder:1204_4","system_server",6809850362
+344,1700,4,1204,"Binder:1204_5","system_server",6809850362
+345,4743,4,1204,"Binder:1204_1A","system_server",6809850362
+346,1216,4,1204,"Binder:1204_1","system_server",6809850362
+347,2695,4,1204,"Binder:1204_15","system_server",6809850362
+407,1364,4,1204,"android.anim.lf","system_server",6809850362
+476,1489,4,1204,"HwBinder:1204_3","system_server",6809850362
+504,1519,4,1204,"TaskSnapshotPer","system_server",6809850362
+525,1529,4,1204,"LazyTaskWriterT","system_server",6809850362
+557,5332,4,1204,"GrallocUploadTh","system_server",6809850362
+636,1517,4,1204,"EthernetService","system_server",6809850362
+645,1246,4,1204,"android.io","system_server",6809850362
+688,1423,4,1204,"NetworkWatchlis","system_server",6809850362
+691,1469,4,1204,"ranker","system_server",6809850362
+692,2381,4,1204,"backup","system_server",6809850362
+761,1441,4,1204,"NetdConnector","system_server",6809850362
+762,1444,4,1204,"NetworkStats","system_server",6809850362
+782,1581,4,1204,"NetworkStatsObs","system_server",6809850362
+784,1445,4,1204,"NetworkPolicy","system_server",6809850362
+789,1383,4,1204,"SettingsProvide","system_server",6809850362
+792,1468,4,1204,"notification-sq","system_server",6809850362
+801,1255,4,1204,"FileObserver","system_server",6809850362
+807,1260,4,1204,"HwBinder:1204_1","system_server",6809850362
+836,3342,4,1204,"pool-4-thread-1","system_server",6809850362
+864,5498,4,1204,"RenderThread","system_server",6809850362
+865,5499,4,1204,"RenderThread","system_server",6809850362
+867,1214,4,1204,"HeapTaskDaemon","system_server",6809850362
+869,1211,4,1204,"ReferenceQueueD","system_server",6809850362
+879,1212,4,1204,"FinalizerDaemon","system_server",6809850362
+880,1213,4,1204,"FinalizerWatchd","system_server",6809850362
+1283,1739,4,1204,"hidl_ssvc_poll","system_server",6809850362
+1489,1480,4,1204,"AudioService","system_server",6809850362
+1619,1597,4,1204,"watchdog","system_server",6809850362
+50,2189,87,2189,"cds_ol_rx_threa","cds_ol_rx_threa",6684635721
+535,5313,23,5313,".android.chrome","com.android.chrome",5125412570
+536,5318,23,5313,"Jit thread pool","com.android.chrome",5125412570
+537,5319,23,5313,"Signal Catcher","com.android.chrome",5125412570
+538,5322,23,5313,"FinalizerDaemon","com.android.chrome",5125412570
+539,5323,23,5313,"FinalizerWatchd","com.android.chrome",5125412570
+540,5321,23,5313,"ReferenceQueueD","com.android.chrome",5125412570
+541,5320,23,5313,"ADB-JDWP Connec","com.android.chrome",5125412570
+542,5324,23,5313,"HeapTaskDaemon","com.android.chrome",5125412570
+543,5325,23,5313,"Binder:5313_1","com.android.chrome",5125412570
+544,5326,23,5313,"Binder:5313_2","com.android.chrome",5125412570
+546,5327,23,5313,"Profile Saver","com.android.chrome",5125412570
+561,5333,23,5313,"CrAsyncTask #1","com.android.chrome",5125412570
+562,5334,23,5313,"CrAsyncTask #2","com.android.chrome",5125412570
+563,5335,23,5313,"CrAsyncTask #3","com.android.chrome",5125412570
+569,5336,23,5313,"SharedPreferenc","com.android.chrome",5125412570
+571,5339,23,5313,"Thread-2","com.android.chrome",5125412570
+576,5342,23,5313,"Thread-3","com.android.chrome",5125412570
+577,5343,23,5313,"CrAsyncTask #4","com.android.chrome",5125412570
+578,5344,23,5313,"magnifier pixel","com.android.chrome",5125412570
+579,5345,23,5313,"RenderThread","com.android.chrome",5125412570
+580,5346,23,5313,"Gservices","com.android.chrome",5125412570
+581,5347,23,5313,"Chrome_ProcessL","com.android.chrome",5125412570
+603,5364,23,5313,"Binder:5313_3","com.android.chrome",5125412570
+605,5365,23,5313,"Chrome_IOThread","com.android.chrome",5125412570
+606,5366,23,5313,"TaskSchedulerSe","com.android.chrome",5125412570
+607,5367,23,5313,"TaskSchedulerFo","com.android.chrome",5125412570
+608,5368,23,5313,"TaskSchedulerFo","com.android.chrome",5125412570
+609,5369,23,5313,"DnsConfigServic","com.android.chrome",5125412570
+610,5370,23,5313,"TaskSchedulerFo","com.android.chrome",5125412570
+611,5371,23,5313,"TaskSchedulerFo","com.android.chrome",5125412570
+612,5372,23,5313,"TaskSchedulerSi","com.android.chrome",5125412570
+613,5373,23,5313,"queued-work-loo","com.android.chrome",5125412570
+614,5374,23,5313,"AudioThread","com.android.chrome",5125412570
+615,5375,23,5313,"BrowserWatchdog","com.android.chrome",5125412570
+616,5376,23,5313,"Chrome_HistoryT","com.android.chrome",5125412570
+620,5380,23,5313,"TaskSchedulerSi","com.android.chrome",5125412570
+639,5396,23,5313,"CompositorTileW","com.android.chrome",5125412570
+643,5399,23,5313,"hwuiTask1","com.android.chrome",5125412570
+665,5415,23,5313,"TaskSchedulerFo","com.android.chrome",5125412570
+699,5443,23,5313,"SAFE_BROWSING_U","com.android.chrome",5125412570
+700,5444,23,5313,"GoogleApiHandle","com.android.chrome",5125412570
+729,5461,23,5313,"SensorsHandlerT","com.android.chrome",5125412570
+744,5471,23,5313,"Binder:5313_4","com.android.chrome",5125412570
+746,5473,23,5313,"AudioTrack","com.android.chrome",5125412570
+757,5482,23,5313,"Chrome_DevTools","com.android.chrome",5125412570
+857,5496,23,5313,"TaskSchedulerFo","com.android.chrome",5125412570
+920,5502,23,5313,"TaskSchedulerFo","com.android.chrome",5125412570
+921,5503,23,5313,"TaskSchedulerFo","com.android.chrome",5125412570
+1507,5935,23,5313,"Binder:5313_5","com.android.chrome",5125412570
+20,57,110,57,"ksoftirqd/6","ksoftirqd/6",4117624162
+587,5348,24,5348,"dboxed_process0","com.android.chrome:sandboxed_process0",3569713072
+592,5353,24,5348,"Jit thread pool","com.android.chrome:sandboxed_process0",3569713072
+593,5354,24,5348,"Signal Catcher","com.android.chrome:sandboxed_process0",3569713072
+594,5355,24,5348,"ADB-JDWP Connec","com.android.chrome:sandboxed_process0",3569713072
+595,5357,24,5348,"FinalizerDaemon","com.android.chrome:sandboxed_process0",3569713072
+596,5356,24,5348,"ReferenceQueueD","com.android.chrome:sandboxed_process0",3569713072
+597,5358,24,5348,"FinalizerWatchd","com.android.chrome:sandboxed_process0",3569713072
+598,5359,24,5348,"HeapTaskDaemon","com.android.chrome:sandboxed_process0",3569713072
+599,5360,24,5348,"Binder:5348_1","com.android.chrome:sandboxed_process0",3569713072
+600,5361,24,5348,"Binder:5348_2","com.android.chrome:sandboxed_process0",3569713072
+601,5362,24,5348,"Binder:5348_3","com.android.chrome:sandboxed_process0",3569713072
+602,5363,24,5348,"CrRendererMain","com.android.chrome:sandboxed_process0",3569713072
+648,5404,24,5348,"TaskSchedulerFo","com.android.chrome:sandboxed_process0",3569713072
+649,5405,24,5348,"Chrome_ChildIOT","com.android.chrome:sandboxed_process0",3569713072
+650,5403,24,5348,"TaskSchedulerFo","com.android.chrome:sandboxed_process0",3569713072
+651,5402,24,5348,"TaskSchedulerSe","com.android.chrome:sandboxed_process0",3569713072
+652,5406,24,5348,"GpuMemoryThread","com.android.chrome:sandboxed_process0",3569713072
+660,5408,24,5348,"Compositor","com.android.chrome:sandboxed_process0",3569713072
+661,5414,24,5348,"CompositorTileW","com.android.chrome:sandboxed_process0",3569713072
+662,5413,24,5348,"CompositorTileW","com.android.chrome:sandboxed_process0",3569713072
+707,5452,24,5348,"TaskSchedulerFo","com.android.chrome:sandboxed_process0",3569713072
+708,5451,24,5348,"TaskSchedulerFo","com.android.chrome:sandboxed_process0",3569713072
+709,5450,24,5348,"TaskSchedulerFo","com.android.chrome:sandboxed_process0",3569713072
+710,5449,24,5348,"TaskSchedulerFo","com.android.chrome:sandboxed_process0",3569713072
+711,5448,24,5348,"TaskSchedulerFo","com.android.chrome:sandboxed_process0",3569713072
+712,5447,24,5348,"TaskSchedulerFo","com.android.chrome:sandboxed_process0",3569713072
+719,5455,24,5348,"ScriptStreamer ","com.android.chrome:sandboxed_process0",3569713072
+732,5462,24,5348,"Media","com.android.chrome:sandboxed_process0",3569713072
+748,5475,24,5348,"AudioOutputDevi","com.android.chrome:sandboxed_process0",3569713072
+1108,1926,225,759,"HwBinder:759_1","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1112,5608,225,759,"HwBinder:759_1","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1113,5607,225,759,"HwBinder:759_1","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1114,5606,225,759,"HwBinder:759_1","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1115,1696,225,759,"provider@2.4-se","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1116,5609,225,759,"QCamera3HdrPlus","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1119,5610,225,759,"CAM_MctServ","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1121,5611,225,759,"CAM_MctBus","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1123,5614,225,759,"CAM_sensor","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1127,5617,225,759,"CAM_iface_ses","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1130,5620,225,759,"CAM_img_msg","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1131,5621,225,759,"CAM_img_msg","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1132,5622,225,759,"CAM_cpp","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1133,5624,225,759,"CAM_c2d","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1134,5623,225,759,"CAM_isp_trigger","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1135,5625,225,759,"CAM_hw_update","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1137,5627,225,759,"CAM_isp_parser","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1138,5628,225,759,"CAM_startsensor","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1139,5629,225,759,"CAM_gyro_sens","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1140,5630,225,759,"CAM_startsensor","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1141,5631,225,759,"CAM_startsensor","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1144,5633,225,759,"CAM_img_msg","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1148,5635,225,759,"CAM_AECAWB","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1149,5636,225,759,"CAM_AF","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1150,5638,225,759,"CAM_ASD","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1151,5637,225,759,"CAM_AFD","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1152,5639,225,759,"CAM_Dispatch","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1153,5640,225,759,"CAM_evntPoll","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1159,5644,225,759,"CAM_dataPoll","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1233,5705,225,759,"cam_data_proc","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1235,5704,225,759,"cam_data_proc","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1236,5707,225,759,"mm_jpeg_thread","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1237,5708,225,759,"OMX_ImgEnc","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1238,5711,225,759,"cam_data_proc","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1239,5710,225,759,"cam_data_proc","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1240,5709,225,759,"cam_data_proc","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1249,5719,225,759,"CAM_img","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1250,5720,225,759,"CAM_img","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1252,5721,225,759,"CAM_METADATA","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1254,5723,225,759,"CAM_ANALYSISCAM","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1255,5724,225,759,"CAM_PREVIEW","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1256,5725,225,759,"CAM_SNAPSHOT","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1257,5726,225,759,"CAM_CALLBACK","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1258,5727,225,759,"CAM_CALLBACK","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1259,5728,225,759,"CAM_RAW","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1261,5730,225,759,"CAM_StrmAppDat","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1262,5731,225,759,"CAM_StrmAppDat","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1263,1543,225,759,"CAM_imgTh","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1273,5742,225,759,"CAM_iface_poll","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1277,5744,225,759,"CAM_iface_hw","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1284,759,225,759,"provider@2.4-se","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1285,5752,225,759,"HwBinder:759_2","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1299,5756,225,759,"HwBinder:759_1","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1300,5757,225,759,"HwBinder:759_1","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1301,5758,225,759,"CAM_laser_sens","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1305,5762,225,759,"CAM_StrmAppDat","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1308,5765,225,759,"CAM_StrmAppDat","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1309,5766,225,759,"CAM_StrmAppDat","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1310,5767,225,759,"CAM_StrmAppDat","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1311,5768,225,759,"CAM_StrmAppDat","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1313,5770,225,759,"HwBinder:759_3","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1321,5776,225,759,"CAM_sof_timer","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+1425,5862,225,759,"HwBinder:759_4","/vendor/bin/hw/android.hardware.camera.provider@2.4-service",3337433441
+97,2285,5,1572,"Binder:1572_8","com.android.systemui",3072242745
+100,1572,5,1572,"ndroid.systemui","com.android.systemui",3072242745
+114,1589,5,1572,"Binder:1572_1","com.android.systemui",3072242745
+120,1981,5,1572,"RenderThread","com.android.systemui",3072242745
+128,1934,5,1572,"SysUiBg","com.android.systemui",3072242745
+161,2121,5,1572,"ScreenDecoratio","com.android.systemui",3072242745
+205,1876,5,1572,"pool-1-thread-1","com.android.systemui",3072242745
+212,1580,5,1572,"Jit thread pool","com.android.systemui",3072242745
+222,1994,5,1572,"ConnectivityThr","com.android.systemui",3072242745
+243,2021,5,1572,"async_sensor","com.android.systemui",3072242745
+257,2270,5,1572,"hwuiTask1","com.android.systemui",3072242745
+374,2090,5,1572,"recents.fg","com.android.systemui",3072242745
+434,2256,5,1572,"GrallocUploadTh","com.android.systemui",3072242745
+566,1593,5,1572,"Binder:1572_2","com.android.systemui",3072242745
+567,2044,5,1572,"Binder:1572_5","com.android.systemui",3072242745
+568,2079,5,1572,"Binder:1572_7","com.android.systemui",3072242745
+788,1932,5,1572,"VolumeDialogCon","com.android.systemui",3072242745
+795,2275,5,1572,"Thread-2","com.android.systemui",3072242745
+796,5486,5,1572,"AsyncTask #7","com.android.systemui",3072242745
+797,5487,5,1572,"AsyncTask #8","com.android.systemui",3072242745
+798,5488,5,1572,"InflaterThread ","com.android.systemui",3072242745
+799,5489,5,1572,"InflaterThread ","com.android.systemui",3072242745
+800,5490,5,1572,"InflaterThread ","com.android.systemui",3072242745
+822,5155,5,1572,"AsyncTask #6","com.android.systemui",3072242745
+823,5493,5,1572,"InflaterThread ","com.android.systemui",3072242745
+830,2002,5,1572,"AsyncTask #1","com.android.systemui",3072242745
+860,1587,5,1572,"HeapTaskDaemon","com.android.systemui",3072242745
+861,1584,5,1572,"ReferenceQueueD","com.android.systemui",3072242745
+862,1585,5,1572,"FinalizerDaemon","com.android.systemui",3072242745
+863,1586,5,1572,"FinalizerWatchd","com.android.systemui",3072242745
+1109,2059,5,1572,"FlashlightContr","com.android.systemui",3072242745
+29,2798,9,2400,"TimerThread0","com.google.android.googlequicksearchbox:search",2487567838
+30,3004,9,2400,"UserFacing3","com.google.android.googlequicksearchbox:search",2487567838
+35,4163,9,2400,"ChromiumNet","com.google.android.googlequicksearchbox:search",2487567838
+160,2961,9,2400,"Binder:2400_4","com.google.android.googlequicksearchbox:search",2487567838
+229,2921,9,2400,"ConnectivityThr","com.google.android.googlequicksearchbox:search",2487567838
+230,2400,9,2400,"earchbox:search","com.google.android.googlequicksearchbox:search",2487567838
+235,4075,9,2400,"CronetInit","com.google.android.googlequicksearchbox:search",2487567838
+371,5189,9,2400,"Binder:2400_7","com.google.android.googlequicksearchbox:search",2487567838
+399,4155,9,2400,"TaskSchedulerSe","com.google.android.googlequicksearchbox:search",2487567838
+400,4156,9,2400,"TaskSchedulerBa","com.google.android.googlequicksearchbox:search",2487567838
+401,4157,9,2400,"TaskSchedulerBa","com.google.android.googlequicksearchbox:search",2487567838
+402,4910,9,2400,"TaskSchedulerFo","com.google.android.googlequicksearchbox:search",2487567838
+403,4165,9,2400,"TaskSchedulerFo","com.google.android.googlequicksearchbox:search",2487567838
+404,4161,9,2400,"TaskSchedulerFo","com.google.android.googlequicksearchbox:search",2487567838
+405,4162,9,2400,"TaskSchedulerFo","com.google.android.googlequicksearchbox:search",2487567838
+406,5271,9,2400,"magnifier pixel","com.google.android.googlequicksearchbox:search",2487567838
+414,2428,9,2400,"Jit thread pool","com.google.android.googlequicksearchbox:search",2487567838
+433,5281,9,2400,"RenderThread","com.google.android.googlequicksearchbox:search",2487567838
+444,2522,9,2400,"Profile Saver","com.google.android.googlequicksearchbox:search",2487567838
+459,2448,9,2400,"HeapTaskDaemon","com.google.android.googlequicksearchbox:search",2487567838
+466,2690,9,2400,"SearchSettings_","com.google.android.googlequicksearchbox:search",2487567838
+467,2442,9,2400,"ReferenceQueueD","com.google.android.googlequicksearchbox:search",2487567838
+468,2444,9,2400,"FinalizerDaemon","com.google.android.googlequicksearchbox:search",2487567838
+469,2446,9,2400,"FinalizerWatchd","com.google.android.googlequicksearchbox:search",2487567838
+470,4041,9,2400,"NonUserFacing5","com.google.android.googlequicksearchbox:search",2487567838
+471,2834,9,2400,"queued-work-loo","com.google.android.googlequicksearchbox:search",2487567838
+478,2799,9,2400,"UserFacing0","com.google.android.googlequicksearchbox:search",2487567838
+490,2848,9,2400,"UserFacing1","com.google.android.googlequicksearchbox:search",2487567838
+491,5308,9,2400,"IcingConnection","com.google.android.googlequicksearchbox:search",2487567838
+492,4118,9,2400,"UserFacing5","com.google.android.googlequicksearchbox:search",2487567838
+497,2854,9,2400,"UserFacing2","com.google.android.googlequicksearchbox:search",2487567838
+502,4807,9,2400,"Binder:2400_6","com.google.android.googlequicksearchbox:search",2487567838
+503,2846,9,2400,"NonUserFacing1","com.google.android.googlequicksearchbox:search",2487567838
+509,4040,9,2400,"NonUserFacing4","com.google.android.googlequicksearchbox:search",2487567838
+510,2778,9,2400,"NonUserFacing0","com.google.android.googlequicksearchbox:search",2487567838
+511,5310,9,2400,"GcoreGoogleApiC","com.google.android.googlequicksearchbox:search",2487567838
+512,5311,9,2400,"GAC_Executor[1]","com.google.android.googlequicksearchbox:search",2487567838
+513,4306,9,2400,"GAC_Executor[0]","com.google.android.googlequicksearchbox:search",2487567838
+560,2451,9,2400,"Binder:2400_1","com.google.android.googlequicksearchbox:search",2487567838
+804,5491,9,2400,"TaskSchedulerFo","com.google.android.googlequicksearchbox:search",2487567838
+811,4164,9,2400,"DnsConfigServic","com.google.android.googlequicksearchbox:search",2487567838
+828,3841,9,2400,"GoogleApiHandle","com.google.android.googlequicksearchbox:search",2487567838
+859,4039,9,2400,"NonUserFacing3","com.google.android.googlequicksearchbox:search",2487567838
+996,5540,9,2400,"TaskSchedulerFo","com.google.android.googlequicksearchbox:search",2487567838
+997,5539,9,2400,"TaskSchedulerBa","com.google.android.googlequicksearchbox:search",2487567838
+1466,4167,9,2400,"Network File Th","com.google.android.googlequicksearchbox:search",2487567838
+617,5377,25,5377,"ileged_process0","com.android.chrome:privileged_process0",2338957110
+624,5384,25,5377,"Jit thread pool","com.android.chrome:privileged_process0",2338957110
+625,5385,25,5377,"Signal Catcher","com.android.chrome:privileged_process0",2338957110
+626,5386,25,5377,"ADB-JDWP Connec","com.android.chrome:privileged_process0",2338957110
+627,5388,25,5377,"FinalizerDaemon","com.android.chrome:privileged_process0",2338957110
+628,5389,25,5377,"FinalizerWatchd","com.android.chrome:privileged_process0",2338957110
+629,5387,25,5377,"ReferenceQueueD","com.android.chrome:privileged_process0",2338957110
+630,5390,25,5377,"HeapTaskDaemon","com.android.chrome:privileged_process0",2338957110
+631,5391,25,5377,"Binder:5377_1","com.android.chrome:privileged_process0",2338957110
+632,5392,25,5377,"Binder:5377_2","com.android.chrome:privileged_process0",2338957110
+634,5393,25,5377,"Binder:5377_3","com.android.chrome:privileged_process0",2338957110
+635,5394,25,5377,"Profile Saver","com.android.chrome:privileged_process0",2338957110
+638,5395,25,5377,"CrGpuMain","com.android.chrome:privileged_process0",2338957110
+640,5397,25,5377,"Watchdog","com.android.chrome:privileged_process0",2338957110
+656,5411,25,5377,"TaskSchedulerFo","com.android.chrome:privileged_process0",2338957110
+657,5412,25,5377,"Chrome_ChildIOT","com.android.chrome:privileged_process0",2338957110
+658,5410,25,5377,"TaskSchedulerFo","com.android.chrome:privileged_process0",2338957110
+659,5409,25,5377,"TaskSchedulerSe","com.android.chrome:privileged_process0",2338957110
+733,5463,25,5377,"CrGpuMain","com.android.chrome:privileged_process0",2338957110
+734,5464,25,5377,"TaskSchedulerSi","com.android.chrome:privileged_process0",2338957110
+750,5476,25,5377,"AVDAAutoThread","com.android.chrome:privileged_process0",2338957110
+751,5477,25,5377,"AVDASWThread","com.android.chrome:privileged_process0",2338957110
+752,5478,25,5377,"MediaCodec_loop","com.android.chrome:privileged_process0",2338957110
+753,5479,25,5377,"JNISurfaceTextu","com.android.chrome:privileged_process0",2338957110
+755,5480,25,5377,"HwBinder:5377_1","com.android.chrome:privileged_process0",2338957110
+89,652,80,622,"Binder:622_2","/system/bin/surfaceflinger",2155181851
+91,692,80,622,"surfaceflinger","/system/bin/surfaceflinger",2155181851
+92,656,80,622,"sfEventThread","/system/bin/surfaceflinger",2155181851
+94,654,80,622,"DispSync","/system/bin/surfaceflinger",2155181851
+95,1221,80,622,"Binder:622_3","/system/bin/surfaceflinger",2155181851
+98,651,80,622,"Binder:622_1","/system/bin/surfaceflinger",2155181851
+106,622,80,622,"surfaceflinger","/system/bin/surfaceflinger",2155181851
+109,655,80,622,"appEventThread","/system/bin/surfaceflinger",2155181851
+127,688,80,622,"HwBinder:622_1","/system/bin/surfaceflinger",2155181851
+422,4032,80,622,"Binder:622_5","/system/bin/surfaceflinger",2155181851
+423,1438,80,622,"Binder:622_4","/system/bin/surfaceflinger",2155181851
+858,5497,80,622,"surfaceflinger","/system/bin/surfaceflinger",2155181851
+32,2265,57,834,"wifi@1.0-servic","/vendor/bin/hw/android.hardware.wifi@1.0-service",2046147338
+137,834,57,834,"wifi@1.0-servic","/vendor/bin/hw/android.hardware.wifi@1.0-service",2046147338
+169,2551,6,2523,"Binder:2523_1","com.google.android.apps.nexuslauncher",1639085587
+171,2523,6,2523,"s.nexuslauncher","com.google.android.apps.nexuslauncher",1639085587
+172,2745,6,2523,"UiThreadHelper","com.google.android.apps.nexuslauncher",1639085587
+369,3017,6,2523,"RenderThread","com.google.android.apps.nexuslauncher",1639085587
+372,4571,6,2523,"Binder:2523_4","com.google.android.apps.nexuslauncher",1639085587
+373,2639,6,2523,"launcher-loader","com.google.android.apps.nexuslauncher",1639085587
+375,3107,6,2523,"reflection-thre","com.google.android.apps.nexuslauncher",1639085587
+376,2705,6,2523,"GoogleApiHandle","com.google.android.apps.nexuslauncher",1639085587
+378,2531,6,2523,"Jit thread pool","com.google.android.apps.nexuslauncher",1639085587
+379,2838,6,2523,"queued-work-loo","com.google.android.apps.nexuslauncher",1639085587
+381,2988,6,2523,"GrallocUploadTh","com.google.android.apps.nexuslauncher",1639085587
+547,5328,6,2523,"hwuiTask1","com.google.android.apps.nexuslauncher",1639085587
+551,5330,6,2523,"pool-3-thread-1","com.google.android.apps.nexuslauncher",1639085587
+552,2548,6,2523,"HeapTaskDaemon","com.google.android.apps.nexuslauncher",1639085587
+553,2886,6,2523,"TaskThumbnailIc","com.google.android.apps.nexuslauncher",1639085587
+559,2545,6,2523,"ReferenceQueueD","com.google.android.apps.nexuslauncher",1639085587
+572,2546,6,2523,"FinalizerDaemon","com.google.android.apps.nexuslauncher",1639085587
+574,2547,6,2523,"FinalizerWatchd","com.google.android.apps.nexuslauncher",1639085587
+769,2629,6,2523,"Profile Saver","com.google.android.apps.nexuslauncher",1639085587
+844,5495,6,2523,"pool-3-thread-2","com.google.android.apps.nexuslauncher",1639085587
+874,2562,6,2523,"Binder:2523_2","com.google.android.apps.nexuslauncher",1639085587
+875,2582,6,2523,"Binder:2523_3","com.google.android.apps.nexuslauncher",1639085587
+876,5500,6,2523,"Binder:2523_5","com.google.android.apps.nexuslauncher",1639085587
+3,906,41,906,"traced_probes","/system/bin/traced_probes",1598981574
+6,5244,41,906,"traced_probes0","/system/bin/traced_probes",1598981574
+7,5251,41,906,"traced_probes7","/system/bin/traced_probes",1598981574
+9,5250,41,906,"traced_probes6","/system/bin/traced_probes",1598981574
+10,5249,41,906,"traced_probes5","/system/bin/traced_probes",1598981574
+11,5248,41,906,"traced_probes4","/system/bin/traced_probes",1598981574
+12,5247,41,906,"traced_probes3","/system/bin/traced_probes",1598981574
+13,5246,41,906,"traced_probes2","/system/bin/traced_probes",1598981574
+14,5245,41,906,"traced_probes1","/system/bin/traced_probes",1598981574
+1612,916,41,906,"traced_probes","/system/bin/traced_probes",1598981574
+59,2685,3,2139,"GlobalScheduler","com.google.android.gms.persistent",1577881906
+60,2139,3,2139,".gms.persistent","com.google.android.gms.persistent",1577881906
+61,2955,3,2139,"lowpool[2]","com.google.android.gms.persistent",1577881906
+117,4201,3,2139,"Binder:2139_C","com.google.android.gms.persistent",1577881906
+119,3279,3,2139,"FlpThread","com.google.android.gms.persistent",1577881906
+349,4474,3,2139,"Binder:2139_E","com.google.android.gms.persistent",1577881906
+358,3255,3,2139,"GeofencerStateM","com.google.android.gms.persistent",1577881906
+362,3517,3,2139,"GoogleLocationS","com.google.android.gms.persistent",1577881906
+377,2144,3,2139,"Jit thread pool","com.google.android.gms.persistent",1577881906
+380,3635,3,2139,"lowpool[8]","com.google.android.gms.persistent",1577881906
+413,2236,3,2139,"peration loader","com.google.android.gms.persistent",1577881906
+416,4772,3,2139,"raService] idle","com.google.android.gms.persistent",1577881906
+427,2237,3,2139,"queued-work-loo","com.google.android.gms.persistent",1577881906
+463,2682,3,2139,"GoogleApiHandle","com.google.android.gms.persistent",1577881906
+464,5300,3,2139,"raService] idle","com.google.android.gms.persistent",1577881906
+493,2740,3,2139,"netscheduler-qu","com.google.android.gms.persistent",1577881906
+514,4203,3,2139,"Binder:2139_D","com.google.android.gms.persistent",1577881906
+515,2227,3,2139,"GlobalDispatchi","com.google.android.gms.persistent",1577881906
+516,3005,3,2139,"lowpool[4]","com.google.android.gms.persistent",1577881906
+530,2176,3,2139,"Profile Saver","com.google.android.gms.persistent",1577881906
+663,2151,3,2139,"Binder:2139_1","com.google.android.gms.persistent",1577881906
+664,3054,3,2139,"highpool[2]","com.google.android.gms.persistent",1577881906
+714,5453,3,2139,"Thread-26","com.google.android.gms.persistent",1577881906
+718,3745,3,2139,"Okio Watchdog","com.google.android.gms.persistent",1577881906
+727,4114,3,2139,"OkHttp Connecti","com.google.android.gms.persistent",1577881906
+881,2666,3,2139,"Binder:2139_6","com.google.android.gms.persistent",1577881906
+882,2159,3,2139,"Binder:2139_4","com.google.android.gms.persistent",1577881906
+883,3135,3,2139,"Binder:2139_A","com.google.android.gms.persistent",1577881906
+884,2158,3,2139,"Binder:2139_3","com.google.android.gms.persistent",1577881906
+885,2946,3,2139,"Binder:2139_7","com.google.android.gms.persistent",1577881906
+886,3063,3,2139,"Binder:2139_9","com.google.android.gms.persistent",1577881906
+887,2154,3,2139,"Binder:2139_2","com.google.android.gms.persistent",1577881906
+888,2999,3,2139,"Binder:2139_8","com.google.android.gms.persistent",1577881906
+889,3200,3,2139,"Binder:2139_B","com.google.android.gms.persistent",1577881906
+1084,3653,3,2139,"Places","com.google.android.gms.persistent",1577881906
+1599,2660,3,2139,"Binder:2139_5","com.google.android.gms.persistent",1577881906
+1600,6019,3,2139,"Binder:2139_F","com.google.android.gms.persistent",1577881906
+436,150,177,150,"kswapd0","kswapd0",1377437355
+37,2827,1,2238,"GlobalScheduler","com.google.android.gms",1130387110
+38,2238,1,2238,"gle.android.gms","com.google.android.gms",1130387110
+39,2757,1,2238,"lowpool[2]","com.google.android.gms",1130387110
+162,4264,1,2238,"Binder:2238_E","com.google.android.gms",1130387110
+367,3750,1,2238,"Binder:2238_B","com.google.android.gms",1130387110
+425,5275,1,2238,"peration loader","com.google.android.gms",1130387110
+426,5276,1,2238,"raService] idle","com.google.android.gms",1130387110
+428,5277,1,2238,"raService] idle","com.google.android.gms",1130387110
+429,5278,1,2238,"raService] idle","com.google.android.gms",1130387110
+430,2640,1,2238,"GoogleApiHandle","com.google.android.gms",1130387110
+431,5279,1,2238,"raService] idle","com.google.android.gms",1130387110
+435,5282,1,2238,"raService] idle","com.google.android.gms",1130387110
+437,2243,1,2238,"Jit thread pool","com.google.android.gms",1130387110
+507,2772,1,2238,"lowpool[3]","com.google.android.gms",1130387110
+654,3098,1,2238,"GAC_Executor[1]","com.google.android.gms",1130387110
+655,2895,1,2238,"GAC_Executor[0]","com.google.android.gms",1130387110
+713,3905,1,2238,"highpool[2]","com.google.android.gms",1130387110
+722,5458,1,2238,"IntentService[D","com.google.android.gms",1130387110
+736,5465,1,2238,"mdns-send","com.google.android.gms",1130387110
+737,5466,1,2238,"MdnsSocketClien","com.google.android.gms",1130387110
+738,5467,1,2238,"mdns-multicast-","com.google.android.gms",1130387110
+739,3925,1,2238,"lowpool[7]","com.google.android.gms",1130387110
+740,5468,1,2238,"lowpool[8]","com.google.android.gms",1130387110
+826,2254,1,2238,"Profile Saver","com.google.android.gms",1130387110
+870,2761,1,2238,"Binder:2238_6","com.google.android.gms",1130387110
+871,4475,1,2238,"Binder:2238_F","com.google.android.gms",1130387110
+872,2831,1,2238,"Binder:2238_8","com.google.android.gms",1130387110
+1065,4038,1,2238,"Okio Watchdog","com.google.android.gms",1130387110
+1174,2755,1,2238,"Binder:2238_5","com.google.android.gms",1130387110
+1175,3749,1,2238,"Binder:2238_A","com.google.android.gms",1130387110
+1176,2396,1,2238,"Binder:2238_4","com.google.android.gms",1130387110
+1177,4257,1,2238,"Binder:2238_D","com.google.android.gms",1130387110
+1480,5910,1,2238,"peration loader","com.google.android.gms",1130387110
+1481,5911,1,2238,"raService] idle","com.google.android.gms",1130387110
+1591,6013,1,2238,"IntentService[M","com.google.android.gms",1130387110
+1592,6014,1,2238,"MediaTracker bu","com.google.android.gms",1130387110
+1595,2249,1,2238,"HeapTaskDaemon","com.google.android.gms",1130387110
+1597,2246,1,2238,"ReferenceQueueD","com.google.android.gms",1130387110
+1606,2247,1,2238,"FinalizerDaemon","com.google.android.gms",1130387110
+1607,2248,1,2238,"FinalizerWatchd","com.google.android.gms",1130387110
+754,2165,205,943,"HwBinder:943_3","media.codec",930299908
+756,5481,205,943,"VideoDecCallBac","media.codec",930299908
+758,5484,205,943,"OMXCallbackDisp","media.codec",930299908
+759,5483,205,943,"VideoDecMsgThre","media.codec",930299908
+760,1107,205,943,"HwBinder:943_1","media.codec",930299908
+763,2229,205,943,"HwBinder:943_5","media.codec",930299908
+764,1110,205,943,"HwBinder:943_2","media.codec",930299908
+827,2184,205,943,"HwBinder:943_4","media.codec",930299908
+1394,5837,205,943,"OMXCallbackDisp","media.codec",930299908
+1395,5836,205,943,"VideoEncCallBac","media.codec",930299908
+1396,5835,205,943,"VideoEncMsgThre","media.codec",930299908
+1401,943,205,943,"omx@1.0-service","media.codec",930299908
+1402,5841,205,943,"HwBinder:943_6","media.codec",930299908
+1417,5854,205,943,"VideoEncMsgThre","media.codec",930299908
+1418,5855,205,943,"VideoEncMsgThre","media.codec",930299908
+1275,5737,37,5737,"oid.apps.photos","com.google.android.apps.photos",748904789
+1279,5746,37,5737,"Jit thread pool","com.google.android.apps.photos",748904789
+1280,5747,37,5737,"Signal Catcher","com.google.android.apps.photos",748904789
+1281,5748,37,5737,"ADB-JDWP Connec","com.google.android.apps.photos",748904789
+1282,5749,37,5737,"ReferenceQueueD","com.google.android.apps.photos",748904789
+1286,5750,37,5737,"FinalizerDaemon","com.google.android.apps.photos",748904789
+1287,5751,37,5737,"FinalizerWatchd","com.google.android.apps.photos",748904789
+1288,5753,37,5737,"HeapTaskDaemon","com.google.android.apps.photos",748904789
+1291,5754,37,5737,"Binder:5737_1","com.google.android.apps.photos",748904789
+1292,5755,37,5737,"Binder:5737_2","com.google.android.apps.photos",748904789
+1304,5761,37,5737,"Binder:5737_3","com.google.android.apps.photos",748904789
+1314,5771,37,5737,"Profile Saver","com.google.android.apps.photos",748904789
+1322,5777,37,5737,"default_backgro","com.google.android.apps.photos",748904789
+1325,5779,37,5737,"Primes-init-1","com.google.android.apps.photos",748904789
+1334,5788,37,5737,"MediaPageFetche","com.google.android.apps.photos",748904789
+1335,5787,37,5737,"queued-work-loo","com.google.android.apps.photos",748904789
+1390,5832,37,5737,"glide-source-th","com.google.android.apps.photos",748904789
+1428,5866,37,5737,"glide-source-th","com.google.android.apps.photos",748904789
+1590,6012,37,5737,"glide-source-th","com.google.android.apps.photos",748904789
+1596,6017,37,5737,"Binder:5737_4","com.google.android.apps.photos",748904789
+1608,6021,37,5737,"GrallocUploadTh","com.google.android.apps.photos",748904789
+1609,6022,37,5737,"glide-active-re","com.google.android.apps.photos",748904789
+1618,6025,37,5737,"BackgroundTask ","com.google.android.apps.photos",748904789
+110,1774,13,1657,"Binder:1657_3","com.breel.wallpapers",638226980
+152,1657,13,1657,"reel.wallpapers","com.breel.wallpapers",638226980
+261,2060,13,1657,"GLThread 35","com.breel.wallpapers",638226980
+408,1663,13,1657,"Jit thread pool","com.breel.wallpapers",638226980
+409,1801,13,1657,"Profile Saver","com.breel.wallpapers",638226980
+1019,2371,13,1657,"Binder:1657_4","com.breel.wallpapers",638226980
+90,687,82,624,"HwBinder:624_1","/vendor/bin/hw/android.hardware.graphics.composer@2.1-service",617056001
+102,741,82,624,"HwBinder:624_2","/vendor/bin/hw/android.hardware.graphics.composer@2.1-service",617056001
+126,664,82,624,"SDM_EventThread","/vendor/bin/hw/android.hardware.graphics.composer@2.1-service",617056001
+154,686,82,624,"HWC_UeventThrea","/vendor/bin/hw/android.hardware.graphics.composer@2.1-service",617056001
+1156,639,82,624,"Binder:624_2","/vendor/bin/hw/android.hardware.graphics.composer@2.1-service",617056001
+1627,624,82,624,"[NULL]","/vendor/bin/hw/android.hardware.graphics.composer@2.1-service",617056001
+129,1368,98,804,"HwBinder:804_1","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+132,1392,98,804,"HwBinder:804_1","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+133,955,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+138,1393,98,804,"HwBinder:804_1","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+143,1085,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+144,804,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+240,1047,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+241,1046,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+245,1083,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+246,1082,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+251,1041,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+252,1040,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+253,1076,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+254,1075,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+255,1051,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+256,1050,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+475,975,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+725,1391,98,804,"HwBinder:804_1","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+726,959,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+730,1016,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+731,1015,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+1223,5694,98,804,"HwBinder:804_1","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+1224,5695,98,804,"HwBinder:804_1","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+1289,977,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+1290,976,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+1315,1070,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+1490,1069,98,804,"sensors@1.0-ser","/vendor/bin/hw/android.hardware.sensors@1.0-service",536607816
+999,5542,32,5542,"ssioncontroller","com.google.android.permissioncontroller",521893072
+1004,5547,32,5542,"Jit thread pool","com.google.android.permissioncontroller",521893072
+1005,5548,32,5542,"Signal Catcher","com.google.android.permissioncontroller",521893072
+1006,5549,32,5542,"ADB-JDWP Connec","com.google.android.permissioncontroller",521893072
+1007,5550,32,5542,"ReferenceQueueD","com.google.android.permissioncontroller",521893072
+1008,5551,32,5542,"FinalizerDaemon","com.google.android.permissioncontroller",521893072
+1009,5552,32,5542,"FinalizerWatchd","com.google.android.permissioncontroller",521893072
+1010,5553,32,5542,"HeapTaskDaemon","com.google.android.permissioncontroller",521893072
+1011,5554,32,5542,"Binder:5542_1","com.google.android.permissioncontroller",521893072
+1012,5555,32,5542,"Binder:5542_2","com.google.android.permissioncontroller",521893072
+1013,5556,32,5542,"Profile Saver","com.google.android.permissioncontroller",521893072
+1018,5560,32,5542,"RenderThread","com.google.android.permissioncontroller",521893072
+1020,5561,32,5542,"RenderThread","com.google.android.permissioncontroller",521893072
+1021,5562,32,5542,"RenderThread","com.google.android.permissioncontroller",521893072
+1039,5579,32,5542,"Binder:5542_3","com.google.android.permissioncontroller",521893072
+1110,5605,32,5542,"queued-work-loo","com.google.android.permissioncontroller",521893072
+443,5283,22,5283,"d.process.acore","android.process.acore",388957949
+447,5288,22,5283,"Jit thread pool","android.process.acore",388957949
+448,5289,22,5283,"Signal Catcher","android.process.acore",388957949
+450,5294,22,5283,"FinalizerWatchd","android.process.acore",388957949
+451,5290,22,5283,"ADB-JDWP Connec","android.process.acore",388957949
+452,5295,22,5283,"HeapTaskDaemon","android.process.acore",388957949
+453,5293,22,5283,"FinalizerDaemon","android.process.acore",388957949
+454,5292,22,5283,"ReferenceQueueD","android.process.acore",388957949
+457,5297,22,5283,"Binder:5283_1","android.process.acore",388957949
+458,5298,22,5283,"Binder:5283_2","android.process.acore",388957949
+462,5299,22,5283,"Binder:5283_3","android.process.acore",388957949
+465,5301,22,5283,"Profile Saver","android.process.acore",388957949
+472,5302,22,5283,"Worker-1","android.process.acore",388957949
+477,5303,22,5283,"Worker-1","android.process.acore",388957949
+482,5304,22,5283,"Worker-1","android.process.acore",388957949
+484,5306,22,5283,"Worker-1","android.process.acore",388957949
+485,5307,22,5283,"Worker-1","android.process.acore",388957949
+721,5457,22,5283,"android.bg","android.process.acore",388957949
+248,105,145,105,"system","system",379031400
+105,990,93,626,"HwBinder:626_2","/vendor/bin/hw/android.hardware.graphics.allocator@2.0-service",337948219
+383,626,93,626,"allocator@2.0-s","/vendor/bin/hw/android.hardware.graphics.allocator@2.0-service",337948219
+384,983,93,626,"HwBinder:626_1","/vendor/bin/hw/android.hardware.graphics.allocator@2.0-service",337948219
+385,5270,93,626,"HwBinder:626_3","/vendor/bin/hw/android.hardware.graphics.allocator@2.0-service",337948219
+202,1175,135,864,"Binder:864_1","/system/bin/audioserver",335741587
+203,1481,135,864,"TimeCheckThread","/system/bin/audioserver",335741587
+494,1225,135,864,"AudioOut_D","/system/bin/audioserver",335741587
+495,1227,135,864,"AudioOut_15","/system/bin/audioserver",335741587
+496,1228,135,864,"AudioOut_1D","/system/bin/audioserver",335741587
+498,1230,135,864,"AudioOut_25","/system/bin/audioserver",335741587
+500,1231,135,864,"AudioOut_2D","/system/bin/audioserver",335741587
+501,1233,135,864,"AudioOut_35","/system/bin/audioserver",335741587
+517,1367,135,864,"soundTrigger cb","/system/bin/audioserver",335741587
+518,864,135,864,"audioserver","/system/bin/audioserver",335741587
+868,1174,135,864,"ApmOutput","/system/bin/audioserver",335741587
+873,1482,135,864,"Binder:864_3","/system/bin/audioserver",335741587
+1241,5712,135,864,"Binder:864_4","/system/bin/audioserver",335741587
+1242,1176,135,864,"Binder:864_2","/system/bin/audioserver",335741587
+1399,1224,135,864,"FastMixer","/system/bin/audioserver",335741587
+21,10,48,10,"rcuop/0","rcuop/0",335600708
+197,5192,36,5133,"Binder:5133_4","android.process.media",299474876
+366,5154,36,5133,"Okio Watchdog","android.process.media",299474876
+931,5133,36,5133,"d.process.media","android.process.media",299474876
+1293,5145,36,5133,"Binder:5133_1","android.process.media",299474876
+1294,5147,36,5133,"Binder:5133_3","android.process.media",299474876
+1295,5146,36,5133,"Binder:5133_2","android.process.media",299474876
+1320,5144,36,5133,"HeapTaskDaemon","android.process.media",299474876
+1378,5138,36,5133,"Jit thread pool","android.process.media",299474876
+1385,5141,36,5133,"ReferenceQueueD","android.process.media",299474876
+1387,5142,36,5133,"FinalizerDaemon","android.process.media",299474876
+1388,5143,36,5133,"FinalizerWatchd","android.process.media",299474876
+1508,5936,36,5133,"Binder:5133_5","android.process.media",299474876
+1598,6018,36,5133,"Binder:5133_6","android.process.media",299474876
+108,4494,91,4494,"mdss_fb0","mdss_fb0",290944157
+296,2539,160,920,"Binder:920_3","/system/bin/cameraserver",285767510
+916,920,160,920,"cameraserver","/system/bin/cameraserver",285767510
+1161,5645,160,920,"C3Dev-0-Status","/system/bin/cameraserver",285767510
+1162,5647,160,920,"CDU-0-FrameProc","/system/bin/cameraserver",285767510
+1163,5646,160,920,"C3Dev-0-ReqQueu","/system/bin/cameraserver",285767510
+1324,1088,160,920,"HwBinder:920_1","/system/bin/cameraserver",285767510
+44,217,63,217,"kworker/2:1","kworker/2:1",275251650
+668,5416,26,5416,"oogle.vr.vrcore","com.google.vr.vrcore",270533097
+673,5421,26,5416,"Jit thread pool","com.google.vr.vrcore",270533097
+674,5422,26,5416,"Signal Catcher","com.google.vr.vrcore",270533097
+675,5423,26,5416,"ADB-JDWP Connec","com.google.vr.vrcore",270533097
+677,5428,26,5416,"HeapTaskDaemon","com.google.vr.vrcore",270533097
+678,5427,26,5416,"FinalizerWatchd","com.google.vr.vrcore",270533097
+679,5426,26,5416,"FinalizerDaemon","com.google.vr.vrcore",270533097
+680,5425,26,5416,"ReferenceQueueD","com.google.vr.vrcore",270533097
+681,5429,26,5416,"Binder:5416_1","com.google.vr.vrcore",270533097
+682,5430,26,5416,"Binder:5416_2","com.google.vr.vrcore",270533097
+683,5431,26,5416,"Binder:5416_3","com.google.vr.vrcore",270533097
+684,5432,26,5416,"Profile Saver","com.google.vr.vrcore",270533097
+689,5436,26,5416,"queued-work-loo","com.google.vr.vrcore",270533097
+690,5437,26,5416,"GAC_Executor[0]","com.google.vr.vrcore",270533097
+693,5438,26,5416,"Primes-init-1","com.google.vr.vrcore",270533097
+695,5440,26,5416,"AsyncTask #1","com.google.vr.vrcore",270533097
+696,5442,26,5416,"SharedPreferenc","com.google.vr.vrcore",270533097
+697,5441,26,5416,"GAC_Executor[1]","com.google.vr.vrcore",270533097
+164,4358,21,2470,"Binder:2470_10","com.google.process.gservices",248908946
+445,2750,21,2470,"Binder:2470_7","com.google.process.gservices",248908946
+446,2470,21,2470,"[NULL]","com.google.process.gservices",248908946
+505,2492,21,2470,"HeapTaskDaemon","com.google.process.gservices",248908946
+1070,4270,21,2470,"Binder:2470_F","com.google.process.gservices",248908946
+1071,3878,21,2470,"Binder:2470_D","com.google.process.gservices",248908946
+1072,4192,21,2470,"Binder:2470_E","com.google.process.gservices",248908946
+1073,2493,21,2470,"Binder:2470_1","com.google.process.gservices",248908946
+1074,2667,21,2470,"Binder:2470_5","com.google.process.gservices",248908946
+1075,2709,21,2470,"Binder:2470_6","com.google.process.gservices",248908946
+1076,3753,21,2470,"Binder:2470_C","com.google.process.gservices",248908946
+1077,2501,21,2470,"Binder:2470_2","com.google.process.gservices",248908946
+1171,2489,21,2470,"ReferenceQueueD","com.google.process.gservices",248908946
+1178,2490,21,2470,"FinalizerDaemon","com.google.process.gservices",248908946
+1179,2491,21,2470,"FinalizerWatchd","com.google.process.gservices",248908946
+1182,3075,21,2470,"Binder:2470_A","com.google.process.gservices",248908946
+1183,3708,21,2470,"Binder:2470_B","com.google.process.gservices",248908946
+1184,2782,21,2470,"Binder:2470_8","com.google.process.gservices",248908946
+1185,2512,21,2470,"Binder:2470_3","com.google.process.gservices",248908946
+1186,2896,21,2470,"Binder:2470_9","com.google.process.gservices",248908946
+1187,2633,21,2470,"Binder:2470_4","com.google.process.gservices",248908946
+204,1483,136,757,"HwBinder:757_3","/vendor/bin/hw/android.hardware.audio@2.0-service",247532931
+499,757,136,757,"audio@2.0-servi","/vendor/bin/hw/android.hardware.audio@2.0-service",247532931
+520,5312,136,757,"audio@2.0-servi","/vendor/bin/hw/android.hardware.audio@2.0-service",247532931
+558,1168,136,757,"audio@2.0-servi","/vendor/bin/hw/android.hardware.audio@2.0-service",247532931
+743,1223,136,757,"HwBinder:757_2","/vendor/bin/hw/android.hardware.audio@2.0-service",247532931
+765,5485,136,757,"writer","/vendor/bin/hw/android.hardware.audio@2.0-service",247532931
+1400,5840,136,757,"writer","/vendor/bin/hw/android.hardware.audio@2.0-service",247532931
+667,6,200,6,"kworker/u16:0","kworker/u16:0",230962436
+41,905,60,905,"traced","/system/bin/traced",227754138
+1611,909,60,905,"traced","/system/bin/traced",227754138
+1,606,50,586,"logd.klogd","/system/bin/logd",215959701
+5,595,50,586,"logd.writer","/system/bin/logd",215959701
+480,607,50,586,"logd.auditd","/system/bin/logd",215959701
+481,591,50,586,"logd.daemon","/system/bin/logd",215959701
+1624,586,50,586,"[NULL]","/system/bin/logd",215959701
+1022,5563,33,5563,"ndroid.contacts","com.google.android.contacts",205871264
+1027,5568,33,5563,"Jit thread pool","com.google.android.contacts",205871264
+1028,5569,33,5563,"Signal Catcher","com.google.android.contacts",205871264
+1029,5570,33,5563,"ADB-JDWP Connec","com.google.android.contacts",205871264
+1030,5571,33,5563,"ReferenceQueueD","com.google.android.contacts",205871264
+1031,5572,33,5563,"FinalizerDaemon","com.google.android.contacts",205871264
+1032,5573,33,5563,"FinalizerWatchd","com.google.android.contacts",205871264
+1033,5574,33,5563,"HeapTaskDaemon","com.google.android.contacts",205871264
+1034,5575,33,5563,"Binder:5563_1","com.google.android.contacts",205871264
+1035,5576,33,5563,"Binder:5563_2","com.google.android.contacts",205871264
+1037,5577,33,5563,"Binder:5563_3","com.google.android.contacts",205871264
+1038,5578,33,5563,"Profile Saver","com.google.android.contacts",205871264
+1041,5581,33,5563,"Primes-init-1","com.google.android.contacts",205871264
+1042,5582,33,5563,"AsyncTask #1","com.google.android.contacts",205871264
+1045,5585,33,5563,"AsyncTask #2","com.google.android.contacts",205871264
+1048,5588,33,5563,"measurement-1","com.google.android.contacts",205871264
+1049,5589,33,5563,"GoogleApiHandle","com.google.android.contacts",205871264
+1050,5590,33,5563,"AsyncTask #3","com.google.android.contacts",205871264
+1051,5591,33,5563,"AsyncTask #4","com.google.android.contacts",205871264
+1052,5592,33,5563,"queued-work-loo","com.google.android.contacts",205871264
+1173,5656,33,5563,"Binder:5563_4","com.google.android.contacts",205871264
+27,860,46,860,"kworker/u16:14","kworker/u16:14",193101748
+46,2796,2,2712,"Monitor Thread ","com.android.vending",177335230
+47,2712,2,2712,"android.vending","com.android.vending",177335230
+54,3042,2,2712,"ChromiumNet","com.android.vending",177335230
+56,2815,2,2712,"BlockingExecuto","com.android.vending",177335230
+178,2744,2,2712,"Binder:2712_3","com.android.vending",177335230
+225,3019,2,2712,"CronetInit","com.android.vending",177335230
+226,5173,2,2712,"Binder:2712_6","com.android.vending",177335230
+785,3040,2,2712,"TaskSchedulerFo","com.android.vending",177335230
+812,3044,2,2712,"DnsConfigServic","com.android.vending",177335230
+829,3041,2,2712,"TaskSchedulerFo","com.android.vending",177335230
+924,5120,2,2712,".lowPriority #1","com.android.vending",177335230
+925,5124,2,2712,".lowPriority #2","com.android.vending",177335230
+1067,2719,2,2712,"Jit thread pool","com.android.vending",177335230
+1068,2945,2,2712,"queued-work-loo","com.android.vending",177335230
+1069,3177,2,2712,"Db-scheduler","com.android.vending",177335230
+1078,3394,2,2712,"ogging_store.db","com.android.vending",177335230
+1079,5593,2,2712,"acquisitions.db","com.android.vending",177335230
+1080,3000,2,2712,"libraries-threa","com.android.vending",177335230
+1081,4742,2,2712,"bgExecutor #3","com.android.vending",177335230
+1601,5117,2,2712,"Binder:2712_5","com.android.vending",177335230
+1602,2737,2,2712,"Binder:2712_1","com.android.vending",177335230
+1603,3887,2,2712,"Binder:2712_4","com.android.vending",177335230
+1604,2739,2,2712,"Binder:2712_2","com.android.vending",177335230
+1605,6020,2,2712,"Binder:2712_7","com.android.vending",177335230
+1613,2771,2,2712,"Profile Saver","com.android.vending",177335230
+1615,5125,2,2712,"Okio Watchdog","com.android.vending",177335230
+368,561,167,561,"kworker/u16:10","kworker/u16:10",162785755
+787,1165,212,968,"fingerprint@2.1","/vendor/bin/hw/android.hardware.biometrics.fingerprint@2.1-service.fpc",154062201
+1648,968,212,968,"[NULL]","/vendor/bin/hw/android.hardware.biometrics.fingerprint@2.1-service.fpc",154062201
+107,292,94,292,"kgsl_worker_thr","kgsl_worker_thr",151947892
+238,462,122,462,"kworker/u16:8","kworker/u16:8",150465902
+85,1028,78,935,"statsd.writer","/system/bin/statsd",128205711
+1626,935,78,935,"[NULL]","/system/bin/statsd",128205711
+749,1354,206,924,"Binder:924_3","/system/bin/installd",125398920
+1251,1381,206,924,"Binder:924_5","/system/bin/installd",125398920
+1266,1371,206,924,"Binder:924_4","/system/bin/installd",125398920
+1647,924,206,924,"[NULL]","/system/bin/installd",125398920
+396,360,179,360,"kworker/u16:6","kworker/u16:6",120714225
+16,7,39,7,"rcu_preempt","rcu_preempt",119952293
+1188,5659,35,5659,"e.process.gapps","com.google.process.gapps",116729960
+1193,5664,35,5659,"Jit thread pool","com.google.process.gapps",116729960
+1194,5665,35,5659,"Signal Catcher","com.google.process.gapps",116729960
+1195,5666,35,5659,"ADB-JDWP Connec","com.google.process.gapps",116729960
+1196,5669,35,5659,"FinalizerWatchd","com.google.process.gapps",116729960
+1197,5668,35,5659,"FinalizerDaemon","com.google.process.gapps",116729960
+1198,5667,35,5659,"ReferenceQueueD","com.google.process.gapps",116729960
+1199,5670,35,5659,"HeapTaskDaemon","com.google.process.gapps",116729960
+1200,5671,35,5659,"Binder:5659_1","com.google.process.gapps",116729960
+1201,5672,35,5659,"Binder:5659_2","com.google.process.gapps",116729960
+1206,5677,35,5659,"Binder:5659_3","com.google.process.gapps",116729960
+1207,5678,35,5659,"Profile Saver","com.google.process.gapps",116729960
+1221,5692,35,5659,"RefQueueWorker@","com.google.process.gapps",116729960
+43,665,61,665,"kworker/0:3","kworker/0:3",106548861
+364,568,165,568,"irq/760-synapti","irq/760-synapti",106209494
+550,193,195,193,"spi_wdsp","spi_wdsp",100615236
+2,253,49,253,"kworker/3:1","kworker/3:1",92350845
+284,5252,14,5252,"android.ramdump","com.android.ramdump",88012042
+285,5257,14,5252,"Jit thread pool","com.android.ramdump",88012042
+286,5258,14,5252,"Signal Catcher","com.android.ramdump",88012042
+287,5262,14,5252,"FinalizerWatchd","com.android.ramdump",88012042
+288,5263,14,5252,"HeapTaskDaemon","com.android.ramdump",88012042
+289,5261,14,5252,"FinalizerDaemon","com.android.ramdump",88012042
+290,5260,14,5252,"ReferenceQueueD","com.android.ramdump",88012042
+291,5259,14,5252,"ADB-JDWP Connec","com.android.ramdump",88012042
+292,5264,14,5252,"Binder:5252_1","com.android.ramdump",88012042
+294,5265,14,5252,"Binder:5252_2","com.android.ramdump",88012042
+297,5266,14,5252,"Binder:5252_3","com.android.ramdump",88012042
+299,5267,14,5252,"Profile Saver","com.android.ramdump",88012042
+302,5269,14,5252,"queued-work-loo","com.android.ramdump",88012042
+644,5400,14,5252,"android.bg","com.android.ramdump",88012042
+274,734,58,734,"main","zygote64",84352921
+280,5256,58,734,"HeapTaskDaemon","zygote64",84352921
+281,5255,58,734,"FinalizerWatchd","zygote64",84352921
+282,5254,58,734,"FinalizerDaemon","zygote64",84352921
+283,5253,58,734,"ReferenceQueueD","zygote64",84352921
+439,5287,58,734,"HeapTaskDaemon","zygote64",84352921
+440,5286,58,734,"FinalizerWatchd","zygote64",84352921
+441,5285,58,734,"FinalizerDaemon","zygote64",84352921
+442,5284,58,734,"ReferenceQueueD","zygote64",84352921
+669,5418,58,734,"FinalizerDaemon","zygote64",84352921
+670,5417,58,734,"ReferenceQueueD","zygote64",84352921
+671,5420,58,734,"HeapTaskDaemon","zygote64",84352921
+672,5419,58,734,"FinalizerWatchd","zygote64",84352921
+949,5507,58,734,"ReferenceQueueD","zygote64",84352921
+951,5508,58,734,"FinalizerDaemon","zygote64",84352921
+952,5509,58,734,"FinalizerWatchd","zygote64",84352921
+953,5510,58,734,"HeapTaskDaemon","zygote64",84352921
+1000,5546,58,734,"HeapTaskDaemon","zygote64",84352921
+1001,5545,58,734,"FinalizerWatchd","zygote64",84352921
+1002,5544,58,734,"FinalizerDaemon","zygote64",84352921
+1003,5543,58,734,"ReferenceQueueD","zygote64",84352921
+1023,5564,58,734,"ReferenceQueueD","zygote64",84352921
+1024,5565,58,734,"FinalizerDaemon","zygote64",84352921
+1025,5567,58,734,"HeapTaskDaemon","zygote64",84352921
+1026,5566,58,734,"FinalizerWatchd","zygote64",84352921
+1189,5660,58,734,"ReferenceQueueD","zygote64",84352921
+1190,5661,58,734,"FinalizerDaemon","zygote64",84352921
+1191,5662,58,734,"FinalizerWatchd","zygote64",84352921
+1192,5663,58,734,"HeapTaskDaemon","zygote64",84352921
+1269,5741,58,734,"HeapTaskDaemon","zygote64",84352921
+1270,5740,58,734,"FinalizerWatchd","zygote64",84352921
+1271,5739,58,734,"FinalizerDaemon","zygote64",84352921
+1274,5738,58,734,"ReferenceQueueD","zygote64",84352921
+83,587,77,587,"servicemanager","/system/bin/servicemanager",79206880
+177,3672,17,3657,"Binder:3657_2","com.google.android.inputmethod.latin",77776147
+359,3657,17,3657,"putmethod.latin","com.google.android.inputmethod.latin",77776147
+417,3688,17,3657,"MetricsManager","com.google.android.inputmethod.latin",77776147
+418,3673,17,3657,"Binder:3657_3","com.google.android.inputmethod.latin",77776147
+419,3671,17,3657,"Binder:3657_1","com.google.android.inputmethod.latin",77776147
+421,3677,17,3657,"queued-work-loo","com.google.android.inputmethod.latin",77776147
+424,5274,17,3657,"AsyncTask #1","com.google.android.inputmethod.latin",77776147
+488,3701,17,3657,"NativeLogger-1","com.google.android.inputmethod.latin",77776147
+489,4340,17,3657,"DecoderWrapper","com.google.android.inputmethod.latin",77776147
+604,4808,17,3657,"Binder:3657_5","com.google.android.inputmethod.latin",77776147
+831,4287,17,3657,"OkHttp Dispatch","com.google.android.inputmethod.latin",77776147
+832,4238,17,3657,"OkHttp Http2Con","com.google.android.inputmethod.latin",77776147
+835,4239,17,3657,"Okio Watchdog","com.google.android.inputmethod.latin",77776147
+922,4338,17,3657,"DFacilitator-1","com.google.android.inputmethod.latin",77776147
+1525,3662,17,3657,"Jit thread pool","com.google.android.inputmethod.latin",77776147
+1526,3674,17,3657,"Profile Saver","com.google.android.inputmethod.latin",77776147
+8,739,45,739,"kworker/u16:12","kworker/u16:12",75191272
+158,2505,28,2024,"Binder:2024_3","com.google.android.ext.services",70194314
+350,2024,28,2024,"id.ext.services","com.google.android.ext.services",70194314
+839,2031,28,2024,"Jit thread pool","com.google.android.ext.services",70194314
+1380,2040,28,2024,"Binder:2024_1","com.google.android.ext.services",70194314
+1510,2052,28,2024,"Profile Saver","com.google.android.ext.services",70194314
+26,87,43,87,"smem_native_rpm","smem_native_rpm",66468457
+1089,2195,226,930,"Binder:930_3","media.extractor",65836741
+1146,930,226,930,"mediaextractor","media.extractor",65836741
+55,588,69,588,"hwservicemanage","/system/bin/hwservicemanager",63243286
+397,877,174,877,"kworker/u16:15","kworker/u16:15",62642499
+141,2188,106,2188,"cds_mc_thread","cds_mc_thread",58715477
+24,592,44,592,"sugov:0","sugov:0",57337287
+42,42,101,42,"kworker/4:0","kworker/4:0",53199534
+295,866,156,866,"lmkd","/system/bin/lmkd",50165676
+1620,859,253,859,"rmt_storage","/vendor/bin/rmt_storage",49808599
+1621,1183,253,859,"rmt_storage","/vendor/bin/rmt_storage",49808599
+72,641,75,641,"jbd2/sda45-8","jbd2/sda45-8",49714183
+211,849,140,849,"msm_irqbalance","/vendor/bin/msm_irqbalance",46455318
+79,749,79,749,"suspend@1.0-ser","/system/bin/hw/android.system.suspend@1.0-service",43663325
+22,28,42,28,"rcuop/2","rcuop/2",40951065
+142,767,137,767,"light@2.0-servi","/vendor/bin/hw/android.hardware.light@2.0-service",39666625
+52,1815,15,1815,"m.android.phone","com.android.phone",37507869
+153,1829,15,1815,"Binder:1815_1","com.android.phone",37507869
+637,2133,15,1815,"Binder:1815_8","com.android.phone",37507869
+1366,1822,15,1815,"Jit thread pool","com.android.phone",37507869
+1367,1872,15,1815,"Profile Saver","com.android.phone",37507869
+174,2585,29,2557,"Binder:2557_3","com.google.android.apps.pixelmigrate",35978391
+793,2557,29,2557,"ps.pixelmigrate","com.google.android.apps.pixelmigrate",35978391
+820,2565,29,2557,"Jit thread pool","com.google.android.apps.pixelmigrate",35978391
+821,2600,29,2557,"Profile Saver","com.google.android.apps.pixelmigrate",35978391
+890,2758,29,2557,"queued-work-loo","com.google.android.apps.pixelmigrate",35978391
+1404,2578,29,2557,"Binder:2557_2","com.google.android.apps.pixelmigrate",35978391
+163,2399,20,2383,"Binder:2383_3","com.google.android.googlequicksearchbox:interactor",32259686
+410,2383,20,2383,"hbox:interactor","com.google.android.googlequicksearchbox:interactor",32259686
+411,2386,20,2383,"Jit thread pool","com.google.android.googlequicksearchbox:interactor",32259686
+420,5273,20,2383,"GELServices0","com.google.android.googlequicksearchbox:interactor",32259686
+564,4318,20,2383,"queued-work-loo","com.google.android.googlequicksearchbox:interactor",32259686
+93,795,81,795,"power@1.2-servi","/vendor/bin/hw/android.hardware.power@1.2-service.wahoo-libperfmgr",29634741
+96,2330,81,795,"NodeLooperThrea","/vendor/bin/hw/android.hardware.power@1.2-service.wahoo-libperfmgr",29634741
+99,2331,81,795,"power@1.2-servi","/vendor/bin/hw/android.hardware.power@1.2-service.wahoo-libperfmgr",29634741
+701,933,202,933,"mediaserver","/system/bin/mediaserver",28837457
+702,1931,202,933,"Binder:933_3","/system/bin/mediaserver",28837457
+703,1139,202,933,"Binder:933_1","/system/bin/mediaserver",28837457
+704,1930,202,933,"Binder:933_2","/system/bin/mediaserver",28837457
+705,5445,202,933,"Binder:933_4","/system/bin/mediaserver",28837457
+706,5446,202,933,"Binder:933_5","/system/bin/mediaserver",28837457
+75,713,84,707,"netd","/system/bin/netd",28341775
+122,721,84,707,"netd","/system/bin/netd",28341775
+151,714,84,707,"netd","/system/bin/netd",28341775
+646,718,84,707,"netd","/system/bin/netd",28341775
+647,5401,84,707,"netd","/system/bin/netd",28341775
+676,5424,84,707,"netd","/system/bin/netd",28341775
+777,724,84,707,"Binder:707_3","/system/bin/netd",28341775
+817,715,84,707,"netd","/system/bin/netd",28341775
+818,723,84,707,"Binder:707_2","/system/bin/netd",28341775
+1628,707,84,707,"[NULL]","/system/bin/netd",28341775
+522,83,189,83,"smem_native_lpa","smem_native_lpa",25394851
+23,36,55,36,"rcuop/3","rcuop/3",25286302
+521,84,188,84,"lpass_smem_glin","lpass_smem_glin",21108382
+398,738,175,738,"kworker/u16:11","kworker/u16:11",19811607
+125,188,97,188,"vsync_retire_wo","vsync_retire_wo",19256755
+58,20,70,20,"rcuop/1","rcuop/1",19090257
+298,215,157,215,"hwrng","hwrng",18838324
+104,2287,100,2287,"irq/35-1008000.","irq/35-1008000.",18035090
+19,60,54,60,"rcuop/6","rcuop/6",17623175
+15,8,51,8,"rcu_sched","rcu_sched",17556886
+165,2427,16,2405,"Binder:2405_2","com.android.nfc",17234063
+353,2405,16,2405,"com.android.nfc","com.android.nfc",17234063
+354,2724,16,2405,"AsyncTask #1","com.android.nfc",17234063
+361,2703,16,2405,"AsyncTask #1","com.android.nfc",17234063
+363,2736,16,2405,"HwBinder:2405_1","com.android.nfc",17234063
+176,2625,30,2586,"Binder:2586_2","com.google.android.as",17085108
+794,2586,30,2586,"ogle.android.as","com.google.android.as",17085108
+1405,2630,30,2586,"Binder:2586_3","com.google.android.as",17085108
+131,875,105,855,"sensors.qcom","/vendor/bin/sensors.qcom",16853030
+239,884,105,855,"sensors.qcom","/vendor/bin/sensors.qcom",16853030
+723,874,105,855,"sensors.qcom","/vendor/bin/sensors.qcom",16853030
+1629,855,105,855,"[NULL]","/vendor/bin/sensors.qcom",16853030
+33,18,67,18,"kworker/1:0","kworker/1:0",16450528
+348,735,65,735,"main","zygote",16213076
+531,5316,65,735,"FinalizerWatchd","zygote",16213076
+532,5315,65,735,"FinalizerDaemon","zygote",16213076
+533,5317,65,735,"HeapTaskDaemon","zygote",16213076
+534,5314,65,735,"ReferenceQueueD","zygote",16213076
+618,5378,65,735,"ReferenceQueueD","zygote",16213076
+619,5379,65,735,"FinalizerDaemon","zygote",16213076
+621,5381,65,735,"FinalizerWatchd","zygote",16213076
+622,5382,65,735,"HeapTaskDaemon","zygote",16213076
+34,3,59,3,"ksoftirqd/0","ksoftirqd/0",15973387
+189,5031,10,4716,"Binder:4716_4","com.google.android.youtube",15832867
+201,4716,10,4716,"android.youtube","com.google.android.youtube",15832867
+232,4774,10,4716,"ConnectivityThr","com.google.android.youtube",15832867
+236,4813,10,4716,"CronetInit","com.google.android.youtube",15832867
+262,4827,10,4716,"TaskSchedulerSe","com.google.android.youtube",15832867
+263,4831,10,4716,"TaskSchedulerFo","com.google.android.youtube",15832867
+264,4828,10,4716,"TaskSchedulerBa","com.google.android.youtube",15832867
+265,4832,10,4716,"TaskSchedulerFo","com.google.android.youtube",15832867
+266,4829,10,4716,"TaskSchedulerBa","com.google.android.youtube",15832867
+267,4992,10,4716,"TaskSchedulerFo","com.google.android.youtube",15832867
+268,4843,10,4716,"TaskSchedulerFo","com.google.android.youtube",15832867
+816,4837,10,4716,"DnsConfigServic","com.google.android.youtube",15832867
+926,4834,10,4716,"ChromiumNet","com.google.android.youtube",15832867
+928,4858,10,4716,"RxIoScheduler-1","com.google.android.youtube",15832867
+1450,5885,10,4716,"TaskSchedulerFo","com.google.android.youtube",15832867
+1451,5886,10,4716,"TaskSchedulerFo","com.google.android.youtube",15832867
+1452,5884,10,4716,"TaskSchedulerBa","com.google.android.youtube",15832867
+1614,4844,10,4716,"Network File Th","com.google.android.youtube",15832867
+519,748,192,748,"allocator@1.0-s","/system/bin/hw/android.hidl.allocator@1.0-service",15704215
+208,937,117,937,"wificond","/system/bin/wificond",15345262
+49,5098,27,5071,"RxSchedulerPurg","com.android.vending:instant_app_installer",15183338
+196,5118,27,5071,"Binder:5071_5","com.android.vending:instant_app_installer",15183338
+716,5076,27,5071,"Jit thread pool","com.android.vending:instant_app_installer",15183338
+717,5071,27,5071,"[NULL]","com.android.vending:instant_app_installer",15183338
+1504,5932,250,5932,"mdss_fb0","mdss_fb0",15134014
+25,33,56,33,"ksoftirqd/3","ksoftirqd/3",14923229
+237,44,141,44,"rcuop/4","rcuop/4",14607086
+1551,4795,251,4795,"kworker/2:3","kworker/2:3",14394787
+666,829,201,829,"kworker/u16:13","kworker/u16:13",13106411
+111,777,92,777,"memtrack@1.0-se","/vendor/bin/hw/android.hardware.memtrack@1.0-service",12793649
+31,17,66,17,"ksoftirqd/1","ksoftirqd/1",12746514
+199,68,144,68,"rcuop/7","rcuop/7",11663380
+242,640,152,640,"kworker/7:2","kworker/7:2",11563228
+355,781,164,781,"nfc@1.1-service","/vendor/bin/hw/android.hardware.nfc@1.1-service",11324160
+356,2763,164,781,"nfc@1.1-service","/vendor/bin/hw/android.hardware.nfc@1.1-service",11324160
+357,2765,164,781,"nfc@1.1-service","/vendor/bin/hw/android.hardware.nfc@1.1-service",11324160
+360,2762,164,781,"nfc@1.1-service","/vendor/bin/hw/android.hardware.nfc@1.1-service",11324160
+186,4588,127,4572,"Binder:4572_2","com.google.android.videos",10846095
+303,4572,127,4572,".android.videos","com.google.android.videos",10846095
+150,2119,19,2104,"Binder:2104_2","com.google.android.euicc",10600157
+388,2116,19,2104,"HeapTaskDaemon","com.google.android.euicc",10600157
+389,2104,19,2104,"[NULL]","com.google.android.euicc",10600157
+390,2113,19,2104,"ReferenceQueueD","com.google.android.euicc",10600157
+391,2114,19,2104,"FinalizerDaemon","com.google.android.euicc",10600157
+392,2115,19,2104,"FinalizerWatchd","com.google.android.euicc",10600157
+53,782,68,747,"thermal-engine","/vendor/bin/thermal-engine",10386569
+124,768,68,747,"HwBinder:747_1","/vendor/bin/thermal-engine",10386569
+1625,747,68,747,"[NULL]","/vendor/bin/thermal-engine",10386569
+524,330,191,330,"spi2","spi2",10153284
+1111,521,228,521,"set_state_work","set_state_work",9652813
+135,85,138,85,"smem_native_dsp","smem_native_dsp",9464583
+1351,368,246,368,"rot_commitq_0_0","rot_commitq_0_0",9046302
+116,766,90,766,"health@2.0-serv","/vendor/bin/hw/android.hardware.health@2.0-service.wahoo",8993956
+213,2232,118,2232,"wpa_supplicant","/vendor/bin/hw/wpa_supplicant",8946564
+147,3215,7,1767,"Binder:1767_4",".dataservices",8929067
+215,1871,7,1767,"MainEventThread",".dataservices",8929067
+216,1767,7,1767,"[NULL]",".dataservices",8929067
+220,1868,7,1767,"ConnectivityThr",".dataservices",8929067
+221,1802,7,1767,"Binder:1767_3",".dataservices",8929067
+805,1789,7,1767,"Binder:1767_1",".dataservices",8929067
+134,86,99,86,"dsps_smem_glink","dsps_smem_glink",8925199
+549,807,194,807,"irq/254-wcd9xxx","irq/254-wcd9xxx",8525734
+1352,370,247,370,"rot_doneq_0_0","rot_doneq_0_0",8500466
+48,4,64,4,"kworker/0:0","kworker/0:0",8271980
+582,1603,197,1603,"webview_zygote","webview_zygote",8038281
+588,5349,197,1603,"ReferenceQueueD","webview_zygote",8038281
+589,5352,197,1603,"HeapTaskDaemon","webview_zygote",8038281
+590,5351,197,1603,"FinalizerWatchd","webview_zygote",8038281
+591,5350,197,1603,"FinalizerDaemon","webview_zygote",8038281
+206,415,147,415,"kworker/6:2","kworker/6:2",7999679
+249,52,146,52,"rcuop/5","rcuop/5",6847037
+70,610,72,610,"wlan_logging_th","wlan_logging_th",6831663
+1347,765,245,765,"gnss@1.0-servic","/vendor/bin/hw/android.hardware.gnss@1.0-service-qti",6572600
+1348,1649,245,765,"Loc_hal","/vendor/bin/hw/android.hardware.gnss@1.0-service-qti",6572600
+1353,1676,245,765,"Loc_hal","/vendor/bin/hw/android.hardware.gnss@1.0-service-qti",6572600
+1623,1674,245,765,"Loc_hal","/vendor/bin/hw/android.hardware.gnss@1.0-service-qti",6572600
+28,25,47,25,"ksoftirqd/2","ksoftirqd/2",6568908
+556,194,196,194,"wdsp_spi_glink_","wdsp_spi_glink_",6245167
+214,2259,120,1398,"lowi-server","lowi-server",6218334
+766,1406,120,1398,"lowi-server","lowi-server",6218334
+806,2260,120,1398,"lowi-server","lowi-server",6218334
+813,1403,120,1398,"lowi-server","lowi-server",6218334
+1635,1398,120,1398,"[NULL]","lowi-server",6218334
+74,926,86,926,"kworker/3:1H","kworker/3:1H",6151237
+36,329,107,329,"kworker/5:1","kworker/5:1",6129165
+209,13,116,13,"migration/0","migration/0",6019582
+269,1030,154,918,"netlink socket","/vendor/bin/ipacm",5797711
+271,1029,154,918,"ipacm","/vendor/bin/ipacm",5797711
+1645,918,154,918,"[NULL]","/vendor/bin/ipacm",5797711
+1117,1329,235,944,"rild","/vendor/bin/hw/rild",5642917
+1459,1316,235,944,"rild","/vendor/bin/hw/rild",5642917
+1460,1188,235,944,"rild","/vendor/bin/hw/rild",5642917
+1652,944,235,944,"[NULL]","/vendor/bin/hw/rild",5642917
+293,5232,159,5232,"adbd","/system/bin/adbd",5559584
+1345,5798,244,5798,"rot_fenceq_0_0","rot_fenceq_0_0",5520255
+123,24,96,24,"migration/2","migration/2",4888326
+1330,345,242,345,"irq/262-vl53l0_","irq/262-vl53l0_",4656812
+843,1084,222,1084,"kworker/u17:1","kworker/u17:1",4391826
+387,32,171,32,"migration/3","migration/3",4379169
+341,11,158,11,"rcuos/0","rcuos/0",4111771
+77,1,40,1,"init","/system/bin/init",3984013
+415,16,176,16,"migration/1","migration/1",3864697
+698,94,203,94,"irq/126-cpr3","irq/126-cpr3",3853854
+279,61,155,61,"rcuos/6","rcuos/6",3755260
+1091,1066,231,921,"Binder:921_1","/system/bin/drmserver",3717808
+1651,921,231,921,"[NULL]","/system/bin/drmserver",3717808
+810,5492,216,5492,"kworker/3:4","kworker/3:4",3522241
+184,5190,18,4431,"Binder:4431_5","com.google.android.setupwizard",3362133
+231,4431,18,4431,"oid.setupwizard","com.google.android.setupwizard",3362133
+866,1061,223,931,"Binder:931_1","media.metrics",3343382
+1650,931,223,931,"[NULL]","media.metrics",3343382
+352,1948,163,1948,"kworker/2:2","kworker/2:2",3278172
+200,5205,12,5193,"Binder:5193_1","com.google.android.apps.turbo",2687762
+258,5204,12,5193,"HeapTaskDaemon","com.google.android.apps.turbo",2687762
+259,5193,12,5193,"roid.apps.turbo","com.google.android.apps.turbo",2687762
+877,5207,12,5193,"Binder:5193_3","com.google.android.apps.turbo",2687762
+878,5229,12,5193,"Binder:5193_4","com.google.android.apps.turbo",2687762
+45,80,62,80,"kworker/0:1","kworker/0:1",2316250
+219,1006,148,913,"HwBinder:913_1","/vendor/bin/cnd",2234739
+224,913,148,913,"cnd","/vendor/bin/cnd",2234739
+17,29,52,29,"rcuos/2","rcuos/2",2107032
+778,711,209,711,"iptables-restor","/system/bin/iptables-restore",1913334
+803,3776,213,3776,"kworker/3:3","kworker/3:3",1896459
+395,545,173,545,"kworker/6:1H","kworker/6:1H",1883224
+159,1490,142,806,"HwBinder:806_1","/vendor/bin/hw/android.hardware.usb@1.1-service.wahoo",1785000
+1642,806,142,806,"[NULL]","/vendor/bin/hw/android.hardware.usb@1.1-service.wahoo",1785000
+486,21,185,21,"rcuos/1","rcuos/1",1652702
+365,546,166,546,"kworker/4:1H","kworker/4:1H",1630985
+814,1071,214,914,"netmgrd","/vendor/bin/netmgrd",1580886
+815,1162,214,914,"netmgrd","/vendor/bin/netmgrd",1580886
+1649,914,214,914,"[NULL]","/vendor/bin/netmgrd",1580886
+460,761,180,761,"contexthub@1.0-","/vendor/bin/hw/android.hardware.contexthub@1.0-service",1580624
+474,794,180,761,"contexthub@1.0-","/vendor/bin/hw/android.hardware.contexthub@1.0-service",1580624
+386,45,170,45,"rcuos/4","rcuos/4",1510723
+40,49,108,49,"ksoftirqd/5","ksoftirqd/5",1440728
+842,813,221,813,"vibrator@1.2-se","/vendor/bin/hw/android.hardware.vibrator@1.2-service.wahoo",1428749
+487,1946,186,625,"HwBinder:625_2","/vendor/bin/hw/android.hardware.configstore@1.2-service",1419479
+1646,625,186,625,"[NULL]","/vendor/bin/hw/android.hardware.configstore@1.2-service",1419479
+179,3875,11,3862,"Binder:3862_1","com.google.android.ims",1399063
+233,3917,11,3862,"ConnectivityThr","com.google.android.ims",1399063
+234,3862,11,3862,"[NULL]","com.google.android.ims",1399063
+790,4140,11,3862,"WebRtcVolumeLev","com.google.android.ims",1399063
+63,41,102,41,"ksoftirqd/4","ksoftirqd/4",1389897
+80,756,85,756,"kworker/1:1H","kworker/1:1H",1334268
+181,4535,8,4007,"Binder:4007_4","com.google.android.connectivitymonitor",1253492
+227,4088,8,4007,"ConnectivityThr","com.google.android.connectivitymonitor",1253492
+228,4007,8,4007,"[NULL]","com.google.android.connectivitymonitor",1253492
+260,547,153,547,"kworker/7:1H","kworker/7:1H",1252138
+155,613,121,604,"Binder:604_2","/system/bin/vold",1173387
+250,703,121,604,"Binder:604_4","/system/bin/vold",1173387
+1636,604,121,604,"[NULL]","/system/bin/vold",1173387
+508,64,187,64,"migration/7","migration/7",1159275
+51,65,88,65,"ksoftirqd/7","ksoftirqd/7",1113747
+351,69,162,69,"rcuos/7","rcuos/7",1101406
+461,962,183,962,"chre","/vendor/bin/chre",1097968
+473,1132,183,962,"chre","/vendor/bin/chre",1097968
+779,712,210,712,"ip6tables-resto","/system/bin/ip6tables-restore",1078437
+394,40,178,40,"migration/4","migration/4",1049219
+370,549,168,549,"kworker/5:1H","kworker/5:1H",937763
+1155,589,227,589,"vndservicemanag","/vendor/bin/vndservicemanager",918385
+175,3558,34,3543,"Binder:3543_2","com.google.android.gms.unstable",865106
+1083,3543,34,3543,"id.gms.unstable","com.google.android.gms.unstable",865106
+300,56,161,56,"migration/6","migration/6",852711
+1118,459,229,459,"irq/226-bcm1560","irq/226-bcm1560",814738
+73,737,76,737,"kworker/2:1H","kworker/2:1H",772971
+545,559,193,559,"kworker/0:1H","kworker/0:1H",752236
+809,2,38,2,"kthreadd","kthreadd",734166
+247,927,149,927,"keystore","/system/bin/keystore",721094
+62,14,73,14,"watchdog/0","watchdog/0",694114
+18,37,53,37,"rcuos/3","rcuos/3",591927
+767,411,207,411,"kworker/1:1","kworker/1:1",570470
+786,321,211,321,"irq/286-soc:fp_","irq/286-soc:fp_",570414
+393,53,169,53,"rcuos/5","rcuos/5",472133
+66,31,71,31,"watchdog/3","watchdog/3",470833
+195,5049,134,5035,"Binder:5035_3","com.android.keychain",457189
+1641,5035,134,5035,"[NULL]","com.android.keychain",457189
+64,15,83,15,"watchdog/1","watchdog/1",455415
+146,1848,123,1623,"Binder:1623_3","com.google.modemservice",426041
+1637,1623,123,1623,"[NULL]","com.google.modemservice",426041
+1145,81,234,81,"smem_native_mps","smem_native_mps",414167
+768,634,208,634,"kworker/1:3","kworker/1:3",388280
+479,597,184,597,"kauditd","kauditd",377498
+382,48,172,48,"migration/5","migration/5",370572
+65,23,74,23,"watchdog/2","watchdog/2",342031
+170,3890,125,3526,"Binder:3526_5","com.google.android.apps.messaging",340676
+1638,3526,125,3526,"[NULL]","com.google.android.apps.messaging",340676
+157,564,139,564,"ueventd","/system/bin/ueventd",326822
+156,1867,113,1852,"Binder:1852_1","com.qualcomm.qcrilmsgtunnel",316457
+1631,1852,113,1852,"[NULL]","com.qualcomm.qcrilmsgtunnel",316457
+193,5230,133,4995,"Binder:4995_4","com.google.android.apps.messaging:rcs",305835
+1640,4995,133,4995,"[NULL]","com.google.android.apps.messaging:rcs",305835
+121,492,95,492,"irq/747-ima-rdy","irq/747-ima-rdy",305308
+191,4927,131,4912,"Binder:4912_1","com.qualcomm.telephony",303488
+1639,4912,131,4912,"[NULL]","com.qualcomm.telephony",303488
+149,2377,112,1796,"Binder:1796_3","com.qualcomm.qti.telephonyservice",303385
+1630,1796,112,1796,"[NULL]","com.qualcomm.qti.telephonyservice",303385
+1142,82,233,82,"mpss_smem_glink","mpss_smem_glink",298386
+523,695,190,695,"msm_slim_qmi_cl","msm_slim_qmi_cl",285730
+173,2579,115,2534,"Binder:2534_2","com.google.intelligence.sense",280938
+1633,2534,115,2534,"[NULL]","com.google.intelligence.sense",280938
+198,2509,151,2452,"Binder:2452_3","com.google.SSRestartDetector",272813
+1644,2452,151,2452,"[NULL]","com.google.SSRestartDetector",272813
+166,2521,114,2421,"Binder:2421_3","com.android.se",270469
+1632,2421,114,2421,"[NULL]","com.android.se",270469
+194,3280,150,2439,"Binder:2439_4","com.android.ims.rcsservice",265937
+1643,2439,150,2439,"[NULL]","com.android.ims.rcsservice",265937
+735,872,204,872,"kworker/3:2","kworker/3:2",257036
+168,750,143,750,"healthd","/system/bin/healthd",250625
+69,55,111,55,"watchdog/6","watchdog/6",247083
+190,4896,130,4881,"Binder:4881_3","com.google.mds",242969
+1053,4881,130,4881,"com.google.mds","com.google.mds",242969
+841,91,220,91,"msm_watchdog","msm_watchdog",237864
+825,949,217,949,"cnss-daemon","/vendor/bin/cnss-daemon",237396
+192,4976,132,4964,"Binder:4964_1","com.tmobile.planprovider",228385
+1097,4964,132,4964,"le.planprovider","com.tmobile.planprovider",228385
+180,3951,126,3934,"Binder:3934_2","com.google.android.carrier",228281
+845,3934,126,3934,"android.carrier","com.google.android.carrier",228281
+188,4740,129,4689,"Binder:4689_4","com.google.android.wfcactivation",215626
+903,4689,129,4689,"d.wfcactivation","com.google.android.wfcactivation",215626
+456,520,182,520,"kworker/5:2","kworker/5:2",192500
+1622,1409,254,1399,"pcid-lo","xtra-daemon",189271
+1653,1399,254,1399,"[NULL]","xtra-daemon",189271
+167,5061,124,2963,"Binder:2963_8","com.google.process.gapps",179740
+933,2963,124,2963,"e.process.gapps","com.google.process.gapps",179740
+187,4666,128,4650,"Binder:4650_1","com.google.android.volta",173594
+891,4650,128,4650,"e.android.volta","com.google.android.volta",173594
+1160,528,232,528,"irq/758-mnh_pci","irq/758-mnh_pci",168855
+68,47,109,47,"watchdog/5","watchdog/5",161093
+67,39,103,39,"watchdog/4","watchdog/4",147342
+71,63,89,63,"watchdog/7","watchdog/7",144117
+641,201,199,201,"kworker/4:1","kworker/4:1",130885
+1302,5759,240,5759,"irq/164-arm-smm","irq/164-arm-smm",115989
+1064,667,224,667,"kworker/0:4","kworker/0:4",111771
+633,372,198,372,"kworker/4:3","kworker/4:3",103905
+1326,5780,243,5780,"ois_wq","ois_wq",99375
+1298,523,239,523,"irq/751-mnh_pci","irq/751-mnh_pci",90937
+1278,5745,236,5745,"irq/163-arm-smm","irq/163-arm-smm",86615
+1323,5778,241,5778,"irq/165-arm-smm","irq/165-arm-smm",72500
+808,34,215,34,"kworker/3:0","kworker/3:0",67917
+1124,522,230,522,"irq/227-mnh-rea","irq/227-mnh-rea",50365
+438,704,181,704,"kworker/5:3","kworker/5:3",47343
+838,1055,219,1055,"kworker/7:3","kworker/7:3",38178
+1297,526,238,526,"irq/754-mnh_pci","irq/754-mnh_pci",32136
+837,66,218,66,"kworker/7:0","kworker/7:0",28750
+1350,5800,249,5800,"irq/167-arm-smm","irq/167-arm-smm",23177
+1346,5799,248,5799,"irq/166-arm-smm","irq/166-arm-smm",19478
+1296,524,237,524,"irq/752-mnh_pci","irq/752-mnh_pci",14271
+1587,93,252,93,"kworker/u16:1","kworker/u16:1",10729
+0,0,"[NULL]","[NULL]","swapper/0","[NULL]","[NULL]"
+4,5243,"[NULL]","[NULL]","atrace","[NULL]","[NULL]"
+57,2817,"[NULL]","[NULL]","BlockingExecuto","[NULL]","[NULL]"
+275,5197,"[NULL]","[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
+276,5194,"[NULL]","[NULL]","ReferenceQueueD","[NULL]","[NULL]"
+277,5195,"[NULL]","[NULL]","FinalizerDaemon","[NULL]","[NULL]"
+278,5196,"[NULL]","[NULL]","FinalizerWatchd","[NULL]","[NULL]"
+301,5268,"[NULL]","[NULL]","Thread-2","[NULL]","[NULL]"
+305,4580,"[NULL]","[NULL]","Jit thread pool","[NULL]","[NULL]"
+306,4581,"[NULL]","[NULL]","Signal Catcher","[NULL]","[NULL]"
+307,4582,"[NULL]","[NULL]","ADB-JDWP Connec","[NULL]","[NULL]"
+308,4584,"[NULL]","[NULL]","FinalizerDaemon","[NULL]","[NULL]"
+309,4583,"[NULL]","[NULL]","ReferenceQueueD","[NULL]","[NULL]"
+310,4585,"[NULL]","[NULL]","FinalizerWatchd","[NULL]","[NULL]"
+311,4586,"[NULL]","[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
+312,4587,"[NULL]","[NULL]","Binder:4572_1","[NULL]","[NULL]"
+313,4701,"[NULL]","[NULL]","GAC_Executor[1]","[NULL]","[NULL]"
+314,4683,"[NULL]","[NULL]","GAC_Executor[0]","[NULL]","[NULL]"
+315,4676,"[NULL]","[NULL]","GoogleApiHandle","[NULL]","[NULL]"
+316,4669,"[NULL]","[NULL]","sync-1","[NULL]","[NULL]"
+317,4667,"[NULL]","[NULL]","pool-5-thread-1","[NULL]","[NULL]"
+318,4657,"[NULL]","[NULL]","ConnectivityThr","[NULL]","[NULL]"
+319,4653,"[NULL]","[NULL]","local-2","[NULL]","[NULL]"
+320,4645,"[NULL]","[NULL]","local-1","[NULL]","[NULL]"
+321,4643,"[NULL]","[NULL]","network-4","[NULL]","[NULL]"
+322,4640,"[NULL]","[NULL]","network-3","[NULL]","[NULL]"
+323,4639,"[NULL]","[NULL]","network-2","[NULL]","[NULL]"
+324,4638,"[NULL]","[NULL]","network-1","[NULL]","[NULL]"
+325,4635,"[NULL]","[NULL]","PlayEventLogger","[NULL]","[NULL]"
+326,4625,"[NULL]","[NULL]","queued-work-loo","[NULL]","[NULL]"
+327,4620,"[NULL]","[NULL]","tentative-gc-ru","[NULL]","[NULL]"
+328,4619,"[NULL]","[NULL]","Thread-11","[NULL]","[NULL]"
+329,4618,"[NULL]","[NULL]","Thread-10","[NULL]","[NULL]"
+330,4617,"[NULL]","[NULL]","Thread-9","[NULL]","[NULL]"
+331,4616,"[NULL]","[NULL]","Thread-8","[NULL]","[NULL]"
+332,4615,"[NULL]","[NULL]","Thread-7","[NULL]","[NULL]"
+333,4614,"[NULL]","[NULL]","RefQueueWorker@","[NULL]","[NULL]"
+334,4613,"[NULL]","[NULL]","Thread-5","[NULL]","[NULL]"
+335,4612,"[NULL]","[NULL]","Thread-4","[NULL]","[NULL]"
+336,4611,"[NULL]","[NULL]","Thread-3","[NULL]","[NULL]"
+337,4610,"[NULL]","[NULL]","RefQueueWorker@","[NULL]","[NULL]"
+338,4608,"[NULL]","[NULL]","movies_logging","[NULL]","[NULL]"
+339,4593,"[NULL]","[NULL]","Profile Saver","[NULL]","[NULL]"
+340,4589,"[NULL]","[NULL]","Binder:4572_3","[NULL]","[NULL]"
+412,5272,"[NULL]","[NULL]","applyRouting","[NULL]","[NULL]"
+432,5280,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+449,5291,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+455,5296,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+483,5305,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+506,5309,"[NULL]","[NULL]","gcm-task#1","[NULL]","[NULL]"
+526,5075,"[NULL]","[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
+527,5072,"[NULL]","[NULL]","ReferenceQueueD","[NULL]","[NULL]"
+528,5073,"[NULL]","[NULL]","FinalizerDaemon","[NULL]","[NULL]"
+529,5074,"[NULL]","[NULL]","FinalizerWatchd","[NULL]","[NULL]"
+548,5329,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+554,5331,"[NULL]","[NULL]","EGL Init","[NULL]","[NULL]"
+555,3607,"[NULL]","[NULL]","pool-4-thread-1","[NULL]","[NULL]"
+565,5337,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+570,5338,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+573,5340,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+575,5341,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+583,1613,"[NULL]","[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
+584,1610,"[NULL]","[NULL]","ReferenceQueueD","[NULL]","[NULL]"
+585,1611,"[NULL]","[NULL]","FinalizerDaemon","[NULL]","[NULL]"
+586,1612,"[NULL]","[NULL]","FinalizerWatchd","[NULL]","[NULL]"
+623,5383,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+642,5398,"[NULL]","[NULL]","gcm-task#1","[NULL]","[NULL]"
+653,5407,"[NULL]","[NULL]","IntentService[D","[NULL]","[NULL]"
+685,5433,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+686,5434,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+687,5435,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+694,5439,"[NULL]","[NULL]","Thread-25","[NULL]","[NULL]"
+715,5454,"[NULL]","[NULL]","netd","[NULL]","[NULL]"
+720,5456,"[NULL]","[NULL]","netd","[NULL]","[NULL]"
+724,5459,"[NULL]","[NULL]","sensors.qcom","[NULL]","[NULL]"
+728,5460,"[NULL]","[NULL]","netd","[NULL]","[NULL]"
+741,5469,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+742,5470,"[NULL]","[NULL]","netd","[NULL]","[NULL]"
+745,5472,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+747,5474,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+770,5097,"[NULL]","[NULL]","AsyncTask #5","[NULL]","[NULL]"
+771,5103,"[NULL]","[NULL]","AsyncTask #1","[NULL]","[NULL]"
+772,5108,"[NULL]","[NULL]","AsyncTask #2","[NULL]","[NULL]"
+773,5238,"[NULL]","[NULL]","pool-6-thread-1","[NULL]","[NULL]"
+774,2088,"[NULL]","[NULL]","AsyncTask #4","[NULL]","[NULL]"
+775,2283,"[NULL]","[NULL]","InflaterThread ","[NULL]","[NULL]"
+776,2282,"[NULL]","[NULL]","InflaterThread ","[NULL]","[NULL]"
+780,5239,"[NULL]","[NULL]","pool-7-thread-1","[NULL]","[NULL]"
+781,2329,"[NULL]","[NULL]","InflaterThread ","[NULL]","[NULL]"
+783,2281,"[NULL]","[NULL]","InflaterThread ","[NULL]","[NULL]"
+791,4143,"[NULL]","[NULL]","unnerJobService","[NULL]","[NULL]"
+802,5115,"[NULL]","[NULL]","TaskSchedulerFo","[NULL]","[NULL]"
+819,4230,"[NULL]","[NULL]","OkHttp Dispatch","[NULL]","[NULL]"
+824,4207,"[NULL]","[NULL]","oundTaskService","[NULL]","[NULL]"
+833,4237,"[NULL]","[NULL]","OkHttp Http2Con","[NULL]","[NULL]"
+834,4285,"[NULL]","[NULL]","oundTaskService","[NULL]","[NULL]"
+840,5494,"[NULL]","[NULL]","netd","[NULL]","[NULL]"
+846,3942,"[NULL]","[NULL]","Signal Catcher","[NULL]","[NULL]"
+847,3944,"[NULL]","[NULL]","ADB-JDWP Connec","[NULL]","[NULL]"
+848,3945,"[NULL]","[NULL]","ReferenceQueueD","[NULL]","[NULL]"
+849,3946,"[NULL]","[NULL]","FinalizerDaemon","[NULL]","[NULL]"
+850,3947,"[NULL]","[NULL]","FinalizerWatchd","[NULL]","[NULL]"
+851,3948,"[NULL]","[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
+852,4600,"[NULL]","[NULL]","queued-work-loo","[NULL]","[NULL]"
+853,3941,"[NULL]","[NULL]","Jit thread pool","[NULL]","[NULL]"
+854,3949,"[NULL]","[NULL]","Binder:3934_1","[NULL]","[NULL]"
+855,3954,"[NULL]","[NULL]","Binder:3934_3","[NULL]","[NULL]"
+856,3960,"[NULL]","[NULL]","Profile Saver","[NULL]","[NULL]"
+892,4659,"[NULL]","[NULL]","Jit thread pool","[NULL]","[NULL]"
+893,4660,"[NULL]","[NULL]","Signal Catcher","[NULL]","[NULL]"
+894,4663,"[NULL]","[NULL]","FinalizerDaemon","[NULL]","[NULL]"
+895,4664,"[NULL]","[NULL]","FinalizerWatchd","[NULL]","[NULL]"
+896,4668,"[NULL]","[NULL]","Binder:4650_2","[NULL]","[NULL]"
+897,4672,"[NULL]","[NULL]","Profile Saver","[NULL]","[NULL]"
+898,4684,"[NULL]","[NULL]","Binder:4650_3","[NULL]","[NULL]"
+899,4686,"[NULL]","[NULL]","queued-work-loo","[NULL]","[NULL]"
+900,4665,"[NULL]","[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
+901,4662,"[NULL]","[NULL]","ReferenceQueueD","[NULL]","[NULL]"
+902,4661,"[NULL]","[NULL]","ADB-JDWP Connec","[NULL]","[NULL]"
+904,4694,"[NULL]","[NULL]","Jit thread pool","[NULL]","[NULL]"
+905,4695,"[NULL]","[NULL]","Signal Catcher","[NULL]","[NULL]"
+906,4696,"[NULL]","[NULL]","ADB-JDWP Connec","[NULL]","[NULL]"
+907,4698,"[NULL]","[NULL]","FinalizerDaemon","[NULL]","[NULL]"
+908,4697,"[NULL]","[NULL]","ReferenceQueueD","[NULL]","[NULL]"
+909,4699,"[NULL]","[NULL]","FinalizerWatchd","[NULL]","[NULL]"
+910,4730,"[NULL]","[NULL]","queued-work-loo","[NULL]","[NULL]"
+911,4713,"[NULL]","[NULL]","Binder:4689_3","[NULL]","[NULL]"
+912,4709,"[NULL]","[NULL]","Profile Saver","[NULL]","[NULL]"
+913,4703,"[NULL]","[NULL]","Binder:4689_2","[NULL]","[NULL]"
+914,4702,"[NULL]","[NULL]","Binder:4689_1","[NULL]","[NULL]"
+915,4700,"[NULL]","[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
+917,5501,"[NULL]","[NULL]","netd","[NULL]","[NULL]"
+918,5504,"[NULL]","[NULL]","netd","[NULL]","[NULL]"
+919,5505,"[NULL]","[NULL]","netd","[NULL]","[NULL]"
+923,3434,"[NULL]","[NULL]","measurement-1","[NULL]","[NULL]"
+927,5126,"[NULL]","[NULL]",".lowPriority #3","[NULL]","[NULL]"
+929,5129,"[NULL]","[NULL]","AsyncTask #3","[NULL]","[NULL]"
+930,5131,"[NULL]","[NULL]","AsyncTask #4","[NULL]","[NULL]"
+932,2972,"[NULL]","[NULL]","FinalizerDaemon","[NULL]","[NULL]"
+934,2969,"[NULL]","[NULL]","Signal Catcher","[NULL]","[NULL]"
+935,2968,"[NULL]","[NULL]","Jit thread pool","[NULL]","[NULL]"
+936,2970,"[NULL]","[NULL]","ADB-JDWP Connec","[NULL]","[NULL]"
+937,2982,"[NULL]","[NULL]","Binder:2963_1","[NULL]","[NULL]"
+938,2971,"[NULL]","[NULL]","ReferenceQueueD","[NULL]","[NULL]"
+939,2992,"[NULL]","[NULL]","Profile Saver","[NULL]","[NULL]"
+940,2973,"[NULL]","[NULL]","FinalizerWatchd","[NULL]","[NULL]"
+941,4200,"[NULL]","[NULL]","Binder:2963_5","[NULL]","[NULL]"
+942,2974,"[NULL]","[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
+943,2985,"[NULL]","[NULL]","Binder:2963_2","[NULL]","[NULL]"
+944,2986,"[NULL]","[NULL]","Binder:2963_3","[NULL]","[NULL]"
+945,3073,"[NULL]","[NULL]","RefQueueWorker@","[NULL]","[NULL]"
+946,3513,"[NULL]","[NULL]","Binder:2963_4","[NULL]","[NULL]"
+947,4380,"[NULL]","[NULL]","Binder:2963_6","[NULL]","[NULL]"
+948,4476,"[NULL]","[NULL]","Binder:2963_7","[NULL]","[NULL]"
+956,4902,"[NULL]","[NULL]","pool-17-thread-","[NULL]","[NULL]"
+964,4873,"[NULL]","[NULL]","pool-17-thread-","[NULL]","[NULL]"
+965,4876,"[NULL]","[NULL]","pool-17-thread-","[NULL]","[NULL]"
+966,4904,"[NULL]","[NULL]","pool-17-thread-","[NULL]","[NULL]"
+967,4872,"[NULL]","[NULL]","pool-17-thread-","[NULL]","[NULL]"
+968,4903,"[NULL]","[NULL]","pool-17-thread-","[NULL]","[NULL]"
+969,4874,"[NULL]","[NULL]","pool-17-thread-","[NULL]","[NULL]"
+970,4901,"[NULL]","[NULL]","pool-17-thread-","[NULL]","[NULL]"
+971,4905,"[NULL]","[NULL]","pool-17-thread-","[NULL]","[NULL]"
+972,4906,"[NULL]","[NULL]","pool-17-thread-","[NULL]","[NULL]"
+974,5521,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+976,5523,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+982,3095,"[NULL]","[NULL]","AsyncTask #1","[NULL]","[NULL]"
+985,5158,"[NULL]","[NULL]","TaskSchedulerFo","[NULL]","[NULL]"
+986,5157,"[NULL]","[NULL]","TaskSchedulerBa","[NULL]","[NULL]"
+991,5535,"[NULL]","[NULL]","EGL Init","[NULL]","[NULL]"
+992,5064,"[NULL]","[NULL]","AsyncTask #5","[NULL]","[NULL]"
+1015,3140,"[NULL]","[NULL]","AsyncTask #3","[NULL]","[NULL]"
+1016,5558,"[NULL]","[NULL]","EGL Init","[NULL]","[NULL]"
+1036,4985,"[NULL]","[NULL]","dScanJobService","[NULL]","[NULL]"
+1040,5580,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1043,5583,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1044,5584,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1046,5586,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1047,5587,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1054,4887,"[NULL]","[NULL]","Jit thread pool","[NULL]","[NULL]"
+1055,4888,"[NULL]","[NULL]","Signal Catcher","[NULL]","[NULL]"
+1056,4889,"[NULL]","[NULL]","ADB-JDWP Connec","[NULL]","[NULL]"
+1057,4890,"[NULL]","[NULL]","ReferenceQueueD","[NULL]","[NULL]"
+1058,4891,"[NULL]","[NULL]","FinalizerDaemon","[NULL]","[NULL]"
+1059,4892,"[NULL]","[NULL]","FinalizerWatchd","[NULL]","[NULL]"
+1060,4893,"[NULL]","[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
+1061,4894,"[NULL]","[NULL]","Binder:4881_1","[NULL]","[NULL]"
+1062,4895,"[NULL]","[NULL]","Binder:4881_2","[NULL]","[NULL]"
+1063,4900,"[NULL]","[NULL]","Profile Saver","[NULL]","[NULL]"
+1066,5119,"[NULL]","[NULL]",".lowPriority #0","[NULL]","[NULL]"
+1082,5594,"[NULL]","[NULL]","sensors.qcom","[NULL]","[NULL]"
+1094,5603,"[NULL]","[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
+1095,5602,"[NULL]","[NULL]",".vorbis.decoder","[NULL]","[NULL]"
+1098,4969,"[NULL]","[NULL]","Jit thread pool","[NULL]","[NULL]"
+1099,4970,"[NULL]","[NULL]","Signal Catcher","[NULL]","[NULL]"
+1100,4971,"[NULL]","[NULL]","ADB-JDWP Connec","[NULL]","[NULL]"
+1101,4972,"[NULL]","[NULL]","ReferenceQueueD","[NULL]","[NULL]"
+1102,4973,"[NULL]","[NULL]","FinalizerDaemon","[NULL]","[NULL]"
+1103,4974,"[NULL]","[NULL]","FinalizerWatchd","[NULL]","[NULL]"
+1104,4975,"[NULL]","[NULL]","HeapTaskDaemon","[NULL]","[NULL]"
+1105,4977,"[NULL]","[NULL]","Binder:4964_2","[NULL]","[NULL]"
+1106,4978,"[NULL]","[NULL]","Binder:4964_3","[NULL]","[NULL]"
+1107,4980,"[NULL]","[NULL]","Profile Saver","[NULL]","[NULL]"
+1120,5612,"[NULL]","[NULL]","CAM_startsensor","[NULL]","[NULL]"
+1122,5613,"[NULL]","[NULL]","CAM_startiface","[NULL]","[NULL]"
+1125,5615,"[NULL]","[NULL]","CAM_startisp","[NULL]","[NULL]"
+1126,5616,"[NULL]","[NULL]","CAM_startstats","[NULL]","[NULL]"
+1128,5618,"[NULL]","[NULL]","CAM_startpproc","[NULL]","[NULL]"
+1129,5619,"[NULL]","[NULL]","CAM_startimglib","[NULL]","[NULL]"
+1157,5642,"[NULL]","[NULL]",".vorbis.decoder","[NULL]","[NULL]"
+1158,5643,"[NULL]","[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
+1168,5652,"[NULL]","[NULL]",".vorbis.decoder","[NULL]","[NULL]"
+1169,5653,"[NULL]","[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
+1212,5683,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1214,5685,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1216,5687,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1217,5688,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1218,5689,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1219,5691,"[NULL]","[NULL]","cam_data_proc","[NULL]","[NULL]"
+1220,5690,"[NULL]","[NULL]","cam_data_proc","[NULL]","[NULL]"
+1222,5693,"[NULL]","[NULL]","CAM_jpeg_jobmgr","[NULL]","[NULL]"
+1226,5697,"[NULL]","[NULL]","OMX_ImgEnc","[NULL]","[NULL]"
+1227,5698,"[NULL]","[NULL]","cam_data_proc","[NULL]","[NULL]"
+1228,5699,"[NULL]","[NULL]","cam_data_proc","[NULL]","[NULL]"
+1229,5700,"[NULL]","[NULL]","cam_data_proc","[NULL]","[NULL]"
+1244,5714,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1245,5715,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1246,5716,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1247,5717,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1248,5718,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1268,5736,"[NULL]","[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
+1276,5735,"[NULL]","[NULL]",".vorbis.decoder","[NULL]","[NULL]"
+1306,5763,"[NULL]","[NULL]",".vorbis.decoder","[NULL]","[NULL]"
+1307,5764,"[NULL]","[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
+1318,5774,"[NULL]","[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
+1319,5773,"[NULL]","[NULL]",".vorbis.decoder","[NULL]","[NULL]"
+1328,5783,"[NULL]","[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
+1329,5782,"[NULL]","[NULL]",".vorbis.decoder","[NULL]","[NULL]"
+1331,5784,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1332,5785,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1333,5786,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1336,5789,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1337,5790,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1338,5791,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1339,5792,"[NULL]","[NULL]","applyRouting","[NULL]","[NULL]"
+1354,5803,"[NULL]","[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
+1355,5802,"[NULL]","[NULL]",".vorbis.decoder","[NULL]","[NULL]"
+1358,5807,"[NULL]","[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
+1359,5806,"[NULL]","[NULL]",".vorbis.decoder","[NULL]","[NULL]"
+1361,5810,"[NULL]","[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
+1362,5809,"[NULL]","[NULL]",".vorbis.decoder","[NULL]","[NULL]"
+1364,5813,"[NULL]","[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
+1365,5812,"[NULL]","[NULL]",".vorbis.decoder","[NULL]","[NULL]"
+1369,5816,"[NULL]","[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
+1370,5815,"[NULL]","[NULL]",".vorbis.decoder","[NULL]","[NULL]"
+1372,5818,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1373,5819,"[NULL]","[NULL]",".vorbis.decoder","[NULL]","[NULL]"
+1374,5820,"[NULL]","[NULL]","OMXCallbackDisp","[NULL]","[NULL]"
+1375,5821,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1376,5822,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1377,5823,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1384,5828,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1389,5830,"[NULL]","[NULL]","HwBinder:943_4","[NULL]","[NULL]"
+1391,5831,"[NULL]","[NULL]","HwBinder:943_4","[NULL]","[NULL]"
+1393,5833,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1397,5838,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1403,5842,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1406,5843,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1407,5844,"[NULL]","[NULL]","gcm-task#1","[NULL]","[NULL]"
+1408,5846,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1419,5856,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1420,5857,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1421,5858,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1422,5859,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1423,5860,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1424,5861,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1426,5863,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1427,5864,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1430,5867,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1431,5868,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1434,5871,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1437,5874,"[NULL]","[NULL]","gcm-task#1","[NULL]","[NULL]"
+1438,5174,"[NULL]","[NULL]","TaskSchedulerBa","[NULL]","[NULL]"
+1439,5176,"[NULL]","[NULL]","TaskSchedulerFo","[NULL]","[NULL]"
+1440,5175,"[NULL]","[NULL]","TaskSchedulerFo","[NULL]","[NULL]"
+1446,5880,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1447,5881,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1448,5882,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1449,5883,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1453,5887,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1454,5888,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1455,5889,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1456,5890,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1457,5891,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1458,5892,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1461,5893,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1462,5894,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1463,5895,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1464,5896,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1465,5897,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1467,5898,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1468,3097,"[NULL]","[NULL]","AsyncTask #2","[NULL]","[NULL]"
+1469,5899,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1470,5900,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1471,5901,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1472,5902,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1473,5903,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1474,5904,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1475,5905,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1476,5906,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1477,5907,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1478,5908,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1479,5909,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1482,5912,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1483,5913,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1484,5914,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1485,5915,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1486,5916,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1487,5917,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1488,5918,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1491,5919,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1492,5920,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1493,5921,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1494,5922,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1496,5924,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1497,5925,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1498,5926,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1499,5928,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1500,5927,"[NULL]","[NULL]","applyRouting","[NULL]","[NULL]"
+1501,5929,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1502,5930,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1503,5931,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1505,5933,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1506,5934,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1509,5937,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1512,5939,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1515,5942,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1523,5950,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1524,5951,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1527,5952,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1528,5953,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1529,5954,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1530,5955,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1531,5956,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1532,5957,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1533,5958,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1534,5959,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1535,5960,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1536,5961,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1537,5962,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1538,5963,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1539,5964,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1540,5965,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1541,5966,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1542,5967,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1543,5968,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1544,5969,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1545,5970,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1546,5971,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1547,5972,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1548,5973,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1549,5974,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1550,5975,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1552,5976,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1553,5977,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1554,5228,"[NULL]","[NULL]","Measurement Wor","[NULL]","[NULL]"
+1555,5978,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1556,5979,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1557,5980,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1558,5981,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1559,5982,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1560,5983,"[NULL]","[NULL]","driver_slow_ae:","[NULL]","[NULL]"
+1561,5986,"[NULL]","[NULL]","CAM_SNAPSHOT","[NULL]","[NULL]"
+1562,5987,"[NULL]","[NULL]","CAM_CALLBACK","[NULL]","[NULL]"
+1563,5988,"[NULL]","[NULL]","CAM_CALLBACK","[NULL]","[NULL]"
+1564,5989,"[NULL]","[NULL]","CAM_RAW","[NULL]","[NULL]"
+1565,5990,"[NULL]","[NULL]","CAM_ANALYSISCAM","[NULL]","[NULL]"
+1566,5985,"[NULL]","[NULL]","CAM_PREVIEW","[NULL]","[NULL]"
+1567,5984,"[NULL]","[NULL]","CAM_METADATA","[NULL]","[NULL]"
+1568,5991,"[NULL]","[NULL]","CAM_StrmAppDat","[NULL]","[NULL]"
+1569,5992,"[NULL]","[NULL]","CAM_StrmAppDat","[NULL]","[NULL]"
+1570,5993,"[NULL]","[NULL]","CAM_iface_poll","[NULL]","[NULL]"
+1571,5994,"[NULL]","[NULL]","CAM_iface_hw","[NULL]","[NULL]"
+1572,5995,"[NULL]","[NULL]","irq/164-arm-smm","[NULL]","[NULL]"
+1573,5996,"[NULL]","[NULL]","CAM_StrmAppDat","[NULL]","[NULL]"
+1574,5997,"[NULL]","[NULL]","CAM_StrmAppDat","[NULL]","[NULL]"
+1575,5998,"[NULL]","[NULL]","CAM_StrmAppDat","[NULL]","[NULL]"
+1576,5999,"[NULL]","[NULL]","CAM_StrmAppDat","[NULL]","[NULL]"
+1577,6000,"[NULL]","[NULL]","CAM_StrmAppDat","[NULL]","[NULL]"
+1578,6001,"[NULL]","[NULL]","irq/165-arm-smm","[NULL]","[NULL]"
+1579,6002,"[NULL]","[NULL]","CAM_sof_timer","[NULL]","[NULL]"
+1580,6003,"[NULL]","[NULL]","HwBinder:759_2","[NULL]","[NULL]"
+1581,6004,"[NULL]","[NULL]","CAM_stopsensor","[NULL]","[NULL]"
+1582,6005,"[NULL]","[NULL]","CAM_stopiface","[NULL]","[NULL]"
+1583,6006,"[NULL]","[NULL]","CAM_stopisp","[NULL]","[NULL]"
+1584,6007,"[NULL]","[NULL]","CAM_stopstats","[NULL]","[NULL]"
+1585,6008,"[NULL]","[NULL]","CAM_stoppproc","[NULL]","[NULL]"
+1586,6009,"[NULL]","[NULL]","CAM_stopimglib","[NULL]","[NULL]"
+1588,6010,"[NULL]","[NULL]","ProPrgsFin","[NULL]","[NULL]"
+1593,6015,"[NULL]","[NULL]","gcm-task#1","[NULL]","[NULL]"
+1594,6016,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1610,6023,"[NULL]","[NULL]","SharedPreferenc","[NULL]","[NULL]"
+1616,5218,"[NULL]","[NULL]","Measurement Wor","[NULL]","[NULL]"
+1617,6024,"[NULL]","[NULL]","sensors.qcom","[NULL]","[NULL]"
+1634,950,119,950,"[NULL]","[NULL]","[NULL]"
diff --git a/test/trace_processor/track_event_same_tids.py b/test/trace_processor/track_event_same_tids.py
deleted file mode 100644
index c838d6d..0000000
--- a/test/trace_processor/track_event_same_tids.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/python
-# Copyright (C) 2019 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.
-
-from os import sys, path
-sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
-import synth_common
-
-trace = synth_common.create_trace()
-
-# Chrome renderer processes don't know their "true" tids on some platforms.
-# Instead, they each write tids that start at 1 - which means, the same tids are
-# used in multiple different processes at the same time. This trace replicates
-# such a situation.
-
-trace.add_thread_track_descriptor(
-    ps=1, ts=0, uuid=1, pid=5, tid=1, thread_name="t1", inc_state_cleared=True)
-trace.add_thread_track_descriptor(
-    ps=1, ts=0, uuid=2, pid=10, tid=1, thread_name="t2")
-
-trace.add_track_event(
-    ps=1, ts=1000, track_uuid=1, cat="cat", name="name1", type=3)
-trace.add_track_event(
-    ps=1, ts=2000, track_uuid=2, cat="cat", name="name2", type=3)
-
-print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/track_event_same_tids_slices.out b/test/trace_processor/track_event_same_tids_slices.out
deleted file mode 100644
index f66b8ce..0000000
--- a/test/trace_processor/track_event_same_tids_slices.out
+++ /dev/null
@@ -1,3 +0,0 @@
-"ts","dur","category","name"
-1000,0,"cat","name1"
-2000,0,"cat","name2"
diff --git a/test/trace_processor/track_event_same_tids_threads.out b/test/trace_processor/track_event_same_tids_threads.out
deleted file mode 100644
index b4ce83a..0000000
--- a/test/trace_processor/track_event_same_tids_threads.out
+++ /dev/null
@@ -1,5 +0,0 @@
-"tid","pid","pname","tname"
-1,5,"[NULL]","t1"
-1,10,"[NULL]","t2"
-5,5,"[NULL]","[NULL]"
-10,10,"[NULL]","[NULL]"
diff --git a/test/trace_processor/track_event_slices.sql b/test/trace_processor/track_event_slices.sql
deleted file mode 100644
index b69c990..0000000
--- a/test/trace_processor/track_event_slices.sql
+++ /dev/null
@@ -1 +0,0 @@
-select ts, dur, category, name from slice order by ts asc;
\ No newline at end of file
diff --git a/test/trace_processor/ts_desc_filter.sql b/test/trace_processor/ts_desc_filter.sql
index 8bf5f24..01494fe 100644
--- a/test/trace_processor/ts_desc_filter.sql
+++ b/test/trace_processor/ts_desc_filter.sql
@@ -1,6 +1,5 @@
 select ts
 from sched
-inner join thread using(utid)
-where tid = 23850
+where utid = 1
 order by ts desc
-limit 10
+limit 10
\ No newline at end of file
diff --git a/tools/BUILD.gn b/tools/BUILD.gn
index 6214548..044562a 100644
--- a/tools/BUILD.gn
+++ b/tools/BUILD.gn
@@ -12,38 +12,27 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../gn/perfetto.gni")
-
-# Prevent that this file is accidentally included in embedder builds.
-assert(enable_perfetto_tools)
-
-# Lists all tools. The root "all" target depends on this.
-group("tools") {
+copy("copy_protoc_helper") {
   testonly = true
-  deps = [
-    ":copy_protoc",
-    ":idle_alloc",
-    "compact_reencode",
-    "ftrace_proto_gen",
-    "protoprofile",
+  sources = [
+    "protoc_helper.py",
   ]
-  if (is_linux || is_android) {
-    deps += [
-      "busy_threads",
-      "cpu_utilization",
-      "dump_ftrace_stats",
-      "skippy",
-    ]
-  }
-  if (enable_perfetto_tools_trace_to_text) {
-    deps += [
-      "trace_to_text",
-      "trace_to_text:trace_to_text_lite",
-    ]
-  }
+  outputs = [
+    "${root_out_dir}/protoc_helper",
+  ]
 }
 
-if (is_linux && enable_perfetto_heapprofd) {
+group("protoc_helper") {
+  testonly = true
+  public_deps = [
+    ":copy_protoc_helper",
+  ]
+  deps = [
+    "../buildtools:protoc($host_toolchain)",
+  ]
+}
+
+if (is_linux) {
   executable("profiling_sample_distribution") {
     sources = [
       "profiling_sample_distribution.cc",
@@ -55,40 +44,3 @@
     ]
   }
 }
-
-executable("idle_alloc") {
-  deps = [
-    "../gn:default_deps",
-  ]
-  sources = [
-    "idle_alloc.cc",
-  ]
-}
-
-# The protoc binary can end up in out/protoc or out/gcc_like_host/protoc
-# depending on whether this is a pure-host build vs a host+target (i.e. android)
-# build. This rule ensures that in both cases we end up with a host binary in
-# out/protoc, so tools can consistently refer to that one location.
-protoc_target = "../gn:protoc($host_toolchain)"
-if (current_toolchain != host_toolchain) {
-  copy("copy_protoc") {
-    testonly = true
-    deps = [
-      protoc_target,
-    ]
-    host_out_dir = get_label_info(protoc_target, "root_out_dir")
-    sources = [
-      "$host_out_dir/protoc",
-    ]
-    outputs = [
-      "$root_build_dir/protoc",
-    ]
-  }
-} else {
-  # Nothing to do, in this case protoc is already built in the root out dir.
-  group("copy_protoc") {
-    public_deps = [
-      protoc_target,
-    ]
-  }
-}
diff --git a/tools/add_test_trace.sh b/tools/add_test_trace.sh
index 976955a..6472ffd 100755
--- a/tools/add_test_trace.sh
+++ b/tools/add_test_trace.sh
@@ -39,10 +39,10 @@
 
 echo ""
 echo "SHA1 of file $NEW_TEST_DATA is"
-if which shasum > /dev/null; then
-NEW_SHA=$(shasum /tmp/$NEW_TEST_DATA | cut -c1-40)  # Mac OS
+if which shasum; then
+NEW_SHA=$(shasum /tmp/$NEW_TEST_DATA)  # Mac OS
 else
-NEW_SHA=$(sha1sum /tmp/$NEW_TEST_DATA | cut -c1-40)  # Linux
+NEW_SHA=$(sha1sum /tmp/$NEW_TEST_DATA)  # Linux
 fi
 echo $NEW_SHA
 
@@ -56,16 +56,10 @@
 echo ""
 echo "Updating tools/install-build-deps"
 echo ""
-
-OLD_SHA=$(cat tools/install-build-deps | grep '/test-data-.*.zip' -A1 | tail -n1 | cut -c10-49)
-
-# Cannot easily use sed -i, it has different syntax on Linux vs Mac.
-cat tools/install-build-deps \
-  | sed -e "s|/test-data-.*.zip|/$NEW_TEST_DATA|g" \
-  | sed -e "s|$OLD_SHA|$NEW_SHA|g" \
-  > tools/install-build-deps.tmp
-
-mv -f tools/install-build-deps.tmp tools/install-build-deps
-chmod 755 tools/install-build-deps
+OLD_URL="https://\(.*/perfetto\)/test-data-.*.zip"
+NEW_URL="https://\1/$NEW_TEST_DATA"
+OLD_SHA="\w*"
+SED_MAGIC="s|'$OLD_URL',\n\(\s*\)'$OLD_SHA'|'$NEW_URL',\n\2'$NEW_SHA'|g"
+sed -i '' -z -e "$SED_MAGIC" tools/install-build-deps
 
 echo "All done!"
diff --git a/tools/analyze_pipestats.py b/tools/analyze_pipestats.py
new file mode 100755
index 0000000..81cfbab
--- /dev/null
+++ b/tools/analyze_pipestats.py
@@ -0,0 +1,68 @@
+#!/usr/bin/python
+
+# 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.
+
+import os
+import sys
+
+import numpy as np
+from matplotlib import pyplot as plt
+
+from absl import app
+from absl import flags
+
+FLAGS = flags.FLAGS
+
+flags.DEFINE_integer('window', 100, 'Size of rolling average window')
+
+COLORS = ['b', 'g', 'r', 'c', 'm', 'y', 'k', 'indigo']
+
+
+def max_default(seq, default):
+  try:
+    return np.max(seq)
+  except ValueError:
+    return default
+
+
+def main(argv):
+  max_val = 0
+  max_key = ""
+
+  n = 0
+  for fn in argv[1:]:
+    name = os.path.basename(fn)
+    xs = np.loadtxt(fn, dtype=np.int)
+    ys = np.arange(len(xs))
+
+    delta = ys - np.array([max_default(ys[xs < x - FLAGS.window], np.NaN)
+                           for x in xs])
+
+    max_delta = np.nanmax(delta)
+    if max_delta > max_val:
+      max_val = max_delta
+      max_key = name
+
+    plt.plot(xs, delta, color=COLORS[n % len(COLORS)], label=name)
+    print xs, delta
+    n += 1
+  print "Max delta %d in %s" % (max_val, max_key)
+  print "Buffer size: %d KB" % (max_val * 4)
+  plt.legend()
+  plt.show()
+
+
+if __name__ == '__main__':
+  app.run(main)
diff --git a/tools/analyze_profiling_sampling_distribution.py b/tools/analyze_profiling_sampling_distribution.py
index e1e41cb..a33ffb3 100644
--- a/tools/analyze_profiling_sampling_distribution.py
+++ b/tools/analyze_profiling_sampling_distribution.py
@@ -24,7 +24,6 @@
 from collections import defaultdict
 from matplotlib import pyplot as plt
 
-
 def main(argv):
   sns.set()
 
@@ -45,9 +44,8 @@
       distributions[code_location][int(itr)] += int(size)
 
   # Map from key to list of bytes allocated, one for each iteration.
-  flat_distributions = {
-      key: value.values() for key, value in distributions.iteritems()
-  }
+  flat_distributions = {key: value.values() for key, value
+                        in distributions.iteritems()}
 
   for key, value in flat_distributions.iteritems():
     print key, "ground truth %d " % ground_truth[key], sp.stats.describe(value)
diff --git a/tools/build_all_configs.py b/tools/build_all_configs.py
index 14ebdd1..d4d1517 100755
--- a/tools/build_all_configs.py
+++ b/tools/build_all_configs.py
@@ -13,92 +13,65 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import print_function
-
 import argparse
 import os
-import platform
 import subprocess
 import sys
 
-from compat import iteritems, quote
-
 MAC_BUILD_CONFIGS = {
-    'mac_debug': ('is_clang=true', 'is_debug=true'),
-    'mac_release': ('is_clang=true', 'is_debug=false'),
-    'mac_asan': ('is_clang=true', 'is_debug=false', 'is_asan=true'),
-    'mac_tsan': ('is_clang=true', 'is_debug=false', 'is_tsan=true'),
-    'mac_ubsan': ('is_clang=true', 'is_debug=false', 'is_ubsan=true'),
+  'mac_debug': ['is_clang=true', 'is_debug=true'],
+  'mac_release': ['is_clang=true', 'is_debug=false'],
+  'mac_asan': ['is_clang=true', 'is_debug=false', 'is_asan=true'],
+  'mac_tsan': ['is_clang=true', 'is_debug=false', 'is_tsan=true'],
+  'mac_ubsan': ['is_clang=true', 'is_debug=false', 'is_ubsan=true'],
 }
 
 ANDROID_BUILD_CONFIGS = {
-    'android_debug': ('target_os="android"', 'is_clang=true', 'is_debug=true'),
-    'android_release': ('target_os="android"', 'is_clang=true',
-                        'is_debug=false'),
-    'android_release_incl_heapprofd': ('target_os="android"', 'is_clang=true',
-                                       'is_debug=false',
-                                       'android_api_level=26'),
-    'android_asan': ('target_os="android"', 'is_clang=true', 'is_debug=false',
-                     'is_asan=true'),
-    'android_lsan': ('target_os="android"', 'is_clang=true', 'is_debug=false',
-                     'is_lsan=true'),
+  'android_debug': ['target_os="android"', 'is_clang=true', 'is_debug=true'],
+  'android_release': ['target_os="android"', 'is_clang=true', 'is_debug=false'],
+  'android_release_incl_heapprofd':
+    ['target_os="android"', 'is_clang=true', 'is_debug=false', 'android_api_level=26'],
+  'android_asan': ['target_os="android"', 'is_clang=true', 'is_debug=false', 'is_asan=true'],
+  'android_lsan': ['target_os="android"', 'is_clang=true', 'is_debug=false', 'is_lsan=true'],
 }
 
-ANDROID_ARCHS = ('arm', 'arm64')
+ANDROID_ARCHS = [ 'arm', 'arm64' ]
 
 LINUX_BUILD_CONFIGS = {
-    'linux_gcc_debug': ('is_clang=false', 'is_debug=true'),
-    'linux_gcc_release': ('is_clang=false', 'is_debug=false'),
-    'linux_clang_debug': ('is_clang=true', 'is_debug=true'),
-    'linux_clang_release': ('is_clang=true', 'is_debug=false'),
-    'linux_asan': ('is_clang=true', 'is_debug=false', 'is_asan=true'),
-    'linux_lsan': ('is_clang=true', 'is_debug=false', 'is_lsan=true'),
-    'linux_msan': ('is_clang=true', 'is_debug=false', 'is_msan=true'),
-    'linux_tsan': ('is_clang=true', 'is_debug=false', 'is_tsan=true'),
-    'linux_ubsan': ('is_clang=true', 'is_debug=false', 'is_ubsan=true'),
-    'linux_fuzzer': ('is_clang=true', 'is_debug=false', 'is_fuzzer=true',
-                     'is_asan=true'),
+  'linux_gcc_debug': ['is_clang=false', 'is_debug=true'],
+  'linux_gcc_release': ['is_clang=false', 'is_debug=false'],
+  'linux_clang_debug': ['is_clang=true', 'is_debug=true'],
+  'linux_clang_release': ['is_clang=true', 'is_debug=false'],
+  'linux_asan': ['is_clang=true', 'is_debug=false', 'is_asan=true'],
+  'linux_lsan': ['is_clang=true', 'is_debug=false', 'is_lsan=true'],
+  'linux_msan': ['is_clang=true', 'is_debug=false', 'is_msan=true'],
+  'linux_tsan': ['is_clang=true', 'is_debug=false', 'is_tsan=true'],
+  'linux_ubsan': ['is_clang=true', 'is_debug=false', 'is_ubsan=true'],
+  'linux_fuzzer': ['is_clang=true', 'is_debug=false', 'is_fuzzer=true',
+                   'is_asan=true'],
 }
 
-LINUX_ARCHS = ('arm64',)
-
 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
-
 def main():
   parser = argparse.ArgumentParser()
-  parser.add_argument('--ccache', action='store_true', default=False)
   parser.add_argument('--host-only', action='store_true', default=False)
-  parser.add_argument('--no-android', action='store_true', default=False)
-  parser.add_argument('--build', metavar='TARGET')
+  parser.add_argument('--build', default=None)
   args = parser.parse_args()
 
   configs = {}
   if not args.host_only:
-    if not args.no_android:
-      for config_name, gn_args in iteritems(ANDROID_BUILD_CONFIGS):
-        for arch in ANDROID_ARCHS:
-          full_config_name = '%s_%s' % (config_name, arch)
-          configs[full_config_name] = gn_args + ('target_cpu="%s"' % arch,)
-    for config_name, gn_args in iteritems(LINUX_BUILD_CONFIGS):
-      if dict(a.split('=') for a in gn_args).get('is_clang', None) == 'true':
-        continue
-      for arch in LINUX_ARCHS:
+    for config_name, gn_args in ANDROID_BUILD_CONFIGS.iteritems():
+      for arch in ANDROID_ARCHS:
         full_config_name = '%s_%s' % (config_name, arch)
-        configs[full_config_name] = gn_args + ('target_cpu="%s"' % arch,
-                                               'target_os="linux"')
+        configs[full_config_name] = gn_args + ['target_cpu="%s"' % arch]
 
-  system = platform.system().lower()
-  if system == 'linux':
+  if sys.platform == 'linux2':
     configs.update(LINUX_BUILD_CONFIGS)
-  elif system == 'darwin':
+  elif sys.platform == 'darwin':
     configs.update(MAC_BUILD_CONFIGS)
   else:
-    assert False, 'Unsupported system %r' % system
-
-  if args.ccache:
-    for config_name, gn_args in iteritems(configs):
-      configs[config_name] = gn_args + ('cc_wrapper="ccache"',)
+    assert(False)
 
   out_base_dir = os.path.join(ROOT_DIR, 'out')
   if not os.path.isdir(out_base_dir):
@@ -106,18 +79,17 @@
 
   gn = os.path.join(ROOT_DIR, 'tools', 'gn')
 
-  for config_name, gn_args in iteritems(configs):
-    print('\n\033[32mBuilding %-20s[%s]\033[0m' % (config_name,
-                                                   ','.join(gn_args)))
+  for config_name, gn_args in configs.iteritems():
+    print '\n\033[32mBuilding %-20s[%s]\033[0m' % (config_name, ','.join(gn_args))
     out_dir = os.path.join(ROOT_DIR, 'out', config_name)
     if not os.path.isdir(out_dir):
       os.mkdir(out_dir)
-    gn_cmd = (gn, 'gen', out_dir, '--args=%s' % (' '.join(gn_args)), '--check')
-    print(' '.join(quote(c) for c in gn_cmd))
+    gn_cmd = [gn, 'gen', out_dir, '--args=%s' % (' '.join(gn_args)), '--check']
+    print ' '.join(gn_cmd)
     subprocess.check_call(gn_cmd, cwd=ROOT_DIR)
     if args.build:
       ninja = os.path.join(ROOT_DIR, 'tools', 'ninja')
-      ninja_cmd = (ninja, '-C', '.', args.build)
+      ninja_cmd = [ninja, '-C', '.', args.build]
       subprocess.check_call(ninja_cmd, cwd=out_dir)
 
 
diff --git a/tools/busy_threads/busy_threads.cc b/tools/busy_threads/busy_threads.cc
index d6dc6d7..183e093 100644
--- a/tools/busy_threads/busy_threads.cc
+++ b/tools/busy_threads/busy_threads.cc
@@ -15,7 +15,6 @@
  */
 
 #include <getopt.h>
-#include <inttypes.h>
 #include <stdint.h>
 #include <unistd.h>
 
@@ -24,88 +23,37 @@
 #include "perfetto/base/logging.h"
 #include "perfetto/base/time.h"
 
-#define PERFETTO_HAVE_PTHREADS                \
-  (PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) ||   \
-   PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
-   PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX))
-
-#if PERFETTO_HAVE_PTHREADS
-#include <pthread.h>
-#endif
-
 // Spawns the requested number threads that alternate between busy-waiting and
 // sleeping.
 
 namespace perfetto {
 namespace {
 
-void SetRandomThreadName(uint32_t thread_name_count) {
-#if PERFETTO_HAVE_PTHREADS
-  char name[16] = {};
-  snprintf(name, sizeof(name), "busy-%" PRIu32,
-           static_cast<uint32_t>(rand()) % thread_name_count);
-  pthread_setname_np(pthread_self(), name);
-#endif
-}
-
-void PrintUsage(const char* bin_name) {
-#if PERFETTO_HAVE_PTHREADS
-  PERFETTO_ELOG(
-      "Usage: %s --threads=N --period_us=N --duty_cycle=[1-100] "
-      "[--thread_names=N]",
-      bin_name);
-#else
-  PERFETTO_ELOG("Usage: %s --threads=N --period_us=N --duty_cycle=[1-100]",
-                bin_name);
-#endif
-}
-
-__attribute__((noreturn)) void BusyWait(int64_t tstart,
-                                        int64_t period_us,
-                                        int64_t busy_us,
-                                        uint32_t thread_name_count) {
-  int64_t tbusy = tstart;
-  int64_t tnext = tstart;
-  for (;;) {
-    if (thread_name_count)
-      SetRandomThreadName(thread_name_count);
-
-    tbusy = tnext + busy_us * 1000;
-    tnext += period_us * 1000;
-    while (base::GetWallTimeNs().count() < tbusy) {
+__attribute__((noreturn)) void BusyWait(long busy_us, long sleep_us) {
+  while (1) {
+    base::TimeNanos start = base::GetWallTimeNs();
+    while ((base::GetWallTimeNs() - start).count() < busy_us * 1000) {
       for (int i = 0; i < 10000; i++) {
         asm volatile("" ::: "memory");
       }
     }
-    auto tnow = base::GetWallTimeNs().count();
-    if (tnow >= tnext) {
+    if (sleep_us > 0)
+      base::SleepMicroseconds(static_cast<unsigned>(sleep_us));
+    else
       std::this_thread::yield();
-      continue;
-    }
-
-    while (tnow < tnext) {
-      // +1 to prevent sleeping twice when there is truncation.
-      base::SleepMicroseconds(static_cast<uint32_t>((tnext - tnow) / 1000) + 1);
-      tnow = base::GetWallTimeNs().count();
-    }
   }
 }
 
 int BusyThreadsMain(int argc, char** argv) {
-  int64_t num_threads = -1;
-  int64_t period_us = -1;
-  int64_t duty_cycle = -1;
-  uint32_t thread_name_count = 0;
+  long num_threads = -1;
+  long period_us = -1;
+  long duty_cycle = -1;
 
   static struct option long_options[] = {
-    {"threads", required_argument, nullptr, 't'},
-    {"period_us", required_argument, nullptr, 'p'},
-    {"duty_cycle", required_argument, nullptr, 'd'},
-#if PERFETTO_HAVE_PTHREADS
-    {"thread_names", required_argument, nullptr, 'r'},
-#endif
-    {nullptr, 0, nullptr, 0}
-  };
+      {"threads", required_argument, nullptr, 't'},
+      {"period_us", required_argument, nullptr, 'p'},
+      {"duty_cycle", required_argument, nullptr, 'd'},
+      {nullptr, 0, nullptr, 0}};
   int option_index;
   int c;
   while ((c = getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
@@ -119,30 +67,24 @@
       case 'd':
         duty_cycle = atol(optarg);
         break;
-#if PERFETTO_HAVE_PTHREADS
-      case 'r':
-        thread_name_count = static_cast<uint32_t>(atoi(optarg));
-        break;
-#endif
       default:
         break;
     }
   }
-  if (num_threads < 1 || period_us < 0 || duty_cycle < 1 || duty_cycle > 100 ||
-      thread_name_count > (1 << 20)) {
-    PrintUsage(argv[0]);
+  if (num_threads < 1 || period_us < 0 || duty_cycle < 1 || duty_cycle > 100) {
+    PERFETTO_ELOG("Usage: %s --threads=N --period_us=N --duty_cycle=[1-100]",
+                  argv[0]);
     return 1;
   }
 
-  int64_t busy_us = static_cast<int64_t>(period_us * (duty_cycle / 100.0));
+  long busy_us = period_us * duty_cycle / 100;
+  long sleep_us = period_us - busy_us;
 
-  PERFETTO_LOG("Spawning %" PRId64 " threads; period duration: %" PRId64
-               "us; busy duration: %" PRId64 "us.",
-               num_threads, period_us, busy_us);
-
-  int64_t tstart = base::GetWallTimeNs().count();
+  PERFETTO_LOG(
+      "Spawning %ld threads; wait duration: %ldus; sleep duration: %ldus.",
+      num_threads, busy_us, sleep_us);
   for (int i = 0; i < num_threads; i++) {
-    std::thread th(BusyWait, tstart, period_us, busy_us, thread_name_count);
+    std::thread th(BusyWait, busy_us, sleep_us);
     th.detach();
   }
   PERFETTO_LOG("Threads spawned, Ctrl-C to stop.");
diff --git a/tools/check_include_violations b/tools/check_include_violations
deleted file mode 100755
index e308ec7..0000000
--- a/tools/check_include_violations
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2019 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 tool checks for layering violations in the include/ directory.
-# It checks that:
-# - public includes don't end up depending on non-public /ext/ includes.
-# - public includes don't end up depending on private src/ headers.
-# - We use consistently <angle brackets> for other libraries.
-
-import os
-import re
-import subprocess
-import sys
-
-ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-
-def main():
-  errors = 0
-  include_root = os.path.join(ROOT_DIR, 'include')
-  for root, _, files in os.walk(include_root):
-    for fname in files:
-      fpath = os.path.join(root, fname)
-      rel_path = os.path.relpath(fpath, ROOT_DIR)
-      if not os.path.isfile(fpath):
-        continue
-      if fpath.endswith('.cc'):
-        sys.stderr.write('.cc files not allowed in includes/ : ' + rel_path +
-                         '\n')
-        errors += 1
-        continue
-      if fpath.endswith('.h'):
-        with open(fpath) as f:
-          lines = f.readlines()
-        for line in lines:
-          if '// no-include-violation-check' in line:
-            continue
-          m = re.findall(r'^#include "(.*\.h)"', line)
-          if not m:
-            continue
-          incl = m[0]
-
-          # Allow only #include "perfetto/..." or "protos/..." but not "src/".
-          if not (incl.startswith('perfetto/') or incl.startswith('protos/')):
-            sys.stderr.write(
-                ('Public header %s is trying to include %s which is outside ' +
-                 'of include/. If you are trying to include a library use ' +
-                 ' <angle brackets> instead\n') % (rel_path, incl))
-            errors += 1
-            continue
-
-          # Ignore lines marked with nogncheck.
-          if '// nogncheck' in line:
-            continue
-
-          # Public (non-/ext/) headers cannot include /ext/ headers.
-          if (not rel_path.startswith('include/perfetto/ext/') and
-              incl.startswith('perfetto/ext/')):
-            sys.stderr.write(('Public header %s cannot include the non-public' +
-                              '/ext/ header %s.\n') % (rel_path, incl))
-            errors += 1
-            continue
-
-  return 0 if errors == 0 else 1
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/tools/compact_reencode/BUILD.gn b/tools/compact_reencode/BUILD.gn
deleted file mode 100644
index 6556b9d..0000000
--- a/tools/compact_reencode/BUILD.gn
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../gn/perfetto_host_executable.gni")
-
-perfetto_host_executable("compact_reencode") {
-  testonly = true
-  deps = [
-    ":common",
-    "../../gn:default_deps",
-  ]
-}
-
-source_set("common") {
-  testonly = true
-  public_deps = [
-    "../../gn:default_deps",
-    "../../include/perfetto/protozero",
-    "../../protos/perfetto/trace:zero",
-    "../../protos/perfetto/trace/ftrace:zero",
-    "../../src/base",
-  ]
-  sources = [
-    "main.cc",
-  ]
-}
diff --git a/tools/compact_reencode/main.cc b/tools/compact_reencode/main.cc
deleted file mode 100644
index ae4a2c4..0000000
--- a/tools/compact_reencode/main.cc
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (C) 2019 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 <stdint.h>
-#include <string>
-#include <vector>
-
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/protozero/proto_utils.h"
-#include "perfetto/protozero/scattered_heap_buffer.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
-#include "protos/perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h"
-#include "protos/perfetto/trace/ftrace/sched.pbzero.h"
-#include "protos/perfetto/trace/trace.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-
-// Re-encodes the given trace, converting sched events to their compact
-// representation.
-//
-// Notes:
-// * doesn't do bundle splitting/merging, the original trace must already
-//   have multi-page bundles for the re-encoding to be realistic.
-// * when importing the resulting trace into trace_processor, a few leading
-//   switch/wakeup events can be skipped (since there's not enough info to
-//   reconstruct the full events at that point), and this might change the
-//   trace_bounds.
-
-namespace perfetto {
-namespace compact_reencode {
-namespace {
-
-void WriteToFile(const std::string& out, const char* path) {
-  PERFETTO_CHECK(!unlink(path) || errno == ENOENT);
-  auto out_fd = base::OpenFile(path, O_RDWR | O_CREAT, 0666);
-  if (!out_fd || base::WriteAll(out_fd.get(), out.data(), out.size()) !=
-                     static_cast<ssize_t>(out.size())) {
-    PERFETTO_FATAL("WriteToFile");
-  }
-}
-
-static void CopyField(protozero::Message* out, const protozero::Field& field) {
-  using protozero::proto_utils::ProtoWireType;
-  if (field.type() == ProtoWireType::kVarInt) {
-    out->AppendVarInt(field.id(), field.as_uint64());
-  } else if (field.type() == ProtoWireType::kLengthDelimited) {
-    out->AppendBytes(field.id(), field.as_bytes().data, field.as_bytes().size);
-  } else if (field.type() == ProtoWireType::kFixed32) {
-    out->AppendFixed(field.id(), field.as_uint32());
-  } else if (field.type() == ProtoWireType::kFixed64) {
-    out->AppendFixed(field.id(), field.as_uint64());
-  } else {
-    PERFETTO_FATAL("unexpected wire type");
-  }
-}
-
-void ReEncodeBundle(protos::pbzero::TracePacket* packet_out,
-                    const uint8_t* data,
-                    size_t size) {
-  protos::pbzero::FtraceEventBundle::Decoder bundle(data, size);
-  auto* bundle_out = packet_out->set_ftrace_events();
-
-  if (bundle.has_lost_events())
-    bundle_out->set_lost_events(bundle.lost_events());
-  if (bundle.has_cpu())
-    bundle_out->set_cpu(bundle.cpu());
-
-  protozero::PackedVarInt switch_timestamp;
-  protozero::PackedVarInt switch_prev_state;
-  protozero::PackedVarInt switch_next_pid;
-  protozero::PackedVarInt switch_next_prio;
-  protozero::PackedVarInt switch_next_comm_index;
-
-  uint64_t last_switch_timestamp = 0;
-
-  std::vector<std::string> string_table;
-  auto intern = [&string_table](std::string str) {
-    for (size_t i = 0; i < string_table.size(); i++) {
-      if (str == string_table[i])
-        return static_cast<uint32_t>(i);
-    }
-    size_t new_idx = string_table.size();
-    string_table.push_back(str);
-    return static_cast<uint32_t>(new_idx);
-  };
-
-  // sched_waking pieces
-  protozero::PackedVarInt waking_timestamp;
-  protozero::PackedVarInt waking_pid;
-  protozero::PackedVarInt waking_target_cpu;
-  protozero::PackedVarInt waking_prio;
-  protozero::PackedVarInt waking_comm_index;
-
-  uint64_t last_waking_timestamp = 0;
-
-  for (auto event_it = bundle.event(); event_it; ++event_it) {
-    protos::pbzero::FtraceEvent::Decoder event(*event_it);
-    if (!event.has_sched_switch() && !event.has_sched_waking()) {
-      CopyField(bundle_out, event_it.field());
-    } else if (event.has_sched_switch()) {
-      switch_timestamp.Append(event.timestamp() - last_switch_timestamp);
-      last_switch_timestamp = event.timestamp();
-
-      protos::pbzero::SchedSwitchFtraceEvent::Decoder sswitch(
-          event.sched_switch());
-
-      auto iid = intern(sswitch.next_comm().ToStdString());
-      switch_next_comm_index.Append(iid);
-
-      switch_next_pid.Append(sswitch.next_pid());
-      switch_next_prio.Append(sswitch.next_prio());
-      switch_prev_state.Append(sswitch.prev_state());
-    } else {
-      waking_timestamp.Append(event.timestamp() - last_waking_timestamp);
-      last_waking_timestamp = event.timestamp();
-
-      protos::pbzero::SchedWakingFtraceEvent::Decoder swaking(
-          event.sched_waking());
-
-      auto iid = intern(swaking.comm().ToStdString());
-      waking_comm_index.Append(iid);
-
-      waking_pid.Append(swaking.pid());
-      waking_target_cpu.Append(swaking.target_cpu());
-      waking_prio.Append(swaking.prio());
-    }
-  }
-
-  auto* compact_sched = bundle_out->set_compact_sched();
-
-  for (const auto& s : string_table)
-    compact_sched->add_intern_table(s.data(), s.size());
-
-  compact_sched->set_switch_timestamp(switch_timestamp);
-  compact_sched->set_switch_next_comm_index(switch_next_comm_index);
-  compact_sched->set_switch_next_pid(switch_next_pid);
-  compact_sched->set_switch_next_prio(switch_next_prio);
-  compact_sched->set_switch_prev_state(switch_prev_state);
-
-  compact_sched->set_waking_timestamp(waking_timestamp);
-  compact_sched->set_waking_pid(waking_pid);
-  compact_sched->set_waking_target_cpu(waking_target_cpu);
-  compact_sched->set_waking_prio(waking_prio);
-  compact_sched->set_waking_comm_index(waking_comm_index);
-}
-
-std::string ReEncode(const std::string& raw) {
-  protos::pbzero::Trace::Decoder trace(raw);
-  protozero::HeapBuffered<protos::pbzero::Trace> output;
-
-  for (auto packet_it = trace.packet(); packet_it; ++packet_it) {
-    protozero::ProtoDecoder packet(*packet_it);
-    protos::pbzero::TracePacket* packet_out = output->add_packet();
-
-    for (auto field = packet.ReadField(); field.valid();
-         field = packet.ReadField()) {
-      if (field.id() == protos::pbzero::TracePacket::kFtraceEventsFieldNumber) {
-        ReEncodeBundle(packet_out, field.data(), field.size());
-      } else {
-        CopyField(packet_out, field);
-      }
-    }
-  }
-  // Minor technicality: we will be a tiny bit off the real encoding since
-  // we've encoded the top-level Trace & TracePacket sizes redundantly, while
-  // the tracing service writes them as a minimal varint (so only a few bytes
-  // off per trace packet).
-  return output.SerializeAsString();
-}
-
-int Main(int argc, const char** argv) {
-  if (argc < 3) {
-    PERFETTO_LOG("Usage: %s input output", argv[0]);
-    return 1;
-  }
-  const char* in_path = argv[1];
-  const char* out_path = argv[2];
-
-  std::string raw;
-  if (!base::ReadFile(in_path, &raw)) {
-    PERFETTO_PLOG("ReadFile");
-    return 1;
-  }
-
-  std::string raw_out = ReEncode(raw);
-  WriteToFile(raw_out, out_path);
-  return 0;
-}
-
-}  // namespace
-}  // namespace compact_reencode
-}  // namespace perfetto
-
-int main(int argc, const char** argv) {
-  return perfetto::compact_reencode::Main(argc, argv);
-}
diff --git a/tools/compat.py b/tools/compat.py
deleted file mode 100644
index cdf5afa..0000000
--- a/tools/compat.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2019 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.
-
-
-try:
-  from shlex import quote
-except ImportError:
-  from pipes import quote
-
-try:
-  from urllib.request import urlretrieve
-except ImportError:
-  from urllib import urlretrieve
-
-try:
-  xrange = xrange
-except NameError:
-  xrange = range
-
-try:
-  basestring = basestring
-except NameError:
-  basestring = str
-
-def itervalues(o):
-  try:
-    return o.itervalues()
-  except AttributeError:
-    return o.values()
-
-
-def iteritems(o):
-  try:
-    return o.iteritems()
-  except AttributeError:
-    return o.items()
diff --git a/tools/continuous_fuzz b/tools/continuous_fuzz
new file mode 100755
index 0000000..bebf1d6
--- /dev/null
+++ b/tools/continuous_fuzz
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# 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.
+
+set -euo pipefail
+
+while true; do
+  git fetch origin
+  git checkout origin/master
+  tools/install-build-deps
+  tools/run_all_fuzzers &
+  PID=$!
+  # Sleep 30min
+  sleep 1800
+  kill -INT ${PID}
+done
diff --git a/tools/cpu_utilization/BUILD.gn b/tools/cpu_utilization/BUILD.gn
deleted file mode 100644
index 1b70388..0000000
--- a/tools/cpu_utilization/BUILD.gn
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (C) 2019 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.
-
-executable("cpu_utilization") {
-  testonly = true
-  deps = [
-    "../../gn:default_deps",
-    "../../src/base",
-  ]
-  sources = [
-    "cpu_utilization.cc",
-  ]
-}
diff --git a/tools/cpu_utilization/cpu_utilization.cc b/tools/cpu_utilization/cpu_utilization.cc
deleted file mode 100644
index 829fd7f..0000000
--- a/tools/cpu_utilization/cpu_utilization.cc
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2019 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 <fcntl.h>
-#include <getopt.h>
-#include <inttypes.h>
-#include <stdint.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <string>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/base/time.h"
-#include "perfetto/ext/base/scoped_file.h"
-
-// Periodically prints an un-normalized cpu usage ratio (full use of a single
-// core = 1.0) of a target process. Based on /proc/pid/stat utime (userspace) &
-// stime (kernel space).
-
-namespace perfetto {
-namespace {
-
-uint64_t TimespecToMs(struct timespec ts) {
-  PERFETTO_CHECK(ts.tv_sec >= 0 && ts.tv_nsec >= 0);
-  return static_cast<uint64_t>(ts.tv_sec) * 1000 +
-         static_cast<uint64_t>(ts.tv_nsec) / 1000 / 1000;
-}
-
-uint64_t ReadWallTimeMs(clockid_t clk) {
-  struct timespec ts = {};
-  PERFETTO_CHECK(clock_gettime(clk, &ts) == 0);
-  return TimespecToMs(ts);
-}
-
-void ReadUtimeStime(const base::ScopedFile& stat_fd,
-                    unsigned long* utime_out,
-                    unsigned long* stime_out) {
-  char buf[1024] = {};
-  lseek(stat_fd.get(), 0, SEEK_SET);
-  PERFETTO_CHECK(read(stat_fd.get(), buf, sizeof(buf)) > 0);
-  buf[sizeof(buf) - 1] = '\0';
-
-  PERFETTO_CHECK(
-      sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu",
-             utime_out, stime_out) == 2);
-}
-
-int CpuUtilizationMain(int argc, char** argv) {
-  unsigned sleep_duration_us = 10 * 1000 * 1000;  // 10s
-  int sleep_intervals = 6;
-  int target_pid = -1;
-
-  static struct option long_options[] = {
-      {"pid", required_argument, nullptr, 'p'},
-      {"sleep-duration-us", required_argument, nullptr, 't'},
-      {"sleep-intervals", required_argument, nullptr, 'n'},
-      {nullptr, 0, nullptr, 0}};
-  int option_index;
-  int c;
-  while ((c = getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
-    switch (c) {
-      case 'p':
-        target_pid = atoi(optarg);
-        break;
-      case 't':
-        sleep_duration_us = static_cast<unsigned>(atoi(optarg));
-        break;
-      case 'n':
-        sleep_intervals = atoi(optarg);
-        break;
-      default:
-        break;
-    }
-  }
-
-  if (target_pid < 1) {
-    PERFETTO_ELOG(
-        "Usage: %s --pid=target_pid [--sleep-duration-us=N] "
-        "[--sleep-intervals=N]",
-        argv[0]);
-    return 1;
-  }
-
-  // Resolution of utime/stime from procfs, at least 10 ms.
-  long ticks = sysconf(_SC_CLK_TCK);
-  PERFETTO_CHECK(ticks >= 100);
-  unsigned long ticks_per_s = static_cast<unsigned long>(ticks);
-
-  // Resolution of wallclock time, at least 1 ms. Should be O(ns) in practice.
-  auto clk = CLOCK_MONOTONIC_RAW;
-  struct timespec ts = {};
-  PERFETTO_CHECK(clock_getres(clk, &ts) == 0);
-  PERFETTO_CHECK(ts.tv_sec == 0 && ts.tv_nsec <= 1 * 1000 * 1000);
-
-  PERFETTO_LOG("--- setup: ---");
-  PERFETTO_LOG("target pid: %d", target_pid);
-  PERFETTO_LOG("intervals: %d x %uus", sleep_intervals, sleep_duration_us);
-  PERFETTO_LOG("utime/stime ticks per sec: %ld", ticks_per_s);
-  PERFETTO_LOG("wall clock resolution (ns): %ld", ts.tv_nsec);
-  PERFETTO_LOG("--- timings: ---");
-
-  base::ScopedFile fd = base::OpenFile(
-      std::string("/proc/") + std::to_string(target_pid) + std::string("/stat"),
-      O_RDONLY);
-  PERFETTO_CHECK(fd);
-
-  // Read the base times.
-  unsigned long first_utime = 0;
-  unsigned long first_stime = 0;
-  ReadUtimeStime(fd, &first_utime, &first_stime);
-  uint64_t first_walltime_ms = ReadWallTimeMs(clk);
-
-  uint64_t last_walltime_ms = first_walltime_ms;
-  unsigned long last_utime = first_utime;
-  unsigned long last_stime = first_stime;
-
-  // Report the utilization for each fixed duration chunk.
-  for (int i = 0; i < sleep_intervals; i++) {
-    base::SleepMicroseconds(sleep_duration_us);
-
-    unsigned long utime = 0;
-    unsigned long stime = 0;
-    ReadUtimeStime(fd, &utime, &stime);
-    uint64_t walltime_ms = ReadWallTimeMs(clk);
-
-    uint64_t wall_diff_ms = walltime_ms - last_walltime_ms;
-    PERFETTO_LOG("wall_ms    : [%" PRIu64 "] - [%" PRIu64 "] = [%" PRIu64 "]",
-                 walltime_ms, last_walltime_ms, wall_diff_ms);
-
-    unsigned long utime_diff = utime - last_utime;
-    unsigned long stime_diff = stime - last_stime;
-    PERFETTO_LOG("utime_ticks: [%lu] - [%lu] = [%lu]", utime, last_utime,
-                 utime_diff);
-    PERFETTO_LOG("stime_ticks: [%lu] - [%lu] = [%lu]", stime, last_stime,
-                 stime_diff);
-
-    // Calculate the utilization, resolution of inputs will be no worse than
-    // 10ms due to the above assert. At the default 10s wall time, we therefore
-    // get a resolution of at least 0.1%.
-    double utime_diff_ms = static_cast<double>(utime_diff * 1000 / ticks_per_s);
-    double stime_diff_ms = static_cast<double>(stime_diff * 1000 / ticks_per_s);
-
-    double utime_ratio = utime_diff_ms / wall_diff_ms;
-    double stime_ratio = stime_diff_ms / wall_diff_ms;
-
-    PERFETTO_LOG("utime ratio   : %f", utime_ratio);
-    PERFETTO_LOG("stime ratio   : %f", stime_ratio);
-    PERFETTO_LOG("combined ratio: %f\n", utime_ratio + stime_ratio);
-
-    last_walltime_ms = walltime_ms;
-    last_utime = utime;
-    last_stime = stime;
-  }
-
-  PERFETTO_LOG("--- timings over the whole period: ---");
-  unsigned long utime_diff = last_utime - first_utime;
-  unsigned long stime_diff = last_stime - first_stime;
-  uint64_t wall_diff_ms = last_walltime_ms - first_walltime_ms;
-  double utime_diff_ms = static_cast<double>(utime_diff * 1000 / ticks_per_s);
-  double stime_diff_ms = static_cast<double>(stime_diff * 1000 / ticks_per_s);
-  double utime_ratio = utime_diff_ms / wall_diff_ms;
-  double stime_ratio = stime_diff_ms / wall_diff_ms;
-  PERFETTO_LOG("utime ratio   : %f", utime_ratio);
-  PERFETTO_LOG("stime ratio   : %f", stime_ratio);
-  PERFETTO_LOG("combined ratio: %f\n", utime_ratio + stime_ratio);
-
-  return 0;
-}
-
-}  // namespace
-}  // namespace perfetto
-
-int main(int argc, char** argv) {
-  return perfetto::CpuUtilizationMain(argc, argv);
-}
diff --git a/tools/diff_test_trace_processor.py b/tools/diff_test_trace_processor.py
index 8da9d45..d7329c6 100755
--- a/tools/diff_test_trace_processor.py
+++ b/tools/diff_test_trace_processor.py
@@ -17,189 +17,39 @@
 import difflib
 import glob
 import importlib
-import json
 import os
 import subprocess
 import sys
 import tempfile
 
-from itertools import chain
-from google.protobuf import descriptor, descriptor_pb2, message_factory
-from google.protobuf import reflection, text_format
-
 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+TEST_DATA_DIR = os.path.join(ROOT_DIR, "test", "trace_processor")
 
-
-class PerfResult(object):
-
-  def __init__(self, trace_name, query_or_metric, ingest_time, real_time):
-    self.trace_name = trace_name
-    self.query_or_metric = query_or_metric
-    self.ingest_time = ingest_time
-    self.real_time = real_time
-
-
-def create_message_factory(descriptor_file_path, proto_type):
-  with open(descriptor_file_path, 'rb') as descriptor_file:
-    descriptor_content = descriptor_file.read()
-
-  file_desc_set_pb2 = descriptor_pb2.FileDescriptorSet()
-  file_desc_set_pb2.MergeFromString(descriptor_content)
-
-  desc_by_path = {}
-  for f_desc_pb2 in file_desc_set_pb2.file:
-    f_desc_pb2_encode = f_desc_pb2.SerializeToString()
-    f_desc = descriptor.FileDescriptor(
-        name=f_desc_pb2.name,
-        package=f_desc_pb2.package,
-        serialized_pb=f_desc_pb2_encode)
-
-    for desc in f_desc.message_types_by_name.values():
-      desc_by_path[desc.full_name] = desc
-
-  return message_factory.MessageFactory().GetPrototype(desc_by_path[proto_type])
-
-
-def create_trace_message_factory(trace_descriptor_path):
-  return create_message_factory(trace_descriptor_path, 'perfetto.protos.Trace')
-
-
-def create_metrics_message_factory(metrics_descriptor_path):
-  return create_message_factory(metrics_descriptor_path,
-                                'perfetto.protos.TraceMetrics')
-
-
-def serialize_text_proto_to_file(proto_descriptor_path, text_proto_path,
-                                 output_file):
-  trace_message_factory = create_trace_message_factory(proto_descriptor_path)
-  proto = trace_message_factory()
-  with open(text_proto_path, 'r') as text_proto_file:
-    text_format.Merge(text_proto_file.read(), proto)
-  output_file.write(proto.SerializeToString())
-  output_file.flush()
-
-
-def write_diff(expected, actual):
-  expected_lines = expected.splitlines(True)
-  actual_lines = actual.splitlines(True)
-  diff = difflib.unified_diff(
-      expected_lines, actual_lines, fromfile='expected', tofile='actual')
-  for line in diff:
-    sys.stderr.write(line)
-
-
-class TestResult(object):
-
-  def __init__(self, test_type, input_name, cmd, expected, actual):
-    self.test_type = test_type
-    self.input_name = input_name
-    self.cmd = cmd
-    self.expected = expected
-    self.actual = actual
-
-
-def run_metrics_test(trace_processor_path, gen_trace_path, metric,
-                     expected_path, perf_path, metrics_message_factory):
-  with open(expected_path, 'r') as expected_file:
-    expected = expected_file.read()
-
-  json_output = os.path.basename(expected_path).endswith('.json.out')
-  cmd = [
-      trace_processor_path,
-      '--run-metrics',
-      metric,
-      '--metrics-output=%s' % ('json' if json_output else 'binary'),
-      gen_trace_path,
-      '--perf-file',
-      perf_path,
-  ]
-  actual = subprocess.check_output(cmd)
-
-  if json_output:
-    expected_text = expected
-    actual_text = actual
-  else:
-    # Expected will be in text proto format and we'll need to parse it to a real
-    # proto.
-    expected_message = metrics_message_factory()
-    text_format.Merge(expected, expected_message)
-
-    # Actual will be the raw bytes of the proto and we'll need to parse it into
-    # a message.
-    actual_message = metrics_message_factory()
-    actual_message.ParseFromString(actual)
-
-    # Convert both back to text format.
-    expected_text = text_format.MessageToString(expected_message)
-    actual_text = text_format.MessageToString(actual_message)
-
-  return TestResult('metric', metric, cmd, expected_text, actual_text)
-
-
-def run_query_test(trace_processor_path, gen_trace_path, query_path,
-                   expected_path, perf_path):
-  with open(expected_path, 'r') as expected_file:
-    expected = expected_file.read()
-
-  cmd = [
-      trace_processor_path,
-      '-q',
-      query_path,
-      gen_trace_path,
-      '--perf-file',
-      perf_path,
-  ]
-  actual = subprocess.check_output(cmd).decode('utf-8')
-
-  return TestResult('query', query_path, cmd, expected, actual)
-
+def trace_processor_command(trace_processor_path, trace_path, query_path):
+  return [trace_processor_path, '-q', query_path, trace_path]
 
 def main():
   parser = argparse.ArgumentParser()
-  parser.add_argument('--test-type', type=str, default='queries')
-  parser.add_argument('--trace-descriptor', type=str)
-  parser.add_argument('--metrics-descriptor', type=str)
-  parser.add_argument('--perf-file', type=str)
-  parser.add_argument(
-      'trace_processor', type=str, help='location of trace processor binary')
+  parser.add_argument('--index', type=str, help='location of index file',
+                      default=os.path.join(TEST_DATA_DIR, "index"))
+  parser.add_argument('--trace-descriptor', type=str,
+                      help='$(dirname trace_processor)/gen/protos/trace/trace.descriptor')
+  parser.add_argument('trace_processor', type=str,
+                      help='location of trace processor binary')
   args = parser.parse_args()
 
-  test_dir = os.path.join(ROOT_DIR, 'test')
-  if args.test_type == 'queries':
-    index = os.path.join(test_dir, 'trace_processor', 'index')
-  elif args.test_type == 'metrics':
-    index = os.path.join(test_dir, 'metrics', 'index')
-  else:
-    print('Unknown test type {}. Supported: queries, metircs'.format(
-        args.test_type))
-    return 1
-
-  with open(index, 'r') as file:
+  with open(args.index, 'r') as file:
     index_lines = file.readlines()
 
   if args.trace_descriptor:
     trace_descriptor_path = args.trace_descriptor
   else:
     out_path = os.path.dirname(args.trace_processor)
-    trace_protos_path = os.path.join(out_path, 'gen', 'protos', 'perfetto',
-                                     'trace')
-    trace_descriptor_path = os.path.join(trace_protos_path, 'trace.descriptor')
+    trace_protos_path = os.path.join(out_path, "gen", "protos", "trace")
+    trace_descriptor_path = os.path.join(trace_protos_path, "trace.descriptor")
 
-  if args.metrics_descriptor:
-    metrics_descriptor_path = args.metrics_descriptor
-  else:
-    out_path = os.path.dirname(args.trace_processor)
-    metrics_protos_path = os.path.join(out_path, 'gen', 'protos', 'perfetto',
-                                       'metrics')
-    metrics_descriptor_path = os.path.join(metrics_protos_path,
-                                           'metrics.descriptor')
-
-  metrics_message_factory = create_metrics_message_factory(
-      metrics_descriptor_path)
-
-  perf_data = []
   test_failure = 0
-  index_dir = os.path.dirname(index)
+  index_dir = os.path.dirname(args.index)
   for line in index_lines:
     stripped = line.strip()
     if stripped.startswith('#'):
@@ -207,113 +57,65 @@
     elif not stripped:
       continue
 
-    [trace_fname, query_fname_or_metric, expected_fname] = stripped.split(' ')
+    [trace_fname, query_fname, expected_fname] = stripped.split(' ')
 
     trace_path = os.path.abspath(os.path.join(index_dir, trace_fname))
+    query_path = os.path.abspath(os.path.join(index_dir, query_fname))
     expected_path = os.path.abspath(os.path.join(index_dir, expected_fname))
     if not os.path.exists(trace_path):
-      print('Trace file not found {}'.format(trace_path))
+      print("Trace file not found {}".format(trace_path))
+      return 1
+    elif not os.path.exists(query_path):
+      print("Query file not found {}".format(query_path))
       return 1
     elif not os.path.exists(expected_path):
-      print('Expected file not found {}'.format(expected_path))
+      print("Expected file not found {}".format(expected_path))
       return 1
 
-    if trace_path.endswith('.py'):
-      gen_trace_file = tempfile.NamedTemporaryFile()
-      python_cmd = ['python', trace_path, trace_descriptor_path]
-      subprocess.check_call(python_cmd, stdout=gen_trace_file)
-      gen_trace_path = os.path.realpath(gen_trace_file.name)
-    elif trace_path.endswith('.textproto'):
-      gen_trace_file = tempfile.NamedTemporaryFile()
-      serialize_text_proto_to_file(trace_descriptor_path, trace_path,
-                                   gen_trace_file)
-      gen_trace_path = os.path.realpath(gen_trace_file.name)
+    if trace_path.endswith(".py"):
+      with tempfile.NamedTemporaryFile() as out:
+        python_cmd = [
+          "python",
+          trace_path,
+          trace_descriptor_path
+        ]
+        subprocess.check_call(
+          python_cmd,
+          stdout=out
+        )
+        cmd = trace_processor_command(
+            args.trace_processor, out.name, query_path)
+        actual_raw = subprocess.check_output(cmd)
     else:
-      gen_trace_file = None
-      gen_trace_path = trace_path
+      cmd = trace_processor_command(
+          args.trace_processor, trace_path, query_path)
+      actual_raw = subprocess.check_output(cmd)
 
-    with tempfile.NamedTemporaryFile() as tmp_perf_file:
-      tmp_perf_path = tmp_perf_file.name
-      if args.test_type == 'queries':
-        query_path = os.path.abspath(
-            os.path.join(index_dir, query_fname_or_metric))
-        if not os.path.exists(query_path):
-          print('Query file not found {}'.format(query_path))
-          return 1
+    actual = actual_raw.decode("utf-8")
+    actual_lines = actual_raw.splitlines(True)
 
-        result = run_query_test(args.trace_processor, gen_trace_path,
-                                query_path, expected_path, tmp_perf_path)
-      elif args.test_type == 'metrics':
-        result = run_metrics_test(args.trace_processor, gen_trace_path,
-                                  query_fname_or_metric, expected_path,
-                                  tmp_perf_path, metrics_message_factory)
-      else:
-        assert False
+    with open(expected_path, "r") as expected_file:
+      expected = expected_file.read()
+      if expected != actual:
+        sys.stderr.write(
+          "Expected did not match actual for trace {} and query {}\n"
+          .format(trace_path, query_path))
+        sys.stderr.write("Expected file: {}\n".format(expected_path))
+        sys.stderr.write("Commandline: {}\n".format(' '.join(cmd)))
 
-      perf_lines = tmp_perf_file.readlines()
-
-    if gen_trace_file:
-      gen_trace_file.close()
-
-    if result.expected == result.actual:
-      assert len(perf_lines) == 1
-      perf_numbers = perf_lines[0].split(',')
-
-      trace_shortpath = os.path.relpath(trace_path, test_dir)
-
-      assert len(perf_numbers) == 2
-      perf_result = PerfResult(trace_shortpath, query_fname_or_metric,
-                               perf_numbers[0], perf_numbers[1])
-      perf_data.append(perf_result)
-    else:
-      sys.stderr.write(
-          'Expected did not match actual for trace {} and {} {}\n'.format(
-              trace_path, result.test_type, result.input_name))
-      sys.stderr.write('Expected file: {}\n'.format(expected_path))
-      sys.stderr.write('Command line: {}\n'.format(' '.join(result.cmd)))
-
-      write_diff(result.expected, result.actual)
-
-      test_failure += 1
+        expected_lines = expected.splitlines(True)
+        diff = difflib.unified_diff(expected_lines, actual_lines,
+                                    fromfile="expected", tofile="actual")
+        for line in diff:
+          sys.stderr.write(line)
+        test_failure += 1
 
   if test_failure == 0:
-    print('All tests passed successfully')
-
-    if args.perf_file:
-      metrics = [[{
-          'metric': 'tp_perf_test_ingest_time',
-          'value': float(perf_args.ingest_time) / 1.0e9,
-          'unit': 's',
-          'tags': {
-              'test_name':
-                  '{}-{}'.format(perf_args.trace_name,
-                                 perf_args.query_or_metric),
-              'test_type':
-                  args.test_type,
-          },
-          'labels': {},
-      },
-                  {
-                      'metric': 'perf_test_real_time',
-                      'value': float(perf_args.real_time) / 1.0e9,
-                      'unit': 's',
-                      'tags': {
-                          'test_name':
-                              '{}-{}'.format(perf_args.trace_name,
-                                             perf_args.query_or_metric),
-                          'test_type':
-                              args.test_type,
-                      },
-                      'labels': {},
-                  }] for perf_args in sorted(perf_data)]
-      output_data = {'metrics': list(chain.from_iterable(metrics))}
-      with open(args.perf_file, 'w+') as perf_file:
-        perf_file.write(json.dumps(output_data, indent=2))
+    print("All tests passed successfully")
     return 0
   else:
-    print('Total failures: {}'.format(test_failure))
+    print("Total failures: {}".format(test_failure))
     return 1
 
-
 if __name__ == '__main__':
   sys.exit(main())
diff --git a/tools/dump_ftrace_stats/main.cc b/tools/dump_ftrace_stats/main.cc
index c28812d..032aaa9 100644
--- a/tools/dump_ftrace_stats/main.cc
+++ b/tools/dump_ftrace_stats/main.cc
@@ -16,12 +16,12 @@
 
 #include <signal.h>
 
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/string_writer.h"
-#include "perfetto/ext/base/unix_task_runner.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/file_utils.h"
+#include "perfetto/base/string_splitter.h"
+#include "perfetto/base/string_utils.h"
+#include "perfetto/base/string_writer.h"
+#include "perfetto/base/unix_task_runner.h"
+#include "perfetto/base/utils.h"
 
 namespace perfetto {
 namespace {
diff --git a/tools/extract_linux_syscall_tables b/tools/extract_linux_syscall_tables
index 4b2def0..9252f26 100755
--- a/tools/extract_linux_syscall_tables
+++ b/tools/extract_linux_syscall_tables
@@ -20,7 +20,7 @@
   table = {}
   for line in data.splitlines():
     line = line.strip()
-    if line.startswith('#') or not (line):
+    if line.startswith('#') or not(line):
       continue
     parts = line.split()
     table[int(parts[0])] = 'sys_' + parts[2]
diff --git a/tools/find_scan_roots.py b/tools/find_scan_roots.py
index b483bfb..c17a9f2 100755
--- a/tools/find_scan_roots.py
+++ b/tools/find_scan_roots.py
@@ -21,9 +21,7 @@
 import sys
 import argparse
 
-
 class Node(object):
-
   def __init__(self, name, label=None):
     self.name = name
     self.label = label
@@ -83,8 +81,8 @@
 
 def main():
   parser = argparse.ArgumentParser()
-  parser.add_argument(
-      'labels', metavar='L', type=str, nargs='+', help='labels we want to find')
+  parser.add_argument('labels', metavar='L', type=str, nargs='+',
+                      help='labels we want to find')
   args = parser.parse_args()
   root = BuildTree()
   for fullpath, elem in root:
diff --git a/tools/fix_include_guards b/tools/fix_include_guards
index 4f08b41..8c8d4e0 100755
--- a/tools/fix_include_guards
+++ b/tools/fix_include_guards
@@ -13,23 +13,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import print_function
-
 import os
 import re
 import sys
 
-from codecs import open
-from compat import xrange
-
-
 def fix_guards(fpath, checkonly):
-  with open(fpath, 'r', encoding='utf-8') as f:
+  with open(fpath, 'rb') as f:
     lines = [l.strip('\n') for l in f.readlines()]
-
-  if any(x.startswith('// fix_include_guards: off') for x in lines):
-    return 0
-
   res = []
   guard = re.sub(r'[^a-zA-Z0-9_-]', '_', fpath.upper()) + '_'
   replacements = 0
@@ -50,20 +40,19 @@
       line = '#define ' + guard
       replacements = 2
     elif line_idx == endif_line_idx and replacements == 2:
-      assert (line.startswith('#endif'))
+      assert(line.startswith('#endif'))
       line = '#endif  // ' + guard
     res.append(line)
     line_idx += 1
   if res == lines:
     return 0
   if checkonly:
-    print('Wrong #include guards in %s' % fpath, file=sys.stderr)
+    print >>sys.stderr, 'Wrong #include guards in %s' % fpath
     return 1
-  with open(fpath, 'w', encoding='utf-8') as f:
+  with open(fpath, 'w') as f:
     f.write('\n'.join(res) + '\n')
   return 1
 
-
 def main():
   checkonly = '--check-only' in sys.argv
   num_files_changed = 0
@@ -77,8 +66,7 @@
   if checkonly:
     return 0 if num_files_changed == 0 else 1
   else:
-    print('%d files changed' % num_files_changed)
-
+    print '%d files changed' % num_files_changed
 
 if __name__ == '__main__':
   sys.exit(main())
diff --git a/tools/ftrace_proto_gen/BUILD.gn b/tools/ftrace_proto_gen/BUILD.gn
index a63d696..20727bb 100644
--- a/tools/ftrace_proto_gen/BUILD.gn
+++ b/tools/ftrace_proto_gen/BUILD.gn
@@ -12,37 +12,20 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import("../../gn/perfetto_host_executable.gni")
-import("../../gn/test.gni")
-
-perfetto_host_executable("ftrace_proto_gen") {
-  testonly = true
-  sources = [
-    "main.cc",
-  ]
-  deps = [
-    ":lib",
-    "../../gn:default_deps",
-    "../../gn:protobuf_full",
-    "../../src/base",
-    "../../src/traced/probes/ftrace:format_parser",
-  ]
-}
-
-perfetto_unittest_source_set("unittests") {
+source_set("unittests") {
   testonly = true
   deps = [
-    ":lib",
+    ":ftrace_proto_gen_src",
     "../../gn:default_deps",
-    "../../gn:gtest_and_gmock",
-    "../../gn:protobuf_full",
+    "../../gn:gtest_deps",
+    "../../gn:protobuf_full_deps",
   ]
   sources = [
     "ftrace_proto_gen_unittest.cc",
   ]
 }
 
-source_set("lib") {
+source_set("ftrace_proto_gen_src") {
   testonly = true
   sources = [
     "ftrace_descriptor_gen.cc",
@@ -54,7 +37,21 @@
   ]
   deps = [
     "../../gn:default_deps",
-    "../../gn:protobuf_full",
+    "../../gn:protobuf_full_deps",
+    "../../src/base",
+    "../../src/traced/probes/ftrace:format_parser",
+  ]
+}
+
+executable("ftrace_proto_gen") {
+  testonly = true
+  sources = [
+    "main.cc",
+  ]
+  deps = [
+    ":ftrace_proto_gen_src",
+    "../../gn:default_deps",
+    "../../gn:protobuf_full_deps",
     "../../src/base",
     "../../src/traced/probes/ftrace:format_parser",
   ]
diff --git a/tools/ftrace_proto_gen/ftrace_descriptor_gen.cc b/tools/ftrace_proto_gen/ftrace_descriptor_gen.cc
index 65f0f5f..fbd1ec7 100644
--- a/tools/ftrace_proto_gen/ftrace_descriptor_gen.cc
+++ b/tools/ftrace_proto_gen/ftrace_descriptor_gen.cc
@@ -35,13 +35,13 @@
   *fout << std::string("// ") + __FILE__ + "\n";
   *fout << "// Do not edit.\n";
   *fout << R"(
-#include "src/trace_processor/importers/ftrace/ftrace_descriptors.h"
+  #include "src/trace_processor/ftrace_descriptors.h"
 
-namespace perfetto {
-namespace trace_processor {
-namespace {
+  namespace perfetto {
+  namespace trace_processor {
+  namespace {
 
-std::array<MessageDescriptor,
+  std::array<MessageDescriptor,
   )";
   *fout << std::to_string(max_id + 1) + "> descriptors{{";
 
@@ -82,16 +82,16 @@
   }
   *fout << "}};\n";
   *fout << R"(
-} // namespace
+  } // namespace
 
-MessageDescriptor* GetMessageDescriptorForId(size_t id) {
-  PERFETTO_CHECK(id < descriptors.size());
-  return &descriptors[id];
-}
+  MessageDescriptor* GetMessageDescriptorForId(size_t id) {
+    PERFETTO_CHECK(id < descriptors.size());
+    return &descriptors[id];
+  }
 
-size_t GetDescriptorsSize() {
-  return descriptors.size();
-}
+  size_t GetDescriptorsSize() {
+    return descriptors.size();
+  }
   )";
   *fout << "} // namespace trace_processor\n} // namespace perfetto\n";
 }
diff --git a/tools/ftrace_proto_gen/ftrace_proto_gen.cc b/tools/ftrace_proto_gen/ftrace_proto_gen.cc
index 1b76c05..e545622 100644
--- a/tools/ftrace_proto_gen/ftrace_proto_gen.cc
+++ b/tools/ftrace_proto_gen/ftrace_proto_gen.cc
@@ -23,11 +23,11 @@
 #include <fstream>
 #include <regex>
 
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/pipe.h"
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/ext/base/string_utils.h"
+#include "perfetto/base/pipe.h"
+#include "perfetto/base/string_splitter.h"
+#include "perfetto/base/string_utils.h"
 
 namespace perfetto {
 
@@ -58,6 +58,52 @@
   return lines;
 }
 
+void PrintEventFormatterMain(const std::set<std::string>& events) {
+  printf(
+      "\nAdd output to FormatEventText in "
+      "tools/trace_to_text/ftrace_event_formatter.cc\n");
+  for (auto event : events) {
+    printf(
+        "else if (event.has_%s()) {\nconst auto& inner = event.%s();\nreturn "
+        "Format%s(inner);\n} ",
+        event.c_str(), event.c_str(), ToCamelCase(event).c_str());
+  }
+}
+
+// Add output to ParseInode in ftrace_inode_handler
+void PrintInodeHandlerMain(const std::string& event_name,
+                           const perfetto::Proto& proto) {
+  for (const auto& p : proto.fields) {
+    const Proto::Field& field = p.second;
+    if (Contains(field.name, "ino") && !Contains(field.name, "minor"))
+      printf(
+          "else if (event.has_%s() && event.%s().%s()) {\n*inode = "
+          "static_cast<uint64_t>(event.%s().%s());\n return true;\n} ",
+          event_name.c_str(), event_name.c_str(), field.name.c_str(),
+          event_name.c_str(), field.name.c_str());
+  }
+}
+
+void PrintEventFormatterUsingStatements(const std::set<std::string>& events) {
+  printf("\nAdd output to tools/trace_to_text/ftrace_event_formatter.cc\n");
+  for (auto event : events) {
+    printf("using protos::%sFtraceEvent;\n", ToCamelCase(event).c_str());
+  }
+}
+
+void PrintEventFormatterFunctions(const std::set<std::string>& events) {
+  printf(
+      "\nAdd output to tools/trace_to_text/ftrace_event_formatter.cc and "
+      "then manually go through format files to match fields\n");
+  for (auto event : events) {
+    printf(
+        "std::string Format%s(const %sFtraceEvent& event) {"
+        "\nchar line[2048];"
+        "\nsprintf(line,\"%s: );\nreturn std::string(line);\n}\n",
+        ToCamelCase(event).c_str(), ToCamelCase(event).c_str(), event.c_str());
+  }
+}
+
 bool GenerateProto(const FtraceEvent& format, Proto* proto_out) {
   proto_out->name = EventNameToProtoName(format.name);
   proto_out->event_name = format.name;
@@ -98,11 +144,10 @@
   *fout << "option optimize_for = LITE_RUNTIME;\n\n";
 
   for (const std::string& group : groups) {
-    *fout << R"(import "protos/perfetto/trace/ftrace/)" << group
-          << R"(.proto";)"
+    *fout << R"(import "perfetto/trace/ftrace/)" << group << R"(.proto";)"
           << "\n";
   }
-  *fout << "import \"protos/perfetto/trace/ftrace/generic.proto\";\n";
+  *fout << "import \"perfetto/trace/ftrace/generic.proto\";\n";
   *fout << "\n";
   *fout << "package perfetto.protos;\n\n";
   *fout << R"(message FtraceEvent {
@@ -159,29 +204,16 @@
 std::string SingleEventInfo(perfetto::Proto proto,
                             const std::string& group,
                             const uint32_t proto_field_id) {
-  std::string s = "{";
-  s += "\"" + proto.event_name + "\", ";
-  s += "\"" + group + "\", ";
+  std::string s = "";
+  s += "    event->name = \"" + proto.event_name + "\";\n";
+  s += "    event->group = \"" + group + "\";\n";
+  s += "    event->proto_field_id = " + std::to_string(proto_field_id) + ";\n";
 
-  // Vector of fields.
-  s += "{ ";
   for (const auto& field : proto.SortedFields()) {
-    s += "{";
-    s += "kUnsetOffset, ";
-    s += "kUnsetSize, ";
-    s += "FtraceFieldType::kInvalidFtraceFieldType, ";
-    s += "\"" + field->name + "\", ";
-    s += std::to_string(field->number) + ", ";
-    s += "ProtoSchemaType::k" + ToCamelCase(field->type.ToString()) + ", ";
-    s += "TranslationStrategy::kInvalidTranslationStrategy";
-    s += "}, ";
+    s += "    event->fields.push_back(MakeField(\"" + field->name + "\", " +
+         std::to_string(field->number) + ", ProtoSchemaType::k" +
+         ToCamelCase(field->type.ToString()) + "));\n";
   }
-  s += "}, ";
-
-  s += "kUnsetFtraceId, ";
-  s += std::to_string(proto_field_id) + ", ";
-  s += "kUnsetSize";
-  s += "}";
   return s;
 }
 
@@ -200,20 +232,20 @@
 using protozero::proto_utils::ProtoSchemaType;
 
 std::vector<Event> GetStaticEventInfo() {
-  static constexpr uint16_t kUnsetOffset = 0;
-  static constexpr uint16_t kUnsetSize = 0;
-  static constexpr uint16_t kUnsetFtraceId = 0;
-  return
+  std::vector<Event> events;
 )";
 
-  s += " {";
   for (const auto& event : events_info) {
+    s += "\n";
+    s += "  {\n";
+    s += "    events.emplace_back(Event{});\n";
+    s += "    Event* event = &events.back();\n";
     s += event;
-    s += ",\n";
+    s += "  }\n";
   }
-  s += "};";
 
   s += R"(
+  return events;
 }
 
 }  // namespace perfetto
diff --git a/tools/ftrace_proto_gen/ftrace_proto_gen.h b/tools/ftrace_proto_gen/ftrace_proto_gen.h
index 7258737..9136ef0 100644
--- a/tools/ftrace_proto_gen/ftrace_proto_gen.h
+++ b/tools/ftrace_proto_gen/ftrace_proto_gen.h
@@ -32,6 +32,13 @@
 std::string EventNameToProtoName(const std::string&);
 std::string EventNameToProtoFieldName(const std::string&);
 
+void PrintFtraceEventProtoAdditions(const std::set<std::string>& events);
+void PrintEventFormatterMain(const std::set<std::string>& events);
+void PrintEventFormatterUsingStatements(const std::set<std::string>& events);
+void PrintEventFormatterFunctions(const std::set<std::string>& events);
+void PrintInodeHandlerMain(const std::string& event_name,
+                           const perfetto::Proto& proto);
+
 std::vector<FtraceEventName> ReadWhitelist(const std::string& filename);
 void GenerateFtraceEventProto(const std::vector<FtraceEventName>& raw_whitelist,
                               const std::set<std::string>& groups,
diff --git a/tools/ftrace_proto_gen/ftrace_proto_gen_unittest.cc b/tools/ftrace_proto_gen/ftrace_proto_gen_unittest.cc
index 6d0d46d..8943e7b 100644
--- a/tools/ftrace_proto_gen/ftrace_proto_gen_unittest.cc
+++ b/tools/ftrace_proto_gen/ftrace_proto_gen_unittest.cc
@@ -15,7 +15,7 @@
  */
 
 #include "tools/ftrace_proto_gen/ftrace_proto_gen.h"
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace {
diff --git a/tools/ftrace_proto_gen/main.cc b/tools/ftrace_proto_gen/main.cc
index 65f2e2d..c539372 100644
--- a/tools/ftrace_proto_gen/main.cc
+++ b/tools/ftrace_proto_gen/main.cc
@@ -27,8 +27,8 @@
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/descriptor.pb.h>
 
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
 #include "src/traced/probes/ftrace/format_parser.h"
 #include "tools/ftrace_proto_gen/ftrace_descriptor_gen.h"
 #include "tools/ftrace_proto_gen/ftrace_proto_gen.h"
@@ -42,13 +42,6 @@
     const std::string& filename) {
   return std::unique_ptr<std::ostream>(new perfetto::VerifyStream(filename));
 }
-
-void PrintUsage(const char* bin_name) {
-  fprintf(stderr,
-          "Usage: %s -w whitelist_dir -o output_dir -d proto_descriptor "
-          "[--check_only] input_dir...\n",
-          bin_name);
-}
 }  // namespace
 
 int main(int argc, char** argv) {
@@ -58,7 +51,7 @@
       {"proto_descriptor", required_argument, nullptr, 'd'},
       {"update_build_files", no_argument, nullptr, 'b'},
       {"check_only", no_argument, nullptr, 'c'},
-      {nullptr, 0, nullptr, 0}};
+  };
 
   int option_index;
   int c;
@@ -87,23 +80,21 @@
         break;
       case 'c':
         ostream_factory = &MakeVerifyStream;
-        break;
-      default: {
-        PrintUsage(argv[0]);
-        return 1;
-      }
     }
   }
 
-  if (optind >= argc) {
-    PrintUsage(argv[0]);
-    return 1;
-  }
-
   PERFETTO_CHECK(!whitelist_path.empty());
   PERFETTO_CHECK(!output_dir.empty());
   PERFETTO_CHECK(!proto_descriptor.empty());
 
+  if (optind >= argc) {
+    fprintf(stderr,
+            "Usage: ./%s -w whitelist_dir -o output_dir -d proto_descriptor "
+            "[--check_only] input_dir...\n",
+            argv[0]);
+    return 1;
+  }
+
   std::vector<perfetto::FtraceEventName> whitelist =
       perfetto::ReadWhitelist(whitelist_path);
   std::vector<std::string> events_info;
@@ -146,6 +137,15 @@
     perfetto::GenerateFtraceEventProto(whitelist, groups, out.get());
   }
 
+  if (!new_events.empty()) {
+    perfetto::PrintEventFormatterMain(new_events);
+    perfetto::PrintEventFormatterUsingStatements(new_events);
+    perfetto::PrintEventFormatterFunctions(new_events);
+    printf(
+        "\nAdd output to ParseInode in "
+        "tools/ftrace_proto_gen/ftrace_inode_handler.cc\n");
+  }
+
   for (const std::string& group : groups) {
     std::string proto_file_name = group + ".proto";
     std::string output_path = output_dir + std::string("/") + proto_file_name;
@@ -198,6 +198,9 @@
         proto.MergeFrom(event_proto);
       }
 
+      if (!new_events.empty())
+        PrintInodeHandlerMain(proto.name, proto);
+
       uint32_t i = 0;
       for (; it->second != &whitelist[i]; i++)
         ;
@@ -219,8 +222,8 @@
   }
 
   {
-    std::unique_ptr<std::ostream> out = ostream_factory(
-        "src/trace_processor/importers/ftrace/ftrace_descriptors.cc");
+    std::unique_ptr<std::ostream> out =
+        ostream_factory("src/trace_processor/ftrace_descriptors.cc");
     perfetto::GenerateFtraceDescriptors(descriptor_pool, out.get());
     PERFETTO_CHECK(!out->fail());
   }
diff --git a/tools/ftrace_proto_gen/proto_gen_utils.cc b/tools/ftrace_proto_gen/proto_gen_utils.cc
index 6fa9e3f..9e9f34e 100644
--- a/tools/ftrace_proto_gen/proto_gen_utils.cc
+++ b/tools/ftrace_proto_gen/proto_gen_utils.cc
@@ -23,11 +23,11 @@
 #include <fstream>
 #include <regex>
 
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/pipe.h"
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/ext/base/string_utils.h"
+#include "perfetto/base/pipe.h"
+#include "perfetto/base/string_splitter.h"
+#include "perfetto/base/string_utils.h"
 
 namespace perfetto {
 
@@ -91,10 +91,9 @@
 
 }  // namespace
 
-using base::Contains;
 using base::EndsWith;
 using base::StartsWith;
-using base::Uppercase;
+using base::Contains;
 
 VerifyStream::VerifyStream(std::string filename)
     : filename_(std::move(filename)) {
@@ -147,7 +146,7 @@
     }
     if (upperCaseNextChar) {
       upperCaseNextChar = false;
-      c = Uppercase(c);
+      c = static_cast<char>(toupper(c));
     }
     result.push_back(c);
   }
diff --git a/tools/gen_all b/tools/gen_all
index 92d545c..6b8e062 100755
--- a/tools/gen_all
+++ b/tools/gen_all
@@ -13,7 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import print_function
 import os
 import argparse
 import subprocess
@@ -22,7 +21,7 @@
 
 
 def protoc_path(out_directory):
-  path = os.path.join(out_directory, 'protoc')
+  path = os.path.join(out_directory, 'gcc_like_host', 'protoc')
   assert os.path.isfile(path)
   return path
 
@@ -30,7 +29,7 @@
 def call(cmd, *args):
   path = os.path.join('tools', cmd)
   command = [path] + list(args)
-  print('Running', ' '.join(command))
+  print 'Running ', ' '.join(command)
   try:
     subprocess.check_call(command, cwd=ROOT_DIR)
   except subprocess.CalledProcessError as e:
@@ -39,7 +38,6 @@
 
 def main():
   parser = argparse.ArgumentParser()
-  parser.add_argument('--check-only', default=False, action='store_true')
   parser.add_argument('OUT')
   args = parser.parse_args()
   out = args.OUT
@@ -47,14 +45,13 @@
   try:
     assert os.path.isdir(out), \
         'Output directory "{}" is not a directory'.format(out)
-    check_only = ['--check-only'] if args.check_only else []
-    call('check_include_violations')
-    call('fix_include_guards', *check_only)
-    call('gen_bazel', *check_only)
-    call('gen_android_bp', *check_only)
-    call('gen_merged_protos', *check_only)
-    call('ninja', '-C', out, 'protoc')
-    call('gen_binary_descriptors', '--protoc', protoc_path(out), *check_only)
+    call('fix_include_guards')
+    call('gen_build')
+    call('gen_android_bp')
+    call('gen_merged_protos')
+    call('gen_binary_descriptors', '--protoc', protoc_path(out))
+    call('gen_tracing_cpp_headers_from_protos', out)
+    call('gen_amalgamated', '--check', '--quiet')  # Keep last
 
   except AssertionError as e:
     if not str(e):
@@ -64,6 +61,5 @@
 
   return 0
 
-
 if __name__ == '__main__':
   exit(main())
diff --git a/tools/gen_amalgamated b/tools/gen_amalgamated
deleted file mode 100755
index ea6e254..0000000
--- a/tools/gen_amalgamated
+++ /dev/null
@@ -1,608 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2019 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 tool uses a collection of BUILD.gn files and build targets to generate
-# an "amalgamated" C++ header and source file pair which compiles to an
-# equivalent program. The tool also outputs the necessary compiler and linker
-# flags needed to compile the resulting source code.
-
-from __future__ import print_function
-import argparse
-import os
-import re
-import shutil
-import subprocess
-import sys
-import tempfile
-
-import gn_utils
-
-# Default targets to include in the result.
-# TODO(primiano): change this script to recurse into target deps when generating
-# headers, but only for proto targets. .pbzero.h files don't include each other
-# and we need to list targets here individually, which is unmaintainable.
-default_targets = [
-    '//:libperfetto_client_experimental',
-    '//include/perfetto/protozero:protozero',
-    '//protos/perfetto/config:zero',
-    '//protos/perfetto/trace:zero',
-]
-
-# Arguments for the GN output directory (unless overridden from the command
-# line).
-gn_args = ' '.join([
-    'is_debug=false',
-    'is_perfetto_build_generator=true',
-    'is_perfetto_embedder=true',
-    'use_custom_libcxx=false',
-    'enable_perfetto_ipc=true',
-])
-
-# By default, the amalgamated .h only recurses in #includes but not in the
-# target deps. In the case of protos we want to follow deps even in lieu of
-# direct #includes. This is because, by design, protozero headers don't
-# inlcude each other but rely on forward declarations. The alternative would
-# be adding each proto sub-target individually (e.g. //proto/trace/gpu:zero),
-# but doing that is unmaintainable.
-recurse_in_header_deps = '^//protos/.*zero$'
-
-# Compiler flags which aren't filtered out.
-cflag_whitelist = r'^-(W.*|fno-exceptions|fPIC|std.*|fvisibility.*)$'
-
-# Linker flags which aren't filtered out.
-ldflag_whitelist = r'^-()$'
-
-# Libraries which are filtered out.
-lib_blacklist = r'^(c|gcc_eh)$'
-
-# Macros which aren't filtered out.
-define_whitelist = r'^(PERFETTO.*|GOOGLE_PROTOBUF.*)$'
-
-# Includes which will be removed from the generated source.
-includes_to_remove = r'^(gtest).*$'
-
-default_cflags = [
-    # Since we're expanding header files into the generated source file, some
-    # constant may remain unused.
-    '-Wno-unused-const-variable'
-]
-
-# Build flags to satisfy a protobuf (lite or full) dependency.
-protobuf_cflags = [
-    # Note that these point to the local copy of protobuf in buildtools. In
-    # reality the user of the amalgamated result will have to provide a path to
-    # an installed copy of the exact same version of protobuf which was used to
-    # generate the amalgamated build.
-    '-isystembuildtools/protobuf/src',
-    '-Lbuildtools/protobuf/src/.libs',
-    # We also need to disable some warnings for protobuf.
-    '-Wno-missing-prototypes',
-    '-Wno-missing-variable-declarations',
-    '-Wno-sign-conversion',
-    '-Wno-unknown-pragmas',
-    '-Wno-unused-macros',
-]
-
-# A mapping of dependencies to system libraries. Libraries in this map will not
-# be built statically but instead added as dependencies of the amalgamated
-# project.
-system_library_map = {
-    '//buildtools:protobuf_full': {
-        'libs': ['protobuf'],
-        'cflags': protobuf_cflags,
-    },
-    '//buildtools:protobuf_lite': {
-        'libs': ['protobuf-lite'],
-        'cflags': protobuf_cflags,
-    },
-    '//buildtools:protoc_lib': {
-        'libs': ['protoc']
-    },
-}
-
-# ----------------------------------------------------------------------------
-# End of configuration.
-# ----------------------------------------------------------------------------
-
-tool_name = os.path.basename(__file__)
-preamble = """// Copyright (C) 2019 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 file is automatically generated by %s. Do not edit.
-""" % tool_name
-
-
-def apply_blacklist(blacklist, items):
-  return [item for item in items if not re.match(blacklist, item)]
-
-
-def apply_whitelist(whitelist, items):
-  return [item for item in items if re.match(whitelist, item)]
-
-
-class Error(Exception):
-  pass
-
-
-class DependencyNode(object):
-  """A target in a GN build description along with its dependencies."""
-
-  def __init__(self, target_name):
-    self.target_name = target_name
-    self.dependencies = set()
-
-  def add_dependency(self, target_node):
-    if target_node in self.dependencies:
-      return
-    self.dependencies.add(target_node)
-
-  def iterate_depth_first(self):
-    for node in sorted(self.dependencies, key=lambda n: n.target_name):
-      for node in node.iterate_depth_first():
-        yield node
-    if self.target_name:
-      yield self
-
-
-class DependencyTree(object):
-  """A tree of GN build target dependencies."""
-
-  def __init__(self):
-    self.target_to_node_map = {}
-    self.root = self._get_or_create_node(None)
-
-  def _get_or_create_node(self, target_name):
-    if target_name in self.target_to_node_map:
-      return self.target_to_node_map[target_name]
-    node = DependencyNode(target_name)
-    self.target_to_node_map[target_name] = node
-    return node
-
-  def add_dependency(self, from_target, to_target):
-    from_node = self._get_or_create_node(from_target)
-    to_node = self._get_or_create_node(to_target)
-    assert from_node is not to_node
-    from_node.add_dependency(to_node)
-
-  def iterate_depth_first(self):
-    for node in self.root.iterate_depth_first():
-      yield node
-
-
-class AmalgamatedProject(object):
-  """In-memory representation of an amalgamated source/header pair."""
-
-  def __init__(self, desc, source_deps, compute_deps_only=False):
-    """Constructor.
-
-        Args:
-            desc: JSON build description.
-            source_deps: A map of (source file, [dependency header]) which is
-                to detect which header files are included by each source file.
-            compute_deps_only: If True, the project will only be used to compute
-                dependency information. Use |get_source_files()| to retrieve
-                the result.
-        """
-    self.desc = desc
-    self.source_deps = source_deps
-    self.header = []
-    self.source = []
-    self.source_defines = []
-    # Note that we don't support multi-arg flags.
-    self.cflags = set(default_cflags)
-    self.ldflags = set()
-    self.defines = set()
-    self.libs = set()
-    self._dependency_tree = DependencyTree()
-    self._processed_sources = set()
-    self._processed_headers = set()
-    self._processed_header_deps = set()
-    self._processed_source_headers = set()  # Header files included from .cc
-    self._include_re = re.compile(r'#include "(.*)"')
-    self._compute_deps_only = compute_deps_only
-
-  def add_target(self, target_name):
-    """Include |target_name| in the amalgamated result."""
-    self._dependency_tree.add_dependency(None, target_name)
-    self._add_target_dependencies(target_name)
-    self._add_target_flags(target_name)
-    self._add_target_headers(target_name)
-
-    # Recurse into target deps, but only for protos. This generates headers
-    # for all the .pbzero.h files, even if they don't #include each other.
-    for _, dep in self._iterate_dep_edges(target_name):
-      if (dep not in self._processed_header_deps and
-          re.match(recurse_in_header_deps, dep)):
-        self._processed_header_deps.add(dep)
-        self.add_target(dep)
-
-  def _iterate_dep_edges(self, target_name):
-    target = self.desc[target_name]
-    for dep in target.get('deps', []):
-      # Ignore system libraries since they will be added as build-time
-      # dependencies.
-      if dep in system_library_map:
-        continue
-      # Don't descend into build action dependencies.
-      if self.desc[dep]['type'] == 'action':
-        continue
-      for sub_target, sub_dep in self._iterate_dep_edges(dep):
-        yield sub_target, sub_dep
-      yield target_name, dep
-
-  def _iterate_target_and_deps(self, target_name):
-    yield target_name
-    for _, dep in self._iterate_dep_edges(target_name):
-      yield dep
-
-  def _add_target_dependencies(self, target_name):
-    for target, dep in self._iterate_dep_edges(target_name):
-      self._dependency_tree.add_dependency(target, dep)
-
-    def process_dep(dep):
-      if dep in system_library_map:
-        self.libs.update(system_library_map[dep].get('libs', []))
-        self.cflags.update(system_library_map[dep].get('cflags', []))
-        self.defines.update(system_library_map[dep].get('defines', []))
-        return True
-
-    def walk_all_deps(target_name):
-      target = self.desc[target_name]
-      for dep in target.get('deps', []):
-        if process_dep(dep):
-          return
-        walk_all_deps(dep)
-
-    walk_all_deps(target_name)
-
-  def _filter_cflags(self, cflags):
-    # Since we want to deduplicate flags, combine two-part switches (e.g.,
-    # "-foo bar") into one value ("-foobar") so we can store the result as
-    # a set.
-    result = []
-    for flag in cflags:
-      if flag.startswith('-'):
-        result.append(flag)
-      else:
-        result[-1] += flag
-    return apply_whitelist(cflag_whitelist, result)
-
-  def _add_target_flags(self, target_name):
-    for target_name in self._iterate_target_and_deps(target_name):
-      target = self.desc[target_name]
-      self.cflags.update(self._filter_cflags(target.get('cflags', [])))
-      self.cflags.update(self._filter_cflags(target.get('cflags_cc', [])))
-      self.ldflags.update(
-          apply_whitelist(ldflag_whitelist, target.get('ldflags', [])))
-      self.libs.update(apply_blacklist(lib_blacklist, target.get('libs', [])))
-      self.defines.update(
-          apply_whitelist(define_whitelist, target.get('defines', [])))
-
-  def _add_target_headers(self, target_name):
-    target = self.desc[target_name]
-    if not 'sources' in target:
-      return
-    headers = [
-        gn_utils.label_to_path(s) for s in target['sources'] if s.endswith('.h')
-    ]
-    for header in headers:
-      self._add_header(target_name, header)
-
-  def _get_include_dirs(self, target_name):
-    include_dirs = set()
-    for target_name in self._iterate_target_and_deps(target_name):
-      target = self.desc[target_name]
-      if 'include_dirs' in target:
-        include_dirs.update(
-            [gn_utils.label_to_path(d) for d in target['include_dirs']])
-    return include_dirs
-
-  def _add_source_included_header(self, include_dirs, allowed_files,
-                                  header_name):
-    if header_name in self._processed_source_headers:
-      return
-    self._processed_source_headers.add(header_name)
-    for include_dir in include_dirs:
-      rel_path = os.path.join(include_dir, header_name)
-      full_path = os.path.join(gn_utils.repo_root(), rel_path)
-      if os.path.exists(full_path):
-        if not rel_path in allowed_files:
-          return
-        with open(full_path) as f:
-          self.source.append('// %s begin header: %s' % (tool_name, rel_path))
-          self.source.extend(
-              self._process_source_includes(include_dirs, allowed_files, f))
-        return
-    if self._compute_deps_only:
-      return
-    msg = 'Looked in %s' % ', '.join('"%s"' % d for d in include_dirs)
-    raise Error('Header file %s not found. %s' % (header_name, msg))
-
-  def _add_source(self, target_name, source_name):
-    if source_name in self._processed_sources:
-      return
-    self._processed_sources.add(source_name)
-    include_dirs = self._get_include_dirs(target_name)
-    deps = self.source_deps[source_name]
-    full_path = os.path.join(gn_utils.repo_root(), source_name)
-    if not os.path.exists(full_path):
-      raise Error('Source file %s not found' % source_name)
-    with open(full_path) as f:
-      self.source.append('// %s begin source: %s' % (tool_name, source_name))
-      try:
-        self.source.extend(
-            self._patch_source(
-                source_name,
-                self._process_source_includes(include_dirs, deps, f)))
-      except Error as e:
-        raise Error('Failed adding source %s: %s' % (source_name, e.message))
-
-  def _add_header_included_header(self, include_dirs, header_name):
-    if header_name in self._processed_headers:
-      return
-    self._processed_headers.add(header_name)
-    for include_dir in include_dirs:
-      full_path = os.path.join(gn_utils.repo_root(), include_dir, header_name)
-      if os.path.exists(full_path):
-        with open(full_path) as f:
-          self.header.append('// %s begin header: %s' % (tool_name, full_path))
-          self.header.extend(self._process_header_includes(include_dirs, f))
-        return
-    if self._compute_deps_only:
-      return
-    msg = 'Looked in %s' % ', '.join('"%s"' % d for d in include_dirs)
-    raise Error('Header file %s not found. %s' % (header_name, msg))
-
-  def _add_header(self, target_name, header_name):
-    if header_name in self._processed_headers:
-      return
-    self._processed_headers.add(header_name)
-    include_dirs = self._get_include_dirs(target_name)
-    full_path = os.path.join(gn_utils.repo_root(), header_name)
-    if not os.path.exists(full_path):
-      if self._compute_deps_only:
-        return
-      raise Error('Header file %s not found' % header_name)
-    with open(full_path) as f:
-      self.header.append('// %s begin header: %s' % (tool_name, header_name))
-      try:
-        self.header.extend(self._process_header_includes(include_dirs, f))
-      except Error as e:
-        raise Error('Failed adding header %s: %s' % (header_name, e.message))
-
-  def _patch_source(self, source_name, lines):
-    result = []
-    namespace = re.sub(r'[^a-z]', '_',
-                       os.path.splitext(os.path.basename(source_name))[0])
-    for line in lines:
-      # Protobuf generates an identical anonymous function into each
-      # message description. Rename all but the first occurrence to avoid
-      # duplicate symbol definitions.
-      line = line.replace('MergeFromFail', '%s_MergeFromFail' % namespace)
-      result.append(line)
-    return result
-
-  def _process_source_includes(self, include_dirs, allowed_files, file):
-    result = []
-    for line in file:
-      line = line.rstrip('\n')
-      m = self._include_re.match(line)
-      if not m:
-        result.append(line)
-        continue
-      elif re.match(includes_to_remove, m.group(1)):
-        result.append('// %s removed: %s' % (tool_name, line))
-      else:
-        result.append('// %s expanded: %s' % (tool_name, line))
-        self._add_source_included_header(include_dirs, allowed_files,
-                                         m.group(1))
-    return result
-
-  def _process_header_includes(self, include_dirs, file):
-    result = []
-    for line in file:
-      line = line.rstrip('\n')
-      m = self._include_re.match(line)
-      if not m:
-        result.append(line)
-        continue
-      elif re.match(includes_to_remove, m.group(1)):
-        result.append('// %s removed: %s' % (tool_name, line))
-      else:
-        result.append('// %s expanded: %s' % (tool_name, line))
-        self._add_header_included_header(include_dirs, m.group(1))
-    return result
-
-  def generate(self):
-    """Prepares the output for this amalgamated project.
-
-        Call save() to persist the result.
-        """
-    assert not self._compute_deps_only
-    self.source_defines.append('// %s: predefined macros' % tool_name)
-
-    def add_define(name):
-      # Valued macros aren't supported for now.
-      assert '=' not in name
-      self.source_defines.append('#if !defined(%s)' % name)
-      self.source_defines.append('#define %s' % name)
-      self.source_defines.append('#endif')
-
-    for name in self.defines:
-      add_define(name)
-    for target_name, source_name in self.get_source_files():
-      self._add_source(target_name, source_name)
-
-  def get_source_files(self):
-    """Return a list of (target, [source file]) that describes the source
-           files pulled in by each target which is a dependency of this project.
-        """
-    source_files = []
-    for node in self._dependency_tree.iterate_depth_first():
-      target = self.desc[node.target_name]
-      if not 'sources' in target:
-        continue
-      sources = [(node.target_name, gn_utils.label_to_path(s))
-                 for s in target['sources']
-                 if s.endswith('.cc')]
-      source_files.extend(sources)
-    return source_files
-
-  def _get_nice_path(self, prefix, format):
-    basename = os.path.basename(prefix)
-    return os.path.join(
-        os.path.relpath(os.path.dirname(prefix)), format % basename)
-
-  def _make_directories(self, directory):
-    if not os.path.isdir(directory):
-      os.makedirs(directory)
-
-  def save(self, output_prefix):
-    """Save the generated header and source file pair.
-
-        Returns a message describing the output with build instructions.
-        """
-    header_file = self._get_nice_path(output_prefix, '%s.h')
-    source_file = self._get_nice_path(output_prefix, '%s.cc')
-    self._make_directories(os.path.dirname(header_file))
-    self._make_directories(os.path.dirname(source_file))
-    with open(header_file, 'w') as f:
-      f.write('\n'.join([preamble] + self.header + ['\n']))
-    with open(source_file, 'w') as f:
-      include_stmt = '#include "%s"' % os.path.basename(header_file)
-      f.write('\n'.join([preamble] + self.source_defines + [include_stmt] +
-                        self.source + ['\n']))
-    build_cmd = self.get_build_command(output_prefix)
-
-    return """Amalgamated project written to %s and %s.
-
-Build settings:
- - cflags:    %s
- - ldflags:   %s
- - libs:      %s
-
-Example build command:
-
-%s
-""" % (header_file, source_file, ' '.join(self.cflags), ' '.join(
-        self.ldflags), ' '.join(self.libs), ' '.join(build_cmd))
-
-  def get_build_command(self, output_prefix):
-    """Returns an example command line for building the output source."""
-    source = self._get_nice_path(output_prefix, '%s.cc')
-    library = self._get_nice_path(output_prefix, 'lib%s.so')
-    build_cmd = ['clang++', source, '-o', library, '-shared'] + \
-        sorted(self.cflags) + sorted(self.ldflags)
-    for lib in sorted(self.libs):
-      build_cmd.append('-l%s' % lib)
-    return build_cmd
-
-
-def main():
-  parser = argparse.ArgumentParser(
-      description='Generate an amalgamated header/source pair from a GN '
-      'build description.')
-  parser.add_argument(
-      '--out',
-      help='The name of the temporary build folder in \'out\'',
-      default='tmp.gen_amalgamated.%u' % os.getpid())
-  parser.add_argument(
-      '--output',
-      help='Base name of files to create. A .cc/.h extension will be added',
-      default=os.path.join(gn_utils.repo_root(), 'out/amalgamated/perfetto'))
-  parser.add_argument(
-      '--gn_args',
-      help='GN arguments used to prepare the output directory',
-      default=gn_args)
-  parser.add_argument(
-      '--keep',
-      help='Don\'t delete the GN output directory at exit',
-      action='store_true')
-  parser.add_argument(
-      '--build', help='Also compile the generated files', action='store_true')
-  parser.add_argument(
-      '--check', help='Don\'t keep the generated files', action='store_true')
-  parser.add_argument('--quiet', help='Only report errors', action='store_true')
-  parser.add_argument(
-      '--dump-deps',
-      help='List all source files that the amalgamated output depends on',
-      action='store_true')
-  parser.add_argument(
-      'targets',
-      nargs=argparse.REMAINDER,
-      help='Targets to include in the output (e.g., "//:libperfetto")')
-  args = parser.parse_args()
-  targets = args.targets or default_targets
-
-  output = args.output
-  if args.check:
-    output = os.path.join(tempfile.mkdtemp(), 'perfetto_amalgamated')
-
-  out = gn_utils.prepare_out_directory(args.gn_args, args.out)
-  if not args.quiet:
-    print('Building project...')
-  try:
-    desc = gn_utils.load_build_description(out)
-
-    # We need to build everything first so that the necessary header
-    # dependencies get generated. However if we are just dumping dependency
-    # information this can be skipped, allowing cross-platform operation.
-    if not args.dump_deps:
-      gn_utils.build_targets(out, targets)
-    source_deps = gn_utils.compute_source_dependencies(out)
-    project = AmalgamatedProject(
-        desc, source_deps, compute_deps_only=args.dump_deps)
-
-    for target in targets:
-      project.add_target(target)
-
-    if args.dump_deps:
-      source_files = [
-          source_file for _, source_file in project.get_source_files()
-      ]
-      print('\n'.join(sorted(set(source_files))))
-      return
-
-    project.generate()
-    result = project.save(output)
-    if not args.quiet:
-      print(result)
-    if args.build:
-      if not args.quiet:
-        sys.stdout.write('Building amalgamated project...')
-        sys.stdout.flush()
-      subprocess.check_call(project.get_build_command(output))
-      if not args.quiet:
-        print('done')
-  finally:
-    if not args.keep:
-      shutil.rmtree(out)
-    if args.check:
-      shutil.rmtree(os.path.dirname(output))
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index 2d1203b..69079e8 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -26,68 +26,48 @@
 # libraries are also mapped to their Android equivalents -- see |builtin_deps|.
 
 import argparse
+import errno
 import json
 import os
 import re
+import shutil
+import subprocess
 import sys
 
-import gn_utils
-
-from compat import itervalues
-
-ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-# Arguments for the GN output directory.
-gn_args = ' '.join([
-    'is_debug=false',
-    'is_perfetto_build_generator=true',
-    'perfetto_build_with_android=true',
-    'target_cpu="arm"',
-    'target_os="android"',
-])
-
 # Default targets to translate to the blueprint file.
 default_targets = [
-    '//:libperfetto_client_experimental',
     '//:libperfetto',
+    '//:libperfetto_android_internal',
     '//:perfetto_integrationtests',
+    '//:perfetto_trace_protos',
     '//:perfetto_unittests',
-    '//protos/perfetto/trace:perfetto_trace_protos',
-    '//src/android_internal:libperfetto_android_internal',
-    '//src/perfetto_cmd:perfetto',
-    '//src/perfetto_cmd:trigger_perfetto',
-    '//src/profiling/memory:heapprofd_client',
-    '//src/profiling/memory:heapprofd',
-    '//src/traced/probes:traced_probes',
-    '//src/traced/service:traced',
-]
-
-# Host targets
-ipc_plugin = '//src/ipc/protoc_plugin:ipc_plugin(%s)' % gn_utils.HOST_TOOLCHAIN
-protozero_plugin = '//src/protozero/protoc_plugin:protozero_plugin(%s)' % (
-    gn_utils.HOST_TOOLCHAIN)
-cppgen_plugin = '//src/protozero/protoc_plugin:cppgen_plugin(%s)' % (
-    gn_utils.HOST_TOOLCHAIN)
-
-default_targets += [
-    '//src/trace_processor:trace_processor_shell(%s)' % gn_utils.HOST_TOOLCHAIN,
-    '//tools/trace_to_text:trace_to_text(%s)' % gn_utils.HOST_TOOLCHAIN,
-    protozero_plugin,
-    ipc_plugin,
+    '//:perfetto',
+    '//:traced',
+    '//:traced_probes',
+    '//:trace_to_text',
+    '//:heapprofd_client',
+    '//:heapprofd',
+    '//:trigger_perfetto',
 ]
 
 # Defines a custom init_rc argument to be applied to the corresponding output
 # blueprint target.
 target_initrc = {
-    '//src/traced/service:traced': {'perfetto.rc'},
-    '//src/profiling/memory:heapprofd': {'heapprofd.rc'},
+    '//:traced': 'perfetto.rc',
+    '//:heapprofd': 'heapprofd.rc',
 }
 
 target_host_supported = [
-    '//protos/perfetto/trace:perfetto_trace_protos',
-    '//:libperfetto',
+    '//:perfetto_trace_protos',
 ]
 
+target_host_only = [
+    '//:trace_to_text',
+]
+
+# Arguments for the GN output directory.
+gn_args = 'target_os="android" target_cpu="arm" is_debug=false perfetto_build_with_android=true'
+
 # All module names are prefixed with this string to avoid collisions.
 module_prefix = 'perfetto_'
 
@@ -119,7 +99,7 @@
 cflag_whitelist = r'^-DPERFETTO.*$'
 
 # Compiler defines which are passed through to the blueprint.
-define_whitelist = r'^(GOOGLE_PROTO.*)|(ZLIB_.*)|(USE_MMAP)|(HAVE_HIDDEN)$'
+define_whitelist = r'^(GOOGLE_PROTO.*)|(PERFETTO_BUILD_WITH_ANDROID)|(ZLIB_.*)|(USE_MMAP)|(HAVE_HIDDEN)$'
 
 # Shared libraries which are not in PDK.
 library_not_in_pdk = {
@@ -127,100 +107,73 @@
     'libservices',
 }
 
-# The directory where the generated perfetto_build_flags.h will be copied into.
-buildflags_dir = 'include/perfetto/base/build_configs/android_tree'
-
-
-def enumerate_data_deps():
-  with open(os.path.join(ROOT_DIR, 'tools', 'test_data.txt')) as f:
-    lines = f.readlines()
-  for line in (line.strip() for line in lines if not line.startswith('#')):
-    assert os.path.exists(line), line
-    if line.endswith('/'):
-      yield line + '**/*'
-    else:
-      yield line
-
-
 # Additional arguments to apply to Android.bp rules.
 additional_args = {
     'heapprofd_client': [
-        ('include_dirs', {'bionic/libc'}),
-        ('static_libs', {'libasync_safe'}),
-        ('header_libs', {'bionic_libc_platform_headers'}),
+        ('include_dirs', ['bionic/libc']),
+        ('static_libs', ['libasync_safe']),
     ],
-    'perfetto_unittests': [('data', set(enumerate_data_deps())),],
     'traced_probes': [
-        ('required', {'libperfetto_android_internal', 'trigger_perfetto'}),
+      ('required', ['libperfetto_android_internal', 'trigger_perfetto']),
     ],
-    'libperfetto_android_internal': [('static_libs', {'libhealthhalutils'}),],
-    'trace_processor_shell': [('static_executable', True),],
+    'libperfetto_android_internal': [
+      ('static_libs', ['libhealthhalutils']),
+    ],
 }
 
 
 def enable_gmock(module):
-  module.static_libs.add('libgmock')
+    module.static_libs.append('libgmock')
+
+
+def enable_gtest_prod(module):
+    module.static_libs.append('libgtest_prod')
+
+
+def enable_gtest(module):
+    assert module.type == 'cc_test'
 
 
 def enable_protobuf_full(module):
-  module.shared_libs.add('libprotobuf-cpp-full')
+    module.shared_libs.append('libprotobuf-cpp-full')
 
 
 def enable_protobuf_lite(module):
-  module.shared_libs.add('libprotobuf-cpp-lite')
+    module.shared_libs.append('libprotobuf-cpp-lite')
 
 
 def enable_protoc_lib(module):
-  if module.type == 'cc_binary_host':
-    module.static_libs.add('libprotoc')
-  else:
-    module.shared_libs.add('libprotoc')
-
+    module.shared_libs.append('libprotoc')
 
 def enable_libunwindstack(module):
-  module.shared_libs.add('libunwindstack')
-  module.shared_libs.add('libprocinfo')
-  module.shared_libs.add('libbase')
-
+    module.shared_libs.append('libunwindstack')
+    module.shared_libs.append('libprocinfo')
+    module.shared_libs.append('libbase')
 
 def enable_libunwind(module):
-  # libunwind is disabled on Darwin so we cannot depend on it.
-  pass
-
+    # libunwind is disabled on Darwin so we cannot depend on it.
+    pass
 
 def enable_sqlite(module):
-  if module.type == 'cc_binary_host':
-    module.static_libs.add('libsqlite')
-  else:
-    # Copy what the sqlite3 command line tool does.
-    module.android.shared_libs.add('libsqlite')
-    module.android.shared_libs.add('libandroidicu')
-    module.android.shared_libs.add('liblog')
-    module.android.shared_libs.add('libutils')
-    module.host.static_libs.add('libsqlite')
-
+    module.static_libs.append('libsqlite')
 
 def enable_zlib(module):
-  if module.type == 'cc_binary_host':
-    module.static_libs.add('libz')
-  else:
-    module.shared_libs.add('libz')
-
+    module.shared_libs.append('libz')
 
 # Android equivalents for third-party libraries that the upstream project
 # depends on.
 builtin_deps = {
-    '//gn:default_deps': lambda x: None,
-    '//gn:gtest_main': lambda x: None,
-    '//gn:protoc': lambda x: None,
-    '//gn:gtest_and_gmock': enable_gmock,
-    '//gn:libunwind': enable_libunwind,
-    '//gn:protobuf_full': enable_protobuf_full,
-    '//gn:protobuf_lite': enable_protobuf_lite,
-    '//gn:protoc_lib': enable_protoc_lib,
-    '//gn:libunwindstack': enable_libunwindstack,
-    '//gn:sqlite': enable_sqlite,
-    '//gn:zlib': enable_zlib,
+    '//buildtools:gmock': enable_gmock,
+    '//buildtools:gtest': enable_gtest,
+    '//gn:gtest_prod_config': enable_gtest_prod,
+    '//buildtools:gtest_main': enable_gtest,
+    '//buildtools:libunwind': enable_libunwind,
+    '//buildtools:protobuf_full': enable_protobuf_full,
+    '//buildtools:protobuf_lite': enable_protobuf_lite,
+    '//buildtools:protoc_lib': enable_protoc_lib,
+    '//buildtools:libunwindstack': enable_libunwindstack,
+    '//buildtools:sqlite': enable_sqlite,
+    '//buildtools:zlib': enable_zlib,
 }
 
 # ----------------------------------------------------------------------------
@@ -229,210 +182,226 @@
 
 
 class Error(Exception):
-  pass
+    pass
 
 
 class ThrowingArgumentParser(argparse.ArgumentParser):
+    def __init__(self, context):
+        super(ThrowingArgumentParser, self).__init__()
+        self.context = context
 
-  def __init__(self, context):
-    super(ThrowingArgumentParser, self).__init__()
-    self.context = context
-
-  def error(self, message):
-    raise Error('%s: %s' % (self.context, message))
-
-
-def write_blueprint_key_value(output, name, value, sort=True):
-  """Writes a Blueprint key-value pair to the output"""
-
-  if not value:
-    return
-  if isinstance(value, set):
-    value = sorted(value)
-  if isinstance(value, list):
-    output.append('  %s: [' % name)
-    for item in sorted(value) if sort else value:
-      output.append('    "%s",' % item)
-    output.append('  ],')
-    return
-  if isinstance(value, bool):
-    output.append('  %s: true,' % name)
-    return
-  if isinstance(value, Target):
-    value.to_string(output)
-    return
-  output.append('  %s: "%s",' % (name, value))
-
-
-class Target(object):
-  """A target-scoped part of a module"""
-
-  def __init__(self, name):
-    self.name = name
-    self.shared_libs = set()
-    self.static_libs = set()
-    self.cflags = set()
-
-  def to_string(self, output):
-    nested_out = []
-    self._output_field(nested_out, 'shared_libs')
-    self._output_field(nested_out, 'static_libs')
-    self._output_field(nested_out, 'cflags')
-
-    if nested_out:
-      output.append('  %s: {' % self.name)
-      for line in nested_out:
-        output.append('  %s' % line)
-      output.append('  },')
-
-  def _output_field(self, output, name, sort=True):
-    value = getattr(self, name)
-    return write_blueprint_key_value(output, name, value, sort)
+    def error(self, message):
+        raise Error('%s: %s' % (self.context, message))
 
 
 class Module(object):
-  """A single module (e.g., cc_binary, cc_test) in a blueprint."""
+    """A single module (e.g., cc_binary, cc_test) in a blueprint."""
 
-  def __init__(self, mod_type, name, gn_target):
-    self.type = mod_type
-    self.gn_target = gn_target
-    self.name = name
-    self.srcs = set()
-    self.comment = 'GN: ' + gn_utils.label_without_toolchain(gn_target)
-    self.shared_libs = set()
-    self.static_libs = set()
-    self.tools = set()
-    self.cmd = None
-    self.host_supported = False
-    self.init_rc = set()
-    self.out = set()
-    self.export_include_dirs = set()
-    self.generated_headers = set()
-    self.export_generated_headers = set()
-    self.defaults = set()
-    self.cflags = set()
-    self.include_dirs = set()
-    self.header_libs = set()
-    self.required = set()
-    self.user_debug_flag = False
-    self.tool_files = None
-    self.android = Target('android')
-    self.host = Target('host')
-    self.lto = None
-    self.static_executable = False
-    self.data = set()
-    # The genrule_XXX below are properties that must to be propagated back
-    # on the module(s) that depend on the genrule.
-    self.genrule_headers = set()
-    self.genrule_srcs = set()
-    self.genrule_shared_libs = set()
+    def __init__(self, mod_type, name):
+        self.type = mod_type
+        self.name = name
+        self.srcs = []
+        self.comment = None
+        self.shared_libs = []
+        self.static_libs = []
+        self.tools = []
+        self.cmd = None
+        self.host_supported = False
+        self.init_rc = []
+        self.out = []
+        self.export_include_dirs = []
+        self.generated_headers = []
+        self.export_generated_headers = []
+        self.defaults = []
+        self.cflags = set()
+        self.local_include_dirs = []
+        self.include_dirs = []
+        self.required = []
+        self.user_debug_flag = False
+        self.tool_files = None
 
-  def to_string(self, output):
-    if self.comment:
-      output.append('// %s' % self.comment)
-    output.append('%s {' % self.type)
-    self._output_field(output, 'name')
-    self._output_field(output, 'srcs')
-    self._output_field(output, 'shared_libs')
-    self._output_field(output, 'static_libs')
-    self._output_field(output, 'tools')
-    self._output_field(output, 'cmd', sort=False)
-    self._output_field(output, 'host_supported')
-    self._output_field(output, 'init_rc')
-    self._output_field(output, 'out')
-    self._output_field(output, 'export_include_dirs')
-    self._output_field(output, 'generated_headers')
-    self._output_field(output, 'export_generated_headers')
-    self._output_field(output, 'defaults')
-    self._output_field(output, 'cflags')
-    self._output_field(output, 'include_dirs')
-    self._output_field(output, 'header_libs')
-    self._output_field(output, 'required')
-    self._output_field(output, 'static_executable')
-    self._output_field(output, 'tool_files')
-    self._output_field(output, 'data')
+    def to_string(self, output):
+        if self.comment:
+            output.append('// %s' % self.comment)
+        output.append('%s {' % self.type)
+        self._output_field(output, 'name')
+        self._output_field(output, 'srcs')
+        self._output_field(output, 'shared_libs')
+        self._output_field(output, 'static_libs')
+        self._output_field(output, 'tools')
+        self._output_field(output, 'cmd', sort=False)
+        self._output_field(output, 'host_supported')
+        self._output_field(output, 'init_rc')
+        self._output_field(output, 'out')
+        self._output_field(output, 'export_include_dirs')
+        self._output_field(output, 'generated_headers')
+        self._output_field(output, 'export_generated_headers')
+        self._output_field(output, 'defaults')
+        self._output_field(output, 'cflags')
+        self._output_field(output, 'local_include_dirs')
+        self._output_field(output, 'include_dirs')
+        self._output_field(output, 'required')
+        self._output_field(output, 'tool_files')
 
-    target_out = []
-    self._output_field(target_out, 'android')
-    self._output_field(target_out, 'host')
-    if target_out:
-      output.append('  target: {')
-      for line in target_out:
-        output.append('  %s' % line)
-      output.append('  },')
+        disable_pdk = any(name in library_not_in_pdk for name in self.shared_libs)
+        if self.user_debug_flag or disable_pdk:
+            output.append('  product_variables: {')
+            if disable_pdk:
+                output.append('    pdk: {')
+                output.append('      enabled: false,')
+                output.append('    },')
+            if self.user_debug_flag:
+                output.append('    debuggable: {')
+                output.append('      cflags: ["-DPERFETTO_BUILD_WITH_ANDROID_USERDEBUG"],')
+                output.append('    },')
+            output.append('  },')
+        output.append('}')
+        output.append('')
 
-    disable_pdk = any(name in library_not_in_pdk for name in self.shared_libs)
-    if self.user_debug_flag or disable_pdk:
-      output.append('  product_variables: {')
-      if disable_pdk:
-        output.append('    pdk: {')
-        output.append('      enabled: false,')
-        output.append('    },')
-      if self.user_debug_flag:
-        output.append('    debuggable: {')
-        output.append(
-            '      cflags: ["-DPERFETTO_BUILD_WITH_ANDROID_USERDEBUG"],')
-        output.append('    },')
-      output.append('  },')
-    if self.lto is not None:
-      output.append('  target: {')
-      output.append('    android: {')
-      output.append('      lto: {')
-      output.append('        thin: %s,' % 'true' if self.lto else 'false')
-      output.append('      },')
-      output.append('    },')
-      output.append('  },')
-    output.append('}')
-    output.append('')
+    def _output_field(self, output, name, sort=True):
+        value = getattr(self, name)
+        return self._write_value(output, name, value, sort)
 
-  def _output_field(self, output, name, sort=True):
-    value = getattr(self, name)
-    return write_blueprint_key_value(output, name, value, sort)
+    def _write_value(self, output, name, value, sort=True):
+        if not value:
+            return
+        if isinstance(value, set):
+            value = sorted(value)
+        if isinstance(value, list):
+            output.append('  %s: [' % name)
+            for item in sorted(value) if sort else value:
+                output.append('    "%s",' % item)
+            output.append('  ],')
+            return
+        if isinstance(value, bool):
+           output.append('  %s: true,' % name)
+           return
+        output.append('  %s: "%s",' % (name, value))
 
 
 class Blueprint(object):
-  """In-memory representation of an Android.bp file."""
+    """In-memory representation of an Android.bp file."""
 
-  def __init__(self):
-    self.modules = {}
+    def __init__(self):
+        self.modules = {}
 
-  def add_module(self, module):
-    """Adds a new module to the blueprint, replacing any existing module
+    def add_module(self, module):
+        """Adds a new module to the blueprint, replacing any existing module
         with the same name.
 
         Args:
             module: Module instance.
         """
-    self.modules[module.name] = module
+        self.modules[module.name] = module
 
-  def to_string(self, output):
-    for m in sorted(itervalues(self.modules), key=lambda m: m.name):
-      m.to_string(output)
+    def to_string(self, output):
+        for m in sorted(self.modules.itervalues(), key=lambda m: m.name):
+            m.to_string(output)
+
+
+def label_to_path(label):
+    """Turn a GN output label (e.g., //some_dir/file.cc) into a path."""
+    assert label.startswith('//')
+    return label[2:]
 
 
 def label_to_module_name(label):
-  """Turn a GN label (e.g., //:perfetto_tests) into a module name."""
-  # If the label is explicibly listed in the default target list, don't prefix
-  # its name and return just the target name. This is so tools like
-  # "trace_to_text" stay as such in the Android tree.
-  label_without_toolchain = gn_utils.label_without_toolchain(label)
-  if label in default_targets or label_without_toolchain in default_targets:
-    return label_without_toolchain.split(':')[-1]
+    """Turn a GN label (e.g., //:perfetto_tests) into a module name."""
+    module = re.sub(r'^//:?', '', label)
+    module = re.sub(r'[^a-zA-Z0-9_]', '_', module)
+    if not module.startswith(module_prefix) and label not in default_targets:
+        return module_prefix + module
+    return module
 
-  module = re.sub(r'^//:?', '', label_without_toolchain)
-  module = re.sub(r'[^a-zA-Z0-9_]', '_', module)
-  if not module.startswith(module_prefix):
-    return module_prefix + module
-  return module
+
+def label_without_toolchain(label):
+    """Strips the toolchain from a GN label.
+
+    Return a GN label (e.g //buildtools:protobuf(//gn/standalone/toolchain:
+    gcc_like_host) without the parenthesised toolchain part.
+    """
+    return label.split('(')[0]
 
 
 def is_supported_source_file(name):
-  """Returns True if |name| can appear in a 'srcs' list."""
-  return os.path.splitext(name)[1] in ['.c', '.cc', '.proto']
+    """Returns True if |name| can appear in a 'srcs' list."""
+    return os.path.splitext(name)[1] in ['.c', '.cc', '.proto']
 
 
-def create_proto_modules(blueprint, gn, target):
-  """Generate genrules for a proto GN target.
+def is_generated_by_action(desc, label):
+    """Checks if a label is generated by an action.
+
+    Returns True if a GN output label |label| is an output for any action,
+    i.e., the file is generated dynamically.
+    """
+    for target in desc.itervalues():
+        if target['type'] == 'action' and label in target['outputs']:
+            return True
+    return False
+
+
+def apply_module_dependency(blueprint, desc, module, dep_name):
+    """Recursively collect dependencies for a given module.
+
+    Walk the transitive dependencies for a GN target and apply them to a given
+    module. This effectively flattens the dependency tree so that |module|
+    directly contains all the sources, libraries, etc. in the corresponding GN
+    dependency tree.
+
+    Args:
+        blueprint: Blueprint instance which is being generated.
+        desc: JSON GN description.
+        module: Module to which dependencies should be added.
+        dep_name: GN target of the dependency.
+    """
+    # If the dependency refers to a library which we can replace with an Android
+    # equivalent, stop recursing and patch the dependency in.
+    if label_without_toolchain(dep_name) in builtin_deps:
+        builtin_deps[label_without_toolchain(dep_name)](module)
+        return
+
+    # Similarly some shared libraries are directly mapped to Android
+    # equivalents.
+    target = desc[dep_name]
+    for lib in target.get('libs', []):
+        # Generally library names sould be mangled as 'libXXX', unless they are
+        # HAL libraries (e.g., android.hardware.health@2.0).
+        android_lib = lib if '@' in lib else 'lib' + lib
+        if lib in library_whitelist and not android_lib in module.shared_libs:
+            module.shared_libs.append(android_lib)
+
+    type = target['type']
+    if type == 'action':
+        if "gen_merged_sql_metrics" in dep_name:
+          dep_mod = create_merged_sql_metrics_target(blueprint, desc, dep_name)
+          module.generated_headers.append(dep_mod.name)
+        else:
+          create_modules_from_target(blueprint, desc, dep_name)
+          # Depend both on the generated sources and headers -- see
+          # make_genrules_for_action.
+          module.srcs.append(':' + label_to_module_name(dep_name))
+          module.generated_headers.append(
+              label_to_module_name(dep_name) + '_headers')
+    elif type == 'static_library' and label_to_module_name(
+            dep_name) != module.name:
+        create_modules_from_target(blueprint, desc, dep_name)
+        module.static_libs.append(label_to_module_name(dep_name))
+    elif type == 'shared_library' and label_to_module_name(
+            dep_name) != module.name:
+        module.shared_libs.append(label_to_module_name(dep_name))
+    elif type in ['group', 'source_set', 'executable', 'static_library'
+                  ] and 'sources' in target:
+        # Ignore source files that are generated by actions since they will be
+        # implicitly added by the genrule dependencies.
+        module.srcs.extend(
+            label_to_path(src) for src in target['sources']
+            if is_supported_source_file(src)
+            and not is_generated_by_action(desc, src))
+    module.cflags |= _get_cflags(target)
+
+
+def make_genrules_for_action(blueprint, desc, target_name):
+    """Generate genrules for a GN action.
 
     GN actions are used to dynamically generate files during the build. The
     Soong equivalent is a genrule. This function turns a specific kind of
@@ -441,317 +410,322 @@
 
     Args:
         blueprint: Blueprint instance which is being generated.
-        target: gn_utils.Target object.
+        desc: JSON GN description.
+        target_name: GN target for genrule generation.
 
     Returns:
-        The source_genrule module.
+        A (source_genrule, header_genrule) module tuple.
     """
-  assert (target.type == 'proto_library')
-  cpp_out_dir = '$(genDir)/%s/' % tree_path
-  cmd = [
-      'mkdir -p %s &&' % cpp_out_dir, '$(location aprotoc)',
-      '--cpp_out=%s' % cpp_out_dir
-  ]
+    target = desc[target_name]
 
-  # We create two genrules for each proto target: one for the headers and
-  # another for the sources. This is because the module that depends on the
-  # generated files needs to declare two different types of dependencies --
-  # source files in 'srcs' and headers in 'generated_headers' -- and it's not
-  # valid to generate .h files from a source dependency and vice versa.
-  source_module_name = label_to_module_name(target.name) + '_gen'
-  source_module = Module('genrule', source_module_name, target.name)
-  blueprint.add_module(source_module)
-  source_module.srcs.update(
-      gn_utils.label_to_path(src) for src in target.sources)
-  tools = {'aprotoc'}
+    # We only support genrules which call protoc (with or without a plugin) to
+    # turn .proto files into header and source files.
+    args = target['args']
+    if not args[0].endswith('/protoc'):
+        raise Error('Unsupported action in target %s: %s' % (target_name,
+                                                             target['args']))
+    parser = ThrowingArgumentParser('Action in target %s (%s)' %
+                                    (target_name, ' '.join(target['args'])))
+    parser.add_argument('--proto_path')
+    parser.add_argument('--cpp_out')
+    parser.add_argument('--plugin')
+    parser.add_argument('--plugin_out')
+    parser.add_argument('--descriptor_set_out')
+    parser.add_argument('--include_imports', action='store_true')
+    parser.add_argument('protos', nargs=argparse.REMAINDER)
+    args = parser.parse_args(args[1:])
 
-  header_module = Module('genrule', source_module_name + '_headers',
-                         target.name)
-  blueprint.add_module(header_module)
-  header_module.srcs = set(source_module.srcs)
+    # Depending on whether we are using the default protoc C++ generator or the
+    # protozero plugin, the output dir is passed as:
+    # --cpp_out=gen/xxx or
+    # --plugin_out=:gen/xxx or
+    # --plugin_out=wrapper_namespace=pbzero:gen/xxx
+    gen_dir = args.cpp_out if args.cpp_out else args.plugin_out.split(':')[1]
+    assert gen_dir.startswith('gen/')
+    gen_dir = gen_dir[4:]
+    cpp_out_dir = ('$(genDir)/%s/%s' % (tree_path, gen_dir)).rstrip('/')
 
-  # TODO(primiano): at some point we should remove this. This was introduced
-  # by aosp/1108421 when adding "protos/" to .proto include paths, in order to
-  # avoid doing multi-repo changes and allow old clients in the android tree
-  # to still do the old #include "perfetto/..." rather than
-  # #include "protos/perfetto/...".
-  header_module.export_include_dirs = {'.', 'protos'}
+    # TODO(skyostil): Is there a way to avoid hardcoding the tree path here?
+    # TODO(skyostil): Find a way to avoid creating the directory.
+    cmd = [
+        'mkdir -p %s &&' % cpp_out_dir,
+        '$(location aprotoc)',
+        '--cpp_out=%s' % cpp_out_dir
+    ]
 
-  source_module.genrule_srcs.add(':' + source_module.name)
-  source_module.genrule_headers.add(header_module.name)
+    # We create two genrules for each action: one for the protobuf headers and
+    # another for the sources. This is because the module that depends on the
+    # generated files needs to declare two different types of dependencies --
+    # source files in 'srcs' and headers in 'generated_headers' -- and it's not
+    # valid to generate .h files from a source dependency and vice versa.
+    source_module = Module('genrule', label_to_module_name(target_name))
+    source_module.srcs.extend(label_to_path(src) for src in target['sources'])
+    source_module.tools = ['aprotoc']
 
-  # In GN builds the proto path is always relative to the output directory
-  # (out/tmp.xxx).
-  cmd += ['--proto_path=%s' % tree_path]
+    header_module = Module('genrule',
+                           label_to_module_name(target_name) + '_headers')
+    header_module.srcs = source_module.srcs[:]
+    header_module.tools = source_module.tools[:]
+    header_module.export_include_dirs = [gen_dir or '.']
 
-  suffixes = ['pb']
-  if target.proto_plugin == 'proto':
-    source_module.genrule_shared_libs.add('libprotobuf-cpp-lite')
-  elif target.proto_plugin == 'protozero':
-    suffixes = ['pbzero']
-    plugin = create_modules_from_target(blueprint, gn, protozero_plugin)
-    tools.add(plugin.name)
-    cmd += ['--plugin=protoc-gen-plugin=$(location %s)' % plugin.name]
-    cmd += ['--plugin_out=wrapper_namespace=pbzero:' + cpp_out_dir]
-  elif target.proto_plugin == 'cppgen':
-    suffixes = ['gen']
-    plugin = create_modules_from_target(blueprint, gn, cppgen_plugin)
-    tools.add(plugin.name)
-    cmd += ['--plugin=protoc-gen-plugin=$(location %s)' % plugin.name]
-    cmd += ['--plugin_out=:' + cpp_out_dir]
-  elif target.proto_plugin == 'ipc':
-    suffixes.append('ipc')
-    plugin = create_modules_from_target(blueprint, gn, ipc_plugin)
-    tools.add(plugin.name)
-    cmd += ['--plugin=protoc-gen-plugin=$(location %s)' % plugin.name]
-    cmd += ['--plugin_out=:' + cpp_out_dir]
-  else:
-    raise Error('Unsupported proto plugin: %s' % target.proto_plugin)
+    # In GN builds the proto path is always relative to the output directory
+    # (out/tmp.xxx).
+    assert args.proto_path.startswith('../../')
+    cmd += [ '--proto_path=%s/%s' % (tree_path, args.proto_path[6:])]
 
-  cmd += ['$(in)']
-  source_module.cmd = ' '.join(cmd)
-  header_module.cmd = source_module.cmd
-  source_module.tools = tools
-  header_module.tools = tools
+    namespaces = ['pb']
+    if args.plugin:
+        _, plugin = os.path.split(args.plugin)
+        # TODO(skyostil): Can we detect this some other way?
+        if plugin == 'ipc_plugin':
+            namespaces.append('ipc')
+        elif plugin == 'protoc_plugin':
+            namespaces = ['pbzero']
+        for dep in target['deps']:
+            if desc[dep]['type'] != 'executable':
+                continue
+            _, executable = os.path.split(desc[dep]['outputs'][0])
+            if executable == plugin:
+                cmd += [
+                    '--plugin=protoc-gen-plugin=$(location %s)' %
+                    label_to_module_name(dep)
+                ]
+                source_module.tools.append(label_to_module_name(dep))
+                # Also make sure the module for the tool is generated.
+                create_modules_from_target(blueprint, desc, dep)
+                break
+        else:
+            raise Error('Unrecognized protoc plugin in target %s: %s' %
+                        (target_name, args[i]))
+    if args.plugin_out:
+        plugin_args = args.plugin_out.split(':')[0]
+        cmd += ['--plugin_out=%s:%s' % (plugin_args, cpp_out_dir)]
 
-  for sfx in suffixes:
-    source_module.out.update('%s/%s' %
-                             (tree_path, src.replace('.proto', '.%s.cc' % sfx))
-                             for src in source_module.srcs)
-    header_module.out.update('%s/%s' %
-                             (tree_path, src.replace('.proto', '.%s.h' % sfx))
-                             for src in header_module.srcs)
-  return source_module
+    cmd += ['$(in)']
+    source_module.cmd = ' '.join(cmd)
+    header_module.cmd = source_module.cmd
+    header_module.tools = source_module.tools[:]
 
+    for ns in namespaces:
+        source_module.out += [
+            '%s/%s' % (tree_path, src.replace('.proto', '.%s.cc' % ns))
+            for src in source_module.srcs
+        ]
+        header_module.out += [
+            '%s/%s' % (tree_path, src.replace('.proto', '.%s.h' % ns))
+            for src in header_module.srcs
+        ]
+    return source_module, header_module
 
-def create_merged_sql_metrics_module(blueprint, target):
-  module = Module('genrule', 'gen_merged_sql_metrics',
-                  '//src/trace_processor/metrics:gen_merged_sql_metrics')
-  module.genrule_headers.add('gen_merged_sql_metrics')
-  module.tool_files = [
-      'tools/gen_merged_sql_metrics.py',
-  ]
-  module.cmd = ' '.join([
-      '$(location tools/gen_merged_sql_metrics.py)',
-      '--cpp_out=$(out)',
-      '$(in)',
-  ])
-  module.out.update(target.outputs)
-  module.srcs.update(gn_utils.label_to_path(src) for src in target.inputs)
-  blueprint.add_module(module)
-  return module
-
+def create_merged_sql_metrics_target(blueprint, desc, gn_target_name):
+    target_desc = desc[gn_target_name]
+    module = Module(
+        'genrule',
+        'gen_merged_sql_metrics',
+    )
+    module.tool_files = [
+        'tools/gen_merged_sql_metrics.py',
+    ]
+    module.cmd = ' '.join([
+        '$(location tools/gen_merged_sql_metrics.py)',
+        '--cpp_out=$(out)',
+        '$(in)',
+    ])
+    module.out = set(
+        src[src.index('gen/') + len('gen/'):]
+        for src in target_desc.get('outputs', [])
+    )
+    module.srcs.extend(
+      label_to_path(src)
+      for src in target_desc.get('inputs', [])
+    )
+    blueprint.add_module(module)
+    return module
 
 def _get_cflags(target):
-  cflags = {flag for flag in target.cflags if re.match(cflag_whitelist, flag)}
-  cflags |= set("-D%s" % define
-                for define in target.defines
-                if re.match(define_whitelist, define))
-  return cflags
+    cflags = set(flag for flag in target.get('cflags', [])
+        if re.match(cflag_whitelist, flag))
+    cflags |= set("-D%s" % define for define in target.get('defines', [])
+                  if re.match(define_whitelist, define))
+    return cflags
 
 
-def create_modules_from_target(blueprint, gn, gn_target_name):
-  """Generate module(s) for a given GN target.
+def create_modules_from_target(blueprint, desc, target_name):
+    """Generate module(s) for a given GN target.
 
     Given a GN target name, generate one or more corresponding modules into a
-    blueprint. The only case when this generates >1 module is proto libraries.
+    blueprint.
 
     Args:
         blueprint: Blueprint instance which is being generated.
-        gn: gn_utils.GnParser object.
-        gn_target_name: GN target for module generation.
+        desc: JSON GN description.
+        target_name: GN target for module generation.
     """
-  bp_module_name = label_to_module_name(gn_target_name)
-  if bp_module_name in blueprint.modules:
-    return blueprint.modules[bp_module_name]
-  target = gn.get_target(gn_target_name)
-  export_include_dirs = {'include', buildflags_dir}
-
-  if target.type == 'executable':
-    if target.toolchain == gn_utils.HOST_TOOLCHAIN:
-      module_type = 'cc_binary_host'
-    elif target.testonly:
-      module_type = 'cc_test'
+    target = desc[target_name]
+    if target['type'] == 'executable':
+        if 'host' in target['toolchain'] or target_name in target_host_only:
+            module_type = 'cc_binary_host'
+        elif target.get('testonly'):
+            module_type = 'cc_test'
+        else:
+            module_type = 'cc_binary'
+        modules = [Module(module_type, label_to_module_name(target_name))]
+    elif target['type'] == 'action':
+        modules = make_genrules_for_action(blueprint, desc, target_name)
+    elif target['type'] == 'static_library':
+        module = Module('cc_library_static', label_to_module_name(target_name))
+        module.export_include_dirs = ['include']
+        modules = [module]
+    elif target['type'] == 'shared_library':
+        modules = [
+            Module('cc_library_shared', label_to_module_name(target_name))
+        ]
     else:
-      module_type = 'cc_binary'
-    module = Module(module_type, bp_module_name, gn_target_name)
-  elif target.type == 'static_library':
-    module = Module('cc_library_static', bp_module_name, gn_target_name)
-    module.export_include_dirs = export_include_dirs
-  elif target.type == 'shared_library':
-    module = Module('cc_library_shared', bp_module_name, gn_target_name)
-    module.export_include_dirs = export_include_dirs
-  elif target.type == 'source_set':
-    module = Module('filegroup', bp_module_name, gn_target_name)
-  elif target.type == 'group':
-    # "group" targets are resolved recursively by gn_utils.get_target().
-    # There's nothing we need to do at this level for them.
-    return None
-  elif target.type == 'proto_library':
-    module = create_proto_modules(blueprint, gn, target)
-  elif target.type == 'action' and 'gen_merged_sql_metrics' in target.name:
-    module = create_merged_sql_metrics_module(blueprint, target)
-  else:
-    raise Error('Unknown target %s (%s)' % (target.name, target.type))
+        raise Error('Unknown target type: %s' % target['type'])
 
-  blueprint.add_module(module)
-  module.host_supported = target.name in target_host_supported
-  module.init_rc = target_initrc.get(target.name, [])
-  module.srcs.update(
-      gn_utils.label_to_path(src)
-      for src in target.sources
-      if is_supported_source_file(src))
+    for module in modules:
+        module.comment = 'GN target: %s' % target_name
+        if target_name in target_initrc:
+          module.init_rc = [target_initrc[target_name]]
+        if target_name in target_host_supported:
+          module.host_supported = True
 
-  if target.type in gn_utils.LINKER_UNIT_TYPES:
-    module.cflags.update(_get_cflags(target))
+        # Don't try to inject library/source dependencies into genrules because
+        # they are not compiled in the traditional sense.
+        if module.type != 'genrule':
+            module.defaults = [defaults_module]
+            apply_module_dependency(blueprint, desc, module, target_name)
+            for dep in resolve_dependencies(desc, target_name):
+                apply_module_dependency(blueprint, desc, module, dep)
 
-  module_is_compiled = module.type not in ('genrule', 'filegroup')
-  if module_is_compiled:
-    # Don't try to inject library/source dependencies into genrules or
-    # filegroups because they are not compiled in the traditional sense.
-    module.defaults = [defaults_module]
-    for lib in target.libs:
-      # Generally library names should be mangled as 'libXXX', unless they
-      # are HAL libraries (e.g., android.hardware.health@2.0).
-      android_lib = lib if '@' in lib else 'lib' + lib
-      if lib in library_whitelist:
-        module.shared_libs.add(android_lib)
+        # If the module is a static library, export all the generated headers.
+        if module.type == 'cc_library_static':
+            module.export_generated_headers = module.generated_headers
 
-  # If the module is a static library, export all the generated headers.
-  if module.type == 'cc_library_static':
-    module.export_generated_headers = module.generated_headers
+        # Merge in additional hardcoded arguments.
+        for key, add_val in additional_args.get(module.name, []):
+          curr = getattr(module, key)
+          if add_val and isinstance(add_val, list) and isinstance(curr, list):
+            curr.extend(add_val)
+          else:
+            raise Error('Unimplemented type of additional_args')
 
-  # Merge in additional hardcoded arguments.
-  for key, add_val in additional_args.get(module.name, []):
-    curr = getattr(module, key)
-    if add_val and isinstance(add_val, set) and isinstance(curr, set):
-      curr.update(add_val)
-    elif isinstance(add_val, bool) and isinstance(curr, bool):
-      setattr(module, key, add_val)
-    else:
-      raise Error('Unimplemented type of additional_args: %r' % key)
-
-  # dep_name is an unmangled GN target name (e.g. //foo:bar(toolchain)).
-  for dep_name in target.deps | target.source_set_deps | target.proto_deps:
-    # If the dependency refers to a library which we can replace with an
-    # Android equivalent, stop recursing and patch the dependency in.
-    # Don't recurse into //buildtools, builtin_deps are intercepted at
-    # the //gn:xxx level.
-    if dep_name.startswith('//buildtools'):
-      continue
-
-    # Ignore the dependency on the gen_buildflags genrule. That is run
-    # separately in this generator and the generated file is copied over
-    # into the repo (see usage of |buildflags_dir| in this script).
-    if dep_name.startswith(gn_utils.BUILDFLAGS_TARGET):
-      continue
-
-    dep_module = create_modules_from_target(blueprint, gn, dep_name)
-
-    # For filegroups and genrule, recurse but don't apply the deps.
-    if not module_is_compiled:
-      continue
-
-    # |builtin_deps| override GN deps with Android-specific ones. See the
-    # config in the top of this file.
-    if gn_utils.label_without_toolchain(dep_name) in builtin_deps:
-      builtin_deps[gn_utils.label_without_toolchain(dep_name)](module)
-      continue
-
-    # Don't recurse in any other //gn dep if not handled by builtin_deps.
-    if dep_name.startswith('//gn:'):
-      continue
-
-    if dep_module is None:
-      continue
-    if dep_module.type == 'cc_library_shared':
-      module.shared_libs.add(dep_module.name)
-    elif dep_module.type == 'cc_library_static':
-      module.static_libs.add(dep_module.name)
-    elif dep_module.type == 'filegroup':
-      module.srcs.add(':' + dep_module.name)
-    elif dep_module.type == 'genrule':
-      module.generated_headers.update(dep_module.genrule_headers)
-      module.srcs.update(dep_module.genrule_srcs)
-      module.shared_libs.update(dep_module.genrule_shared_libs)
-    else:
-      raise Error('Unknown dep %s (%s) for target %s' %
-                  (dep_module.name, dep_module.type, module.name))
-
-  return module
+        blueprint.add_module(module)
 
 
-def create_blueprint_for_targets(gn, desc, targets):
-  """Generate a blueprint for a list of GN targets."""
-  blueprint = Blueprint()
+def resolve_dependencies(desc, target_name):
+    """Return the transitive set of dependent-on targets for a GN target.
 
-  # Default settings used by all modules.
-  defaults = Module('cc_defaults', defaults_module, '//gn:default_deps')
+    Args:
+        blueprint: Blueprint instance which is being generated.
+        desc: JSON GN description.
 
-  # We have to use include_dirs passing the path relative to the android tree.
-  # This is because: (i) perfetto_cc_defaults is used also by
-  # test/**/Android.bp; (ii) if we use local_include_dirs instead, paths
-  # become relative to the Android.bp that *uses* cc_defaults (not the one
-  # that defines it).s
-  defaults.include_dirs = {
-      tree_path, tree_path + '/include', tree_path + '/' + buildflags_dir
-  }
-  defaults.cflags = [
-      '-Wno-error=return-type',
-      '-Wno-sign-compare',
-      '-Wno-sign-promo',
-      '-Wno-unused-parameter',
-      '-fvisibility=hidden',
-      '-O2',
-  ]
-  defaults.user_debug_flag = True
-  defaults.lto = True
+    Returns:
+        A set of transitive dependencies in the form of GN targets.
+    """
 
-  blueprint.add_module(defaults)
-  gn = gn_utils.GnParser(desc)
-  for target in targets:
-    create_modules_from_target(blueprint, gn, target)
-  return blueprint
+    if label_without_toolchain(target_name) in builtin_deps:
+        return set()
+    target = desc[target_name]
+    resolved_deps = set()
+    for dep in target.get('deps', []):
+        resolved_deps.add(dep)
+        # Ignore the transitive dependencies of actions because they are
+        # explicitly converted to genrules.
+        if desc[dep]['type'] == 'action':
+            continue
+        # Dependencies on shared libraries shouldn't propagate any transitive
+        # dependencies but only depend on the shared library target
+        if desc[dep]['type'] == 'shared_library':
+            continue
+        resolved_deps.update(resolve_dependencies(desc, dep))
+    return resolved_deps
+
+
+def create_blueprint_for_targets(desc, targets):
+    """Generate a blueprint for a list of GN targets."""
+    blueprint = Blueprint()
+
+    # Default settings used by all modules.
+    defaults = Module('cc_defaults', defaults_module)
+    defaults.local_include_dirs = ['include']
+    defaults.cflags = [
+        '-Wno-error=return-type',
+        '-Wno-sign-compare',
+        '-Wno-sign-promo',
+        '-Wno-unused-parameter',
+        '-fvisibility=hidden',
+        '-Oz',
+    ]
+    defaults.user_debug_flag = True
+
+    blueprint.add_module(defaults)
+    for target in targets:
+        create_modules_from_target(blueprint, desc, target)
+    return blueprint
+
+
+def repo_root():
+    """Returns an absolute path to the repository root."""
+
+    return os.path.join(
+        os.path.realpath(os.path.dirname(__file__)), os.path.pardir)
+
+
+def create_build_description():
+    """Creates the JSON build description by running GN."""
+
+    out = os.path.join(repo_root(), 'out', 'tmp.gen_android_bp')
+    try:
+        try:
+            os.makedirs(out)
+        except OSError as e:
+            if e.errno != errno.EEXIST:
+                raise
+        subprocess.check_output(
+            ['gn', 'gen', out, '--args=%s' % gn_args], cwd=repo_root())
+        desc = subprocess.check_output(
+            ['gn', 'desc', out, '--format=json', '--all-toolchains', '//*'],
+            cwd=repo_root())
+        return json.loads(desc)
+    finally:
+        shutil.rmtree(out)
 
 
 def main():
-  parser = argparse.ArgumentParser(
-      description='Generate Android.bp from a GN description.')
-  parser.add_argument(
-      '--check-only',
-      help='Don\'t keep the generated files',
-      action='store_true')
-  parser.add_argument(
-      '--desc',
-      help='GN description (e.g., gn desc out --format=json --all-toolchains "//*"'
-  )
-  parser.add_argument(
-      '--extras',
-      help='Extra targets to include at the end of the Blueprint file',
-      default=os.path.join(gn_utils.repo_root(), 'Android.bp.extras'),
-  )
-  parser.add_argument(
-      '--output',
-      help='Blueprint file to create',
-      default=os.path.join(gn_utils.repo_root(), 'Android.bp'),
-  )
-  parser.add_argument(
-      'targets',
-      nargs=argparse.REMAINDER,
-      help='Targets to include in the blueprint (e.g., "//:perfetto_tests")')
-  args = parser.parse_args()
+    parser = argparse.ArgumentParser(
+        description='Generate Android.bp from a GN description.')
+    parser.add_argument(
+        '--desc',
+        help=
+        'GN description (e.g., gn desc out --format=json --all-toolchains "//*"'
+    )
+    parser.add_argument(
+        '--extras',
+        help='Extra targets to include at the end of the Blueprint file',
+        default=os.path.join(repo_root(), 'Android.bp.extras'),
+    )
+    parser.add_argument(
+        '--output',
+        help='Blueprint file to create',
+        default=os.path.join(repo_root(), 'Android.bp'),
+    )
+    parser.add_argument(
+        'targets',
+        nargs=argparse.REMAINDER,
+        help='Targets to include in the blueprint (e.g., "//:perfetto_tests")')
+    args = parser.parse_args()
 
-  if args.desc:
-    with open(args.desc) as f:
-      desc = json.load(f)
-  else:
-    desc = gn_utils.create_build_description(gn_args)
+    if args.desc:
+        with open(args.desc) as f:
+            desc = json.load(f)
+    else:
+        desc = create_build_description()
 
-  gn = gn_utils.GnParser(desc)
-  blueprint = create_blueprint_for_targets(gn, desc, args.targets or
-                                           default_targets)
-  output = [
-      """// Copyright (C) 2017 The Android Open Source Project
+    blueprint = create_blueprint_for_targets(desc, args.targets or
+                                             default_targets)
+    output = [
+        """// Copyright (C) 2017 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.
@@ -767,26 +741,14 @@
 //
 // This file is automatically generated by %s. Do not edit.
 """ % (__file__)
-  ]
-  blueprint.to_string(output)
-  with open(args.extras, 'r') as r:
-    for line in r:
-      output.append(line.rstrip("\n\r"))
-
-  out_files = []
-
-  # Generate the Android.bp file.
-  out_files.append(args.output + '.swp')
-  with open(out_files[-1], 'w') as f:
-    f.write('\n'.join(output))
-
-  # Generate the perfetto_build_flags.h file.
-  out_files.append(os.path.join(buildflags_dir, 'perfetto_build_flags.h.swp'))
-  gn_utils.gen_buildflags(gn_args, out_files[-1])
-
-  # Either check the contents or move the files to their final destination.
-  return gn_utils.check_or_commit_generated_files(out_files, args.check_only)
+    ]
+    blueprint.to_string(output)
+    with open(args.extras, 'r') as r:
+        for line in r:
+            output.append(line.rstrip("\n\r"))
+    with open(args.output, 'w') as f:
+        f.write('\n'.join(output))
 
 
 if __name__ == '__main__':
-  sys.exit(main())
+    sys.exit(main())
diff --git a/tools/gen_bazel b/tools/gen_bazel
deleted file mode 100755
index 38dcee9..0000000
--- a/tools/gen_bazel
+++ /dev/null
@@ -1,488 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-# This tool translates a collection of BUILD.gn files into a mostly equivalent
-# BUILD file for the Bazel build system. The input to the tool is a
-# JSON description of the GN build definition generated with the following
-# command:
-#
-#   gn desc out --format=json --all-toolchains "//*" > desc.json
-#
-# The tool is then given a list of GN labels for which to generate Bazel
-# build rules.
-
-from __future__ import print_function
-import argparse
-import json
-import os
-import re
-import sys
-
-import gn_utils
-
-from compat import itervalues, iteritems, basestring
-
-# Arguments for the GN output directory.
-# host_os="linux" is to generate the right build files from Mac OS.
-gn_args = ' '.join([
-    'host_os="linux"',
-    'is_debug=false',
-    'is_perfetto_build_generator=true',
-    'enable_perfetto_watchdog=true',
-    'monolithic_binaries=true',
-    'target_os="linux"',
-])
-
-# Default targets to translate to the blueprint file.
-
-# These targets will be exported with public visibility in the generated BUILD.
-public_targets = [
-    '//:libperfetto_client_experimental',
-    '//src/perfetto_cmd:perfetto',
-    '//src/traced/probes:traced_probes',
-    '//src/traced/service:traced',
-    '//src/trace_processor:trace_processor_shell',
-    '//src/trace_processor:trace_processor',
-    '//tools/trace_to_text:trace_to_text',
-    '//tools/trace_to_text:libpprofbuilder',
-]
-
-# These targets are required by internal build rules but don't need to be
-# exported publicly.
-default_targets = [
-    '//src/ipc:perfetto_ipc',
-    '//src/ipc/protoc_plugin:ipc_plugin',
-    '//src/protozero:libprotozero',
-    '//src/protozero/protoc_plugin:protozero_plugin',
-    '//src/protozero/protoc_plugin:cppgen_plugin',
-] + public_targets
-
-# Root proto targets (to force discovery of intermediate proto targets).
-# These targets are marked public.
-proto_targets = [
-    '//protos/perfetto/trace:merged_trace',
-    '//protos/perfetto/config:merged_config',
-    '//protos/perfetto/metrics:lite',
-    '//protos/perfetto/trace:lite',
-    '//protos/perfetto/config:lite',
-]
-
-# The directory where the generated perfetto_build_flags.h will be copied into.
-buildflags_dir = 'include/perfetto/base/build_configs/bazel'
-
-# Internal equivalents for third-party libraries that the upstream project
-# depends on.
-external_deps = {
-    '//gn:default_deps': [],
-    '//gn:jsoncpp': ['PERFETTO_CONFIG.deps.jsoncpp'],
-    '//gn:linenoise': ['PERFETTO_CONFIG.deps.linenoise'],
-    '//gn:protobuf_full': ['PERFETTO_CONFIG.deps.protobuf_full'],
-    '//gn:protobuf_lite': ['PERFETTO_CONFIG.deps.protobuf_lite'],
-    '//gn:protoc_lib': ['PERFETTO_CONFIG.deps.protoc_lib'],
-    '//gn:protoc': ['PERFETTO_CONFIG.deps.protoc'],
-    '//gn:sqlite': [
-        'PERFETTO_CONFIG.deps.sqlite',
-        'PERFETTO_CONFIG.deps.sqlite_ext_percentile'
-    ],
-    '//gn:zlib': ['PERFETTO_CONFIG.deps.zlib'],
-    '//gn/standalone:gen_git_revision': [],
-    '//src/trace_processor/metrics:gen_merged_sql_metrics': [[
-        ":cc_merged_sql_metrics"
-    ]]
-}
-
-
-def gen_sql_metrics(target):
-  label = BazelLabel(get_bazel_label_name(target.name), 'genrule')
-  label.srcs += [re.sub('^//', '', x) for x in sorted(target.inputs)]
-  label.outs += target.outputs
-  label.cmd = r'$(location gen_merged_sql_metrics_py) --cpp_out=$@ $(SRCS)'
-  label.tools += [':gen_merged_sql_metrics_py']
-  return [label]
-
-
-custom_actions = {
-    '//src/trace_processor/metrics:gen_merged_sql_metrics': gen_sql_metrics,
-}
-
-# ------------------------------------------------------------------------------
-# End of configuration.
-# ------------------------------------------------------------------------------
-
-
-class Error(Exception):
-  pass
-
-
-class BazelLabel(object):
-
-  def __init__(self, name, type):
-    self.comment = None
-    self.name = name
-    self.type = type
-    self.visibility = []
-    self.srcs = []
-    self.hdrs = []
-    self.deps = []
-    self.external_deps = []
-    self.tools = []
-    self.outs = []
-
-  def __lt__(self, other):
-    if isinstance(other, self.__class__):
-      return self.name < other.name
-    raise TypeError('\'<\' not supported between instances of \'%s\' and \'%s\''
-                    % (type(self).__name__, type(other).__name__))
-
-  def __str__(self):
-    """Converts the object into a Bazel Starlark label."""
-    res = ''
-    res += ('# GN target: %s\n' % self.comment) if self.comment else ''
-    res += '%s(\n' % self.type
-    any_deps = len(self.deps) + len(self.external_deps) > 0
-    ORD = ['name', 'srcs', 'hdrs', 'visibility', 'deps', 'outs', 'cmd', 'tools']
-    hasher = lambda x: sum((99,) + tuple(ord(c) for c in x))
-    key_sorter = lambda kv: ORD.index(kv[0]) if kv[0] in ORD else hasher(kv[0])
-    for k, v in sorted(iteritems(self.__dict__), key=key_sorter):
-      if k in ('type', 'comment',
-               'external_deps') or v is None or (v == [] and
-                                                 (k != 'deps' or not any_deps)):
-        continue
-      res += '    %s = ' % k
-      if isinstance(v, basestring):
-        res += '"%s",\n' % v
-      elif isinstance(v, list):
-        res += '[\n'
-        if k == 'deps' and len(self.external_deps) > 1:
-          indent = '           '
-        else:
-          indent = '    '
-        for entry in v:
-          res += '%s    "%s",\n' % (indent, entry)
-        res += '%s]' % indent
-        if k == 'deps' and self.external_deps:
-          res += ' + %s' % self.external_deps[0]
-          for edep in self.external_deps[1:]:
-            if isinstance(edep, list):
-              res += ' + [\n'
-              for inner_dep in edep:
-                res += '        "%s",\n' % inner_dep
-              res += '    ]'
-            else:
-              res += ' +\n%s%s' % (indent, edep)
-        res += ',\n'
-      else:
-        raise Error('Unsupported value %s', type(v))
-    res += ')\n\n'
-    return res
-
-
-def get_bazel_label_name(gn_name):
-  """Converts a GN target name into a Bazel label name.
-
-  If target is in the public taraget list, returns only the GN target name,
-  e.g.: //src/ipc:perfetto_ipc -> perfetto_ipc
-
-  Otherwise, in the case of an intermediate taraget, returns a mangled path.
-  e.g.:  //include/perfetto/base:base -> include_perfetto_base_base.
-  """
-  if gn_name in default_targets:
-    return gn_utils.label_without_toolchain(gn_name).split(':')[1]
-  return gn_utils.label_to_target_name_with_path(gn_name)
-
-
-def gen_proto_labels(target):
-  """ Generates the xx_proto_library label for proto targets.
-
-  Bazel requires that each protobuf-related target is modeled with two labels:
-  1. A plugin-dependent target (e.g. cc_library, cc_protozero_library) that has
-     only a dependency on 2 and does NOT refer to any .proto sources.
-  2. A plugin-agnostic target that defines only the .proto sources and their
-     dependencies.
-  """
-  assert (target.type == 'proto_library')
-
-  def get_sources_label(target_name):
-    return re.sub('_(lite|zero|cpp)$', '',
-                  get_bazel_label_name(target_name)) + '_protos'
-
-  sources_label_name = get_sources_label(target.name)
-
-  # Generates 1.
-  if target.proto_plugin == 'proto':
-    plugin_label_type = 'perfetto_cc_proto_library'
-  elif target.proto_plugin == 'protozero':
-    plugin_label_type = 'perfetto_cc_protozero_library'
-  elif target.proto_plugin == 'cppgen':
-    plugin_label_type = 'perfetto_cc_protocpp_library'
-  elif target.proto_plugin == 'ipc':
-    plugin_label_type = 'perfetto_cc_ipc_library'
-  else:
-    raise Error('Unknown proto plugin: %s' % target.proto_plugin)
-  plugin_label_name = get_bazel_label_name(target.name)
-  plugin_label = BazelLabel(plugin_label_name, plugin_label_type)
-  plugin_label.comment = target.name
-  plugin_label.deps += [':' + sources_label_name]
-
-  # When using the cppgen plugin we need to pass down also the transitive deps.
-  # For instance consider foo.proto including common.proto. The generated
-  # foo.cc will #include "common.gen.h". Hence the generated cc_protocpp_library
-  # rule need to pass down the dependency on the target that generates
-  # common.gen.{cc,h}. This is not needed for protozero because protozero
-  # headers are fully hermetic deps-wise and use only on forward declarations.
-  if target.proto_deps and target.proto_plugin == 'cppgen':
-    plugin_label.deps += [
-        ':' + get_bazel_label_name(x) for x in target.proto_deps
-    ]
-
-  # Generates 2.
-  sources_label = BazelLabel(sources_label_name, 'perfetto_proto_library')
-  sources_label.comment = target.name
-  assert (all(x.startswith('//') for x in target.sources))
-  assert (all(x.endswith('.proto') for x in target.sources))
-  sources_label.srcs = sorted([x[2:] for x in target.sources])  # Strip //.
-  deps = [':' + get_sources_label(x) for x in target.proto_deps]
-  sources_label.deps = sorted(deps)
-
-  if target.name in proto_targets:
-    sources_label.visibility = ['//visibility:public']
-
-  return [plugin_label, sources_label]
-
-
-def gen_target(gn_target):
-  if gn_target.type == 'proto_library':
-    return gen_proto_labels(gn_target)
-  elif gn_target.type == 'action':
-    if gn_target.name in custom_actions:
-      return custom_actions[gn_target.name](gn_target)
-    return []
-  elif gn_target.type == 'group':
-    return []
-  elif gn_target.type == 'executable':
-    bazel_type = 'perfetto_cc_binary'
-  elif gn_target.type == 'shared_library':
-    bazel_type = 'perfetto_cc_binary'
-    vars['linkshared'] = True
-  elif gn_target.type == 'static_library':
-    bazel_type = 'perfetto_cc_library'
-  elif gn_target.type == 'source_set':
-    bazel_type = 'filegroup'
-  else:
-    raise Error('target type not supported: %s' % gn_target.type)
-
-  label = BazelLabel(get_bazel_label_name(gn_target.name), bazel_type)
-  label.comment = gn_target.name
-  label.srcs = [x[2:] for x in gn_target.sources]
-
-  if gn_target.name in public_targets:
-    label.visibility = ['//visibility:public']
-
-  if gn_target.type in gn_utils.LINKER_UNIT_TYPES:
-    # |source_sets| contains the transitive set of source_set deps.
-    for trans_dep in gn_target.source_set_deps:
-      name = ':' + get_bazel_label_name(trans_dep)
-      if name.startswith(
-          ':include_perfetto_') and gn_target.type != 'executable':
-        label.hdrs += [name]
-      else:
-        label.srcs += [name]
-    for dep in sorted(gn_target.deps):
-      if dep.startswith('//gn:'):
-        assert (dep in external_deps), dep
-      if dep in external_deps:
-        assert (isinstance(external_deps[dep], list))
-        label.external_deps += external_deps[dep]
-      else:
-        label.deps += [':' + get_bazel_label_name(dep)]
-    label.deps += [':' + get_bazel_label_name(x) for x in gn_target.proto_deps]
-
-  # All items starting with : need to be sorted to the end of the list.
-  # However, Python makes specifying a comparator function hard so cheat
-  # instead and make everything start with : sort as if it started with |
-  # As | > all other normal ASCII characters, this will lead to all : targets
-  # starting with : to be sorted to the end.
-  label.srcs = sorted(label.srcs, key=lambda x: x.replace(':', '|'))
-
-  label.deps = sorted(label.deps)
-  label.hdrs = sorted(label.hdrs)
-  return [label]
-
-
-def gen_target_str(gn_target):
-  return ''.join(str(x) for x in gen_target(gn_target))
-
-
-def generate_build(gn_desc, targets, extras):
-  gn = gn_utils.GnParser(gn_desc)
-  res = '''
-# Copyright (C) 2019 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 file is automatically generated by {}. Do not edit.
-
-load("@perfetto_cfg//:perfetto_cfg.bzl", "PERFETTO_CONFIG")
-load(
-    "@perfetto//bazel:rules.bzl",
-    "perfetto_cc_binary",
-    "perfetto_cc_ipc_library",
-    "perfetto_cc_library",
-    "perfetto_cc_proto_library",
-    "perfetto_cc_protocpp_library",
-    "perfetto_cc_protozero_library",
-    "perfetto_java_proto_library",
-    "perfetto_proto_library",
-    "perfetto_py_binary",
-    "perfetto_gensignature_internal_only",
-)
-
-package(default_visibility = ["//visibility:private"])
-
-licenses(["notice"])
-
-exports_files(["NOTICE"])
-
-'''.format(__file__).lstrip()
-
-  # Public targets need to be computed at the beginning (to figure out the
-  # intermediate deps) but printed at the end (because declaration order matters
-  # in Bazel).
-  public_str = ''
-  for target_name in sorted(public_targets):
-    target = gn.get_target(target_name)
-    public_str += gen_target_str(target)
-
-  res += '''
-# ##############################################################################
-# Internal targets
-# ##############################################################################
-
-'''.lstrip()
-  # Generate the other non-public targets.
-  for target_name in sorted(set(default_targets) - set(public_targets)):
-    target = gn.get_target(target_name)
-    res += gen_target_str(target)
-
-  # Generate all the intermediate targets.
-  for target in sorted(itervalues(gn.all_targets)):
-    if target.name in default_targets or target.name in gn.proto_libs:
-      continue
-    res += gen_target_str(target)
-
-  res += '''
-# ##############################################################################
-# Proto libraries
-# ##############################################################################
-
-'''.lstrip()
-  # Force discovery of explicilty listed root proto targets.
-  for target_name in sorted(proto_targets):
-    gn.get_target(target_name)
-
-  # Generate targets for the transitive set of proto targets.
-  # TODO explain deduping here.
-  labels = {}
-  for target in sorted(itervalues(gn.proto_libs)):
-    for label in gen_target(target):
-      labels[label.name] = label
-
-  res += ''.join(str(x) for x in sorted(itervalues(labels)))
-
-  res += '''
-# ##############################################################################
-# Public targets
-# ##############################################################################
-
-'''.lstrip()
-  res += public_str
-  res += '# Content from BUILD.extras\n\n'
-  res += extras
-  return res
-
-
-def main():
-  parser = argparse.ArgumentParser(
-      description='Generate BUILD from a GN description.')
-  parser.add_argument(
-      '--check-only',
-      help='Don\'t keep the generated files',
-      action='store_true')
-  parser.add_argument(
-      '--desc',
-      help='GN description ' +
-      '(e.g., gn desc out --format=json --all-toolchains "//*"')
-  parser.add_argument(
-      '--repo-root',
-      help='Standalone Perfetto repository to generate a GN description',
-      default=gn_utils.repo_root(),
-  )
-  parser.add_argument(
-      '--extras',
-      help='Extra targets to include at the end of the BUILD file',
-      default=os.path.join(gn_utils.repo_root(), 'BUILD.extras'),
-  )
-  parser.add_argument(
-      '--output',
-      help='BUILD file to create',
-      default=os.path.join(gn_utils.repo_root(), 'BUILD'),
-  )
-  parser.add_argument(
-      '--output-proto',
-      help='Proto BUILD file to create',
-      default=os.path.join(gn_utils.repo_root(), 'protos', 'BUILD'),
-  )
-  parser.add_argument(
-      'targets',
-      nargs=argparse.REMAINDER,
-      help='Targets to include in the BUILD file (e.g., "//:perfetto_tests")')
-  args = parser.parse_args()
-
-  if args.desc:
-    with open(args.desc) as f:
-      desc = json.load(f)
-  else:
-    desc = gn_utils.create_build_description(gn_args, args.repo_root)
-
-  out_files = []
-
-  # Generate the main BUILD file.
-  with open(args.extras, 'r') as extra_f:
-    extras = extra_f.read()
-
-  contents = generate_build(desc, args.targets or default_targets, extras)
-  out_files.append(args.output + '.swp')
-  with open(out_files[-1], 'w') as out_f:
-    out_f.write(contents)
-
-  # Generate the build flags file.
-  out_files.append(os.path.join(buildflags_dir, 'perfetto_build_flags.h.swp'))
-  gn_utils.gen_buildflags(gn_args, out_files[-1])
-
-  return gn_utils.check_or_commit_generated_files(out_files, args.check_only)
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/tools/gen_binary_descriptors b/tools/gen_binary_descriptors
index 1d26587..1dc600f 100755
--- a/tools/gen_binary_descriptors
+++ b/tools/gen_binary_descriptors
@@ -24,13 +24,10 @@
 import subprocess
 import hashlib
 import textwrap
-from compat import iteritems
 
 SOURCE_TARGET = {
     'protos/perfetto/config/perfetto_config.proto':
-        'src/perfetto_cmd/perfetto_config.descriptor.h',
-    'protos/perfetto/metrics/metrics.proto':
-        'src/trace_processor/metrics/metrics.descriptor.h',
+            'src/perfetto_cmd/perfetto_config.descriptor.h',
 }
 
 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
@@ -40,15 +37,18 @@
 
 def hash_path(path):
   hash = hashlib.sha1()
-  with open(os.path.join(ROOT_DIR, path), 'rb') as f:
+  with open(os.path.join(ROOT_DIR, path)) as f:
     hash.update(f.read())
   return hash.hexdigest()
 
 
 def find_protoc():
-  for root, _, files in os.walk(os.path.join(ROOT_DIR, 'out')):
+  for root, dirs, files in os.walk(ROOT_DIR):
     if 'protoc' in files:
       return os.path.join(root, 'protoc')
+    for name in ('src', 'buildtools'):
+      if name in dirs:
+        dirs.remove(name)
   return None
 
 
@@ -59,7 +59,7 @@
   with open(target, 'rb') as f:
     s = f.read()
 
-  hashes = re.findall(r'// SHA1\((.*)\)\n// (.*)\n', s.decode())
+  hashes = re.findall(r'// SHA1\((.*)\)\n// (.*)\n', s)
   assert sorted([SCRIPT_PATH, source]) == sorted([key for key, _ in hashes])
   for path, expected_sha1 in hashes:
     actual_sha1 = hash_path(os.path.join(ROOT_DIR, path))
@@ -75,24 +75,19 @@
   with tempfile.NamedTemporaryFile() as fdescriptor:
     subprocess.check_call([
         protoc_path,
-        '--include_imports',
-        '--proto_path=.',
-        '--descriptor_set_out={}'.format(fdescriptor.name),
+        '--proto_path=protos',
+        '-o{}'.format(fdescriptor.name),
         source,
-    ],
-                          cwd=ROOT_DIR)
+    ], cwd=ROOT_DIR)
 
     s = fdescriptor.read()
     proto_name = source_name[:-len('.proto')].title().replace("_", "")
     constant_name = 'k' + proto_name + 'Descriptor'
-    try:
-      ord(s[0])
-      ordinal = ord
-    except TypeError:
-      ordinal = lambda x: x
-    binary = '{' + ', '.join('{0:#04x}'.format(ordinal(c)) for c in s) + '}'
-    binary = textwrap.fill(
-        binary, width=80, initial_indent='    ', subsequent_indent='     ')
+    binary = '{' + ', '.join('{0:#04x}'.format(ord(c)) for c in s) + '}'
+    binary = textwrap.fill(binary,
+        width=80,
+        initial_indent='    ',
+        subsequent_indent='     ')
     include_guard = target.replace('/', '_').replace('.', '_').upper() + '_'
 
     with open(os.path.join(ROOT_DIR, target), 'wb') as f:
@@ -123,17 +118,17 @@
 }}  // namespace perfetto
 
 #endif  // {include_guard}
-""".format(
-          proto_name=proto_name,
-          size=len(s),
-          constant_name=constant_name,
-          binary=binary,
-          include_guard=include_guard,
-          script_path=SCRIPT_PATH,
-          script_hash=hash_path(__file__),
-          source_path=source,
-          source_hash=hash_path(os.path.join(source)),
-      ).encode())
+""".format(**{
+        'proto_name': proto_name,
+        'size': len(s),
+        'constant_name': constant_name,
+        'binary': binary,
+        'include_guard': include_guard,
+        'script_path': SCRIPT_PATH,
+        'script_hash': hash_path(__file__),
+        'source_path': source,
+        'source_hash': hash_path(os.path.join(source)),
+      }))
 
 
 def main():
@@ -143,9 +138,9 @@
   args = parser.parse_args()
 
   try:
-    for source, target in iteritems(SOURCE_TARGET):
+    for source, target in SOURCE_TARGET.iteritems():
       if args.check_only:
-        check(source, target)
+          check(source, target)
       else:
         protoc = args.protoc or find_protoc()
         assert protoc, 'protoc not found specific (--protoc PROTOC_PATH)'
@@ -159,6 +154,5 @@
     print('Error: {}'.format(e))
     return 1
 
-
 if __name__ == '__main__':
   exit(main())
diff --git a/tools/gen_build b/tools/gen_build
new file mode 100755
index 0000000..2bfbb3d
--- /dev/null
+++ b/tools/gen_build
@@ -0,0 +1,687 @@
+#!/usr/bin/env python
+# 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.
+
+# This tool translates a collection of BUILD.gn files into a mostly equivalent
+# BUILD file for the Bazel build system. The input to the tool is a
+# JSON description of the GN build definition generated with the following
+# command:
+#
+#   gn desc out --format=json --all-toolchains "//*" > desc.json
+#
+# The tool is then given a list of GN labels for which to generate Bazel
+# build rules.
+
+from __future__ import print_function
+import argparse
+import errno
+import functools
+import json
+import os
+import re
+import shutil
+import subprocess
+import sys
+import textwrap
+
+# Copyright header for generated code.
+header = """# Copyright (C) 2019 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 file is automatically generated by {}. Do not edit.
+""".format(__file__)
+
+# Arguments for the GN output directory.
+# host_os="linux" is to generate the right build files from Mac OS.
+gn_args = 'target_os="linux" is_debug=false host_os="linux"'
+
+# Default targets to translate to the blueprint file.
+default_targets = [
+  '//src/protozero:libprotozero',
+  '//src/trace_processor:trace_processor',
+  '//src/trace_processor:trace_processor_shell_host(//gn/standalone/toolchain:gcc_like_host)',
+  '//tools/trace_to_text:trace_to_text_host(//gn/standalone/toolchain:gcc_like_host)',
+  '//protos/perfetto/config:merged_config_gen',
+  '//protos/perfetto/trace:merged_trace_gen',
+]
+
+# Aliases to add to the BUILD file
+alias_targets = {
+  '//src/protozero:libprotozero': 'libprotozero',
+  '//src/trace_processor:trace_processor': 'trace_processor',
+  '//src/trace_processor:trace_processor_shell_host': 'trace_processor_shell',
+  '//tools/trace_to_text:trace_to_text_host': 'trace_to_text',
+}
+
+
+def enable_sqlite(module):
+  module.deps.add(Label('//third_party/sqlite'))
+  module.deps.add(Label('//third_party/sqlite:sqlite_ext_percentile'))
+
+
+def enable_jsoncpp(module):
+  module.deps.add(Label('//third_party/perfetto/google:jsoncpp'))
+
+
+def enable_linenoise(module):
+  module.deps.add(Label('//third_party/perfetto/google:linenoise'))
+
+
+def enable_gtest_prod(module):
+  module.deps.add(Label('//third_party/perfetto/google:gtest_prod'))
+
+
+def enable_protobuf_full(module):
+  module.deps.add(Label('//third_party/protobuf:libprotoc'))
+  module.deps.add(Label('//third_party/protobuf'))
+
+
+def enable_perfetto_version(module):
+  module.deps.add(Label('//third_party/perfetto/google:perfetto_version'))
+
+
+def disable_module(module):
+  pass
+
+
+# Internal equivalents for third-party libraries that the upstream project
+# depends on.
+builtin_deps = {
+    '//gn:jsoncpp_deps': enable_jsoncpp,
+    '//buildtools:linenoise': enable_linenoise,
+    '//buildtools:protobuf_lite': disable_module,
+    '//buildtools:protobuf_full': enable_protobuf_full,
+    '//buildtools:protoc': disable_module,
+    '//buildtools:sqlite': enable_sqlite,
+    '//gn:default_deps': disable_module,
+    '//gn:gtest_prod_config': enable_gtest_prod,
+    '//gn:protoc_lib_deps': enable_protobuf_full,
+    '//gn/standalone:gen_git_revision': enable_perfetto_version,
+}
+
+# ----------------------------------------------------------------------------
+# End of configuration.
+# ----------------------------------------------------------------------------
+
+
+def check_output(cmd, cwd):
+  try:
+    output = subprocess.check_output(
+        cmd, stderr=subprocess.STDOUT, cwd=cwd)
+  except subprocess.CalledProcessError as e:
+    print('Cmd "{}" failed in {}:'.format(
+        ' '.join(cmd), cwd), file=sys.stderr)
+    print(e.output)
+    exit(1)
+  else:
+    return output
+
+
+class Error(Exception):
+  pass
+
+
+def repo_root():
+  """Returns an absolute path to the repository root."""
+  return os.path.join(
+      os.path.realpath(os.path.dirname(__file__)), os.path.pardir)
+
+
+def create_build_description(repo_root):
+  """Creates the JSON build description by running GN."""
+
+  out = os.path.join(repo_root, 'out', 'tmp.gen_build')
+  try:
+    try:
+      os.makedirs(out)
+    except OSError as e:
+      if e.errno != errno.EEXIST:
+        raise
+    check_output(
+        ['gn', 'gen', out, '--args=%s' % gn_args], repo_root)
+    desc = check_output(
+        ['gn', 'desc', out, '--format=json', '--all-toolchains', '//*'],
+        repo_root)
+    return json.loads(desc)
+  finally:
+    shutil.rmtree(out)
+
+
+def label_to_path(label):
+  """Turn a GN output label (e.g., //some_dir/file.cc) into a path."""
+  assert label.startswith('//')
+  return label[2:]
+
+
+def label_to_target_name_with_path(label):
+  """
+  Turn a GN label into a target name involving the full path.
+  e.g., //src/perfetto:tests -> src_perfetto_tests
+  """
+  name = re.sub(r'^//:?', '', label)
+  name = re.sub(r'[^a-zA-Z0-9_]', '_', name)
+  return name
+
+
+def label_without_toolchain(label):
+  """Strips the toolchain from a GN label.
+
+  Return a GN label (e.g //buildtools:protobuf(//gn/standalone/toolchain:
+  gcc_like_host) without the parenthesised toolchain part.
+  """
+  return label.split('(')[0]
+
+
+def is_public_header(label):
+  """
+  Returns if this is a c++ header file that is part of the API.
+  Args:
+      label: Label to evaluate
+  """
+  return label.endswith('.h') and label.startswith('//include/perfetto/')
+
+
+@functools.total_ordering
+class Label(object):
+  """Represents a label in BUILD file terminology. This class wraps a string
+  label to allow for correct comparision of labels for sorting.
+
+  Args:
+      label: The string rerepsentation of the label.
+  """
+
+  def __init__(self, label):
+    self.label = label
+
+  def is_absolute(self):
+    return self.label.startswith('//')
+
+  def dirname(self):
+    return self.label.split(':')[0] if ':' in self.label else self.label
+
+  def basename(self):
+    return self.label.split(':')[1] if ':' in self.label else ''
+
+  def __eq__(self, other):
+    return self.label == other.label
+
+  def __lt__(self, other):
+    return (
+        self.is_absolute(),
+        self.dirname(),
+        self.basename()
+    ) < (
+        other.is_absolute(),
+        other.dirname(),
+        other.basename()
+    )
+
+  def __str__(self):
+    return self.label
+
+  def __hash__(self):
+    return hash(self.label)
+
+
+class Writer(object):
+  def __init__(self, output, width=79):
+    self.output = output
+    self.width = width
+
+  def comment(self, text):
+    for line in textwrap.wrap(text,
+                              self.width - 2,
+                              break_long_words=False,
+                              break_on_hyphens=False):
+      self.output.write('# {}\n'.format(line))
+
+  def newline(self):
+    self.output.write('\n')
+
+  def line(self, s, indent=0):
+    self.output.write('    ' * indent + s + '\n')
+
+  def variable(self, key, value, sort=True):
+    if value is None:
+      return
+    if isinstance(value, set) or isinstance(value, list):
+      if len(value) == 0:
+        return
+      self.line('{} = ['.format(key), indent=1)
+      for v in sorted(list(value)) if sort else value:
+        self.line('"{}",'.format(v), indent=2)
+      self.line('],', indent=1)
+    elif isinstance(value, basestring):
+      self.line('{} = "{}",'.format(key, value), indent=1)
+    else:
+      self.line('{} = {},'.format(key, value), indent=1)
+
+  def header(self):
+    self.output.write(header)
+
+
+class Target(object):
+  """In-memory representation of a BUILD target."""
+
+  def __init__(self, type, name, gn_name=None):
+    assert type in ('cc_binary', 'cc_library', 'cc_proto_library',
+                    'proto_library', 'filegroup', 'alias',
+                    'pbzero_cc_proto_library', 'genrule', )
+    self.type = type
+    self.name = name
+    self.srcs = set()
+    self.hdrs = set()
+    self.deps = set()
+    self.visibility = set()
+    self.gn_name = gn_name
+    self.is_pbzero = False
+    self.src_proto_library = None
+    self.outs = set()
+    self.cmd = None
+    self.tools = set()
+
+  def write(self, writer):
+    if self.gn_name:
+      writer.comment('GN target: {}'.format(self.gn_name))
+
+    writer.line('{}('.format(self.type))
+    writer.variable('name', self.name)
+    writer.variable('srcs', self.srcs)
+    writer.variable('hdrs', self.hdrs)
+
+    if self.type == 'proto_library' and not self.is_pbzero:
+      if self.srcs:
+        writer.variable('has_services', 1)
+      writer.variable('cc_api_version', 2)
+      if self.srcs:
+        writer.variable('cc_generic_services', 1)
+
+    writer.variable('src_proto_library', self.src_proto_library)
+
+    writer.variable('outs', self.outs)
+    writer.variable('cmd', self.cmd)
+    writer.variable('tools', self.tools)
+
+    # Keep visibility and deps last.
+    writer.variable('visibility', self.visibility)
+
+    if type != 'filegroup':
+      writer.variable('deps', self.deps)
+
+    writer.line(')')
+
+
+class Build(object):
+  """In-memory representation of a BUILD file."""
+
+  def __init__(self, public, header_lines=[]):
+    self.targets = {}
+    self.public = public
+    self.header_lines = header_lines
+
+  def add_target(self, target):
+    self.targets[target.name] = target
+
+  def write(self, writer):
+    writer.header()
+    writer.newline()
+    for line in self.header_lines:
+      writer.line(line)
+    if self.header_lines:
+      writer.newline()
+    if self.public:
+      writer.line(
+          'package(default_visibility = ["//visibility:public"])')
+    else:
+      writer.line(
+          'package(default_visibility = ["//third_party/perfetto:__subpackages__"])')
+    writer.newline()
+    writer.line('licenses(["notice"])  # Apache 2.0')
+    writer.newline()
+    writer.line('exports_files(["LICENSE"])')
+    writer.newline()
+
+    sorted_targets = sorted(
+        self.targets.itervalues(), key=lambda m: m.name)
+    for target in sorted_targets[:-1]:
+      target.write(writer)
+      writer.newline()
+
+    # BUILD files shouldn't have a trailing new line.
+    sorted_targets[-1].write(writer)
+
+
+class BuildGenerator(object):
+  def __init__(self, desc):
+    self.desc = desc
+    self.action_generated_files = set()
+
+    for target in self.desc.itervalues():
+      if target['type'] == 'action':
+        self.action_generated_files.update(target['outputs'])
+
+
+  def create_build_for_targets(self, targets):
+    """Generate a BUILD for a list of GN targets and aliases."""
+    self.build = Build(public=True)
+
+    proto_cc_import = 'load("//tools/build_defs/proto/cpp:cc_proto_library.bzl", "cc_proto_library")'
+    pbzero_cc_import = 'load("//third_party/perfetto/google:build_defs.bzl", "pbzero_cc_proto_library")'
+    self.proto_build = Build(public=False, header_lines=[
+                        proto_cc_import, pbzero_cc_import])
+
+    for target in targets:
+      self.create_target(target)
+
+    return (self.build, self.proto_build)
+
+
+  def resolve_dependencies(self, target_name):
+    """Return the set of direct dependent-on targets for a GN target.
+
+    Args:
+        desc: JSON GN description.
+        target_name: Name of target
+
+    Returns:
+        A set of transitive dependencies in the form of GN targets.
+    """
+
+    if label_without_toolchain(target_name) in builtin_deps:
+      return set()
+    target = self.desc[target_name]
+    resolved_deps = set()
+    for dep in target.get('deps', []):
+      resolved_deps.add(dep)
+    return resolved_deps
+
+
+  def apply_module_sources_to_target(self, target, module_desc):
+    """
+    Args:
+        target: Module to which dependencies should be added.
+        module_desc: JSON GN description of the module.
+        visibility: Whether the module is visible with respect to the target.
+    """
+    for src in module_desc['sources']:
+      label = Label(label_to_path(src))
+      if target.type == 'cc_library' and is_public_header(src):
+        target.hdrs.add(label)
+      else:
+        target.srcs.add(label)
+
+
+  def apply_module_dependency(self, target, dep_name):
+    """
+    Args:
+        build: BUILD instance which is being generated.
+        proto_build: BUILD instance which is being generated to hold protos.
+        desc: JSON GN description.
+        target: Module to which dependencies should be added.
+        dep_name: GN target of the dependency.
+    """
+    # If the dependency refers to a library which we can replace with an internal
+    # equivalent, stop recursing and patch the dependency in.
+    dep_name_no_toolchain = label_without_toolchain(dep_name)
+    if dep_name_no_toolchain in builtin_deps:
+      builtin_deps[dep_name_no_toolchain](target)
+      return
+
+    dep_desc = self.desc[dep_name]
+    if dep_desc['type'] == 'source_set':
+      for inner_name in self.resolve_dependencies(dep_name):
+        self.apply_module_dependency(target, inner_name)
+
+      # Any source set which has a source generated by an action doesn't need
+      # to be depended on as we will depend on the action directly.
+      if any(src in self.action_generated_files for src in dep_desc['sources']):
+        return
+
+      self.apply_module_sources_to_target(target, dep_desc)
+    elif dep_desc['type'] == 'action':
+      args = dep_desc['args']
+      if "gen_merged_sql_metrics" in dep_name:
+        dep_target = self.create_merged_sql_metrics_target(dep_name)
+        target.deps.add(Label("//third_party/perfetto:" + dep_target.name))
+
+        if target.type == 'cc_library' or target.type == 'cc_binary':
+          target.srcs.update(dep_target.outs)
+      elif args[0].endswith('/protoc'):
+        (proto_target, cc_target) = self.create_proto_target(dep_name)
+        if target.type == 'proto_library':
+          dep_target_name = proto_target.name
+        else:
+          dep_target_name = cc_target.name
+        target.deps.add(
+            Label("//third_party/perfetto/protos:" + dep_target_name))
+      else:
+        raise Error('Unsupported action in target %s: %s' % (dep_target_name,
+                                                            args))
+    elif dep_desc['type'] == 'static_library':
+      dep_target = self.create_target(dep_name)
+      target.deps.add(Label("//third_party/perfetto:" + dep_target.name))
+    elif dep_desc['type'] == 'group':
+      for inner_name in self.resolve_dependencies(dep_name):
+        self.apply_module_dependency(target, inner_name)
+    elif dep_desc['type'] == 'executable':
+      # Just create the dep target but don't add it as a dep because it's an
+      # executable.
+      self.create_target(dep_name)
+    else:
+      raise Error('Unknown target name %s with type: %s' %
+                  (dep_name, dep_desc['type']))
+
+  def create_merged_sql_metrics_target(self, gn_target_name):
+    target_desc = self.desc[gn_target_name]
+    gn_target_name_no_toolchain = label_without_toolchain(gn_target_name)
+    target = Target(
+      'genrule',
+      'gen_merged_sql_metrics',
+      gn_name=gn_target_name_no_toolchain,
+    )
+    target.outs.update(
+      Label(src[src.index('gen/') + len('gen/'):])
+      for src in target_desc.get('outputs', [])
+    )
+    target.cmd = '$(location gen_merged_sql_metrics_py) --cpp_out=$@ $(SRCS)'
+    target.tools.update([
+      'gen_merged_sql_metrics_py',
+    ])
+    target.srcs.update(
+      Label(label_to_path(src))
+      for src in target_desc.get('inputs', [])
+      if src not in self.action_generated_files
+    )
+    self.build.add_target(target)
+    return target
+
+  def create_proto_target(self, gn_target_name):
+    target_desc = self.desc[gn_target_name]
+    args = target_desc['args']
+
+    gn_target_name_no_toolchain = label_without_toolchain(gn_target_name)
+    stripped_path = gn_target_name_no_toolchain.replace("protos/perfetto/", "")
+    pretty_target_name = label_to_target_name_with_path(stripped_path)
+    pretty_target_name = pretty_target_name.replace("_lite_gen", "")
+    pretty_target_name = pretty_target_name.replace("_zero_gen", "_zero")
+
+    proto_target = Target(
+      'proto_library',
+      pretty_target_name,
+      gn_name=gn_target_name_no_toolchain
+    )
+    proto_target.is_pbzero = any("pbzero" in arg for arg in args)
+    proto_target.srcs.update([
+      Label(label_to_path(src).replace('protos/', ''))
+      for src in target_desc.get('sources', [])
+    ])
+    if not proto_target.is_pbzero:
+      proto_target.visibility.add("//visibility:public")
+    self.proto_build.add_target(proto_target)
+
+    for dep_name in self.resolve_dependencies(gn_target_name):
+      self.apply_module_dependency(proto_target, dep_name)
+
+    if proto_target.is_pbzero:
+      # Remove all the protozero srcs from the proto_library.
+      proto_target.srcs.difference_update(
+          [src for src in proto_target.srcs if not src.label.endswith('.proto')])
+
+      # Remove all the non-proto deps from the proto_library and add to the cc
+      # library.
+      cc_deps = [
+        dep for dep in proto_target.deps
+        if not dep.label.startswith('//third_party/perfetto/protos')
+      ]
+      proto_target.deps.difference_update(cc_deps)
+
+      cc_target_name = proto_target.name + "_cc_proto"
+      cc_target = Target('pbzero_cc_proto_library', cc_target_name,
+                         gn_name=gn_target_name_no_toolchain)
+
+      cc_target.deps.add(Label('//third_party/perfetto:libprotozero'))
+      cc_target.deps.update(cc_deps)
+
+      # Add the proto_library to the cc_target.
+      cc_target.src_proto_library = \
+          "//third_party/perfetto/protos:" + proto_target.name
+
+      self.proto_build.add_target(cc_target)
+    else:
+      cc_target_name = proto_target.name + "_cc_proto"
+      cc_target = Target('cc_proto_library',
+                        cc_target_name, gn_name=gn_target_name_no_toolchain)
+      cc_target.visibility.add("//visibility:public")
+      cc_target.deps.add(
+          Label("//third_party/perfetto/protos:" + proto_target.name))
+      self.proto_build.add_target(cc_target)
+
+    return (proto_target, cc_target)
+
+
+  def create_target(self, gn_target_name):
+    """Generate module(s) for a given GN target.
+
+    Given a GN target name, generate one or more corresponding modules into a
+    build file.
+
+    Args:
+        build: Build instance which is being generated.
+        desc: JSON GN description.
+        gn_target_name: GN target name for module generation.
+    """
+
+    target_desc = self.desc[gn_target_name]
+    if target_desc['type'] == 'action':
+      args = target_desc['args']
+      if args[0].endswith('/protoc'):
+        return self.create_proto_target(gn_target_name)
+      else:
+        raise Error('Unsupported action in target %s: %s' % (gn_target_name,
+                                                            args))
+    elif target_desc['type'] == 'executable':
+      target_type = 'cc_binary'
+    elif target_desc['type'] == 'static_library':
+      target_type = 'cc_library'
+    elif target_desc['type'] == 'source_set':
+      target_type = 'filegroup'
+    else:
+      raise Error('Unknown target type: %s' % target_desc['type'])
+
+    label_no_toolchain = label_without_toolchain(gn_target_name)
+    target_name_path = label_to_target_name_with_path(label_no_toolchain)
+    target_name = alias_targets.get(label_no_toolchain, target_name_path)
+    target = Target(target_type, target_name, gn_name=label_no_toolchain)
+    target.srcs.update(
+        Label(label_to_path(src))
+        for src in target_desc.get('sources', [])
+        if src not in self.action_generated_files
+    )
+
+    for dep_name in self.resolve_dependencies(gn_target_name):
+      self.apply_module_dependency(target, dep_name)
+
+    self.build.add_target(target)
+    return target
+
+def main():
+  parser = argparse.ArgumentParser(
+      description='Generate BUILD from a GN description.')
+  parser.add_argument(
+      '--desc',
+      help='GN description (e.g., gn desc out --format=json --all-toolchains "//*"'
+  )
+  parser.add_argument(
+      '--repo-root',
+      help='Standalone Perfetto repository to generate a GN description',
+      default=repo_root(),
+  )
+  parser.add_argument(
+      '--extras',
+      help='Extra targets to include at the end of the BUILD file',
+      default=os.path.join(repo_root(), 'BUILD.extras'),
+  )
+  parser.add_argument(
+      '--output',
+      help='BUILD file to create',
+      default=os.path.join(repo_root(), 'BUILD'),
+  )
+  parser.add_argument(
+      '--output-proto',
+      help='Proto BUILD file to create',
+      default=os.path.join(repo_root(), 'protos', 'BUILD'),
+  )
+  parser.add_argument(
+      'targets',
+      nargs=argparse.REMAINDER,
+      help='Targets to include in the BUILD file (e.g., "//:perfetto_tests")')
+  args = parser.parse_args()
+
+  if args.desc:
+    with open(args.desc) as f:
+      desc = json.load(f)
+  else:
+    desc = create_build_description(args.repo_root)
+
+  build_generator = BuildGenerator(desc)
+  build, proto_build = build_generator.create_build_for_targets(
+      args.targets or default_targets)
+  with open(args.output, 'w') as f:
+    writer = Writer(f)
+    build.write(writer)
+    writer.newline()
+
+    with open(args.extras, 'r') as r:
+      for line in r:
+        writer.line(line.rstrip("\n\r"))
+
+  with open(args.output_proto, 'w') as f:
+    proto_build.write(Writer(f))
+
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/tools/gen_merged_protos b/tools/gen_merged_protos
index 2530e71..5a0a97a 100755
--- a/tools/gen_merged_protos
+++ b/tools/gen_merged_protos
@@ -19,92 +19,72 @@
 import os
 import re
 import sys
-from codecs import open
 
 COMMON_PROTOS = (
-    'protos/perfetto/common/android_log_constants.proto',
-    'protos/perfetto/common/data_source_descriptor.proto',
-    'protos/perfetto/common/gpu_counter_descriptor.proto',
-    'protos/perfetto/common/sys_stats_counters.proto',
-    'protos/perfetto/common/trace_stats.proto',
-    'protos/perfetto/common/tracing_service_state.proto',
-    'protos/perfetto/common/track_event_descriptor.proto',
+  'protos/perfetto/common/android_log_constants.proto',
+  'protos/perfetto/common/sys_stats_counters.proto',
 )
 
 CONFIG_PROTOS = (
-    'protos/perfetto/config/android/android_log_config.proto',
-    'protos/perfetto/config/chrome/chrome_config.proto',
-    'protos/perfetto/config/data_source_config.proto',
-    'protos/perfetto/config/ftrace/ftrace_config.proto',
-    'protos/perfetto/config/inode_file/inode_file_config.proto',
-    'protos/perfetto/config/power/android_power_config.proto',
-    'protos/perfetto/config/process_stats/process_stats_config.proto',
-    'protos/perfetto/config/sys_stats/sys_stats_config.proto',
-    'protos/perfetto/config/test_config.proto',
-    'protos/perfetto/config/trace_config.proto',
-    'protos/perfetto/config/profiling/heapprofd_config.proto',
-    'protos/perfetto/config/profiling/java_hprof_config.proto',
-    'protos/perfetto/config/gpu/gpu_counter_config.proto',
-    'protos/perfetto/config/android/packages_list_config.proto',
+  'protos/perfetto/config/android/android_log_config.proto',
+  'protos/perfetto/config/chrome/chrome_config.proto',
+  'protos/perfetto/config/data_source_config.proto',
+  'protos/perfetto/config/ftrace/ftrace_config.proto',
+  'protos/perfetto/config/inode_file/inode_file_config.proto',
+  'protos/perfetto/config/power/android_power_config.proto',
+  'protos/perfetto/config/process_stats/process_stats_config.proto',
+  'protos/perfetto/config/sys_stats/sys_stats_config.proto',
+  'protos/perfetto/config/test_config.proto',
+  'protos/perfetto/config/trace_config.proto',
+  'protos/perfetto/config/profiling/heapprofd_config.proto',
+  'protos/perfetto/config/android/packages_list_config.proto',
 )
 
 MERGED_CONFIG_PROTO = 'protos/perfetto/config/perfetto_config.proto'
 
 TRACE_PROTOS = (
-    'protos/perfetto/trace/android/android_log.proto',
-    'protos/perfetto/trace/android/graphics_frame_event.proto',
-    'protos/perfetto/trace/android/packages_list.proto',
-    'protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto',
-    "protos/perfetto/trace/chrome/chrome_metadata.proto",
-    'protos/perfetto/trace/clock_snapshot.proto',
-    'protos/perfetto/trace/filesystem/inode_file_map.proto',
-    'protos/perfetto/trace/ftrace/binder.proto',
-    'protos/perfetto/trace/ftrace/block.proto',
-    'protos/perfetto/trace/ftrace/clk.proto',
-    'protos/perfetto/trace/ftrace/ext4.proto',
-    'protos/perfetto/trace/ftrace/f2fs.proto',
-    'protos/perfetto/trace/ftrace/filemap.proto',
-    'protos/perfetto/trace/ftrace/ftrace.proto',
-    'protos/perfetto/trace/ftrace/ftrace_event.proto',
-    'protos/perfetto/trace/ftrace/ftrace_event_bundle.proto',
-    'protos/perfetto/trace/ftrace/ftrace_stats.proto',
-    'protos/perfetto/trace/ftrace/generic.proto',
-    'protos/perfetto/trace/ftrace/kmem.proto',
-    'protos/perfetto/trace/ftrace/lowmemorykiller.proto',
-    'protos/perfetto/trace/ftrace/mm_event.proto',
-    'protos/perfetto/trace/ftrace/power.proto',
-    'protos/perfetto/trace/ftrace/raw_syscalls.proto',
-    'protos/perfetto/trace/ftrace/sched.proto',
-    'protos/perfetto/trace/ftrace/signal.proto',
-    'protos/perfetto/trace/ftrace/systrace.proto',
-    'protos/perfetto/trace/ftrace/task.proto',
-    'protos/perfetto/trace/ftrace/vmscan.proto',
-    'protos/perfetto/trace/interned_data/interned_data.proto',
-    'protos/perfetto/trace/perfetto/perfetto_metatrace.proto',
-    'protos/perfetto/trace/power/battery_counters.proto',
-    'protos/perfetto/trace/power/power_rails.proto',
-    'protos/perfetto/trace/profiling/heap_graph.proto',
-    'protos/perfetto/trace/profiling/profile_common.proto',
-    'protos/perfetto/trace/profiling/profile_packet.proto',
-    'protos/perfetto/trace/ps/process_stats.proto',
-    'protos/perfetto/trace/ps/process_tree.proto',
-    'protos/perfetto/trace/sys_stats/sys_stats.proto',
-    'protos/perfetto/trace/system_info.proto',
-    'protos/perfetto/trace/trace.proto',
-    'protos/perfetto/trace/trace_packet.proto',
-    'protos/perfetto/trace/trace_packet_defaults.proto',
-    'protos/perfetto/trace/track_event/debug_annotation.proto',
-    'protos/perfetto/trace/track_event/log_message.proto',
-    'protos/perfetto/trace/track_event/process_descriptor.proto',
-    'protos/perfetto/trace/track_event/source_location.proto',
-    'protos/perfetto/trace/track_event/task_execution.proto',
-    'protos/perfetto/trace/track_event/thread_descriptor.proto',
-    'protos/perfetto/trace/track_event/track_descriptor.proto',
-    'protos/perfetto/trace/track_event/track_event.proto',
-    'protos/perfetto/trace/trigger.proto',
-    'protos/perfetto/trace/gpu/gpu_counter_event.proto',
-    'protos/perfetto/trace/gpu/gpu_log.proto',
-    'protos/perfetto/trace/gpu/gpu_render_stage_event.proto',
+  'protos/perfetto/common/trace_stats.proto', # only referenced by trace protos
+  'protos/perfetto/trace/android/android_log.proto',
+  'protos/perfetto/trace/android/packages_list.proto',
+  'protos/perfetto/trace/clock_snapshot.proto',
+  'protos/perfetto/trace/filesystem/inode_file_map.proto',
+  'protos/perfetto/trace/ftrace/binder.proto',
+  'protos/perfetto/trace/ftrace/block.proto',
+  'protos/perfetto/trace/ftrace/clk.proto',
+  'protos/perfetto/trace/ftrace/ext4.proto',
+  'protos/perfetto/trace/ftrace/f2fs.proto',
+  'protos/perfetto/trace/ftrace/filemap.proto',
+  'protos/perfetto/trace/ftrace/ftrace.proto',
+  'protos/perfetto/trace/ftrace/ftrace_event.proto',
+  'protos/perfetto/trace/ftrace/ftrace_event_bundle.proto',
+  'protos/perfetto/trace/ftrace/ftrace_stats.proto',
+  'protos/perfetto/trace/ftrace/generic.proto',
+  'protos/perfetto/trace/ftrace/kmem.proto',
+  'protos/perfetto/trace/ftrace/lowmemorykiller.proto',
+  'protos/perfetto/trace/ftrace/mm_event.proto',
+  'protos/perfetto/trace/ftrace/power.proto',
+  'protos/perfetto/trace/ftrace/raw_syscalls.proto',
+  'protos/perfetto/trace/ftrace/sched.proto',
+  'protos/perfetto/trace/ftrace/signal.proto',
+  'protos/perfetto/trace/ftrace/systrace.proto',
+  'protos/perfetto/trace/ftrace/task.proto',
+  'protos/perfetto/trace/ftrace/vmscan.proto',
+  'protos/perfetto/trace/interned_data/interned_data.proto',
+  'protos/perfetto/trace/power/battery_counters.proto',
+  'protos/perfetto/trace/power/power_rails.proto',
+  'protos/perfetto/trace/profiling/profile_packet.proto',
+  'protos/perfetto/trace/ps/process_stats.proto',
+  'protos/perfetto/trace/ps/process_tree.proto',
+  'protos/perfetto/trace/sys_stats/sys_stats.proto',
+  'protos/perfetto/trace/system_info.proto',
+  'protos/perfetto/trace/trace.proto',
+  'protos/perfetto/trace/trace_packet.proto',
+  'protos/perfetto/trace/track_event/debug_annotation.proto',
+  'protos/perfetto/trace/track_event/process_descriptor.proto',
+  'protos/perfetto/trace/track_event/task_execution.proto',
+  'protos/perfetto/trace/track_event/thread_descriptor.proto',
+  'protos/perfetto/trace/track_event/track_event.proto',
+  'protos/perfetto/trace/trigger.proto',
 )
 
 MERGED_TRACE_PROTO = 'protos/perfetto/trace/perfetto_trace.proto'
@@ -124,13 +104,12 @@
 package perfetto.protos;
 '''
 
-
 def merge_protos(proto_paths, output_path):
   root_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
   merged_content = ''
   for proto in proto_paths:
     path = os.path.join(root_dir, proto)
-    with open(path, 'r', encoding='utf-8') as f:
+    with open(path) as f:
       content = f.read()
 
     # Remove header
@@ -169,7 +148,7 @@
 
   prev_content = None
   if os.path.exists(out_path):
-    with open(out_path, 'r', encoding='utf-8') as fprev:
+    with open(out_path, 'rb') as fprev:
       prev_content = fprev.read()
 
   if prev_content == merged_content:
@@ -179,11 +158,10 @@
     return False
 
   print('Updating {}'.format(output_path))
-  with open(out_path, 'w', encoding='utf-8') as fout:
+  with open(out_path, 'wb') as fout:
     fout.write(merged_content)
   return True
 
-
 def main():
   config_result = merge_protos(COMMON_PROTOS + CONFIG_PROTOS,
                                MERGED_CONFIG_PROTO)
@@ -191,6 +169,5 @@
                               MERGED_TRACE_PROTO)
   return 0 if config_result and trace_result else 1
 
-
 if __name__ == '__main__':
   sys.exit(main())
diff --git a/tools/gen_merged_sql_metrics.py b/tools/gen_merged_sql_metrics.py
index 07c57e1..071423c 100755
--- a/tools/gen_merged_sql_metrics.py
+++ b/tools/gen_merged_sql_metrics.py
@@ -54,11 +54,22 @@
 
 FILE_TO_SQL_STRUCT = '''
 struct FileToSql {
-  const char* path;
+  const char* filename;
   const char* sql;
 };
 '''
 
+FIND_SQL_FN = '''
+inline const char* GetBundledMetric(const char* filename) {
+  for (const auto& filename_to_sql : sql_metrics::kFileToSql) {
+    if (strcmp(filename_to_sql.filename, filename) == 0) {
+      return filename_to_sql.sql;
+    }
+  }
+  return nullptr;
+}
+'''
+
 NAMESPACE_END = '''
 }  // namespace sql_metrics
 }  // namespace metrics
@@ -66,56 +77,47 @@
 }  // namsepace perfetto
 '''
 
-
 def filename_to_variable(filename):
   return "k" + "".join([x.capitalize() for x in filename.split("_")])
 
-
 def main():
   parser = argparse.ArgumentParser()
   parser.add_argument('--cpp_out', required=True)
   parser.add_argument('sql_files', nargs='*')
   args = parser.parse_args()
 
-  root_path = os.path.commonprefix([os.path.abspath(x) for x in args.sql_files])
-
   # Extract the SQL output from each file.
-  sql_outputs = {}
+  escaped_sql_outputs = {}
   for file_name in args.sql_files:
     with open(file_name, 'r') as f:
-      relpath = os.path.relpath(file_name, root_path)
-      sql_outputs[relpath] = "".join(
-          x for x in f.readlines() if not x.startswith('--'))
+      basename = os.path.basename(file_name)
+
+      # Escape any quote characters.
+      escaped_sql_outputs[basename] = "".join(f.readlines())
 
   with open(args.cpp_out, 'w+') as output:
     output.write(REPLACEMENT_HEADER)
     output.write(NAMESPACE_BEGIN)
 
     # Create the C++ variable for each SQL file.
-    for path, sql in sql_outputs.items():
-      name = os.path.basename(path)
+    for name, sql in escaped_sql_outputs.items():
       variable = filename_to_variable(os.path.splitext(name)[0])
-      output.write(
-          '\nconst char {}[] = R"gendelimiter(\n{})gendelimiter";\n'.format(
-              variable, sql))
+      output.write('\nconst char {}[] = R"gendelimiter(\n{})gendelimiter";\n'
+        .format(variable, sql))
 
     output.write(FILE_TO_SQL_STRUCT)
 
     # Create mapping of filename to variable name for each variable.
     output.write("\nconst FileToSql kFileToSql[] = {")
-    for path in sql_outputs.keys():
-      name = os.path.basename(path)
+    for name in escaped_sql_outputs.keys():
       variable = filename_to_variable(os.path.splitext(name)[0])
-
-      # This is for Windows which has \ as a path separator.
-      path = path.replace("\\", "\\\\")
-      output.write('\n  {{"{}", {}}},\n'.format(path, variable))
+      output.write('\n  {{"{}", {}}},\n'.format(name, variable))
     output.write("};\n")
 
+    output.write(FIND_SQL_FN)
     output.write(NAMESPACE_END)
 
   return 0
 
-
 if __name__ == '__main__':
   sys.exit(main())
diff --git a/tools/gen_tracing_cpp_headers_from_protos b/tools/gen_tracing_cpp_headers_from_protos
new file mode 100755
index 0000000..d70bb3c
--- /dev/null
+++ b/tools/gen_tracing_cpp_headers_from_protos
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+# Copyright (C) 2017 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.
+
+import os
+import subprocess
+import sys
+
+PROTOS = (
+  'perfetto/common/android_log_constants.proto',
+  'perfetto/common/commit_data_request.proto',
+  'perfetto/common/data_source_descriptor.proto',
+  'perfetto/common/observable_events.proto',
+  'perfetto/common/sys_stats_counters.proto',
+  'perfetto/common/trace_stats.proto',
+  'perfetto/common/tracing_service_state.proto',
+  'perfetto/config/android/android_log_config.proto',
+  'perfetto/config/chrome/chrome_config.proto',
+  'perfetto/config/data_source_config.proto',
+  'perfetto/config/ftrace/ftrace_config.proto',
+  'perfetto/config/inode_file/inode_file_config.proto',
+  'perfetto/config/power/android_power_config.proto',
+  'perfetto/config/process_stats/process_stats_config.proto',
+  'perfetto/config/profiling/heapprofd_config.proto',
+  'perfetto/config/sys_stats/sys_stats_config.proto',
+  'perfetto/config/test_config.proto',
+  'perfetto/config/trace_config.proto',
+  'perfetto/config/android/packages_list_config.proto',
+)
+
+HEADER_PATH = 'include/perfetto/tracing/core'
+CPP_PATH = 'src/tracing/core'
+INCLUDE_PATH = 'perfetto/tracing/core'
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+def run(cmd):
+  print('\nRunning ' + ' '.join(cmd))
+  subprocess.check_call(cmd)
+
+
+def main():
+  if not os.path.exists('.gn'):
+    print('This script must be executed from the perfetto root directory')
+    return 1
+  if len(sys.argv) < 2:
+    print('Usage: %s out/xxx' % sys.argv[0])
+    return 1
+  out_dir = sys.argv[1]
+  arch = 'mac' if sys.platform == 'darwin' else 'linux64'
+  clang_format_path = os.path.join(ROOT_DIR, 'buildtools', arch, 'clang-format')
+  clang_format = [clang_format_path, '-i', '--sort-includes']
+  tool = os.path.join(out_dir, 'proto_to_cpp')
+  if not os.path.exists(tool):
+    print('Could not find %s, run ninja -C %s proto_to_cpp' % (tool, out_dir))
+  for proto in PROTOS:
+    run([tool, proto] + [HEADER_PATH, CPP_PATH, INCLUDE_PATH])
+    fname = os.path.basename(proto).replace('.proto', '')
+    run(clang_format + [os.path.join(HEADER_PATH, fname + '.h')])
+    run(clang_format + [os.path.join(CPP_PATH, fname + '.cc')])
+
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/tools/gn_utils.py b/tools/gn_utils.py
deleted file mode 100644
index 53894d2..0000000
--- a/tools/gn_utils.py
+++ /dev/null
@@ -1,387 +0,0 @@
-# Copyright (C) 2019 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.
-
-# A collection of utilities for extracting build rule information from GN
-# projects.
-
-from __future__ import print_function
-import errno
-import filecmp
-import json
-import os
-import re
-import shutil
-import subprocess
-import sys
-from compat import iteritems
-
-BUILDFLAGS_TARGET = '//gn:gen_buildflags'
-TARGET_TOOLCHAIN = '//gn/standalone/toolchain:gcc_like_host'
-HOST_TOOLCHAIN = '//gn/standalone/toolchain:gcc_like_host'
-LINKER_UNIT_TYPES = ('executable', 'shared_library', 'static_library')
-
-
-def _check_command_output(cmd, cwd):
-  try:
-    output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, cwd=cwd)
-  except subprocess.CalledProcessError as e:
-    print(
-        'Command "{}" failed in {}:'.format(' '.join(cmd), cwd),
-        file=sys.stderr)
-    print(e.output.decode(), file=sys.stderr)
-    sys.exit(1)
-  else:
-    return output.decode()
-
-
-def repo_root():
-  """Returns an absolute path to the repository root."""
-  return os.path.join(
-      os.path.realpath(os.path.dirname(__file__)), os.path.pardir)
-
-
-def _tool_path(name):
-  return os.path.join(repo_root(), 'tools', name)
-
-
-def prepare_out_directory(gn_args, name, root=repo_root()):
-  """Creates the JSON build description by running GN.
-
-    Returns (path, desc) where |path| is the location of the output directory
-    and |desc| is the JSON build description.
-    """
-  out = os.path.join(root, 'out', name)
-  try:
-    os.makedirs(out)
-  except OSError as e:
-    if e.errno != errno.EEXIST:
-      raise
-  _check_command_output([_tool_path('gn'), 'gen', out,
-                         '--args=%s' % gn_args],
-                        cwd=repo_root())
-  return out
-
-
-def load_build_description(out):
-  """Creates the JSON build description by running GN."""
-  desc = _check_command_output([
-      _tool_path('gn'), 'desc', out, '--format=json', '--all-toolchains', '//*'
-  ],
-                               cwd=repo_root())
-  return json.loads(desc)
-
-
-def create_build_description(gn_args, root=repo_root()):
-  """Prepares a GN out directory and loads the build description from it.
-
-    The temporary out directory is automatically deleted.
-    """
-  out = prepare_out_directory(gn_args, 'tmp.gn_utils', root=root)
-  try:
-    return load_build_description(out)
-  finally:
-    shutil.rmtree(out)
-
-
-def build_targets(out, targets, quiet=False):
-  """Runs ninja to build a list of GN targets in the given out directory.
-
-    Compiling these targets is required so that we can include any generated
-    source files in the amalgamated result.
-    """
-  targets = [t.replace('//', '') for t in targets]
-  with open(os.devnull, 'w') as devnull:
-    stdout = devnull if quiet else None
-    subprocess.check_call(
-        [_tool_path('ninja')] + targets, cwd=out, stdout=stdout)
-
-
-def compute_source_dependencies(out):
-  """For each source file, computes a set of headers it depends on."""
-  ninja_deps = _check_command_output([_tool_path('ninja'), '-t', 'deps'],
-                                     cwd=out)
-  deps = {}
-  current_source = None
-  for line in ninja_deps.split('\n'):
-    filename = os.path.relpath(os.path.join(out, line.strip()), repo_root())
-    if not line or line[0] != ' ':
-      current_source = None
-      continue
-    elif not current_source:
-      # We're assuming the source file is always listed before the
-      # headers.
-      assert os.path.splitext(line)[1] in ['.c', '.cc', '.cpp', '.S']
-      current_source = filename
-      deps[current_source] = []
-    else:
-      assert current_source
-      deps[current_source].append(filename)
-  return deps
-
-
-def label_to_path(label):
-  """Turn a GN output label (e.g., //some_dir/file.cc) into a path."""
-  assert label.startswith('//')
-  return label[2:]
-
-
-def label_without_toolchain(label):
-  """Strips the toolchain from a GN label.
-
-    Return a GN label (e.g //buildtools:protobuf(//gn/standalone/toolchain:
-    gcc_like_host) without the parenthesised toolchain part.
-    """
-  return label.split('(')[0]
-
-
-def label_to_target_name_with_path(label):
-  """
-  Turn a GN label into a target name involving the full path.
-  e.g., //src/perfetto:tests -> src_perfetto_tests
-  """
-  name = re.sub(r'^//:?', '', label)
-  name = re.sub(r'[^a-zA-Z0-9_]', '_', name)
-  return name
-
-
-def gen_buildflags(gn_args, target_file):
-  """Generates the perfetto_build_flags.h for the given config.
-
-    target_file: the path, relative to the repo root, where the generated
-        buildflag header will be copied into.
-    """
-  tmp_out = prepare_out_directory(gn_args, 'tmp.gen_buildflags')
-  build_targets(tmp_out, [BUILDFLAGS_TARGET], quiet=True)
-  src = os.path.join(tmp_out, 'gen', 'build_config', 'perfetto_build_flags.h')
-  shutil.copy(src, os.path.join(repo_root(), target_file))
-  shutil.rmtree(tmp_out)
-
-
-def check_or_commit_generated_files(tmp_files, check):
-  """Checks that gen files are unchanged or renames them to the final location
-
-    Takes in input a list of 'xxx.swp' files that have been written.
-    If check == False, it renames xxx.swp -> xxx.
-    If check == True, it just checks that the contents of 'xxx.swp' == 'xxx'.
-    Returns 0 if no diff was detected, 1 otherwise (to be used as exit code).
-    """
-  res = 0
-  for tmp_file in tmp_files:
-    assert (tmp_file.endswith('.swp'))
-    target_file = os.path.relpath(tmp_file[:-4])
-    if check:
-      if not filecmp.cmp(tmp_file, target_file):
-        sys.stderr.write('%s needs to be regenerated\n' % target_file)
-        res = 1
-      os.unlink(tmp_file)
-    else:
-      os.rename(tmp_file, target_file)
-  return res
-
-
-class GnParser(object):
-  """A parser with some cleverness for GN json desc files
-
-    The main goals of this parser are:
-    1) Deal with the fact that other build systems don't have an equivalent
-       notion to GN's source_set. Conversely to Bazel's and Soong's filegroups,
-       GN source_sets expect that dependencies, cflags and other source_set
-       properties propagate up to the linker unit (static_library, executable or
-       shared_library). This parser simulates the same behavior: when a
-       source_set is encountered, some of its variables (cflags and such) are
-       copied up to the dependent targets. This is to allow gen_xxx to create
-       one filegroup for each source_set and then squash all the other flags
-       onto the linker unit.
-    2) Detect and special-case protobuf targets, figuring out the protoc-plugin
-       being used.
-    """
-
-  class Target(object):
-    """Reperesents A GN target.
-
-        Maked properties are propagated up the dependency chain when a
-        source_set dependency is encountered.
-        """
-
-    def __init__(self, name, type):
-      self.name = name  # e.g. //src/ipc:ipc
-
-      VALID_TYPES = ('static_library', 'shared_library', 'executable', 'group',
-                     'action', 'source_set', 'proto_library')
-      assert (type in VALID_TYPES)
-      self.type = type
-      self.testonly = False
-      self.toolchain = None
-
-      # Only set when type == proto_library.
-      # This is typically: 'proto', 'protozero', 'ipc'.
-      self.proto_plugin = None
-
-      self.sources = set()
-
-      # These are valid only for type == 'action'
-      self.inputs = set()
-      self.outputs = set()
-      self.script = None
-      self.args = []
-
-      # These variables are propagated up when encountering a dependency
-      # on a source_set target.
-      self.cflags = set()
-      self.defines = set()
-      self.deps = set()
-      self.libs = set()
-      self.include_dirs = set()
-      self.ldflags = set()
-      self.source_set_deps = set()  # Transitive set of source_set deps.
-      self.proto_deps = set()  # Transitive set of protobuf deps.
-
-      # Deps on //gn:xxx have this flag set to True. These dependencies
-      # are special because they pull third_party code from buildtools/.
-      # We don't want to keep recursing into //buildtools in generators,
-      # this flag is used to stop the recursion and create an empty
-      # placeholder target once we hit //gn:protoc or similar.
-      self.is_third_party_dep_ = False
-
-    def __lt__(self, other):
-      if isinstance(other, self.__class__):
-        return self.name < other.name
-      raise TypeError(
-          '\'<\' not supported between instances of \'%s\' and \'%s\'' %
-          (type(self).__name__, type(other).__name__))
-
-    def __repr__(self):
-      return json.dumps({
-          k: (list(sorted(v)) if isinstance(v, set) else v)
-          for (k, v) in iteritems(self.__dict__)
-      },
-                        indent=4,
-                        sort_keys=True)
-
-    def update(self, other):
-      for key in ('cflags', 'defines', 'deps', 'include_dirs', 'ldflags',
-                  'source_set_deps', 'proto_deps', 'libs'):
-        self.__dict__[key].update(other.__dict__.get(key, []))
-
-  def __init__(self, gn_desc):
-    self.gn_desc_ = gn_desc
-    self.all_targets = {}
-    self.linker_units = {}  # Executables, shared or static libraries.
-    self.source_sets = {}
-    self.actions = {}
-    self.proto_libs = {}
-
-  def get_target(self, gn_target_name):
-    """Returns a Target object from the fully qualified GN target name.
-
-        It bubbles up variables from source_set dependencies as described in the
-        class-level comments.
-        """
-    target = self.all_targets.get(gn_target_name)
-    if target is not None:
-      return target  # Taraget already processed.
-
-    desc = self.gn_desc_[gn_target_name]
-    target = GnParser.Target(gn_target_name, desc['type'])
-    target.testonly = desc.get('testonly', False)
-    target.toolchain = desc.get('toolchain', None)
-    self.all_targets[gn_target_name] = target
-
-    # We should never have GN targets directly depend on buidtools. They
-    # should hop via //gn:xxx, so we can give generators an opportunity to
-    # override them.
-    assert (not gn_target_name.startswith('//buildtools'))
-
-    # Don't descend further into third_party targets. Genrators are supposed
-    # to either ignore them or route to other externally-provided targets.
-    if gn_target_name.startswith('//gn'):
-      target.is_third_party_dep_ = True
-      return target
-
-    proto_target_type, proto_desc = self.get_proto_target_type_(target)
-    if proto_target_type is not None:
-      self.proto_libs[target.name] = target
-      target.type = 'proto_library'
-      target.proto_plugin = proto_target_type
-      target.sources.update(proto_desc.get('sources', []))
-      assert (all(x.endswith('.proto') for x in target.sources))
-    elif target.type == 'source_set':
-      self.source_sets[gn_target_name] = target
-      target.sources.update(desc.get('sources', []))
-    elif target.type in LINKER_UNIT_TYPES:
-      self.linker_units[gn_target_name] = target
-      target.sources.update(desc.get('sources', []))
-    elif target.type == 'action':
-      self.actions[gn_target_name] = target
-      target.inputs.update(desc['inputs'])
-      outs = [re.sub('^//out/.+?/gen/', '', x) for x in desc['outputs']]
-      target.outputs.update(outs)
-      target.script = desc['script']
-      # Args are typically relative to the root build dir (../../xxx)
-      # because root build dir is typically out/xxx/).
-      target.args = [re.sub('^../../', '//', x) for x in desc['args']]
-
-    target.cflags.update(desc.get('cflags', []) + desc.get('cflags_cc', []))
-    target.libs.update(desc.get('libs', []))
-    target.ldflags.update(desc.get('ldflags', []))
-    target.defines.update(desc.get('defines', []))
-    target.include_dirs.update(desc.get('include_dirs', []))
-
-    # Recurse in dependencies.
-    for dep_name in desc.get('deps', []):
-      dep = self.get_target(dep_name)
-      if dep.is_third_party_dep_:
-        target.deps.add(dep_name)
-      elif dep.type == 'proto_library':
-        target.proto_deps.add(dep_name)
-        target.proto_deps.update(dep.proto_deps)  # Bubble up deps.
-      elif dep.type == 'source_set':
-        target.source_set_deps.add(dep_name)
-        target.update(dep)  # Bubble up source set's cflags/ldflags etc.
-      elif dep.type == 'group':
-        target.update(dep)  # Bubble up groups's cflags/ldflags etc.
-      elif dep.type == 'action':
-        if proto_target_type is None:
-          target.deps.add(dep_name)
-      elif dep.type in LINKER_UNIT_TYPES:
-        target.deps.add(dep_name)
-
-    return target
-
-  def get_proto_target_type_(self, target):
-    """ Checks if the target is a proto library and return the plugin.
-
-        Returns:
-            (None, None): if the target is not a proto library.
-            (plugin, gen_desc) where |plugin| is 'proto' in the default (lite)
-            case or 'protozero' or 'ipc'; |gen_desc| is the GN json descriptor
-            of the _gen target (the one with .proto sources).
-        """
-    parts = target.name.split('(', 1)
-    name = parts[0]
-    toolchain = '(' + parts[1] if len(parts) > 1 else ''
-    gen_desc = self.gn_desc_.get('%s_gen%s' % (name, toolchain))
-    if gen_desc is None or gen_desc['type'] != 'action':
-      return None, None
-    args = gen_desc.get('args', [])
-    if '/protoc' not in args[0]:
-      return None, None
-    plugin = 'proto'
-    for arg in (arg for arg in args if arg.startswith('--plugin=')):
-      # |arg| at this point looks like:
-      #  --plugin=protoc-gen-plugin=gcc_like_host/protozero_plugin
-      # or
-      #  --plugin=protoc-gen-plugin=protozero_plugin
-      plugin = arg.split('=')[-1].split('/')[-1].replace('_plugin', '')
-    return plugin, gen_desc
diff --git a/tools/heap_profile b/tools/heap_profile
index 8f57b59..92579e9 100755
--- a/tools/heap_profile
+++ b/tools/heap_profile
@@ -22,7 +22,6 @@
 import atexit
 import hashlib
 import os
-import shutil
 import signal
 import subprocess
 import sys
@@ -31,16 +30,17 @@
 import urllib
 
 TRACE_TO_TEXT_SHAS = {
-    'linux': '74cb40d9413d7ad756e327e09e46a8adde90db92',
-    'mac': '47045bc6abd4f9113969211f37fdd2259b0c1cc3',
+  'linux': 'a8171d85c5964ccafe457142dbb7df68ca8da543',
+  'mac': '268c2fc096039566979d16c1a7a99eabef0d9682',
 }
 TRACE_TO_TEXT_PATH = tempfile.gettempdir()
-TRACE_TO_TEXT_BASE_URL = ('https://storage.googleapis.com/perfetto/')
+TRACE_TO_TEXT_BASE_URL = (
+    'https://storage.googleapis.com/perfetto/')
 
 NULL = open(os.devnull)
 NOOUT = {
-    'stdout': NULL,
-    'stderr': NULL,
+  'stdout': NULL,
+  'stderr': NULL,
 }
 
 
@@ -71,20 +71,19 @@
   return local_file
 
 
-PACKAGES_LIST_CFG = '''data_sources {
-  config {
-    name: "android.packages_list"
-  }
-}
-'''
-
 CFG_IDENT = '      '
-CFG = '''buffers {{
+CFG='''buffers {{
   size_kb: 32768
 }}
 
 data_sources {{
   config {{
+    name: "android.packages_list"
+  }}
+}}
+
+data_sources {{
+  config {{
     name: "android.heapprofd"
     heapprofd_config {{
 
@@ -97,7 +96,6 @@
 }}
 
 duration_ms: {duration}
-write_into_file: true
 flush_timeout_ms: 30000
 '''
 
@@ -108,12 +106,10 @@
       }}
 """
 
-PERFETTO_CMD = ('CFG=\'{cfg}\'; echo ${{CFG}} | '
-                'perfetto --txt -c - -o '
-                '/data/misc/perfetto-traces/profile-{user} -d')
+PERFETTO_CMD=('CFG=\'{cfg}\'; echo ${{CFG}} | '
+              'perfetto --txt -c - -o '
+              '/data/misc/perfetto-traces/profile-{user} -d')
 IS_INTERRUPTED = False
-
-
 def sigint_handler(sig, frame):
   global IS_INTERRUPTED
   IS_INTERRUPTED = True
@@ -121,108 +117,39 @@
 
 def main(argv):
   parser = argparse.ArgumentParser()
-  parser.add_argument(
-      "-i",
-      "--interval",
-      help="Sampling interval. "
-      "Default 4096 (4KiB)",
-      type=int,
-      default=4096)
-  parser.add_argument(
-      "-d",
-      "--duration",
-      help="Duration of profile (ms). "
-      "Default 7 days.",
-      type=int,
-      default=604800000)
-  parser.add_argument(
-      "--no-start", help="Do not start heapprofd.", action='store_true')
-  parser.add_argument(
-      "-p",
-      "--pid",
-      help="Comma-separated list of PIDs to "
-      "profile.",
-      metavar="PIDS")
-  parser.add_argument(
-      "-n",
-      "--name",
-      help="Comma-separated list of process "
-      "names to profile.",
-      metavar="NAMES")
-  parser.add_argument(
-      "-c",
-      "--continuous-dump",
-      help="Dump interval in ms. 0 to disable continuous dump.",
-      type=int,
-      default=0)
-  parser.add_argument(
-      "--disable-selinux",
-      action="store_true",
-      help="Disable SELinux enforcement for duration of "
-      "profile.")
-  parser.add_argument(
-      "--no-versions",
-      action="store_true",
-      help="Do not get version information about APKs.")
-  parser.add_argument(
-      "--no-running",
-      action="store_true",
-      help="Do not target already running processes.")
-  parser.add_argument(
-      "--no-startup",
-      action="store_true",
-      help="Do not target processes that start during "
-      "the profile.")
-  parser.add_argument(
-      "--shmem-size",
-      help="Size of buffer between client and "
-      "heapprofd. Default 8MiB. Needs to be a power of two "
-      "multiple of 4096, at least 8192.",
-      type=int,
-      default=8 * 1048576)
-  parser.add_argument(
-      "--block-client",
-      help="When buffer is full, block the "
-      "client to wait for buffer space. Use with caution as "
-      "this can significantly slow down the client. "
-      "This is the default",
-      action="store_true")
-  parser.add_argument(
-      "--no-block-client",
-      help="When buffer is full, stop the "
-      "profile early.",
-      action="store_true")
-  parser.add_argument(
-      "--idle-allocations",
-      help="Keep track of how many "
-      "bytes were unused since the last dump, per "
-      "callstack",
-      action="store_true")
-  parser.add_argument(
-      "--dump-at-max",
-      help="Dump the maximum memory usage"
-      "rather than at the time of the dump.",
-      action="store_true")
-  parser.add_argument(
-      "--simpleperf",
-      action="store_true",
-      help="Get simpleperf profile of heapprofd. This is "
-      "only for heapprofd development.")
-  parser.add_argument(
-      "--trace-to-text-binary",
-      help="Path to local trace to text. For debugging.")
-  parser.add_argument(
-      "--print-config",
-      action="store_true",
-      help="Print config instead of running. For debugging.")
+  parser.add_argument("-i", "--interval", help="Sampling interval. "
+                      "Default 4096 (4KiB)", type=int, default=4096)
+  parser.add_argument("-d", "--duration", help="Duration of profile (ms). "
+                      "Default 7 days.", type=int, default=604800000)
+  parser.add_argument("--no-start", help="Do not start heapprofd.",
+                      action='store_true')
+  parser.add_argument("-p", "--pid", help="Comma-separated list of PIDs to "
+                      "profile.", metavar="PIDS")
+  parser.add_argument("-n", "--name", help="Comma-separated list of process "
+                      "names to profile.", metavar="NAMES")
+  parser.add_argument("-c", "--continuous-dump",
+                      help="Dump interval in ms. 0 to disable continuous dump.",
+                      type=int, default=0)
+  parser.add_argument("--disable-selinux", action="store_true",
+                      help="Disable SELinux enforcement for duration of "
+                      "profile.")
+  parser.add_argument("--shmem-size", help="Size of buffer between client and "
+                      "heapprofd. Default 8MiB. Needs to be a power of two "
+                      "multiple of 4096, at least 8192.", type=int,
+                      default=8 * 1048576)
+  parser.add_argument("--block-client", help="When buffer is full, block the "
+                      "client to wait for buffer space. Use with caution as "
+                      "this can significantly slow down the client.",
+                      action="store_true")
+  parser.add_argument("--simpleperf", action="store_true",
+                      help="Get simpleperf profile of heapprofd. This is "
+                      "only for heapprofd development.")
+  parser.add_argument("--trace-to-text-binary",
+                      help="Path to local trace to text. For debugging.")
 
   args = parser.parse_args()
 
   fail = False
-  if args.block_client and args.no_block_client:
-    print(
-        "FATAL: Both block-client and no-block-client given.", file=sys.stderr)
-    fail = True
   if args.pid is None and args.name is None:
     print("FATAL: Neither PID nor NAME given.", file=sys.stderr)
     fail = True
@@ -243,16 +170,8 @@
     fail = True
 
   target_cfg = ""
-  if not args.no_block_client:
+  if args.block_client:
     target_cfg += "block_client: true\n"
-  if args.idle_allocations:
-    target_cfg += "idle_allocations: true\n"
-  if args.no_startup:
-    target_cfg += "no_startup: true\n"
-  if args.no_running:
-    target_cfg += "no_running: true\n"
-  if args.dump_at_max:
-    target_cfg += "dump_at_max: true\n"
   if args.pid:
     for pid in args.pid.split(','):
       try:
@@ -286,23 +205,14 @@
   if args.continuous_dump:
     continuous_dump_cfg = CONTINUOUS_DUMP.format(
         dump_interval=args.continuous_dump)
-  cfg = CFG.format(
-      interval=args.interval,
-      duration=args.duration,
-      target_cfg=target_cfg,
-      continuous_dump_cfg=continuous_dump_cfg,
-      shmem_size=args.shmem_size)
-  if not args.no_versions:
-    cfg += PACKAGES_LIST_CFG
-
-  if args.print_config:
-    print(cfg)
-    return 0
+  cfg = CFG.format(interval=args.interval,
+                   duration=args.duration, target_cfg=target_cfg,
+                   continuous_dump_cfg=continuous_dump_cfg,
+                   shmem_size=args.shmem_size)
 
   if args.disable_selinux:
     enforcing = subprocess.check_output(['adb', 'shell', 'getenforce'])
-    atexit.register(
-        subprocess.check_call,
+    atexit.register(subprocess.check_call,
         ['adb', 'shell', 'su root setenforce %s' % enforcing])
     subprocess.check_call(['adb', 'shell', 'su root setenforce 0'])
 
@@ -313,25 +223,25 @@
       subprocess.check_call(
           ['adb', 'shell', 'setprop persist.heapprofd.enable 1'])
       atexit.register(subprocess.check_call,
-                      ['adb', 'shell', 'setprop persist.heapprofd.enable 0'])
+          ['adb', 'shell', 'setprop persist.heapprofd.enable 0'])
 
   user = subprocess.check_output(['adb', 'shell', 'whoami']).strip()
 
   if args.simpleperf:
-    subprocess.check_call([
-        'adb', 'shell', 'mkdir -p /data/local/tmp/heapprofd_profile && '
-        'cd /data/local/tmp/heapprofd_profile &&'
-        '(nohup simpleperf record -g -p $(pidof heapprofd) 2>&1 &) '
-        '> /dev/null'
-    ])
+    subprocess.check_call(
+        ['adb', 'shell',
+         'mkdir -p /data/local/tmp/heapprofd_profile && '
+         'cd /data/local/tmp/heapprofd_profile &&'
+         '(nohup simpleperf record -g -p $(pgrep heapprofd) 2>&1 &) '
+         '> /dev/null'])
 
   perfetto_pid = subprocess.check_output(
-      ['adb', 'exec-out',
-       PERFETTO_CMD.format(cfg=cfg, user=user)]).strip()
+      ['adb', 'exec-out', PERFETTO_CMD.format(cfg=cfg, user=user)]).strip()
   try:
     int(perfetto_pid.strip())
   except ValueError:
-    print("Failed to invoke perfetto: {}".format(perfetto_pid), file=sys.stderr)
+    print("Failed to invoke perfetto: {}".format(perfetto_pid),
+          file=sys.stderr)
     return 1
 
   old_handler = signal.signal(signal.SIGINT, sigint_handler)
@@ -341,7 +251,8 @@
   device_connected = True
   while not device_connected or (exists and not IS_INTERRUPTED):
     exists = subprocess.call(
-        ['adb', 'shell', '[ -d /proc/{} ]'.format(perfetto_pid)], **NOOUT) == 0
+        ['adb', 'shell', '[ -d /proc/{} ]'.format(perfetto_pid)],
+        **NOOUT) == 0
     device_connected = subprocess.call(['adb', 'shell', 'true'], **NOOUT) == 0
     time.sleep(1)
   signal.signal(signal.SIGINT, old_handler)
@@ -352,10 +263,11 @@
     subprocess.check_call(['adb', 'shell', 'killall', '-INT', 'simpleperf'])
     print("Waiting for simpleperf to exit.")
     while subprocess.call(
-        ['adb', 'shell', '[ -f /proc/$(pidof simpleperf)/exe ]'], **NOOUT) == 0:
+        ['adb', 'shell', '[ -f /proc/$(pgrep simpleperf)/exe ]'],
+        **NOOUT) == 0:
       time.sleep(1)
-    subprocess.check_call(
-        ['adb', 'pull', '/data/local/tmp/heapprofd_profile', '/tmp'])
+    subprocess.check_call(['adb', 'pull', '/data/local/tmp/heapprofd_profile',
+                           '/tmp'])
     print("Pulled simpleperf profile to /tmp/heapprofd_profile")
 
   # Wait for perfetto cmd to return.
@@ -364,11 +276,9 @@
         ['adb', 'shell', '[ -d /proc/{} ]'.format(perfetto_pid)]) == 0
     time.sleep(1)
 
-  subprocess.check_call([
-      'adb', 'pull', '/data/misc/perfetto-traces/profile-{}'.format(user),
-      '/tmp/profile'
-  ],
-                        stdout=NULL)
+  subprocess.check_call(['adb', 'pull',
+                         '/data/misc/perfetto-traces/profile-{}'.format(user),
+                         '/tmp/profile'], stdout=NULL)
   trace_to_text_output = subprocess.check_output(
       [trace_to_text_binary, 'profile', '/tmp/profile'])
   profile_path = None
@@ -382,22 +292,16 @@
   profile_files = os.listdir(profile_path)
   if not profile_files:
     print("No profiles generated", file=sys.stderr)
-    print(
-        "If this is unexpected, check "
-        "https://docs.perfetto.dev/#/heapprofd?id=troubleshooting.",
-        file=sys.stderr)
     return 1
 
-  subprocess.check_call(
-      ['gzip'] +
-      [os.path.join(profile_path, x) for x in os.listdir(profile_path)])
+  subprocess.check_call(['gzip'] + [os.path.join(profile_path, x) for x in
+                                    os.listdir(profile_path)])
 
-  symlink_path = os.path.join(
-      os.path.dirname(profile_path), "heap_profile-latest")
+  symlink_path = os.path.join(os.path.dirname(profile_path),
+                                        "heap_profile-latest")
   if os.path.lexists(symlink_path):
     os.unlink(symlink_path)
   os.symlink(profile_path, symlink_path)
-  shutil.copyfile('/tmp/profile', os.path.join(profile_path, 'raw-trace'))
 
   print("Wrote profiles to {} (symlink {})".format(profile_path, symlink_path))
   print("These can be viewed using pprof. Googlers: head to pprof/ and "
diff --git a/tools/idle_alloc.cc b/tools/idle_alloc.cc
deleted file mode 100644
index 1a1dd5a..0000000
--- a/tools/idle_alloc.cc
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2019 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 <memory>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-namespace {
-
-constexpr auto kIdleSize = 10000 * 4096;
-constexpr auto kNoIdleSize = 1000 * 4096;
-
-static bool interrupted = false;
-
-volatile unsigned char* __attribute__((noinline)) AllocIdle(size_t bytes);
-volatile unsigned char* __attribute__((noinline)) AllocIdle(size_t bytes) {
-  // This volatile is needed to prevent the compiler from trying to be
-  // helpful and compiling a "useless" malloc + free into a noop.
-  volatile unsigned char* x = static_cast<unsigned char*>(malloc(bytes));
-  if (x) {
-    x[1] = 'x';
-  }
-  return x;
-}
-
-volatile unsigned char* __attribute__((noinline)) AllocNoIdle(size_t bytes);
-volatile unsigned char* __attribute__((noinline)) AllocNoIdle(size_t bytes) {
-  // This volatile is needed to prevent the compiler from trying to be
-  // helpful and compiling a "useless" malloc + free into a noop.
-  volatile unsigned char* x = static_cast<unsigned char*>(malloc(bytes));
-  if (x) {
-    x[0] = 'x';
-  }
-  return x;
-}
-
-class MemoryToucher {
- public:
-  virtual void Touch(volatile unsigned char* nonidle) = 0;
-  virtual ~MemoryToucher() = default;
-};
-
-class ReadDevZeroChunks : public MemoryToucher {
- public:
-  ReadDevZeroChunks(size_t chunk_size)
-      : chunk_size_(chunk_size), fd_(open("/dev/zero", O_RDONLY)) {
-    if (fd_ == -1) {
-      fprintf(stderr, "Failed to open: %s", strerror(errno));
-      abort();
-    }
-  }
-
-  ~ReadDevZeroChunks() override = default;
-
-  void Touch(volatile unsigned char* nonidle) override {
-    size_t total_rd = 0;
-    while (total_rd < kNoIdleSize) {
-      size_t chunk = chunk_size_;
-      if (chunk > kNoIdleSize - total_rd)
-        chunk = kNoIdleSize - total_rd;
-
-      ssize_t rd =
-          read(fd_, const_cast<unsigned char*>(nonidle) + total_rd, chunk);
-      if (rd == -1) {
-        fprintf(stderr, "Failed to write: %s.", strerror(errno));
-        abort();
-      }
-      total_rd += static_cast<size_t>(rd);
-    }
-  }
-
- private:
-  size_t chunk_size_;
-  int fd_;
-};
-
-class ReadDevZeroChunksAndSleep : public ReadDevZeroChunks {
- public:
-  ReadDevZeroChunksAndSleep(size_t chunk_size)
-      : ReadDevZeroChunks(chunk_size) {}
-  void Touch(volatile unsigned char* nonidle) override {
-    ReadDevZeroChunks::Touch(nonidle);
-    sleep(1);
-  }
-};
-
-class SumUp : public MemoryToucher {
- public:
-  SumUp()
-      : sum_(const_cast<volatile uint64_t*>(
-            static_cast<uint64_t*>(malloc(sizeof(uint64_t))))) {}
-  ~SumUp() override = default;
-
-  void Touch(volatile unsigned char* nonidle) override {
-    for (size_t i = 0; i < kNoIdleSize; ++i)
-      *sum_ += nonidle[i];
-  }
-
- private:
-  volatile uint64_t* sum_;
-};
-
-class ReadDevZeroChunksAndSum : public ReadDevZeroChunks {
- public:
-  ReadDevZeroChunksAndSum(size_t chunk_size) : ReadDevZeroChunks(chunk_size) {}
-  void Touch(volatile unsigned char* nonidle) override {
-    ReadDevZeroChunks::Touch(nonidle);
-    sum_up_.Touch(nonidle);
-  }
-
- private:
-  SumUp sum_up_;
-};
-
-class AssignValues : public MemoryToucher {
- public:
-  ~AssignValues() override = default;
-
-  void Touch(volatile unsigned char* nonidle) override {
-    for (size_t i = 0; i < kNoIdleSize; ++i)
-      nonidle[i] = static_cast<unsigned char>(i % 256);
-  }
-};
-
-}  // namespace
-
-int main(int argc, char** argv) {
-  volatile auto* idle = AllocIdle(kIdleSize);
-  volatile auto* nonidle = AllocNoIdle(kNoIdleSize);
-
-  printf("Own PID: %" PRIdMAX "\n", static_cast<intmax_t>(getpid()));
-  printf("Idle: %p\n", static_cast<void*>(const_cast<unsigned char*>(idle)));
-  printf("Nonidle: %p\n",
-         static_cast<void*>(const_cast<unsigned char*>(nonidle)));
-
-  for (size_t i = 0; i < kIdleSize; ++i)
-    idle[i] = static_cast<unsigned char>(i % 256);
-  for (size_t i = 0; i < kNoIdleSize; ++i)
-    nonidle[i] = static_cast<unsigned char>(i % 256);
-
-  printf("Allocated everything.\n");
-
-  struct sigaction action = {};
-  action.sa_handler = [](int) { interrupted = true; };
-  if (sigaction(SIGUSR1, &action, nullptr) != 0) {
-    fprintf(stderr, "Failed to register signal handler.\n");
-    abort();
-  }
-
-  if (argc < 2) {
-    fprintf(stderr,
-            "Specifiy one of AssignValues / SumUp / ReadDevZeroChunks\n");
-    abort();
-  }
-
-  std::unique_ptr<MemoryToucher> toucher;
-  if (strcmp(argv[1], "AssignValues") == 0) {
-    toucher.reset(new AssignValues());
-    printf("Using AssignValues.\n");
-  } else if (strcmp(argv[1], "SumUp") == 0) {
-    toucher.reset(new SumUp());
-    printf("Using SumUp.\n");
-  } else if (strcmp(argv[1], "ReadDevZeroChunks") == 0 ||
-             strcmp(argv[1], "ReadDevZeroChunksAndSleep") == 0 ||
-             strcmp(argv[1], "ReadDevZeroChunksAndSum") == 0) {
-    if (argc < 3) {
-      fprintf(stderr, "Specify chunk size.\n");
-      abort();
-    }
-    char* end;
-    long long chunk_arg = strtoll(argv[2], &end, 10);
-    if (*end != '\0' || *argv[2] == '\0') {
-      fprintf(stderr, "Invalid chunk size: %s\n", argv[2]);
-      abort();
-    }
-    if (strcmp(argv[1], "ReadDevZeroChunksAndSleep") == 0) {
-      printf("Using ReadDevZeroChunksAndSleep.\n");
-      toucher.reset(
-          new ReadDevZeroChunksAndSleep(static_cast<size_t>(chunk_arg)));
-    } else if (strcmp(argv[1], "ReadDevZeroChunksAndSum") == 0) {
-      printf("Using ReadDevZeroChunksAndSum.\n");
-      toucher.reset(
-          new ReadDevZeroChunksAndSum(static_cast<size_t>(chunk_arg)));
-    } else {
-      printf("Using ReadDevZeroChunks.\n");
-      toucher.reset(new ReadDevZeroChunks(static_cast<size_t>(chunk_arg)));
-    }
-  } else {
-    fprintf(stderr, "Invalid input.\n");
-    abort();
-  }
-
-  while (true) {
-    bool report = interrupted;
-    if (report) {
-      printf("Waiting to finish touching everything.\n");
-      interrupted = false;
-      sleep(2);
-    }
-
-    toucher->Touch(nonidle);
-
-    if (report)
-      printf("Touched everything.\n");
-  }
-}
diff --git a/tools/install-build-deps b/tools/install-build-deps
index a8cd83e..6744c44 100755
--- a/tools/install-build-deps
+++ b/tools/install-build-deps
@@ -20,13 +20,13 @@
 import shutil
 import subprocess
 import sys
-import tempfile
+import urllib
 import zipfile
 
 from collections import namedtuple
-from platform import system
 
-from compat import urlretrieve
+# When adding a new git dependency here please also add a corresponding entry in
+# .travis.yml under the "cache:" section.
 
 # The format for the deps below is the following:
 # (target_folder, source_url, sha1, target_platform)
@@ -37,124 +37,174 @@
 # |target_folder|, taking care of stripping the root folder if it's a single
 # root (to avoid ending up with buildtools/protobuf/protobuf-1.2.3/... and have
 # instead just buildtools/protobuf).
-# |target_platform| is either 'darwin', 'linux' or 'all' and applies the dep
-# only on the given platform
+# |target_platform| is either 'darwin', 'linux2' or 'all' and applies the dep
+# only on the given platform (ask python why linux2 and not just linux).
 
 # Dependencies required to build code on the host or when targeting desktop OS.
 BUILD_DEPS_HOST = [
-    # GN
-    ('buildtools/mac/gn',
-     'https://storage.googleapis.com/perfetto/gn-mac-b5b65ca39d93a7cde9fa713be31b114755252f28',
-     'b5b65ca39d93a7cde9fa713be31b114755252f28', 'darwin'),
-    ('buildtools/linux64/gn',
-     'https://storage.googleapis.com/perfetto/gn-linux64-1370d9c5358868b7b66292821b6fe61950826870',
-     '1370d9c5358868b7b66292821b6fe61950826870', 'linux'),
+  # GN
+  ('buildtools/mac/gn',
+   'https://storage.googleapis.com/chromium-gn/9be792dd9010ce303a9c3a497a67bcc5ac8c7666',
+   '9be792dd9010ce303a9c3a497a67bcc5ac8c7666',
+   'darwin'
+  ),
+  ('buildtools/linux64/gn',
+   'https://storage.googleapis.com/chromium-gn/2f27ff0b6118e5886df976da5effa6003d19d1ce',
+   '2f27ff0b6118e5886df976da5effa6003d19d1ce',
+   'linux2'
+  ),
 
-    # clang-format
-    ('buildtools/mac/clang-format',
-     'https://storage.googleapis.com/chromium-clang-format/025ca7c75f37ef4a40f3a67d81ddd11d7d0cdb9b',
-     '025ca7c75f37ef4a40f3a67d81ddd11d7d0cdb9b', 'darwin'),
-    ('buildtools/linux64/clang-format',
-     'https://storage.googleapis.com/chromium-clang-format/942fc8b1789144b8071d3fc03ff0fcbe1cf81ac8',
-     '942fc8b1789144b8071d3fc03ff0fcbe1cf81ac8', 'linux'),
-    # Keep the SHA1 in sync with |clang_format_rev| in chromium //buildtools/DEPS.
-    ('buildtools/clang_format/script',
-     'https://chromium.googlesource.com/chromium/llvm-project/cfe/tools/clang-format.git',
-     '96636aa0e9f047f17447f2d45a094d0b59ed7917', 'all'),
+  # clang-format
+  ('buildtools/mac/clang-format',
+   'https://storage.googleapis.com/chromium-clang-format/0679b295e2ce2fce7919d1e8d003e497475f24a3',
+   '0679b295e2ce2fce7919d1e8d003e497475f24a3',
+   'darwin'
+  ),
+  ('buildtools/linux64/clang-format',
+   'https://storage.googleapis.com/chromium-clang-format/5349d1954e17f6ccafb6e6663b0f13cdb2bb33c8',
+   '5349d1954e17f6ccafb6e6663b0f13cdb2bb33c8',
+   'linux2'
+  ),
+  # Keep the SHA1 in sync with |clang_format_rev| in chromium //buildtools/DEPS.
+  ('buildtools/clang_format/script',
+   'https://chromium.googlesource.com/chromium/llvm-project/cfe/tools/clang-format.git',
+   '0653eee0c81ea04715c635dd0885e8096ff6ba6d',
+   'all'
+  ),
 
-    # Ninja
-    ('buildtools/mac/ninja',
-     'https://storage.googleapis.com/perfetto/ninja-mac-c15b0698da038b2bd2e8970c14c75fadc06b1add',
-     'c15b0698da038b2bd2e8970c14c75fadc06b1add', 'darwin'),
-    ('buildtools/linux64/ninja',
-     'https://storage.googleapis.com/perfetto/ninja-linux64-c866952bda50c29a669222477309287119bbb7e8',
-     'c866952bda50c29a669222477309287119bbb7e8', 'linux'),
+  # Ninja
+  ('buildtools/mac/ninja',
+   'https://storage.googleapis.com/fuchsia-build/fuchsia/ninja/mac/a1db595e824c50cf565fbf0af2437fd91b7babf4',
+   'a1db595e824c50cf565fbf0af2437fd91b7babf4',
+   'darwin'
+  ),
+  ('buildtools/linux64/ninja',
+   'https://storage.googleapis.com/fuchsia-build/fuchsia/ninja/linux64/d35b36c84a09f7e38b25947cafada10e8bf835bc',
+   'd35b36c84a09f7e38b25947cafada10e8bf835bc',
+   'linux2'
+  ),
 
-    # Keep in sync with Android's //external/googletest/README.version.
-    ('buildtools/googletest.zip',
-     'https://github.com/google/googletest/archive/3f05f651ae3621db58468153e32016bc1397800b.zip',
-     '86384688f7c533ad325a505efc917e0cdf39a0ce', 'all'),
+  # Keep in sync with Android's //external/googletest/README.version.
+  ('buildtools/googletest.zip',
+   'https://github.com/google/googletest/archive/ff07a5de0e81580547f1685e101194ed1a4fcd56.zip',
+   'c7edec7d7e6db1fc37a20710de9c4d89e3a3893b',
+   'all'
+  ),
 
-    # Keep in sync with Android's //external/protobuf/README.version.
-    ('buildtools/protobuf.zip',
-     'https://github.com/google/protobuf/releases/download/v3.0.0-beta-3/protobuf-cpp-3.0.0-beta-3.zip',
-     '3caec60aa9d8eefc8c3c3201b6b8ca19935edb89', 'all'),
+  # Keep in sync with Android's //external/protobuf/README.version.
+  ('buildtools/protobuf.zip',
+   'https://github.com/google/protobuf/releases/download/v3.0.0-beta-3/protobuf-cpp-3.0.0-beta-3.zip',
+   '3caec60aa9d8eefc8c3c3201b6b8ca19935edb89',
+   'all'
+  ),
 
-    # libc++, libc++abi and libunwind for Linux where we need to rebuild the C++
-    # lib from sources. Keep the SHA1s in sync with Chrome's src/buildtools/DEPS.
-    ('buildtools/libcxx',
-     'https://chromium.googlesource.com/chromium/llvm-project/libcxx.git',
-     '5938e0582bac570a41edb3d6a2217c299adc1bc6', 'all'),
-    ('buildtools/libcxxabi',
-     'https://chromium.googlesource.com/chromium/llvm-project/libcxxabi.git',
-     '0d529660e32d77d9111912d73f2c74fc5fa2a858', 'all'),
-    ('buildtools/libunwind',
-     'https://chromium.googlesource.com/external/llvm.org/libunwind.git',
-     '69d9b84cca8354117b9fe9705a4430d789ee599b', 'all'),
+  # libc++, libc++abi and libunwind for Linux where we need to rebuild the C++
+  # lib from sources. Keep the SHA1s in sync with Chrome's src/buildtools/DEPS.
+  ('buildtools/libcxx',
+   'https://chromium.googlesource.com/chromium/llvm-project/libcxx.git',
+   '2199647acb904b91eea0a5e045f5b227c87d6e85',
+   'all'
+  ),
+  ('buildtools/libcxxabi',
+   'https://chromium.googlesource.com/chromium/llvm-project/libcxxabi.git',
+   'c3f4753f7139c73063304235781e4f7788a94c06',
+   'all'
+  ),
+  ('buildtools/libunwind',
+   'https://chromium.googlesource.com/external/llvm.org/libunwind.git',
+   '317087cfd8e608bd24e53934d59b5b85e0a9ded6',
+   'all'
+  ),
 
-    # Keep the revision in sync with Chrome's PACKAGE_VERSION in
-    # tools/clang/scripts/update.py.
-    ('buildtools/clang.tgz',
-     'https://commondatastorage.googleapis.com/chromium-browser-clang/Linux_x64/clang-365097-f7e52fbd-8.tgz',
-     'fe1b1e5bd7381ae655661cb9658487389561568d', 'linux'),
+  # Keep the revision in sync with Chrome's CLANG_REVISION in
+  # tools/clang/scripts/update.py.
+  ('buildtools/clang.tgz',
+   'https://commondatastorage.googleapis.com/chromium-browser-clang/Linux_x64/clang-346388-1.tgz',
+   'c2998d67a9c623fe12e01a33e8b7cf437b396099',
+   'linux2'
+  ),
 
-    # Keep in sync with chromium DEPS.
-    ('buildtools/libfuzzer',
-     'https://chromium.googlesource.com/chromium/llvm-project/compiler-rt/lib/fuzzer.git',
-     'b9f51dc8c98065df0c8da13c051046f5bab833db', 'linux'),
+  # Keep in sync with chromium DEPS.
+  ('buildtools/libfuzzer',
+   'https://chromium.googlesource.com/chromium/llvm-project/compiler-rt/lib/fuzzer.git',
+   '2a53098584c48af50aec3fb51febe5e651489774',
+   'linux2'
+  ),
 
-    # Benchmarking tool.
-    ('buildtools/benchmark.zip',
-     'https://github.com/google/benchmark/archive/v1.3.0.zip',
-     'f387e0df37d54bfd5be239e8d0d3ea2e2c3e34f4', 'all'),
+  # Benchmarking tool.
+  ('buildtools/benchmark.zip',
+   'https://github.com/google/benchmark/archive/v1.3.0.zip',
+   'f387e0df37d54bfd5be239e8d0d3ea2e2c3e34f4',
+   'all'
+  ),
 
-    # Libbacktrace, for stacktraces in Linux/Android debug builds.
-    ('buildtools/libbacktrace.zip',
-     'https://github.com/ianlancetaylor/libbacktrace/archive/177940370e4a6b2509e92a0aaa9749184e64af43.zip',
-     'b723fe9d671d1ab54df1297f6afbf2893a41c3ea', 'all'),
+  # Libbacktrace, for stacktraces in Linux/Android debug builds.
+  ('buildtools/libbacktrace.zip',
+   'https://github.com/ianlancetaylor/libbacktrace/archive/177940370e4a6b2509e92a0aaa9749184e64af43.zip',
+   'b723fe9d671d1ab54df1297f6afbf2893a41c3ea',
+   'all'
+  ),
 
-    # Sqlite for the trace processing library.
-    # This is the amalgamated source whose compiled output is meant to be faster.
-    # We still pull the full source for the extensions (not amalgamated).
-    ('buildtools/sqlite.zip',
-     'https://storage.googleapis.com/perfetto/sqlite-amalgamation-3250300.zip',
-     'b78c2cb0d2c9182686c582312479f96a82bf5380', 'all'),
-    ('buildtools/sqlite_src.zip',
-     'https://storage.googleapis.com/perfetto/sqlite-src-3250300.zip',
-     'd1af2883bb800852946f9bf8ab6055e7698e18ee', 'all'),
+  # Sqlite for the trace processing library.
+  # This is the amalgamated source whose compiled output is meant to be faster.
+  # We still pull the full source for the extensions (not amalgamated).
+  ('buildtools/sqlite.zip',
+   'https://storage.googleapis.com/perfetto/sqlite-amalgamation-3250300.zip',
+   'b78c2cb0d2c9182686c582312479f96a82bf5380',
+   'all'
+  ),
+  ('buildtools/sqlite_src.zip',
+   'https://storage.googleapis.com/perfetto/sqlite-src-3250300.zip',
+   'd1af2883bb800852946f9bf8ab6055e7698e18ee',
+   'all'
+  ),
 
-    # JsonCpp for legacy json import. Used only by the trace processor in
-    # standalone builds.
-    ('buildtools/jsoncpp.zip',
-     'https://github.com/open-source-parsers/jsoncpp/archive/1.0.0.zip',
-     '3219e26f2e249bb46b7d688478208c7ec138fea4', 'all'),
+  # JsonCpp for legacy json import. Used only by the trace processor in
+  # standalone builds.
+  ('buildtools/jsoncpp.zip',
+   'https://github.com/open-source-parsers/jsoncpp/archive/1.0.0.zip',
+   '3219e26f2e249bb46b7d688478208c7ec138fea4',
+   'all'
+  ),
 
-    # These dependencies are for libunwindstack, which is used by src/profiling.
-    ('buildtools/android-core',
-     'https://android.googlesource.com/platform/system/core.git',
-     '3f407fcc37b401c91784700c0a691ba8b1f7ef15', 'all'),
-    ('buildtools/lzma',
-     'https://android.googlesource.com/platform/external/lzma.git',
-     '7851dce6f4ca17f5caa1c93a4e0a45686b1d56c3', 'all'),
-    ('buildtools/zlib',
-     'https://android.googlesource.com/platform/external/zlib.git',
-     'dfa0646a03b4e1707469e04dc931b09774968fe6', 'all'),
-    ('buildtools/bionic',
-     'https://android.googlesource.com/platform/bionic.git',
-     'a60488109cda997dfd83832731c8527feaa2825e', 'all'),
+  # These dependencies are for libunwindstack, which is used by src/profiling.
+  ('buildtools/android-core',
+   'https://android.googlesource.com/platform/system/core.git',
+   '9d3310c019839ec342b5c0712f3ba59cfd5ca4a0',
+   'all'
+  ),
 
-    # Example traces for regression tests.
-    (
-        'buildtools/test_data.zip',
-        'https://storage.googleapis.com/perfetto/test-data-20191107-164334.zip',
-        '499f11fbc2b04ef7742662a26b85ef03141e24bd',
-        'all',
-    ),
+  ('buildtools/lzma',
+   'https://android.googlesource.com/platform/external/lzma.git',
+   '7851dce6f4ca17f5caa1c93a4e0a45686b1d56c3',
+   'all'
+  ),
 
-    # Linenoise, used only by trace_processor in standalone builds.
-    ('buildtools/linenoise',
-     'https://fuchsia.googlesource.com/third_party/linenoise.git',
-     'c894b9e59f02203dbe4e2be657572cf88c4230c3', 'all'),
+  ('buildtools/zlib',
+   'https://android.googlesource.com/platform/external/zlib.git',
+   'dfa0646a03b4e1707469e04dc931b09774968fe6',
+   'all'
+  ),
+
+  ('buildtools/bionic',
+   'https://android.googlesource.com/platform/bionic.git',
+   'a60488109cda997dfd83832731c8527feaa2825e',
+   'all'
+  ),
+
+  # Example traces for regression tests.
+  ('buildtools/test_data.zip',
+   'https://storage.googleapis.com/perfetto/test-data-20190423-131328.zip',
+   '263db97612203fd0dd047edd54eaa7007e32bf91',
+   'all',
+  ),
+
+  # Linenoise, used only by trace_processor in standalone builds.
+  ('buildtools/linenoise',
+   'https://fuchsia.googlesource.com/third_party/linenoise.git',
+   'c894b9e59f02203dbe4e2be657572cf88c4230c3',
+   'all'
+  ),
 ]
 
 # Dependencies required to build Android code.
@@ -162,34 +212,46 @@
 # - https://dl.google.com/android/repository/repository-11.xml
 # - https://dl.google.com/android/repository/sys-img/android/sys-img.xml
 BUILD_DEPS_ANDROID = [
-    # Android NDK
-    ('buildtools/ndk.zip',
-     'https://dl.google.com/android/repository/android-ndk-r17b-darwin-x86_64.zip',
-     'f990aafaffec0b583d2c5420bfa622e52ac14248', 'darwin'),
-    ('buildtools/ndk.zip',
-     'https://dl.google.com/android/repository/android-ndk-r17b-linux-x86_64.zip',
-     'dd5762ee7ef4995ad04fe0c45a608c344d99ca9f', 'linux'),
+  # Android NDK
+  ('buildtools/ndk.zip',
+   'https://dl.google.com/android/repository/android-ndk-r17b-darwin-x86_64.zip',
+   'f990aafaffec0b583d2c5420bfa622e52ac14248',
+   'darwin'
+  ),
+  ('buildtools/ndk.zip',
+   'https://dl.google.com/android/repository/android-ndk-r17b-linux-x86_64.zip',
+   'dd5762ee7ef4995ad04fe0c45a608c344d99ca9f',
+   'linux2'
+  ),
 ]
 
 # Dependencies required to run Android tests.
 TEST_DEPS_ANDROID = [
-    # Android emulator images.
-    ('buildtools/aosp-arm.zip',
-     'https://storage.googleapis.com/perfetto/aosp-02022018-arm.zip',
-     'a480d5e7d3ca888b0a58fe15ce76b1791537429a', 'all'),
+  # Android emulator images.
+  ('buildtools/aosp-arm.zip',
+   'https://storage.googleapis.com/perfetto/aosp-02022018-arm.zip',
+   'a480d5e7d3ca888b0a58fe15ce76b1791537429a',
+   'all'
+  ),
 
-    # platform-tools.zip contains adb binaries.
-    ('buildtools/android_sdk/platform-tools.zip',
-     'https://dl.google.com/android/repository/platform-tools_r26.0.0-darwin.zip',
-     'e75b6137dc444f777eb02f44a6d9819b3aabff82', 'darwin'),
-    ('buildtools/android_sdk/platform-tools.zip',
-     'https://dl.google.com/android/repository/platform-tools_r26.0.0-linux.zip',
-     '00de8a6631405b617c10f68cd11ff2e1cd528e23', 'linux'),
+  # platform-tools.zip contains adb binaries.
+  ('buildtools/android_sdk/platform-tools.zip',
+   'https://dl.google.com/android/repository/platform-tools_r26.0.0-darwin.zip',
+   'e75b6137dc444f777eb02f44a6d9819b3aabff82',
+   'darwin'
+  ),
+  ('buildtools/android_sdk/platform-tools.zip',
+   'https://dl.google.com/android/repository/platform-tools_r26.0.0-linux.zip',
+   '00de8a6631405b617c10f68cd11ff2e1cd528e23',
+   'linux2'
+  ),
 
-    # Android emulator binaries.
-    ('buildtools/emulator',
-     'https://android.googlesource.com/platform/prebuilts/android-emulator.git',
-     '4b260028dc27bc92c39bee9129cb2ba839970956', 'all'),
+  # Android emulator binaries.
+  ('buildtools/emulator',
+   'https://android.googlesource.com/platform/prebuilts/android-emulator.git',
+   '4b260028dc27bc92c39bee9129cb2ba839970956',
+   'all'
+  ),
 ]
 
 # This variable is updated by tools/roll-catapult-trace-viewer.
@@ -198,33 +260,51 @@
 TYPEFACES_SHA1 = '756b0a015b8f99f5718f7fdf967d052c1ec55ab3'
 
 UI_DEPS = [
-    ('buildtools/nodejs.tgz',
-     'https://storage.googleapis.com/perfetto/node-v10.3.0-darwin-x64.tar.gz',
-     '6d9a122785f38c256add3b25f74adf125497861a', 'darwin'),
-    ('buildtools/nodejs.tgz',
-     'https://storage.googleapis.com/perfetto/node-v10.3.0-linux-x64.tar.xz',
-     '118f6ea19f75089b3f12ac2ddfce357bff872b5e', 'linux'),
-    ('buildtools/emsdk/emscripten.tgz',
-     'https://storage.googleapis.com/perfetto/emscripten-1.37.40.tar.gz',
-     '588c28221321ebbdfc8e3a6f47ea6106f589669b', 'all'),
-    ('buildtools/emsdk/llvm.tgz',
-     'https://storage.googleapis.com/perfetto/emscripten-llvm-e1.37.40-darwin.tar.gz',
-     '7a894ef0a52821c62f6abaac552dc4ce5d424607', 'darwin'),
-    ('buildtools/emsdk/llvm.tgz',
-     'https://storage.googleapis.com/perfetto/emscripten-llvm-e1.37.40-static-linux.tar.gz',
-     '478501b9b7a14884e546c84efe209a90052cbb07', 'linux'),
-    ('buildtools/d8.tgz',
-     'https://storage.googleapis.com/perfetto/d8-linux-5.7.492.65.tar.gz',
-     '95e82ad7faf0a6f74d950c2aa65e3858b7bdb6c6', 'linux'),
-    ('buildtools/d8.tgz',
-     'https://storage.googleapis.com/perfetto/d8-darwin-6.6.346.32.tar.gz',
-     '1abd630619bb1977ab62095570a113d782a1545d', 'darwin'),
-    ('buildtools/catapult_trace_viewer.tgz',
-     'https://storage.googleapis.com/perfetto/catapult_trace_viewer-%s.tar.gz' %
-     CATAPULT_SHA1, CATAPULT_SHA1, 'all'),
-    ('buildtools/typefaces.tgz',
-     'https://storage.googleapis.com/perfetto/typefaces-%s.tar.gz' %
-     TYPEFACES_SHA1, TYPEFACES_SHA1, 'all')
+  ('buildtools/nodejs.tgz',
+   'https://storage.googleapis.com/perfetto/node-v10.3.0-darwin-x64.tar.gz',
+   '6d9a122785f38c256add3b25f74adf125497861a',
+   'darwin'
+  ),
+  ('buildtools/nodejs.tgz',
+   'https://storage.googleapis.com/perfetto/node-v10.3.0-linux-x64.tar.xz',
+   '118f6ea19f75089b3f12ac2ddfce357bff872b5e',
+   'linux2'
+  ),
+  ('buildtools/emsdk/emscripten.tgz',
+   'https://storage.googleapis.com/perfetto/emscripten-1.37.40.tar.gz',
+   '588c28221321ebbdfc8e3a6f47ea6106f589669b',
+   'all'
+  ),
+  ('buildtools/emsdk/llvm.tgz',
+   'https://storage.googleapis.com/perfetto/emscripten-llvm-e1.37.40-darwin.tar.gz',
+   '7a894ef0a52821c62f6abaac552dc4ce5d424607',
+   'darwin'
+  ),
+  ('buildtools/emsdk/llvm.tgz',
+   'https://storage.googleapis.com/perfetto/emscripten-llvm-e1.37.40-static-linux.tar.gz',
+   '478501b9b7a14884e546c84efe209a90052cbb07',
+   'linux2'
+  ),
+  ('buildtools/d8.tgz',
+   'https://storage.googleapis.com/perfetto/d8-linux2-5.7.492.65.tar.gz',
+   '95e82ad7faf0a6f74d950c2aa65e3858b7bdb6c6',
+   'linux2'
+  ),
+  ('buildtools/d8.tgz',
+   'https://storage.googleapis.com/perfetto/d8-darwin-6.6.346.32.tar.gz',
+   '1abd630619bb1977ab62095570a113d782a1545d',
+   'darwin'
+  ),
+  ('buildtools/catapult_trace_viewer.tgz',
+   'https://storage.googleapis.com/perfetto/catapult_trace_viewer-%s.tar.gz' % CATAPULT_SHA1,
+    CATAPULT_SHA1,
+   'all'
+  ),
+  ('buildtools/typefaces.tgz',
+   'https://storage.googleapis.com/perfetto/typefaces-%s.tar.gz' % TYPEFACES_SHA1,
+    TYPEFACES_SHA1,
+   'all'
+  )
 ]
 
 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -234,7 +314,7 @@
   if not os.path.exists(path):
     return None
   with open(path) as f:
-    return f.read().strip()
+      return f.read().strip()
 
 
 def MkdirRecursive(path):
@@ -245,7 +325,7 @@
     if not os.path.exists(cwd):
       os.makedirs(cwd)
     else:
-      assert (os.path.isdir(cwd))
+      assert(os.path.isdir(cwd))
 
 
 def HashLocalFile(path):
@@ -259,7 +339,7 @@
   zf.extract(info.filename, path=path)
   target_path = os.path.join(path, info.filename)
   min_acls = 0o755 if info.filename.endswith('/') else 0o644
-  os.chmod(target_path, (info.external_attr >> 16) | min_acls)
+  os.chmod(target_path, (info.external_attr >> 16L) | min_acls)
 
 
 def IsGitRepoCheckoutOutAtRevision(path, revision):
@@ -275,45 +355,23 @@
   logging.info('Fetching %s @ %s into %s', git_url, revision, path)
   subprocess.check_call(['git', 'init', path], cwd=path)
   subprocess.check_call(
-      ['git', 'fetch', '--quiet', '--depth', '1', git_url, revision], cwd=path)
+    ['git', 'fetch', '--quiet', '--depth', '1', git_url, revision], cwd=path)
   subprocess.check_call(['git', 'checkout', revision, '--quiet'], cwd=path)
-  assert (IsGitRepoCheckoutOutAtRevision(path, revision))
+  assert(IsGitRepoCheckoutOutAtRevision(path, revision))
   return True
 
-
 def InstallNodeModules():
   ui_dir = os.path.join(ROOT_DIR, 'ui')
   logging.info("Running npm install in {0}".format(ui_dir))
-  subprocess.check_call([os.path.join(ui_dir, 'npm'), 'install', '--no-save'],
-                        cwd=os.path.join(ROOT_DIR, 'ui'))
-
-
-def CheckHashes():
-  for deps in [BUILD_DEPS_HOST, BUILD_DEPS_ANDROID, TEST_DEPS_ANDROID, UI_DEPS]:
-    for rel_path, url, expected_sha1, platform in deps:
-      if url.endswith('.git'):
-        continue
-      logging.info('Downloading %s from %s', rel_path, url)
-      with tempfile.NamedTemporaryFile(delete=False) as f:
-        f.close()
-        urlretrieve(url, f.name)
-        actual_sha1 = HashLocalFile(f.name)
-        os.unlink(f.name)
-        if (actual_sha1 != expected_sha1):
-          logging.fatal('SHA1 mismatch for {} expected {} was {}'.format(
-              url, expected_sha1, actual_sha1))
-
+  subprocess.check_call(
+    [os.path.join(ui_dir, 'npm'), 'install', '--no-save'],
+    cwd=os.path.join(ROOT_DIR, 'ui'))
 
 def Main():
   parser = argparse.ArgumentParser()
   parser.add_argument('--no-android', action='store_true')
   parser.add_argument('--ui', action='store_true')
-  parser.add_argument(
-      '--check-hashes', help='Check hashes for all URLs', action='store_true')
   args = parser.parse_args()
-  if args.check_hashes:
-    CheckHashes()
-    return 0
   deps = BUILD_DEPS_HOST
   if not args.no_android:
     deps += BUILD_DEPS_ANDROID + TEST_DEPS_ANDROID
@@ -321,7 +379,7 @@
     deps += UI_DEPS
   deps_updated = False
   for rel_path, url, expected_sha1, platform in deps:
-    if (platform != 'all' and platform != system().lower()):
+    if (platform != 'all' and platform != sys.platform):
       continue
     local_path = os.path.join(ROOT_DIR, rel_path)
     if url.endswith('.git'):
@@ -339,7 +397,7 @@
     if HashLocalFile(local_path) != expected_sha1:
       download_path = local_path + '.tmp'
       logging.info('Downloading %s from %s', local_path, url)
-      urlretrieve(url, download_path)
+      urllib.urlretrieve(url, download_path)
       os.chmod(download_path, 0o755)
       actual_sha1 = HashLocalFile(download_path)
       if (actual_sha1 != expected_sha1):
@@ -348,11 +406,11 @@
             download_path, expected_sha1, actual_sha1))
         return 1
       os.rename(download_path, local_path)
-    assert (HashLocalFile(local_path) == expected_sha1)
+    assert(HashLocalFile(local_path) == expected_sha1)
 
     if is_zip:
       logging.info('Extracting %s into %s' % (local_path, zip_target_dir))
-      assert (os.path.commonprefix((ROOT_DIR, zip_target_dir)) == ROOT_DIR)
+      assert(os.path.commonprefix((ROOT_DIR, zip_target_dir)) == ROOT_DIR)
       if os.path.exists(zip_target_dir):
         logging.info('Deleting stale dir %s' % zip_target_dir)
         shutil.rmtree(zip_target_dir)
@@ -373,7 +431,7 @@
         subdir = os.path.join(zip_target_dir, subdir[0])
         if os.path.isdir(subdir):
           for subf in os.listdir(subdir):
-            shutil.move(os.path.join(subdir, subf), zip_target_dir)
+            shutil.move(os.path.join(subdir,subf), zip_target_dir)
           os.rmdir(subdir)
 
       # Create stamp and remove the archive.
@@ -388,9 +446,8 @@
   if deps_updated:
     # Stale binary files may be compiled against old sysroot headers that aren't
     # tracked by gn.
-    logging.warning('Remember to run "gn clean <output_directory>" ' +
-                    'to avoid stale binary files.')
-
+    logging.warn('Remember to run "gn clean <output_directory>" ' +
+                 'to avoid stale binary files.')
 
 if __name__ == '__main__':
   logging.basicConfig(level=logging.INFO)
diff --git a/tools/load_tool b/tools/load_tool
index a67e4b7..9bbd1d6 100755
--- a/tools/load_tool
+++ b/tools/load_tool
@@ -43,38 +43,38 @@
 '''
 
 PERFETTO_PER_CPU_BUFFER_SIZE_KB_PARAMS = [
-    128,
-    256,
-    512,
-    1 * 1024,  # 1 MB
-    2 * 1024,  # 2 MB
-    4 * 1024,  # 4 MB
+  128,
+  256,
+  512,
+  1 * 1024, # 1 MB
+  2 * 1024, # 2 MB
+  4 * 1024, # 4 MB
 ]
 
 PERFETTO_DRAIN_RATE_MS_PARAMS = [
-    100,
-    240,
-    500,
-    1 * 1000,  # 1s
-    2 * 1000,  # 2s
-    5 * 1000,  # 5s
+  100,
+  240,
+  500,
+  1 * 1000, # 1s
+  2 * 1000, # 2s
+  5 * 1000, # 5s
 ]
 
 BUSY_THREADS_NUM_THREADS_PARAMS = [
-    8,
-    32,
-    128,
+  8,
+  32,
+  128,
 ]
 
 BUSY_THREADS_DUTY_CYCLE_PARAMS = [
-    10,
-    100,
+  10,
+  100,
 ]
 
 BUSY_THREADS_PERIOD_US_PARAMS = [
-    500,
-    1 * 1000,  # 1 ms
-    10 * 1000,  # 10 ms
+  500,
+  1 * 1000,  # 1 ms
+  10 * 1000, # 10 ms
 ]
 
 TRACE_PROCESSOR_QUERY = """
@@ -91,42 +91,58 @@
 ) as b
 """
 
-
 def AdbArgs(*args):
   cmd = [ADB_PATH] + list([str(x) for x in args])
   logging.debug('> adb ' + ' '.join([str(x) for x in args]))
   return cmd
 
-
 def AdbCall(*args):
   return subprocess.check_output(AdbArgs(*args)).decode('utf-8').rstrip()
 
-
-def SingleTraceRun(out_dir, prio_name, buffer_size_kb, drain_rate_ms,
-                   num_threads, duty_cycle, period_us):
-  busy_threads_args = AdbArgs('shell', '/data/local/tmp/busy_threads',
-                              '--threads={}'.format(num_threads),
-                              '--duty_cycle={}'.format(duty_cycle),
-                              '--period_us={}'.format(period_us))
-  perfetto_args = AdbArgs('shell', 'perfetto', '--txt', '-c', '-', '-o', '-')
+def SingleTraceRun(out_dir,
+                   prio_name,
+                   buffer_size_kb,
+                   drain_rate_ms,
+                   num_threads,
+                   duty_cycle,
+                   period_us):
+  busy_threads_args = AdbArgs(
+    'shell',
+    '/data/local/tmp/busy_threads',
+    '--threads={}'.format(num_threads),
+    '--duty_cycle={}'.format(duty_cycle),
+    '--period_us={}'.format(period_us)
+  )
+  perfetto_args = AdbArgs(
+    'shell',
+    'perfetto',
+    '--txt',
+    '-c',
+    '-',
+    '-o',
+    '-'
+  )
 
   # Create a file object to read the trace into.
   with tempfile.NamedTemporaryFile() as trace_file:
-    logging.info(
-        "Starting trace with parameters ({}, {}, {}, {}, {}, {})".format(
-            prio_name, buffer_size_kb, drain_rate_ms, num_threads, duty_cycle,
-            period_us))
+    logging.info("Starting trace with parameters ({}, {}, {}, {}, {}, {})"
+      .format(prio_name,
+              buffer_size_kb,
+              drain_rate_ms,
+              num_threads,
+              duty_cycle,
+              period_us))
 
     # Start the busy threads running.
     busy_threads_handle = subprocess.Popen(busy_threads_args)
 
     # Start the Perfetto trace.
     perfetto_handle = subprocess.Popen(
-        perfetto_args, stdin=subprocess.PIPE, stdout=trace_file)
+      perfetto_args, stdin=subprocess.PIPE, stdout=trace_file)
 
     # Create the config with the parameters
     config = TEMPLATED_PERFETTO_CFG.format(
-        buffer_size_kb=buffer_size_kb, drain_period_ms=drain_rate_ms)
+      buffer_size_kb=buffer_size_kb, drain_period_ms=drain_rate_ms)
 
     # Send the config to the Perfetto binary and wait for response.
     perfetto_handle.stdin.write(config.encode())
@@ -139,7 +155,7 @@
     # Return any errors from Perfetto.
     if perfetto_ret:
       raise subprocess.CalledProcessError(
-          cmd=perfetto_args, returncode=perfetto_ret)
+        cmd=perfetto_args, returncode=perfetto_ret)
 
     # TODO(lalitm): allow trace processor to take the query file from stdin
     # to prevent this hack from being required.
@@ -150,16 +166,21 @@
       # Run the trace processor on the config.
       tp_path = os.path.join(out_dir, 'trace_processor_shell')
       tp_out = subprocess.check_output(
-          [tp_path, '-q', trace_query_file.name, trace_file.name])
+        [tp_path, '-q', trace_query_file.name, trace_file.name])
 
       # Get the CSV output from trace processor (stripping the header).
       [num_sched, num_overrun] = str(tp_out).split('\n')[1].split(',')
 
     # Print the row to stdout.
-    sys.stdout.write('"{}",{},{},{},{},{},{},{}\n'.format(
-        prio_name, buffer_size_kb, drain_rate_ms, num_threads, duty_cycle,
-        period_us, num_sched, num_overrun))
-
+    sys.stdout.write('"{}",{},{},{},{},{},{},{}\n'
+      .format(prio_name,
+              buffer_size_kb,
+              drain_rate_ms,
+              num_threads,
+              duty_cycle,
+              period_us,
+              num_sched,
+              num_overrun))
 
 def SinglePriorityRun(out_dir, prio_name):
   for buffer_size_kb in PERFETTO_PER_CPU_BUFFER_SIZE_KB_PARAMS:
@@ -167,9 +188,15 @@
       for num_threads in BUSY_THREADS_NUM_THREADS_PARAMS:
         for duty_cycle in BUSY_THREADS_DUTY_CYCLE_PARAMS:
           for period_us in BUSY_THREADS_PERIOD_US_PARAMS:
-            SingleTraceRun(out_dir, prio_name, buffer_size_kb, drain_rate_ms,
-                           num_threads, duty_cycle, period_us)
-
+            SingleTraceRun(
+              out_dir,
+              prio_name,
+              buffer_size_kb,
+              drain_rate_ms,
+              num_threads,
+              duty_cycle,
+              period_us
+            )
 
 def CycleTracedAndProbes():
   AdbCall('shell', 'stop', 'traced')
@@ -179,10 +206,9 @@
   AdbCall('shell', 'sleep', '5')
   traced_pid = AdbCall('shell', 'pidof', 'traced')
   probes_pid = AdbCall('shell', 'pidof', 'traced_probes')
-  assert (traced_pid is not None and probes_pid is not None)
+  assert(traced_pid is not None and probes_pid is not None)
   return (traced_pid, probes_pid)
 
-
 def Main():
   parser = argparse.ArgumentParser()
   parser.add_argument('linux_out_dir', help='out/android/')
@@ -205,9 +231,15 @@
   (traced_pid, probes_pid) = CycleTracedAndProbes()
 
   # Print the header for csv.
-  sys.stdout.write('"{}","{}","{}","{}","{}","{}","{}","{}"\n'.format(
-      'prio_name', 'buffer_size_kb', 'drain_rate_ms', 'num_threads',
-      'duty_cycle', 'period_us', 'num_sched', 'num_overrun'))
+  sys.stdout.write('"{}","{}","{}","{}","{}","{}","{}","{}"\n'
+      .format('prio_name',
+              'buffer_size_kb',
+              'drain_rate_ms',
+              'num_threads',
+              'duty_cycle',
+              'period_us',
+              'num_sched',
+              'num_overrun'))
 
   # First, do a single run in all configurations without changing prio.
   SinglePriorityRun(args.linux_out_dir, 'Default')
@@ -248,7 +280,6 @@
 
   return 0
 
-
 if __name__ == '__main__':
   logging.basicConfig(level=logging.INFO)
   sys.exit(Main())
diff --git a/tools/profiling_sample_distribution.cc b/tools/profiling_sample_distribution.cc
index 9fd140e..8a2195a 100644
--- a/tools/profiling_sample_distribution.cc
+++ b/tools/profiling_sample_distribution.cc
@@ -34,12 +34,12 @@
 // 1 bar 100
 
 #include <iostream>
-#include <map>
 #include <string>
 #include <thread>
 
 #include <unistd.h>
 
+#include "src/profiling/memory/client.h"
 #include "src/profiling/memory/sampler.h"
 
 #include "perfetto/base/logging.h"
@@ -113,20 +113,36 @@
   for (const auto& pair : total_ground_truth)
     std::cout << "g " << pair.first << " " << pair.second << std::endl;
 
-  while (times-- > 0) {
-    Sampler sampler(sampling_interval);
-    std::map<std::string, uint64_t> totals;
-    for (const auto& pair : allocations) {
-      size_t sample_size = sampler.SampleSize(pair.second);
-      // We also want to add 0 to make downstream processing easier, making
-      // sure every iteration has an entry for every key, even if it is
-      // zero.
-      totals[pair.first] += sample_size;
-    }
+  std::default_random_engine seed_engine(init_seed);
 
-    for (const auto& pair : totals)
-      std::cout << times << " " << pair.first << " " << pair.second
-                << std::endl;
+  while (times-- > 0) {
+    PThreadKey key(ThreadLocalSamplingData::KeyDestructor);
+    ThreadLocalSamplingData::seed = seed_engine();
+    // We want to use the same API here that the client uses, which involves
+    // TLS. In order to destruct that TLS, we need to spawn a thread because
+    // pthread_key_delete does not delete any associated data, but rather it
+    // gets deleted when the owning thread terminates.
+    //
+    // Sad times.
+    std::thread th([&] {
+      if (!key.valid())
+        PERFETTO_FATAL("Failed to initialize TLS.");
+
+      std::map<std::string, uint64_t> totals;
+      for (const auto& pair : allocations) {
+        size_t sample_size =
+            SampleSize(key.get(), pair.second, sampling_interval, malloc, free);
+        // We also want to add 0 to make downstream processing easier, making
+        // sure every iteration has an entry for every key, even if it is
+        // zero.
+        totals[pair.first] += sample_size;
+      }
+
+      for (const auto& pair : totals)
+        std::cout << times << " " << pair.first << " " << pair.second
+                  << std::endl;
+    });
+    th.join();
   }
 
   return 0;
diff --git a/tools/proto_to_cpp/BUILD.gn b/tools/proto_to_cpp/BUILD.gn
new file mode 100644
index 0000000..00b36f6
--- /dev/null
+++ b/tools/proto_to_cpp/BUILD.gn
@@ -0,0 +1,42 @@
+# Copyright (C) 2017 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 (current_toolchain == host_toolchain) {
+  executable("proto_to_cpp_host") {
+    testonly = true
+    deps = [
+      "../../gn:default_deps",
+      "../../gn:protobuf_full_deps",
+      "../../src/base",
+    ]
+    sources = [
+      "proto_to_cpp.cc",
+    ]
+  }
+}
+
+copy("proto_to_cpp") {
+  testonly = true
+  host_out_dir_ =
+      get_label_info(":proto_to_cpp_host($host_toolchain)", "root_out_dir")
+  deps = [
+    ":proto_to_cpp_host($host_toolchain)",
+  ]
+  sources = [
+    "${host_out_dir_}/proto_to_cpp_host",
+  ]
+  outputs = [
+    "${root_out_dir}/proto_to_cpp",
+  ]
+}
diff --git a/tools/proto_to_cpp/proto_to_cpp.cc b/tools/proto_to_cpp/proto_to_cpp.cc
new file mode 100644
index 0000000..52e85c3
--- /dev/null
+++ b/tools/proto_to_cpp/proto_to_cpp.cc
@@ -0,0 +1,519 @@
+/*
+ * Copyright (C) 2017 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 <google/protobuf/compiler/importer.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/util/field_comparator.h>
+#include <google/protobuf/util/message_differencer.h>
+
+#include <stdio.h>
+
+#include <fstream>
+#include <iostream>
+
+#include "perfetto/base/logging.h"
+
+using namespace google::protobuf;
+using namespace google::protobuf::compiler;
+using namespace google::protobuf::io;
+
+namespace {
+
+static const char kHeader[] = R"(/*
+ * Copyright (C) 2017 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.
+ */
+
+/*******************************************************************************
+ * AUTOGENERATED - DO NOT EDIT
+ *******************************************************************************
+ * This file has been generated from the protobuf message
+ * $p$
+ * by
+ * $f$.
+ * If you need to make changes here, change the .proto file and then run
+ * ./tools/gen_tracing_cpp_headers_from_protos
+ */
+
+)";
+
+class ErrorPrinter : public MultiFileErrorCollector {
+  virtual void AddError(const string& filename,
+                        int line,
+                        int col,
+                        const string& msg) {
+    PERFETTO_ELOG("%s %d:%d: %s", filename.c_str(), line, col, msg.c_str());
+  }
+  virtual void AddWarning(const string& filename,
+                          int line,
+                          int col,
+                          const string& msg) {
+    PERFETTO_ILOG("%s %d:%d: %s", filename.c_str(), line, col, msg.c_str());
+  }
+};
+
+std::string GetProtoHeader(const FileDescriptor* proto_file) {
+  return StringReplace(proto_file->name(), ".proto", ".pb.h", false);
+}
+
+std::string GetFwdDeclType(const Descriptor* msg, bool with_namespace = false) {
+  std::string full_type;
+  full_type.append(msg->name());
+  for (const Descriptor* par = msg->containing_type(); par;
+       par = par->containing_type()) {
+    full_type.insert(0, par->name() + "_");
+  }
+  if (with_namespace) {
+    std::vector<std::string> namespaces = Split(msg->file()->package(), ".");
+    for (auto it = namespaces.rbegin(); it != namespaces.rend(); it++) {
+      full_type.insert(0, *it + "::");
+    }
+  }
+  return full_type;
+}
+
+void GenFwdDecl(const Descriptor* msg, Printer* p) {
+  p->Print("class $n$;", "n", GetFwdDeclType(msg));
+
+  // Recurse into subtypes
+  for (int i = 0; i < msg->field_count(); i++) {
+    const FieldDescriptor* field = msg->field(i);
+    if (field->type() == FieldDescriptor::TYPE_MESSAGE)
+      GenFwdDecl(field->message_type(), p);
+  }
+}
+
+}  // namespace
+
+class ProtoToCpp {
+ public:
+  ProtoToCpp(const std::string& header_dir,
+             const std::string& cpp_dir,
+             const std::string& include_path);
+
+  static std::string GetCppType(const FieldDescriptor* field, bool constref);
+
+  void Convert(const std::string& src_proto);
+  std::string GetHeaderPath(const FileDescriptor*);
+  std::string GetCppPath(const FileDescriptor*);
+  std::string GetIncludePath(const FileDescriptor*);
+  void GenHeader(const Descriptor*, Printer*);
+  void GenCpp(const Descriptor*, Printer*, std::string prefix);
+
+ private:
+  std::string header_dir_;
+  std::string cpp_dir_;
+  std::string include_path_;
+  DiskSourceTree dst_;
+  ErrorPrinter error_printer_;
+  Importer importer_;
+};
+
+ProtoToCpp::ProtoToCpp(const std::string& header_dir,
+                       const std::string& cpp_dir,
+                       const std::string& include_path)
+    : header_dir_(header_dir),
+      cpp_dir_(cpp_dir),
+      include_path_(include_path),
+      importer_(&dst_, &error_printer_) {
+  dst_.MapPath("", "protos");
+}
+
+std::string ProtoToCpp::GetHeaderPath(const FileDescriptor* proto_file) {
+  std::string basename = Split(proto_file->name(), "/").back();
+  return header_dir_ + "/" + StringReplace(basename, ".proto", ".h", false);
+}
+
+std::string ProtoToCpp::GetCppPath(const FileDescriptor* proto_file) {
+  std::string basename = Split(proto_file->name(), "/").back();
+  return cpp_dir_ + "/" + StringReplace(basename, ".proto", ".cc", false);
+}
+
+std::string ProtoToCpp::GetIncludePath(const FileDescriptor* proto_file) {
+  std::string basename = Split(proto_file->name(), "/").back();
+  return include_path_ + "/" + StringReplace(basename, ".proto", ".h", false);
+}
+
+std::string ProtoToCpp::GetCppType(const FieldDescriptor* field,
+                                   bool constref) {
+  switch (field->type()) {
+    case FieldDescriptor::TYPE_DOUBLE:
+      return "double";
+    case FieldDescriptor::TYPE_FLOAT:
+      return "float";
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_UINT32:
+      return "uint32_t";
+    case FieldDescriptor::TYPE_SFIXED32:
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_SINT32:
+      return "int32_t";
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_UINT64:
+      return "uint64_t";
+    case FieldDescriptor::TYPE_SFIXED64:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_INT64:
+      return "int64_t";
+    case FieldDescriptor::TYPE_BOOL:
+      return "bool";
+    case FieldDescriptor::TYPE_STRING:
+    case FieldDescriptor::TYPE_BYTES:
+      return constref ? "const std::string&" : "std::string";
+    case FieldDescriptor::TYPE_MESSAGE:
+      return constref ? "const " + field->message_type()->name() + "&"
+                      : field->message_type()->name();
+    case FieldDescriptor::TYPE_ENUM:
+      return field->enum_type()->name();
+    case FieldDescriptor::TYPE_GROUP:
+      PERFETTO_FATAL("No cpp type for a group field.");
+  }
+  PERFETTO_FATAL("Not reached");  // for gcc
+}
+
+void ProtoToCpp::Convert(const std::string& src_proto) {
+  const FileDescriptor* proto_file = importer_.Import(src_proto);
+  if (!proto_file) {
+    PERFETTO_ELOG("Failed to load %s", src_proto.c_str());
+    exit(1);
+  }
+
+  std::string dst_header = GetHeaderPath(proto_file);
+  std::string dst_cpp = GetCppPath(proto_file);
+
+  std::ofstream header_ostr;
+  header_ostr.open(dst_header);
+  PERFETTO_CHECK(header_ostr.is_open());
+  OstreamOutputStream header_proto_ostr(&header_ostr);
+  Printer header_printer(&header_proto_ostr, '$');
+
+  std::ofstream cpp_ostr;
+  cpp_ostr.open(dst_cpp);
+  PERFETTO_CHECK(cpp_ostr.is_open());
+  OstreamOutputStream cpp_proto_ostr(&cpp_ostr);
+  Printer cpp_printer(&cpp_proto_ostr, '$');
+
+  std::string include_guard = dst_header + "_";
+  UpperString(&include_guard);
+  StripString(&include_guard, ".-/\\", '_');
+  header_printer.Print(kHeader, "f", __FILE__, "p", src_proto);
+  header_printer.Print("#ifndef $g$\n#define $g$\n\n", "g", include_guard);
+  header_printer.Print("#include <stdint.h>\n");
+  header_printer.Print("#include <vector>\n");
+  header_printer.Print("#include <string>\n");
+  header_printer.Print("#include <type_traits>\n\n");
+  header_printer.Print("#include \"perfetto/base/export.h\"\n\n");
+
+  cpp_printer.Print(kHeader, "f", __FILE__, "p", src_proto);
+  PERFETTO_CHECK(dst_header.find("include/") == 0);
+  cpp_printer.Print("#include \"$f$\"\n", "f",
+                    dst_header.substr(strlen("include/")));
+
+  // Generate includes for translated types of dependencies.
+  for (int i = 0; i < proto_file->dependency_count(); i++) {
+    const FileDescriptor* dep = proto_file->dependency(i);
+    header_printer.Print("#include \"$f$\"\n", "f", GetIncludePath(dep));
+  }
+  header_printer.Print("\n");
+
+  cpp_printer.Print("\n#include \"$f$\"\n", "f", GetProtoHeader(proto_file));
+  for (int i = 0; i < proto_file->dependency_count(); i++) {
+    const FileDescriptor* dep = proto_file->dependency(i);
+    cpp_printer.Print("#include \"$f$\"\n", "f", GetProtoHeader(dep));
+  }
+
+  // Generate forward declarations in the header for proto types.
+  header_printer.Print("// Forward declarations for protobuf types.\n");
+  std::vector<std::string> namespaces = Split(proto_file->package(), ".");
+  for (size_t i = 0; i < namespaces.size(); i++)
+    header_printer.Print("namespace $n$ {\n", "n", namespaces[i]);
+  for (int i = 0; i < proto_file->message_type_count(); i++)
+    GenFwdDecl(proto_file->message_type(i), &header_printer);
+  for (size_t i = 0; i < namespaces.size(); i++)
+    header_printer.Print("}\n");
+
+  header_printer.Print("\nnamespace perfetto {\n");
+  cpp_printer.Print("\nnamespace perfetto {\n");
+
+  for (int i = 0; i < proto_file->message_type_count(); i++) {
+    const Descriptor* msg = proto_file->message_type(i);
+    GenHeader(msg, &header_printer);
+    GenCpp(msg, &cpp_printer, "");
+  }
+
+  cpp_printer.Print("}  // namespace perfetto\n");
+  header_printer.Print("}  // namespace perfetto\n");
+  header_printer.Print("\n#endif  // $g$\n", "g", include_guard);
+}
+
+void ProtoToCpp::GenHeader(const Descriptor* msg, Printer* p) {
+  PERFETTO_ILOG("GEN %s %s", msg->name().c_str(), msg->file()->name().c_str());
+  p->Print("\nclass PERFETTO_EXPORT $n$ {\n", "n", msg->name());
+  p->Print(" public:\n");
+  p->Indent();
+  // Do a first pass to generate nested types.
+  for (int i = 0; i < msg->field_count(); i++) {
+    const FieldDescriptor* field = msg->field(i);
+    if (field->has_default_value()) {
+      PERFETTO_FATAL(
+          "Error on field %s: Explicitly declared default values are not "
+          "supported",
+          field->name().c_str());
+    }
+
+    if (field->type() == FieldDescriptor::TYPE_ENUM) {
+      const EnumDescriptor* enum_desc = field->enum_type();
+      p->Print("enum $n$ {\n", "n", enum_desc->name());
+      for (int e = 0; e < enum_desc->value_count(); e++) {
+        const EnumValueDescriptor* value = enum_desc->value(e);
+        p->Print("  $n$ = $v$,\n", "n", value->name(), "v",
+                 std::to_string(value->number()));
+      }
+      p->Print("};\n");
+    } else if (field->type() == FieldDescriptor::TYPE_MESSAGE &&
+               field->message_type()->file() == msg->file()) {
+      GenHeader(field->message_type(), p);
+    }
+  }
+
+  p->Print("$n$();\n", "n", msg->name());
+  p->Print("~$n$();\n", "n", msg->name());
+  p->Print("$n$($n$&&) noexcept;\n", "n", msg->name());
+  p->Print("$n$& operator=($n$&&);\n", "n", msg->name());
+  p->Print("$n$(const $n$&);\n", "n", msg->name());
+  p->Print("$n$& operator=(const $n$&);\n", "n", msg->name());
+  p->Print("bool operator==(const $n$&) const;\n", "n", msg->name());
+  p->Print(
+      "bool operator!=(const $n$& other) const { return !(*this == other); }\n",
+      "n", msg->name());
+  p->Print("\n");
+
+  std::string proto_type = GetFwdDeclType(msg, true);
+  p->Print("// Conversion methods from/to the corresponding protobuf types.\n");
+  p->Print("void FromProto(const $p$&);\n", "n", msg->name(), "p", proto_type);
+  p->Print("void ToProto($p$*) const;\n", "p", proto_type);
+
+  // Generate accessors.
+  for (int i = 0; i < msg->field_count(); i++) {
+    const FieldDescriptor* field = msg->field(i);
+    p->Print("\n");
+    if (!field->is_repeated()) {
+      p->Print("$t$ $n$() const { return $n$_; }\n", "t",
+               GetCppType(field, true), "n", field->lowercase_name());
+      if (field->type() == FieldDescriptor::TYPE_MESSAGE) {
+        p->Print("$t$* mutable_$n$() { return &$n$_; }\n", "t",
+                 GetCppType(field, false), "n", field->lowercase_name());
+      } else {
+        p->Print("void set_$n$($t$ value) { $n$_ = value; }\n", "t",
+                 GetCppType(field, true), "n", field->lowercase_name());
+        if (field->type() == FieldDescriptor::TYPE_BYTES) {
+          p->Print(
+              "void set_$n$(const void* p, size_t s) { "
+              "$n$_.assign(reinterpret_cast<const char*>(p), s); }\n",
+              "n", field->lowercase_name());
+        }
+      }
+    } else {  // is_repeated()
+      p->Print(
+          "int $n$_size() const { return static_cast<int>($n$_.size()); }\n",
+          "t", GetCppType(field, false), "n", field->lowercase_name());
+      p->Print("const std::vector<$t$>& $n$() const { return $n$_; }\n", "t",
+               GetCppType(field, false), "n", field->lowercase_name());
+      p->Print("std::vector<$t$>* mutable_$n$() { return &$n$_; }\n", "t",
+               GetCppType(field, false), "n", field->lowercase_name());
+      p->Print("void clear_$n$() { $n$_.clear(); }\n", "n",
+               field->lowercase_name());
+      p->Print("$t$* add_$n$() { $n$_.emplace_back(); return &$n$_.back(); }\n",
+               "t", GetCppType(field, false), "n", field->lowercase_name());
+    }
+  }
+  p->Outdent();
+  p->Print("\n private:\n");
+  p->Indent();
+
+  // Generate fields.
+  for (int i = 0; i < msg->field_count(); i++) {
+    const FieldDescriptor* field = msg->field(i);
+    if (!field->is_repeated()) {
+      p->Print("$t$ $n$_ = {};\n", "t", GetCppType(field, false), "n",
+               field->lowercase_name());
+    } else {  // is_repeated()
+      p->Print("std::vector<$t$> $n$_;\n", "t", GetCppType(field, false), "n",
+               field->lowercase_name());
+    }
+  }
+  p->Print("\n");
+  p->Print("// Allows to preserve unknown protobuf fields for compatibility\n");
+  p->Print("// with future versions of .proto files.\n");
+  p->Print("std::string unknown_fields_;\n");
+  p->Outdent();
+  p->Print("};\n\n");
+}
+
+void ProtoToCpp::GenCpp(const Descriptor* msg, Printer* p, std::string prefix) {
+  p->Print("\n");
+  std::string full_name = prefix + msg->name();
+  p->Print("$f$::$n$() = default;\n", "f", full_name, "n", msg->name());
+  p->Print("$f$::~$n$() = default;\n", "f", full_name, "n", msg->name());
+  p->Print("$f$::$n$(const $f$&) = default;\n", "f", full_name, "n",
+           msg->name());
+  p->Print("$f$& $f$::operator=(const $f$&) = default;\n", "f", full_name, "n",
+           msg->name());
+  p->Print("$f$::$n$($f$&&) noexcept = default;\n", "f", full_name, "n",
+           msg->name());
+  p->Print("$f$& $f$::operator=($f$&&) = default;\n", "f", full_name, "n",
+           msg->name());
+
+  p->Print("\n");
+
+  // Comparison operator
+  p->Print("#pragma GCC diagnostic push\n");
+  p->Print("#pragma GCC diagnostic ignored \"-Wfloat-equal\"\n");
+  p->Print("bool $f$::operator==(const $f$& other) const {\n", "f", full_name,
+           "n", msg->name());
+  p->Indent();
+
+  p->Print("return ");
+  for (int i = 0; i < msg->field_count(); i++) {
+    if (i > 0)
+      p->Print("\n && ");
+    const FieldDescriptor* field = msg->field(i);
+    p->Print("($n$_ == other.$n$_)", "n", field->name());
+  }
+  p->Print(";");
+  p->Outdent();
+  p->Print("}\n");
+  p->Print("#pragma GCC diagnostic pop\n\n");
+
+  std::string proto_type = GetFwdDeclType(msg, true);
+
+  // Genrate the FromProto() method definition.
+  p->Print("void $f$::FromProto(const $p$& proto) {\n", "f", full_name, "p",
+           proto_type);
+  p->Indent();
+  for (int i = 0; i < msg->field_count(); i++) {
+    p->Print("\n");
+    const FieldDescriptor* field = msg->field(i);
+    if (!field->is_repeated()) {
+      if (field->type() == FieldDescriptor::TYPE_MESSAGE) {
+        p->Print("$n$_.FromProto(proto.$n$());\n", "n", field->name());
+      } else {
+        p->Print(
+            "static_assert(sizeof($n$_) == sizeof(proto.$n$()), \"size "
+            "mismatch\");\n",
+            "n", field->name());
+        p->Print("$n$_ = static_cast<decltype($n$_)>(proto.$n$());\n", "n",
+                 field->name());
+      }
+    } else {  // is_repeated()
+      p->Print("$n$_.clear();\n", "n", field->name());
+      p->Print("for (const auto& field : proto.$n$()) {\n", "n", field->name());
+      p->Print("  $n$_.emplace_back();\n", "n", field->name());
+      if (field->type() == FieldDescriptor::TYPE_MESSAGE) {
+        p->Print("  $n$_.back().FromProto(field);\n", "n", field->name());
+      } else {
+        p->Print(
+            "static_assert(sizeof($n$_.back()) == sizeof(proto.$n$(0)), \"size "
+            "mismatch\");\n",
+            "n", field->name());
+        p->Print(
+            "  $n$_.back() = static_cast<decltype($n$_)::value_type>(field);\n",
+            "n", field->name());
+      }
+      p->Print("}\n");
+    }
+  }
+  p->Print("unknown_fields_ = proto.unknown_fields();\n");
+  p->Outdent();
+  p->Print("}\n\n");
+
+  // Genrate the ToProto() method definition.
+  p->Print("void $f$::ToProto($p$* proto) const {\n", "f", full_name, "p",
+           proto_type);
+  p->Indent();
+  p->Print("proto->Clear();\n");
+  for (int i = 0; i < msg->field_count(); i++) {
+    p->Print("\n");
+    const FieldDescriptor* field = msg->field(i);
+    if (!field->is_repeated()) {
+      if (field->type() == FieldDescriptor::TYPE_MESSAGE) {
+        p->Print("$n$_.ToProto(proto->mutable_$n$());\n", "n", field->name());
+      } else {
+        p->Print(
+            "static_assert(sizeof($n$_) == sizeof(proto->$n$()), \"size "
+            "mismatch\");\n",
+            "n", field->name());
+        p->Print("proto->set_$n$(static_cast<decltype(proto->$n$())>($n$_));\n",
+                 "n", field->name());
+      }
+    } else {  // is_repeated()
+      p->Print("for (const auto& it : $n$_) {\n", "n", field->name());
+      if (field->type() == FieldDescriptor::TYPE_MESSAGE) {
+        p->Print("  auto* entry = proto->add_$n$();\n", "n", field->name());
+        p->Print("  it.ToProto(entry);\n");
+      } else {
+        p->Print(
+            "  proto->add_$n$(static_cast<decltype(proto->$n$(0))>(it));\n",
+            "n", field->name());
+        p->Print(
+            "static_assert(sizeof(it) == sizeof(proto->$n$(0)), \"size "
+            "mismatch\");\n",
+            "n", field->name());
+      }
+      p->Print("}\n");
+    }
+  }
+  p->Print("*(proto->mutable_unknown_fields()) = unknown_fields_;\n");
+  p->Outdent();
+  p->Print("}\n\n");
+
+  // Recurse into nested types.
+  for (int i = 0; i < msg->field_count(); i++) {
+    const FieldDescriptor* field = msg->field(i);
+
+    if (field->type() == FieldDescriptor::TYPE_MESSAGE &&
+        field->message_type()->file() == msg->file()) {
+      std::string child_prefix = prefix + msg->name() + "::";
+      GenCpp(field->message_type(), p, child_prefix);
+    }
+  }
+}
+
+int main(int argc, char** argv) {
+  if (argc <= 4) {
+    PERFETTO_ELOG(
+        "Usage: %s source.proto dir/for/header dir/for/cc include/path",
+        argv[0]);
+    return 1;
+  }
+  ProtoToCpp proto_to_cpp(argv[2], argv[3], argv[4]);
+  proto_to_cpp.Convert(argv[1]);
+  return 0;
+}
diff --git a/tools/protoc_helper.py b/tools/protoc_helper.py
index 6861009..c937a25 100755
--- a/tools/protoc_helper.py
+++ b/tools/protoc_helper.py
@@ -18,7 +18,16 @@
 import subprocess
 import sys
 
-ROOT_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
+
+def run(encode_or_decode, protoc_path, proto, root, input, output):
+  cmd = [
+      protoc_path,
+      '--{}=perfetto.protos.{}'.format(encode_or_decode, proto),
+      os.path.join(root, 'protos/perfetto/config/trace_config.proto'),
+      os.path.join(root, 'protos/perfetto/trace/trace.proto'),
+      '--proto_path={}/protos'.format(root),
+  ]
+  subprocess.check_call(cmd, stdin=input, stdout=output, stderr=sys.stderr)
 
 
 def main():
@@ -26,33 +35,30 @@
   parser.add_argument(
       'encode_or_decode',
       choices=['encode', 'decode'],
-      help='encode into binary format or decode to text.')
-  parser.add_argument(
-      '--proto_name',
-      default='TraceConfig',
+      help='encode into binary format or decode to text.'
+  )
+  parser.add_argument('--proto_name', default='TraceConfig',
       help='name of proto to encode/decode (default: TraceConfig).')
-  parser.add_argument(
-      '--protoc', default='protoc', help='Path to the protoc executable')
-  parser.add_argument(
-      '--input',
-      default='-',
+  parser.add_argument('--protoc_path', default=None,
+      help='path to protoc')
+  parser.add_argument('--root', default='.',
+      help='root directory (default: "protos")')
+  parser.add_argument('--input', default='-',
       help='input file, or "-" for stdin (default: "-")')
-  parser.add_argument(
-      '--output',
-      default='-',
+  parser.add_argument('--output', default='-',
       help='output file, or "-" for stdout (default: "-")')
   args = parser.parse_args()
 
-  cmd = [
-      args.protoc,
-      '--%s=perfetto.protos.%s' % (args.encode_or_decode, args.proto_name),
-      '--proto_path=%s' % ROOT_DIR,
-      os.path.join(ROOT_DIR, 'protos/perfetto/config/trace_config.proto'),
-      os.path.join(ROOT_DIR, 'protos/perfetto/trace/trace.proto'),
-  ]
-  in_file = sys.stdin if args.input == '-' else open(args.input, 'rb')
-  out_file = sys.stdout if args.output == '-' else open(args.output, 'wb')
-  subprocess.check_call(cmd, stdin=in_file, stdout=out_file, stderr=sys.stderr)
+  encode_or_decode = args.encode_or_decode
+  proto_name = args.proto_name
+  protoc_path =  args.protoc_path
+  root =  args.root
+  input = sys.stdin if args.input == '-' else open(args.input, 'rb')
+  output = sys.stdout if args.output == '-' else open(args.output, 'wb')
+  if not protoc_path:
+    directory = os.path.dirname(__file__)
+    protoc_path = os.path.join(directory, 'gcc_like_host', 'protoc')
+  run(encode_or_decode, protoc_path, proto_name, root, input, output)
   return 0
 
 
diff --git a/tools/protoprofile/BUILD.gn b/tools/protoprofile/BUILD.gn
deleted file mode 100644
index fe31432..0000000
--- a/tools/protoprofile/BUILD.gn
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (C) 2019 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.
-
-import("../../gn/perfetto_host_executable.gni")
-
-perfetto_host_executable("protoprofile") {
-  testonly = true
-  deps = [
-    ":common",
-    "../../gn:default_deps",
-  ]
-}
-
-source_set("common") {
-  testonly = true
-  public_deps = [
-    "../../gn:default_deps",
-    "../../protos/third_party/pprof:lite",
-    "../../src/base",
-    "../../src/protozero",
-  ]
-  sources = [
-    "main.cc",
-  ]
-  deps = [
-    "../../gn:protobuf_full",
-  ]
-}
diff --git a/tools/protoprofile/main.cc b/tools/protoprofile/main.cc
deleted file mode 100644
index f7bad27..0000000
--- a/tools/protoprofile/main.cc
+++ /dev/null
@@ -1,367 +0,0 @@
-#include <algorithm>
-#include <vector>
-
-#include <google/protobuf/compiler/importer.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/protozero/field.h"
-#include "perfetto/protozero/proto_decoder.h"
-#include "perfetto/protozero/proto_utils.h"
-
-#include "protos/third_party/pprof/profile.pb.h"
-
-namespace perfetto {
-namespace protoprofile {
-namespace {
-
-using protozero::proto_utils::ProtoWireType;
-using GLine = ::perfetto::third_party::perftools::profiles::Line;
-using GMapping = ::perfetto::third_party::perftools::profiles::Mapping;
-using GLocation = ::perfetto::third_party::perftools::profiles::Location;
-using GProfile = ::perfetto::third_party::perftools::profiles::Profile;
-using GValueType = ::perfetto::third_party::perftools::profiles::ValueType;
-using GFunction = ::perfetto::third_party::perftools::profiles::Function;
-using GSample = ::perfetto::third_party::perftools::profiles::Sample;
-using ::google::protobuf::Descriptor;
-using ::google::protobuf::DynamicMessageFactory;
-using ::google::protobuf::FieldDescriptor;
-using ::google::protobuf::FileDescriptor;
-using ::google::protobuf::Message;
-using ::google::protobuf::compiler::DiskSourceTree;
-using ::google::protobuf::compiler::Importer;
-using ::google::protobuf::compiler::MultiFileErrorCollector;
-
-class MultiFileErrorCollectorImpl : public MultiFileErrorCollector {
- public:
-  ~MultiFileErrorCollectorImpl() override;
-  void AddError(const std::string& filename,
-                int line,
-                int column,
-                const std::string& message) override;
-
-  void AddWarning(const std::string& filename,
-                  int line,
-                  int column,
-                  const std::string& message) override;
-};
-
-MultiFileErrorCollectorImpl::~MultiFileErrorCollectorImpl() = default;
-
-void MultiFileErrorCollectorImpl::AddError(const std::string& filename,
-                                           int line,
-                                           int column,
-                                           const std::string& message) {
-  PERFETTO_ELOG("Error %s %d:%d: %s", filename.c_str(), line, column,
-                message.c_str());
-}
-
-void MultiFileErrorCollectorImpl::AddWarning(const std::string& filename,
-                                             int line,
-                                             int column,
-                                             const std::string& message) {
-  PERFETTO_ELOG("Error %s %d:%d: %s", filename.c_str(), line, column,
-                message.c_str());
-}
-
-class SizeProfileComputer {
- public:
-  GProfile Compute(const uint8_t* ptr,
-                   size_t size,
-                   const Descriptor* descriptor);
-
- private:
-  struct StackInfo {
-    std::vector<size_t> samples;
-    std::vector<int> locations;
-  };
-
-  void ComputeInner(const uint8_t* ptr,
-                    size_t size,
-                    const Descriptor* descriptor);
-  void Sample(size_t size);
-  int InternString(const std::string& str);
-  int InternLocation(const std::string& str);
-  size_t GetFieldSize(const protozero::Field& f);
-
-  // Convert the current stack into a string:
-  // {"Foo", "#bar", "Bar", "#baz", "int"} -> "Foo$#bar$Bar$#baz$int$"
-  std::string StackToKey();
-
-  // The current 'stack' we're considering as we parse the protobuf.
-  // For example if we're currently looking at the varint field baz which is
-  // nested inside message Bar which is in turn a field named bar on the message
-  // Foo. Then the stack would be: Foo, #bar, Bar, #baz, int
-  // We keep track of both the field names (#bar, #baz) and the field types
-  // (Foo, Bar, int) as sometimes we are intrested in which fields are big
-  // and sometimes which types are big.
-  std::vector<std::string> stack_;
-
-  // Information about each stack seen. Keyed by a unique string for each stack.
-  std::map<std::string, StackInfo> stack_info_;
-
-  // Interned strings:
-  std::vector<std::string> strings_;
-  std::map<std::string, int> string_to_id_;
-
-  // Interned 'locations', each location is a single frame of the stack.
-  std::map<std::string, int> locations_;
-};
-
-size_t SizeProfileComputer::GetFieldSize(const protozero::Field& f) {
-  uint8_t buf[10];
-  switch (f.type()) {
-    case protozero::proto_utils::ProtoWireType::kVarInt:
-      return static_cast<size_t>(
-          protozero::proto_utils::WriteVarInt(f.as_uint64(), buf) - buf);
-    case protozero::proto_utils::ProtoWireType::kLengthDelimited:
-      return f.size();
-    case protozero::proto_utils::ProtoWireType::kFixed32:
-      return 4;
-    case protozero::proto_utils::ProtoWireType::kFixed64:
-      return 8;
-  }
-  PERFETTO_FATAL("unexpected field type");  // for gcc
-}
-
-int SizeProfileComputer::InternString(const std::string& s) {
-  if (string_to_id_.count(s)) {
-    return string_to_id_[s];
-  }
-  strings_.push_back(s);
-  int id = static_cast<int>(strings_.size() - 1);
-  string_to_id_[s] = id;
-  return id;
-}
-
-int SizeProfileComputer::InternLocation(const std::string& s) {
-  if (locations_.count(s)) {
-    return locations_[s];
-  }
-  int id = static_cast<int>(locations_.size()) + 1;
-  locations_[s] = id;
-  return id;
-}
-
-std::string SizeProfileComputer::StackToKey() {
-  std::string key;
-  for (const std::string& part : stack_) {
-    key += part;
-    key += "$";
-  }
-  return key;
-}
-
-void SizeProfileComputer::Sample(size_t size) {
-  const std::string& key = StackToKey();
-
-  if (!stack_info_.count(key)) {
-    StackInfo& info = stack_info_[key];
-    info.locations.resize(stack_.size());
-    for (size_t i = 0; i < stack_.size(); i++) {
-      info.locations[i] = InternLocation(stack_[i]);
-    }
-  }
-
-  stack_info_[key].samples.push_back(size);
-}
-
-GProfile SizeProfileComputer::Compute(const uint8_t* ptr,
-                                      size_t size,
-                                      const Descriptor* descriptor) {
-  PERFETTO_CHECK(InternString("") == 0);
-  ComputeInner(ptr, size, descriptor);
-  GProfile profile;
-
-  GValueType* sample_type;
-
-  sample_type = profile.add_sample_type();
-  sample_type->set_type(InternString("protos"));
-  sample_type->set_unit(InternString("count"));
-
-  sample_type = profile.add_sample_type();
-  sample_type->set_type(InternString("max_size"));
-  sample_type->set_unit(InternString("bytes"));
-
-  sample_type = profile.add_sample_type();
-  sample_type->set_type(InternString("min_size"));
-  sample_type->set_unit(InternString("bytes"));
-
-  sample_type = profile.add_sample_type();
-  sample_type->set_type(InternString("median"));
-  sample_type->set_unit(InternString("bytes"));
-
-  sample_type = profile.add_sample_type();
-  sample_type->set_type(InternString("total_size"));
-  sample_type->set_unit(InternString("bytes"));
-
-  // For each unique stack we've seen write out the stats:
-  for (auto& id_info : stack_info_) {
-    StackInfo& info = id_info.second;
-
-    GSample* sample = profile.add_sample();
-    for (auto it = info.locations.rbegin(); it != info.locations.rend(); ++it) {
-      sample->add_location_id(static_cast<uint64_t>(*it));
-    }
-
-    std::sort(info.samples.begin(), info.samples.end());
-    size_t count = info.samples.size();
-    size_t total_size = 0;
-    size_t max_size = info.samples[count - 1];
-    size_t min_size = info.samples[0];
-    size_t median_size = info.samples[count / 2];
-    for (size_t i = 0; i < count; ++i)
-      total_size += info.samples[i];
-    // These have to be in the same order as the sample types above:
-    sample->add_value(static_cast<int64_t>(count));
-    sample->add_value(static_cast<int64_t>(max_size));
-    sample->add_value(static_cast<int64_t>(min_size));
-    sample->add_value(static_cast<int64_t>(median_size));
-    sample->add_value(static_cast<int64_t>(total_size));
-  }
-
-  // The proto profile has a two step mapping where samples are associated with
-  // locations which in turn are associated to functions. We don't currently
-  // distinguish them so we make a 1:1 mapping between the locations and the
-  // functions:
-  for (const auto& location_id : locations_) {
-    GLocation* location = profile.add_location();
-    location->set_id(static_cast<uint64_t>(location_id.second));
-    GLine* line = location->add_line();
-    line->set_function_id(static_cast<uint64_t>(location_id.second));
-  }
-
-  for (const auto& location_id : locations_) {
-    GFunction* function = profile.add_function();
-    function->set_id(static_cast<uint64_t>(location_id.second));
-    function->set_name(InternString(location_id.first));
-  }
-
-  // Finally the string table. We intern more strings above, so this has to be
-  // last.
-  for (int i = 0; i < static_cast<int>(strings_.size()); i++) {
-    profile.add_string_table(strings_[static_cast<size_t>(i)]);
-  }
-  return profile;
-}
-
-void SizeProfileComputer::ComputeInner(const uint8_t* ptr,
-                                       size_t size,
-                                       const Descriptor* descriptor) {
-  size_t overhead = size;
-  size_t unknown = 0;
-  protozero::ProtoDecoder decoder(ptr, size);
-
-  stack_.push_back(descriptor->name());
-
-  // Compute the size of each sub-field of this message, subtracting it
-  // from overhead and possible adding it to unknown.
-  for (;;) {
-    if (decoder.bytes_left() == 0)
-      break;
-    protozero::Field field = decoder.ReadField();
-    if (!field.valid()) {
-      PERFETTO_ELOG("Field not valid (can mean field id >1000)");
-      break;
-    }
-
-    int id = field.id();
-    ProtoWireType type = field.type();
-    size_t field_size = GetFieldSize(field);
-
-    overhead -= field_size;
-    const FieldDescriptor* field_descriptor = descriptor->FindFieldByNumber(id);
-    if (!field_descriptor) {
-      unknown += field_size;
-      continue;
-    }
-
-    stack_.push_back("#" + field_descriptor->name());
-    bool is_message_type =
-        field_descriptor->type() == FieldDescriptor::TYPE_MESSAGE;
-    if (type == ProtoWireType::kLengthDelimited && is_message_type) {
-      ComputeInner(field.data(), field.size(),
-                   field_descriptor->message_type());
-    } else {
-      stack_.push_back(field_descriptor->type_name());
-      Sample(field_size);
-      stack_.pop_back();
-    }
-    stack_.pop_back();
-  }
-
-  if (unknown) {
-    stack_.push_back("#:unknown:");
-    Sample(unknown);
-    stack_.pop_back();
-  }
-
-  // Anything not blamed on a child is overhead for this message.
-  Sample(overhead);
-  stack_.pop_back();
-}
-
-int PrintUsage(int, const char** argv) {
-  fprintf(stderr, "Usage: %s INPUT_PATH OUTPUT_PATH\n", argv[0]);
-  return 1;
-}
-
-int Main(int argc, const char** argv) {
-  if (argc != 3)
-    return PrintUsage(argc, argv);
-
-  const char* input_path = argv[1];
-  const char* output_path = argv[2];
-
-  base::ScopedFile proto_fd = base::OpenFile(input_path, O_RDONLY);
-  if (!proto_fd) {
-    PERFETTO_ELOG("Could not open input path (%s)", input_path);
-    return 1;
-  }
-
-  std::string s;
-  base::ReadFileDescriptor(proto_fd.get(), &s);
-
-  const Descriptor* descriptor;
-  DiskSourceTree dst;
-  dst.MapPath("", "");
-  MultiFileErrorCollectorImpl mfe;
-  Importer importer(&dst, &mfe);
-  const FileDescriptor* parsed_file =
-      importer.Import("protos/perfetto/trace/trace.proto");
-  DynamicMessageFactory dmf;
-  descriptor = parsed_file->message_type(0);
-
-  const uint8_t* start = reinterpret_cast<const uint8_t*>(s.data());
-  size_t size = s.size();
-
-  if (!descriptor) {
-    PERFETTO_ELOG("Could not parse trace.proto");
-    return 1;
-  }
-
-  base::ScopedFile output_fd =
-      base::OpenFile(output_path, O_WRONLY | O_TRUNC | O_CREAT, 0600);
-  if (!output_fd) {
-    PERFETTO_ELOG("Could not open output path (%s)", output_path);
-    return 1;
-  }
-  SizeProfileComputer computer;
-  GProfile profile = computer.Compute(start, size, descriptor);
-  std::string out;
-  profile.SerializeToString(&out);
-  base::WriteAll(output_fd.get(), out.data(), out.size());
-  base::FlushFile(output_fd.get());
-
-  return 0;
-}
-
-}  // namespace
-}  // namespace protoprofile
-}  // namespace perfetto
-
-int main(int argc, const char** argv) {
-  return perfetto::protoprofile::Main(argc, argv);
-}
diff --git a/tools/pull_ftrace_format_files.py b/tools/pull_ftrace_format_files.py
index be934bc..abf27ac 100755
--- a/tools/pull_ftrace_format_files.py
+++ b/tools/pull_ftrace_format_files.py
@@ -19,6 +19,7 @@
 import os
 import subprocess
 import sys
+
 """Pulls all format files from an Android device.
 
 Usage: ./tools/pull_ftrace_format_files.py [-s serial] [-p directory_prefix]
@@ -27,7 +28,6 @@
 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 ADB_PATH = os.path.join(ROOT_DIR, 'buildtools/android_sdk/platform-tools/adb')
 
-
 def adb(*cmd, **kwargs):
   serial = kwargs.get('serial', None)
   prefix = [ADB_PATH]
@@ -121,13 +121,10 @@
 
 def main():
   parser = argparse.ArgumentParser(description='Pull format files.')
-  parser.add_argument(
-      '-p', dest='prefix', default=None, help='the output directory prefix')
-  parser.add_argument(
-      '-s',
-      dest='serial',
-      default=None,
-      help='use device with the given serial')
+  parser.add_argument('-p', dest='prefix', default=None,
+                      help='the output directory prefix')
+  parser.add_argument('-s', dest='serial', default=None,
+                      help='use device with the given serial')
   args = parser.parse_args()
 
   prefix = args.prefix
@@ -143,4 +140,5 @@
 
 
 if __name__ == '__main__':
-  sys.exit(main())
+    sys.exit(main())
+
diff --git a/tools/run_all_fuzzers b/tools/run_all_fuzzers
new file mode 100755
index 0000000..a3193dd
--- /dev/null
+++ b/tools/run_all_fuzzers
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+# 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.
+
+set -euo pipefail
+
+OUTDIR=out/linux_fuzzer_run
+
+tools/gn gen "$OUTDIR" \
+  --args="is_clang=true is_debug=false is_fuzzer=true is_asan=true" \
+  --check
+
+tools/ninja -C $OUTDIR
+
+FUZZERS=$(cd $OUTDIR && ls *fuzzer)
+
+for fuzzer in $FUZZERS; do
+  mkdir -p "fuzz_out/$fuzzer/corpus"
+  mkdir -p "fuzz_out/$fuzzer/artifacts"
+  for crash in $(ls fuzz_out/$fuzzer/artifacts/crash-* 2> /dev/null); do
+    if "$OUTDIR/$fuzzer" "$crash"; then
+      rm $crash;
+    else
+      echo "$crash still exists"
+    fi
+  done;
+
+  "$OUTDIR/$fuzzer" -artifact_prefix="fuzz_out/$fuzzer/artifacts/" \
+    "fuzz_out/$fuzzer/corpus" 2> "fuzz_out/$fuzzer/log.err" &
+done
+
+for job in `jobs -p`
+do
+    wait $job
+done
diff --git a/tools/run_android_emulator b/tools/run_android_emulator
index 7852919..3a4121a 100755
--- a/tools/run_android_emulator
+++ b/tools/run_android_emulator
@@ -28,33 +28,31 @@
   root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
   if sys.platform.startswith('linux'):
-    emulator_root = os.path.join(root_dir, 'buildtools', 'emulator',
-                                 'linux-x86_64')
+    emulator_root = os.path.join(
+      root_dir, 'buildtools', 'emulator', 'linux-x86_64')
     emulator_path = os.path.join(emulator_root, 'qemu', 'linux-x86_64')
   else:
-    emulator_root = os.path.join(root_dir, 'buildtools', 'emulator',
-                                 'darwin-x86_64')
+    emulator_root = os.path.join(
+      root_dir, 'buildtools', 'emulator', 'darwin-x86_64')
     emulator_path = os.path.join(emulator_root, 'qemu', 'darwin-x86_64')
 
   aosp_path = os.path.join(root_dir, 'buildtools', 'aosp-arm')
 
   env = {
-      # The CI env doesn't set this and causes the emulator to fallback in
+      # Travis CI doesn't set this and causes the emulator to fallback in
       # 32-bit mode with a "Cannot decide host bitness because $SHELL" error.
       'SHELL': '/bin/bash',
       'LD_LIBRARY_PATH': os.path.join(emulator_root, 'lib64', 'qt', 'lib'),
       'DYLD_LIBRARY_PATH': os.path.join(emulator_root, 'lib64', 'qt', 'lib'),
   }
   emulator_bin = os.path.join(emulator_path, 'qemu-system-armel')
-  emulator_args = [
-      '-no-window', '-no-snapshot', '-gpu', 'off', '-no-accel', '-sysdir',
-      aosp_path, '-system',
-      os.path.join(aosp_path, 'system-qemu.img'), '-kernel',
-      os.path.join(aosp_path, 'kernel-ranchu'), '-ramdisk',
-      os.path.join(aosp_path, 'ramdisk.img'), '-vendor',
-      os.path.join(aosp_path, 'vendor-qemu.img'), '-data',
-      os.path.join(aosp_path, 'userdata-qemu.img')
-  ]
+  emulator_args = ['-no-window', '-no-snapshot',  '-gpu', 'off', '-no-accel',
+                   '-sysdir', aosp_path,
+                   '-system', os.path.join(aosp_path, 'system-qemu.img'),
+                   '-kernel', os.path.join(aosp_path, 'kernel-ranchu'),
+                   '-ramdisk', os.path.join(aosp_path, 'ramdisk.img'),
+                   '-vendor', os.path.join(aosp_path, 'vendor-qemu.img'),
+                   '-data', os.path.join(aosp_path, 'userdata-qemu.img')]
   print '\n'.join('='.join(x) for x in env.items())
   print ' '.join([emulator_bin] + emulator_args)
   if args.pid:
diff --git a/tools/run_android_test b/tools/run_android_test
index 27fd273..f22138d 100755
--- a/tools/run_android_test
+++ b/tools/run_android_test
@@ -22,6 +22,8 @@
 import sys
 import tempfile
 import time
+
+
 """ Runs a test executable on Android.
 
 Takes care of pushing the extra shared libraries that might be required by
@@ -51,9 +53,7 @@
       will be raised and falsy values returned to the caller (except when
       returns_falsy='raise').
   """
-
   def Decorator(f):
-
     @functools.wraps(f)
     def Wrapper(*args, **kwargs):
       wait = 1
@@ -77,9 +77,7 @@
       if returns_falsy == 'raise' and not value:
         raise ValueError('%s returned %r' % (f.__name__, value))
       return value
-
     return Wrapper
-
   return Decorator
 
 
@@ -89,13 +87,6 @@
   return subprocess.check_call(cmd)
 
 
-def AdbPush(host, device):
-  cmd = [ADB_PATH, 'push', host, device]
-  print '> adb push ' + ' '.join(cmd[2:])
-  with open(os.devnull) as devnull:
-    return subprocess.check_call(cmd, stdout=devnull)
-
-
 def GetProp(prop):
   cmd = [ADB_PATH, 'shell', 'getprop', prop]
   print '> adb ' + ' '.join(cmd)
@@ -152,36 +143,33 @@
   # This gets linked into our tests via libundwindstack.so.
   #
   # See https://android.googlesource.com/platform/system/core/+/master/rootdir/etc/ld.config.txt.
-  AdbPush(test_bin, "/data/nativetest")
+  AdbCall('push', test_bin, "/data/nativetest")
 
   if not args.no_data_deps:
     for dep in EnumerateDataDeps():
-      AdbPush(os.path.join(ROOT_DIR, dep), target_dir + '/' + dep)
+      AdbCall('push', os.path.join(ROOT_DIR, dep), target_dir + '/' + dep)
 
   # LLVM sanitizers require to sideload a libclangrtXX.so on the device.
   sanitizer_libs = os.path.join(args.out_dir, 'sanitizer_libs')
   env = ' '.join(args.env if args.env is not None else []) + ' '
   if os.path.exists(sanitizer_libs):
-    AdbPush(sanitizer_libs, target_dir)
+    AdbCall('push', sanitizer_libs, target_dir)
     env += 'LD_LIBRARY_PATH="%s/sanitizer_libs" ' % (target_dir)
-  cmd = 'cd %s;' % target_dir
+  cmd = 'cd %s;' % target_dir;
   binary = env + '/data/nativetest/%s' % args.test_name
   cmd += binary
   if args.cmd_args:
     actual_args = [arg.replace(args.test_name, binary) for arg in args.cmd_args]
     cmd += ' ' + ' '.join(actual_args)
+  cmd += ';echo -e "\\nTEST_RET_CODE=$?"'
   print cmd
-  retcode = subprocess.call([ADB_PATH, 'shell', cmd])
+  test_output = subprocess.check_output([ADB_PATH, 'shell', cmd])
+  print test_output
+  retcode = re.search(r'^TEST_RET_CODE=(\d)', test_output, re.MULTILINE)
+  assert retcode, 'Could not find TEST_RET_CODE=N marker'
+  retcode = int(retcode.group(1))
   if not args.no_cleanup:
     AdbCall('shell', 'rm -rf "%s"' % target_dir)
-
-  # Smoke test that adb shell is actually propagating retcode. adb has a history
-  # of breaking this.
-  test_code = subprocess.call([ADB_PATH, 'shell', 'echo Done; exit 42'])
-  if test_code != 42:
-    logging.fatal('adb is incorrectly propagating the exit code')
-    return 1
-
   return retcode
 
 
diff --git a/tools/run_ftrace_proto_gen b/tools/run_ftrace_proto_gen
index c8e9ca7..3e9141f 100755
--- a/tools/run_ftrace_proto_gen
+++ b/tools/run_ftrace_proto_gen
@@ -16,7 +16,7 @@
   fi
 fi
 
-DESCRIPTOR='gen/protos/perfetto/trace/ftrace/ftrace.descriptor'
+DESCRIPTOR='gen/protos/perfetto/trace/ftrace.descriptor'
 "$DIR/ninja" -C "$BUILDDIR" ftrace_proto_gen $DESCRIPTOR
 
 # FIXME(fmayer): make ftrace_proto_gen independent of cwd.
diff --git a/tools/run_test_like_ci b/tools/run_test_like_ci
deleted file mode 100755
index 4f35def..0000000
--- a/tools/run_test_like_ci
+++ /dev/null
@@ -1,168 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2019 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.
-
-from __future__ import print_function
-import argparse
-import distutils
-import errno
-import grp
-import os
-import readline
-import sys
-import shutil
-import subprocess
-from pipes import quote
-from subprocess import check_call
-
-try:
-  from shutil import which as find_executable
-except AttributeError:
-  from distutils.spawn import find_executable
-
-REPO_ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
-sys.path.append(os.path.join(REPO_ROOT, 'infra', 'ci'))
-from config import JOB_CONFIGS, SANDBOX_IMG
-
-try:
-  input = raw_input
-except NameError:
-  pass
-
-
-def user_in_docker_group():
-  try:
-    group = grp.getgrnam('docker')
-  except KeyError:
-    return False
-  else:
-    return group.gr_gid in os.getgroups()
-
-
-def decision(question='Would you like to continue', confirm=True, default='n'):
-  default = default.lower().strip()
-  yes = default in {'y', 'yes'}
-  no = default in {'n', 'no'}
-  default = 'y' if yes else 'n'
-  prompt = '%s? [%s/%s]: ' % (question, 'Y' if yes else 'y', 'N' if no else 'n')
-  if not confirm:
-    print('%sy' % prompt)
-    return
-  while True:
-    choice = input(prompt).lower().strip()
-    if not choice:
-      choice = default
-    if choice in {'y', 'yes'}:
-      return
-    elif choice in {'n', 'no'}:
-      sys.exit(3)
-
-
-def main():
-  parser = argparse.ArgumentParser(
-      formatter_class=argparse.ArgumentDefaultsHelpFormatter)
-  parser.add_argument('config', choices=JOB_CONFIGS.keys())
-  parser.add_argument(
-      '--runner',
-      help='The container runner executable to use',
-      choices=('podman', 'docker'),
-      default='podman' if find_executable('podman') else 'docker')
-  parser.add_argument(
-      '--build',
-      action='store_true',
-      help='Will perform a build of sandbox image')
-  group = parser.add_mutually_exclusive_group()
-  group.add_argument(
-      '--confirm',
-      action='store_true',
-      default=True,
-      help='User confirmation of decision prompts')
-  group.add_argument(
-      '--no-confirm',
-      dest='confirm',
-      action='store_false',
-      help='Forces confirmation of decision prompts')
-  args = parser.parse_args()
-
-  # Check that the directory is clean.
-  git_cmd = ['git', '-C', REPO_ROOT, 'status', '--porcelain']
-  modified_files = subprocess.check_output(git_cmd).decode()
-  if modified_files:
-    print('The current Git repo has modified/untracked files.')
-    print('The sandboxed VM will fetch the HEAD of your current git repo.')
-    print('This is probably not the state you want to be in.')
-    print('I suggest you stop, commit and then re-run this script')
-    print('Modified files:\n' + modified_files)
-    decision('Do you know what you are doing', confirm=args.confirm)
-
-  if args.build:
-    print('')
-    print('About to build %r locally with %r' % (args.image, args.runner))
-    decision(confirm=args.confirm)
-    check_call(('make', '-C', os.path.join(REPO_ROOT, 'infra',
-                                           'ci'),
-                'BUILDER=%s' % args.runner, 'build-sandbox'))
-
-  env = {
-      'PERFETTO_TEST_GIT_REF': 'file:///ci/source',
-  }
-  env.update(JOB_CONFIGS[args.config])
-
-  workdir = os.path.join(REPO_ROOT, 'out', 'tmp.ci')
-  cmd = []
-  if args.runner == 'docker' and not user_in_docker_group():
-    cmd += ['sudo', '--']
-  cmd += [
-      args.runner, 'run', '-it', '--name', 'perfetto_ci', '--cap-add',
-      'SYS_PTRACE', '--rm', '--volume',
-      '%s:/ci/ramdisk' % workdir, '--tmpfs', '/tmp:exec',
-      '--volume=%s:/ci/source:ro' % REPO_ROOT
-  ]
-  for kv in env.items():
-    cmd += ['--env', '%s=%s' % kv]
-  cmd += [SANDBOX_IMG]
-  cmd += [
-      'bash', '-c',
-      'cd /ci/ramdisk; bash /ci/init.sh || sudo -u perfetto -EH bash -i'
-  ]
-
-  print(
-      'About to run\n',
-      ' '.join('\n  ' + c if c.startswith('--') or c == 'bash' else quote(c)
-               for c in cmd))
-  print('')
-  print('The VM will have read-only acess to: %s, mounted as /ci/source' %
-        REPO_ROOT)
-  print('The VM workdir /ci/ramdisk will be mounted into: %s' % workdir)
-  print('The contents of %s will be deleted before starting the VM' % workdir)
-  decision(confirm=args.confirm)
-
-  try:
-    shutil.rmtree(workdir)
-  except EnvironmentError as e:
-    if e.errno == errno.ENOENT:
-      pass
-    elif e.errno == errno.EACCES:
-      print('')
-      print('Removing previous volume %r' % workdir)
-      check_call(('sudo', 'rm', '-r', quote(workdir)))
-    else:
-      raise
-
-  os.makedirs(workdir)
-  os.execvp(cmd[0], cmd)
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/tools/sanitizers_unittests/BUILD.gn b/tools/sanitizers_unittests/BUILD.gn
index be69e1a..72c6c5c 100644
--- a/tools/sanitizers_unittests/BUILD.gn
+++ b/tools/sanitizers_unittests/BUILD.gn
@@ -16,7 +16,7 @@
   testonly = true
   deps = [
     "../../gn:default_deps",
-    "../../gn:gtest_and_gmock",
+    "../../gn:gtest_deps",
   ]
   sources = [
     "sanitizers_unittest.cc",
diff --git a/tools/sanitizers_unittests/sanitizers_unittest.cc b/tools/sanitizers_unittests/sanitizers_unittest.cc
index ee025a9..5f61f2f 100644
--- a/tools/sanitizers_unittests/sanitizers_unittest.cc
+++ b/tools/sanitizers_unittests/sanitizers_unittest.cc
@@ -21,7 +21,7 @@
 
 #include <memory>
 
-#include "test/gtest_and_gmock.h"
+#include "gtest/gtest.h"
 
 namespace perfetto {
 namespace {
@@ -77,8 +77,7 @@
 }
 #endif
 
-// b/141460117: Leak sanitizer tests don't work in debug builds.
-#if defined(LEAK_SANITIZER) && defined(NDEBUG)
+#if defined(LEAK_SANITIZER)
 TEST(SanitizerTests, LSAN_LeakMalloc) {
   EXPECT_DEATH(
       {
@@ -104,7 +103,7 @@
       },
       "LeakSanitizer:.*detected memory leaks");
 }
-#endif  // LEAK_SANITIZER && defined(NDEBUG)
+#endif  // LEAK_SANITIZER
 
 #if defined(UNDEFINED_SANITIZER)
 TEST(SanitizerTests, UBSAN_DivisionByZero) {
diff --git a/tools/screenrecordtest b/tools/screenrecordtest
deleted file mode 100644
index c883c6f..0000000
--- a/tools/screenrecordtest
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/bash
-# Rough script for screenrecord and trace
-# ./screenrecordtest [time limit in seconds - 180 seconds maximum]
-# Runs screenrecord along with a perfetto trace
-
-set -e
-
-time=$1
-if [ "$#" -ne 1 ]; then
-    echo "Usage: $0 SECONDS_TO_RECORD"
-    exit 1
-fi
-timems=`expr $time \* 1000`
-adb shell screenrecord --time-limit $time "/sdcard/tracescr.mp4" & SCRN=$!
-
-adb shell perfetto \
-  -c - --txt \
-  -o /data/misc/perfetto-traces/trace \
-<<<"
-
-buffers: {
-    size_kb: 8960
-    fill_policy: DISCARD
-}
-buffers: {
-    size_kb: 1280
-    fill_policy: DISCARD
-}
-data_sources: {
-    config {
-        name: \"linux.sys_stats\"
-        sys_stats_config {
-            stat_period_ms: 1000
-            stat_counters: STAT_CPU_TIMES
-            stat_counters: STAT_FORK_COUNT
-        }
-    }
-}
-duration_ms: $timems
-
-"
-
-wait $SCRN
-
-adb pull "/sdcard/tracescr.mp4"
-adb pull "/data/misc/perfetto-traces/trace"
diff --git a/tools/test_gen_amalgamated.py b/tools/test_gen_amalgamated.py
deleted file mode 100755
index c153215..0000000
--- a/tools/test_gen_amalgamated.py
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2019 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.
-
-from __future__ import print_function
-
-import os
-import subprocess
-
-from compat import quote
-
-GN_ARGS = ' '.join(
-    quote(s) for s in (
-        'is_debug=false',
-        'is_perfetto_build_generator=true',
-        'is_perfetto_embedder=true',
-        'use_custom_libcxx=false',
-        'enable_perfetto_ipc=true',
-    ))
-
-ROOT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
-
-
-def call(cmd, *args):
-  path = os.path.join('tools', cmd)
-  command = [path] + list(args)
-  print('Running:', ' '.join(quote(c) for c in command))
-  try:
-    return subprocess.check_output(command, cwd=ROOT_DIR).decode()
-  except subprocess.CalledProcessError as e:
-    assert False, 'Command: {} failed'.format(' '.join(command))
-
-
-def check_amalgamated_output():
-  call('gen_amalgamated', '--check', '--quiet')
-
-
-def check_amalgamated_dependencies():
-  os_deps = {}
-  for os_name in ['android', 'linux', 'mac']:
-    gn_args = (' target_os="%s"' % os_name) + GN_ARGS
-    os_deps[os_name] = call('gen_amalgamated', '--gn_args', gn_args, '--out',
-                            'tmp.test_gen_amalgamated', '--dump-deps',
-                            '--quiet').split('\n')
-  for os_name, deps in os_deps.items():
-    for dep in deps:
-      for other_os, other_deps in os_deps.items():
-        if not dep in other_deps:
-          raise AssertionError('Discrepancy in amalgamated build dependencies: '
-                               '%s is missing on %s.' % (dep, other_os))
-
-
-def main():
-  check_amalgamated_output()
-  check_amalgamated_dependencies()
-
-
-if __name__ == '__main__':
-  exit(main())
diff --git a/tools/tmux b/tools/tmux
index 035127f..4f626b7 100755
--- a/tools/tmux
+++ b/tools/tmux
@@ -21,162 +21,77 @@
   TMPDIR=/tmp
 fi
 
-function get_gn_value() {
+function is_monolithic {
   local out=$1
-  local key=$2
-  gn args "$out" --list --short | sed -n -e "s/$key = \"\(.*\)\"/\1/p"
+  gn args $out --list --short | grep 'monolithic_binaries = true' 2>&1 >/dev/null
+  return $?
 }
 
-function is_monolithic() {
+function is_android {
   local out=$1
-  value=$(get_gn_value "$out" "monolithic_binaries")
-  test "$value" == "true"
+  gn args $out --list --short | grep 'target_os = "android"' 2>&1 >/dev/null
+  return $?
 }
 
-function is_android() {
-  local out=$1
-  value=$(get_gn_value "$out" "target_os")
-  test "$value" == "android"
-}
-
-function is_ssh_target() {
-  [[ -n "$SSH_TARGET" ]]
-}
-
-function is_mac() {
-  # shellcheck disable=2251
+function is_mac {
   ! test -d /proc
   return $?
 }
 
-function tmux_ensure_bash() {
-  if [[ $SHELL == *"fish" ]]; then
-    tmux send-keys "bash" Enter
-  fi
-}
-
-function reset_tracing() {
-  if is_android "$OUT"; then
+function reset_tracing {
+  if is_android $OUT; then
     adb shell 'echo 0 > /d/tracing/tracing_on'
   elif ! is_mac; then
-    # shellcheck disable=SC2016
-    local script='
     if [ ! -w /sys/kernel/debug ]; then
       echo "debugfs not accessible, try sudo chown -R $USER /sys/kernel/debug"
-      sudo chown -R "$USER" /sys/kernel/debug
+      sudo chown -R $USER /sys/kernel/debug
     fi
 
     echo 0 > /sys/kernel/debug/tracing/tracing_on
-    '
-
-    if is_ssh_target; then
-      # shellcheck disable=SC2029
-      ssh -t "$SSH_TARGET" "sh -c '$script'"
-    else
-      sh -c "$script"
-    fi
   fi
 }
 
-function adb_supports_push_sync() {
-  adb --help 2>&1 | grep 'push.*\[--sync\]' >/dev/null 2>&1
+function adb_supports_push_sync {
+  adb --help 2>&1 | grep 'push.*\[--sync\]' 2>&1 >/dev/null
 }
 
-function push() {
-  if is_android "$OUT"; then
+function push {
+  if is_android $OUT; then
     local maybe_sync=''
     if adb_supports_push_sync; then
-      maybe_sync='--sync'
+      maybe_sync='--sync '
     fi
-    echo adb push $maybe_sync "$1" "$DIR"
-    adb push $maybe_sync "$1" "$DIR"
-  elif is_ssh_target; then
-    echo scp "$1" "$SSH_TARGET:$DIR"
-    scp "$1" "$SSH_TARGET:$DIR"
+    echo adb push $maybe_sync $1 $DIR
+    adb push $maybe_sync $1 $DIR
   else
-    echo cp "$1" "$DIR"
-    cp "$1" "$DIR"
+    echo cp $1 $DIR
+    cp $1 $DIR
   fi
 }
 
-function pull() {
-  if is_android "$OUT"; then
-    echo adb pull "$DIR/$1" "$2"
-    adb pull "$DIR/$1" "$2"
-  elif is_ssh_target; then
-    echo scp "$SSH_TARGET:$DIR/$1" "$2"
-    scp "$SSH_TARGET:$DIR/$1" "$2"
+function pull {
+  if is_android $OUT; then
+    echo adb pull $DIR/$1 $2
+    adb pull $DIR/$1 $2
   else
-    echo mv "$DIR/$1" "$2"
-    mv "$DIR/$1" "$2"
+    echo mv $DIR/$1 $2
+    mv $DIR/$1 $2
   fi
 }
 
-BACKGROUND=0
-SKIP_CONVERTERS=0
-TMUX_LAYOUT="even-vertical"
-CPU_MASK=""
+background=0
 
-while getopts "bl:nt:c:C:z:s:" o; do
+while getopts b o; do
   case "$o" in
-    b) BACKGROUND=1 ;;
-    l) TMUX_LAYOUT=${OPTARG} ;;
-    n) SKIP_CONVERTERS=1 ;;
-    t) SSH_TARGET=${OPTARG} ;;
-    c) CONFIG=${OPTARG} ;;
-    C) OUT=${OPTARG} ;;
-    z) CPU_MASK=${OPTARG} ;;
-    s) SCRIPT=${OPTARG} ;;
-    *)
-      echo >&2 "Invalid option $o"
-      exit
-      ;;
+    b) background=1;;
+    *) echo "Invalid option $o"; exit;;
   esac
 done
 
-# Allow out to be passed as argument
-shift $((OPTIND - 1))
-OUT="${OUT:-$1}"
-
-# Provide useful usage information
-if [ -z "$OUT" ]; then
-  echo "Usage: $0 [OPTION]... [OUTPUT]"
-  echo ""
-  echo "Options:"
-  echo "  -b          run in the background"
-  echo "  -l LAYOUT   tmux pane layout"
-  echo "  -n          skip post-trace convertors"
-  echo "  -t TARGET   SSH device target"
-  echo "  -c CONFIG   trace configuration file"
-  echo "  -C OUTPUT   output directory"
-  echo "  -z MASK     constrain binaries to given cpu mask (taskset syntax)"
-  echo "  -s SCRIPT   a script to put into a tmux pane"
-  echo ""
-  echo "Environment variables:"
-  echo "  SSH_TARGET  SSH device target"
-  echo "  CONFIG      trace configuration file"
-  echo "  OUT         output directory"
-  exit 1
-fi
-
-# Warn about invalid output directories
+# If not set guess the OUT dir using the latest directory.
 if [ ! -f "$OUT/args.gn" ]; then
-  echo >&2 "OUT=$OUT doesn't look like an output directory."
-  echo >&2 "Please specify a directory by doing:"
-  echo >&2 "  export OUT=out/xxx $0"
-  exit 1
-fi
-
-# Check SSH target is valid
-if is_ssh_target && ! ssh -q "$SSH_TARGET" exit; then
-  echo >&2 "SSH_TARGET=$SSH_TARGET doesn't look like a valid SSH target."
-  echo >&2 "Please specify a SSH cross-compilation target by doing:"
-  echo >&2 "  export SSH_TARGET=<user>@<host> $0"
-  exit 1
-fi
-
-if ! builtin type -P tmux &>/dev/null; then
-  echo >&2 "tmux not found"
+  echo "OUT=$OUT doesn't look like an output directory."
+  echo "Please specify a directory by doing: export OUT=out/xxx"
   exit 1
 fi
 
@@ -184,70 +99,60 @@
 # CONFIG=ftrace.cfg or to :test. Defaults to :test.
 CONFIG="${CONFIG:-:test}"
 
-if is_android "$OUT"; then
+if is_android $OUT ; then
   DIR=/data/local/tmp
-elif is_ssh_target; then
-  DIR=$(ssh "$SSH_TARGET" mktemp -d $TMPDIR/perfetto.XXXXXX)
 elif is_mac; then
   DIR=$(mktemp -d $TMPDIR/perfetto.XXXXXX)
 else
   DIR=$(mktemp -p $TMPDIR -d perfetto.XXXXXX)
 fi
 
-tools/ninja -C "$OUT" traced traced_probes perfetto trace_to_text test/configs
+tools/ninja -C $OUT traced traced_probes perfetto trace_to_text test/configs
 
-push "$OUT/traced"
-push "$OUT/traced_probes"
-push "$OUT/perfetto"
+push $OUT/traced
+push $OUT/traced_probes
+push $OUT/perfetto
 reset_tracing
 
-if is_android "$OUT"; then
+if is_android $OUT; then
   PREFIX="PERFETTO_CONSUMER_SOCK_NAME=@perfetto_test_consumer PERFETTO_PRODUCER_SOCK_NAME=@perfetto_test_producer"
 else
   PREFIX=""
 fi
 
-if ! is_monolithic "$OUT"; then
+if ! is_monolithic $OUT; then
   PREFIX="$PREFIX LD_LIBRARY_PATH=$DIR"
-  push "$OUT/libperfetto.so"
+  push $OUT/libperfetto.so
 fi
 
 CONFIG_DEVICE_PATH="$CONFIG"
 CMD_OPTS=""
 if [[ "$CONFIG" == *.protobuf ]]; then
   CONFIG_DEVICE_PATH="$CONFIG"
-  CONFIG_PATH=$OUT/$CONFIG
+  CONFIG_PATH=$OUT/$CONFIG;
   if [[ ! -f $CONFIG_PATH ]]; then
-    echo >&2 "Config \"$CONFIG_PATH\" not known."
+    echo 'Config "'$CONFIG_PATH'" not known.'
     exit 1
   fi
-  push "$CONFIG_PATH"
+  push $CONFIG_PATH
 elif [[ "$CONFIG" != ":test" ]]; then
-  CONFIG_DEVICE_PATH="$(basename "$CONFIG")"
+  CONFIG_DEVICE_PATH="$(basename $CONFIG)"
   CONFIG_PATH=test/configs/$CONFIG
   # Check if this is a valid absolute path
   if [[ ! -f $CONFIG_PATH ]]; then
     CONFIG_PATH=$CONFIG
     if [[ ! -f $CONFIG_PATH ]]; then
-      echo >&2 "Config \"$CONFIG\" not known."
+      echo 'Config "'$CONFIG'" not known.'
       exit 1
     fi
   fi
   CMD_OPTS="--txt $CMD_OPTS"
-  push "$CONFIG_PATH"
-fi
-
-if [[ -f "$SCRIPT" ]]; then
-  push "$SCRIPT"
+  push $CONFIG_PATH
 fi
 
 POSTFIX=""
 
-if [[ -n "$CPU_MASK" ]]; then
-  PREFIX="$PREFIX taskset $CPU_MASK"
-fi
-
-if [[ BACKGROUND -eq 1 ]]; then
+if [[ background -eq 1 ]]; then
   PREFIX="$PREFIX nohup"
   POSTFIX=" &> /dev/null &"
 fi
@@ -269,104 +174,62 @@
 tmux split-window -v
 tmux split-window -v
 
-if [[ -n "$SCRIPT" ]]; then
-  tmux split-window -v
-fi
-
-tmux select-layout "${TMUX_LAYOUT}"
+tmux select-layout even-vertical
 
 tmux select-pane -t 0
 tmux send-keys "clear" C-m
-if is_android "$OUT"; then
+if is_android $OUT; then
   tmux send-keys "adb shell" C-m
 fi
 
 tmux select-pane -t 1
 tmux send-keys "clear" C-m
-if is_android "$OUT"; then
+if is_android $OUT; then
   tmux send-keys "adb shell" C-m
 fi
 
 tmux select-pane -t 2
 tmux send-keys "clear" C-m
-if is_android "$OUT"; then
+if is_android $OUT; then
   tmux send-keys "adb shell" C-m
 fi
 
-if [[ -n "$SCRIPT" ]]; then
-  tmux select-pane -t 3
-  tmux send-keys "clear" C-m
-  if is_android "$OUT"; then
-    tmux send-keys "adb shell" C-m
-  fi
-fi
-
 sleep 2
 
 tmux select-pane -t 1
-if is_ssh_target; then
-  tmux send-keys "ssh $SSH_TARGET" Enter
-fi
-tmux_ensure_bash
-tmux send-keys "PS1='[traced]$ '" Enter
+tmux send-keys "PS1='[traced_probes]$ '" Enter
 tmux send-keys "cd $DIR" Enter
-tmux send-keys "clear" C-m
 tmux send-keys "$PREFIX ./traced $POSTFIX" Enter
 
 tmux select-pane -t 0
-if is_ssh_target; then
-  tmux send-keys "ssh $SSH_TARGET" Enter
-fi
-tmux_ensure_bash
-tmux send-keys "PS1='[traced_probes]$ '" Enter
+tmux send-keys "PS1='[traced]$ '" Enter
 tmux send-keys "cd $DIR" Enter
-tmux send-keys "clear" C-m
-tmux send-keys "$PREFIX ./traced_probes $POSTFIX" Enter
+tmux send-keys "$PREFIX PERFETTO_METATRACE_FILE=mtrace ./traced_probes $POSTFIX" Enter
 
 tmux select-pane -t 2
-if is_ssh_target; then
-  tmux send-keys "ssh $SSH_TARGET" Enter
-fi
-tmux_ensure_bash
 tmux send-keys "PS1='[consumer]$ '" Enter
 tmux send-keys "cd $DIR" Enter
-tmux send-keys "clear" C-m
 tmux send-keys "$PREFIX ./perfetto $CMD_OPTS -c $CONFIG_DEVICE_PATH -o trace $POSTFIX"
 
-if [[ -n "$SCRIPT" ]]; then
-  tmux select-pane -t 3
-  if is_ssh_target; then
-    tmux send-keys "ssh $SSH_TARGET" Enter
-  fi
-  tmux_ensure_bash
-  tmux send-keys "PS1='[script]$ '" Enter
-  tmux send-keys "cd $DIR" Enter
-  tmux send-keys "clear" C-m
-  if [[ -f "$SCRIPT" ]]; then
-    tmux send-keys "./$(basename "$SCRIPT")"
-  else
-    tmux send-keys "$SCRIPT"
-  fi
-fi
-
 # Select consumer pane.
 tmux select-pane -t 2
 
 tmux -2 attach-session -t demo
-if [[ BACKGROUND -eq 1 ]]; then
-  exit 0
+if [[ background -eq 1 ]]; then
+  exit 0;
 fi
 
 reset_tracing
 
 TRACE=$HOME/Downloads/trace
-echo -e "\n\x1b[32mPulling trace into $TRACE.protobuf\x1b[0m"
-pull trace "$TRACE.protobuf"
-
-if [[ SKIP_CONVERTERS -eq 0 ]]; then
-  echo -e "\n\x1b[32mPulling trace into $TRACE.pbtext\x1b[0m"
-  "$OUT/trace_to_text" text <"$TRACE.protobuf" >"$TRACE.pbtext"
-  echo -e "\n\x1b[32mPulling trace into $TRACE.json\x1b[0m"
-  "$OUT/trace_to_text" systrace <"$TRACE.protobuf" >"$TRACE.json"
-  # Keep this last so it can fail.
-fi
+pull trace /tmp/trace.protobuf
+echo -e "\n\x1b[32mPulling trace into $TRACE.pbtext\x1b[0m"
+$OUT/trace_to_text text < /tmp/trace.protobuf > $TRACE.pbtext
+echo -e "\n\x1b[32mPulling trace into $TRACE.json\x1b[0m"
+$OUT/trace_to_text systrace < /tmp/trace.protobuf > $TRACE.json
+# Keep this last so it can fail.
+pull mtrace /tmp/mtrace.json
+# Add [ to beginning of file and replace trailing , with ] to turn into valid
+# JSON array.
+sed -i -e '$ s/.$/]/' /tmp/mtrace.json
+sed -i -e '1s/^/[/' /tmp/mtrace.json
diff --git a/tools/trace_processor b/tools/trace_processor
deleted file mode 100755
index e85568e..0000000
--- a/tools/trace_processor
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2019 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 file should do the same thing when being invoked in any of these ways:
-# ./trace_processor
-# python trace_processor
-# bash trace_processor
-# cat ./trace_processor | bash
-# cat ./trace_processor | python -
-
-BASH_FALLBACK = """ "
-exec python - "$@" <<'#'EOF
-#"""
-
-import hashlib
-import os
-import sys
-import tempfile
-import urllib
-
-TRACE_PROCESSOR_SHELL_SHAS = {
-    'linux': 'dc506737a39264232609261f235caecf7e1cb4e6',
-    'mac': '54c84c12d15a89e2b83a2be6e25d1d799f4ed93b',
-}
-TRACE_PROCESSOR_SHELL_PATH = tempfile.gettempdir()
-TRACE_PROCESSOR_SHELL_BASE_URL = ('https://storage.googleapis.com/perfetto/')
-
-
-def check_hash(file_name, sha_value):
-  with open(file_name, 'rb') as fd:
-    file_hash = hashlib.sha1(fd.read()).hexdigest()
-    return file_hash == sha_value
-
-
-def load_trace_processor_shell(platform):
-  sha_value = TRACE_PROCESSOR_SHELL_SHAS[platform]
-  file_name = 'trace_processor_shell-' + platform + '-' + sha_value
-  local_file = os.path.join(TRACE_PROCESSOR_SHELL_PATH, file_name)
-
-  if os.path.exists(local_file):
-    if not check_hash(local_file, sha_value):
-      os.remove(local_file)
-    else:
-      return local_file
-
-  url = TRACE_PROCESSOR_SHELL_BASE_URL + file_name
-  urllib.urlretrieve(url, local_file)
-  if not check_hash(local_file, sha_value):
-    os.remove(local_file)
-    raise ValueError("Invalid signature.")
-  os.chmod(local_file, 0o755)
-  return local_file
-
-
-def main(argv):
-  platform = None
-  if sys.platform.startswith('linux'):
-    platform = 'linux'
-  elif sys.platform.startswith('darwin'):
-    platform = 'mac'
-  else:
-    print("Invalid platform: {}".format(sys.platform))
-    return 1
-
-  trace_processor_shell_binary = load_trace_processor_shell(platform)
-  os.execv(trace_processor_shell_binary,
-           [trace_processor_shell_binary] + argv[1:])
-
-
-if __name__ == '__main__':
-  sys.exit(main(sys.argv))
-
-#EOF
diff --git a/tools/trace_to_text/BUILD.gn b/tools/trace_to_text/BUILD.gn
index 5ddea68..94f1c06 100644
--- a/tools/trace_to_text/BUILD.gn
+++ b/tools/trace_to_text/BUILD.gn
@@ -13,149 +13,38 @@
 # limitations under the License.
 
 import("../../gn/perfetto.gni")
-import("../../gn/perfetto_host_executable.gni")
+import("../../gn/proto_library.gni")
 import("../../gn/wasm.gni")
 
-perfetto_host_executable("trace_to_text") {
-  testonly = true
-  deps = [
-    ":full",
-    "../../gn:default_deps",
-  ]
-}
-
-# This is just to check that we can build a version of trace_to_text against
-# libprotobuf-lite. This configuration is only used by WASM. Unfortunately,
-# however, the WASM linker is very permissive and failures show up only when
-# loading the executable in the browser.
-perfetto_host_executable("trace_to_text_lite") {
-  testonly = true
-  deps = [
-    ":lite",
-    "../../gn:default_deps",
-  ]
-}
-
-source_set("utils") {
-  deps = [
-    ":symbolizer",
-  ]
+# The core source files that are used both by the "full" version (the host
+# executable) and by the "lite" version (the WASM module for the UI).
+source_set("common") {
   public_deps = [
     "../../gn:default_deps",
-    "../../gn:zlib",
     "../../include/perfetto/base",
-    "../../include/perfetto/ext/base",
-    "../../include/perfetto/ext/traced:sys_stats_counters",
+    "../../include/perfetto/trace_processor:trace_processor",
+    "../../include/perfetto/traced:sys_stats_counters",
     "../../protos/perfetto/trace:lite",
     "../../protos/perfetto/trace/ftrace:lite",
-    "../../protos/perfetto/trace/interned_data:lite",
-    "../../protos/perfetto/trace/profiling:lite",
-    "../../src/trace_processor:lib",
-  ]
-  sources = [
-    "utils.cc",
-    "utils.h",
-  ]
-}
-
-source_set("local_symbolizer") {
-  public_deps = [
-    ":symbolizer",
-    ":utils",
-    "../../gn:default_deps",
-    "../../include/perfetto/base",
-    "../../include/perfetto/ext/base",
-    "../../include/perfetto/protozero",
-    "../../protos/perfetto/trace:lite",
-    "../../protos/perfetto/trace:zero",
-    "../../protos/perfetto/trace/interned_data:lite",
-    "../../protos/perfetto/trace/profiling:lite",
-  ]
-  sources = [
-    "local_symbolizer.cc",
-    "local_symbolizer.h",
-  ]
-}
-
-source_set("symbolizer") {
-  public_deps = [
-    "../../gn:default_deps",
-    "../../include/perfetto/base",
-    "../../include/perfetto/ext/base",
-    "../../include/perfetto/profiling:symbolizer",
-    "../../include/perfetto/protozero",
-    "../../protos/perfetto/trace:lite",
-    "../../protos/perfetto/trace:zero",
-    "../../protos/perfetto/trace/interned_data:lite",
-    "../../protos/perfetto/trace/profiling:lite",
-  ]
-  sources = [
-    "symbolizer.cc",
-  ]
-}
-
-source_set("pprofbuilder") {
-  deps = [
-    ":symbolizer",
-    ":utils",
-    "../../gn:default_deps",
-    "../../include/perfetto/base",
-    "../../include/perfetto/profiling:symbolizer",
-    "../../protos/perfetto/trace:lite",
     "../../protos/perfetto/trace/profiling:lite",
     "../../protos/third_party/pprof:lite",
     "../../src/base",
     "../../src/trace_processor:lib",
   ]
   sources = [
-    "pprof_builder.cc",
-  ]
-}
-
-# Exposed in bazel builds.
-static_library("libpprofbuilder") {
-  complete_static_lib = true
-  deps = [
-    ":pprofbuilder",
-  ]
-}
-
-# The core source files that are used both by the "full" version (the host
-# executable) and by the "lite" version (the WASM module for the UI).
-source_set("common") {
-  deps = [
-    ":local_symbolizer",
-    ":pprofbuilder",
-    ":symbolizer",
-    ":utils",
-  ]
-  public_deps = [
-    "../../gn:default_deps",
-    "../../include/perfetto/base",
-    "../../include/perfetto/ext/traced:sys_stats_counters",
-    "../../include/perfetto/protozero",
-    "../../protos/perfetto/trace:lite",
-    "../../protos/perfetto/trace:zero",
-    "../../protos/perfetto/trace/ftrace:lite",
-    "../../protos/perfetto/trace/interned_data:lite",
-    "../../protos/perfetto/trace/profiling:lite",
-    "../../src/base",
-    "../../src/trace_processor:lib",
-  ]
-  sources = [
     "main.cc",
-    "symbolize_profile.cc",
-    "symbolize_profile.h",
-    "trace_to_json.cc",
-    "trace_to_json.h",
     "trace_to_profile.cc",
     "trace_to_profile.h",
     "trace_to_systrace.cc",
     "trace_to_systrace.h",
     "trace_to_text.h",
+    "utils.cc",
+    "utils.h",
   ]
-  if (enable_perfetto_version_gen) {
-    deps += [ "//gn/standalone:gen_git_revision" ]
+  if (perfetto_build_standalone) {
+    deps = [
+      "../../gn/standalone:gen_git_revision",
+    ]
   }
 }
 
@@ -170,15 +59,13 @@
   ]
 }
 
-# Full target for the host. Depends on libprotobuf-full.
+# Full traget for the host. Depends on libprotobuf-full.
 source_set("full") {
   testonly = true
   deps = [
     ":common",
-    ":utils",
     "../../gn:default_deps",
-    "../../gn:protobuf_full",
-    "../../gn:zlib",
+    "../../gn:protobuf_full_deps",
   ]
   sources = [
     "proto_full_utils.cc",
@@ -187,6 +74,25 @@
   ]
 }
 
+if (current_toolchain == host_toolchain) {
+  executable("trace_to_text_host") {
+    testonly = true
+    deps = [
+      ":full",
+      "../../gn:default_deps",
+    ]
+  }
+
+  # WASM is too permissive, build a normal version of the binary to test for
+  # missing symbols.
+  executable("trace_to_text_lite_host") {
+    deps = [
+      ":lite",
+      "../../gn:default_deps",
+    ]
+  }
+}
+
 wasm_lib("trace_to_text_wasm") {
   name = "trace_to_text"
   deps = [
@@ -194,3 +100,21 @@
     "../../gn:default_deps",
   ]
 }
+
+# The one for the android tree is defined in the top-level BUILD.gn.
+if (!perfetto_build_with_android) {
+  copy("trace_to_text") {
+    testonly = true
+    host_out_dir_ =
+        get_label_info(":trace_to_text_host($host_toolchain)", "root_out_dir")
+    deps = [
+      ":trace_to_text_host($host_toolchain)",
+    ]
+    sources = [
+      "${host_out_dir_}/trace_to_text_host",
+    ]
+    outputs = [
+      "${root_out_dir}/trace_to_text",
+    ]
+  }
+}
diff --git a/tools/trace_to_text/local_symbolizer.cc b/tools/trace_to_text/local_symbolizer.cc
deleted file mode 100644
index 3daa0be..0000000
--- a/tools/trace_to_text/local_symbolizer.cc
+++ /dev/null
@@ -1,408 +0,0 @@
-
-/*
- * Copyright (C) 2019 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 "perfetto/base/build_config.h"
-
-// This translation unit is built only on Linux. See //gn/BUILD.gn.
-#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
-
-#include "tools/trace_to_text/local_symbolizer.h"
-
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/utils.h"
-
-#include <elf.h>
-#include <inttypes.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-namespace perfetto {
-namespace trace_to_text {
-
-namespace {
-
-std::vector<std::string> GetLines(FILE* f) {
-  std::vector<std::string> lines;
-  size_t n = 0;
-  char* line = nullptr;
-  ssize_t rd = 0;
-  do {
-    rd = getline(&line, &n, f);
-    // Do not read empty line that terminates the output.
-    if (rd > 1) {
-      // Remove newline character.
-      PERFETTO_DCHECK(line[rd - 1] == '\n');
-      line[rd - 1] = '\0';
-      lines.emplace_back(line);
-    }
-    free(line);
-    line = nullptr;
-    n = 0;
-  } while (rd > 1);
-  return lines;
-}
-
-
-struct Elf32 {
-  using Ehdr = Elf32_Ehdr;
-  using Shdr = Elf32_Shdr;
-  using Nhdr = Elf32_Nhdr;
-};
-
-struct Elf64 {
-  using Ehdr = Elf64_Ehdr;
-  using Shdr = Elf64_Shdr;
-  using Nhdr = Elf64_Nhdr;
-};
-
-template <typename E>
-typename E::Shdr* GetShdr(void* mem, const typename E::Ehdr* ehdr, size_t i) {
-  return reinterpret_cast<typename E::Shdr*>(
-      static_cast<char*>(mem) + ehdr->e_shoff + i * sizeof(typename E::Shdr));
-}
-
-bool InRange(const void* base,
-             size_t total_size,
-             const void* ptr,
-             size_t size) {
-  return ptr >= base && static_cast<const char*>(ptr) + size <=
-                            static_cast<const char*>(base) + total_size;
-}
-
-template <typename E>
-base::Optional<std::string> GetBuildId(void* mem, size_t size) {
-  const typename E::Ehdr* ehdr = static_cast<typename E::Ehdr*>(mem);
-  if (!InRange(mem, size, ehdr, sizeof(typename E::Ehdr))) {
-    PERFETTO_ELOG("Corrupted ELF.");
-    return base::nullopt;
-  }
-  for (size_t i = 0; i < ehdr->e_shnum; ++i) {
-    typename E::Shdr* shdr = GetShdr<E>(mem, ehdr, i);
-    if (!InRange(mem, size, shdr, sizeof(typename E::Shdr))) {
-      PERFETTO_ELOG("Corrupted ELF.");
-      return base::nullopt;
-    }
-
-    if (shdr->sh_type != SHT_NOTE)
-      continue;
-
-    auto offset = shdr->sh_offset;
-    while (offset < shdr->sh_offset + shdr->sh_size) {
-      typename E::Nhdr* nhdr =
-          reinterpret_cast<typename E::Nhdr*>(static_cast<char*>(mem) + offset);
-
-      if (!InRange(mem, size, nhdr, sizeof(typename E::Nhdr))) {
-        PERFETTO_ELOG("Corrupted ELF.");
-        return base::nullopt;
-      }
-      if (nhdr->n_type == NT_GNU_BUILD_ID && nhdr->n_namesz == 4) {
-        char* name = reinterpret_cast<char*>(nhdr) + sizeof(*nhdr);
-        if (!InRange(mem, size, name, 4)) {
-          PERFETTO_ELOG("Corrupted ELF.");
-          return base::nullopt;
-        }
-        if (memcmp(name, "GNU", 3) == 0) {
-          const char* value = reinterpret_cast<char*>(nhdr) + sizeof(*nhdr) +
-                              base::AlignUp<4>(nhdr->n_namesz);
-
-          if (!InRange(mem, size, value, nhdr->n_descsz)) {
-            PERFETTO_ELOG("Corrupted ELF.");
-            return base::nullopt;
-          }
-          return std::string(value, nhdr->n_descsz);
-        }
-      }
-      offset += sizeof(*nhdr) + base::AlignUp<4>(nhdr->n_namesz) +
-                base::AlignUp<4>(nhdr->n_descsz);
-    }
-  }
-  return base::nullopt;
-}
-
-class ScopedMmap {
- public:
-  ScopedMmap(void* addr,
-             size_t length,
-             int prot,
-             int flags,
-             int fd,
-             off_t offset)
-      : length_(length), ptr_(mmap(addr, length, prot, flags, fd, offset)) {}
-  ~ScopedMmap() {
-    if (ptr_ != MAP_FAILED)
-      munmap(ptr_, length_);
-  }
-
-  void* operator*() { return ptr_; }
-
- private:
-  size_t length_;
-  void* ptr_;
-};
-
-bool ParseLine(std::string line, std::string* file_name, uint32_t* line_no) {
-  base::StringSplitter sp(std::move(line), ':');
-  if (!sp.Next())
-    return false;
-  *file_name = sp.cur_token();
-  if (!sp.Next())
-    return false;
-  char* endptr;
-  auto parsed_line_no = strtoll(sp.cur_token(), &endptr, 10);
-  if (parsed_line_no >= 0)
-    *line_no = static_cast<uint32_t>(parsed_line_no);
-  return *endptr == '\0' && parsed_line_no >= 0;
-}
-
-std::string SplitBuildID(const std::string& hex_build_id) {
-  if (hex_build_id.size() < 3) {
-    PERFETTO_DFATAL_OR_ELOG("Invalid build-id (< 3 char) %s",
-                            hex_build_id.c_str());
-    return {};
-  }
-
-  return hex_build_id.substr(0, 2) + "/" + hex_build_id.substr(2);
-}
-
-}  // namespace
-
-base::Optional<std::string> LocalBinaryFinder::FindBinary(
-    const std::string& abspath,
-    const std::string& build_id) {
-  auto p = cache_.emplace(abspath, base::nullopt);
-  if (!p.second)
-    return p.first->second;
-
-  base::Optional<std::string>& cache_entry = p.first->second;
-
-  for (const std::string& root_str : roots_) {
-    cache_entry = FindBinaryInRoot(root_str, abspath, build_id);
-    if (cache_entry)
-      return cache_entry;
-  }
-  PERFETTO_ELOG("Could not find %s (Build ID: %s).", abspath.c_str(),
-                base::ToHex(build_id).c_str());
-  return cache_entry;
-}
-
-bool LocalBinaryFinder::IsCorrectFile(const std::string& symbol_file,
-                                      const std::string& build_id) {
-  base::ScopedFile fd(base::OpenFile(symbol_file, O_RDONLY));
-  if (!fd)
-    return false;
-
-  struct stat statbuf;
-  if (fstat(*fd, &statbuf) == -1)
-    return false;
-
-  size_t size = static_cast<size_t>(statbuf.st_size);
-
-  if (size <= EI_CLASS)
-    return false;
-
-  ScopedMmap map(nullptr, size, PROT_READ, MAP_PRIVATE, *fd, 0);
-  if (*map == MAP_FAILED) {
-    PERFETTO_PLOG("mmap");
-    return false;
-  }
-  char* mem = static_cast<char*>(*map);
-
-  if (mem[EI_MAG0] != ELFMAG0 || mem[EI_MAG1] != ELFMAG1 ||
-      mem[EI_MAG2] != ELFMAG2 || mem[EI_MAG3] != ELFMAG3) {
-    return false;
-  }
-
-  switch (mem[EI_CLASS]) {
-    case ELFCLASS32:
-      return build_id == GetBuildId<Elf32>(mem, size);
-    case ELFCLASS64:
-      return build_id == GetBuildId<Elf64>(mem, size);
-    default:
-      return false;
-  }
-}
-
-base::Optional<std::string> LocalBinaryFinder::FindBinaryInRoot(
-    const std::string& root_str,
-    const std::string& abspath,
-    const std::string& build_id) {
-  constexpr char kApkPrefix[] = "base.apk!";
-
-  std::string filename;
-  std::string dirname;
-
-  for (base::StringSplitter sp(abspath, '/'); sp.Next();) {
-    if (!dirname.empty())
-      dirname += "/";
-    dirname += filename;
-    filename = sp.cur_token();
-  }
-
-  // Return the first match for the following options:
-  // * absolute path of library file relative to root.
-  // * absolute path of library file relative to root, but with base.apk!
-  //   removed from filename.
-  // * only filename of library file relative to root.
-  // * only filename of library file relative to root, but with base.apk!
-  //   removed from filename.
-  // * in the subdirectory .build-id: the first two hex digits of the build-id
-  //   as subdirectory, then the rest of the hex digits, with ".debug"appended.
-  //   See
-  //   https://fedoraproject.org/wiki/RolandMcGrath/BuildID#Find_files_by_build_ID
-  //
-  // For example, "/system/lib/base.apk!foo.so" with build id abcd1234,
-  // is looked for at
-  // * $ROOT/system/lib/base.apk!foo.so
-  // * $ROOT/system/lib/foo.so
-  // * $ROOT/base.apk!foo.so
-  // * $ROOT/foo.so
-  // * $ROOT/.build-id/ab/cd1234.debug
-
-  std::string symbol_file = root_str + "/" + dirname + "/" + filename;
-  if (access(symbol_file.c_str(), F_OK) == 0 &&
-      IsCorrectFile(symbol_file, build_id))
-    return {symbol_file};
-
-  if (filename.find(kApkPrefix) == 0) {
-    symbol_file =
-        root_str + "/" + dirname + "/" + filename.substr(sizeof(kApkPrefix));
-    if (access(symbol_file.c_str(), F_OK) == 0 &&
-        IsCorrectFile(symbol_file, build_id))
-      return {symbol_file};
-  }
-
-  symbol_file = root_str + "/" + filename;
-  if (access(symbol_file.c_str(), F_OK) == 0 &&
-      IsCorrectFile(symbol_file, build_id))
-    return {symbol_file};
-
-  if (filename.find(kApkPrefix) == 0) {
-    symbol_file = root_str + "/" + filename.substr(sizeof(kApkPrefix));
-    if (access(symbol_file.c_str(), F_OK) == 0 &&
-        IsCorrectFile(symbol_file, build_id))
-      return {symbol_file};
-  }
-
-  std::string hex_build_id = base::ToHex(build_id.c_str(), build_id.size());
-  std::string split_hex_build_id = SplitBuildID(hex_build_id);
-  if (!split_hex_build_id.empty()) {
-    symbol_file =
-        root_str + "/" + ".build-id" + "/" + split_hex_build_id + ".debug";
-    if (access(symbol_file.c_str(), F_OK) == 0 &&
-        IsCorrectFile(symbol_file, build_id))
-      return {symbol_file};
-  }
-
-  return base::nullopt;
-}
-
-Subprocess::Subprocess(const std::string& file, std::vector<std::string> args)
-    : input_pipe_(base::Pipe::Create(base::Pipe::kBothBlock)),
-      output_pipe_(base::Pipe::Create(base::Pipe::kBothBlock)) {
-  std::vector<char*> c_str_args(args.size() + 1, nullptr);
-  for (std::string& arg : args)
-    c_str_args.push_back(&(arg[0]));
-
-  if ((pid_ = fork()) == 0) {
-    // Child
-    PERFETTO_CHECK(dup2(*input_pipe_.rd, STDIN_FILENO) != -1);
-    PERFETTO_CHECK(dup2(*output_pipe_.wr, STDOUT_FILENO) != -1);
-    input_pipe_.wr.reset();
-    output_pipe_.rd.reset();
-    PERFETTO_CHECK(execvp(file.c_str(), &(c_str_args[0])) != -1);
-  }
-  PERFETTO_CHECK(pid_ != -1);
-  input_pipe_.rd.reset();
-  output_pipe_.wr.reset();
-}
-
-Subprocess::~Subprocess() {
-  if (pid_ != -1) {
-    kill(pid_, SIGKILL);
-    int wstatus;
-    waitpid(pid_, &wstatus, 0);
-  }
-}
-
-LLVMSymbolizerProcess::LLVMSymbolizerProcess()
-    : subprocess_("llvm-symbolizer", {"llvm-symbolizer"}),
-      read_file_(fdopen(subprocess_.read_fd(), "r")) {}
-
-std::vector<SymbolizedFrame> LLVMSymbolizerProcess::Symbolize(
-    const std::string& binary,
-    uint64_t address) {
-  std::vector<SymbolizedFrame> result;
-
-  if (PERFETTO_EINTR(dprintf(subprocess_.write_fd(), "%s 0x%" PRIx64 "\n",
-                             binary.c_str(), address)) < 0) {
-    PERFETTO_ELOG("Failed to write to llvm-symbolizer.");
-    return result;
-  }
-  auto lines = GetLines(read_file_);
-  // llvm-symbolizer writes out records in the form of
-  // Foo(Bar*)
-  // foo.cc:123
-  // This is why we should always get a multiple of two number of lines.
-  PERFETTO_DCHECK(lines.size() % 2 == 0);
-  result.resize(lines.size() / 2);
-  for (size_t i = 0; i < lines.size(); ++i) {
-    SymbolizedFrame& cur = result[i / 2];
-    if (i % 2 == 0) {
-      cur.function_name = lines[i];
-    } else {
-      if (!ParseLine(lines[i], &cur.file_name, &cur.line)) {
-        PERFETTO_ELOG("Failed to parse llvm-symbolizer line: %s",
-                      lines[i].c_str());
-        cur.file_name = "";
-        cur.line = 0;
-      }
-    }
-  }
-
-  for (auto it = result.begin(); it != result.end();) {
-    if (it->function_name == "??")
-      it = result.erase(it);
-    else
-      ++it;
-  }
-  return result;
-}
-std::vector<std::vector<SymbolizedFrame>> LocalSymbolizer::Symbolize(
-    const std::string& mapping_name,
-    const std::string& build_id,
-    const std::vector<uint64_t>& addresses) {
-  base::Optional<std::string> binary =
-      finder_.FindBinary(mapping_name, build_id);
-  if (!binary)
-    return {};
-  std::vector<std::vector<SymbolizedFrame>> result;
-  result.reserve(addresses.size());
-  for (uint64_t address : addresses)
-    result.emplace_back(llvm_symbolizer_.Symbolize(*binary, address));
-  return result;
-}
-
-LocalSymbolizer::~LocalSymbolizer() = default;
-
-}  // namespace trace_to_text
-}  // namespace perfetto
-
-#endif  // PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
diff --git a/tools/trace_to_text/local_symbolizer.h b/tools/trace_to_text/local_symbolizer.h
deleted file mode 100644
index e1eef9e..0000000
--- a/tools/trace_to_text/local_symbolizer.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2019 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 TOOLS_TRACE_TO_TEXT_LOCAL_SYMBOLIZER_H_
-#define TOOLS_TRACE_TO_TEXT_LOCAL_SYMBOLIZER_H_
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include "perfetto/ext/base/optional.h"
-#include "perfetto/ext/base/pipe.h"
-#include "perfetto/profiling/symbolizer.h"
-
-namespace perfetto {
-namespace trace_to_text {
-
-class LocalBinaryFinder {
- public:
-  LocalBinaryFinder(std::vector<std::string> roots)
-      : roots_(std::move(roots)) {}
-
-  base::Optional<std::string> FindBinary(const std::string& abspath,
-                                         const std::string& build_id);
-
- private:
-  bool IsCorrectFile(const std::string& symbol_file,
-                     const std::string& build_id);
-
-  base::Optional<std::string> FindBinaryInRoot(const std::string& root_str,
-                                               const std::string& abspath,
-                                               const std::string& build_id);
-
- private:
-  std::vector<std::string> roots_;
-  std::map<std::string, base::Optional<std::string>> cache_;
-};
-
-class Subprocess {
- public:
-  Subprocess(const std::string& file, std::vector<std::string> args);
-
-  ~Subprocess();
-
-  int read_fd() { return output_pipe_.rd.get(); }
-  int write_fd() { return input_pipe_.wr.get(); }
-
- private:
-  base::Pipe input_pipe_;
-  base::Pipe output_pipe_;
-
-  pid_t pid_ = -1;
-};
-
-class LLVMSymbolizerProcess {
- public:
-  LLVMSymbolizerProcess();
-
-  std::vector<SymbolizedFrame> Symbolize(const std::string& binary,
-                                         uint64_t address);
-
- private:
-  Subprocess subprocess_;
-  FILE* read_file_;
-};
-
-class LocalSymbolizer : public Symbolizer {
- public:
-  LocalSymbolizer(std::vector<std::string> roots) : finder_(std::move(roots)) {}
-
-  std::vector<std::vector<SymbolizedFrame>> Symbolize(
-      const std::string& mapping_name,
-      const std::string& build_id,
-      const std::vector<uint64_t>& address) override;
-
-  ~LocalSymbolizer() override;
-
- private:
-  LLVMSymbolizerProcess llvm_symbolizer_;
-  LocalBinaryFinder finder_;
-};
-
-}  // namespace trace_to_text
-}  // namespace perfetto
-
-#endif  // TOOLS_TRACE_TO_TEXT_LOCAL_SYMBOLIZER_H_
diff --git a/tools/trace_to_text/main.cc b/tools/trace_to_text/main.cc
index 223fc64..e6c2b3f 100644
--- a/tools/trace_to_text/main.cc
+++ b/tools/trace_to_text/main.cc
@@ -16,99 +16,45 @@
 
 #include <fstream>
 #include <iostream>
-#include <limits>
-#include <vector>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "tools/trace_to_text/symbolize_profile.h"
-#include "tools/trace_to_text/trace_to_json.h"
 #include "tools/trace_to_text/trace_to_profile.h"
 #include "tools/trace_to_text/trace_to_systrace.h"
 #include "tools/trace_to_text/trace_to_text.h"
 
-#if PERFETTO_BUILDFLAG(PERFETTO_VERSION_GEN)
+#if PERFETTO_BUILDFLAG(PERFETTO_STANDALONE_BUILD)
 #include "perfetto_version.gen.h"
 #else
 #define PERFETTO_GET_GIT_REVISION() "unknown"
 #endif
 
-namespace perfetto {
-namespace trace_to_text {
 namespace {
 
 int Usage(const char* argv0) {
-  fprintf(stderr,
-          "Usage: %s systrace|json|ctrace|text|profile [--pid PID] "
-          "[--timestamps TIMESTAMP1,TIMESTAMP2,...] "
-          "[--truncate start|end] "
-          "[--full-sort] "
-          "[trace.pb] "
-          "[trace.txt]\n"
-          "\nProfile mode only:\n"
-          "\t--timestamps TIMESTAMP1,TIMESTAMP2,... generate profiles "
-          "only for these timestamps\n"
-          "\t--pid PID generate profiles only for this process id\n",
-          argv0);
+  printf(
+      "Usage: %s systrace|json|text|profile [trace.pb] "
+      "[trace.txt]\n",
+      argv0);
   return 1;
 }
 
-uint64_t StringToUint64OrDie(const char* str) {
-  char* end;
-  uint64_t number = static_cast<uint64_t>(strtoll(str, &end, 10));
-  if (*end != '\0') {
-    PERFETTO_ELOG("Invalid %s. Expected decimal integer.", str);
-    exit(1);
-  }
-  return number;
-}
+}  // namespace
 
-int Main(int argc, char** argv) {
-  std::vector<const char*> positional_args;
-  Keep truncate_keep = Keep::kAll;
-  uint64_t pid = 0;
-  std::vector<uint64_t> timestamps;
-  bool full_sort = false;
+int main(int argc, char** argv) {
   for (int i = 1; i < argc; i++) {
     if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) {
       printf("%s\n", PERFETTO_GET_GIT_REVISION());
       return 0;
-    } else if (strcmp(argv[i], "-t") == 0 ||
-               strcmp(argv[i], "--truncate") == 0) {
-      i++;
-      if (i <= argc && strcmp(argv[i], "start") == 0) {
-        truncate_keep = Keep::kStart;
-      } else if (i <= argc && strcmp(argv[i], "end") == 0) {
-        truncate_keep = Keep::kEnd;
-      } else {
-        PERFETTO_ELOG(
-            "--truncate must specify whether to keep the end or the "
-            "start of the trace.");
-        return Usage(argv[0]);
-      }
-    } else if (i <= argc && strcmp(argv[i], "--pid") == 0) {
-      i++;
-      pid = StringToUint64OrDie(argv[i]);
-    } else if (i <= argc && strcmp(argv[i], "--timestamps") == 0) {
-      i++;
-      std::vector<std::string> ts_strings = base::SplitString(argv[i], ",");
-      for (const std::string& ts : ts_strings) {
-        timestamps.emplace_back(StringToUint64OrDie(ts.c_str()));
-      }
-    } else if (strcmp(argv[i], "--full-sort") == 0) {
-      full_sort = true;
-    } else {
-      positional_args.push_back(argv[i]);
     }
   }
 
-  if (positional_args.size() < 1)
+  if (argc < 2)
     return Usage(argv[0]);
 
   std::istream* input_stream;
   std::ifstream file_istream;
-  if (positional_args.size() > 1) {
-    const char* file_path = positional_args[1];
+  if (argc > 2) {
+    const char* file_path = argv[2];
     file_istream.open(file_path, std::ios_base::in | std::ios_base::binary);
     if (!file_istream.is_open())
       PERFETTO_FATAL("Could not open %s", file_path);
@@ -125,8 +71,8 @@
 
   std::ostream* output_stream;
   std::ofstream file_ostream;
-  if (positional_args.size() > 2) {
-    const char* file_path = positional_args[2];
+  if (argc > 3) {
+    const char* file_path = argv[3];
     file_ostream.open(file_path, std::ios_base::out | std::ios_base::trunc);
     if (!file_ostream.is_open())
       PERFETTO_FATAL("Could not open %s", file_path);
@@ -135,54 +81,19 @@
     output_stream = &std::cout;
   }
 
-  std::string format(positional_args[0]);
-
-  if (format != "profile" && (pid != 0 || !timestamps.empty())) {
-    PERFETTO_ELOG(
-        "--pid and --timestamps are supported only for profile format.");
-    return 1;
-  }
+  std::string format(argv[1]);
 
   if (format == "json")
-    return TraceToJson(input_stream, output_stream, /*compress=*/false,
-                       truncate_keep, full_sort);
-
+    return perfetto::trace_to_text::TraceToSystrace(input_stream, output_stream,
+                                                    /*wrap_in_json=*/true);
   if (format == "systrace")
-    return TraceToSystrace(input_stream, output_stream, /*compress=*/false,
-                           truncate_keep, full_sort);
-
-  if (format == "ctrace")
-    return TraceToSystrace(input_stream, output_stream, /*compress=*/true,
-                           truncate_keep, full_sort);
-
-  if (truncate_keep != Keep::kAll) {
-    PERFETTO_ELOG(
-        "--truncate is unsupported for text|profile|symbolize format.");
-    return 1;
-  }
-
-  if (full_sort) {
-    PERFETTO_ELOG(
-        "--full-sort is unsupported for text|profile|symbolize format.");
-    return 1;
-  }
-
+    return perfetto::trace_to_text::TraceToSystrace(input_stream, output_stream,
+                                                    /*wrap_in_json=*/false);
   if (format == "text")
-    return TraceToText(input_stream, output_stream);
+    return perfetto::trace_to_text::TraceToText(input_stream, output_stream);
 
   if (format == "profile")
-    return TraceToProfile(input_stream, output_stream, pid, timestamps);
-
-  if (format == "symbolize")
-    return SymbolizeProfile(input_stream, output_stream);
+    return perfetto::trace_to_text::TraceToProfile(input_stream, output_stream);
 
   return Usage(argv[0]);
 }
-
-}  // namespace
-}  // namespace trace_to_text
-}  // namespace perfetto
-
-int main(int argc, char** argv) {
-  return perfetto::trace_to_text::Main(argc, argv);
-}
diff --git a/tools/trace_to_text/pprof_builder.cc b/tools/trace_to_text/pprof_builder.cc
deleted file mode 100644
index 4c61eb3..0000000
--- a/tools/trace_to_text/pprof_builder.cc
+++ /dev/null
@@ -1,599 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/profiling/pprof_builder.h"
-
-#include <cxxabi.h>
-#include <inttypes.h>
-
-#include <algorithm>
-#include <map>
-#include <set>
-#include <utility>
-#include <vector>
-
-#include "tools/trace_to_text/utils.h"
-
-#include "perfetto/base/logging.h"
-#include "perfetto/base/time.h"
-#include "perfetto/ext/base/string_utils.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/profiling/symbolizer.h"
-
-#include "protos/perfetto/trace/profiling/profile_common.pb.h"
-#include "protos/perfetto/trace/profiling/profile_packet.pb.h"
-#include "protos/perfetto/trace/trace.pb.h"
-#include "protos/perfetto/trace/trace.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-#include "protos/third_party/pprof/profile.pb.h"
-
-namespace perfetto {
-namespace trace_to_text {
-
-namespace {
-
-using ::protozero::proto_utils::kMessageLengthFieldSize;
-using ::protozero::proto_utils::MakeTagLengthDelimited;
-using ::protozero::proto_utils::WriteVarInt;
-
-using GLine = ::perfetto::third_party::perftools::profiles::Line;
-using GMapping = ::perfetto::third_party::perftools::profiles::Mapping;
-using GLocation = ::perfetto::third_party::perftools::profiles::Location;
-using GProfile = ::perfetto::third_party::perftools::profiles::Profile;
-using GValueType = ::perfetto::third_party::perftools::profiles::ValueType;
-using GFunction = ::perfetto::third_party::perftools::profiles::Function;
-using GSample = ::perfetto::third_party::perftools::profiles::Sample;
-
-struct View {
-  const char* type;
-  const char* unit;
-  const char* aggregator;
-  const char* filter;
-};
-
-void MaybeDemangle(std::string* name) {
-  int ignored;
-  char* data = abi::__cxa_demangle(name->c_str(), nullptr, nullptr, &ignored);
-  if (data) {
-    *name = data;
-    free(data);
-  }
-}
-
-const View kSpaceView{"space", "bytes", "SUM(size)", nullptr};
-const View kAllocSpaceView{"alloc_space", "bytes", "SUM(size)", "size > 0"};
-const View kAllocObjectsView{"alloc_objects", "count", "sum(count)",
-                             "size > 0"};
-const View kObjectsView{"objects", "count", "SUM(count)", nullptr};
-
-const View kViews[] = {kAllocObjectsView, kObjectsView, kAllocSpaceView,
-                       kSpaceView};
-
-using Iterator = trace_processor::TraceProcessor::Iterator;
-
-constexpr const char* kQueryProfiles =
-    "select distinct hpa.upid, hpa.ts, p.pid from heap_profile_allocation hpa, "
-    "process p where p.upid = hpa.upid;";
-
-int64_t GetStatsInt(trace_processor::TraceProcessor* tp,
-                    const std::string& name,
-                    uint64_t pid) {
-  auto it = tp->ExecuteQuery("SELECT value from stats where name = '" + name +
-                             "' AND idx = " + std::to_string(pid));
-  if (!it.Next()) {
-    if (!it.Status().ok()) {
-      PERFETTO_DFATAL_OR_ELOG("Invalid iterator: %s",
-                              it.Status().message().c_str());
-      return -1;
-    }
-    // TODO(fmayer): Remove this case once we always get an entry in the stats
-    // table.
-    return 0;
-  }
-  return it.Get(0).long_value;
-}
-
-bool VerifyPIDStats(trace_processor::TraceProcessor* tp, uint64_t pid) {
-  bool success = true;
-  int64_t stat = GetStatsInt(tp, "heapprofd_buffer_corrupted", pid);
-  if (stat == -1) {
-    PERFETTO_DFATAL_OR_ELOG("Failed to get heapprofd_buffer_corrupted stat");
-  } else if (stat > 0) {
-    success = false;
-    PERFETTO_ELOG("WARNING: The profile for %" PRIu64
-                  " ended early due to a buffer corruption."
-                  " THIS IS ALWAYS A BUG IN HEAPPROFD OR"
-                  " CLIENT MEMORY CORRUPTION.",
-                  pid);
-  }
-  stat = GetStatsInt(tp, "heapprofd_buffer_overran", pid);
-  if (stat == -1) {
-    PERFETTO_DFATAL_OR_ELOG("Failed to get heapprofd_buffer_overran stat");
-  } else if (stat > 0) {
-    success = false;
-    PERFETTO_ELOG("WARNING: The profile for %" PRIu64
-                  " ended early due to a buffer overrun.",
-                  pid);
-  }
-
-  stat = GetStatsInt(tp, "heapprofd_rejected_concurrent", pid);
-  if (stat == -1) {
-    PERFETTO_DFATAL_OR_ELOG("Failed to get heapprofd_rejected_concurrent stat");
-  } else if (stat > 0) {
-    success = false;
-    PERFETTO_ELOG("WARNING: The profile for %" PRIu64
-                  " was rejected due to a concurrent profile.",
-                  pid);
-  }
-  return success;
-}
-
-struct Callsite {
-  int64_t id;
-  int64_t frame_id;
-};
-
-// Return map from callsite_id to list of frame_ids that make up the callstack.
-std::vector<std::vector<int64_t>> GetCallsiteToFrames(
-    trace_processor::TraceProcessor* tp) {
-  Iterator count_it =
-      tp->ExecuteQuery("select count(*) from stack_profile_callsite;");
-  if (!count_it.Next()) {
-    PERFETTO_DFATAL_OR_ELOG("Failed to get number of callsites: %s",
-                            count_it.Status().message().c_str());
-    return {};
-  }
-  int64_t count = count_it.Get(0).long_value;
-
-  Iterator it = tp->ExecuteQuery(
-      "select id, parent_id, frame_id from stack_profile_callsite order by "
-      "depth;");
-  std::vector<std::vector<int64_t>> result(static_cast<size_t>(count));
-  while (it.Next()) {
-    int64_t id = it.Get(0).long_value;
-    int64_t parent_id = it.Get(1).long_value;
-    int64_t frame_id = it.Get(2).long_value;
-    std::vector<int64_t>& path = result[static_cast<size_t>(id)];
-    path.push_back(frame_id);
-    if (parent_id != -1) {
-      const std::vector<int64_t>& parent_path =
-          result[static_cast<size_t>(parent_id)];
-      path.insert(path.end(), parent_path.begin(), parent_path.end());
-    }
-  }
-
-  if (!it.Status().ok()) {
-    PERFETTO_DFATAL_OR_ELOG("Invalid iterator: %s",
-                            it.Status().message().c_str());
-    return {};
-  }
-  return result;
-}
-
-struct Line {
-  int64_t symbol_id;
-  uint32_t line_number;
-};
-
-std::map<int64_t, std::vector<Line>> GetSymbolSetIdToLines(
-    trace_processor::TraceProcessor* tp) {
-  std::map<int64_t, std::vector<Line>> result;
-  Iterator it = tp->ExecuteQuery(
-      "SELECT symbol_set_id, id, line_number FROM stack_profile_symbol;");
-  while (it.Next()) {
-    int64_t symbol_set_id = it.Get(0).long_value;
-    int64_t id = it.Get(1).long_value;
-    int64_t line_number = it.Get(2).long_value;
-    result[symbol_set_id].emplace_back(
-        Line{id, static_cast<uint32_t>(line_number)});
-  }
-
-  if (!it.Status().ok()) {
-    PERFETTO_DFATAL_OR_ELOG("Invalid iterator: %s",
-                            it.Status().message().c_str());
-    return {};
-  }
-  return result;
-}
-
-class GProfileBuilder {
- public:
-  GProfileBuilder(
-      const std::vector<std::vector<int64_t>>& callsite_to_frames,
-      const std::map<int64_t, std::vector<Line>>& symbol_set_id_to_lines,
-      int64_t max_symbol_id)
-      : callsite_to_frames_(callsite_to_frames),
-        symbol_set_id_to_lines_(symbol_set_id_to_lines),
-        max_symbol_id_(max_symbol_id) {
-    // The pprof format expects the first entry in the string table to be the
-    // empty string.
-    Intern("");
-  }
-
-  std::vector<Iterator> BuildViewIterators(trace_processor::TraceProcessor* tp,
-                                           uint64_t upid,
-                                           uint64_t ts) {
-    std::vector<Iterator> view_its;
-    for (size_t i = 0; i < base::ArraySize(kViews); ++i) {
-      const View& v = kViews[i];
-      std::string query = "SELECT hpa.callsite_id ";
-      query += ", " + std::string(v.aggregator) +
-               " FROM heap_profile_allocation hpa ";
-      // TODO(fmayer): Figure out where negative callsite_id comes from.
-      query += "WHERE hpa.callsite_id >= 0 ";
-      query += "AND hpa.upid = " + std::to_string(upid) + " ";
-      query += "AND hpa.ts <= " + std::to_string(ts) + " ";
-      if (v.filter)
-        query += "AND " + std::string(v.filter) + " ";
-      query += "GROUP BY hpa.callsite_id;";
-      view_its.emplace_back(tp->ExecuteQuery(query));
-    }
-    return view_its;
-  }
-
-  bool WriteAllocations(std::vector<Iterator>* view_its,
-                        std::set<int64_t>* seen_frames) {
-    for (;;) {
-      bool all_next = true;
-      bool any_next = false;
-      for (size_t i = 0; i < base::ArraySize(kViews); ++i) {
-        Iterator& it = (*view_its)[i];
-        bool next = it.Next();
-        if (!it.Status().ok()) {
-          PERFETTO_DFATAL_OR_ELOG("Invalid view iterator: %s",
-                                  it.Status().message().c_str());
-          return false;
-        }
-        all_next = all_next && next;
-        any_next = any_next || next;
-      }
-
-      if (!all_next) {
-        PERFETTO_DCHECK(!any_next);
-        break;
-      }
-
-      GSample* gsample = result_.add_sample();
-      for (size_t i = 0; i < base::ArraySize(kViews); ++i) {
-        int64_t callstack_id = (*view_its)[i].Get(0).long_value;
-        if (i == 0) {
-          auto frames = FramesForCallstack(callstack_id);
-          if (frames.empty())
-            return false;
-          for (int64_t frame : frames)
-            gsample->add_location_id(ToPprofId(frame));
-          seen_frames->insert(frames.cbegin(), frames.cend());
-        } else {
-          if (callstack_id != (*view_its)[i].Get(0).long_value) {
-            PERFETTO_DFATAL_OR_ELOG("Wrong callstack.");
-            return false;
-          }
-        }
-        gsample->add_value((*view_its)[i].Get(1).long_value);
-      }
-    }
-    return true;
-  }
-
-  bool WriteMappings(trace_processor::TraceProcessor* tp,
-                     const std::set<int64_t> seen_mappings) {
-    Iterator mapping_it = tp->ExecuteQuery(
-        "SELECT id, exact_offset, start, end, name "
-        "FROM stack_profile_mapping;");
-    size_t mappings_no = 0;
-    while (mapping_it.Next()) {
-      int64_t id = mapping_it.Get(0).long_value;
-      if (seen_mappings.find(id) == seen_mappings.end())
-        continue;
-      ++mappings_no;
-      GMapping* gmapping = result_.add_mapping();
-      gmapping->set_id(ToPprofId(id));
-      // Do not set the build_id here to avoid downstream services
-      // trying to symbolize (e.g. b/141735056)
-      gmapping->set_file_offset(
-          static_cast<uint64_t>(mapping_it.Get(1).long_value));
-      gmapping->set_memory_start(
-          static_cast<uint64_t>(mapping_it.Get(2).long_value));
-      gmapping->set_memory_limit(
-          static_cast<uint64_t>(mapping_it.Get(3).long_value));
-      gmapping->set_filename(Intern(mapping_it.Get(4).string_value));
-    }
-    if (!mapping_it.Status().ok()) {
-      PERFETTO_DFATAL_OR_ELOG("Invalid mapping iterator: %s",
-                              mapping_it.Status().message().c_str());
-      return false;
-    }
-    if (mappings_no != seen_mappings.size()) {
-      PERFETTO_DFATAL_OR_ELOG("Missing mappings.");
-      return false;
-    }
-    return true;
-  }
-
-  bool WriteSymbols(trace_processor::TraceProcessor* tp,
-                    const std::set<int64_t>& seen_symbol_ids) {
-    Iterator symbol_it = tp->ExecuteQuery(
-        "SELECT id, name, source_file FROM stack_profile_symbol");
-    size_t symbols_no = 0;
-    while (symbol_it.Next()) {
-      int64_t id = symbol_it.Get(0).long_value;
-      if (seen_symbol_ids.find(id) == seen_symbol_ids.end())
-        continue;
-      ++symbols_no;
-      const std::string& name = symbol_it.Get(1).string_value;
-      std::string demangled_name = name;
-      MaybeDemangle(&demangled_name);
-
-      GFunction* gfunction = result_.add_function();
-      gfunction->set_id(ToPprofId(id));
-      gfunction->set_name(Intern(demangled_name));
-      gfunction->set_system_name(Intern(name));
-      gfunction->set_filename(Intern(symbol_it.Get(2).string_value));
-    }
-
-    if (!symbol_it.Status().ok()) {
-      PERFETTO_DFATAL_OR_ELOG("Invalid iterator: %s",
-                              symbol_it.Status().message().c_str());
-      return false;
-    }
-
-    if (symbols_no != seen_symbol_ids.size()) {
-      PERFETTO_DFATAL_OR_ELOG("Missing symbols.");
-      return false;
-    }
-    return true;
-  }
-
-  bool WriteFrames(trace_processor::TraceProcessor* tp,
-                   const std::set<int64_t>& seen_frames,
-                   std::set<int64_t>* seen_mappings,
-                   std::set<int64_t>* seen_symbol_ids) {
-    Iterator frame_it = tp->ExecuteQuery(
-        "SELECT spf.id, spf.name, spf.mapping, spf.rel_pc, spf.symbol_set_id "
-        "FROM stack_profile_frame spf;");
-    size_t frames_no = 0;
-    while (frame_it.Next()) {
-      int64_t frame_id = frame_it.Get(0).long_value;
-      if (seen_frames.find(frame_id) == seen_frames.end())
-        continue;
-      frames_no++;
-      std::string frame_name = frame_it.Get(1).string_value;
-      int64_t mapping_id = frame_it.Get(2).long_value;
-      int64_t rel_pc = frame_it.Get(3).long_value;
-      int64_t symbol_set_id = frame_it.Get(4).long_value;
-
-      seen_mappings->emplace(mapping_id);
-      GLocation* glocation = result_.add_location();
-      glocation->set_id(ToPprofId(frame_id));
-      glocation->set_mapping_id(ToPprofId(mapping_id));
-      // TODO(fmayer): Convert to abspc.
-      // relpc + (mapping.start - (mapping.exact_offset -
-      //                           mapping.start_offset)).
-      glocation->set_address(static_cast<uint64_t>(rel_pc));
-      if (symbol_set_id) {
-        for (const Line& line : LineForSymbolSetId(symbol_set_id)) {
-          seen_symbol_ids->emplace(line.symbol_id);
-          GLine* gline = glocation->add_line();
-          gline->set_line(line.line_number);
-          gline->set_function_id(ToPprofId(line.symbol_id));
-        }
-      } else {
-        int64_t synthesized_symbol_id = ++max_symbol_id_;
-        std::string demangled_name = frame_name;
-        MaybeDemangle(&demangled_name);
-
-        GFunction* gfunction = result_.add_function();
-        gfunction->set_id(ToPprofId(synthesized_symbol_id));
-        gfunction->set_name(Intern(demangled_name));
-        gfunction->set_system_name(Intern(frame_name));
-
-        GLine* gline = glocation->add_line();
-        gline->set_line(0);
-        gline->set_function_id(ToPprofId(synthesized_symbol_id));
-      }
-    }
-
-    if (!frame_it.Status().ok()) {
-      PERFETTO_DFATAL_OR_ELOG("Invalid iterator: %s",
-                              frame_it.Status().message().c_str());
-      return false;
-    }
-    if (frames_no != seen_frames.size()) {
-      PERFETTO_DFATAL_OR_ELOG("Missing frames.");
-      return false;
-    }
-    return true;
-  }
-
-  uint64_t ToPprofId(int64_t id) {
-    PERFETTO_DCHECK(id >= 0);
-    return static_cast<uint64_t>(id) + 1;
-  }
-
-  void WriteSampleTypes() {
-    for (size_t i = 0; i < base::ArraySize(kViews); ++i) {
-      auto* sample_type = result_.add_sample_type();
-      sample_type->set_type(Intern(kViews[i].type));
-      sample_type->set_unit(Intern(kViews[i].unit));
-    }
-  }
-
-  GProfile GenerateGProfile(trace_processor::TraceProcessor* tp,
-                            uint64_t upid,
-                            uint64_t ts) {
-    std::set<int64_t> seen_frames;
-    std::set<int64_t> seen_mappings;
-    std::set<int64_t> seen_symbol_ids;
-
-    std::vector<Iterator> view_its = BuildViewIterators(tp, upid, ts);
-
-    WriteSampleTypes();
-    if (!WriteAllocations(&view_its, &seen_frames))
-      return {};
-    if (!WriteFrames(tp, seen_frames, &seen_mappings, &seen_symbol_ids))
-      return {};
-    if (!WriteMappings(tp, seen_mappings))
-      return {};
-    if (!WriteSymbols(tp, seen_symbol_ids))
-      return {};
-    return std::move(result_);
-  }
-
-  const std::vector<int64_t>& FramesForCallstack(int64_t callstack_id) {
-    size_t callsite_idx = static_cast<size_t>(callstack_id);
-    PERFETTO_CHECK(callstack_id >= 0 &&
-                   callsite_idx < callsite_to_frames_.size());
-    return callsite_to_frames_[callsite_idx];
-  }
-
-  const std::vector<Line>& LineForSymbolSetId(int64_t symbol_set_id) {
-    auto it = symbol_set_id_to_lines_.find(symbol_set_id);
-    if (it == symbol_set_id_to_lines_.end())
-      return empty_line_vector_;
-    return it->second;
-  }
-
-  int64_t Intern(const std::string& s) {
-    auto it = string_table_.find(s);
-    if (it == string_table_.end()) {
-      std::tie(it, std::ignore) =
-          string_table_.emplace(s, string_table_.size());
-      result_.add_string_table(s);
-    }
-    return it->second;
-  }
-
- private:
-  GProfile result_;
-  std::map<std::string, int64_t> string_table_;
-  const std::vector<std::vector<int64_t>>& callsite_to_frames_;
-  const std::map<int64_t, std::vector<Line>>& symbol_set_id_to_lines_;
-  const std::vector<Line> empty_line_vector_;
-  int64_t max_symbol_id_;
-};
-
-}  // namespace
-
-bool TraceToPprof(std::istream* input,
-                  std::vector<SerializedProfile>* output,
-                  Symbolizer* symbolizer,
-                  uint64_t pid,
-                  const std::vector<uint64_t>& timestamps) {
-  trace_processor::Config config;
-  std::unique_ptr<trace_processor::TraceProcessor> tp =
-      trace_processor::TraceProcessor::CreateInstance(config);
-
-  if (!ReadTrace(tp.get(), input))
-    return false;
-
-  tp->NotifyEndOfFile();
-  return TraceToPprof(tp.get(), output, symbolizer, pid, timestamps);
-}
-
-bool TraceToPprof(trace_processor::TraceProcessor* tp,
-                  std::vector<SerializedProfile>* output,
-                  Symbolizer* symbolizer,
-                  uint64_t pid,
-                  const std::vector<uint64_t>& timestamps) {
-  if (symbolizer) {
-    SymbolizeDatabase(
-        tp, symbolizer, [&tp](perfetto::protos::TracePacket packet) {
-          size_t size = static_cast<size_t>(packet.ByteSize());
-          std::unique_ptr<uint8_t[]> buf(new uint8_t[size]);
-          packet.SerializeToArray(buf.get(), packet.ByteSize());
-
-          std::unique_ptr<uint8_t[]> preamble(new uint8_t[11]);
-          preamble[0] =
-              MakeTagLengthDelimited(protos::pbzero::Trace::kPacketFieldNumber);
-          uint8_t* end = WriteVarInt(size, &preamble[1]);
-          size_t preamble_size = static_cast<size_t>(end - &preamble[0]);
-          auto status = tp->Parse(std::move(preamble), preamble_size);
-          if (!status.ok()) {
-            PERFETTO_DFATAL_OR_ELOG("Failed to parse: %s",
-                                    status.message().c_str());
-            return;
-          }
-          status = tp->Parse(std::move(buf), size);
-          if (!status.ok()) {
-            PERFETTO_DFATAL_OR_ELOG("Failed to parse: %s",
-                                    status.message().c_str());
-            return;
-          }
-        });
-  }
-
-  tp->NotifyEndOfFile();
-  auto max_symbol_id_it =
-      tp->ExecuteQuery("SELECT MAX(id) from stack_profile_symbol");
-  if (!max_symbol_id_it.Next()) {
-    PERFETTO_DFATAL_OR_ELOG("Failed to get max symbol set id: %s",
-                            max_symbol_id_it.Status().message().c_str());
-    return false;
-  }
-
-  int64_t max_symbol_id = max_symbol_id_it.Get(0).long_value;
-  const auto callsite_to_frames = GetCallsiteToFrames(tp);
-  const auto symbol_set_id_to_lines = GetSymbolSetIdToLines(tp);
-
-  bool any_fail = false;
-  Iterator it = tp->ExecuteQuery(kQueryProfiles);
-  while (it.Next()) {
-    GProfileBuilder builder(callsite_to_frames, symbol_set_id_to_lines,
-                            max_symbol_id);
-    uint64_t upid = static_cast<uint64_t>(it.Get(0).long_value);
-    uint64_t ts = static_cast<uint64_t>(it.Get(1).long_value);
-    uint64_t profile_pid = static_cast<uint64_t>(it.Get(2).long_value);
-    if ((pid > 0 && profile_pid != pid) ||
-        (!timestamps.empty() && std::find(timestamps.begin(), timestamps.end(),
-                                          ts) == timestamps.end())) {
-      continue;
-    }
-
-    if (!VerifyPIDStats(tp, pid))
-      any_fail = true;
-
-    std::string pid_query = "select pid from process where upid = ";
-    pid_query += std::to_string(upid) + ";";
-    Iterator pid_it = tp->ExecuteQuery(pid_query);
-    PERFETTO_CHECK(pid_it.Next());
-
-    GProfile profile = builder.GenerateGProfile(tp, upid, ts);
-    output->emplace_back(
-        SerializedProfile{static_cast<uint64_t>(pid_it.Get(0).long_value),
-                          profile.SerializeAsString()});
-  }
-  if (any_fail) {
-    PERFETTO_ELOG(
-        "One or more of your profiles had an issue. Please consult "
-        "https://docs.perfetto.dev/#/heapprofd?id=troubleshooting.");
-  }
-  if (!it.Status().ok()) {
-    PERFETTO_DFATAL_OR_ELOG("Invalid iterator: %s",
-                            it.Status().message().c_str());
-    return false;
-  }
-  return true;
-}
-
-bool TraceToPprof(std::istream* input,
-                  std::vector<SerializedProfile>* output,
-                  uint64_t pid,
-                  const std::vector<uint64_t>& timestamps) {
-  return TraceToPprof(input, output, nullptr, pid, timestamps);
-}
-
-}  // namespace trace_to_text
-}  // namespace perfetto
diff --git a/tools/trace_to_text/symbolize_profile.cc b/tools/trace_to_text/symbolize_profile.cc
deleted file mode 100644
index 1d2812d..0000000
--- a/tools/trace_to_text/symbolize_profile.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2019 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 "tools/trace_to_text/symbolize_profile.h"
-
-#include <vector>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/profiling/symbolizer.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
-#include "tools/trace_to_text/local_symbolizer.h"
-#endif
-
-#include "protos/perfetto/trace/trace.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pbzero.h"
-#include "tools/trace_to_text/utils.h"
-
-namespace perfetto {
-namespace trace_to_text {
-namespace {
-
-using ::protozero::proto_utils::kMessageLengthFieldSize;
-using ::protozero::proto_utils::MakeTagLengthDelimited;
-using ::protozero::proto_utils::WriteVarInt;
-
-void WriteTracePacket(const std::string& str, std::ostream* output) {
-  constexpr char kPreamble =
-      MakeTagLengthDelimited(protos::pbzero::Trace::kPacketFieldNumber);
-  uint8_t length_field[10];
-  uint8_t* end = WriteVarInt(str.size(), length_field);
-  *output << kPreamble;
-  *output << std::string(length_field, end);
-  *output << str;
-}
-}
-
-// Ingest profile, and emit a symbolization table for each sequence. This can
-// be prepended to the profile to attach the symbol information.
-int SymbolizeProfile(std::istream* input, std::ostream* output) {
-  std::unique_ptr<Symbolizer> symbolizer;
-  auto binary_path = GetPerfettoBinaryPath();
-  if (!binary_path.empty()) {
-#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
-    symbolizer.reset(new LocalSymbolizer(GetPerfettoBinaryPath()));
-#else
-    PERFETTO_FATAL("This build does not support local symbolization.");
-#endif
-  }
-
-  if (!symbolizer)
-    PERFETTO_FATAL("No symbolizer selected");
-  trace_processor::Config config;
-  std::unique_ptr<trace_processor::TraceProcessor> tp =
-      trace_processor::TraceProcessor::CreateInstance(config);
-
-  if (!ReadTrace(tp.get(), input))
-    PERFETTO_FATAL("Failed to read trace.");
-
-  tp->NotifyEndOfFile();
-
-  SymbolizeDatabase(tp.get(), symbolizer.get(),
-                    [output](const perfetto::protos::TracePacket& packet) {
-                      WriteTracePacket(packet.SerializeAsString(), output);
-                    });
-  return 0;
-}
-
-}  // namespace trace_to_text
-}  // namespace perfetto
diff --git a/tools/trace_to_text/symbolize_profile.h b/tools/trace_to_text/symbolize_profile.h
deleted file mode 100644
index 3c787fd..0000000
--- a/tools/trace_to_text/symbolize_profile.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2019 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 TOOLS_TRACE_TO_TEXT_SYMBOLIZE_PROFILE_H_
-#define TOOLS_TRACE_TO_TEXT_SYMBOLIZE_PROFILE_H_
-
-#include "perfetto/profiling/symbolizer.h"
-#include "perfetto/trace_processor/trace_processor.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
-
-#include <functional>
-#include <iostream>
-
-namespace perfetto {
-namespace trace_to_text {
-
-int SymbolizeProfile(std::istream* input, std::ostream* output);
-
-}  // namespace trace_to_text
-}  // namespace perfetto
-
-#endif  // TOOLS_TRACE_TO_TEXT_SYMBOLIZE_PROFILE_H_
diff --git a/tools/trace_to_text/symbolizer.cc b/tools/trace_to_text/symbolizer.cc
deleted file mode 100644
index 1cd83cb..0000000
--- a/tools/trace_to_text/symbolizer.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2019 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 "perfetto/profiling/symbolizer.h"
-
-namespace perfetto {
-namespace trace_to_text {
-
-Symbolizer::~Symbolizer() = default;
-
-}  // namespace trace_to_text
-}  // namespace perfetto
diff --git a/tools/trace_to_text/trace_to_json.cc b/tools/trace_to_text/trace_to_json.cc
deleted file mode 100644
index 7f4ba66..0000000
--- a/tools/trace_to_text/trace_to_json.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2019 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 "tools/trace_to_text/trace_to_json.h"
-
-#include <stdio.h>
-
-#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/trace_processor/trace_processor.h"
-#include "tools/trace_to_text/utils.h"
-
-namespace perfetto {
-namespace trace_to_text {
-
-namespace {
-
-const char kTraceHeader[] = R"({
-  "traceEvents": [],
-)";
-
-const char kTraceFooter[] = R"(,
-  "controllerTraceDataKey": "systraceController"
-})";
-
-bool ExportUserspaceEvents(trace_processor::TraceProcessor* tp,
-                           TraceWriter* writer) {
-  fprintf(stderr, "Converting userspace events%c", kProgressChar);
-  fflush(stderr);
-
-  // Write userspace trace to a temporary file.
-  // TODO(eseckler): Support streaming the result out of TP directly instead.
-  auto file = base::TempFile::Create();
-  char query[100];
-  sprintf(query, "select export_json(\"%s\")", file.path().c_str());
-  auto it = tp->ExecuteQuery(query);
-
-  if (!it.Next()) {
-    auto status = it.Status();
-    PERFETTO_CHECK(!status.ok());
-    PERFETTO_ELOG("Could not convert userspace events: %s", status.c_message());
-    return false;
-  }
-
-  base::ScopedFstream source(fopen(file.path().c_str(), "r"));
-  if (!source) {
-    PERFETTO_ELOG("Could not convert userspace events: Couldn't read file %s",
-                  file.path().c_str());
-    return false;
-  }
-
-  char buf[BUFSIZ];
-  size_t size;
-  while ((size = fread(buf, sizeof(char), BUFSIZ, *source)) > 0) {
-    // Skip writing the closing brace since we'll append system trace data.
-    if (feof(*source))
-      size--;
-    writer->Write(buf, size);
-  }
-  return true;
-}
-
-}  // namespace
-
-int TraceToJson(std::istream* input,
-                std::ostream* output,
-                bool compress,
-                Keep truncate_keep,
-                bool full_sort) {
-  std::unique_ptr<TraceWriter> trace_writer(
-      compress ? new DeflateTraceWriter(output) : new TraceWriter(output));
-
-  trace_processor::Config config;
-  config.force_full_sort = full_sort;
-  std::unique_ptr<trace_processor::TraceProcessor> tp =
-      trace_processor::TraceProcessor::CreateInstance(config);
-
-  if (!ReadTrace(tp.get(), input))
-    return 1;
-  tp->NotifyEndOfFile();
-
-  // TODO(eseckler): Support truncation of userspace event data.
-  if (ExportUserspaceEvents(tp.get(), trace_writer.get())) {
-    trace_writer->Write(",\n");
-  } else {
-    trace_writer->Write(kTraceHeader);
-  }
-
-  int ret = ExtractSystrace(tp.get(), trace_writer.get(),
-                            /*wrapped_in_json=*/true, truncate_keep);
-  if (ret)
-    return ret;
-
-  trace_writer->Write(kTraceFooter);
-  return 0;
-}
-
-}  // namespace trace_to_text
-}  // namespace perfetto
diff --git a/tools/trace_to_text/trace_to_json.h b/tools/trace_to_text/trace_to_json.h
deleted file mode 100644
index dc0aa18..0000000
--- a/tools/trace_to_text/trace_to_json.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2019 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 TOOLS_TRACE_TO_TEXT_TRACE_TO_JSON_H_
-#define TOOLS_TRACE_TO_TEXT_TRACE_TO_JSON_H_
-
-#include <iostream>
-
-#include "tools/trace_to_text/trace_to_systrace.h"
-
-namespace perfetto {
-namespace trace_to_text {
-
-int TraceToJson(std::istream* input,
-                std::ostream* output,
-                bool compress,
-                Keep truncate_keep,
-                bool full_sort);
-
-}  // namespace trace_to_text
-}  // namespace perfetto
-
-#endif  // TOOLS_TRACE_TO_TEXT_TRACE_TO_JSON_H_
diff --git a/tools/trace_to_text/trace_to_profile.cc b/tools/trace_to_text/trace_to_profile.cc
index 4f5f1ec..1605056 100644
--- a/tools/trace_to_text/trace_to_profile.cc
+++ b/tools/trace_to_text/trace_to_profile.cc
@@ -16,27 +16,42 @@
 
 #include "tools/trace_to_text/trace_to_profile.h"
 
-#include <string>
+#include <cxxabi.h>
+#include <inttypes.h>
+
+#include <algorithm>
+#include <map>
+#include <set>
 #include <vector>
 
-#include "perfetto/base/build_config.h"
-
-#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
-#include "tools/trace_to_text/local_symbolizer.h"
-#endif
 #include "tools/trace_to_text/utils.h"
 
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/temp_file.h"
-#include "perfetto/ext/base/utils.h"
-#include "perfetto/profiling/pprof_builder.h"
-#include "perfetto/profiling/symbolizer.h"
+#include "perfetto/base/temp_file.h"
+
+#include "perfetto/trace/profiling/profile_packet.pb.h"
+#include "perfetto/trace/trace.pb.h"
+#include "perfetto/trace/trace_packet.pb.h"
+
+#include "third_party/pprof/profile.pb.h"
+
+namespace perfetto {
+namespace trace_to_text {
 
 namespace {
 
 constexpr const char* kDefaultTmp = "/tmp";
 
+void MaybeDemangle(std::string* name) {
+  int ignored;
+  char* data = abi::__cxa_demangle(name->c_str(), nullptr, nullptr, &ignored);
+  if (data) {
+    *name = data;
+    free(data);
+  }
+}
+
 std::string GetTemp() {
   const char* tmp = getenv("TMPDIR");
   if (tmp == nullptr)
@@ -44,47 +59,251 @@
   return tmp;
 }
 
-}  // namespace
+using ::perfetto::protos::ProfilePacket;
 
-namespace perfetto {
-namespace trace_to_text {
+using GLine = ::perftools::profiles::Line;
+using GMapping = ::perftools::profiles::Mapping;
+using GLocation = ::perftools::profiles::Location;
+using GProfile = ::perftools::profiles::Profile;
+using GValueType = ::perftools::profiles::ValueType;
+using GFunction = ::perftools::profiles::Function;
+using GSample = ::perftools::profiles::Sample;
 
-int TraceToProfile(std::istream* input,
-                   std::ostream* output,
-                   uint64_t pid,
-                   std::vector<uint64_t> timestamps) {
-  std::unique_ptr<Symbolizer> symbolizer;
-  auto binary_path = GetPerfettoBinaryPath();
-  if (!binary_path.empty()) {
-#if PERFETTO_BUILDFLAG(PERFETTO_LOCAL_SYMBOLIZER)
-    symbolizer.reset(new LocalSymbolizer(GetPerfettoBinaryPath()));
-#else
-    PERFETTO_ELOG(
-        "This build does not support local symbolization. "
-        "Continuing without symbolization.");
-#endif
+std::string ToHex(const std::string& build_id) {
+  std::string hex_build_id(2 * build_id.size() + 1, ' ');
+  for (size_t i = 0; i < build_id.size(); ++i)
+    snprintf(&(hex_build_id[2 * i]), 3, "%02hhx", build_id[i]);
+  // Remove the trailing nullbyte.
+  hex_build_id.resize(2 * build_id.size());
+  return hex_build_id;
+}
+
+enum Strings : int64_t {
+  kEmpty = 0,
+  kObjects,
+  kAllocObjects,
+  kCount,
+  kSpace,
+  kAllocSpace,
+  kBytes
+};
+
+void DumpProfilePacket(std::vector<ProfilePacket>& packet_fragments,
+                       const std::string& file_prefix) {
+  std::map<uint64_t, std::string> string_lookup;
+  // A profile packet can be split into multiple fragments. We need to iterate
+  // over all of them to reconstruct the original packet.
+  for (const ProfilePacket& packet : packet_fragments) {
+    for (const ProfilePacket::InternedString& interned_string :
+         packet.strings())
+      string_lookup.emplace(interned_string.id(), interned_string.str());
   }
 
-  std::vector<SerializedProfile> profiles;
-  TraceToPprof(input, &profiles, symbolizer.get(), pid, timestamps);
-  if (profiles.empty()) {
-    return 0;
+  std::map<uint64_t, const std::vector<uint64_t>> callstack_lookup;
+  for (const ProfilePacket& packet : packet_fragments) {
+    for (const ProfilePacket::Callstack& callstack : packet.callstacks()) {
+      std::vector<uint64_t> frame_ids(
+          static_cast<size_t>(callstack.frame_ids().size()));
+      std::reverse_copy(callstack.frame_ids().cbegin(),
+                        callstack.frame_ids().cend(), frame_ids.begin());
+      callstack_lookup.emplace(callstack.id(), std::move(frame_ids));
+    }
   }
 
-  std::string temp_dir = GetTemp() + "/heap_profile-XXXXXXX";
-  PERFETTO_CHECK(mkdtemp(&temp_dir[0]));
-  size_t itr = 0;
-  for (const auto& profile : profiles) {
-    std::string filename = temp_dir + "/heap_dump." + std::to_string(++itr) +
-                           "." + std::to_string(profile.pid) + ".pb";
+  std::map<std::string, uint64_t> string_table;
+  string_table[""] = kEmpty;
+  string_table["objects"] = kObjects;
+  string_table["alloc_objects"] = kAllocObjects;
+  string_table["count"] = kCount;
+  string_table["space"] = kSpace;
+  string_table["alloc_space"] = kAllocSpace;
+  string_table["bytes"] = kBytes;
+
+  GProfile profile;
+  GValueType* value_type = profile.add_sample_type();
+  value_type->set_type(kObjects);
+  value_type->set_unit(kCount);
+
+  value_type = profile.add_sample_type();
+  value_type->set_type(kAllocObjects);
+  value_type->set_unit(kCount);
+
+  value_type = profile.add_sample_type();
+  value_type->set_type(kAllocSpace);
+  value_type->set_unit(kBytes);
+
+  // The last value is the default one selected.
+  value_type = profile.add_sample_type();
+  value_type->set_type(kSpace);
+  value_type->set_unit(kBytes);
+
+  for (const ProfilePacket& packet : packet_fragments) {
+    for (const ProfilePacket::Mapping& mapping : packet.mappings()) {
+      GMapping* gmapping = profile.add_mapping();
+      gmapping->set_id(mapping.id());
+      gmapping->set_memory_start(mapping.start());
+      gmapping->set_memory_limit(mapping.end());
+      gmapping->set_file_offset(mapping.offset());
+      std::string filename;
+      for (uint64_t str_id : mapping.path_string_ids()) {
+        auto it = string_lookup.find(str_id);
+        if (it == string_lookup.end()) {
+          PERFETTO_ELOG("Mapping %" PRIu64
+                        " referring to invalid string_id %" PRIu64 ".",
+                        static_cast<uint64_t>(mapping.id()), str_id);
+          continue;
+        }
+
+        filename += "/" + it->second;
+      }
+
+      decltype(string_table)::iterator it;
+      std::tie(it, std::ignore) =
+          string_table.emplace(filename, string_table.size());
+      gmapping->set_filename(static_cast<int64_t>(it->second));
+
+      auto str_it = string_lookup.find(mapping.build_id());
+      if (str_it != string_lookup.end()) {
+        const std::string& build_id = str_it->second;
+        std::tie(it, std::ignore) =
+            string_table.emplace(ToHex(build_id), string_table.size());
+        gmapping->set_build_id(static_cast<int64_t>(it->second));
+      }
+    }
+  }
+
+  std::set<uint64_t> functions_to_dump;
+  for (const ProfilePacket& packet : packet_fragments) {
+    for (const ProfilePacket::Frame& frame : packet.frames()) {
+      GLocation* glocation = profile.add_location();
+      glocation->set_id(frame.id());
+      glocation->set_mapping_id(frame.mapping_id());
+      // TODO(fmayer): This is probably incorrect. Probably should be abs pc.
+      glocation->set_address(frame.rel_pc());
+      GLine* gline = glocation->add_line();
+      gline->set_function_id(frame.function_name_id());
+      functions_to_dump.emplace(frame.function_name_id());
+    }
+  }
+
+  for (uint64_t function_name_id : functions_to_dump) {
+    auto str_it = string_lookup.find(function_name_id);
+    if (str_it == string_lookup.end()) {
+      PERFETTO_ELOG("Function referring to invalid string id %" PRIu64,
+                    function_name_id);
+      continue;
+    }
+    decltype(string_table)::iterator it;
+    std::string function_name = str_it->second;
+    // This assumes both the device that captured the trace and the host
+    // machine use the same mangling scheme. This is a reasonable
+    // assumption as the Itanium ABI is the de-facto standard for mangling.
+    MaybeDemangle(&function_name);
+    std::tie(it, std::ignore) =
+        string_table.emplace(std::move(function_name), string_table.size());
+    GFunction* gfunction = profile.add_function();
+    gfunction->set_id(function_name_id);
+    gfunction->set_name(static_cast<int64_t>(it->second));
+  }
+
+  // We keep the interning table as string -> uint64_t for fast and easy
+  // lookup. When dumping, we need to turn it into a uint64_t -> string
+  // table so we get it sorted by key order.
+  std::map<uint64_t, std::string> inverted_string_table;
+  for (const auto& p : string_table)
+    inverted_string_table[p.second] = p.first;
+  for (const auto& p : inverted_string_table)
+    profile.add_string_table(p.second);
+
+  std::map<uint64_t, std::vector<const ProfilePacket::ProcessHeapSamples*>>
+      heap_samples;
+  for (const ProfilePacket& packet : packet_fragments) {
+    for (const ProfilePacket::ProcessHeapSamples& samples :
+         packet.process_dumps()) {
+      heap_samples[samples.pid()].emplace_back(&samples);
+    }
+  }
+  for (const auto& p : heap_samples) {
+    GProfile cur_profile = profile;
+    uint64_t pid = p.first;
+    for (const ProfilePacket::ProcessHeapSamples* samples : p.second) {
+      if (samples->rejected_concurrent()) {
+        PERFETTO_ELOG("WARNING: The profile for %" PRIu64
+                      " was rejected due to a concurrent profile.",
+                      pid);
+      }
+      if (samples->buffer_overran()) {
+        PERFETTO_ELOG("WARNING: The profile for %" PRIu64
+                      " ended early due to a buffer overrun.",
+                      pid);
+      }
+      if (samples->buffer_corrupted()) {
+        PERFETTO_ELOG("WARNING: The profile for %" PRIu64
+                      " ended early due to a buffer corruption."
+                      " THIS IS ALWAYS A BUG IN HEAPPROFD OR"
+                      " CLIENT MEMORY CORRUPTION.",
+                      pid);
+      }
+
+      for (const ProfilePacket::HeapSample& sample : samples->samples()) {
+        GSample* gsample = cur_profile.add_sample();
+        auto it = callstack_lookup.find(sample.callstack_id());
+        if (it == callstack_lookup.end()) {
+          PERFETTO_ELOG("Callstack referring to invalid callstack id %" PRIu64,
+                        static_cast<uint64_t>(sample.callstack_id()));
+          continue;
+        }
+        for (uint64_t frame_id : it->second)
+          gsample->add_location_id(frame_id);
+        gsample->add_value(
+            static_cast<int64_t>(sample.alloc_count() - sample.free_count()));
+        gsample->add_value(static_cast<int64_t>(sample.alloc_count()));
+        gsample->add_value(static_cast<int64_t>(sample.self_allocated()));
+        gsample->add_value(static_cast<int64_t>(sample.self_allocated() -
+                                                sample.self_freed()));
+      }
+    }
+    std::string filename = file_prefix + std::to_string(pid) + ".pb";
     base::ScopedFile fd(base::OpenFile(filename, O_CREAT | O_WRONLY, 0700));
     if (!fd)
       PERFETTO_FATAL("Failed to open %s", filename.c_str());
-    PERFETTO_CHECK(base::WriteAll(*fd, profile.serialized.c_str(),
-                                  profile.serialized.size()) ==
-                   static_cast<ssize_t>(profile.serialized.size()));
+    std::string serialized = cur_profile.SerializeAsString();
+    PERFETTO_CHECK(base::WriteAll(*fd, serialized.c_str(), serialized.size()) ==
+                   static_cast<ssize_t>(serialized.size()));
   }
+}
+
+}  // namespace
+
+int TraceToProfile(std::istream* input, std::ostream* output) {
+  std::string temp_dir = GetTemp() + "/heap_profile-XXXXXXX";
+  size_t itr = 0;
+  PERFETTO_CHECK(mkdtemp(&temp_dir[0]));
+  std::vector<ProfilePacket> rolling_profile_packets;
+  ForEachPacketInTrace(input, [&temp_dir, &itr, &rolling_profile_packets](
+                                  const protos::TracePacket& packet) {
+    if (!packet.has_profile_packet())
+      return;
+    rolling_profile_packets.emplace_back(packet.profile_packet());
+    if (!packet.profile_packet().continued()) {
+      for (size_t i = 1; i < rolling_profile_packets.size(); ++i) {
+        // Ensure we are not missing a chunk.
+        PERFETTO_CHECK(rolling_profile_packets[i - 1].index() + 1 ==
+                       rolling_profile_packets[i].index());
+      }
+      DumpProfilePacket(rolling_profile_packets,
+                        temp_dir + "/heap_dump." + std::to_string(++itr) + ".");
+      rolling_profile_packets.clear();
+    }
+  });
+
+  if (!rolling_profile_packets.empty()) {
+    *output << "WARNING: Truncated heap dump. Not generating profile."
+            << std::endl;
+  }
+
   *output << "Wrote profiles to " << temp_dir << std::endl;
+
   return 0;
 }
 
diff --git a/tools/trace_to_text/trace_to_profile.h b/tools/trace_to_text/trace_to_profile.h
index 629d3ef..4e84f8e 100644
--- a/tools/trace_to_text/trace_to_profile.h
+++ b/tools/trace_to_text/trace_to_profile.h
@@ -18,15 +18,11 @@
 #define TOOLS_TRACE_TO_TEXT_TRACE_TO_PROFILE_H_
 
 #include <iostream>
-#include <vector>
 
 namespace perfetto {
 namespace trace_to_text {
 
-int TraceToProfile(std::istream* input,
-                   std::ostream* output,
-                   uint64_t pid = 0,
-                   std::vector<uint64_t> timestamps = {});
+int TraceToProfile(std::istream* input, std::ostream* output);
 
 }  // namespace trace_to_text
 }  // namespace perfetto
diff --git a/tools/trace_to_text/trace_to_systrace.cc b/tools/trace_to_text/trace_to_systrace.cc
index 8e8b310..5e07c05 100644
--- a/tools/trace_to_text/trace_to_systrace.cc
+++ b/tools/trace_to_text/trace_to_systrace.cc
@@ -27,20 +27,35 @@
 
 #include "perfetto/base/build_config.h"
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_writer.h"
-#include "perfetto/ext/base/utils.h"
+#include "perfetto/base/paged_memory.h"
+#include "perfetto/base/string_writer.h"
 #include "perfetto/trace_processor/trace_processor.h"
-#include "tools/trace_to_text/utils.h"
 
-#define FILTER_RAW_EVENTS \
-  " where not (name like \"chrome_event.%\" or name like \"track_event.%\")"
+// When running in Web Assembly, fflush() is a no-op and the stdio buffering
+// sends progress updates to JS only when a write ends with \n.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WASM)
+#define PROGRESS_CHAR "\n"
+#else
+#define PROGRESS_CHAR "\r"
+#endif
 
 namespace perfetto {
 namespace trace_to_text {
 
 namespace {
 
+// Having an empty traceEvents object is necessary for trace viewer to
+// load the json properly.
+const char kTraceHeader[] = R"({
+  "traceEvents": [],
+)";
+
+const char kTraceFooter[] = R"(\n",
+  "controllerTraceDataKey": "systraceController"
+})";
+
 const char kProcessDumpHeader[] =
+    ""
     "\"androidProcessDump\": "
     "\"PROCESS DUMP\\nUSER           PID  PPID     VSZ    RSS WCHAN  "
     "PC S NAME                        COMM                       \\n";
@@ -48,6 +63,7 @@
 const char kThreadHeader[] = "USER           PID   TID CMD \\n";
 
 const char kSystemTraceEvents[] =
+    ""
     "  \"systemTraceEvents\": \"";
 
 const char kFtraceHeader[] =
@@ -76,13 +92,6 @@
     "#           TASK-PID    TGID   CPU#  ||||    TIMESTAMP  FUNCTION\\n"
     "#              | |        |      |   ||||       |         |\\n";
 
-// The legacy trace viewer requires a clock sync marker to tie ftrace and
-// userspace clocks together. Trace processor already aligned these clocks, so
-// we just emit a clock sync for an equality mapping.
-const char kSystemTraceEventsFooter[] =
-    "\\n<...>-12345 (-----) [000] ...1 0.000000: tracing_mark_write: "
-    "trace_event_clock_sync: parent_ts=0\\n\"";
-
 inline void FormatProcess(uint32_t pid,
                           uint32_t ppid,
                           const base::StringView& name,
@@ -114,11 +123,11 @@
 
 class QueryWriter {
  public:
-  QueryWriter(trace_processor::TraceProcessor* tp, TraceWriter* trace_writer)
+  QueryWriter(trace_processor::TraceProcessor* tp, std::ostream* output)
       : tp_(tp),
         buffer_(base::PagedMemory::Allocate(kBufferSize)),
         global_writer_(static_cast<char*>(buffer_.Get()), kBufferSize),
-        trace_writer_(trace_writer) {}
+        output_(output) {}
 
   template <typename Callback>
   bool RunQuery(const std::string& sql, Callback callback) {
@@ -129,24 +138,24 @@
       callback(&iterator, &line_writer);
 
       if (global_writer_.pos() + line_writer.pos() >= global_writer_.size()) {
-        fprintf(stderr, "Writing row %" PRIu32 "%c", rows, kProgressChar);
+        fprintf(stderr, "Writing row %" PRIu32 PROGRESS_CHAR, rows);
         auto str = global_writer_.GetStringView();
-        trace_writer_->Write(str.data(), str.size());
+        output_->write(str.data(), static_cast<std::streamsize>(str.size()));
         global_writer_.reset();
       }
       global_writer_.AppendStringView(line_writer.GetStringView());
     }
 
     // Check if we have an error in the iterator and print if so.
-    auto status = iterator.Status();
-    if (!status.ok()) {
-      PERFETTO_ELOG("Error while writing systrace %s", status.c_message());
+    auto opt_error = iterator.GetLastError();
+    if (opt_error.has_value()) {
+      PERFETTO_ELOG("Error while writing systrace %s", opt_error->c_str());
       return false;
     }
 
     // Flush any dangling pieces in the global writer.
     auto str = global_writer_.GetStringView();
-    trace_writer_->Write(str.data(), str.size());
+    output_->write(str.data(), static_cast<std::streamsize>(str.size()));
     global_writer_.reset();
     return true;
   }
@@ -157,42 +166,60 @@
   trace_processor::TraceProcessor* tp_ = nullptr;
   base::PagedMemory buffer_;
   base::StringWriter global_writer_;
-  TraceWriter* trace_writer_;
+  std::ostream* output_ = nullptr;
 };
 
 }  // namespace
 
 int TraceToSystrace(std::istream* input,
                     std::ostream* output,
-                    bool compress,
-                    Keep truncate_keep,
-                    bool full_sort) {
-  std::unique_ptr<TraceWriter> trace_writer(
-      compress ? new DeflateTraceWriter(output) : new TraceWriter(output));
-
+                    bool wrap_in_json) {
   trace_processor::Config config;
-  config.force_full_sort = full_sort;
   std::unique_ptr<trace_processor::TraceProcessor> tp =
       trace_processor::TraceProcessor::CreateInstance(config);
 
-  if (!ReadTrace(tp.get(), input))
-    return 1;
+  // 1MB chunk size seems the best tradeoff on a MacBook Pro 2013 - i7 2.8 GHz.
+  constexpr size_t kChunkSize = 1024 * 1024;
+
+// Printing the status update on stderr can be a perf bottleneck. On WASM print
+// status updates more frequently because it can be slower to parse each chunk.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WASM)
+  constexpr int kStderrRate = 1;
+#else
+  constexpr int kStderrRate = 128;
+#endif
+  uint64_t file_size = 0;
+  for (int i = 0;; i++) {
+    if (i % kStderrRate == 0) {
+      fprintf(stderr, "Loading trace %.2f MB" PROGRESS_CHAR, file_size / 1.0e6);
+      fflush(stderr);
+    }
+
+    std::unique_ptr<uint8_t[]> buf(new uint8_t[kChunkSize]);
+    input->read(reinterpret_cast<char*>(buf.get()), kChunkSize);
+    if (input->bad()) {
+      PERFETTO_ELOG("Failed when reading trace");
+      return 1;
+    }
+
+    auto rsize = input->gcount();
+    if (rsize <= 0)
+      break;
+    file_size += static_cast<uint64_t>(rsize);
+    tp->Parse(std::move(buf), static_cast<size_t>(rsize));
+  }
   tp->NotifyEndOfFile();
 
-  *output << "TRACE:\n";
-  return ExtractSystrace(tp.get(), trace_writer.get(),
-                         /*wrapped_in_json=*/false, truncate_keep);
-}
+  fprintf(stderr, "Loaded trace" PROGRESS_CHAR);
+  fflush(stderr);
 
-int ExtractSystrace(trace_processor::TraceProcessor* tp,
-                    TraceWriter* trace_writer,
-                    bool wrapped_in_json,
-                    Keep truncate_keep) {
   using Iterator = trace_processor::TraceProcessor::Iterator;
 
-  QueryWriter q_writer(tp, trace_writer);
-  if (wrapped_in_json) {
-    trace_writer->Write(kProcessDumpHeader);
+  QueryWriter q_writer(tp.get(), output);
+  if (wrap_in_json) {
+    *output << kTraceHeader;
+
+    *output << kProcessDumpHeader;
 
     // Write out all the processes in the trace.
     // TODO(lalitm): change this query to actually use ppid when it is exposed
@@ -201,84 +228,52 @@
     auto p_callback = [](Iterator* it, base::StringWriter* writer) {
       uint32_t pid = static_cast<uint32_t>(it->Get(0 /* col */).long_value);
       uint32_t ppid = static_cast<uint32_t>(it->Get(1 /* col */).long_value);
-      const auto& name_col = it->Get(2 /* col */);
-      auto name_view = name_col.type == trace_processor::SqlValue::kString
-                           ? base::StringView(name_col.string_value)
-                           : base::StringView();
-      FormatProcess(pid, ppid, name_view, writer);
+      const char* name = it->Get(2 /* col */).string_value;
+      FormatProcess(pid, ppid, name, writer);
     };
     if (!q_writer.RunQuery(kPSql, p_callback))
       return 1;
 
-    trace_writer->Write(kThreadHeader);
+    *output << kThreadHeader;
 
     // Write out all the threads in the trace.
     static const char kTSql[] =
         "select tid, COALESCE(upid, 0), thread.name "
-        "from thread left join process using (upid)";
+        "from thread inner join process using (upid)";
     auto t_callback = [](Iterator* it, base::StringWriter* writer) {
       uint32_t tid = static_cast<uint32_t>(it->Get(0 /* col */).long_value);
       uint32_t tgid = static_cast<uint32_t>(it->Get(1 /* col */).long_value);
-      const auto& name_col = it->Get(2 /* col */);
-      auto name_view = name_col.type == trace_processor::SqlValue::kString
-                           ? base::StringView(name_col.string_value)
-                           : base::StringView();
-      FormatThread(tid, tgid, name_view, writer);
+      const char* name = it->Get(2 /* col */).string_value;
+      FormatThread(tid, tgid, name, writer);
     };
     if (!q_writer.RunQuery(kTSql, t_callback))
       return 1;
 
-    trace_writer->Write("\",\n");
-    trace_writer->Write(kSystemTraceEvents);
-    trace_writer->Write(kFtraceJsonHeader);
+    *output << "\",";
+    *output << kSystemTraceEvents;
+    *output << kFtraceJsonHeader;
   } else {
-    trace_writer->Write(kFtraceHeader);
+    *output << "TRACE:\n";
+    *output << kFtraceHeader;
   }
 
-  fprintf(stderr, "Converting ftrace events%c", kProgressChar);
+  fprintf(stderr, "Converting trace events" PROGRESS_CHAR);
   fflush(stderr);
 
-  static const char kEstimateSql[] =
-      "select count(1) from raw" FILTER_RAW_EVENTS;
-  uint32_t raw_events = 0;
-  auto e_callback = [&raw_events](Iterator* it, base::StringWriter*) {
-    raw_events = static_cast<uint32_t>(it->Get(0).long_value);
-  };
-  if (!q_writer.RunQuery(kEstimateSql, e_callback))
-    return 1;
-
-  auto raw_callback = [wrapped_in_json](Iterator* it,
-                                        base::StringWriter* writer) {
+  static const char kRawSql[] = "select to_ftrace(id) from raw";
+  auto raw_callback = [wrap_in_json](Iterator* it, base::StringWriter* writer) {
     const char* line = it->Get(0 /* col */).string_value;
-    if (wrapped_in_json) {
+    if (wrap_in_json) {
       for (uint32_t i = 0; line[i] != '\0'; i++) {
         char c = line[i];
-        switch (c) {
-          case '\n':
-            writer->AppendLiteral("\\n");
-            break;
-          case '\f':
-            writer->AppendLiteral("\\f");
-            break;
-          case '\b':
-            writer->AppendLiteral("\\b");
-            break;
-          case '\r':
-            writer->AppendLiteral("\\r");
-            break;
-          case '\t':
-            writer->AppendLiteral("\\t");
-            break;
-          case '\\':
-            writer->AppendLiteral("\\\\");
-            break;
-          case '"':
-            writer->AppendLiteral("\\\"");
-            break;
-          default:
-            writer->AppendChar(c);
-            break;
+        if (c == '\n') {
+          writer->AppendLiteral("\\n");
+          continue;
         }
+
+        if (c == '\\' || c == '"')
+          writer->AppendChar('\\');
+        writer->AppendChar(c);
       }
       writer->AppendChar('\\');
       writer->AppendChar('n');
@@ -287,32 +282,11 @@
       writer->AppendChar('\n');
     }
   };
+  if (!q_writer.RunQuery(kRawSql, raw_callback))
+    return 1;
 
-  // An estimate of 130b per ftrace event, allowing some space for the processes
-  // and threads.
-  const uint32_t max_ftrace_events = (140 * 1024 * 1024) / 130;
-
-  static const char kRawEventsQuery[] =
-      "select to_ftrace(id) from raw" FILTER_RAW_EVENTS;
-
-  if (truncate_keep == Keep::kEnd && raw_events > max_ftrace_events) {
-    char end_truncate[150];
-    sprintf(end_truncate, "%s limit %d offset %d", kRawEventsQuery,
-            max_ftrace_events, raw_events - max_ftrace_events);
-    if (!q_writer.RunQuery(end_truncate, raw_callback))
-      return 1;
-  } else if (truncate_keep == Keep::kStart) {
-    char start_truncate[150];
-    sprintf(start_truncate, "%s limit %d", kRawEventsQuery, max_ftrace_events);
-    if (!q_writer.RunQuery(start_truncate, raw_callback))
-      return 1;
-  } else {
-    if (!q_writer.RunQuery(kRawEventsQuery, raw_callback))
-      return 1;
-  }
-
-  if (wrapped_in_json)
-    trace_writer->Write(kSystemTraceEventsFooter);
+  if (wrap_in_json)
+    *output << kTraceFooter;
 
   return 0;
 }
diff --git a/tools/trace_to_text/trace_to_systrace.h b/tools/trace_to_text/trace_to_systrace.h
index 4e540f6..fbb6b38 100644
--- a/tools/trace_to_text/trace_to_systrace.h
+++ b/tools/trace_to_text/trace_to_systrace.h
@@ -20,27 +20,15 @@
 #include <iostream>
 
 namespace perfetto {
-
-namespace trace_processor {
-class TraceProcessor;
-}  // namespace trace_processor
-
 namespace trace_to_text {
 
-class TraceWriter;
-
-enum class Keep { kStart = 0, kEnd, kAll };
-
 int TraceToSystrace(std::istream* input,
                     std::ostream* output,
-                    bool compress,
-                    Keep truncate_keep,
-                    bool full_sort);
+                    bool wrap_in_json);
 
-int ExtractSystrace(trace_processor::TraceProcessor*,
-                    TraceWriter*,
-                    bool wrapped_in_json,
-                    Keep truncate_keep);
+int TraceToSystraceLegacy(std::istream* input,
+                          std::ostream* output,
+                          bool wrap_in_json);
 
 }  // namespace trace_to_text
 }  // namespace perfetto
diff --git a/tools/trace_to_text/trace_to_text.cc b/tools/trace_to_text/trace_to_text.cc
index 6a05a03..872fe58 100644
--- a/tools/trace_to_text/trace_to_text.cc
+++ b/tools/trace_to_text/trace_to_text.cc
@@ -16,31 +16,24 @@
 
 #include "tools/trace_to_text/trace_to_text.h"
 
-#include <zlib.h>
-
 #include <google/protobuf/compiler/importer.h>
 #include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/text_format.h>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/base/scoped_file.h"
 #include "tools/trace_to_text/proto_full_utils.h"
 #include "tools/trace_to_text/utils.h"
 
-#include "protos/perfetto/trace/trace.pbzero.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
-
 namespace perfetto {
 namespace trace_to_text {
 
 namespace {
 using google::protobuf::Descriptor;
 using google::protobuf::DynamicMessageFactory;
-using google::protobuf::FieldDescriptor;
 using google::protobuf::FileDescriptor;
 using google::protobuf::Message;
-using google::protobuf::Reflection;
 using google::protobuf::TextFormat;
 using google::protobuf::compiler::DiskSourceTree;
 using google::protobuf::compiler::Importer;
@@ -66,62 +59,9 @@
   output->BackUp(size - static_cast<int>(bytes_to_copy));
 }
 
-constexpr char kCompressedPacketsPrefix[] = "compressed_packets {\n";
-constexpr char kCompressedPacketsSuffix[] = "}\n";
-
-constexpr char kIndentedPacketPrefix[] = "  packet {\n";
-constexpr char kIndentedPacketSuffix[] = "  }\n";
-
 constexpr char kPacketPrefix[] = "packet {\n";
 constexpr char kPacketSuffix[] = "}\n";
 
-void PrintCompressedPackets(const std::string& packets,
-                            Message* compressed_msg_scratch,
-                            ZeroCopyOutputStream* output) {
-  uint8_t out[4096];
-  std::vector<uint8_t> data;
-
-  z_stream stream{};
-  stream.next_in =
-      const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(packets.data()));
-  stream.avail_in = static_cast<unsigned int>(packets.length());
-
-  if (inflateInit(&stream) != Z_OK) {
-    PERFETTO_ELOG("Error when initiliazing zlib to decompress packets");
-    return;
-  }
-
-  int ret;
-  do {
-    stream.next_out = out;
-    stream.avail_out = sizeof(out);
-    ret = inflate(&stream, Z_NO_FLUSH);
-    if (ret != Z_STREAM_END && ret != Z_OK) {
-      PERFETTO_ELOG("Error when decompressing packets");
-      return;
-    }
-    data.insert(data.end(), out, out + (sizeof(out) - stream.avail_out));
-  } while (ret != Z_STREAM_END);
-  inflateEnd(&stream);
-
-  protos::pbzero::Trace::Decoder decoder(data.data(), data.size());
-  WriteToZeroCopyOutput(output, kCompressedPacketsPrefix,
-                        sizeof(kCompressedPacketsPrefix) - 1);
-  TextFormat::Printer printer;
-  printer.SetInitialIndentLevel(2);
-  for (auto it = decoder.packet(); it; ++it) {
-    protozero::ConstBytes cb = *it;
-    compressed_msg_scratch->ParseFromArray(cb.data, static_cast<int>(cb.size));
-    WriteToZeroCopyOutput(output, kIndentedPacketPrefix,
-                          sizeof(kIndentedPacketPrefix) - 1);
-    printer.Print(*compressed_msg_scratch, output);
-    WriteToZeroCopyOutput(output, kIndentedPacketSuffix,
-                          sizeof(kIndentedPacketSuffix) - 1);
-  }
-  WriteToZeroCopyOutput(output, kCompressedPacketsSuffix,
-                        sizeof(kCompressedPacketsSuffix) - 1);
-}
-
 }  // namespace
 
 int TraceToText(std::istream* input, std::ostream* output) {
@@ -136,11 +76,11 @@
   }
 
   DiskSourceTree dst;
-  dst.MapPath("", "");
+  dst.MapPath("perfetto", "protos/perfetto");
   MultiFileErrorCollectorImpl mfe;
   Importer importer(&dst, &mfe);
   const FileDescriptor* parsed_file =
-      importer.Import("protos/perfetto/trace/trace_packet.proto");
+      importer.Import("perfetto/trace/trace_packet.proto");
 
   DynamicMessageFactory dmf;
   const Descriptor* trace_descriptor = parsed_file->message_type(0);
@@ -149,35 +89,18 @@
   OstreamOutputStream* zero_copy_output_ptr = &zero_copy_output;
   Message* msg = root->New();
 
-  constexpr uint32_t kCompressedPacketFieldDescriptor = 50;
-  const Reflection* reflect = msg->GetReflection();
-  const FieldDescriptor* compressed_desc =
-      trace_descriptor->FindFieldByNumber(kCompressedPacketFieldDescriptor);
-  Message* compressed_msg_scratch = root->New();
-  std::string compressed_packet_scratch;
-
-  TextFormat::Printer printer;
-  printer.SetInitialIndentLevel(1);
   ForEachPacketBlobInTrace(
-      input, [msg, reflect, compressed_desc, zero_copy_output_ptr,
-              &compressed_packet_scratch, compressed_msg_scratch,
-              &printer](std::unique_ptr<char[]> buf, size_t size) {
+      input,
+      [msg, zero_copy_output_ptr](std::unique_ptr<char[]> buf, size_t size) {
         if (!msg->ParseFromArray(buf.get(), static_cast<int>(size))) {
           PERFETTO_ELOG("Skipping invalid packet");
           return;
         }
-        if (reflect->HasField(*msg, compressed_desc)) {
-          const auto& compressed_packets = reflect->GetStringReference(
-              *msg, compressed_desc, &compressed_packet_scratch);
-          PrintCompressedPackets(compressed_packets, compressed_msg_scratch,
-                                 zero_copy_output_ptr);
-        } else {
-          WriteToZeroCopyOutput(zero_copy_output_ptr, kPacketPrefix,
-                                sizeof(kPacketPrefix) - 1);
-          printer.Print(*msg, zero_copy_output_ptr);
-          WriteToZeroCopyOutput(zero_copy_output_ptr, kPacketSuffix,
-                                sizeof(kPacketSuffix) - 1);
-        }
+        WriteToZeroCopyOutput(zero_copy_output_ptr, kPacketPrefix,
+                              sizeof(kPacketPrefix) - 1);
+        TextFormat::Print(*msg, zero_copy_output_ptr);
+        WriteToZeroCopyOutput(zero_copy_output_ptr, kPacketSuffix,
+                              sizeof(kPacketSuffix) - 1);
       });
   return 0;
 }
diff --git a/tools/trace_to_text/utils.cc b/tools/trace_to_text/utils.cc
index 5055b98..111f5d4 100644
--- a/tools/trace_to_text/utils.cc
+++ b/tools/trace_to_text/utils.cc
@@ -24,75 +24,14 @@
 #include <utility>
 
 #include "perfetto/base/logging.h"
-#include "perfetto/ext/base/string_splitter.h"
-#include "perfetto/ext/traced/sys_stats_counters.h"
-#include "protos/perfetto/trace/ftrace/ftrace_stats.pb.h"
+#include "perfetto/trace/ftrace/ftrace_stats.pb.h"
+#include "perfetto/traced/sys_stats_counters.h"
 
-#include "protos/perfetto/trace/trace.pb.h"
-#include "protos/perfetto/trace/trace_packet.pb.h"
+#include "perfetto/trace/trace.pb.h"
+#include "perfetto/trace/trace_packet.pb.h"
 
 namespace perfetto {
 namespace trace_to_text {
-namespace {
-
-using Iterator = trace_processor::TraceProcessor::Iterator;
-
-constexpr const char* kQueryUnsymbolized =
-    "select spm.name, spm.build_id, spf.rel_pc "
-    "from stack_profile_frame spf "
-    "join stack_profile_mapping spm "
-    "on spf.mapping = spm.id "
-    "where spm.build_id != '' and spf.symbol_set_id == 0";
-
-constexpr size_t kCompressionBufferSize = 500 * 1024;
-
-std::string FromHex(const char* str, size_t size) {
-  if (size % 2) {
-    PERFETTO_DFATAL_OR_ELOG("Failed to parse hex %s", str);
-    return "";
-  }
-  std::string result(size / 2, '\0');
-  for (size_t i = 0; i < size; i += 2) {
-    char hex_byte[3];
-    hex_byte[0] = str[i];
-    hex_byte[1] = str[i + 1];
-    hex_byte[2] = '\0';
-    char* end;
-    long int byte = strtol(hex_byte, &end, 16);
-    if (*end != '\0') {
-      PERFETTO_DFATAL_OR_ELOG("Failed to parse hex %s", str);
-      return "";
-    }
-    result[i / 2] = static_cast<char>(byte);
-  }
-  return result;
-}
-
-std::string FromHex(const std::string& str) {
-  return FromHex(str.c_str(), str.size());
-}
-
-using NameAndBuildIdPair = std::pair<std::string, std::string>;
-
-std::map<NameAndBuildIdPair, std::vector<uint64_t>> GetUnsymbolizedFrames(
-    trace_processor::TraceProcessor* tp) {
-  std::map<std::pair<std::string, std::string>, std::vector<uint64_t>> res;
-  Iterator it = tp->ExecuteQuery(kQueryUnsymbolized);
-  while (it.Next()) {
-    auto name_and_buildid =
-        std::make_pair(it.Get(0).string_value, FromHex(it.Get(1).string_value));
-    int64_t rel_pc = it.Get(2).long_value;
-    res[name_and_buildid].emplace_back(rel_pc);
-  }
-  if (!it.Status().ok()) {
-    PERFETTO_DFATAL_OR_ELOG("Invalid iterator: %s",
-                            it.Status().message().c_str());
-    return {};
-  }
-  return res;
-}
-
-}  // namespace
 
 void ForEachPacketBlobInTrace(
     std::istream* input,
@@ -152,144 +91,6 @@
         }
         f(packet);
       });
-  fprintf(stderr, "\n");
-}
-
-std::vector<std::string> GetPerfettoBinaryPath() {
-  std::vector<std::string> roots;
-  const char* root = getenv("PERFETTO_BINARY_PATH");
-  if (root != nullptr) {
-    for (base::StringSplitter sp(std::string(root), ':'); sp.Next();)
-      roots.emplace_back(sp.cur_token(), sp.cur_token_size());
-  }
-  return roots;
-}
-
-bool ReadTrace(trace_processor::TraceProcessor* tp, std::istream* input) {
-  // 1MB chunk size seems the best tradeoff on a MacBook Pro 2013 - i7 2.8 GHz.
-  constexpr size_t kChunkSize = 1024 * 1024;
-
-// Printing the status update on stderr can be a perf bottleneck. On WASM print
-// status updates more frequently because it can be slower to parse each chunk.
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WASM)
-  constexpr int kStderrRate = 1;
-#else
-  constexpr int kStderrRate = 128;
-#endif
-  uint64_t file_size = 0;
-
-  for (int i = 0;; i++) {
-    if (i % kStderrRate == 0) {
-      fprintf(stderr, "Loading trace %.2f MB%c", file_size / 1.0e6,
-              kProgressChar);
-      fflush(stderr);
-    }
-
-    std::unique_ptr<uint8_t[]> buf(new uint8_t[kChunkSize]);
-    input->read(reinterpret_cast<char*>(buf.get()), kChunkSize);
-    if (input->bad()) {
-      PERFETTO_ELOG("Failed when reading trace");
-      return false;
-    }
-
-    auto rsize = input->gcount();
-    if (rsize <= 0)
-      break;
-    file_size += static_cast<uint64_t>(rsize);
-    tp->Parse(std::move(buf), static_cast<size_t>(rsize));
-  }
-
-  fprintf(stderr, "Loaded trace%c", kProgressChar);
-  fflush(stderr);
-  return true;
-}
-
-void SymbolizeDatabase(
-    trace_processor::TraceProcessor* tp,
-    Symbolizer* symbolizer,
-    std::function<void(perfetto::protos::TracePacket)> callback) {
-  PERFETTO_CHECK(symbolizer);
-  auto unsymbolized = GetUnsymbolizedFrames(tp);
-  for (auto it = unsymbolized.cbegin(); it != unsymbolized.cend(); ++it) {
-    const auto& name_and_buildid = it->first;
-    const std::vector<uint64_t>& rel_pcs = it->second;
-    auto res = symbolizer->Symbolize(name_and_buildid.first,
-                                     name_and_buildid.second, rel_pcs);
-    if (res.empty())
-      continue;
-
-    perfetto::protos::TracePacket packet;
-    perfetto::protos::ModuleSymbols* module_symbols =
-        packet.mutable_module_symbols();
-    module_symbols->set_path(name_and_buildid.first);
-    module_symbols->set_build_id(name_and_buildid.second);
-    PERFETTO_DCHECK(res.size() == rel_pcs.size());
-    for (size_t i = 0; i < res.size(); ++i) {
-      auto* address_symbols = module_symbols->add_address_symbols();
-      address_symbols->set_address(rel_pcs[i]);
-      for (const SymbolizedFrame& frame : res[i]) {
-        auto* line = address_symbols->add_lines();
-        line->set_function_name(frame.function_name);
-        line->set_source_file_name(frame.file_name);
-        line->set_line_number(frame.line);
-      }
-    }
-    callback(std::move(packet));
-  }
-}
-
-TraceWriter::TraceWriter(std::ostream* output) : output_(output) {}
-
-TraceWriter::~TraceWriter() = default;
-
-void TraceWriter::Write(std::string s) {
-  Write(s.data(), s.size());
-}
-
-void TraceWriter::Write(const char* data, size_t sz) {
-  output_->write(data, static_cast<std::streamsize>(sz));
-}
-
-DeflateTraceWriter::DeflateTraceWriter(std::ostream* output)
-    : TraceWriter(output),
-      buf_(base::PagedMemory::Allocate(kCompressionBufferSize)),
-      start_(static_cast<uint8_t*>(buf_.Get())),
-      end_(start_ + buf_.size()) {
-  CheckEq(deflateInit(&stream_, 9), Z_OK);
-  stream_.next_out = start_;
-  stream_.avail_out = static_cast<unsigned int>(end_ - start_);
-}
-
-DeflateTraceWriter::~DeflateTraceWriter() {
-  while (deflate(&stream_, Z_FINISH) != Z_STREAM_END) {
-    Flush();
-  }
-  CheckEq(deflateEnd(&stream_), Z_OK);
-}
-
-void DeflateTraceWriter::Write(const char* data, size_t sz) {
-  stream_.next_in = reinterpret_cast<uint8_t*>(const_cast<char*>(data));
-  stream_.avail_in = static_cast<unsigned int>(sz);
-  while (stream_.avail_in > 0) {
-    CheckEq(deflate(&stream_, Z_NO_FLUSH), Z_OK);
-    if (stream_.avail_out == 0) {
-      Flush();
-    }
-  }
-}
-
-void DeflateTraceWriter::Flush() {
-  TraceWriter::Write(reinterpret_cast<char*>(start_),
-                     static_cast<size_t>(stream_.next_out - start_));
-  stream_.next_out = start_;
-  stream_.avail_out = static_cast<unsigned int>(end_ - start_);
-}
-
-void DeflateTraceWriter::CheckEq(int actual_code, int expected_code) {
-  if (actual_code == expected_code)
-    return;
-  PERFETTO_FATAL("Expected %d got %d: %s", actual_code, expected_code,
-                 stream_.msg);
 }
 
 }  // namespace trace_to_text
diff --git a/tools/trace_to_text/utils.h b/tools/trace_to_text/utils.h
index f4004c3..a861a3a 100644
--- a/tools/trace_to_text/utils.h
+++ b/tools/trace_to_text/utils.h
@@ -24,14 +24,8 @@
 #include <functional>
 #include <iostream>
 #include <memory>
-#include <vector>
-
-#include <zlib.h>
 
 #include "perfetto/base/build_config.h"
-#include "perfetto/ext/base/paged_memory.h"
-#include "perfetto/profiling/symbolizer.h"
-#include "perfetto/trace_processor/trace_processor.h"
 
 namespace perfetto {
 
@@ -57,44 +51,6 @@
     std::istream* input,
     const std::function<void(const protos::TracePacket&)>&);
 
-std::vector<std::string> GetPerfettoBinaryPath();
-
-bool ReadTrace(trace_processor::TraceProcessor* tp, std::istream* input);
-
-void SymbolizeDatabase(
-    trace_processor::TraceProcessor* tp,
-    Symbolizer* symbolizer,
-    std::function<void(perfetto::protos::TracePacket)> callback);
-
-class TraceWriter {
- public:
-  TraceWriter(std::ostream* output);
-  virtual ~TraceWriter();
-
-  void Write(std::string s);
-  virtual void Write(const char* data, size_t sz);
-
- private:
-  std::ostream* output_;
-};
-
-class DeflateTraceWriter : public TraceWriter {
- public:
-  DeflateTraceWriter(std::ostream* output);
-  ~DeflateTraceWriter() override;
-
-  void Write(const char* data, size_t sz) override;
-
- private:
-  void Flush();
-  void CheckEq(int actual_code, int expected_code);
-
-  z_stream stream_{};
-  base::PagedMemory buf_;
-  uint8_t* const start_;
-  uint8_t* const end_;
-};
-
 }  // namespace trace_to_text
 }  // namespace perfetto
 
diff --git a/tools/traceconv b/tools/traceconv
index 6cfe78a..080cd72 100755
--- a/tools/traceconv
+++ b/tools/traceconv
@@ -20,7 +20,7 @@
 # cat ./traceconv | bash
 # cat ./traceconv | python -
 
-BASH_FALLBACK = """ "
+BASH_FALLBACK=""" "
 exec python - "$@" <<'#'EOF
 #"""
 
@@ -30,22 +30,19 @@
 import tempfile
 import urllib
 
-# Keep this in sync with the SHAs in catapult file
-# systrace/systrace/tracing_agents/atrace_from_file_agent.py.
 TRACE_TO_TEXT_SHAS = {
-    'linux': '46ce31e5bf41aa872bb27b2694d912ddce03b87b',
-    'mac': 'ca6d3f969282e323fc8cc3dc73ba9722df1f2649',
+  'linux': '91cbc8addb9adc4dcc0cbf398e7ff67a8ad14ece',
+  'mac': '36a1313c8900b3b59b40e6f07488a6d2c7ffaa94',
 }
 TRACE_TO_TEXT_PATH = tempfile.gettempdir()
-TRACE_TO_TEXT_BASE_URL = ('https://storage.googleapis.com/perfetto/')
-
+TRACE_TO_TEXT_BASE_URL = (
+    'https://storage.googleapis.com/perfetto/')
 
 def check_hash(file_name, sha_value):
   with open(file_name, 'rb') as fd:
     file_hash = hashlib.sha1(fd.read()).hexdigest()
     return file_hash == sha_value
 
-
 def load_trace_to_text(platform):
   sha_value = TRACE_TO_TEXT_SHAS[platform]
   file_name = 'trace_to_text-' + platform + '-' + sha_value
@@ -65,7 +62,6 @@
   os.chmod(local_file, 0o755)
   return local_file
 
-
 def main(argv):
   platform = None
   if sys.platform.startswith('linux'):
@@ -79,7 +75,6 @@
   trace_to_text_binary = load_trace_to_text(platform)
   os.execv(trace_to_text_binary, [trace_to_text_binary] + argv[1:])
 
-
 if __name__ == '__main__':
   sys.exit(main(sys.argv))
 
diff --git a/tools/update_trace_processor b/tools/update_trace_processor
deleted file mode 100755
index 6601ca9..0000000
--- a/tools/update_trace_processor
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/bash
-
-set -e
-
-DIR=$(mktemp -d out/perfetto.XXXXXX)
-
-function cleanup {
-  rm -rf "$DIR"
-  echo "Deleted temp working directory $DIR"
-}
-
-#trap cleanup EXIT
-
-function is_mac {
-  ! test -d /proc
-  return $?
-}
-
-tools/gn gen $DIR --args='is_clang=true is_debug=false'
-tools/ninja -C $DIR trace_processor_shell
-
-if which shasum; then
-  NEW_SHA=$(shasum $DIR/trace_processor_shell | cut -f1 -d' ') # Mac OS
-else
-  NEW_SHA=$(sha1sum $DIR/trace_processor_shell | cut -f1 -d' ') # Linux
-fi
-
-if is_mac; then
-  platform=mac
-else
-  platform=linux
-fi
-
-name=trace_processor_shell-$platform-$NEW_SHA
-
-gsutil cp $DIR/trace_processor_shell gs://perfetto/$name
-gsutil acl ch -u AllUsers:R gs://perfetto/$name
-
-echo 'Now run the following command to update tools/trace_processor:'
-echo "sed \"s/'$platform': '[^']*',/'$platform': '$NEW_SHA',/\" --in-place tools/trace_processor"
diff --git a/ui/BUILD.gn b/ui/BUILD.gn
index f7f5529..4b81c71 100644
--- a/ui/BUILD.gn
+++ b/ui/BUILD.gn
@@ -16,11 +16,7 @@
 import("../gn/wasm.gni")
 import("../protos/perfetto/trace_processor/proto_files.gni")
 
-# Prevent that this file is accidentally included in embedder builds.
-assert(enable_perfetto_ui)
-
 ui_dir = "$root_build_dir/ui"
-chrome_extension_dir = "$root_build_dir/chrome_extension"
 ui_gen_dir = "$target_out_dir/gen"
 nodejs_root = "../buildtools/nodejs"
 nodejs_bin = rebase_path("$nodejs_root/bin", root_build_dir)
@@ -32,8 +28,6 @@
   deps = [
     ":assets_dist",
     ":catapult_dist",
-    ":chrome_extension_assets_dist",
-    ":chrome_extension_bundle_dist",
     ":controller_bundle_dist",
     ":engine_bundle_dist",
     ":frontend_bundle_dist",
@@ -158,14 +152,6 @@
   output = "$target_out_dir/frontend_bundle.js"
 }
 
-bundle("chrome_extension_bundle") {
-  deps = [
-    ":transpile_all_ts",
-  ]
-  input = "$target_out_dir/chrome_extension/index.js"
-  output = "$target_out_dir/chrome_extension_bundle.js"
-}
-
 bundle("controller_bundle") {
   deps = [
     ":transpile_all_ts",
@@ -198,11 +184,7 @@
   foreach(proto, trace_processor_protos) {
     inputs += [ "../protos/perfetto/trace_processor/$proto.proto" ]
   }
-  inputs += [
-    "../protos/perfetto/config/perfetto_config.proto",
-    "../protos/perfetto/ipc/consumer_port.proto",
-    "../protos/perfetto/ipc/wire_protocol.proto",
-  ]
+  inputs += [ "../protos/perfetto/config/perfetto_config.proto" ]
   outputs = [
     "$ui_gen_dir/protos.js",
   ]
@@ -213,7 +195,7 @@
            "-w",
            "commonjs",
            "-p",
-           rebase_path("..", root_build_dir),
+           rebase_path("../protos", root_build_dir),
            "-o",
            rebase_path(outputs[0], root_build_dir),
          ] + rebase_path(inputs, root_build_dir)
@@ -234,7 +216,7 @@
   node_cmd = "pbts"
   args = [
     "-p",
-    rebase_path("..", root_build_dir),
+    rebase_path("../protos", root_build_dir),
     "-o",
     rebase_path(outputs[0], root_build_dir),
     rebase_path(inputs[0], root_build_dir),
@@ -260,7 +242,6 @@
     "$target_out_dir/engine/index.js",
     "$target_out_dir/controller/index.js",
     "$target_out_dir/query/index.js",
-    "$target_out_dir/chrome_extension/index.js",
   ]
 
   depfile = root_out_dir + "/tsc.d"
@@ -295,8 +276,6 @@
   "src/assets/topbar.scss",
   "src/assets/record.scss",
   "src/assets/common.scss",
-  "src/assets/modal.scss",
-  "src/assets/details.scss",
 ]
 
 # Build css.
@@ -380,16 +359,6 @@
     "$ui_dir/assets/{{source_file_part}}",
   ]
 }
-copy("chrome_extension_assets_dist") {
-  sources = [
-    "src/assets/logo-128.png",
-    "src/assets/logo.png",
-    "src/chrome_extension/manifest.json",
-  ]
-  outputs = [
-    "$chrome_extension_dir/{{source_file_part}}",
-  ]
-}
 
 sorcery("frontend_bundle_dist") {
   deps = [
@@ -399,14 +368,6 @@
   output = "$ui_dir/frontend_bundle.js"
 }
 
-sorcery("chrome_extension_bundle_dist") {
-  deps = [
-    ":chrome_extension_bundle",
-  ]
-  input = "$target_out_dir/chrome_extension_bundle.js"
-  output = "$chrome_extension_dir/chrome_extension_bundle.js"
-}
-
 sorcery("controller_bundle_dist") {
   deps = [
     ":controller_bundle",
diff --git a/ui/PRESUBMIT.py b/ui/PRESUBMIT.py
index a4d6df0..362bf9a 100644
--- a/ui/PRESUBMIT.py
+++ b/ui/PRESUBMIT.py
@@ -17,45 +17,42 @@
 
 
 def CheckChange(input, output):
-  results = []
-  results += CheckTslint(input, output)
-  return results
+    results = []
+    results += CheckTslint(input, output)
+    return results
 
 
 def CheckChangeOnUpload(input_api, output_api):
-  return CheckChange(input_api, output_api)
+    return CheckChange(input_api, output_api)
 
 
 def CheckChangeOnCommit(input_api, output_api):
-  return CheckChange(input_api, output_api)
+    return CheckChange(input_api, output_api)
 
 
 def CheckTslint(input_api, output_api):
-  path = input_api.os_path
-  ui_path = input_api.PresubmitLocalPath()
-  node = path.join(ui_path, 'node')
-  tslint = path.join(ui_path, 'node_modules', '.bin', 'tslint')
+    path = input_api.os_path
+    ui_path = input_api.PresubmitLocalPath();
+    node = path.join(ui_path, 'node')
+    tslint = path.join(ui_path, 'node_modules', '.bin', 'tslint')
 
-  if not path.exists(tslint):
-    repo_root = input_api.change.RepositoryRoot()
-    install_path = path.join(repo_root, 'tools', 'install-build-deps')
-    return [
-        output_api.PresubmitError("Tslint not found. Please first run\n" +
-                                  "$ {0} --ui".format(install_path))
-    ]
+    if not path.exists(tslint):
+        repo_root = input_api.change.RepositoryRoot()
+        install_path = path.join(repo_root, 'tools', 'install-build-deps')
+        return [
+            output_api.PresubmitError("Tslint not found. Please first run\n" +
+                "$ {0} --ui".format(install_path))
+        ]
 
-  # Some tslint rules require type information and thus need the whole
-  # project. We therefore call tslint on the whole project instead of only the
-  # changed files. It is possible to break tslint on files that was not
-  # changed by changing the type of an object.
-  if subprocess.call(
-      [node, tslint, '--project', ui_path, '--format', 'codeFrame']):
-    return [
-        output_api.PresubmitError("""\
+    # Some tslint rules require type information and thus need the whole
+    # project. We therefore call tslint on the whole project instead of only the
+    # changed files. It is possible to break tslint on files that was not
+    # changed by changing the type of an object.
+    if subprocess.call([node, tslint, '--project', ui_path,
+                        '--format', 'codeFrame']):
+        return [
+            output_api.PresubmitError("""\
 There were tslint errors. You may be able to fix some of them using
-$ {} {} --project {} --fix
-
-If this is unexpected: did you remember to do a UI build before running the
-presubmit?""".format(relpath(node), relpath(tslint), ui_path))
-    ]
-  return []
+$ {} {} --project {} --fix""".format(relpath(node), relpath(tslint), ui_path))
+        ]
+    return []
diff --git a/ui/index.html b/ui/index.html
index c375f93..ad3d369 100644
--- a/ui/index.html
+++ b/ui/index.html
@@ -10,10 +10,7 @@
   <link rel="preload" href="trace_processor.wasm" as="fetch">
 </head>
 <body>
-  <main>
-    <div class="full-page-loading-screen"></div>
-  </main>
-  <div id="main-modal" aria-hidden="true" class="modal micromodal-slide"></div>
+  <div class="full-page-loading-screen"></div>
 </body>
 </html>
 <script src="frontend_bundle.js"></script>
diff --git a/ui/node_modules/.gitignore b/ui/node_modules/.gitignore
index b15ad74..355164c 100644
--- a/ui/node_modules/.gitignore
+++ b/ui/node_modules/.gitignore
@@ -1,2 +1 @@
 */
-custom_utils
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 276f9d6..66c7197 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -86,14 +86,6 @@
       "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
       "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA="
     },
-    "@types/chrome": {
-      "version": "0.0.86",
-      "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.86.tgz",
-      "integrity": "sha512-7ehebPf/5IR64SYdD2Vig0q0oUCNbWMQ29kASlNJaHVVtA5/J/DnrxnYVPCID70o7LgHdYsav6I4/XdqAxjTLQ==",
-      "requires": {
-        "@types/filesystem": "*"
-      }
-    },
     "@types/color-convert": {
       "version": "1.9.0",
       "resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-1.9.0.tgz",
@@ -113,19 +105,6 @@
       "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
       "dev": true
     },
-    "@types/filesystem": {
-      "version": "0.0.29",
-      "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.29.tgz",
-      "integrity": "sha512-85/1KfRedmfPGsbK8YzeaQUyV1FQAvMPMTuWFQ5EkLd2w7szhNO96bk3Rh/SKmOfd9co2rCLf0Voy4o7ECBOvw==",
-      "requires": {
-        "@types/filewriter": "*"
-      }
-    },
-    "@types/filewriter": {
-      "version": "0.0.28",
-      "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.28.tgz",
-      "integrity": "sha1-wFTor02d11205jq8dviFFocU1LM="
-    },
     "@types/jest": {
       "version": "22.2.3",
       "resolved": "https://registry.npmjs.org/@types/jest/-/jest-22.2.3.tgz",
@@ -147,24 +126,10 @@
       "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.17.tgz",
       "integrity": "sha512-3N3FRd/rA1v5glXjb90YdYUa+sOB7WrkU2rAhKZnF4TKD86Cym9swtulGuH0p9nxo7fP5woRNa8b0oFTpCO1bg=="
     },
-    "@types/pako": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/@types/pako/-/pako-1.0.1.tgz",
-      "integrity": "sha512-GdZbRSJ3Cv5fiwT6I0SQ3ckeN2PWNqxd26W9Z2fCK1tGrrasGy4puvNFtnddqH9UJFMQYXxEuuB7B8UK+LLwSg=="
-    },
     "@types/puppeteer": {
-      "version": "1.12.4",
-      "resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-1.12.4.tgz",
-      "integrity": "sha512-aaGbJaJ9TuF9vZfTeoh876sBa+rYJWPwtsmHmYr28pGr42ewJnkDTq2aeSKEmS39SqUdkwLj73y/d7rBSp7mDQ==",
-      "dev": true,
-      "requires": {
-        "@types/node": "*"
-      }
-    },
-    "@types/resolve": {
-      "version": "0.0.8",
-      "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz",
-      "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==",
+      "version": "1.12.1",
+      "resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-1.12.1.tgz",
+      "integrity": "sha512-6qpe7XXM93iWh8quEP8Ay516Vmfc2r+ZAxFH3Mt6fx3vzmZz+4Q+hYxc9PxeEIXJhWLAAPYAgAiM/vLHEUwGpw==",
       "dev": true,
       "requires": {
         "@types/node": "*"
@@ -178,11 +143,6 @@
         "@types/node": "*"
       }
     },
-    "@types/w3c-web-usb": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/@types/w3c-web-usb/-/w3c-web-usb-1.0.3.tgz",
-      "integrity": "sha512-XilIvno46lLRyOj/1G5z88M6iimYs3dr3LNdSN9UxSWifytKsBMmRtAi53X3j0ThrrqyVotqrSeaYv9a0I131w=="
-    },
     "abab": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz",
@@ -1375,9 +1335,9 @@
       "dev": true
     },
     "builtin-modules": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz",
-      "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==",
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+      "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
       "dev": true
     },
     "bytes": {
@@ -1830,9 +1790,6 @@
         "array-find-index": "^1.0.1"
       }
     },
-    "custom_utils": {
-      "version": "file:src/base/utils"
-    },
     "dashdash": {
       "version": "1.14.1",
       "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -1906,6 +1863,7 @@
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
       "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+      "dev": true,
       "requires": {
         "object-keys": "^1.0.12"
       }
@@ -2008,11 +1966,6 @@
       "integrity": "sha1-p2o+0YVb56ASu4rBbLgPPADcKPA=",
       "dev": true
     },
-    "devtools-protocol": {
-      "version": "0.0.681549",
-      "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.681549.tgz",
-      "integrity": "sha512-YVwTu4T4zzgf88Y8+t9lIDT+qAn2YDcig4zRgqq5+4bFACn8WDzbqAhct5zVUhefRMOwLGPXyLFTim1FV7keVg=="
-    },
     "diff": {
       "version": "3.5.0",
       "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
@@ -2175,6 +2128,7 @@
       "version": "1.13.0",
       "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
       "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
+      "dev": true,
       "requires": {
         "es-to-primitive": "^1.2.0",
         "function-bind": "^1.1.1",
@@ -2188,6 +2142,7 @@
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
       "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
+      "dev": true,
       "requires": {
         "is-callable": "^1.1.4",
         "is-date-object": "^1.0.1",
@@ -2210,9 +2165,9 @@
       },
       "dependencies": {
         "es6-promise": {
-          "version": "4.2.6",
-          "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz",
-          "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==",
+          "version": "4.2.5",
+          "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz",
+          "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==",
           "dev": true
         }
       }
@@ -2270,9 +2225,9 @@
       "dev": true
     },
     "estree-walker": {
-      "version": "0.6.0",
-      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.0.tgz",
-      "integrity": "sha512-peq1RfVAVzr3PU/jL31RaOjUKLoZJpObQWJJ+LgfcxDUifyLZ1RjPQZTl0pzj2uJ45b7A7XpyppXvxdEqzo4rw==",
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.5.2.tgz",
+      "integrity": "sha512-XpCnW/AE10ws/kDAs37cngSkvgIR8aN3G0MS85m7dUpuK2EREo9VJ00uvw6Dg/hXEpfsE1I1TvJOJr+Z+TL+ig==",
       "dev": true
     },
     "esutils": {
@@ -2293,11 +2248,6 @@
       "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=",
       "dev": true
     },
-    "events": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz",
-      "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA=="
-    },
     "exec-sh": {
       "version": "0.2.2",
       "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.2.tgz",
@@ -2613,8 +2563,7 @@
         "ansi-regex": {
           "version": "2.1.1",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "aproba": {
           "version": "1.2.0",
@@ -2635,14 +2584,12 @@
         "balanced-match": {
           "version": "1.0.0",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "brace-expansion": {
           "version": "1.1.11",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "balanced-match": "^1.0.0",
             "concat-map": "0.0.1"
@@ -2657,20 +2604,17 @@
         "code-point-at": {
           "version": "1.1.0",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "concat-map": {
           "version": "0.0.1",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "console-control-strings": {
           "version": "1.1.0",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "core-util-is": {
           "version": "1.0.2",
@@ -2787,8 +2731,7 @@
         "inherits": {
           "version": "2.0.3",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "ini": {
           "version": "1.3.5",
@@ -2800,7 +2743,6 @@
           "version": "1.0.0",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "number-is-nan": "^1.0.0"
           }
@@ -2815,7 +2757,6 @@
           "version": "3.0.4",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "brace-expansion": "^1.1.7"
           }
@@ -2823,14 +2764,12 @@
         "minimist": {
           "version": "0.0.8",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "minipass": {
           "version": "2.3.5",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "safe-buffer": "^5.1.2",
             "yallist": "^3.0.0"
@@ -2849,7 +2788,6 @@
           "version": "0.5.1",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "minimist": "0.0.8"
           }
@@ -2930,8 +2868,7 @@
         "number-is-nan": {
           "version": "1.0.1",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "object-assign": {
           "version": "4.1.1",
@@ -2943,7 +2880,6 @@
           "version": "1.4.0",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "wrappy": "1"
           }
@@ -3029,8 +2965,7 @@
         "safe-buffer": {
           "version": "5.1.2",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "safer-buffer": {
           "version": "2.1.2",
@@ -3066,7 +3001,6 @@
           "version": "1.0.2",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "code-point-at": "^1.0.0",
             "is-fullwidth-code-point": "^1.0.0",
@@ -3086,7 +3020,6 @@
           "version": "3.0.1",
           "bundled": true,
           "dev": true,
-          "optional": true,
           "requires": {
             "ansi-regex": "^2.0.0"
           }
@@ -3130,21 +3063,19 @@
         "wrappy": {
           "version": "1.0.2",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         },
         "yallist": {
           "version": "3.0.3",
           "bundled": true,
-          "dev": true,
-          "optional": true
+          "dev": true
         }
       }
     },
     "fstream": {
-      "version": "1.0.12",
-      "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
-      "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
+      "version": "1.0.11",
+      "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
+      "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
       "dev": true,
       "requires": {
         "graceful-fs": "^4.1.2",
@@ -3156,7 +3087,8 @@
     "function-bind": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
-      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+      "dev": true
     },
     "gauge": {
       "version": "2.7.4",
@@ -3349,6 +3281,7 @@
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
       "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+      "dev": true,
       "requires": {
         "function-bind": "^1.1.1"
       }
@@ -3394,7 +3327,8 @@
     "has-symbols": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
-      "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q="
+      "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
+      "dev": true
     },
     "has-unicode": {
       "version": "2.0.1",
@@ -3625,7 +3559,8 @@
     "inherits": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
-      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+      "dev": true
     },
     "invariant": {
       "version": "2.2.4",
@@ -3651,11 +3586,6 @@
         "kind-of": "^3.0.2"
       }
     },
-    "is-arguments": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
-      "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA=="
-    },
     "is-arrayish": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
@@ -3680,7 +3610,8 @@
     "is-callable": {
       "version": "1.1.4",
       "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
-      "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA=="
+      "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
+      "dev": true
     },
     "is-ci": {
       "version": "1.2.1",
@@ -3703,7 +3634,8 @@
     "is-date-object": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
-      "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="
+      "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
+      "dev": true
     },
     "is-descriptor": {
       "version": "0.1.6",
@@ -3772,11 +3704,6 @@
       "integrity": "sha1-lp1J4bszKfa7fwkIm+JleLLd1Go=",
       "dev": true
     },
-    "is-generator-function": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz",
-      "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw=="
-    },
     "is-glob": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
@@ -3843,6 +3770,7 @@
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
       "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+      "dev": true,
       "requires": {
         "has": "^1.0.1"
       }
@@ -3857,6 +3785,7 @@
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
       "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+      "dev": true,
       "requires": {
         "has-symbols": "^1.0.0"
       }
@@ -4460,11 +4389,6 @@
       "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
       "dev": true
     },
-    "jsbn-rsa": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/jsbn-rsa/-/jsbn-rsa-1.0.3.tgz",
-      "integrity": "sha512-mQIfIFLCok6A8IPsFUpvOIlQVS9ctcbbnznWDfpH4IFtt3GHq+qG4ujlcvBiGFY0T8/PCqkvSNFABd5zWMTeVg=="
-    },
     "jsdom": {
       "version": "11.12.0",
       "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz",
@@ -4749,12 +4673,30 @@
       "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
       "dev": true
     },
+    "lodash.assign": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
+      "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=",
+      "dev": true
+    },
+    "lodash.clonedeep": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+      "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=",
+      "dev": true
+    },
     "lodash.isfinite": {
       "version": "3.3.2",
       "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz",
       "integrity": "sha1-+4m2WpqAKBgz8LdHizpRBPiY67M=",
       "dev": true
     },
+    "lodash.mergewith": {
+      "version": "4.6.1",
+      "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz",
+      "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==",
+      "dev": true
+    },
     "lodash.sortby": {
       "version": "4.7.0",
       "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
@@ -4911,11 +4853,6 @@
         "regex-cache": "^0.4.2"
       }
     },
-    "micromodal": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/micromodal/-/micromodal-0.4.0.tgz",
-      "integrity": "sha512-YDku9Fi57S4Sm6oitSy3sr786qSp5L6NbatuH2kEeXf0jStvZgZk4bLBKaoSONBaq3BEvFz3hAaoUa7/pV1Kgg=="
-    },
     "mime": {
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
@@ -5023,8 +4960,7 @@
       "version": "2.12.1",
       "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz",
       "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==",
-      "dev": true,
-      "optional": true
+      "dev": true
     },
     "nanomatch": {
       "version": "1.2.13",
@@ -5125,9 +5061,9 @@
       }
     },
     "node-sass": {
-      "version": "4.12.0",
-      "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.12.0.tgz",
-      "integrity": "sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ==",
+      "version": "4.11.0",
+      "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.11.0.tgz",
+      "integrity": "sha512-bHUdHTphgQJZaF1LASx0kAviPH7sGlcyNhWade4eVIpFp6tsn7SV8xNMTbsQFpEV9VXpnwTTnNYlfsZXgGgmkA==",
       "dev": true,
       "requires": {
         "async-foreach": "^0.1.3",
@@ -5137,10 +5073,12 @@
         "get-stdin": "^4.0.1",
         "glob": "^7.0.3",
         "in-publish": "^2.0.0",
-        "lodash": "^4.17.11",
+        "lodash.assign": "^4.2.0",
+        "lodash.clonedeep": "^4.3.2",
+        "lodash.mergewith": "^4.6.0",
         "meow": "^3.7.0",
         "mkdirp": "^0.5.1",
-        "nan": "^2.13.2",
+        "nan": "^2.10.0",
         "node-gyp": "^3.8.0",
         "npmlog": "^4.0.0",
         "request": "^2.88.0",
@@ -5178,12 +5116,6 @@
             "which": "^1.2.9"
           }
         },
-        "nan": {
-          "version": "2.14.0",
-          "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
-          "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
-          "dev": true
-        },
         "strip-ansi": {
           "version": "3.0.1",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
@@ -5201,11 +5133,6 @@
         }
       }
     },
-    "noice-json-rpc": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/noice-json-rpc/-/noice-json-rpc-1.2.0.tgz",
-      "integrity": "sha512-Wm+otW+drKzdqlSPoSwj34tUEq/Xj1gX6Cr2avrykvTW4IY7d3ngLmP+PErALzS0s9nYRokXvYDM54sbFvLlDA=="
-    },
     "nopt": {
       "version": "3.0.6",
       "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
@@ -5329,7 +5256,8 @@
     "object-keys": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz",
-      "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg=="
+      "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==",
+      "dev": true
     },
     "object-path": {
       "version": "0.9.2",
@@ -5354,17 +5282,6 @@
         }
       }
     },
-    "object.entries": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz",
-      "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==",
-      "requires": {
-        "define-properties": "^1.1.3",
-        "es-abstract": "^1.12.0",
-        "function-bind": "^1.1.1",
-        "has": "^1.0.3"
-      }
-    },
     "object.getownpropertydescriptors": {
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
@@ -5538,11 +5455,6 @@
       "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
       "dev": true
     },
-    "pako": {
-      "version": "1.0.10",
-      "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz",
-      "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw=="
-    },
     "parse-glob": {
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
@@ -5823,9 +5735,9 @@
       "dev": true
     },
     "puppeteer": {
-      "version": "1.16.0",
-      "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.16.0.tgz",
-      "integrity": "sha512-7hcmbUw+6INffSPBdnO8KSjJRg2bLRoI7EeZMf5MHdV5kpyYMeoMR5w8AIiZbKIhYGwrXlbgvO7gFTsXNHShuQ==",
+      "version": "1.12.2",
+      "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.12.2.tgz",
+      "integrity": "sha512-xWSyCeD6EazGlfnQweMpM+Hs6X6PhUYhNTHKFj/axNZDq4OmrVERf70isBf7HsnFgB3zOC1+23/8+wCAZYg+Pg==",
       "dev": true,
       "requires": {
         "debug": "^4.1.0",
@@ -5848,9 +5760,9 @@
           }
         },
         "mime": {
-          "version": "2.4.3",
-          "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.3.tgz",
-          "integrity": "sha512-QgrPRJfE+riq5TPZMcHZOtm8c6K/yYrMbKIoRfapfiGLxS8OTeIfRhUGW5LU7MlRa52KOAGCfUNruqLrIBvWZw==",
+          "version": "2.4.0",
+          "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz",
+          "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==",
           "dev": true
         },
         "ms": {
@@ -5860,9 +5772,9 @@
           "dev": true
         },
         "ws": {
-          "version": "6.2.1",
-          "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
-          "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
+          "version": "6.1.3",
+          "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.3.tgz",
+          "integrity": "sha512-tbSxiT+qJI223AP4iLfQbkbxkwdFcneYinM2+x46Gx2wgvbaOMO36czfdfVUBRTHvzAMRhDd98sA5d/BuWbQdg==",
           "dev": true,
           "requires": {
             "async-limiter": "~1.0.0"
@@ -6430,20 +6342,12 @@
       "dev": true
     },
     "resolve": {
-      "version": "1.11.0",
-      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz",
-      "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==",
+      "version": "1.7.1",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz",
+      "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==",
       "dev": true,
       "requires": {
-        "path-parse": "^1.0.6"
-      },
-      "dependencies": {
-        "path-parse": {
-          "version": "1.0.6",
-          "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
-          "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
-          "dev": true
-        }
+        "path-parse": "^1.0.5"
       }
     },
     "resolve-cwd": {
@@ -6493,338 +6397,95 @@
       }
     },
     "rollup": {
-      "version": "1.17.0",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.17.0.tgz",
-      "integrity": "sha512-k/j1m0NIsI4SYgCJR4MWPstGJOWfJyd6gycKoMhyoKPVXxm+L49XtbUwZyFsrSU2YXsOkM4u1ll9CS/ZgJBUpw==",
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.2.2.tgz",
+      "integrity": "sha512-fsn5KJcfSuejjrv8GV7kZNciElqxyzZdUq8rA3e528JsR3ccxrWwoptyUY8GGLlgMFAQMB3dZW8nWF2I1/xrZA==",
       "dev": true,
       "requires": {
         "@types/estree": "0.0.39",
-        "@types/node": "^12.6.2",
-        "acorn": "^6.2.0"
+        "@types/node": "*",
+        "acorn": "^6.1.0"
       },
       "dependencies": {
-        "@types/node": {
-          "version": "12.6.8",
-          "resolved": "https://registry.npmjs.org/@types/node/-/node-12.6.8.tgz",
-          "integrity": "sha512-aX+gFgA5GHcDi89KG5keey2zf0WfZk/HAQotEamsK2kbey+8yGKcson0hbK8E+v0NArlCJQCqMP161YhV6ZXLg==",
-          "dev": true
-        },
         "acorn": {
-          "version": "6.2.1",
-          "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.1.tgz",
-          "integrity": "sha512-JD0xT5FCRDNyjDda3Lrg/IxFscp9q4tiYtxE1/nOzlKCk7hIRuYjhq1kCNkbPjMRMZuFq20HNQn1I9k8Oj0E+Q==",
+          "version": "6.1.0",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.0.tgz",
+          "integrity": "sha512-MW/FjM+IvU9CgBzjO3UIPCE2pyEwUsoFl+VGdczOPEdxfGFjuKny/gN54mOuX7Qxmb9Rg9MCn2oKiSUeW+pjrw==",
           "dev": true
         }
       }
     },
     "rollup-plugin-commonjs": {
-      "version": "9.3.4",
-      "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.3.4.tgz",
-      "integrity": "sha512-DTZOvRoiVIHHLFBCL4pFxOaJt8pagxsVldEXBOn6wl3/V21wVaj17HFfyzTsQUuou3sZL3lEJZVWKPFblJfI6w==",
+      "version": "9.2.0",
+      "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.2.0.tgz",
+      "integrity": "sha512-0RM5U4Vd6iHjL6rLvr3lKBwnPsaVml+qxOGaaNUWN1lSq6S33KhITOfHmvxV3z2vy9Mk4t0g4rNlVaJJsNQPWA==",
       "dev": true,
       "requires": {
-        "estree-walker": "^0.6.0",
-        "magic-string": "^0.25.2",
-        "resolve": "^1.10.0",
-        "rollup-pluginutils": "^2.6.0"
+        "estree-walker": "^0.5.2",
+        "magic-string": "^0.25.1",
+        "resolve": "^1.8.1",
+        "rollup-pluginutils": "^2.3.3"
+      },
+      "dependencies": {
+        "path-parse": {
+          "version": "1.0.6",
+          "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+          "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+          "dev": true
+        },
+        "resolve": {
+          "version": "1.10.0",
+          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz",
+          "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==",
+          "dev": true,
+          "requires": {
+            "path-parse": "^1.0.6"
+          }
+        }
       }
     },
     "rollup-plugin-node-resolve": {
-      "version": "4.2.4",
-      "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-4.2.4.tgz",
-      "integrity": "sha512-t/64I6l7fZ9BxqD3XlX4ZeO6+5RLKyfpwE2CiPNUKa+GocPlQhf/C208ou8y3AwtNsc6bjSk/8/6y/YAyxCIvw==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-4.0.0.tgz",
+      "integrity": "sha512-7Ni+/M5RPSUBfUaP9alwYQiIKnKeXCOHiqBpKUl9kwp3jX5ZJtgXAait1cne6pGEVUUztPD6skIKH9Kq9sNtfw==",
       "dev": true,
       "requires": {
-        "@types/resolve": "0.0.8",
-        "builtin-modules": "^3.1.0",
+        "builtin-modules": "^3.0.0",
         "is-module": "^1.0.0",
-        "resolve": "^1.10.0"
+        "resolve": "^1.8.1"
+      },
+      "dependencies": {
+        "builtin-modules": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.0.0.tgz",
+          "integrity": "sha512-hMIeU4K2ilbXV6Uv93ZZ0Avg/M91RaKXucQ+4me2Do1txxBDyDZWCBa5bJSLqoNTRpXTLwEzIk1KmloenDDjhg==",
+          "dev": true
+        },
+        "path-parse": {
+          "version": "1.0.6",
+          "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+          "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+          "dev": true
+        },
+        "resolve": {
+          "version": "1.10.0",
+          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz",
+          "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==",
+          "dev": true,
+          "requires": {
+            "path-parse": "^1.0.6"
+          }
+        }
       }
     },
     "rollup-pluginutils": {
-      "version": "2.7.1",
-      "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.7.1.tgz",
-      "integrity": "sha512-3nRf3buQGR9qz/IsSzhZAJyoK663kzseps8itkYHr+Z7ESuaffEPfgRinxbCRA0pf0gzLqkNKkSb8aNVTq75NA==",
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.3.3.tgz",
+      "integrity": "sha512-2XZwja7b6P5q4RZ5FhyX1+f46xi1Z3qBKigLRZ6VTZjwbN0K1IFGMlwm06Uu0Emcre2Z63l77nq/pzn+KxIEoA==",
       "dev": true,
       "requires": {
-        "estree-walker": "^0.6.0",
-        "micromatch": "^3.1.10"
-      },
-      "dependencies": {
-        "arr-diff": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
-          "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
-          "dev": true
-        },
-        "array-unique": {
-          "version": "0.3.2",
-          "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
-          "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
-          "dev": true
-        },
-        "braces": {
-          "version": "2.3.2",
-          "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
-          "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
-          "dev": true,
-          "requires": {
-            "arr-flatten": "^1.1.0",
-            "array-unique": "^0.3.2",
-            "extend-shallow": "^2.0.1",
-            "fill-range": "^4.0.0",
-            "isobject": "^3.0.1",
-            "repeat-element": "^1.1.2",
-            "snapdragon": "^0.8.1",
-            "snapdragon-node": "^2.0.1",
-            "split-string": "^3.0.2",
-            "to-regex": "^3.0.1"
-          },
-          "dependencies": {
-            "extend-shallow": {
-              "version": "2.0.1",
-              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-              "dev": true,
-              "requires": {
-                "is-extendable": "^0.1.0"
-              }
-            }
-          }
-        },
-        "expand-brackets": {
-          "version": "2.1.4",
-          "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
-          "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
-          "dev": true,
-          "requires": {
-            "debug": "^2.3.3",
-            "define-property": "^0.2.5",
-            "extend-shallow": "^2.0.1",
-            "posix-character-classes": "^0.1.0",
-            "regex-not": "^1.0.0",
-            "snapdragon": "^0.8.1",
-            "to-regex": "^3.0.1"
-          },
-          "dependencies": {
-            "define-property": {
-              "version": "0.2.5",
-              "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
-              "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
-              "dev": true,
-              "requires": {
-                "is-descriptor": "^0.1.0"
-              }
-            },
-            "extend-shallow": {
-              "version": "2.0.1",
-              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-              "dev": true,
-              "requires": {
-                "is-extendable": "^0.1.0"
-              }
-            },
-            "is-accessor-descriptor": {
-              "version": "0.1.6",
-              "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
-              "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
-              "dev": true,
-              "requires": {
-                "kind-of": "^3.0.2"
-              },
-              "dependencies": {
-                "kind-of": {
-                  "version": "3.2.2",
-                  "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                  "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-                  "dev": true,
-                  "requires": {
-                    "is-buffer": "^1.1.5"
-                  }
-                }
-              }
-            },
-            "is-data-descriptor": {
-              "version": "0.1.4",
-              "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
-              "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
-              "dev": true,
-              "requires": {
-                "kind-of": "^3.0.2"
-              },
-              "dependencies": {
-                "kind-of": {
-                  "version": "3.2.2",
-                  "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-                  "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-                  "dev": true,
-                  "requires": {
-                    "is-buffer": "^1.1.5"
-                  }
-                }
-              }
-            },
-            "is-descriptor": {
-              "version": "0.1.6",
-              "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
-              "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
-              "dev": true,
-              "requires": {
-                "is-accessor-descriptor": "^0.1.6",
-                "is-data-descriptor": "^0.1.4",
-                "kind-of": "^5.0.0"
-              }
-            },
-            "kind-of": {
-              "version": "5.1.0",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
-              "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
-              "dev": true
-            }
-          }
-        },
-        "extglob": {
-          "version": "2.0.4",
-          "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
-          "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
-          "dev": true,
-          "requires": {
-            "array-unique": "^0.3.2",
-            "define-property": "^1.0.0",
-            "expand-brackets": "^2.1.4",
-            "extend-shallow": "^2.0.1",
-            "fragment-cache": "^0.2.1",
-            "regex-not": "^1.0.0",
-            "snapdragon": "^0.8.1",
-            "to-regex": "^3.0.1"
-          },
-          "dependencies": {
-            "define-property": {
-              "version": "1.0.0",
-              "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-              "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
-              "dev": true,
-              "requires": {
-                "is-descriptor": "^1.0.0"
-              }
-            },
-            "extend-shallow": {
-              "version": "2.0.1",
-              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-              "dev": true,
-              "requires": {
-                "is-extendable": "^0.1.0"
-              }
-            }
-          }
-        },
-        "fill-range": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
-          "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
-          "dev": true,
-          "requires": {
-            "extend-shallow": "^2.0.1",
-            "is-number": "^3.0.0",
-            "repeat-string": "^1.6.1",
-            "to-regex-range": "^2.1.0"
-          },
-          "dependencies": {
-            "extend-shallow": {
-              "version": "2.0.1",
-              "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-              "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-              "dev": true,
-              "requires": {
-                "is-extendable": "^0.1.0"
-              }
-            }
-          }
-        },
-        "is-accessor-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-data-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "^6.0.0"
-          }
-        },
-        "is-descriptor": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "^1.0.0",
-            "is-data-descriptor": "^1.0.0",
-            "kind-of": "^6.0.2"
-          }
-        },
-        "is-number": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
-          "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
-          "dev": true,
-          "requires": {
-            "kind-of": "^3.0.2"
-          },
-          "dependencies": {
-            "kind-of": {
-              "version": "3.2.2",
-              "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-              "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-              "dev": true,
-              "requires": {
-                "is-buffer": "^1.1.5"
-              }
-            }
-          }
-        },
-        "isobject": {
-          "version": "3.0.1",
-          "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
-          "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
-          "dev": true
-        },
-        "kind-of": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
-          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
-          "dev": true
-        },
-        "micromatch": {
-          "version": "3.1.10",
-          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
-          "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
-          "dev": true,
-          "requires": {
-            "arr-diff": "^4.0.0",
-            "array-unique": "^0.3.2",
-            "braces": "^2.3.1",
-            "define-property": "^2.0.2",
-            "extend-shallow": "^3.0.2",
-            "extglob": "^2.0.4",
-            "fragment-cache": "^0.2.1",
-            "kind-of": "^6.0.2",
-            "nanomatch": "^1.2.9",
-            "object.pick": "^1.3.0",
-            "regex-not": "^1.0.0",
-            "snapdragon": "^0.8.1",
-            "to-regex": "^3.0.2"
-          }
-        }
+        "estree-walker": "^0.5.2",
+        "micromatch": "^2.3.11"
       }
     },
     "rsvp": {
@@ -6851,7 +6512,8 @@
     "safe-buffer": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+      "dev": true
     },
     "safe-regex": {
       "version": "1.1.0",
@@ -7982,13 +7644,13 @@
       "dev": true
     },
     "tar": {
-      "version": "2.2.2",
-      "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
-      "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
+      "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
       "dev": true,
       "requires": {
         "block-stream": "*",
-        "fstream": "^1.0.12",
+        "fstream": "^1.0.2",
         "inherits": "2"
       }
     },
@@ -8164,42 +7826,23 @@
       "dev": true
     },
     "tslint": {
-      "version": "5.16.0",
-      "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.16.0.tgz",
-      "integrity": "sha512-UxG2yNxJ5pgGwmMzPMYh/CCnCnh0HfPgtlVRDs1ykZklufFBL1ZoTlWFRz2NQjcoEiDoRp+JyT0lhBbbH/obyA==",
+      "version": "5.12.1",
+      "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.12.1.tgz",
+      "integrity": "sha512-sfodBHOucFg6egff8d1BvuofoOQ/nOeYNfbp7LDlKBcLNrL3lmS5zoiDGyOMdT7YsEXAwWpTdAHwOGOc8eRZAw==",
       "dev": true,
       "requires": {
-        "@babel/code-frame": "^7.0.0",
+        "babel-code-frame": "^6.22.0",
         "builtin-modules": "^1.1.1",
         "chalk": "^2.3.0",
         "commander": "^2.12.1",
         "diff": "^3.2.0",
         "glob": "^7.1.1",
-        "js-yaml": "^3.13.0",
+        "js-yaml": "^3.7.0",
         "minimatch": "^3.0.4",
-        "mkdirp": "^0.5.1",
         "resolve": "^1.3.2",
         "semver": "^5.3.0",
         "tslib": "^1.8.0",
-        "tsutils": "^2.29.0"
-      },
-      "dependencies": {
-        "builtin-modules": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
-          "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
-          "dev": true
-        },
-        "js-yaml": {
-          "version": "3.13.1",
-          "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
-          "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
-          "dev": true,
-          "requires": {
-            "argparse": "^1.0.7",
-            "esprima": "^4.0.0"
-          }
-        }
+        "tsutils": "^2.27.2"
       }
     },
     "tsutils": {
@@ -8242,9 +7885,9 @@
       "dev": true
     },
     "typescript": {
-      "version": "3.4.5",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.5.tgz",
-      "integrity": "sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==",
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.3.3.tgz",
+      "integrity": "sha512-Y21Xqe54TBVp+VDSNbuDYdGw0BpoR/Q6wo/+35M8PAU0vipahnyduJWirxxdxjsAkS7hue53x2zp8gz7F05u0A==",
       "dev": true
     },
     "ua-parser-js": {
@@ -8399,18 +8042,6 @@
       "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
       "dev": true
     },
-    "util": {
-      "version": "0.12.1",
-      "resolved": "https://registry.npmjs.org/util/-/util-0.12.1.tgz",
-      "integrity": "sha512-MREAtYOp+GTt9/+kwf00IYoHZyjM8VU4aVrkzUlejyqaIjd2GztVl5V9hGXKlvBKE3gENn/FMfHE5v6hElXGcQ==",
-      "requires": {
-        "inherits": "^2.0.3",
-        "is-arguments": "^1.0.4",
-        "is-generator-function": "^1.0.7",
-        "object.entries": "^1.1.0",
-        "safe-buffer": "^5.1.2"
-      }
-    },
     "util-deprecate": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
diff --git a/ui/package.json b/ui/package.json
index 7e3b8b5..32244cc 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -11,40 +11,29 @@
   "author": "Perfetto Team",
   "license": "Apache-2.0",
   "dependencies": {
-    "@types/chrome": "0.0.86",
-    "@types/color-convert": "^1.9.0",
     "@types/mithril": "^1.1.16",
-    "@types/pako": "^1.0.1",
     "@types/uuid": "^3.4.4",
-    "@types/w3c-web-usb": "^1.0.3",
+    "@types/color-convert": "^1.9.0",
     "color-convert": "^2.0.0",
-    "custom_utils": "file:src/base/utils",
-    "devtools-protocol": "0.0.681549",
-    "events": "^3.0.0",
     "immer": "^1.12.1",
-    "jsbn-rsa": "^1.0.3",
-    "micromodal": "^0.4.0",
     "mithril": "^1.1.6",
-    "noice-json-rpc": "^1.2.0",
-    "pako": "^1.0.10",
     "protobufjs": "^6.8.8",
-    "util": "^0.12.1",
     "uuid": "^3.3.2"
   },
   "devDependencies": {
     "@types/jest": "^22.2.3",
-    "@types/puppeteer": "^1.12.4",
+    "@types/puppeteer": "^1.12.1",
     "dingusjs": "^0.0.3",
     "jest": "^23.6.0",
     "lite-server": "^2.4.0",
-    "node-sass": "^4.12.0",
-    "puppeteer": "^1.16.0",
-    "rollup": "^1.17.0",
-    "rollup-plugin-commonjs": "^9.3.4",
-    "rollup-plugin-node-resolve": "^4.2.4",
+    "node-sass": "^4.11.0",
+    "puppeteer": "^1.12.2",
+    "rollup": "^1.2.2",
+    "rollup-plugin-commonjs": "^9.2.0",
+    "rollup-plugin-node-resolve": "^4.0.0",
     "sorcery": "^0.10.0",
     "tslib": "^1.9.3",
-    "tslint": "^5.16.0",
-    "typescript": "^3.4.5"
+    "tslint": "^5.12.1",
+    "typescript": "^3.3.3"
   }
 }
diff --git a/ui/rollup.config.js b/ui/rollup.config.js
index e4795c4..65d2ce5 100644
--- a/ui/rollup.config.js
+++ b/ui/rollup.config.js
@@ -3,24 +3,19 @@
 
 export default {
   output: {name: 'perfetto'},
-  plugins:
-      [
-        nodeResolve({
-          mainFields: ['browser'],
-          browser: true,
-          preferBuiltins: false,
-        }),
+  plugins: [
+    nodeResolve({module: false, browser: true}),
 
-        // emscripten conditionally executes require('fs') (likewise for
-        // others), when running under node. Rollup can't find those libraries
-        // so expects these to be present in the global scope, which then fails
-        // at runtime. To avoid this we ignore require('fs') and the like.
-        commonjs({
-          ignore: [
-            'fs',
-            'path',
-            'crypto',
-          ]
-        }),
-      ],
+    // emscripten conditionally executes require('fs') (likewise for others),
+    // when running under node. Rollup can't find those libraries so expects
+    // these to be present in the global scope, which then fails at runtime.
+    // To avoid this we ignore require('fs') and the like.
+    commonjs({
+      ignore: [
+        'fs',
+        'path',
+        'crypto',
+      ]
+    }),
+  ]
 }
diff --git a/ui/src/assets/common.scss b/ui/src/assets/common.scss
index dc4e411..a1abd66 100644
--- a/ui/src/assets/common.scss
+++ b/ui/src/assets/common.scss
@@ -65,14 +65,12 @@
 }
 
 html,
-body,
-body>main {
+body {
     height: 100%;
     width: 100%;
     padding: 0;
     margin: 0;
     user-select: none;
-    overscroll-behavior: none;
 }
 
 h1,
@@ -88,14 +86,14 @@
     user-select: text;
 }
 
-body>main {
+body {
     display: grid;
     grid-template-areas:
       "sidebar topbar"
       "sidebar alerts"
       "sidebar page";
-    grid-template-rows: auto auto 1fr;
-    grid-template-columns: auto 1fr;
+    grid-template-rows: var(--topbar-height) auto 1fr;
+    grid-template-columns: var(--sidebar-width) auto;
     color: #121212;
 }
 
@@ -135,43 +133,6 @@
     flex-direction: column
 }
 
-.split-panel {
-  flex: 1;
-  display: flex;
-  flex-flow: row;
-  position: relative;
-}
-
-.video-panel {
-  position: relative;
-  background-color: #262f3c;
-}
-
-.video-panel-setting {
-  position: sticky;
-  word-wrap: break-word;
-  font-weight: 400;
-  font-size: 15px;
-  font-family: "Raleway";
-  line-height: 1.5;
-  padding: 10px 10px 0px 10px;
-  width: 320px;
-  color: #fff
-}
-
-.video-panel-message {
-  position: sticky;
-  word-wrap: break-word;
-  font-weight: 400;
-  font-size: 12px;
-  font-family: "Raleway";
-  line-height: 1.5;
-  padding: 10px 10px 10px 10px;
-  width: 320px;
-  border-bottom: 1px solid #404854;
-  color: #b4b7ba;
-}
-
 .alerts {
   * {
     user-select: text;
@@ -288,7 +249,6 @@
         @include transition();
         padding: 0 10px;
         display: grid;
-        cursor: grab;
         grid-template-areas: "title pin";
         grid-template-columns: 1fr auto auto;
         align-items: center;
@@ -311,10 +271,9 @@
             grid-area: title;
             margin: 0;
             font-size: 14px;
-            overflow: hidden;
             text-overflow: ellipsis;
             text-align: left;
-            white-space: nowrap;
+            direction: rtl;
             font-family: 'Google Sans';
             color: hsl(213, 22%, 30%);
         }
@@ -327,16 +286,9 @@
           opacity: 0;
         }
 
-        .track-button.show {
-          opacity: 1;
-        }
-
         &:hover .track-button{
           opacity: 1;
         }
-        &.flash {
-          background-color: #ffe263;
-        }
     }
 }
 
@@ -383,6 +335,50 @@
   flex-flow: column nowrap;
 }
 
+.details-content {
+  display: grid;
+  grid-template-rows: auto 1fr;
+
+  .handle {
+    background-color: hsl(215, 1%, 95%);
+    border: 1px solid rgba(0,0,0,0.1);
+    cursor: row-resize;
+    height: 28px;
+    min-height: 28px;
+
+    i.material-icons {
+      font-size: 24px;
+      float: right;
+      vertical-align: middle;
+      margin-right: 5px;
+      margin-top: 1px;
+      &:hover{
+        cursor: pointer;
+      }
+    }
+
+    .handle-title {
+      float: left;
+      font-family: 'Google Sans';
+      color: #3c4b5d;
+      margin-left: 5px;
+      padding: 5px;
+      font-size: 13px;
+    }
+  }
+
+  .details-panel-container {
+    .scroll-limiter {
+      height: 100%;
+      display: flex;
+      flex-direction: column;
+      .panel:last-child {
+        flex-grow: 1;
+      }
+    }
+  }
+}
+
 .overview-timeline {
   height: 100px;
 }
@@ -391,14 +387,87 @@
   height: 12px;
 }
 
-.tickbar {
-  height: 5px;
+.details-panel {
+  padding: 10px;
+  font-family: 'Google Sans';
+  color: #3c4b5d;
+
+  .details-panel-heading {
+    font-size: 16px;
+    padding-bottom: 5px;
+  }
+
+  table {
+    font-size: 14px;
+    width: 50%;
+    min-width: 200px;
+    max-width: 50%;
+    table-layout: fixed;
+    word-wrap: break-word;
+    tr:hover {
+      background-color: hsl(214, 22%, 90%);
+    }
+    th {
+      text-align: left;
+      width: 30%;
+      font-weight: normal;
+    }
+  }
+
 }
 
 .notes-panel {
   height: 20px;
 }
 
+.notes-editor-panel {
+  padding: 10px;
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+  font-family: 'Google Sans';
+  color: #3c4b5d;
+
+  .notes-editor-panel-heading-bar {
+    display: flex;
+    padding-bottom: 8px;
+    font-size: 14px;
+    .notes-editor-panel-heading {
+      padding-top: 3px;
+    }
+    input {
+      vertical-align: middle;
+    }
+  }
+
+  button {
+   background: #262f3c;
+   color: white;
+   border-radius: 10px;
+   font-size: 10px;
+   height: 22px;
+   line-height: 18px;
+   min-width: 7em;
+   margin: auto 0 auto 1rem;
+  }
+
+  input[type=text] {
+    flex-grow: 1;
+    border-radius: 4px;
+    border:1px solid #dcdcdc;
+    padding: 3px;
+    margin: 0 10px;
+    &:focus {
+      outline: none;
+      box-shadow: 1px 1px 1px rgba(23, 32, 44, 0.3);
+    }
+  }
+}
+
+.flame-graph-panel {
+  height: 500px;
+}
+
 header.overview {
   display: flex;
   align-content: center;
@@ -434,46 +503,57 @@
 }
 
 .perf-stats {
+  --perfetto-orange: hsl(45, 100%, 48%);
+  --perfetto-red: hsl(6, 70%, 53%);
   --stroke-color: hsl(217, 39%, 94%);
   position: fixed;
   bottom: 0;
-  left: 0;
-  width: 600px;
   color: var(--stroke-color);
   font-family: monospace;
-  padding: 10px 24px;
+  padding: 2px 0px;
   z-index: 100;
-  background-color: rgba(27, 28, 29, 0.90);
-  button {
-    text-decoration: underline;
-    color: hsl(45, 100%, 48%);
-    &:hover {
-      color: hsl(6, 70%, 53%);
+  button:hover {
+    color: var(--perfetto-red);
+  }
+  &[expanded=true] {
+    width: 600px;
+    background-color: rgba(27, 28, 29, 0.95);
+    button {
+      color: var(--perfetto-orange);
+      &:hover {
+        color: var(--perfetto-red);
+      }
     }
   }
-  .close-button {
-    position: absolute;
-    right: 20px;
-    top: 10px;
-    width: 20px;
-    height: 20px;
-    color: var(--stroke-color)
+  &[expanded=false] {
+    width: var(--sidebar-width);
+    background-color: transparent;
   }
-  & > section {
-    padding: 5px;
-    border-bottom: 1px solid var(--stroke-color);
+  i {
+    margin: 0px 24px;
+    font-size: 30px;
   }
-  div {
-    margin: 2px 0px;
-  }
-  table, td, th {
-    border: 1px solid var(--stroke-color);
-    text-align: center;
-    padding: 4px;
-    margin: 4px 0px;
-  }
-  table {
-    border-collapse: collapse;
+  .perf-stats-content {
+    margin: 10px 24px;
+    & > section {
+      padding: 5px;
+      border-bottom: 1px solid var(--stroke-color);
+    }
+    button {
+      text-decoration: underline;
+    }
+    div {
+      margin: 2px 0px;
+    }
+    table, td, th {
+      border: 1px solid var(--stroke-color);
+      text-align: center;
+      padding: 4px;
+      margin: 4px 0px;
+    }
+    table {
+      border-collapse: collapse;
+    }
   }
 }
 
@@ -504,9 +584,6 @@
     background-color: var(--expanded-background);
     color: white;
     font-weight: bold;
-    .shell.flash {
-      color: #121212;
-    }
   }
   .shell {
     padding: 4px 10px;
@@ -520,27 +597,102 @@
     h1 {
       grid-area: title;
       font-size: 14px;
-      overflow: hidden;
       text-overflow: ellipsis;
       font-family: 'Google Sans';
-      white-space: nowrap;
       text-align: left;
+      direction: rtl;
     }
     .fold-button {
       grid-area: fold-button;
-    }
-    &:hover {
       cursor: pointer;
-      .fold-button {
+      &:hover {
         color: hsl(45, 100%, 48%);
       }
     }
-    &.flash {
-      background-color: #ffe263;
-    }
   }
 }
 
 .time-selection-panel {
   height: 10px;
 }
+
+.log-panel {
+  width: 100%;
+  height: 100%;
+  display: grid;
+  grid-template-rows: auto 1fr;
+
+  header.stale {
+    color: grey;
+  }
+
+  .scrolling-container {
+    overflow-y: scroll;
+    position: relative;
+    width: 100%;
+    background-color: #fefefe;
+    border-bottom: 1px solid hsl(213, 22%, 75%);
+
+    .rows {
+      position: relative;
+      direction: ltr;
+      width: 100%;
+
+      .row {
+        @include transition();
+        position: absolute;
+        width: 100%;
+        height: 20px;
+        line-height: 20px;
+        background-color: hsl(214, 22%, 100%);
+
+        &.D { color: hsl(122, 20%, 40%); }
+        &.V { color: hsl(122, 20%, 30%); }
+        &.I { color: hsl(0, 0%, 20%); }
+        &.W { color: hsl(45, 60%, 45%); }
+        &.E { color: hsl(4, 90%, 58%); }
+        &.F { color: hsl(291, 64%, 42%); }
+        &.stale { color: #aaa; }
+        &:nth-child(even) {
+            background-color: hsl(214, 22%, 95%);
+        }
+        &:hover {
+          background-color: hsl(214, 22%, 90%);
+        }
+        .cell {
+          font-size: 11px;
+          font-family: var(--monospace-font);
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          padding-left: 10px;
+          padding-right: 10px;
+          display: inline-block;
+          &:first-child {
+            padding-left: 5px;
+          }
+          &:last-child {
+            padding-right: 5px;
+          }
+          &:nth-child(1) {
+            width: 110px;
+            text-overflow: clip;
+            text-align: right;
+          }
+          &:nth-child(2) {
+            width: 20px;
+          }
+          &:nth-child(3) {
+            width: 15%;
+          }
+          &:nth-child(4) {
+            width: calc(100% - 110px - 20px - 15%);
+          }
+          &:only-child {
+            width: 100%;
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/ui/src/assets/details.scss b/ui/src/assets/details.scss
deleted file mode 100644
index 5a0e44a..0000000
--- a/ui/src/assets/details.scss
+++ /dev/null
@@ -1,285 +0,0 @@
-// Copyright (C) 2019 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.
-
-.details-content {
-  display: grid;
-  grid-template-rows: auto 1fr;
-
-  .handle {
-    background-color: hsl(215, 1%, 95%);
-    border: 1px solid rgba(0,0,0,0.1);
-    border-bottom: none;
-    cursor: row-resize;
-    height: 28px;
-    min-height: 28px;
-    display: grid;
-    grid-auto-columns: 1fr 30px;
-    grid-template-areas: "tabs button";
-
-    .tabs {
-      display: flex;
-
-      .tab {
-        font-family: 'Google Sans';
-        color: #3c4b5d;
-        padding: 3px 10px 10px 10px;
-        margin-top: 3px;
-        font-size: 13px;
-        border-radius: 5px 5px 0px 0px;
-        background-color: hsla(0, 0%, 75%, 1);
-        border-top: solid 1px hsla(0, 0%, 75%, 1);
-        border-left: solid 1px hsla(0, 0%, 75%, 1);
-        border-right: solid 1px hsla(0, 0%, 75%, 1);
-
-        &[active] {
-          background-color: white;
-          &:hover {
-            cursor: default;
-            background-color: white;
-          }
-        }
-
-        &:hover {
-          cursor: pointer;
-          background-color: hsla(0, 0%, 85%, 1);
-        }
-      }
-    }
-
-    i.material-icons {
-      font-size: 24px;
-      float: right;
-      vertical-align: middle;
-      margin-right: 5px;
-      margin-top: 1px;
-      &:hover{
-        cursor: pointer;
-      }
-    }
-
-    .handle-title {
-      float: left;
-      font-family: 'Google Sans';
-      color: #3c4b5d;
-      margin-left: 5px;
-      padding: 5px;
-      font-size: 13px;
-    }
-  }
-
-  .details-panel-container {
-    .scroll-limiter {
-      height: 100%;
-      display: flex;
-      flex-direction: column;
-      .panel:last-child {
-        flex-grow: 1;
-      }
-    }
-  }
-}
-
-.details-panel {
-  padding: 10px;
-  font-family: 'Google Sans';
-  color: #3c4b5d;
-
-  .details-panel-heading {
-    font-size: 16px;
-    padding-bottom: 5px;
-  }
-
-  table {
-    @include transition(0.1s);
-    font-size: 14px;
-    line-height: 18px;
-    width: 50%;
-    min-width: 200px;
-    max-width: 50%;
-    table-layout: fixed;
-    word-wrap: break-word;
-    tr:hover {
-      background-color: hsl(214, 22%, 90%);
-    }
-    th {
-      text-align: left;
-      width: 30%;
-      font-weight: normal;
-    }
-    .material-icons {
-      @include transition(0.3s);
-      font-size: 16px;
-      border-radius: 3px;
-      margin-left: 5px;
-      border: 1px solid transparent;
-      background-color: #e8e8e8;
-      &:hover {
-        cursor: pointer;
-        border: #475566 solid 1px;
-      }
-    }
-  }
-
-  button {
-    background-color: #262f3c;
-    color: #fff;
-    font-size: 0.875rem;
-    padding-left: 1rem;
-    padding-right: 1rem;
-    padding-top: .5rem;
-    padding-bottom: .5rem;
-    border-radius: .25rem;
-    margin-top: 12px;
-  }
-
-  .explanation {
-    font-size: 14px;
-    width: 35%;
-    margin-top: 10px;
-  }
-
-  .material-icons {
-    vertical-align: middle;
-    margin-right: 10px;
-  }
-}
-
-.notes-editor-panel {
-  padding: 10px;
-  display: flex;
-  flex-direction: column;
-  height: 100%;
-  font-family: 'Google Sans';
-  color: #3c4b5d;
-
-  .notes-editor-panel-heading-bar {
-    display: flex;
-    padding-bottom: 8px;
-    font-size: 14px;
-    .notes-editor-panel-heading {
-      padding-top: 3px;
-    }
-    input {
-      vertical-align: middle;
-    }
-  }
-
-  button {
-   background: #262f3c;
-   color: white;
-   border-radius: 10px;
-   font-size: 10px;
-   height: 22px;
-   line-height: 18px;
-   min-width: 7em;
-   margin: auto 0 auto 1rem;
-  }
-
-  input[type=text] {
-    flex-grow: 1;
-    border-radius: 4px;
-    border:1px solid #dcdcdc;
-    padding: 3px;
-    margin: 0 10px;
-    &:focus {
-      outline: none;
-      box-shadow: 1px 1px 1px rgba(23, 32, 44, 0.3);
-    }
-  }
-}
-
-.flame-graph-panel {
-  height: 500px;
-}
-
-.log-panel {
-  width: 100%;
-  height: 100%;
-  display: grid;
-  grid-template-rows: auto 1fr;
-
-  header.stale {
-    color: grey;
-  }
-
-  .scrolling-container {
-    overflow-y: scroll;
-    position: relative;
-    width: 100%;
-    background-color: #fefefe;
-    border-bottom: 1px solid hsl(213, 22%, 75%);
-
-    .rows {
-      position: relative;
-      direction: ltr;
-      width: 100%;
-
-      .row {
-        @include transition();
-        position: absolute;
-        width: 100%;
-        height: 20px;
-        line-height: 20px;
-        background-color: hsl(214, 22%, 100%);
-
-        &.D { color: hsl(122, 20%, 40%); }
-        &.V { color: hsl(122, 20%, 30%); }
-        &.I { color: hsl(0, 0%, 20%); }
-        &.W { color: hsl(45, 60%, 45%); }
-        &.E { color: hsl(4, 90%, 58%); }
-        &.F { color: hsl(291, 64%, 42%); }
-        &.stale { color: #aaa; }
-        &:nth-child(even) {
-            background-color: hsl(214, 22%, 95%);
-        }
-        &:hover {
-          background-color: hsl(214, 22%, 90%);
-        }
-        .cell {
-          font-size: 11px;
-          font-family: var(--monospace-font);
-          white-space: nowrap;
-          overflow: hidden;
-          text-overflow: ellipsis;
-          padding-left: 10px;
-          padding-right: 10px;
-          display: inline-block;
-          &:first-child {
-            padding-left: 5px;
-          }
-          &:last-child {
-            padding-right: 5px;
-          }
-          &:nth-child(1) {
-            width: 110px;
-            text-overflow: clip;
-            text-align: right;
-          }
-          &:nth-child(2) {
-            width: 20px;
-          }
-          &:nth-child(3) {
-            width: 15%;
-          }
-          &:nth-child(4) {
-            width: calc(100% - 110px - 20px - 15%);
-          }
-          &:only-child {
-            width: 100%;
-          }
-        }
-      }
-    }
-  }
-}
diff --git a/ui/src/assets/logo-128.png b/ui/src/assets/logo-128.png
deleted file mode 100644
index 43a2cd1..0000000
--- a/ui/src/assets/logo-128.png
+++ /dev/null
Binary files differ
diff --git a/ui/src/assets/modal.scss b/ui/src/assets/modal.scss
deleted file mode 100644
index 24a8bfd..0000000
--- a/ui/src/assets/modal.scss
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright (C) 2019 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.
-
-/**************************\
-  Basic Modal Styles
-\**************************/
-.modal {
-  font-family: 'Raleway';
-}
-
-.modal-overlay {
-  position: fixed;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  background: rgba(0,0,0,0.6);
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  z-index: 999;
-}
-
-.modal-container {
-  background-color: #fff;
-  padding: 30px;
-  max-width: 90vw;
-  max-height: 90vh;
-  border-radius: 4px;
-  overflow-y: auto;
-  box-sizing: border-box;
-}
-
-.modal-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.modal-title {
-  margin-top: 0;
-  margin-bottom: 0;
-  font-family: 'Raleway';
-  font-weight: 600;
-  font-size: 1.25rem;
-  line-height: 1.25;
-  color: #262f3c;
-  box-sizing: border-box;
-}
-
-.modal-close {
-  background: transparent;
-  border: 0;
-}
-
-.modal-header .modal-close:before { content: "\2715"; }
-
-.modal-content {
-  margin-top: 2rem;
-  margin-bottom: 2rem;
-  line-height: 1.5;
-  color: rgba(0,0,0,.8);
-}
-
-.modal-btn {
-  font-size: .875rem;
-  padding-left: 1rem;
-  padding-right: 1rem;
-  padding-top: .5rem;
-  padding-bottom: .5rem;
-  background-color: #e6e6e6;
-  color: rgba(0,0,0,.8);
-  border-radius: .25rem;
-  border-style: none;
-  border-width: 0;
-  cursor: pointer;
-  -webkit-appearance: button;
-  text-transform: none;
-  overflow: visible;
-  line-height: 1.15;
-  margin: 5px;
-  will-change: transform;
-  -moz-osx-font-smoothing: grayscale;
-  -webkit-backface-visibility: hidden;
-  backface-visibility: hidden;
-  -webkit-transform: translateZ(0);
-  transform: translateZ(0);
-  transition: -webkit-transform .25s ease-out;
-  transition: transform .25s ease-out;
-  transition: transform .25s ease-out,-webkit-transform .25s ease-out;
-}
-
-.modal-btn:focus, .modal-btn:hover {
-  -webkit-transform: scale(1.05);
-  transform: scale(1.05);
-}
-
-.modal-btn-primary {
-  background-color: #262f3c;
-  color: #fff;
-}
-
-.modal-footer {
-  display: flex;
-  justify-content: space-around;
-}
-
-/**************************\
-  Demo Animation Style
-\**************************/
-@keyframes mmfadeIn {
-    from { opacity: 0; }
-      to { opacity: 1; }
-}
-
-@keyframes mmfadeOut {
-    from { opacity: 1; }
-      to { opacity: 0; }
-}
-
-@keyframes mmslideIn {
-  from { transform: translateY(15%); }
-    to { transform: translateY(0); }
-}
-
-@keyframes mmslideOut {
-    from { transform: translateY(0); }
-    to { transform: translateY(-10%); }
-}
-
-.micromodal-slide {
-  display: none;
-}
-
-.micromodal-slide.is-open {
-  display: block;
-}
-
-.micromodal-slide[aria-hidden="false"] .modal-overlay {
-  animation: mmfadeIn .3s cubic-bezier(0.0, 0.0, 0.2, 1);
-}
-
-.micromodal-slide[aria-hidden="false"] .modal-container {
-  animation: mmslideIn .3s cubic-bezier(0, 0, .2, 1);
-}
-
-.micromodal-slide[aria-hidden="true"] .modal-overlay {
-  animation: mmfadeOut .3s cubic-bezier(0.0, 0.0, 0.2, 1);
-}
-
-.micromodal-slide[aria-hidden="true"] .modal-container {
-  animation: mmslideOut .3s cubic-bezier(0, 0, .2, 1);
-}
-
-.micromodal-slide .modal-container,
-.micromodal-slide .modal-overlay {
-  will-change: transform;
-}
-
-.help {
-  table {
-    margin-bottom: 15px;
-    td {
-      min-width: 250px;
-    }
-    td:first-child {
-      font-family: var(--monospace-font);
-    }
-  }
-  h2 {
-    font: inherit;
-    font-weight: bold;
-  }
-}
-
-.modal-pre {
-  white-space: pre-line;
-}
-
-.modal-logs {
-  white-space: pre-wrap;
-  border: 1px solid #999;
-  background: #eee;
-  font-size: 10px;
-  font-family: monospace;
-  -webkit-user-select: text;
-  margin-top: 10px;
-  min-height: 50px;
-  max-height: 40vh;
-  overflow: scroll;
-}
\ No newline at end of file
diff --git a/ui/src/assets/perfetto.scss b/ui/src/assets/perfetto.scss
index 67c0f5e..059a98a 100644
--- a/ui/src/assets/perfetto.scss
+++ b/ui/src/assets/perfetto.scss
@@ -17,5 +17,3 @@
 @import 'sidebar';
 @import 'topbar';
 @import 'record';
-@import 'modal';
-@import 'details';
diff --git a/ui/src/assets/record.scss b/ui/src/assets/record.scss
index 2de7ccd..b4b6888 100644
--- a/ui/src/assets/record.scss
+++ b/ui/src/assets/record.scss
@@ -12,21 +12,16 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-:root {
-  --record-text-color: #333;
-}
-
 // The whole record page.
 .record-page {
   position: relative;
-  overflow-y: scroll;
+  overflow-y: auto;
   background-color: #fefefe;
   padding: 40px 20px;
 }
 
 // The always-visible centered box that has menu and sections on the right.
 .record-container {
-  position: relative;
   max-width: 900px;
   min-height: 500px;
   margin: auto;
@@ -35,142 +30,9 @@
   background-color: #fff;
   display: grid;
   grid-template-columns: 2fr 5fr;
-  grid-template-rows: auto 1fr;
-  grid-template-areas: "header header"
-                       "sidebar section";
+  grid-template-rows: 1fr;
+  grid-template-areas: "sidebar section";
   overflow: hidden;
-  z-index: 6;
-}
-
-.hider {
-  @include transition(0.2s);
-  position: fixed;
-  left: 0;
-  top: 0;
-  bottom: 0;
-  right: 0;
-  background: #000;
-  opacity: 0.2;
-  z-index: 5;
-}
-
-.record-header {
-  grid-area: header;
-  padding: 10px;
-  display: flex;
-  flex-direction: column;
-  border-bottom: 1px solid #eee;
-
-  .top-part {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-
-    // Connect/start/stop tracing buttons.
-    .button {
-      display: flex;
-      justify-content: flex-end;
-      align-items: center;
-      width: auto;
-      height: 50px;
-      margin: 0;
-      >* {
-        @include transition(0.2s);
-        cursor: pointer;
-        border-radius: 10px;
-        margin: 10px;
-        text-align: center;
-        background-color: #eee;
-        font-family: 'Raleway', sans-serif;
-        font-size: 17px;
-        @media (max-width: 1280px) {
-          font-size: 1.6vw;
-        }
-        padding: 7px;
-
-        &:hover {
-          background-color: hsl(88, 50%, 84%);
-          box-shadow: 0 0 4px 0px #999;
-        }
-
-        &.selected {
-          background-color: hsl(88, 50%, 67%);
-          box-shadow: 0 0 4px 0px #999;
-        }
-
-        &.disabled {
-          background-color: hsl(0, 0%, 97%);
-        }
-      }
-    }
-
-    .target-and-status {
-      display: flex;
-      flex-direction: column;
-      justify-content: space-evenly;
-
-      .target {
-        display: flex;
-        flex-direction: row;
-        align-items: center;
-      }
-
-      label, select, button {
-        font-weight: 100;
-        margin: 3px;
-        color: #333;
-        font-size: 17px;
-        font-family: 'Roboto', sans-serif;
-        align-items: center;
-
-        &.error-label {
-          max-width: 500px;
-          color: rgb(255, 0, 0);
-          font-size: 15px;
-        }
-      }
-      .chip {
-        @include transition();
-        display: flex;
-        align-items: center;
-        border: 1px solid #eee;
-        outline: none;
-        margin: 4px;
-        border-radius: 10px;
-        padding: 4px;
-        height: 30px;
-        &:hover, &:active {
-          box-shadow: 0 0 4px 0px #999;
-          background-color: hsl(88, 50%, 84%);
-        }
-        i {
-          margin: 3px;
-          align-items: center;
-        }
-      }
-    }
-  }
-
-  .note {
-    border: 1px dashed #ddd;
-    background: #f9eeba;
-    margin: var(--record-section-padding);
-    padding: 10px;
-    font-family: 'Roboto', sans-serif;
-    font-size: 14px;
-    line-height: 20px;
-  }
-
-  select {
-    @include transition();
-    margin-left: 10px;
-    border-radius: 0;
-    border: 1px solid #eee;
-    outline: none;
-    &:hover, &:active {
-      box-shadow: 0 0 6px #ccc;
-    }
-  }
 }
 
 // The left-hand-side menu with 'Cpu', 'Memory' etc.
@@ -260,11 +122,6 @@
       }
     }
   }  // li
-
-  &.disabled {
-    opacity: 0.50;
-    pointer-events: none;
-  }
 }  // record-menu
 
 
@@ -401,7 +258,7 @@
       font-size: 14px;
       font-weight: 200;
       min-height: 50px;
-      color: var(--record-text-color);
+      color: #666;
       line-height: 20px;
     }
 
@@ -477,24 +334,21 @@
   // 1) The full-width one (default), e.g. the one used in the main recording
   //    page for the duration of the trace. This one has both an icon and a
   //    label on the top.
-  // 2) The smaller ones (.thin) used in the probes. This one has no icon.
+  // 2) The smaller ones (.thin) used in the probes. This one has no icon and
+  //    the label is just next to the slider.
   .slider {
     @include transition(0.3s);
     display: grid;
     grid-template-columns: 40px 1fr 130px 0;
-    grid-template-rows: 30px min-content 1fr;
-    grid-template-areas: "hdr hdr hdr hdr" "descr descr descr descr"
-    "icon slider label unit";
+    grid-template-rows: 30px 1fr;
+    grid-template-areas: "hdr hdr hdr hdr" "icon slider label unit";
     margin-top: var(--record-section-padding);
 
     &.thin {
-      grid-template-columns: 1fr 1fr 100px 0;
-      grid-template-areas: "hdr hdr hdr hdr" "descr descr descr descr"
-      "slider slider label unit";
-    }
-
-    &.greyed-out {
-      opacity: 0.5;
+      grid-template-columns: 1fr 3fr 100px 0;
+      grid-template-rows: 45px;
+      grid-template-areas: "hdr slider label unit";
+      margin-top: initial;
     }
 
     >* {
@@ -511,16 +365,8 @@
 
     &.thin >header {
       opacity: 1;
-      color: var(--record-text-color);
-      font-size: 14px;
-    }
-
-    &.thin >header.descr {
-      grid-area: descr;
-      font-size: 12px;
       color: #666;
-      height: 20px;
-      line-height: 20px;
+      font-size: 14px;
     }
 
     &:hover > header {
@@ -542,8 +388,6 @@
       scroll-snap-type: mandatory;
       background-color : transparent;
       outline: none;
-      margin-left: -10px;
-      margin-top: -5px;
 
       &::-webkit-slider-runnable-track {
         margin: 10px;
@@ -618,20 +462,18 @@
 
     &.thin .spinner {
       font-size: 14px;
-      margin-top: -5px;
     }
 
     .unit {
       grid-area: unit;
       font-size: 12px;
-      color: var(--record-text-color);
+      color: #666;
       position: relative;
       line-height: 37px;
       overflow: hidden;
       width: 35px;
       left: -45px;
       text-align: right;
-      margin-top: -5px;
     }
   }
 
@@ -656,7 +498,7 @@
       @include transition();
       min-height: 25px;
       font-size: 12px;
-      color: var(--record-text-color);
+      color: #666;
       cursor: pointer;
       padding: 5px 0;
     }
@@ -690,24 +532,6 @@
         }
         margin: 0;
       }
-
-      &.two-columns {
-        height: 400px;
-        width: auto;
-        margin: var(--record-section-padding);
-        optgroup {
-          display: grid;
-          padding: 0;
-          grid-template-columns: 1fr 1fr;
-        }
-        option {
-          &:nth-of-type(2n + 1) {
-            border-left: 1px solid #eee;
-            border-right: 1px solid #eee;
-          }
-          margin: 0;
-        }
-      }
     }
   }
 
@@ -719,10 +543,6 @@
     height: 152px;
   }
 
-  .chrome-categories {
-    height: 152px;
-  }
-
   textarea.extra-input {
     width: 100%;
     height: 60px;
@@ -744,6 +564,7 @@
     user-select: text;
     box-shadow: 0 0 12px #999;
 
+
     @keyframes ripple{
       0% { transform: scale(1.00); }
       30% { transform: scale(1.20); }
@@ -759,13 +580,6 @@
       background-color: #598eca;
     }
 
-    &.no-top-bar {
-      white-space: 'pre';
-      &::before {
-        height: 0;
-      }
-    }
-
     >code {
       display: block;
       margin: 10px 5px 20px 20px;
@@ -841,53 +655,5 @@
         box-shadow: 0 0 6px #ccc;
       }
     }
-    // Stop/cancel buttons
-    .buttons {
-      display: flex;
-      justify-content: center;
-      align-items: center;
-      width: auto;
-      height: 70px;
-      >* {
-        @include transition(0.2s);
-        cursor: pointer;
-        border-radius: 10px;
-        text-align: center;
-        margin: 3px;
-        background-color: #eee;
-        font-family: 'Raleway', sans-serif;
-        flex-grow: 1;
-        font-size: 17px;
-        @media (max-width: 1280px) {
-          font-size: 1.6vw;
-        }
-        padding: 7px;
-
-        &:hover {
-          background-color: hsl(88, 50%, 84%);
-          box-shadow: 0 0 4px 0px #999;
-        }
-
-        &.selected {
-          background-color: hsl(88, 50%, 67%);
-          box-shadow: 0 0 4px 0px #999;
-        }
-      }
-    }
-
-    progress {
-      -webkit-appearance: none;
-      appearance: none;
-      width: 600px;
-      height: 30px;
-      margin: var(--record-section-padding);
-      border-radius: 5px;
-    }
-    ::-webkit-progress-value {
-      background-color: hsl(88, 50%, 67%);
-    }
-    ::-webkit-progress-bar {
-      background-color: #eee;
-    }
   }
 }  // record-section
diff --git a/ui/src/assets/sidebar.scss b/ui/src/assets/sidebar.scss
index cf975f8..10d97cc 100644
--- a/ui/src/assets/sidebar.scss
+++ b/ui/src/assets/sidebar.scss
@@ -11,16 +11,11 @@
 // 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.
-
 .sidebar {
-    --sidebar-padding-bottom: 40px;
     grid-area: sidebar;
     z-index: 4;
     background-color: #262f3c;
-    overflow: visible;
-    width: var(--sidebar-width);
-    display: flex;
-    flex-direction: column;
+    overflow-y: auto;
     >* {
         border-bottom: 1px solid #404854;
     }
@@ -35,7 +30,6 @@
         font-weight: 400;
         font-size: 24px;
         letter-spacing: 0.5px;
-        overflow: visible;
         &:before {
             width: 32px;
             height: 32px;
@@ -47,191 +41,83 @@
             background-repeat: no-repeat;
             margin-right: 15px;
         }
-        >.sidebar-button {
-          display: inline-block;
-          position: relative;
-          height: inherit;
-          background-color: #262f3c;
-          overflow: visible;
-          padding: 0 10px;
-          border-radius: 0 5px 5px 0;
-          border-bottom: inherit;
-          >button {
-            vertical-align: middle;
-          }
+    }
+    >section {
+        @include transition();
+        padding: 20px 0;
+        max-height: 80px;
+        overflow: hidden;
+        .section-header {
+            cursor: pointer;
+            >h1,
+            >h2 {
+                font-family: 'Raleway';
+                letter-spacing: 0.25px;
+                overflow: hidden;
+                text-overflow: ellipsis;
+                white-space: nowrap;
+                margin: 0 24px;
+            }
+            >h1 {
+                color: #fff;
+                font-size: 15px;
+                font-weight: 500;
+            }
+            >h2 {
+                @include transition();
+                color: rgba(255, 255, 255, 0.5);
+                font-size: 12px;
+                margin-top: 8px;
+                font-weight: 400;
+            }
+        }
+        &:hover {
+            background-color: #373f4b;
+        }
+        &.expanded {
+            background-color: #19212b;
+            max-height: unset;
+            .section-header h2 {
+                opacity: 0;
+            }
+            .section-content {
+                pointer-events: inherit;
+                opacity: 1;
+            }
         }
     }
-    .sidebar-scroll {
-      overflow-y: auto;
-      flex: 1;
-      &::-webkit-scrollbar {
-        width: 0.5em;
-      }
-      &::-webkit-scrollbar-track {
-        background-color: #19212b;
-        border-radius: 2px;
-      }
-      &::-webkit-scrollbar-thumb {
-        background: #b4b7ba6e;
-        border-radius: 2px;
-      }
-      >.sidebar-scroll-container {
-        position: relative;
-        min-height: 100%;
-        padding-bottom: var(--sidebar-padding-bottom);
-
-        >section {
+    .section-content {
+        pointer-events: none;
+        @include transition();
+        opacity: 0;
+        color: #b4b7ba;
+        a {
+            color: #b4b7ba;
+        }
+        ul {
+            list-style-type: none;
+            margin: 0;
+            padding: 0;
+        }
+        li {
             @include transition();
-            padding: 20px 0;
-            max-height: 80px;
-            .section-header {
-                cursor: pointer;
-                >h1,
-                >h2 {
-                    font-family: 'Raleway';
-                    letter-spacing: 0.25px;
-                    overflow: hidden;
-                    text-overflow: ellipsis;
-                    white-space: nowrap;
-                    margin: 0 24px;
-                }
-                >h1 {
-                    color: #fff;
-                    font-size: 15px;
-                    font-weight: 500;
-                }
-                >h2 {
-                    @include transition();
-                    color: rgba(255, 255, 255, 0.5);
-                    font-size: 12px;
-                    margin-top: 8px;
-                    font-weight: 400;
-                }
+            a {
+                line-height: 24px;
+                font-size: 14px;
+                font-weight: 400;
+                font-family: 'Raleway';
+                letter-spacing: 0.5px;
+                padding: 5px 24px;
+                text-decoration: none;
+                display: block;
+            }
+            .material-icons {
+                vertical-align: middle;
+                margin-right: 10px;
             }
             &:hover {
                 background-color: #373f4b;
             }
-            &.expanded {
-                background-color: #19212b;
-                max-height: unset;
-                .section-header h2 {
-                    opacity: 0;
-                }
-                .section-content {
-                    pointer-events: inherit;
-                    opacity: 1;
-                }
-            }
         }
-
-        .section-content {
-            pointer-events: none;
-            @include transition();
-            opacity: 0;
-            color: #b4b7ba;
-            a {
-                color: #b4b7ba;
-            }
-            ul {
-                list-style-type: none;
-                margin: 0;
-                padding: 0;
-            }
-            li {
-                @include transition();
-                a {
-                    line-height: 24px;
-                    font-size: 14px;
-                    font-weight: 400;
-                    font-family: 'Raleway';
-                    letter-spacing: 0.5px;
-                    padding: 5px 24px;
-                    text-decoration: none;
-                    display: block;
-                    &[disabled] {
-                      text-decoration: line-through;
-                    }
-                }
-                .material-icons {
-                    vertical-align: middle;
-                    margin-right: 10px;
-                }
-                &:hover {
-                    background-color: #373f4b;
-                }
-            }
-        }
-      }
     }
-
-    .sidebar-footer {
-      position: absolute;
-      bottom: 0;
-      padding: 2px 10px;
-      display: grid;
-      height: - var(--sidebar-padding-bottom);
-      grid-template-columns: repeat(4, min-content);
-      grid-gap: 10px;
-
-      > button {
-        color: hsl(217, 39%, 94%);
-        i {
-          font-size: 24px;
-        }
-
-        &:hover {
-          color: hsl(45, 100%, 48%);
-        }
-      }
-
-      > .num-queued-queries {
-        width: 24px;
-        height: 22px;
-        line-height: 22px;
-        margin: 1px 0;
-        background: #12161b;
-        color: #4e71b3;
-        border-radius: 5px;
-        font-size: 12px;
-        text-align: center;
-        &.rpc {
-          background: #7aca75;
-          color: #12161b;
-        }
-        &.failed {
-          background: #d32f2f;
-          color: #fff;
-        }
-        > div {
-          font-size: 10px;
-          line-height: 11px;
-        }
-      }
-    }
-}
-
-.hide-sidebar {
-  margin-left: calc(var(--sidebar-width) * -1);
-  .sidebar-button {
-    left: 96px;
-  }
-}
-
-.show-sidebar .sidebar-button {
-  left: 46px;
-}
-
-.keycap {
-  background-color: #fafbfc;
-  border: 1px solid #d1d5da;
-  border-bottom-color: #c6cbd1;
-  border-radius: 3px;
-  box-shadow: inset 0 -1px 0 #c6cbd1;
-  color: #444d56;
-  display: inline-block;
-  font-family: var(--monospace-font);
-  vertical-align: middle;
-
-  line-height: 20px;
-  padding: 3px 7px;
 }
diff --git a/ui/src/assets/topbar.scss b/ui/src/assets/topbar.scss
index 49d7afb..671c119 100644
--- a/ui/src/assets/topbar.scss
+++ b/ui/src/assets/topbar.scss
@@ -23,23 +23,23 @@
     overflow: visible;
     background-color: hsl(215, 1%, 95%);
     box-shadow: 0px -3px 14px 2px #bbb;
-    min-height: var(--topbar-height);
-    display: flex;
-    justify-content: center;
-    align-items: center;
+    line-height: var(--topbar-height);
     .omnibox {
         @include omnibox-width();
         @include transition(0.25s);
         display: grid;
-        grid-template-areas: "icon input stepthrough";
-        grid-template-columns: 34px auto max-content;
+        grid-template-areas: "icon input";
+        grid-template-columns: 34px auto;
         border-radius: 20px;
         background-color: #fcfcfc;
         border: 0;
+        margin: 6px auto 0 auto;
+        height: 36px;
         line-height: 36px;
         &:before {
             @include material-icon('search');
             vertical-align: middle;
+            font-size: 32px;
             margin: 5px;
             color: #aaa;
             grid-area: icon;
@@ -94,23 +94,6 @@
                 content: 'bubble_chart';
             }
         }
-        .stepthrough {
-          grid-area: stepthrough;
-          display: flex;
-          font: inherit;
-          font-size: 14px;
-          font-family: 'Google Sans';
-          color: #aaa;
-          .current {
-            padding-right: 10px;
-          }
-          .material-icons {
-            vertical-align: middle;
-            &.left {
-              border-right: rgb(218, 217, 217) solid 1px;
-            }
-          }
-        }
     }
     .omnibox-results {
         @include transition(0.25s);
@@ -147,8 +130,6 @@
         bottom: 0;
         height: 1px;
         width: 100%;
-      }
-      .progress-anim {
         &:before {
             content: '';
             position: absolute;
diff --git a/ui/src/base/extract_utils.ts b/ui/src/base/extract_utils.ts
deleted file mode 100644
index a82bfbf..0000000
--- a/ui/src/base/extract_utils.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {perfetto} from '../gen/protos';
-
-// In this file are contained a few functions to simplify the proto parsing.
-
-export function extractTraceConfig(enableTracingRequest: Uint8Array):
-    Uint8Array|undefined {
-  try {
-    const enableTracingObject =
-        perfetto.protos.EnableTracingRequest.decode(enableTracingRequest);
-    if (!enableTracingObject.traceConfig) return undefined;
-    return perfetto.protos.TraceConfig.encode(enableTracingObject.traceConfig)
-        .finish();
-  } catch (e) {  // This catch is for possible proto encoding/decoding issues.
-    console.error('Error extracting the config: ', e.message);
-    return undefined;
-  }
-}
-
-export function extractDurationFromTraceConfig(traceConfigProto: Uint8Array) {
-  try {
-    return perfetto.protos.TraceConfig.decode(traceConfigProto).durationMs;
-  } catch (e) {  // This catch is for possible proto encoding/decoding issues.
-    return undefined;
-  }
-}
\ No newline at end of file
diff --git a/ui/src/base/http_utils.ts b/ui/src/base/http_utils.ts
deleted file mode 100644
index 8e54718..0000000
--- a/ui/src/base/http_utils.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2019 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.
-
-export function fetchWithTimeout(
-    input: RequestInfo, init: RequestInit, timeoutMs: number) {
-  return new Promise<Response>((resolve, reject) => {
-    const timer = setTimeout(
-        () => reject(
-            new Error(`fetch(${input}) timed out after ${timeoutMs} ms`)),
-        timeoutMs);
-    fetch(input, init)
-        .then(response => resolve(response))
-        .catch(err => reject(err))
-        .finally(() => clearTimeout(timer));
-  });
-}
diff --git a/ui/src/base/logging.ts b/ui/src/base/logging.ts
index caefe56..c3279c1 100644
--- a/ui/src/base/logging.ts
+++ b/ui/src/base/logging.ts
@@ -12,10 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-export type ErrorHandler = (err: string) => void;
-
-let errorHandler: ErrorHandler = (_: string) => {};
-
 export function assertExists<A>(value: A | null | undefined): A {
   if (value === null || value === undefined) {
     throw new Error('Value doesn\'t exist');
@@ -32,31 +28,3 @@
 export function assertFalse(value: boolean, optMsg?: string) {
   assertTrue(!value, optMsg);
 }
-
-export function setErrorHandler(handler: ErrorHandler) {
-  errorHandler = handler;
-}
-
-export function reportError(err: ErrorEvent|PromiseRejectionEvent|{}) {
-  let errLog = '';
-  let errorObj = undefined;
-
-  if (err instanceof ErrorEvent) {
-    errLog = err.message;
-    errorObj = err.error;
-  } else if (err instanceof PromiseRejectionEvent) {
-    errLog = `${err.reason}`;
-    errorObj = err.reason;
-  } else {
-    errLog = `${err}`;
-  }
-  if (errorObj !== undefined) {
-    const errStack = (errorObj as {stack?: string}).stack;
-    errLog += '\n';
-    errLog += errStack !== undefined ? errStack : JSON.stringify(errorObj);
-  }
-  errLog += `\n\nUA: ${navigator.userAgent}\n`;
-
-  console.error(errLog, err);
-  errorHandler(errLog);
-}
\ No newline at end of file
diff --git a/ui/src/base/string_utils.ts b/ui/src/base/string_utils.ts
deleted file mode 100644
index efe8fb0..0000000
--- a/ui/src/base/string_utils.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (C) 2019 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.
-
-export function uint8ArrayToBase64(buffer: Uint8Array): string {
-  return btoa(uint8ArrayToString(buffer));
-}
-
-// This function will not handle correctly buffers with a large number of
-// elements due to a js limitation on the number of arguments of a function.
-// The apply will in fact do a call like
-// 'String.fromCharCode(buffer[0],buffer[1],...)'.
-export function uint8ArrayToString(buffer: Uint8Array): string {
-  return String.fromCharCode.apply(null, Array.from(buffer));
-}
-
-export function stringToUint8Array(str: string): Uint8Array {
-  const bufView = new Uint8Array(new ArrayBuffer(str.length));
-  const strLen = str.length;
-  for (let i = 0; i < strLen; i++) {
-    bufView[i] = str.charCodeAt(i);
-  }
-  return bufView;
-}
\ No newline at end of file
diff --git a/ui/src/base/string_utils_jsdomtest.ts b/ui/src/base/string_utils_jsdomtest.ts
deleted file mode 100644
index e8bae93..0000000
--- a/ui/src/base/string_utils_jsdomtest.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {
-  stringToUint8Array,
-  uint8ArrayToBase64,
-  uint8ArrayToString
-} from './string_utils';
-
-test('uint8ArrayToBase64', () => {
-  const bytes = [...'Hello, world'].map(c => c.charCodeAt(0));
-  const buffer = new Uint8Array(bytes);
-  expect(uint8ArrayToBase64(buffer)).toEqual('SGVsbG8sIHdvcmxk');
-});
-
-test('stringToBufferToString', () => {
-  const testString = 'Hello world!';
-  const buffer = stringToUint8Array(testString);
-  const convertedBack = uint8ArrayToString(buffer);
-  expect(testString).toEqual(convertedBack);
-});
-
-test('bufferToStringToBuffer', () => {
-  const bytes = [...'Hello, world'].map(c => c.charCodeAt(0));
-  const buffer = new Uint8Array(bytes);
-  const toString = uint8ArrayToString(buffer);
-  const convertedBack = stringToUint8Array(toString);
-  expect(convertedBack).toEqual(buffer);
-});
diff --git a/ui/src/base/utils/index-browser.js b/ui/src/base/utils/index-browser.js
deleted file mode 100644
index 51a6d05..0000000
--- a/ui/src/base/utils/index-browser.js
+++ /dev/null
@@ -1,3 +0,0 @@
-
-export const _TextDecoder = TextDecoder;
-export const _TextEncoder = TextEncoder;
\ No newline at end of file
diff --git a/ui/src/base/utils/index.js b/ui/src/base/utils/index.js
deleted file mode 100644
index ed27974..0000000
--- a/ui/src/base/utils/index.js
+++ /dev/null
@@ -1,5 +0,0 @@
-
-const util = require('util');
-
-module.exports._TextDecoder = util.TextDecoder;
-module.exports._TextEncoder = util.TextEncoder;
diff --git a/ui/src/base/utils/package.json b/ui/src/base/utils/package.json
deleted file mode 100644
index 4e72520..0000000
--- a/ui/src/base/utils/package.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "name": "custom_utils",
-  "browser": {
-    "./index.js": "./index-browser.js"
-  },
-  "description": "Utils functions. The reason why this module has been created is that 'TextDecoder' and 'TextEncoder' are accessible under the global namespace in the browser, and under the 'util' module in nodejs. Since the tests are running under nodejs, thanks to the 'browser' entry in this package.json, the correct file will be used.",
-  "version": "0.0.1"
-}
diff --git a/ui/src/chrome_extension/chrome_tracing_controller.ts b/ui/src/chrome_extension/chrome_tracing_controller.ts
deleted file mode 100644
index 95ffd71..0000000
--- a/ui/src/chrome_extension/chrome_tracing_controller.ts
+++ /dev/null
@@ -1,206 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {Protocol} from 'devtools-protocol';
-import {ProtocolProxyApi} from 'devtools-protocol/types/protocol-proxy-api';
-import * as rpc from 'noice-json-rpc';
-
-import {extractTraceConfig} from '../base/extract_utils';
-import {TraceConfig} from '../common/protos';
-import {
-  ConsumerPortResponse,
-  GetTraceStatsResponse,
-  ReadBuffersResponse
-} from '../controller/consumer_port_types';
-import {RpcConsumerPort} from '../controller/record_controller_interfaces';
-import {perfetto} from '../gen/protos';
-
-import {DevToolsSocket} from './devtools_socket';
-
-// The chunk size should be large enough to support reasonable batching of data,
-// but small enough not to cause stack overflows in uint8ArrayToString().
-const CHUNK_SIZE: number = 1024 * 1024 * 16;  // 16Mb
-
-export class ChromeTracingController extends RpcConsumerPort {
-  private streamHandle: string|undefined = undefined;
-  private uiPort: chrome.runtime.Port;
-  private api: ProtocolProxyApi.ProtocolApi;
-  private devtoolsSocket: DevToolsSocket;
-  private lastBufferUsageEvent: Protocol.Tracing.BufferUsageEvent|undefined;
-
-  constructor(port: chrome.runtime.Port) {
-    super({
-      onConsumerPortResponse: (message: ConsumerPortResponse) =>
-          this.uiPort.postMessage(message),
-
-      onError: (error: string) =>
-          this.uiPort.postMessage({type: 'ChromeExtensionError', error}),
-
-      onStatus: (status) =>
-          this.uiPort.postMessage({type: 'ChromeExtensionStatus', status})
-    });
-    this.uiPort = port;
-    this.devtoolsSocket = new DevToolsSocket();
-    this.devtoolsSocket.on('close', () => this.resetState());
-    const rpcClient = new rpc.Client(this.devtoolsSocket);
-    this.api = rpcClient.api();
-    this.api.Tracing.on('tracingComplete', this.onTracingComplete.bind(this));
-    this.api.Tracing.on('bufferUsage', this.onBufferUsage.bind(this));
-  }
-
-  handleCommand(methodName: string, requestData: Uint8Array) {
-    switch (methodName) {
-      case 'EnableTracing':
-        this.enableTracing(requestData);
-        break;
-      case 'FreeBuffers':
-        this.freeBuffers();
-        break;
-      case 'ReadBuffers':
-        this.readBuffers();
-        break;
-      case 'DisableTracing':
-        this.disableTracing();
-        break;
-      case 'GetTraceStats':
-        this.getTraceStats();
-        break;
-      case 'GetCategories':
-        this.getCategories();
-        break;
-      default:
-        this.sendErrorMessage('Action not recognized');
-        console.log('Received not recognized message: ', methodName);
-        break;
-    }
-  }
-
-  enableTracing(enableTracingRequest: Uint8Array) {
-    this.resetState();
-    const traceConfigProto = extractTraceConfig(enableTracingRequest);
-    if (!traceConfigProto) {
-      this.sendErrorMessage('Invalid trace config');
-      return;
-    }
-    const traceConfig = TraceConfig.decode(traceConfigProto);
-    const chromeConfig = this.extractChromeConfig(traceConfig);
-    this.handleStartTracing(chromeConfig);
-  }
-
-  // TODO(nicomazz): write unit test for this
-  extractChromeConfig(perfettoConfig: TraceConfig):
-      Protocol.Tracing.TraceConfig {
-    for (const ds of perfettoConfig.dataSources) {
-      if (ds.config && ds.config.name === 'org.chromium.trace_event' &&
-          ds.config.chromeConfig && ds.config.chromeConfig.traceConfig) {
-        const chromeConfigJsonString = ds.config.chromeConfig.traceConfig;
-        return JSON.parse(chromeConfigJsonString) as
-            Protocol.Tracing.TraceConfig;
-      }
-    }
-    return {};
-  }
-
-  freeBuffers() {
-    this.devtoolsSocket.detach();
-    this.sendMessage({type: 'FreeBuffersResponse'});
-  }
-
-  async readBuffers(offset = 0) {
-    if (!this.devtoolsSocket.isAttached() || this.streamHandle === undefined) {
-      this.sendErrorMessage('No tracing session to read from');
-      return;
-    }
-
-    const res = await this.api.IO.read(
-        {handle: this.streamHandle, offset, size: CHUNK_SIZE});
-    if (res === undefined) return;
-
-    const chunk = res.base64Encoded ? atob(res.data) : res.data;
-    // The 'as {} as UInt8Array' is done because we can't send ArrayBuffers
-    // trough a chrome.runtime.Port. The conversion from string to ArrayBuffer
-    // takes place on the other side of the port.
-    const response: ReadBuffersResponse = {
-      type: 'ReadBuffersResponse',
-      slices: [{data: chunk as {} as Uint8Array, lastSliceForPacket: res.eof}]
-    };
-    this.sendMessage(response);
-    if (res.eof) return;
-    this.readBuffers(offset + res.data.length);
-  }
-
-  async disableTracing() {
-    await this.api.Tracing.end();
-    this.sendMessage({type: 'DisableTracingResponse'});
-  }
-
-  getTraceStats() {
-    let percentFull = 0;  // If the statistics are not available yet, it is 0.
-    if (this.lastBufferUsageEvent && this.lastBufferUsageEvent.percentFull) {
-      percentFull = this.lastBufferUsageEvent.percentFull;
-    }
-    const stats: perfetto.protos.ITraceStats = {
-      bufferStats:
-          [{bufferSize: 1000, bytesWritten: Math.round(percentFull * 1000)}]
-    };
-    const response: GetTraceStatsResponse = {
-      type: 'GetTraceStatsResponse',
-      traceStats: stats
-    };
-    this.sendMessage(response);
-  }
-
-  getCategories() {
-    const fetchCategories = async () => {
-      const categories = (await this.api.Tracing.getCategories()).categories;
-      this.uiPort.postMessage({type: 'GetCategoriesResponse', categories});
-    };
-    // If a target is already attached, we simply fetch the categories.
-    if (this.devtoolsSocket.isAttached()) {
-      fetchCategories();
-      return;
-    }
-    // Otherwise, we find attach to the target temporarily.
-    this.devtoolsSocket.findAndAttachTarget(async _ => {
-      fetchCategories();
-      this.devtoolsSocket.detach();
-    });
-  }
-
-  resetState() {
-    this.devtoolsSocket.detach();
-    this.streamHandle = undefined;
-  }
-
-  onTracingComplete(params: Protocol.Tracing.TracingCompleteEvent) {
-    this.streamHandle = params.stream;
-    this.sendMessage({type: 'EnableTracingResponse'});
-  }
-
-  onBufferUsage(params: Protocol.Tracing.BufferUsageEvent) {
-    this.lastBufferUsageEvent = params;
-  }
-
-  handleStartTracing(traceConfig: Protocol.Tracing.TraceConfig) {
-    this.devtoolsSocket.findAndAttachTarget(async _ => {
-      await this.api.Tracing.start({
-        traceConfig,
-        streamFormat: 'proto',
-        transferMode: 'ReturnAsStream',
-        streamCompression: 'gzip',
-        bufferUsageReportingInterval: 200
-      });
-    });
-  }
-}
diff --git a/ui/src/chrome_extension/devtools_socket.ts b/ui/src/chrome_extension/devtools_socket.ts
deleted file mode 100644
index aa23f8f..0000000
--- a/ui/src/chrome_extension/devtools_socket.ts
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (C) 2019 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.
-
-import * as rpc from 'noice-json-rpc';
-
-// To really understand how this works it is useful to see the implementation
-// of noice-json-rpc.
-export class DevToolsSocket implements rpc.LikeSocket {
-  private messageCallback: Function = (_: string) => {};
-  private openCallback: Function = () => {};
-  private closeCallback: Function = () => {};
-  private target: chrome.debugger.Debuggee|undefined;
-
-  constructor() {
-    chrome.debugger.onDetach.addListener(this.onDetach.bind(this));
-    chrome.debugger.onEvent.addListener((_source, method, params) => {
-      if (this.messageCallback) {
-        const msg: rpc.JsonRpc2.Notification = {method, params};
-        this.messageCallback(JSON.stringify(msg));
-      }
-    });
-  }
-
-  send(message: string): void {
-    if (this.target === undefined) return;
-
-    const msg: rpc.JsonRpc2.Request = JSON.parse(message);
-    chrome.debugger.sendCommand(
-        this.target, msg.method, msg.params, (result) => {
-          if (result === undefined) result = {};
-          const response: rpc.JsonRpc2.Response = {id: msg.id, result};
-          this.messageCallback(JSON.stringify(response));
-        });
-  }
-
-  // This method will be called once for each event soon after the creation of
-  // this object. To understand better what happens, checking the implementation
-  // of noice-json-rpc is very useful.
-  // While the events "message" and "open" are for implementing the LikeSocket,
-  // "close" is a callback set from ChromeTracingController, to reset the state
-  // after a detach.
-  on(event: string, cb: Function) {
-    if (event === 'message') {
-      this.messageCallback = cb;
-    } else if (event === 'open') {
-      this.openCallback = cb;
-    } else if (event === 'close') {
-      this.closeCallback = cb;
-    }
-  }
-
-  removeListener(_event: string, _cb: Function) {
-    throw new Error('Call unexpected');
-  }
-
-  findTarget(then: (target: chrome.debugger.Debuggee) => void) {
-    chrome.debugger.getTargets(targets => {
-      const perfettoTab =
-          targets.find(target => target.title.includes('Perfetto'));
-      if (perfettoTab === undefined) {
-        console.log('No perfetto tab found');
-        return;
-      }
-      this.target = {targetId: perfettoTab.id};
-      then(this.target);
-    });
-  }
-
-  findAndAttachTarget(then: (target: chrome.debugger.Debuggee) => void) {
-    this.findTarget(t => {
-      chrome.debugger.attach(t, /*requiredVersion=*/ '1.3', () => {
-        this.openCallback();
-        then(t);
-      });
-    });
-  }
-
-  detach() {
-    if (this.target === undefined) return;
-
-    chrome.debugger.detach(this.target, () => {
-      this.target = undefined;
-    });
-  }
-
-  onDetach(_source: chrome.debugger.Debuggee, _reason: string) {
-    if (_source === this.target) {
-      this.target = undefined;
-      this.closeCallback();
-    }
-  }
-
-  isAttached(): boolean {
-    return this.target !== undefined;
-  }
-}
diff --git a/ui/src/chrome_extension/index.ts b/ui/src/chrome_extension/index.ts
deleted file mode 100644
index 2d8f4fc..0000000
--- a/ui/src/chrome_extension/index.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {stringToUint8Array} from '../base/string_utils';
-import {ChromeTracingController} from './chrome_tracing_controller';
-
-let chromeTraceController: ChromeTracingController|undefined = undefined;
-
-enableOnlyOnPerfettoHost();
-
-// Listen for messages from the perfetto ui.
-if (window.chrome) {
-  chrome.runtime.onConnectExternal.addListener(port => {
-    chromeTraceController = new ChromeTracingController(port);
-    port.onMessage.addListener(onUIMessage);
-  });
-}
-
-function onUIMessage(
-    message: {method: string, requestData: string}, port: chrome.runtime.Port) {
-  if (message.method === 'ExtensionVersion') {
-    port.postMessage({version: chrome.runtime.getManifest().version});
-    return;
-  }
-  console.assert(chromeTraceController !== undefined);
-  if (!chromeTraceController) return;
-  // ChromeExtensionConsumerPort sends the request data as string because
-  // chrome.runtime.port doesn't support ArrayBuffers.
-  const requestDataArray: Uint8Array = message.requestData ?
-      stringToUint8Array(message.requestData) :
-      new Uint8Array();
-  chromeTraceController.handleCommand(message.method, requestDataArray);
-}
-
-function enableOnlyOnPerfettoHost() {
-  function enableOnHostWithSuffix(suffix: string) {
-    return {
-      conditions: [new chrome.declarativeContent.PageStateMatcher({
-        pageUrl: {hostSuffix: suffix},
-      })],
-      actions: [new chrome.declarativeContent.ShowPageAction()]
-    };
-  }
-  chrome.declarativeContent.onPageChanged.removeRules(undefined, () => {
-    chrome.declarativeContent.onPageChanged.addRules([
-      enableOnHostWithSuffix('.perfetto.local'),
-      enableOnHostWithSuffix('.perfetto.dev'),
-    ]);
-  });
-}
diff --git a/ui/src/chrome_extension/manifest.json b/ui/src/chrome_extension/manifest.json
deleted file mode 100644
index 049a450..0000000
--- a/ui/src/chrome_extension/manifest.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-  "name": "Perfetto UI",
-  "key":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhm3X7qutsrskke84ltokTObnFJakd/d0XFQ6Ox2wQueHTGJM5GUNPTY/x8bdreNtGnfzvt/Sd0vABbR0wsS6lz5yY+g6ksMXJnigFe9N7uz8E3KojDrl3xYjIe+mkiJo8yxxzPydgb7GjQ6jmsX3g+yjj67kXzm9rZFkmoZ5WmqwBZlguPYVRN/W8CIIqBZkC3Qmq6uSG7b/g93YbwqmTmGiL2sAzgvXtqvDOD6503abtQkRC795E4VjJd+ffyeRH38fAEz5ZIrA6GJsfmov1TZTIu1NTwqylSpBYl5as7C6gpmuxDV4SvHvGT2hMQuIufDhZhErjI3B7bcX+XLe1wIDAQAB",
-  "description": "Enables the Perfetto trace viewer (https://ui.perfetto.dev) to record Chrome browser traces.",
-  "version": "0.0.0.8",
-  "manifest_version": 2,
-  "permissions": [
-    "declarativeContent",
-    "debugger"
-  ],
-  "icons": {
-    "128": "logo-128.png"
-  },
-  "background": {
-    "scripts": [
-      "chrome_extension_bundle.js"
-    ],
-    "persistent": false
-  },
-  "externally_connectable": {
-    "matches": [
-      "*://*.perfetto.local/*",
-      "https://*.perfetto.dev/*"
-    ]
-  }
-}
\ No newline at end of file
diff --git a/ui/src/common/actions.ts b/ui/src/common/actions.ts
index 885cc4c..2ae7a31 100644
--- a/ui/src/common/actions.ts
+++ b/ui/src/common/actions.ts
@@ -15,57 +15,30 @@
 import {Draft} from 'immer';
 
 import {assertExists} from '../base/logging';
-import {ConvertTrace, ConvertTraceToPprof} from '../controller/trace_converter';
+import {ConvertTrace} from '../controller/trace_converter';
 
 import {
-  AdbRecordingTarget,
   createEmptyState,
-  EngineMode,
   LogsPagination,
-  NewEngineMode,
-  OmniboxState,
   RecordConfig,
   SCROLLING_TRACK_GROUP,
-  SelectedTimeRange,
   State,
   Status,
-  TargetOs,
-  TraceSource,
   TraceTime,
-  TrackState,
-  VisibleState,
 } from './state';
 
 type StateDraft = Draft<State>;
 
-export interface AddTrackArgs {
-  id?: string;
-  engineId: string;
-  kind: string;
-  name: string;
-  trackGroup?: string;
-  config: {};
-}
 
 function clearTraceState(state: StateDraft) {
   const nextId = state.nextId;
   const recordConfig = state.recordConfig;
   const route = state.route;
-  const androidDeviceConnected = state.androidDeviceConnected;
-  const extensionInstalled = state.extensionInstalled;
-  const availableDevices = state.availableDevices;
-  const chromeCategories = state.chromeCategories;
-  const newEngineMode = state.newEngineMode;
 
   Object.assign(state, createEmptyState());
   state.nextId = nextId;
   state.recordConfig = recordConfig;
   state.route = route;
-  state.androidDeviceConnected = androidDeviceConnected;
-  state.extensionInstalled = extensionInstalled;
-  state.availableDevices = availableDevices;
-  state.chromeCategories = chromeCategories;
-  state.newEngineMode = newEngineMode;
 }
 
 export const StateActions = {
@@ -80,20 +53,13 @@
     state.engines[id] = {
       id,
       ready: false,
-      source: {type: 'FILE', file: args.file},
+      source: args.file,
     };
     state.route = `/viewer`;
   },
 
-  openTraceFromBuffer(state: StateDraft, args: {buffer: ArrayBuffer}): void {
-    clearTraceState(state);
-    const id = `${state.nextId++}`;
-    state.engines[id] = {
-      id,
-      ready: false,
-      source: {type: 'ARRAY_BUFFER', buffer: args.buffer},
-    };
-    state.route = `/viewer`;
+  convertTraceToJson(_: StateDraft, args: {file: File}): void {
+    ConvertTrace(args.file);
   },
 
   openTraceFromUrl(state: StateDraft, args: {url: string}): void {
@@ -102,55 +68,15 @@
     state.engines[id] = {
       id,
       ready: false,
-      source: {type: 'URL', url: args.url},
+      source: args.url,
     };
     state.route = `/viewer`;
   },
 
-  openTraceFromHttpRpc(state: StateDraft, _args: {}): void {
-    clearTraceState(state);
-    const id = `${state.nextId++}`;
-    state.engines[id] = {
-      id,
-      ready: false,
-      source: {type: 'HTTP_RPC'},
-    };
-    state.route = `/viewer`;
-  },
-
-  openVideoFromFile(state: StateDraft, args: {file: File}): void {
-    state.video = URL.createObjectURL(args.file);
-    state.videoEnabled = true;
-  },
-
-  // TODO(b/141359485): Actions should only modify state.
-  convertTraceToJson(
-      _: StateDraft, args: {file: Blob, truncate?: 'start'|'end'}): void {
-    ConvertTrace(args.file, args.truncate);
-  },
-
-  convertTraceToPprof(
-      _: StateDraft,
-      args: {pid: number, src: TraceSource, ts1: number, ts2?: number}): void {
-    ConvertTraceToPprof(args.pid, args.src, args.ts1, args.ts2);
-  },
-
-  addTracks(state: StateDraft, args: {tracks: AddTrackArgs[]}) {
-    args.tracks.forEach(track => {
-      const id = track.id === undefined ? `${state.nextId++}` : track.id;
-      track.id = id;
-      state.tracks[id] = track as TrackState;
-      if (track.trackGroup === SCROLLING_TRACK_GROUP) {
-        state.scrollingTracks.push(id);
-      } else if (track.trackGroup !== undefined) {
-        assertExists(state.trackGroups[track.trackGroup]).tracks.push(id);
-      }
-    });
-  },
-
   addTrack(state: StateDraft, args: {
     id?: string; engineId: string; kind: string; name: string;
-    trackGroup?: string; config: {};
+    trackGroup?: string;
+    config: {};
   }): void {
     const id = args.id !== undefined ? args.id : `${state.nextId++}`;
     state.tracks[id] = {
@@ -182,13 +108,20 @@
     };
   },
 
-  setVisibleTracks(state: StateDraft, args: {tracks: string[]}) {
-    state.visibleTracks = args.tracks;
+  reqTrackData(state: StateDraft, args: {
+    trackId: string; start: number; end: number; resolution: number;
+  }): void {
+    const id = args.trackId;
+    state.tracks[id].dataReq = {
+      start: args.start,
+      end: args.end,
+      resolution: args.resolution
+    };
   },
 
-  updateTrackConfig(state: StateDraft, args: {id: string, config: {}}) {
-    if (state.tracks[args.id] === undefined) return;
-    state.tracks[args.id].config = args.config;
+  clearTrackDataReq(state: StateDraft, args: {trackId: string}): void {
+    const id = args.trackId;
+    state.tracks[id].dataReq = undefined;
   },
 
   executeQuery(
@@ -257,23 +190,9 @@
         trackGroup.collapsed = !trackGroup.collapsed;
       },
 
-  setEngineReady(
-      state: StateDraft,
-      args: {engineId: string; ready: boolean, mode: EngineMode}): void {
-    state.engines[args.engineId].ready = args.ready;
-    state.engines[args.engineId].mode = args.mode;
-  },
-
-  setNewEngineMode(state: StateDraft, args: {mode: NewEngineMode}): void {
-    state.newEngineMode = args.mode;
-  },
-
-  // Marks all engines matching the given |mode| as failed.
-  setEngineFailed(state: StateDraft, args: {mode: EngineMode; failure: string}):
+  setEngineReady(state: StateDraft, args: {engineId: string; ready: boolean}):
       void {
-        for (const engine of Object.values(state.engines)) {
-          if (engine.mode === args.mode) engine.failed = args.failure;
-        }
+        state.engines[args.engineId].ready = args.ready;
       },
 
   createPermalink(state: StateDraft, _: {}): void {
@@ -302,6 +221,12 @@
     state.traceTime = args;
   },
 
+  setVisibleTraceTime(
+      state: StateDraft, args: {time: TraceTime; lastUpdate: number;}): void {
+    state.frontendLocalState.visibleTraceTime = args.time;
+    state.frontendLocalState.lastUpdate = args.lastUpdate;
+  },
+
   updateStatus(state: StateDraft, args: Status): void {
     state.status = args;
   },
@@ -331,51 +256,17 @@
     }
   },
 
-  addNote(
-      state: StateDraft,
-      args: {timestamp: number, color: string, isMovie: boolean}): void {
+  addNote(state: StateDraft, args: {timestamp: number, color: string}): void {
     const id = `${state.nextId++}`;
     state.notes[id] = {
       id,
       timestamp: args.timestamp,
       color: args.color,
       text: '',
-      isMovie: args.isMovie
     };
-    if (args.isMovie) {
-      state.videoNoteIds.push(id);
-    }
     this.selectNote(state, {id});
   },
 
-  toggleVideo(state: StateDraft): void {
-    state.videoEnabled = !state.videoEnabled;
-    if (!state.videoEnabled) {
-      state.video = null;
-      state.flagPauseEnabled = false;
-      state.scrubbingEnabled = false;
-      state.videoNoteIds.forEach(id => {
-        this.removeNote(state, {id});
-      });
-    }
-  },
-
-  toggleFlagPause(state: StateDraft): void {
-    if (state.video != null) {
-      state.flagPauseEnabled = !state.flagPauseEnabled;
-    }
-  },
-
-  toggleScrubbing(state: StateDraft): void {
-    if (state.video != null) {
-      state.scrubbingEnabled = !state.scrubbingEnabled;
-    }
-  },
-
-  setVideoOffset(state: StateDraft, args: {offset: number}): void {
-    state.videoOffset = args.offset;
-  },
-
   changeNoteColor(state: StateDraft, args: {id: string, newColor: string}):
       void {
         const note = state.notes[args.id];
@@ -390,11 +281,6 @@
   },
 
   removeNote(state: StateDraft, args: {id: string}): void {
-    if (state.notes[args.id].isMovie) {
-      state.videoNoteIds = state.videoNoteIds.filter(id => {
-        return id !== args.id;
-      });
-    }
     delete state.notes[args.id];
     if (state.currentSelection === null) return;
     if (state.currentSelection.kind === 'NOTE' &&
@@ -403,68 +289,32 @@
     }
   },
 
-  selectSlice(state: StateDraft, args: {id: number, trackId: string}): void {
+  selectSlice(state: StateDraft, args: {utid: number, id: number}): void {
     state.currentSelection = {
       kind: 'SLICE',
+      utid: args.utid,
       id: args.id,
-      trackId: args.trackId,
     };
   },
 
-  selectCounter(
+  selectTimeSpan(
+      state: StateDraft, args: {startTs: number, endTs: number}): void {
+    state.currentSelection = {
+      kind: 'TIMESPAN',
+      startTs: args.startTs,
+      endTs: args.endTs,
+    };
+  },
+
+  selectThreadState(
       state: StateDraft,
-      args: {leftTs: number, rightTs: number, id: number, trackId: string}):
-      void {
-        state.currentSelection = {
-          kind: 'COUNTER',
-          leftTs: args.leftTs,
-          rightTs: args.rightTs,
-          id: args.id,
-          trackId: args.trackId,
-        };
-      },
-
-  selectHeapProfile(
-      state: StateDraft, args: {id: number, upid: number, ts: number}): void {
-    state.currentSelection =
-        {kind: 'HEAP_PROFILE', id: args.id, upid: args.upid, ts: args.ts};
-  },
-
-  showHeapProfileFlamegraph(
-      state: StateDraft, args: {id: number, upid: number, ts: number}): void {
-    state.currentHeapProfileFlamegraph = {
-      kind: 'HEAP_PROFILE_FLAMEGRAPH',
-      id: args.id,
-      upid: args.upid,
-      ts: args.ts
-    };
-  },
-
-  selectChromeSlice(state: StateDraft, args: {id: number, trackId: string}):
-      void {
-        state.currentSelection = {
-          kind: 'CHROME_SLICE',
-          id: args.id,
-          trackId: args.trackId
-        };
-      },
-
-  selectThreadState(state: StateDraft, args: {
-    utid: number,
-    ts: number,
-    dur: number,
-    state: string,
-    cpu: number,
-    trackId: string
-  }): void {
+      args: {utid: number, ts: number, dur: number, state: string}): void {
     state.currentSelection = {
       kind: 'THREAD_STATE',
       utid: args.utid,
       ts: args.ts,
       dur: args.dur,
-      state: args.state,
-      cpu: args.cpu,
-      trackId: args.trackId,
+      state: args.state
     };
   },
 
@@ -476,66 +326,6 @@
     state.logsPagination = args;
   },
 
-  startRecording(state: StateDraft): void {
-    state.recordingInProgress = true;
-    state.lastRecordingError = undefined;
-    state.recordingCancelled = false;
-  },
-
-  stopRecording(state: StateDraft): void {
-    state.recordingInProgress = false;
-  },
-
-  cancelRecording(state: StateDraft): void {
-    state.recordingInProgress = false;
-    state.recordingCancelled = true;
-  },
-
-  setExtensionAvailable(state: StateDraft, args: {available: boolean}): void {
-    state.extensionInstalled = args.available;
-  },
-
-  updateBufferUsage(state: StateDraft, args: {percentage: number}): void {
-    state.bufferUsage = args.percentage;
-  },
-
-  setAndroidDevice(state: StateDraft, args: {target?: AdbRecordingTarget}):
-      void {
-        state.recordConfig.targetOS =
-            args.target ? args.target.os as TargetOs : 'Q';
-        state.androidDeviceConnected = args.target;
-      },
-
-  setAvailableDevices(state: StateDraft, args: {devices: AdbRecordingTarget[]}):
-      void {
-        state.availableDevices = args.devices;
-      },
-
-  setOmnibox(state: StateDraft, args: OmniboxState): void {
-    state.frontendLocalState.omniboxState = args;
-  },
-
-  selectTimeRange(state: StateDraft, args: SelectedTimeRange): void {
-    state.frontendLocalState.selectedTimeRange = args;
-  },
-
-  setVisibleTraceTime(state: StateDraft, args: VisibleState): void {
-    state.frontendLocalState.visibleState = args;
-  },
-
-  setChromeCategories(state: StateDraft, args: {categories: string[]}): void {
-    state.chromeCategories = args.categories;
-  },
-
-  setLastRecordingError(state: StateDraft, args: {error?: string}): void {
-    state.lastRecordingError = args.error;
-    state.recordingStatus = undefined;
-  },
-
-  setRecordingStatus(state: StateDraft, args: {status?: string}): void {
-    state.recordingStatus = args.status;
-    state.lastRecordingError = undefined;
-  },
 };
 
 // When we are on the frontend side, we don't really want to execute the
diff --git a/ui/src/common/actions_unittest.ts b/ui/src/common/actions_unittest.ts
index 686da55..4214c19 100644
--- a/ui/src/common/actions_unittest.ts
+++ b/ui/src/common/actions_unittest.ts
@@ -19,8 +19,7 @@
   createEmptyState,
   SCROLLING_TRACK_GROUP,
   State,
-  TraceUrlSource,
-  TrackState,
+  TrackState
 } from './state';
 
 function fakeTrack(state: State, id: string): TrackState {
@@ -249,8 +248,7 @@
   const engineKeys = Object.keys(after.engines);
   expect(after.nextId).toBe(101);
   expect(engineKeys.length).toBe(1);
-  expect((after.engines[engineKeys[0]].source as TraceUrlSource).url)
-      .toBe('https://example.com/bar');
+  expect(after.engines[engineKeys[0]].source).toBe('https://example.com/bar');
   expect(after.route).toBe('/viewer');
   expect(after.recordConfig).toBe(recordConfig);
 });
@@ -279,8 +277,7 @@
 
   const engineKeys = Object.keys(thrice.engines);
   expect(engineKeys.length).toBe(1);
-  expect((thrice.engines[engineKeys[0]].source as TraceUrlSource).url)
-      .toBe('https://example.com/foo');
+  expect(thrice.engines[engineKeys[0]].source).toBe('https://example.com/foo');
   expect(thrice.pinnedTracks.length).toBe(0);
   expect(thrice.scrollingTracks.length).toBe(0);
   expect(thrice.route).toBe('/viewer');
diff --git a/ui/src/common/engine.ts b/ui/src/common/engine.ts
index d9f6760..0ec3be3 100644
--- a/ui/src/common/engine.ts
+++ b/ui/src/common/engine.ts
@@ -12,74 +12,47 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {RawQueryArgs, RawQueryResult} from './protos';
+import {RawQueryResult, TraceProcessor} from './protos';
 import {TimeSpan} from './time';
 
-export interface LoadingTracker {
-  beginLoading(): void;
-  endLoading(): void;
-}
-
-export class NullLoadingTracker implements LoadingTracker {
-  beginLoading(): void {}
-  endLoading(): void {}
-}
-
 /**
  * Abstract interface of a trace proccessor.
- * This is the TypeScript equivalent of src/trace_processor/rpc.h.
+ * This class is wrapper for multiple proto services defined in:
+ * //protos/perfetto/trace_processor/*
+ * For each service ("FooService") Engine will have abstract getter
+ * ("fooService") which returns a protobufjs rpc.Service object for
+ * the given service.
  *
  * Engine also defines helpers for the most common service methods
  * (e.g. query).
  */
 export abstract class Engine {
   abstract readonly id: string;
-  private _cpus?: number[];
-  private _numGpus?: number;
-  private loadingTracker: LoadingTracker;
-
-  constructor(tracker?: LoadingTracker) {
-    this.loadingTracker = tracker ? tracker : new NullLoadingTracker();
-  }
+  private _numCpus?: number;
 
   /**
    * Push trace data into the engine. The engine is supposed to automatically
    * figure out the type of the trace (JSON vs Protobuf).
    */
-  abstract parse(data: Uint8Array): Promise<void>;
+  abstract parse(data: Uint8Array): void;
 
   /**
    * Notify the engine no more data is coming.
    */
   abstract notifyEof(): void;
 
-  /**
-   * Resets the trace processor state by destroying any table/views created by
-   * the UI after loading.
-   */
-  abstract restoreInitialTables(): void;
-
   /*
-   * Performs a SQL query and retruns a proto-encoded RawQueryResult object.
+   * The RCP interface to call service methods defined in trace_processor.proto.
    */
-  abstract rawQuery(rawQueryArgs: Uint8Array): Promise<Uint8Array>;
+  abstract get rpc(): TraceProcessor;
 
   /**
    * Shorthand for sending a SQL query to the engine.
-   * Deals with {,un}marshalling of request/response args.
+   * Exactly the same as engine.rpc.rawQuery({rawQuery});
    */
-  async query(sqlQuery: string): Promise<RawQueryResult> {
-    this.loadingTracker.beginLoading();
-    try {
-      const args = new RawQueryArgs();
-      args.sqlQuery = sqlQuery;
-      args.timeQueuedNs = Math.floor(performance.now() * 1e6);
-      const argsEncoded = RawQueryArgs.encode(args).finish();
-      const respEncoded = await this.rawQuery(argsEncoded);
-      return RawQueryResult.decode(respEncoded);
-    } finally {
-      this.loadingTracker.endLoading();
-    }
+  query(sqlQuery: string): Promise<RawQueryResult> {
+    const timeQueuedNs = Math.floor(performance.now() * 1e6);
+    return this.rpc.rawQuery({sqlQuery, timeQueuedNs});
   }
 
   async queryOneRow(query: string): Promise<number[]> {
@@ -90,22 +63,13 @@
   }
 
   // TODO(hjd): When streaming must invalidate this somehow.
-  async getCpus(): Promise<number[]> {
-    if (!this._cpus) {
-      const result =
-          await this.query('select distinct(cpu) from sched order by cpu;');
-      this._cpus = result.columns[0].longValues!.map(n => +n);
-    }
-    return this._cpus;
-  }
-
-  async getNumberOfGpus(): Promise<number> {
-    if (!this._numGpus) {
+  async getNumberOfCpus(): Promise<number> {
+    if (!this._numCpus) {
       const result = await this.query(
-          'select count(distinct(arg_set_id)) as gpuCount from counters where name = "gpufreq";');
-      this._numGpus = +result.columns[0].longValues![0];
+          'select count(distinct(cpu)) as cpuCount from sched;');
+      this._numCpus = +result.columns[0].longValues![0];
     }
-    return this._numGpus;
+    return this._numCpus;
   }
 
   // TODO: This should live in code that's more specific to chrome, instead of
diff --git a/ui/src/common/http_rpc_engine.ts b/ui/src/common/http_rpc_engine.ts
deleted file mode 100644
index e0da547..0000000
--- a/ui/src/common/http_rpc_engine.ts
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {defer, Deferred} from '../base/deferred';
-import {fetchWithTimeout} from '../base/http_utils';
-import {assertExists} from '../base/logging';
-import {StatusResult} from '../common/protos';
-
-import {Engine, LoadingTracker} from './engine';
-
-export const RPC_URL = 'http://127.0.0.1:9001/';
-const RPC_CONNECT_TIMEOUT_MS = 2000;
-
-export interface HttpRpcState {
-  connected: boolean;
-  loadedTraceName?: string;
-  failure?: string;
-}
-
-interface QueuedRequest {
-  methodName: string;
-  reqData?: Uint8Array;
-  resp: Deferred<Uint8Array>;
-}
-
-export class HttpRpcEngine extends Engine {
-  readonly id: string;
-  private requestQueue = new Array<QueuedRequest>();
-  errorHandler: (err: string) => void = () => {};
-
-  constructor(id: string, loadingTracker?: LoadingTracker) {
-    super(loadingTracker);
-    this.id = id;
-  }
-
-  async parse(data: Uint8Array): Promise<void> {
-    await this.enqueueRequest('parse', data);
-  }
-
-  async notifyEof(): Promise<void> {
-    await this.enqueueRequest('notify_eof');
-  }
-
-  async restoreInitialTables(): Promise<void> {
-    await this.enqueueRequest('restore_initial_tables');
-  }
-
-  rawQuery(rawQueryArgs: Uint8Array): Promise<Uint8Array> {
-    return this.enqueueRequest('raw_query', rawQueryArgs);
-  }
-
-  enqueueRequest(methodName: string, data?: Uint8Array): Promise<Uint8Array> {
-    const resp = defer<Uint8Array>();
-    this.requestQueue.push({methodName, reqData: data, resp});
-    if (this.requestQueue.length === 1) {
-      this.submitNextQueuedRequest();
-    }
-    return resp;
-  }
-
-  private submitNextQueuedRequest() {
-    if (this.requestQueue.length === 0) {
-      return;
-    }
-    const req = this.requestQueue[0];
-    const methodName = req.methodName.toLowerCase();
-    // Deliberately not using fetchWithTimeout() here. These queries can be
-    // arbitrarily long.
-    fetch(RPC_URL + methodName, {
-      method: 'post',
-      cache: 'no-cache',
-      headers: {
-        'Content-Type': 'application/x-protobuf',
-        'Accept': 'application/x-protobuf',
-      },
-      body: req.reqData || new Uint8Array(),
-    })
-        .then(resp => this.onFetchResponse(resp))
-        .catch(err => this.errorHandler(err));
-  }
-
-  private onFetchResponse(resp: Response) {
-    const pendingReq = assertExists(this.requestQueue.shift());
-    if (resp.status !== 200) {
-      pendingReq.resp.reject(`HTTP ${resp.status} - ${resp.statusText}`);
-      return;
-    }
-    resp.arrayBuffer().then(arrBuf => {
-      this.submitNextQueuedRequest();
-      pendingReq.resp.resolve(new Uint8Array(arrBuf));
-    });
-  }
-
-  static async checkConnection(): Promise<HttpRpcState> {
-    const httpRpcState: HttpRpcState = {connected: false};
-    try {
-      const resp = await fetchWithTimeout(
-          RPC_URL + 'status',
-          {method: 'post', cache: 'no-cache'},
-          RPC_CONNECT_TIMEOUT_MS);
-      if (resp.status !== 200) {
-        httpRpcState.failure = `${resp.status} - ${resp.statusText}`;
-      } else {
-        const buf = new Uint8Array(await resp.arrayBuffer());
-        const status = StatusResult.decode(buf);
-        httpRpcState.connected = true;
-        if (status.loadedTraceName) {
-          httpRpcState.loadedTraceName = status.loadedTraceName;
-        }
-      }
-    } catch (err) {
-      httpRpcState.failure = `${err}`;
-    }
-    return httpRpcState;
-  }
-}
diff --git a/ui/src/common/protos.ts b/ui/src/common/protos.ts
index 49533d8..f453a7d 100644
--- a/ui/src/common/protos.ts
+++ b/ui/src/common/protos.ts
@@ -23,31 +23,24 @@
 import BatteryCounters =
     protos.perfetto.protos.AndroidPowerConfig.BatteryCounters;
 import BufferConfig = protos.perfetto.protos.TraceConfig.BufferConfig;
-import ChromeConfig = protos.perfetto.protos.ChromeConfig;
-import ConsumerPort = protos.perfetto.protos.ConsumerPort;
-import ContinuousDumpConfig =
-    protos.perfetto.protos.HeapprofdConfig.ContinuousDumpConfig;
 import DataSourceConfig = protos.perfetto.protos.DataSourceConfig;
 import FtraceConfig = protos.perfetto.protos.FtraceConfig;
-import HeapprofdConfig = protos.perfetto.protos.HeapprofdConfig;
 import IAndroidPowerConfig = protos.perfetto.protos.IAndroidPowerConfig;
 import IBufferConfig = protos.perfetto.protos.TraceConfig.IBufferConfig;
 import IProcessStatsConfig = protos.perfetto.protos.IProcessStatsConfig;
+import IRawQueryArgs = protos.perfetto.protos.IRawQueryArgs;
 import ISysStatsConfig = protos.perfetto.protos.ISysStatsConfig;
 import ITraceConfig = protos.perfetto.protos.ITraceConfig;
 import MeminfoCounters = protos.perfetto.protos.MeminfoCounters;
 import ProcessStatsConfig = protos.perfetto.protos.ProcessStatsConfig;
+import RawQueryArgs = protos.perfetto.protos.RawQueryArgs;
+import RawQueryResult = protos.perfetto.protos.RawQueryResult;
 import StatCounters = protos.perfetto.protos.SysStatsConfig.StatCounters;
 import SysStatsConfig = protos.perfetto.protos.SysStatsConfig;
 import TraceConfig = protos.perfetto.protos.TraceConfig;
+import TraceProcessor = protos.perfetto.protos.TraceProcessor;
 import VmstatCounters = protos.perfetto.protos.VmstatCounters;
 
-// Trace Processor protos.
-import IRawQueryArgs = protos.perfetto.trace_processor.protos.IRawQueryArgs;
-import RawQueryArgs = protos.perfetto.trace_processor.protos.RawQueryArgs;
-import RawQueryResult = protos.perfetto.trace_processor.protos.RawQueryResult;
-import StatusResult = protos.perfetto.trace_processor.protos.StatusResult;
-
 // TODO(hjd): Maybe these should go in their own file.
 export interface Row { [key: string]: number|string; }
 
@@ -205,12 +198,8 @@
   AndroidPowerConfig,
   BatteryCounters,
   BufferConfig,
-  ChromeConfig,
-  ConsumerPort,
-  ContinuousDumpConfig,
   DataSourceConfig,
   FtraceConfig,
-  HeapprofdConfig,
   IAndroidPowerConfig,
   IBufferConfig,
   IProcessStatsConfig,
@@ -221,9 +210,9 @@
   ProcessStatsConfig,
   RawQueryArgs,
   RawQueryResult,
-  StatusResult,
   StatCounters,
   SysStatsConfig,
   TraceConfig,
+  TraceProcessor,
   VmstatCounters,
 };
diff --git a/ui/src/common/search_data.ts b/ui/src/common/search_data.ts
deleted file mode 100644
index 79b7bbf..0000000
--- a/ui/src/common/search_data.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2019 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.
-
-export interface SearchSummary {
-  tsStarts: Float64Array;
-  tsEnds: Float64Array;
-  count: Uint8Array;
-}
-
-export interface CurrentSearchResults {
-  sliceIds: Float64Array;
-  tsStarts: Float64Array;
-  utids: Float64Array;
-  trackIds: string[];
-  refTypes: string[];
-  totalResults: number;
-}
diff --git a/ui/src/common/state.ts b/ui/src/common/state.ts
index 10d7924..2f250c2 100644
--- a/ui/src/common/state.ts
+++ b/ui/src/common/state.ts
@@ -19,56 +19,15 @@
  */
 export interface ObjectById<Class extends{id: string}> { [id: string]: Class; }
 
-export type Timestamped<T> = {
-  [P in keyof T]: T[P];
-}&{lastUpdate: number};
-
-export type OmniboxState =
-    Timestamped<{omnibox: string; mode: 'SEARCH' | 'COMMAND'}>;
-
-export type VisibleState =
-    Timestamped<{startSec: number; endSec: number; resolution: number;}>;
-
-export type SelectedTimeRange =
-    Timestamped<{startSec?: number; endSec?: number;}>;
-
-export const MAX_TIME = 180;
-
 export const SCROLLING_TRACK_GROUP = 'ScrollingTracks';
 
-
-export type EngineMode = 'WASM'|'HTTP_RPC';
-
-export type NewEngineMode = 'USE_HTTP_RPC_IF_AVAILABLE'|'FORCE_BUILTIN_WASM';
-
-export interface TraceFileSource {
-  type: 'FILE';
-  file: File;
-}
-
-export interface TraceArrayBufferSource {
-  type: 'ARRAY_BUFFER';
-  buffer: ArrayBuffer;
-}
-
-export interface TraceUrlSource {
-  type: 'URL';
-  url: string;
-}
-
-export interface TraceHttpRpcSource {
-  type: 'HTTP_RPC';
-}
-
-export type TraceSource =
-    TraceFileSource|TraceArrayBufferSource|TraceUrlSource|TraceHttpRpcSource;
-
 export interface TrackState {
   id: string;
   engineId: string;
   kind: string;
   name: string;
   trackGroup?: string;
+  dataReq?: TrackDataRequest;
   config: {};
 }
 
@@ -81,12 +40,16 @@
   summaryTrackId: string;
 }
 
+export interface TrackDataRequest {
+  start: number;
+  end: number;
+  resolution: number;
+}
+
 export interface EngineConfig {
   id: string;
-  mode?: EngineMode;  // Is undefined until |ready| is true.
   ready: boolean;
-  failed?: string;  // If defined the engine has crashed with the given message.
-  source: TraceSource;
+  source: string|File;
 }
 
 export interface QueryConfig {
@@ -106,9 +69,8 @@
 }
 
 export interface FrontendLocalState {
-  omniboxState: OmniboxState;
-  visibleState: VisibleState;
-  selectedTimeRange: SelectedTimeRange;
+  visibleTraceTime: TraceTime;
+  lastUpdate: number;  // Epoch in seconds (Date.now() / 1000).
 }
 
 export interface Status {
@@ -121,7 +83,6 @@
   timestamp: number;
   color: string;
   text: string;
-  isMovie: boolean;
 }
 
 export interface NoteSelection {
@@ -131,33 +92,14 @@
 
 export interface SliceSelection {
   kind: 'SLICE';
+  utid: number;
   id: number;
 }
 
-export interface CounterSelection {
-  kind: 'COUNTER';
-  leftTs: number;
-  rightTs: number;
-  id: number;
-}
-
-export interface HeapProfileSelection {
-  kind: 'HEAP_PROFILE';
-  id: number;
-  upid: number;
-  ts: number;
-}
-
-export interface HeapProfileFlamegraph {
-  kind: 'HEAP_PROFILE_FLAMEGRAPH';
-  id: number;
-  upid: number;
-  ts: number;
-}
-
-export interface ChromeSliceSelection {
-  kind: 'CHROME_SLICE';
-  id: number;
+export interface TimeSpanSelection {
+  kind: 'TIMESPAN';
+  startTs: number;
+  endTs: number;
 }
 
 export interface ThreadStateSelection {
@@ -166,27 +108,17 @@
   ts: number;
   dur: number;
   state: string;
-  cpu: number;
 }
 
 type Selection =
-    (NoteSelection|SliceSelection|CounterSelection|HeapProfileSelection|
-     ChromeSliceSelection|ThreadStateSelection)&{trackId?: string};
+    NoteSelection|SliceSelection|TimeSpanSelection|ThreadStateSelection;
 
 export interface LogsPagination {
   offset: number;
   count: number;
 }
 
-export interface AdbRecordingTarget {
-  serial: string;
-  name: string;
-  os: string;
-}
-
 export interface State {
-  // tslint:disable-next-line:no-any
-  [key: string]: any;
   route: string|null;
   nextId: number;
 
@@ -199,12 +131,10 @@
   /**
    * Open traces.
    */
-  newEngineMode: NewEngineMode;
   engines: ObjectById<EngineConfig>;
   traceTime: TraceTime;
   trackGroups: ObjectById<TrackGroupState>;
   tracks: ObjectById<TrackState>;
-  visibleTracks: string[];
   scrollingTracks: string[];
   pinnedTracks: string[];
   queries: ObjectById<QueryConfig>;
@@ -212,7 +142,6 @@
   notes: ObjectById<Note>;
   status: Status;
   currentSelection: Selection|null;
-  currentHeapProfileFlamegraph: HeapProfileFlamegraph|null;
 
   logsPagination: LogsPagination;
 
@@ -223,26 +152,6 @@
    * key is most up to date.
    */
   frontendLocalState: FrontendLocalState;
-
-  video: string | null;
-  videoEnabled: boolean;
-  videoOffset: number;
-  videoNoteIds: string[];
-  scrubbingEnabled: boolean;
-  flagPauseEnabled: boolean;
-
-  /**
-   * Trace recording
-   */
-  recordingInProgress: boolean;
-  recordingCancelled: boolean;
-  extensionInstalled: boolean;
-  androidDeviceConnected?: AdbRecordingTarget;
-  availableDevices: AdbRecordingTarget[];
-  lastRecordingError?: string;
-  recordingStatus?: string;
-
-  chromeCategories: string[]|undefined;
 }
 
 export const defaultTraceTime = {
@@ -253,26 +162,11 @@
 export declare type RecordMode =
     'STOP_WHEN_FULL' | 'RING_BUFFER' | 'LONG_TRACE';
 
-// 'Q','P','O' for Android, 'L' for Linux, 'C' for Chrome.
-export declare type TargetOs = 'Q' | 'P' | 'O' | 'C' | 'L';
-
-export function isAndroidTarget(target: TargetOs) {
-  return ['Q', 'P', 'O'].includes(target);
-}
-
-export function isChromeTarget(target: TargetOs) {
-  return target === 'C';
-}
-
-export function isLinuxTarget(target: TargetOs) {
-  return target === 'L';
-}
-
 export interface RecordConfig {
   [key: string]: null|number|boolean|string|string[];
 
   // Global settings
-  targetOS: TargetOs;
+  targetOS: string;  // 'Q','P','O' for Android, 'L' for Linux
   mode: RecordMode;
   durationMs: number;
   bufferSizeMb: number;
@@ -284,11 +178,6 @@
   cpuFreq: boolean;
   cpuCoarse: boolean;
   cpuCoarsePollMs: number;
-  cpuSyscall: boolean;
-
-  screenRecord: boolean;
-
-  gpuFreq: boolean;
 
   ftrace: boolean;
   atrace: boolean;
@@ -315,17 +204,8 @@
   vmstatPeriodMs: number;
   vmstatCounters: string[];
 
-  heapProfiling: boolean;
-  hpSamplingIntervalBytes: number;
-  hpProcesses: string;
-  hpContinuousDumpsPhase: number;
-  hpContinuousDumpsInterval: number;
-  hpSharedMemoryBuffer: number;
-
   procStats: boolean;
   procStatsPeriodMs: number;
-
-  chromeCategoriesSelected: string[];
 }
 
 export function createEmptyRecordConfig(): RecordConfig {
@@ -340,11 +220,6 @@
     cpuSched: false,
     cpuLatency: false,
     cpuFreq: false,
-    cpuSyscall: false,
-
-    screenRecord: false,
-
-    gpuFreq: false,
 
     ftrace: false,
     atrace: false,
@@ -374,18 +249,9 @@
     vmstatPeriodMs: 1000,
     vmstatCounters: [],
 
-    heapProfiling: false,
-    hpSamplingIntervalBytes: 4096,
-    hpProcesses: '',
-    hpContinuousDumpsPhase: 0,
-    hpContinuousDumpsInterval: 0,
-    hpSharedMemoryBuffer: 8 * 1048576,
-
     memLmk: false,
     procStats: false,
     procStatsPeriodMs: 1000,
-
-    chromeCategoriesSelected: [],
   };
 }
 
@@ -393,12 +259,10 @@
   return {
     route: null,
     nextId: 0,
-    newEngineMode: 'USE_HTTP_RPC_IF_AVAILABLE',
     engines: {},
     traceTime: {...defaultTraceTime},
     tracks: {},
     trackGroups: {},
-    visibleTracks: [],
     pinnedTracks: [],
     scrollingTracks: [],
     queries: {},
@@ -409,20 +273,8 @@
     displayConfigAsPbtxt: false,
 
     frontendLocalState: {
-      omniboxState: {
-        lastUpdate: 0,
-        omnibox: '',
-        mode: 'SEARCH',
-      },
-
-      visibleState: {
-        ...defaultTraceTime,
-        lastUpdate: 0,
-        resolution: 0,
-      },
-      selectedTimeRange: {
-        lastUpdate: 0,
-      },
+      visibleTraceTime: {...defaultTraceTime},
+      lastUpdate: 0,
     },
 
     logsPagination: {
@@ -432,33 +284,5 @@
 
     status: {msg: '', timestamp: 0},
     currentSelection: null,
-    currentHeapProfileFlamegraph: null,
-
-    video: null,
-    videoEnabled: false,
-    videoOffset: 0,
-    videoNoteIds: [],
-    scrubbingEnabled: false,
-    flagPauseEnabled: false,
-    recordingInProgress: false,
-    recordingCancelled: false,
-    extensionInstalled: false,
-    androidDeviceConnected: undefined,
-    availableDevices: [],
-
-    chromeCategories: undefined,
   };
 }
-
-export function getContainingTrackId(state: State, trackId: string): null|
-    string {
-  const track = state.tracks[trackId];
-  if (!track) {
-    return null;
-  }
-  const parentId = track.trackGroup;
-  if (!parentId) {
-    return null;
-  }
-  return parentId;
-}
diff --git a/ui/src/common/state_unittest.ts b/ui/src/common/state_unittest.ts
index 5216392..5a8e820 100644
--- a/ui/src/common/state_unittest.ts
+++ b/ui/src/common/state_unittest.ts
@@ -12,33 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {createEmptyState, getContainingTrackId, State} from './state';
+import {createEmptyState, State} from './state';
 
 test('createEmptyState', () => {
   const state: State = createEmptyState();
   expect(state.nextId).toEqual(0);
 });
-
-test('getContainingTrackId', () => {
-  const state: State = createEmptyState();
-  state.tracks['a'] = {
-    id: 'a',
-    engineId: 'engine',
-    kind: 'Foo',
-    name: 'a track',
-    config: {},
-  };
-
-  state.tracks['b'] = {
-    id: 'b',
-    engineId: 'engine',
-    kind: 'Foo',
-    name: 'b track',
-    config: {},
-    trackGroup: 'containsB',
-  };
-
-  expect(getContainingTrackId(state, 'z')).toEqual(null);
-  expect(getContainingTrackId(state, 'a')).toEqual(null);
-  expect(getContainingTrackId(state, 'b')).toEqual('containsB');
-});
diff --git a/ui/src/common/time.ts b/ui/src/common/time.ts
index fce992d..33e13b8 100644
--- a/ui/src/common/time.ts
+++ b/ui/src/common/time.ts
@@ -14,8 +14,6 @@
 
 import {assertTrue} from '../base/logging';
 
-const EPSILON = 0.0000000001;
-
 // TODO(hjd): Combine with timeToCode.
 export function timeToString(sec: number) {
   const units = ['s', 'ms', 'us', 'ns'];
@@ -33,17 +31,6 @@
   return ns / 1e9;
 }
 
-export function toNsFloor(seconds: number) {
-  return Math.floor(seconds * 1e9);
-}
-
-export function toNsCeil(seconds: number) {
-  return Math.ceil(seconds * 1e9);
-}
-
-export function toNs(seconds: number) {
-  return Math.round(seconds * 1e9);
-}
 
 // 1000000023ns -> "1.000 000 023"
 export function formatTimestamp(sec: number) {
@@ -91,9 +78,8 @@
     return new TimeSpan(this.start, this.end);
   }
 
-  equals(other: TimeSpan): boolean {
-    return Math.abs(this.start - other.start) < EPSILON &&
-        Math.abs(this.end - other.end) < EPSILON;
+  equals(other: TimeSpan) {
+    return this.start === other.start && this.end === other.end;
   }
 
   get duration() {
@@ -107,8 +93,4 @@
   add(sec: number): TimeSpan {
     return new TimeSpan(this.start + sec, this.end + sec);
   }
-
-  contains(other: TimeSpan) {
-    return this.start <= other.start && other.end <= this.end;
-  }
 }
diff --git a/ui/src/common/time_unittest.ts b/ui/src/common/time_unittest.ts
index 7bfead1..bbaacd9 100644
--- a/ui/src/common/time_unittest.ts
+++ b/ui/src/common/time_unittest.ts
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {TimeSpan, timeToCode} from './time';
+import {timeToCode} from './time';
 
 test('seconds to code', () => {
   expect(timeToCode(3)).toEqual('3s');
@@ -28,10 +28,3 @@
   expect(timeToCode(200.00000003)).toEqual('3m 20s 30ns');
   expect(timeToCode(0)).toEqual('0s');
 });
-
-test('Time span equality', () => {
-  expect((new TimeSpan(0, 1)).equals(new TimeSpan(0, 1))).toBe(true);
-  expect((new TimeSpan(0, 1)).equals(new TimeSpan(0, 2))).toBe(false);
-  expect((new TimeSpan(0, 1)).equals(new TimeSpan(0, 1 + Number.EPSILON)))
-      .toBe(true);
-});
diff --git a/ui/src/common/track_data.ts b/ui/src/common/track_data.ts
deleted file mode 100644
index 9af7fff..0000000
--- a/ui/src/common/track_data.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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.
-
-// TODO(hjd): Refactor into method on TrackController
-export const LIMIT = 10000;
-
-export interface TrackData {
-  start: number;
-  end: number;
-  resolution: number;
-  length: number;
-}
diff --git a/ui/src/common/wasm_engine_proxy.ts b/ui/src/common/wasm_engine_proxy.ts
index b09c662..8501990 100644
--- a/ui/src/common/wasm_engine_proxy.ts
+++ b/ui/src/common/wasm_engine_proxy.ts
@@ -12,11 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {defer, Deferred} from '../base/deferred';
-import {assertTrue} from '../base/logging';
+import * as protobufjs from 'protobufjs/light';
+
+import {defer} from '../base/deferred';
 import {WasmBridgeRequest, WasmBridgeResponse} from '../engine/wasm_bridge';
 
-import {Engine, LoadingTracker} from './engine';
+import {Engine} from './engine';
+import {TraceProcessor} from './protos';
+import {Method, rpc, Message} from 'protobufjs/light';
 
 const activeWorkers = new Map<string, Worker>();
 let warmWorker: null|Worker = null;
@@ -63,78 +66,77 @@
   warmWorker = createWorker();
 }
 
-interface PendingRequest {
-  id: number;
-  respHandler: Deferred<Uint8Array>;
-}
-
 /**
- * This implementation of Engine uses a WASM backend hosted in a separate
+ * This implementation of Engine uses a WASM backend hosted in a seperate
  * worker thread.
  */
 export class WasmEngineProxy extends Engine {
-  readonly id: string;
   private readonly worker: Worker;
-  private pendingRequests = new Array<PendingRequest>();
-  private nextRequestId = 0;
+  private readonly traceProcessor_: TraceProcessor;
+  private pendingCallbacks: Map<number, protobufjs.RPCImplCallback>;
+  private nextRequestId: number;
+  readonly id: string;
 
-  constructor(id: string, worker: Worker, loadingTracker?: LoadingTracker) {
-    super(loadingTracker);
-    this.id = id;
-    this.worker = worker;
+  constructor(args: {id: string, worker: Worker}) {
+    super();
+    this.nextRequestId = 0;
+    this.pendingCallbacks = new Map();
+    this.id = args.id;
+    this.worker = args.worker;
     this.worker.onmessage = this.onMessage.bind(this);
+    this.traceProcessor_ =
+        TraceProcessor.create(this.rpcImpl.bind(this, 'trace_processor'));
   }
 
-  async parse(reqData: Uint8Array): Promise<void> {
-    // We don't care about the response data (the method is actually a void). We
-    // just want to linearize and wait for the call to have been completed on
-    // the worker.
-    await this.queueRequest('trace_processor_parse', reqData);
+  get rpc(): TraceProcessor {
+    return this.traceProcessor_;
   }
 
-  async notifyEof(): Promise<void> {
-    // We don't care about the response data (the method is actually a void). We
-    // just want to linearize and wait for the call to have been completed on
-    // the worker.
-    await this.queueRequest('trace_processor_notify_eof', new Uint8Array());
-  }
-
-  restoreInitialTables(): Promise<void> {
-    // We should never get here, restoreInitialTables() should be called only
-    // when using the HttpRpcEngine.
-    throw new Error('restoreInitialTables() not supported by the WASM engine');
-  }
-
-  rawQuery(rawQueryArgs: Uint8Array): Promise<Uint8Array> {
-    return this.queueRequest('trace_processor_raw_query', rawQueryArgs);
-  }
-
-  // Enqueues a request to the worker queue via postMessage(). The returned
-  // promised will be resolved once the worker replies to the postMessage()
-  // with the paylad of the response, a proto-encoded object which wraps the
-  // method return value (e.g., RawQueryResult for SQL query results).
-  private queueRequest(methodName: string, reqData: Uint8Array):
-      Deferred<Uint8Array> {
-    const respHandler = defer<Uint8Array>();
+  parse(data: Uint8Array): Promise<void> {
     const id = this.nextRequestId++;
-    const request: WasmBridgeRequest = {id, methodName, data: reqData};
-    this.pendingRequests.push({id, respHandler});
+    const request: WasmBridgeRequest =
+        {id, serviceName: 'trace_processor', methodName: 'parse', data};
+    const promise = defer<void>();
+    this.pendingCallbacks.set(id, () => promise.resolve());
     this.worker.postMessage(request);
-    return respHandler;
+    return promise;
+  }
+
+  notifyEof(): Promise<void> {
+    const id = this.nextRequestId++;
+    const data = Uint8Array.from([]);
+    const request: WasmBridgeRequest =
+        {id, serviceName: 'trace_processor', methodName: 'notifyEof', data};
+    const promise = defer<void>();
+    this.pendingCallbacks.set(id, () => promise.resolve());
+    this.worker.postMessage(request);
+    return promise;
   }
 
   onMessage(m: MessageEvent) {
     const response = m.data as WasmBridgeResponse;
-    assertTrue(this.pendingRequests.length > 0);
-    const request = this.pendingRequests.shift()!;
-
-    // Requests should be executed and ACKed by the worker in the same order
-    // they came in.
-    assertTrue(request.id === response.id);
-    if (response.aborted) {
-      request.respHandler.reject('WASM module crashed');
-    } else {
-      request.respHandler.resolve(response.data);
+    const callback = this.pendingCallbacks.get(response.id);
+    if (callback === undefined) {
+      throw new Error(`No such request: ${response.id}`);
     }
+    this.pendingCallbacks.delete(response.id);
+    callback(null, response.data);
+  }
+
+  rpcImpl(
+      serviceName: string,
+      method: Method | rpc.ServiceMethod<Message<{}>, Message<{}>>,
+      requestData: Uint8Array,
+      callback: protobufjs.RPCImplCallback): void {
+    const methodName = method.name;
+    const id = this.nextRequestId++;
+    this.pendingCallbacks.set(id, callback);
+    const request: WasmBridgeRequest = {
+      id,
+      serviceName,
+      methodName,
+      data: requestData,
+    };
+    this.worker.postMessage(request);
   }
 }
diff --git a/ui/src/controller/adb.ts b/ui/src/controller/adb.ts
deleted file mode 100644
index a20776c..0000000
--- a/ui/src/controller/adb.ts
+++ /dev/null
@@ -1,635 +0,0 @@
-import {_TextDecoder, _TextEncoder} from 'custom_utils';
-
-import {Adb, AdbMsg, AdbStream, CmdType} from './adb_interfaces';
-
-const textEncoder = new _TextEncoder();
-const textDecoder = new _TextDecoder();
-
-export const VERSION_WITH_CHECKSUM = 0x01000000;
-export const VERSION_NO_CHECKSUM = 0x01000001;
-export const DEFAULT_MAX_PAYLOAD_BYTES = 256 * 1024;
-
-export enum AdbState {
-  DISCONNECTED = 0,
-  // Authentication steps, see AdbOverWebUsb's handleAuthentication().
-  AUTH_STEP1 = 1,
-  AUTH_STEP2 = 2,
-  AUTH_STEP3 = 3,
-
-  CONNECTED = 2,
-}
-
-enum AuthCmd {
-  TOKEN = 1,
-  SIGNATURE = 2,
-  RSAPUBLICKEY = 3,
-}
-
-const DEVICE_NOT_SET_ERROR = 'Device not set.';
-
-// This class is a basic TypeScript implementation of adb that only supports
-// shell commands. It is used to send the start tracing command to the connected
-// android device, and to automatically pull the trace after the end of the
-// recording. It works through the webUSB API. A brief description of how it
-// works is the following:
-// - The connection with the device is initiated by findAndConnect, which shows
-//   a dialog with a list of connected devices. Once one is selected the
-//   authentication begins. The authentication has to pass different steps, as
-//   described in the "handeAuthentication" method.
-// - AdbOverWebUsb tracks the state of the authentication via a state machine
-//   (see AdbState).
-// - A Message handler loop is executed to keep receiving the messages.
-// - All the messages received from the device are passed to "onMessage" that is
-//   implemented as a state machine.
-// - When a new shell is established, it becomes an AdbStream, and is kept in
-//   the "streams" map. Each time a message from the device is for a specific
-//   previously opened stream, the "onMessage" function will forward it to the
-//   stream (identified by a number).
-export class AdbOverWebUsb implements Adb {
-  state: AdbState = AdbState.DISCONNECTED;
-  streams = new Map<number, AdbStream>();
-  devProps = '';
-  maxPayload = DEFAULT_MAX_PAYLOAD_BYTES;
-  key?: CryptoKeyPair;
-  onConnected = () => {};
-
-  // Devices after Dec 2017 don't use checksum. This will be auto-detected
-  // during the connection.
-  useChecksum = true;
-
-  private lastStreamId = 0;
-  private dev: USBDevice|undefined;
-  private usbReadEndpoint = -1;
-  private usbWriteEpEndpoint = -1;
-  private filter = {
-    classCode: 255,    // USB vendor specific code
-    subclassCode: 66,  // Android vendor specific subclass
-    protocolCode: 1    // Adb protocol
-  };
-
-  async findDevice() {
-    return navigator.usb.requestDevice({filters: [this.filter]});
-  }
-
-  async getPairedDevices() {
-    try {
-      return navigator.usb.getDevices();
-    } catch (e) {  // WebUSB not available.
-      return Promise.resolve([]);
-    }
-  }
-
-  async connect(device: USBDevice): Promise<void> {
-    // If we are already connected, we are also already authenticated, so we can
-    // skip doing the authentication again.
-    if (this.state === AdbState.CONNECTED) {
-      if (this.dev === device && device.opened) {
-        this.onConnected();
-        this.onConnected = () => {};
-        return;
-      }
-      // Another device was connected.
-      await this.disconnect();
-    }
-
-    this.dev = device;
-    this.useChecksum = true;
-    this.key = await AdbOverWebUsb.initKey();
-
-    await this.dev.open();
-    await this.dev.reset();  // The reset is done so that we can claim the
-                             // device before adb server can.
-
-    const {configValue, usbInterfaceNumber, endpoints} =
-        this.findInterfaceAndEndpoint();
-
-    this.usbReadEndpoint = this.findEndpointNumber(endpoints, 'in');
-    this.usbWriteEpEndpoint = this.findEndpointNumber(endpoints, 'out');
-
-    console.assert(this.usbReadEndpoint >= 0 && this.usbWriteEpEndpoint >= 0);
-
-    await this.dev.selectConfiguration(configValue);
-    await this.dev.claimInterface(usbInterfaceNumber);
-
-    await this.startAuthentication();
-
-    // This will start a message handler loop.
-    this.receiveDeviceMessages();
-    // The promise will be resolved after the handshake.
-    return new Promise<void>((resolve, _) => this.onConnected = resolve);
-  }
-
-  async disconnect(): Promise<void> {
-    this.state = AdbState.DISCONNECTED;
-
-    if (!this.dev) return;
-
-    new Map(this.streams).forEach((stream, _id) => stream.setClosed());
-    console.assert(this.streams.size === 0);
-    this.dev = undefined;
-  }
-
-  async startAuthentication() {
-    // USB connected, now let's authenticate.
-    const VERSION =
-        this.useChecksum ? VERSION_WITH_CHECKSUM : VERSION_NO_CHECKSUM;
-    this.state = AdbState.AUTH_STEP1;
-    await this.send('CNXN', VERSION, this.maxPayload, 'host:1:UsbADB');
-  }
-
-  findInterfaceAndEndpoint() {
-    if (!this.dev) throw Error(DEVICE_NOT_SET_ERROR);
-    for (const config of this.dev.configurations) {
-      for (const interface_ of config.interfaces) {
-        for (const alt of interface_.alternates) {
-          if (alt.interfaceClass === this.filter.classCode &&
-              alt.interfaceSubclass === this.filter.subclassCode &&
-              alt.interfaceProtocol === this.filter.protocolCode) {
-            return {
-              configValue: config.configurationValue,
-              usbInterfaceNumber: interface_.interfaceNumber,
-              endpoints: alt.endpoints
-            };
-          }  // if (alternate)
-        }    // for (interface.alternates)
-      }      // for (configuration.interfaces)
-    }        // for (configurations)
-
-    throw Error('Cannot find interfaces and endpoints');
-  }
-
-  findEndpointNumber(
-      endpoints: USBEndpoint[], direction: 'out'|'in', type = 'bulk'): number {
-    const ep =
-        endpoints.find((ep) => ep.type === type && ep.direction === direction);
-
-    if (ep) return ep.endpointNumber;
-
-    throw Error(`Cannot find ${direction} endpoint`);
-  }
-
-  receiveDeviceMessages() {
-    this.recv()
-        .then(msg => {
-          this.onMessage(msg);
-          this.receiveDeviceMessages();
-        })
-        .catch(e => {
-          // Ignore error with "DEVICE_NOT_SET_ERROR" message since it is always
-          // thrown after the device disconnects.
-          if (e.message !== DEVICE_NOT_SET_ERROR) {
-            console.error(`Exception in recv: ${e.name}. error: ${e.message}`);
-          }
-          this.disconnect();
-        });
-  }
-
-  async onMessage(msg: AdbMsg) {
-    if (!this.key) throw Error('ADB key not initialized');
-
-    if (msg.cmd === 'AUTH' && msg.arg0 === AuthCmd.TOKEN) {
-      this.handleAuthentication(msg);
-    } else if (msg.cmd === 'CNXN') {
-      console.assert(
-          [AdbState.AUTH_STEP2, AdbState.AUTH_STEP3].includes(this.state));
-      this.state = AdbState.CONNECTED;
-      this.handleConnectedMessage(msg);
-    } else if (this.state === AdbState.CONNECTED && [
-                 'OKAY',
-                 'WRTE',
-                 'CLSE'
-               ].indexOf(msg.cmd) >= 0) {
-      const stream = this.streams.get(msg.arg1);
-      if (!stream) {
-        console.warn(`Received message ${msg} for unknown stream ${msg.arg1}`);
-        return;
-      }
-      stream.onMessage(msg);
-    } else {
-      console.error(`Unexpected message `, msg, ` in state ${this.state}`);
-    }
-  }
-
-  async handleAuthentication(msg: AdbMsg) {
-    if (!this.key) throw Error('ADB key not initialized');
-
-    console.assert(msg.cmd === 'AUTH' && msg.arg0 === AuthCmd.TOKEN);
-    const token = msg.data;
-
-    if (this.state === AdbState.AUTH_STEP1) {
-      // During this step, we send back the token received signed with our
-      // private key. If the device has previously received our public key, the
-      // dialog will not be displayed. Otherwise we will receive another message
-      // ending up in AUTH_STEP3.
-      this.state = AdbState.AUTH_STEP2;
-
-      const signedToken =
-          await signAdbTokenWithPrivateKey(this.key.privateKey, token);
-      this.send('AUTH', AuthCmd.SIGNATURE, 0, new Uint8Array(signedToken));
-      return;
-    }
-
-    console.assert(this.state === AdbState.AUTH_STEP2);
-
-    // During this step, we send our public key. The dialog will appear, and
-    // if the user chooses to remember our public key, it will be
-    // saved, so that the next time we will only pass through AUTH_STEP1.
-    this.state = AdbState.AUTH_STEP3;
-    const encodedPubKey = await encodePubKey(this.key.publicKey);
-    this.send('AUTH', AuthCmd.RSAPUBLICKEY, 0, encodedPubKey);
-  }
-
-  private handleConnectedMessage(msg: AdbMsg) {
-    console.assert(msg.cmd === 'CNXN');
-
-    this.maxPayload = msg.arg1;
-    this.devProps = textDecoder.decode(msg.data);
-
-    const deviceVersion = msg.arg0;
-
-    if (![VERSION_WITH_CHECKSUM, VERSION_NO_CHECKSUM].includes(deviceVersion)) {
-      console.error('Version ', msg.arg0, ' not really supported!');
-    }
-    this.useChecksum = deviceVersion === VERSION_WITH_CHECKSUM;
-    this.state = AdbState.CONNECTED;
-
-    // This will resolve the promise returned by "onConnect"
-    this.onConnected();
-    this.onConnected = () => {};
-  }
-
-  shell(cmd: string): Promise<AdbStream> {
-    return this.openStream('shell:' + cmd);
-  }
-
-  socket(path: string): Promise<AdbStream> {
-    return this.openStream('localfilesystem:' + path);
-  }
-
-  openStream(svc: string): Promise<AdbStream> {
-    const stream = new AdbStreamImpl(this, ++this.lastStreamId);
-    this.streams.set(stream.localStreamId, stream);
-    this.send('OPEN', stream.localStreamId, 0, svc);
-
-    //  The stream will resolve this promise once it receives the
-    //  acknowledgement message from the device.
-    return new Promise<AdbStream>((resolve, reject) => {
-      stream.onConnect = () => {
-        stream.onClose = () => {};
-        resolve(stream);
-      };
-      stream.onClose = () => reject();
-    });
-  }
-
-  async shellOutputAsString(cmd: string): Promise<string> {
-    const shell = await this.shell(cmd);
-
-    return new Promise<string>((resolve, _) => {
-      const output: string[] = [];
-      shell.onData = raw => output.push(textDecoder.decode(raw));
-      shell.onClose = () => resolve(output.join());
-    });
-  }
-
-  async send(
-      cmd: CmdType, arg0: number, arg1: number, data?: Uint8Array|string) {
-    await this.sendMsg(AdbMsgImpl.create(
-        {cmd, arg0, arg1, data, useChecksum: this.useChecksum}));
-  }
-
-  //  The header and the message data must be sent consecutively. Using 2 awaits
-  //  Another message can interleave after the first header has been sent,
-  //  resulting in something like [header1] [header2] [data1] [data2];
-  //  In this way we are waiting both promises to be resolved before continuing.
-  async sendMsg(msg: AdbMsgImpl) {
-    const sendPromises = [this.sendRaw(msg.encodeHeader())];
-    if (msg.data.length > 0) sendPromises.push(this.sendRaw(msg.data));
-    await Promise.all(sendPromises);
-  }
-
-  async recv(): Promise<AdbMsg> {
-    const res = await this.recvRaw(ADB_MSG_SIZE);
-    console.assert(res.status === 'ok');
-    const msg = AdbMsgImpl.decodeHeader(res.data!);
-
-    if (msg.dataLen > 0) {
-      const resp = await this.recvRaw(msg.dataLen);
-      msg.data = new Uint8Array(
-          resp.data!.buffer, resp.data!.byteOffset, resp.data!.byteLength);
-    }
-    if (this.useChecksum) {
-      console.assert(AdbOverWebUsb.checksum(msg.data) === msg.dataChecksum);
-    }
-    return msg;
-  }
-
-  static async initKey(): Promise<CryptoKeyPair> {
-    const KEY_SIZE = 2048;
-
-    const keySpec = {
-      name: 'RSASSA-PKCS1-v1_5',
-      modulusLength: KEY_SIZE,
-      publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
-      hash: {name: 'SHA-1'},
-    };
-
-    const key = await crypto.subtle.generateKey(
-        keySpec, /*extractable=*/ true, ['sign', 'verify']);
-
-    return key;
-  }
-
-  static checksum(data: Uint8Array): number {
-    let res = 0;
-    for (let i = 0; i < data.byteLength; i++) res += data[i];
-    return res & 0xFFFFFFFF;
-  }
-
-  sendRaw(buf: Uint8Array): Promise<USBOutTransferResult> {
-    console.assert(buf.length <= this.maxPayload);
-    if (!this.dev) throw Error(DEVICE_NOT_SET_ERROR);
-    return this.dev.transferOut(this.usbWriteEpEndpoint, buf.buffer);
-  }
-
-  recvRaw(dataLen: number): Promise<USBInTransferResult> {
-    if (!this.dev) throw Error(DEVICE_NOT_SET_ERROR);
-    return this.dev.transferIn(this.usbReadEndpoint, dataLen);
-  }
-}
-
-enum AdbStreamState {
-  WAITING_INITIAL_OKAY = 0,
-  CONNECTED = 1,
-  CLOSED = 2
-}
-
-
-// An AdbStream is instantiated after the creation of a shell to the device.
-// Thanks to this, we can send commands and receive their output. Messages are
-// received in the main adb class, and are forwarded to an instance of this
-// class based on a stream id match. Also streams have an initialization flow:
-//   1. WAITING_INITIAL_OKAY: waiting for first "OKAY" message. Once received,
-//      the next state will be "CONNECTED".
-//   2. CONNECTED: ready to receive or send messages.
-//   3. WRITING: this is needed because we must receive an ack after sending
-//      each message (so, before sending the next one). For this reason, many
-//      subsequent "write" calls will result in different messages in the
-//      writeQueue. After each new acknowledgement ('OKAY') a new one will be
-//      sent. When the queue is empty, the state will return to CONNECTED.
-//   4. CLOSED: entered when the device closes the stream or close() is called.
-//      For shell commands, the stream is closed after the command completed.
-export class AdbStreamImpl implements AdbStream {
-  private adb: AdbOverWebUsb;
-  localStreamId: number;
-  private remoteStreamId = -1;
-  private state: AdbStreamState = AdbStreamState.WAITING_INITIAL_OKAY;
-  private writeQueue: Uint8Array[] = [];
-
-  private sendInProgress = false;
-
-  onData: AdbStreamReadCallback = (_) => {};
-  onConnect = () => {};
-  onClose = () => {};
-
-  constructor(adb: AdbOverWebUsb, localStreamId: number) {
-    this.adb = adb;
-    this.localStreamId = localStreamId;
-  }
-
-  close() {
-    console.assert(this.state === AdbStreamState.CONNECTED);
-
-    if (this.writeQueue.length > 0) {
-      console.error(`Dropping ${
-          this.writeQueue.length} queued messages due to stream closing.`);
-      this.writeQueue = [];
-    }
-
-    this.adb.send('CLSE', this.localStreamId, this.remoteStreamId);
-  }
-
-  async write(msg: string|Uint8Array) {
-    const raw = (typeof msg === 'string') ? textEncoder.encode(msg) : msg;
-    if (this.sendInProgress ||
-        this.state === AdbStreamState.WAITING_INITIAL_OKAY) {
-      this.writeQueue.push(raw);
-      return;
-    }
-    console.assert(this.state === AdbStreamState.CONNECTED);
-    this.sendInProgress = true;
-    await this.adb.send('WRTE', this.localStreamId, this.remoteStreamId, raw);
-  }
-
-  setClosed() {
-    this.state = AdbStreamState.CLOSED;
-    this.adb.streams.delete(this.localStreamId);
-    this.onClose();
-  }
-
-  onMessage(msg: AdbMsgImpl) {
-    console.assert(msg.arg1 === this.localStreamId);
-
-    if (this.state === AdbStreamState.WAITING_INITIAL_OKAY &&
-        msg.cmd === 'OKAY') {
-      this.remoteStreamId = msg.arg0;
-      this.state = AdbStreamState.CONNECTED;
-      this.onConnect();
-      return;
-    }
-
-    if (msg.cmd === 'WRTE') {
-      this.adb.send('OKAY', this.localStreamId, this.remoteStreamId);
-      this.onData(msg.data);
-      return;
-    }
-
-    if (msg.cmd === 'OKAY') {
-      console.assert(this.sendInProgress);
-      this.sendInProgress = false;
-      const queuedMsg = this.writeQueue.shift();
-      if (queuedMsg !== undefined) this.write(queuedMsg);
-      return;
-    }
-
-    if (msg.cmd === 'CLSE') {
-      this.setClosed();
-      return;
-    }
-    console.error(
-        `Unexpected stream msg ${msg.toString()} in state ${this.state}`);
-  }
-}
-
-interface AdbStreamReadCallback {
-  (raw: Uint8Array): void;
-}
-
-const ADB_MSG_SIZE = 6 * 4;  // 6 * int32.
-
-export class AdbMsgImpl implements AdbMsg {
-  cmd: CmdType;
-  arg0: number;
-  arg1: number;
-  data: Uint8Array;
-  dataLen: number;
-  dataChecksum: number;
-
-  useChecksum: boolean;
-
-  constructor(
-      cmd: CmdType, arg0: number, arg1: number, dataLen: number,
-      dataChecksum: number, useChecksum = false) {
-    console.assert(cmd.length === 4);
-    this.cmd = cmd;
-    this.arg0 = arg0;
-    this.arg1 = arg1;
-    this.dataLen = dataLen;
-    this.data = new Uint8Array(dataLen);
-    this.dataChecksum = dataChecksum;
-    this.useChecksum = useChecksum;
-  }
-
-
-  static create({cmd, arg0, arg1, data, useChecksum = true}: {
-    cmd: CmdType; arg0: number; arg1: number;
-    data?: Uint8Array | string;
-    useChecksum?: boolean;
-  }): AdbMsgImpl {
-    const encodedData = this.encodeData(data);
-    const msg =
-        new AdbMsgImpl(cmd, arg0, arg1, encodedData.length, 0, useChecksum);
-    msg.data = encodedData;
-    return msg;
-  }
-
-  get dataStr() {
-    return textDecoder.decode(this.data);
-  }
-
-  toString() {
-    return `${this.cmd} [${this.arg0},${this.arg1}] ${this.dataStr}`;
-  }
-
-  // A brief description of the message can be found here:
-  // https://android.googlesource.com/platform/system/core/+/master/adb/protocol.txt
-  //
-  // struct amessage {
-  //     uint32_t command;    // command identifier constant
-  //     uint32_t arg0;       // first argument
-  //     uint32_t arg1;       // second argument
-  //     uint32_t data_length;// length of payload (0 is allowed)
-  //     uint32_t data_check; // checksum of data payload
-  //     uint32_t magic;      // command ^ 0xffffffff
-  // };
-  static decodeHeader(dv: DataView): AdbMsgImpl {
-    console.assert(dv.byteLength === ADB_MSG_SIZE);
-    const cmd = textDecoder.decode(dv.buffer.slice(0, 4)) as CmdType;
-    const cmdNum = dv.getUint32(0, true);
-    const arg0 = dv.getUint32(4, true);
-    const arg1 = dv.getUint32(8, true);
-    const dataLen = dv.getUint32(12, true);
-    const dataChecksum = dv.getUint32(16, true);
-    const cmdChecksum = dv.getUint32(20, true);
-    console.assert(cmdNum === (cmdChecksum ^ 0xFFFFFFFF));
-    return new AdbMsgImpl(cmd, arg0, arg1, dataLen, dataChecksum);
-  }
-
-  encodeHeader(): Uint8Array {
-    const buf = new Uint8Array(ADB_MSG_SIZE);
-    const dv = new DataView(buf.buffer);
-    const cmdBytes: Uint8Array = textEncoder.encode(this.cmd);
-    const rawMsg = AdbMsgImpl.encodeData(this.data);
-    const checksum = this.useChecksum ? AdbOverWebUsb.checksum(rawMsg) : 0;
-    for (let i = 0; i < 4; i++) dv.setUint8(i, cmdBytes[i]);
-
-    dv.setUint32(4, this.arg0, true);
-    dv.setUint32(8, this.arg1, true);
-    dv.setUint32(12, rawMsg.byteLength, true);
-    dv.setUint32(16, checksum, true);
-    dv.setUint32(20, dv.getUint32(0, true) ^ 0xFFFFFFFF, true);
-
-    return buf;
-  }
-
-  static encodeData(data?: Uint8Array|string): Uint8Array {
-    if (data === undefined) return new Uint8Array([]);
-    if (typeof data === 'string') return textEncoder.encode(data + '\0');
-    return data;
-  }
-}
-
-
-function base64StringToArray(s: string) {
-  const decoded = atob(s.replace(/-/g, '+').replace(/_/g, '/'));
-  return [...decoded].map(char => char.charCodeAt(0));
-}
-
-const ANDROID_PUBKEY_MODULUS_SIZE = 2048;
-const MODULUS_SIZE_BYTES = ANDROID_PUBKEY_MODULUS_SIZE / 8;
-
-// RSA Public keys are encoded in a rather unique way. It's a base64 encoded
-// struct of 524 bytes in total as follows (see
-// libcrypto_utils/android_pubkey.c):
-//
-// typedef struct RSAPublicKey {
-//   // Modulus length. This must be ANDROID_PUBKEY_MODULUS_SIZE.
-//   uint32_t modulus_size_words;
-//
-//   // Precomputed montgomery parameter: -1 / n[0] mod 2^32
-//   uint32_t n0inv;
-//
-//   // RSA modulus as a little-endian array.
-//   uint8_t modulus[ANDROID_PUBKEY_MODULUS_SIZE];
-//
-//   // Montgomery parameter R^2 as a little-endian array of little-endian
-//   words. uint8_t rr[ANDROID_PUBKEY_MODULUS_SIZE];
-//
-//   // RSA modulus: 3 or 65537
-//   uint32_t exponent;
-// } RSAPublicKey;
-//
-// However, the Montgomery params (n0inv and rr) are not really used, see
-// comment in android_pubkey_decode() ("Note that we don't extract the
-// montgomery parameters...")
-async function encodePubKey(key: CryptoKey) {
-  const expPubKey = await crypto.subtle.exportKey('jwk', key);
-  const nArr = base64StringToArray(expPubKey.n as string).reverse();
-  const eArr = base64StringToArray(expPubKey.e as string).reverse();
-
-  const arr = new Uint8Array(3 * 4 + 2 * MODULUS_SIZE_BYTES);
-  const dv = new DataView(arr.buffer);
-  dv.setUint32(0, MODULUS_SIZE_BYTES / 4, true);
-
-  // The Mongomery params (n0inv and rr) are not computed.
-  dv.setUint32(4, 0 /*n0inv*/, true);
-  // Modulus
-  for (let i = 0; i < MODULUS_SIZE_BYTES; i++) dv.setUint8(8 + i, nArr[i]);
-
-  // rr:
-  for (let i = 0; i < MODULUS_SIZE_BYTES; i++) {
-    dv.setUint8(8 + MODULUS_SIZE_BYTES + i, 0 /*rr*/);
-  }
-  // Exponent
-  for (let i = 0; i < 4; i++) {
-    dv.setUint8(8 + (2 * MODULUS_SIZE_BYTES) + i, eArr[i]);
-  }
-  return btoa(String.fromCharCode(...new Uint8Array(dv.buffer))) +
-      ' perfetto@webusb';
-}
-
-// TODO(nicomazz): This token signature will be useful only when we save the
-// generated keys. So far, we are not doing so. As a consequence, a dialog is
-// displayed every time a tracing session is started.
-// The reason why it has not already been implemented is that the standard
-// crypto.subtle.sign function assumes that the input needs hashing, which is
-// not the case for ADB, where the 20 bytes token is already hashed.
-// A solution to this is implementing a custom private key signature with a js
-// implementation of big integers. Maybe, wrapping the key like in the following
-// CL can work:
-// https://android-review.googlesource.com/c/platform/external/perfetto/+/1105354/18
-async function signAdbTokenWithPrivateKey(
-    _privateKey: CryptoKey, token: Uint8Array): Promise<ArrayBuffer> {
-  // This function is not implemented.
-  return token.buffer;
-}
diff --git a/ui/src/controller/adb_base_controller.ts b/ui/src/controller/adb_base_controller.ts
deleted file mode 100644
index 6642c98..0000000
--- a/ui/src/controller/adb_base_controller.ts
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {extractDurationFromTraceConfig} from '../base/extract_utils';
-import {extractTraceConfig} from '../base/extract_utils';
-
-import {Adb} from './adb_interfaces';
-import {ReadBuffersResponse} from './consumer_port_types';
-import {globals} from './globals';
-import {Consumer, RpcConsumerPort} from './record_controller_interfaces';
-
-export enum AdbAuthState {
-  DISCONNECTED,
-  AUTH_IN_PROGRESS,
-  CONNECTED,
-}
-
-interface Command {
-  method: string;
-  params: Uint8Array;
-}
-
-export abstract class AdbBaseConsumerPort extends RpcConsumerPort {
-  // Contains the commands sent while the authentication is in progress. They
-  // will all be executed afterwards. If the device disconnects, they are
-  // removed.
-  private commandQueue: Command[] = [];
-
-  protected adb: Adb;
-  protected state = AdbAuthState.DISCONNECTED;
-  protected device?: USBDevice;
-
-  constructor(adb: Adb, consumer: Consumer) {
-    super(consumer);
-    this.adb = adb;
-  }
-
-  async handleCommand(method: string, params: Uint8Array) {
-    try {
-      this.commandQueue.push({method, params});
-      if (this.state === AdbAuthState.DISCONNECTED ||
-          this.deviceDisconnected()) {
-        this.state = AdbAuthState.AUTH_IN_PROGRESS;
-        this.device = await this.findDevice();
-        if (!this.device) {
-          this.state = AdbAuthState.DISCONNECTED;
-          throw Error(`Device with serial ${
-              globals.state.serialAndroidDeviceConnected} not found.`);
-        }
-
-        this.sendStatus(`Please allow USB debugging on device.
-          If you press cancel, reload the page.`);
-
-        await this.adb.connect(this.device);
-
-        // During the authentication the device may have been disconnected.
-        if (!globals.state.recordingInProgress || this.deviceDisconnected()) {
-          throw Error('Recording not in progress after adb authorization.');
-        }
-
-        this.state = AdbAuthState.CONNECTED;
-        this.sendStatus('Device connected.');
-      }
-
-      if (this.state === AdbAuthState.AUTH_IN_PROGRESS) return;
-
-      console.assert(this.state === AdbAuthState.CONNECTED);
-
-      for (const cmd of this.commandQueue) this.invoke(cmd.method, cmd.params);
-
-      this.commandQueue = [];
-    } catch (e) {
-      this.commandQueue = [];
-      this.state = AdbAuthState.DISCONNECTED;
-      this.sendErrorMessage(e.message);
-    }
-  }
-
-  private deviceDisconnected() {
-    return !this.device || !this.device.opened;
-  }
-
-  setDurationStatus(enableTracingProto: Uint8Array) {
-    const traceConfigProto = extractTraceConfig(enableTracingProto);
-    if (!traceConfigProto) return;
-    const duration = extractDurationFromTraceConfig(traceConfigProto);
-    this.sendStatus(`Recording in progress${
-        duration ? ' for ' + duration.toString() + ' ms' : ''}...`);
-  }
-
-  abstract invoke(method: string, argsProto: Uint8Array): void;
-
-  generateChunkReadResponse(data: Uint8Array, last = false):
-      ReadBuffersResponse {
-    return {
-      type: 'ReadBuffersResponse',
-      slices: [{data, lastSliceForPacket: last}]
-    };
-  }
-
-  async findDevice(): Promise<USBDevice|undefined> {
-    const deviceConnected = globals.state.androidDeviceConnected;
-    if (!deviceConnected) return undefined;
-    const devices = await navigator.usb.getDevices();
-    return devices.find(d => d.serialNumber === deviceConnected.serial);
-  }
-}
\ No newline at end of file
diff --git a/ui/src/controller/adb_interfaces.ts b/ui/src/controller/adb_interfaces.ts
deleted file mode 100644
index e4759b8..0000000
--- a/ui/src/controller/adb_interfaces.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (C) 2019 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.
-
-
-export interface Adb {
-  connect(device: USBDevice): Promise<void>;
-  disconnect(): Promise<void>;
-  // Executes a shell command non-interactively.
-  shell(cmd: string): Promise<AdbStream>;
-  // Waits until the shell get closed, and returns all the output.
-  shellOutputAsString(cmd: string): Promise<string>;
-  // Opens a connection to a UNIX socket.
-  socket(path: string): Promise<AdbStream>;
-}
-
-export interface AdbStream {
-  write(msg: string|Uint8Array): Promise<void>;
-  onMessage(message: AdbMsg): void;
-  close(): void;
-  setClosed(): void;
-
-  onConnect: VoidCallback;
-  onClose: VoidCallback;
-  onData: (raw: Uint8Array) => void;
-}
-
-export class MockAdb implements Adb {
-  connect(_: USBDevice): Promise<void> {
-    return Promise.resolve();
-  }
-
-  disconnect(): Promise<void> {
-    return Promise.resolve();
-  }
-
-  shell(_: string): Promise<AdbStream> {
-    return Promise.resolve(new MockAdbStream());
-  }
-
-  shellOutputAsString(_: string): Promise<string> {
-    return Promise.resolve('');
-  }
-
-  socket(_: string): Promise<AdbStream> {
-    return Promise.resolve(new MockAdbStream());
-  }
-}
-
-export class MockAdbStream implements AdbStream {
-  write(_: string|Uint8Array): Promise<void> {
-    return Promise.resolve();
-  }
-  onMessage = (_: AdbMsg) => {};
-  close() {}
-  setClosed() {}
-
-  onConnect = () => {};
-  onClose = () => {};
-  onData = (_: Uint8Array) => {};
-}
-
-export declare type CmdType =
-    'CNXN' | 'AUTH' | 'CLSE' | 'OKAY' | 'WRTE' | 'OPEN';
-
-export interface AdbMsg {
-  cmd: CmdType;
-  arg0: number;
-  arg1: number;
-  data: Uint8Array;
-  dataLen: number;
-  dataChecksum: number;
-}
\ No newline at end of file
diff --git a/ui/src/controller/adb_jsdomtest.ts b/ui/src/controller/adb_jsdomtest.ts
deleted file mode 100644
index 83d05fd..0000000
--- a/ui/src/controller/adb_jsdomtest.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {TextEncoder} from 'util';
-
-import {
-  AdbMsgImpl,
-  AdbOverWebUsb,
-  AdbState,
-  DEFAULT_MAX_PAYLOAD_BYTES,
-  VERSION_WITH_CHECKSUM
-} from './adb';
-
-test('startAuthentication', async () => {
-  const adb = new AdbOverWebUsb();
-
-  const sendRaw = jest.fn();
-  adb.sendRaw = sendRaw;
-  const recvRaw = jest.fn();
-  adb.recvRaw = recvRaw;
-
-
-  const expectedAuthMessage = AdbMsgImpl.create({
-    cmd: 'CNXN',
-    arg0: VERSION_WITH_CHECKSUM,
-    arg1: DEFAULT_MAX_PAYLOAD_BYTES,
-    data: 'host:1:UsbADB',
-    useChecksum: true
-  });
-  await adb.startAuthentication();
-
-  expect(sendRaw).toHaveBeenCalledTimes(2);
-  expect(sendRaw).toBeCalledWith(expectedAuthMessage.encodeHeader());
-  expect(sendRaw).toBeCalledWith(expectedAuthMessage.data);
-});
-
-test('connectedMessage', async () => {
-  const adb = new AdbOverWebUsb();
-  adb.key = {} as unknown as CryptoKeyPair;
-  adb.state = AdbState.AUTH_STEP2;
-
-  const onConnected = jest.fn();
-  adb.onConnected = onConnected;
-
-  const expectedMaxPayload = 42;
-  const connectedMsg = AdbMsgImpl.create({
-    cmd: 'CNXN',
-    arg0: VERSION_WITH_CHECKSUM,
-    arg1: expectedMaxPayload,
-    data: new TextEncoder().encode('device'),
-    useChecksum: true
-  });
-  await adb.onMessage(connectedMsg);
-
-  expect(adb.state).toBe(AdbState.CONNECTED);
-  expect(adb.maxPayload).toBe(expectedMaxPayload);
-  expect(adb.devProps).toBe('device');
-  expect(adb.useChecksum).toBe(true);
-  expect(onConnected).toHaveBeenCalledTimes(1);
-});
-
-
-test('shellOpening', () => {
-  const adb = new AdbOverWebUsb();
-  const openStream = jest.fn();
-  adb.openStream = openStream;
-
-  adb.shell('test');
-  expect(openStream).toBeCalledWith('shell:test');
-});
diff --git a/ui/src/controller/adb_record_controller_jsdomtest.ts b/ui/src/controller/adb_record_controller_jsdomtest.ts
deleted file mode 100644
index 204033c..0000000
--- a/ui/src/controller/adb_record_controller_jsdomtest.ts
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {dingus} from 'dingusjs';
-
-import {stringToUint8Array} from '../base/string_utils';
-import {perfetto} from '../gen/protos';
-
-import {AdbStream, MockAdb, MockAdbStream} from './adb_interfaces';
-import {AdbConsumerPort} from './adb_shell_controller';
-import {Consumer} from './record_controller_interfaces';
-
-function generateMockConsumer(): Consumer {
-  return {
-    onConsumerPortResponse: jest.fn(),
-    onError: jest.fn(),
-    onStatus: jest.fn()
-  };
-}
-const mainCallback = generateMockConsumer();
-const adbMock = new MockAdb();
-const adbController = new AdbConsumerPort(adbMock, mainCallback);
-const mockIntArray = new Uint8Array();
-
-const enableTracingRequest = new perfetto.protos.EnableTracingRequest();
-enableTracingRequest.traceConfig = new perfetto.protos.TraceConfig();
-const enableTracingRequestProto =
-    perfetto.protos.EnableTracingRequest.encode(enableTracingRequest).finish();
-
-
-test('handleCommand', async () => {
-  adbController.findDevice = () => {
-    return Promise.resolve(dingus<USBDevice>());
-  };
-
-  const enableTracing = jest.fn();
-  adbController.enableTracing = enableTracing;
-  await adbController.invoke('EnableTracing', mockIntArray);
-  expect(enableTracing).toHaveBeenCalledTimes(1);
-
-  const readBuffers = jest.fn();
-  adbController.readBuffers = readBuffers;
-  adbController.invoke('ReadBuffers', mockIntArray);
-  expect(readBuffers).toHaveBeenCalledTimes(1);
-
-  const sendErrorMessage = jest.fn();
-  adbController.sendErrorMessage = sendErrorMessage;
-  adbController.invoke('unknown', mockIntArray);
-  expect(sendErrorMessage).toBeCalledWith('Method not recognized: unknown');
-});
-
-test('enableTracing', async () => {
-  const mainCallback = generateMockConsumer();
-  const adbMock = new MockAdb();
-  const adbController = new AdbConsumerPort(adbMock, mainCallback);
-
-  adbController.sendErrorMessage =
-      jest.fn().mockImplementation(s => console.error(s));
-
-  const findDevice = jest.fn().mockImplementation(() => {
-    return Promise.resolve({} as unknown as USBDevice);
-  });
-  adbController.findDevice = findDevice;
-
-  const connectToDevice =
-      jest.fn().mockImplementation((_: USBDevice) => Promise.resolve());
-  adbMock.connect = connectToDevice;
-
-  const stream: AdbStream = new MockAdbStream();
-  const adbShell =
-      jest.fn().mockImplementation((_: string) => Promise.resolve(stream));
-  adbMock.shell = adbShell;
-
-
-  const sendMessage = jest.fn();
-  adbController.sendMessage = sendMessage;
-
-  adbController.generateStartTracingCommand = (_) => 'CMD';
-
-  await adbController.enableTracing(enableTracingRequestProto);
-  expect(adbShell).toBeCalledWith('CMD');
-  expect(sendMessage).toHaveBeenCalledTimes(0);
-
-
-  stream.onData(stringToUint8Array('starting tracing Wrote 123 bytes'));
-  stream.onClose();
-
-  expect(adbController.sendErrorMessage).toHaveBeenCalledTimes(0);
-  expect(sendMessage).toBeCalledWith({type: 'EnableTracingResponse'});
-});
-
-
-test('generateStartTracing', () => {
-  adbController.traceDestFile = 'DEST';
-  const testArray = new Uint8Array(1);
-  testArray[0] = 65;
-  const generatedCmd = adbController.generateStartTracingCommand(testArray);
-  expect(generatedCmd)
-      .toBe(`echo '${btoa('A')}' | base64 -d | perfetto -c - -o DEST`);
-});
-
-test('tracingEndedSuccessfully', () => {
-  expect(adbController.tracingEndedSuccessfully(
-             'Connected to the Perfetto traced service,\ starting tracing for \
-10000 ms\nWrote 564 bytes into /data/misc/perfetto-traces/trace'))
-      .toBe(true);
-  expect(adbController.tracingEndedSuccessfully(
-             'Connected to the Perfetto traced service, starting tracing for \
-10000 ms'))
-      .toBe(false);
-  expect(adbController.tracingEndedSuccessfully(
-             'Connected to the Perfetto traced service, starting tracing for \
-0 ms'))
-      .toBe(false);
-});
diff --git a/ui/src/controller/adb_shell_controller.ts b/ui/src/controller/adb_shell_controller.ts
deleted file mode 100644
index 62c8204..0000000
--- a/ui/src/controller/adb_shell_controller.ts
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {_TextDecoder} from 'custom_utils';
-
-import {extractTraceConfig} from '../base/extract_utils';
-import {uint8ArrayToBase64} from '../base/string_utils';
-
-import {AdbAuthState, AdbBaseConsumerPort} from './adb_base_controller';
-import {Adb, AdbStream} from './adb_interfaces';
-import {ReadBuffersResponse} from './consumer_port_types';
-import {Consumer} from './record_controller_interfaces';
-
-enum AdbShellState {
-  READY,
-  RECORDING,
-  FETCHING
-}
-const DEFAULT_DESTINATION_FILE = '/data/misc/perfetto-traces/trace-by-ui';
-const textDecoder = new _TextDecoder();
-
-export class AdbConsumerPort extends AdbBaseConsumerPort {
-  traceDestFile = DEFAULT_DESTINATION_FILE;
-  shellState: AdbShellState = AdbShellState.READY;
-  private recordShell?: AdbStream;
-
-  constructor(adb: Adb, consumer: Consumer) {
-    super(adb, consumer);
-    this.adb = adb;
-  }
-
-  async invoke(method: string, params: Uint8Array) {
-    // ADB connection & authentication is handled by the superclass.
-    console.assert(this.state === AdbAuthState.CONNECTED);
-
-    switch (method) {
-      case 'EnableTracing':
-        this.enableTracing(params);
-        break;
-      case 'ReadBuffers':
-        this.readBuffers();
-        break;
-      case 'DisableTracing':
-        this.disableTracing();
-        break;
-      case 'FreeBuffers':
-        this.freeBuffers();
-        break;
-      case 'GetTraceStats':
-        break;
-      default:
-        this.sendErrorMessage(`Method not recognized: ${method}`);
-        break;
-    }
-  }
-
-  async enableTracing(enableTracingProto: Uint8Array) {
-    try {
-      const traceConfigProto = extractTraceConfig(enableTracingProto);
-      if (!traceConfigProto) {
-        this.sendErrorMessage('Invalid config.');
-        return;
-      }
-
-      await this.startRecording(traceConfigProto);
-      this.setDurationStatus(enableTracingProto);
-    } catch (e) {
-      this.sendErrorMessage(e.message);
-    }
-  }
-
-  async startRecording(configProto: Uint8Array) {
-    this.shellState = AdbShellState.RECORDING;
-    const recordCommand = this.generateStartTracingCommand(configProto);
-    this.recordShell = await this.adb.shell(recordCommand);
-    const output: string[] = [];
-    this.recordShell.onData = raw => output.push(textDecoder.decode(raw));
-    this.recordShell.onClose = () => {
-      const response = output.join();
-      if (!this.tracingEndedSuccessfully(response)) {
-        this.sendErrorMessage(response);
-        this.shellState = AdbShellState.READY;
-        return;
-      }
-      this.sendStatus('Recording ended successfully. Fetching the trace..');
-      this.sendMessage({type: 'EnableTracingResponse'});
-      this.recordShell = undefined;
-    };
-  }
-
-  tracingEndedSuccessfully(response: string): boolean {
-    return !response.includes(' 0 ms') && response.includes('Wrote ');
-  }
-
-  async readBuffers() {
-    console.assert(this.shellState === AdbShellState.RECORDING);
-    this.shellState = AdbShellState.FETCHING;
-
-    const readTraceShell =
-        await this.adb.shell(this.generateReadTraceCommand());
-    readTraceShell.onData = raw =>
-        this.sendMessage(this.generateChunkReadResponse(raw));
-
-    readTraceShell.onClose = () => {
-      this.sendMessage(
-          this.generateChunkReadResponse(new Uint8Array(), /* last */ true));
-    };
-  }
-
-  async getPidFromShellAsString() {
-    const pidStr =
-        await this.adb.shellOutputAsString(`ps -u shell | grep perfetto`);
-    // We used to use awk '{print $2}' but older phones/Go phones don't have
-    // awk installed. Instead we implement similar functionality here.
-    const awk = pidStr.split(' ').filter(str => str !== '');
-    if (awk.length < 1) {
-      throw Error(`Unabled to find perfetto pid in string "${pidStr}"`);
-    }
-    return awk[1];
-  }
-
-  async disableTracing() {
-    if (!this.recordShell) return;
-    try {
-      // We are not using 'pidof perfetto' so that we can use more filters. 'ps
-      // -u shell' is meant to catch processes started from shell, so if there
-      // are other ongoing tracing sessions started by others, we are not
-      // killing them.
-      const pid = await this.getPidFromShellAsString();
-
-      if (pid.length === 0 || isNaN(Number(pid))) {
-        throw Error(`Perfetto pid not found. Impossible to stop/cancel the
-     recording. Command output: ${pid}`);
-      }
-      // Perfetto stops and finalizes the tracing session on SIGINT.
-      const killOutput =
-          await this.adb.shellOutputAsString(`kill -SIGINT ${pid}`);
-
-      if (killOutput.length !== 0) {
-        throw Error(`Unable to kill perfetto: ${killOutput}`);
-      }
-    } catch (e) {
-      this.sendErrorMessage(e.message);
-    }
-  }
-
-  freeBuffers() {
-    this.shellState = AdbShellState.READY;
-    if (this.recordShell) {
-      this.recordShell.close();
-      this.recordShell = undefined;
-    }
-  }
-
-  generateChunkReadResponse(data: Uint8Array, last = false):
-      ReadBuffersResponse {
-    return {
-      type: 'ReadBuffersResponse',
-      slices: [{data, lastSliceForPacket: last}]
-    };
-  }
-
-  generateReadTraceCommand(): string {
-    // We attempt to delete the trace file after tracing. On a non-root shell,
-    // this will fail (due to selinux denial), but perfetto cmd will be able to
-    // override the file later. However, on a root shell, we need to clean up
-    // the file since perfetto cmd might otherwise fail to override it in a
-    // future session.
-    return `gzip -c ${this.traceDestFile} && rm -f ${this.traceDestFile}`;
-  }
-
-  generateStartTracingCommand(tracingConfig: Uint8Array) {
-    const configBase64 = uint8ArrayToBase64(tracingConfig);
-    const perfettoCmd = `perfetto -c - -o ${this.traceDestFile}`;
-    return `echo '${configBase64}' | base64 -d | ${perfettoCmd}`;
-  }
-}
diff --git a/ui/src/controller/adb_socket_controller.ts b/ui/src/controller/adb_socket_controller.ts
deleted file mode 100644
index 0b63be3..0000000
--- a/ui/src/controller/adb_socket_controller.ts
+++ /dev/null
@@ -1,363 +0,0 @@
-// Copyright (C) 2019 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.
-
-import * as protobuf from 'protobufjs/minimal';
-
-import {perfetto} from '../gen/protos';
-
-import {AdbAuthState, AdbBaseConsumerPort} from './adb_base_controller';
-import {Adb, AdbStream} from './adb_interfaces';
-import {
-  isReadBuffersResponse,
-} from './consumer_port_types';
-import {Consumer} from './record_controller_interfaces';
-
-enum SocketState {
-  DISCONNECTED,
-  BINDING_IN_PROGRESS,
-  BOUND,
-}
-
-// See wire_protocol.proto for more details.
-const WIRE_PROTOCOL_HEADER_SIZE = 4;
-const MAX_IPC_BUFFER_SIZE = 128 * 1024;
-
-const PROTO_LEN_DELIMITED_WIRE_TYPE = 2;
-const TRACE_PACKET_PROTO_ID = 1;
-const TRACE_PACKET_PROTO_TAG =
-    (TRACE_PACKET_PROTO_ID << 3) | PROTO_LEN_DELIMITED_WIRE_TYPE;
-
-declare type Frame = perfetto.ipc.Frame;
-declare type IMethodInfo = perfetto.ipc.Frame.BindServiceReply.IMethodInfo;
-declare type ISlice = perfetto.protos.ReadBuffersResponse.ISlice;
-
-interface Command {
-  method: string;
-  params: Uint8Array;
-}
-
-const TRACED_SOCKET = '/dev/socket/traced_consumer';
-
-export class AdbSocketConsumerPort extends AdbBaseConsumerPort {
-  private socketState = SocketState.DISCONNECTED;
-
-  private socket?: AdbStream;
-  // Wire protocol request ID. After each request it is increased. It is needed
-  // to keep track of the type of request, and parse the response correctly.
-  private requestId = 1;
-
-  // Buffers received wire protocol data.
-  private incomingBuffer = new Uint8Array(MAX_IPC_BUFFER_SIZE);
-  private incomingBufferLen = 0;
-  private frameToParseLen = 0;
-
-  private availableMethods: IMethodInfo[] = [];
-  private serviceId = -1;
-
-  private resolveBindingPromise!: VoidFunction;
-  private requestMethods = new Map<number, string>();
-
-  // Needed for ReadBufferResponse: all the trace packets are split into
-  // several slices. |partialPacket| is the buffer for them. Once we receive a
-  // slice with the flag |lastSliceForPacket|, a new packet is created.
-  private partialPacket: ISlice[] = [];
-  // Accumulates trace packets into a proto trace file..
-  private traceProtoWriter = protobuf.Writer.create();
-
-  private socketCommandQueue: Command[] = [];
-
-  constructor(adb: Adb, consumer: Consumer) {
-    super(adb, consumer);
-  }
-
-  async invoke(method: string, params: Uint8Array) {
-    // ADB connection & authentication is handled by the superclass.
-    console.assert(this.state === AdbAuthState.CONNECTED);
-    this.socketCommandQueue.push({method, params});
-
-    if (this.socketState === SocketState.BINDING_IN_PROGRESS) return;
-    if (this.socketState === SocketState.DISCONNECTED) {
-      this.socketState = SocketState.BINDING_IN_PROGRESS;
-      await this.listenForMessages();
-      await this.bind();
-      this.traceProtoWriter = protobuf.Writer.create();
-      this.socketState = SocketState.BOUND;
-    }
-
-    console.assert(this.socketState === SocketState.BOUND);
-
-    for (const cmd of this.socketCommandQueue) {
-      this.invokeInternal(cmd.method, cmd.params);
-    }
-    this.socketCommandQueue = [];
-  }
-
-  private invokeInternal(method: string, argsProto: Uint8Array) {
-    // Socket is bound in invoke().
-    console.assert(this.socketState === SocketState.BOUND);
-    const requestId = this.requestId++;
-    const methodId = this.findMethodId(method);
-    if (methodId === undefined) {
-      // This can happen with 'GetTraceStats': it seems that not all the Android
-      // <= 9 devices support it.
-      console.error(`Method ${method} not supported by the target`);
-      return;
-    }
-    const frame = new perfetto.ipc.Frame({
-      requestId,
-      msgInvokeMethod: new perfetto.ipc.Frame.InvokeMethod(
-          {serviceId: this.serviceId, methodId, argsProto})
-    });
-    this.requestMethods.set(requestId, method);
-    this.sendFrame(frame);
-
-    if (method === 'EnableTracing') this.setDurationStatus(argsProto);
-  }
-
-  static generateFrameBufferToSend(frame: Frame): Uint8Array {
-    const frameProto: Uint8Array = perfetto.ipc.Frame.encode(frame).finish();
-    const frameLen = frameProto.length;
-    const buf = new Uint8Array(WIRE_PROTOCOL_HEADER_SIZE + frameLen);
-    const dv = new DataView(buf.buffer);
-    dv.setUint32(0, frameProto.length, /* littleEndian */ true);
-    for (let i = 0; i < frameLen; i++) {
-      dv.setUint8(WIRE_PROTOCOL_HEADER_SIZE + i, frameProto[i]);
-    }
-    return buf;
-  }
-
-  async sendFrame(frame: Frame) {
-    console.assert(this.socket !== undefined);
-    if (!this.socket) return;
-    const buf = AdbSocketConsumerPort.generateFrameBufferToSend(frame);
-    await this.socket.write(buf);
-  }
-
-  async listenForMessages() {
-    this.socket = await this.adb.socket(TRACED_SOCKET);
-    this.socket.onData = (raw) => this.handleReceivedData(raw);
-    this.socket.onClose = () => {
-      this.socketState = SocketState.DISCONNECTED;
-      this.socketCommandQueue = [];
-    };
-  }
-
-  private parseMessageSize(buffer: Uint8Array) {
-    const dv = new DataView(buffer.buffer, buffer.byteOffset, buffer.length);
-    return dv.getUint32(0, true);
-  }
-
-  private parseMessage(frameBuffer: Uint8Array) {
-    const frame = perfetto.ipc.Frame.decode(frameBuffer);
-    this.handleIncomingFrame(frame);
-  }
-
-  private incompleteSizeHeader() {
-    if (!this.frameToParseLen) {
-      console.assert(this.incomingBufferLen < WIRE_PROTOCOL_HEADER_SIZE);
-      return true;
-    }
-    return false;
-  }
-
-  private canCompleteSizeHeader(newData: Uint8Array) {
-    return newData.length + this.incomingBufferLen > WIRE_PROTOCOL_HEADER_SIZE;
-  }
-
-  private canParseFullMessage(newData: Uint8Array) {
-    return this.frameToParseLen &&
-        this.incomingBufferLen + newData.length >= this.frameToParseLen;
-  }
-
-  private appendToIncomingBuffer(array: Uint8Array) {
-    this.incomingBuffer.set(array, this.incomingBufferLen);
-    this.incomingBufferLen += array.length;
-  }
-
-  handleReceivedData(newData: Uint8Array) {
-    if (this.incompleteSizeHeader() && this.canCompleteSizeHeader(newData)) {
-      const newDataBytesToRead =
-          WIRE_PROTOCOL_HEADER_SIZE - this.incomingBufferLen;
-      // Add to the incoming buffer the remaining bytes to arrive at
-      // WIRE_PROTOCOL_HEADER_SIZE
-      this.appendToIncomingBuffer(newData.subarray(0, newDataBytesToRead));
-      newData = newData.subarray(newDataBytesToRead);
-
-      this.frameToParseLen = this.parseMessageSize(this.incomingBuffer);
-      this.incomingBufferLen = 0;
-    }
-
-    // Parse all complete messages in incomingBuffer and newData.
-    while (this.canParseFullMessage(newData)) {
-      // All the message is in the newData buffer.
-      if (this.incomingBufferLen === 0) {
-        this.parseMessage(newData.subarray(0, this.frameToParseLen));
-        newData = newData.subarray(this.frameToParseLen);
-      } else {  // We need to complete the local buffer.
-        // Read the remaining part of this message.
-        const bytesToCompleteMessage =
-            this.frameToParseLen - this.incomingBufferLen;
-        this.appendToIncomingBuffer(
-            newData.subarray(0, bytesToCompleteMessage));
-        this.parseMessage(
-            this.incomingBuffer.subarray(0, this.frameToParseLen));
-        this.incomingBufferLen = 0;
-        // Remove the data just parsed.
-        newData = newData.subarray(bytesToCompleteMessage);
-      }
-      this.frameToParseLen = 0;
-      if (!this.canCompleteSizeHeader(newData)) break;
-
-      this.frameToParseLen =
-          this.parseMessageSize(newData.subarray(0, WIRE_PROTOCOL_HEADER_SIZE));
-      newData = newData.subarray(WIRE_PROTOCOL_HEADER_SIZE);
-    }
-    // Buffer the remaining data (part of the next header + message).
-    this.appendToIncomingBuffer(newData);
-  }
-
-  decodeResponse(
-      requestId: number, responseProto: Uint8Array, hasMore = false) {
-    const method = this.requestMethods.get(requestId);
-    if (!method) {
-      console.error(`Unknown request id: ${requestId}`);
-      this.sendErrorMessage(`Wire protocol error.`);
-      return;
-    }
-    const decoder = decoders.get(method);
-    if (decoder === undefined) {
-      console.error(`Unable to decode method: ${method}`);
-      return;
-    }
-    const decodedResponse = decoder(responseProto);
-    const response = {type: `${method}Response`, ...decodedResponse};
-
-    // TODO(nicomazz): Fix this.
-    // We assemble all the trace and then send it back to the main controller.
-    // This is a temporary solution, that will be changed in a following CL,
-    // because now both the chrome consumer port and the other adb consumer port
-    // send back the entire trace, while the correct behavior should be to send
-    // back the slices, that are assembled by the main record controller.
-    if (isReadBuffersResponse(response)) {
-      if (response.slices) this.handleSlices(response.slices);
-      if (!hasMore) this.sendReadBufferResponse();
-      return;
-    }
-    this.sendMessage(response);
-  }
-
-  handleSlices(slices: ISlice[]) {
-    for (const slice of slices) {
-      this.partialPacket.push(slice);
-      if (slice.lastSliceForPacket) {
-        const tracePacket = this.generateTracePacket(this.partialPacket);
-        this.traceProtoWriter.uint32(TRACE_PACKET_PROTO_TAG);
-        this.traceProtoWriter.bytes(tracePacket);
-        this.partialPacket = [];
-      }
-    }
-  }
-
-  generateTracePacket(slices: ISlice[]): Uint8Array {
-    let bufferSize = 0;
-    for (const slice of slices) bufferSize += slice.data!.length;
-    const fullBuffer = new Uint8Array(bufferSize);
-    let written = 0;
-    for (const slice of slices) {
-      const data = slice.data!;
-      fullBuffer.set(data, written);
-      written += data.length;
-    }
-    return fullBuffer;
-  }
-
-  sendReadBufferResponse() {
-    this.sendMessage(this.generateChunkReadResponse(
-        this.traceProtoWriter.finish(), /* last */ true));
-  }
-
-  bind() {
-    console.assert(this.socket !== undefined);
-    const requestId = this.requestId++;
-    const frame = new perfetto.ipc.Frame({
-      requestId,
-      msgBindService:
-          new perfetto.ipc.Frame.BindService({serviceName: 'ConsumerPort'})
-    });
-    return new Promise((resolve, _) => {
-      this.resolveBindingPromise = resolve;
-      this.sendFrame(frame);
-    });
-  }
-
-  findMethodId(method: string): number|undefined {
-    const methodObject = this.availableMethods.find((m) => m.name === method);
-    if (methodObject && methodObject.id) return methodObject.id;
-    return undefined;
-  }
-
-  static async hasSocketAccess(device: USBDevice, adb: Adb): Promise<boolean> {
-    await adb.connect(device);
-    try {
-      const socket = await adb.socket(TRACED_SOCKET);
-      socket.close();
-      return true;
-    } catch (e) {
-      return false;
-    }
-  }
-
-  handleIncomingFrame(frame: perfetto.ipc.Frame) {
-    const requestId = frame.requestId as number;
-    switch (frame.msg) {
-      case 'msgBindServiceReply': {
-        const msgBindServiceReply = frame.msgBindServiceReply;
-        if (msgBindServiceReply && msgBindServiceReply.methods &&
-            msgBindServiceReply.serviceId) {
-          console.assert(msgBindServiceReply.success);
-          this.availableMethods = msgBindServiceReply.methods;
-          this.serviceId = msgBindServiceReply.serviceId;
-          this.resolveBindingPromise();
-          this.resolveBindingPromise = () => {};
-        }
-        return;
-      }
-      case 'msgInvokeMethodReply': {
-        const msgInvokeMethodReply = frame.msgInvokeMethodReply;
-        if (msgInvokeMethodReply && msgInvokeMethodReply.replyProto) {
-          if (!msgInvokeMethodReply.success) {
-            console.error(
-                'Unsuccessful method invocation: ', msgInvokeMethodReply);
-            return;
-          }
-          this.decodeResponse(
-              requestId,
-              msgInvokeMethodReply.replyProto,
-              msgInvokeMethodReply.hasMore === true);
-        }
-        return;
-      }
-      default:
-        console.error(`not recognized frame message: ${frame.msg}`);
-    }
-  }
-}
-
-const decoders =
-    new Map<string, Function>()
-        .set('EnableTracing', perfetto.protos.EnableTracingResponse.decode)
-        .set('FreeBuffers', perfetto.protos.FreeBuffersResponse.decode)
-        .set('ReadBuffers', perfetto.protos.ReadBuffersResponse.decode)
-        .set('DisableTracing', perfetto.protos.DisableTracingResponse.decode)
-        .set('GetTraceStats', perfetto.protos.GetTraceStatsResponse.decode);
\ No newline at end of file
diff --git a/ui/src/controller/app_controller.ts b/ui/src/controller/app_controller.ts
index 8e6e3c9..cf8e6f0 100644
--- a/ui/src/controller/app_controller.ts
+++ b/ui/src/controller/app_controller.ts
@@ -23,14 +23,8 @@
 // the other controllers (e.g., track and query controllers) according to the
 // global state.
 export class AppController extends Controller<'main'> {
-  // extensionPort is needed for the RecordController to communicate with the
-  // extension through the frontend. This is because the controller is running
-  // on a worker, and isn't able to directly send messages to the extension.
-  private extensionPort: MessagePort;
-
-  constructor(extensionPort: MessagePort) {
+  constructor() {
     super('main');
-    this.extensionPort = extensionPort;
   }
 
   // This is the root method that is called every time the controller tree is
@@ -41,10 +35,7 @@
   run() {
     const childControllers: ControllerInitializerAny[] = [
       Child('permalink', PermalinkController, {}),
-      Child(
-          'record',
-          RecordController,
-          {app: globals, extensionPort: this.extensionPort}),
+      Child('record', RecordController, {app: globals}),
     ];
     for (const engineCfg of Object.values(globals.state.engines)) {
       childControllers.push(Child(engineCfg.id, TraceController, engineCfg.id));
diff --git a/ui/src/controller/chrome_proxy_record_controller.ts b/ui/src/controller/chrome_proxy_record_controller.ts
deleted file mode 100644
index 54a4f29..0000000
--- a/ui/src/controller/chrome_proxy_record_controller.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {stringToUint8Array, uint8ArrayToString} from '../base/string_utils';
-
-import {
-  ConsumerPortResponse,
-  isConsumerPortResponse,
-  isReadBuffersResponse,
-  Typed
-} from './consumer_port_types';
-import {Consumer, RpcConsumerPort} from './record_controller_interfaces';
-
-export interface ChromeExtensionError extends Typed {
-  error: string;
-}
-
-export interface ChromeExtensionStatus extends Typed {
-  status: string;
-}
-
-export type ChromeExtensionMessage =
-    ChromeExtensionError|ChromeExtensionStatus|ConsumerPortResponse;
-
-function isError(obj: Typed): obj is ChromeExtensionError {
-  return obj.type === 'ChromeExtensionError';
-}
-
-function isStatus(obj: Typed): obj is ChromeExtensionStatus {
-  return obj.type === 'ChromeExtensionStatus';
-}
-
-// This class acts as a proxy from the record controller (running in a worker),
-// to the frontend. This is needed because we can't directly talk with the
-// extension from a web-worker, so we use a MessagePort to communicate with the
-// frontend, that will consecutively forward it to the extension.
-export class ChromeExtensionConsumerPort extends RpcConsumerPort {
-  private extensionPort: MessagePort;
-
-  constructor(extensionPort: MessagePort, consumer: Consumer) {
-    super(consumer);
-    this.extensionPort = extensionPort;
-    this.extensionPort.onmessage = this.onExtensionMessage.bind(this);
-  }
-
-  onExtensionMessage(message: {data: ChromeExtensionMessage}) {
-    if (isError(message.data)) {
-      this.sendErrorMessage(message.data.error);
-      return;
-    }
-    if (isStatus(message.data)) {
-      this.sendStatus(message.data.status);
-      return;
-    }
-
-    console.assert(isConsumerPortResponse(message.data));
-    // In this else branch message.data will be a ConsumerPortResponse.
-    if (isReadBuffersResponse(message.data) && message.data.slices) {
-      // This is needed because we can't send an ArrayBuffer through a
-      // chrome.runtime.port. A string is sent instead, and here converted to
-      // an ArrayBuffer.
-      const slice = message.data.slices[0].data as unknown as string;
-      message.data.slices[0].data = stringToUint8Array(slice);
-    }
-    this.sendMessage(message.data);
-  }
-
-  handleCommand(method: string, requestData: Uint8Array): void {
-    const buffer = uint8ArrayToString(requestData);
-    // We need to encode the buffer as a string because the message port doesn't
-    // fully support sending ArrayBuffers (they are converted to objects with
-    // indexes as keys).
-    this.extensionPort.postMessage({method, requestData: buffer});
-  }
-}
diff --git a/ui/src/controller/consumer_port_types.ts b/ui/src/controller/consumer_port_types.ts
deleted file mode 100644
index 8a249d4..0000000
--- a/ui/src/controller/consumer_port_types.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {perfetto} from '../gen/protos';
-
-export interface Typed {
-  type: string;
-}
-
-export interface ReadBuffersResponse extends
-    Typed, perfetto.protos.IReadBuffersResponse {}
-export interface EnableTracingResponse extends
-    Typed, perfetto.protos.IEnableTracingResponse {}
-export interface GetTraceStatsResponse extends
-    Typed, perfetto.protos.IGetTraceStatsResponse {}
-
-export type ConsumerPortResponse =
-    EnableTracingResponse|ReadBuffersResponse|GetTraceStatsResponse;
-
-export function isConsumerPortResponse(obj: Typed):
-    obj is ConsumerPortResponse {
-  return isReadBuffersResponse(obj) || isEnableTracingResponse(obj) ||
-      isGetTraceStatsResponse(obj);
-}
-
-export function isReadBuffersResponse(obj: Typed): obj is ReadBuffersResponse {
-  return obj.type === 'ReadBuffersResponse';
-}
-
-export function isEnableTracingResponse(obj: Typed):
-    obj is EnableTracingResponse {
-  return obj.type === 'EnableTracingResponse';
-}
-
-export function isGetTraceStatsResponse(obj: Typed):
-    obj is GetTraceStatsResponse {
-  return obj.type === 'GetTraceStatsResponse';
-}
\ No newline at end of file
diff --git a/ui/src/controller/globals.ts b/ui/src/controller/globals.ts
index e268932..174934a 100644
--- a/ui/src/controller/globals.ts
+++ b/ui/src/controller/globals.ts
@@ -17,18 +17,24 @@
 import {assertExists} from '../base/logging';
 import {Remote} from '../base/remote';
 import {DeferredAction, StateActions} from '../common/actions';
+import {Engine} from '../common/engine';
 import {createEmptyState, State} from '../common/state';
+import {
+  createWasmEngine,
+  destroyWasmEngine,
+  WasmEngineProxy
+} from '../common/wasm_engine_proxy';
+
 import {ControllerAny} from './controller';
 
-type PublishKinds =
-    'OverviewData'|'TrackData'|'Threads'|'QueryResult'|'LegacyTrace'|
-    'SliceDetails'|'CounterDetails'|'HeapDumpDetails'|'FileDownload'|'Loading'|
-    'Search'|'BufferUsage'|'RecordingLog'|'SearchResult';
 
 export interface App {
   state: State;
   dispatch(action: DeferredAction): void;
-  publish(what: PublishKinds, data: {}, transferList?: Array<{}>): void;
+  publish(
+      what: 'OverviewData'|'TrackData'|'Threads'|'QueryResult'|'LegacyTrace'|
+            'SliceDetails',
+      data: {}, transferList?: Array<{}>): void;
 }
 
 /**
@@ -85,8 +91,21 @@
     assertExists(this._frontend).send<void>('patchState', [patches]);
   }
 
+  createEngine(): Engine {
+    const id = new Date().toUTCString();
+    const portAndId = {id, worker: createWasmEngine(id)};
+    return new WasmEngineProxy(portAndId);
+  }
+
+  destroyEngine(id: string): void {
+    destroyWasmEngine(id);
+  }
+
   // TODO: this needs to be cleaned up.
-  publish(what: PublishKinds, data: {}, transferList?: Transferable[]) {
+  publish(
+      what: 'OverviewData'|'TrackData'|'Threads'|'QueryResult'|'LegacyTrace'|
+            'SliceDetails',
+      data: {}, transferList?: Transferable[]) {
     assertExists(this._frontend)
         .send<void>(`publish${what}`, [data], transferList);
   }
diff --git a/ui/src/controller/index.ts b/ui/src/controller/index.ts
index 24e4800..0b4afec 100644
--- a/ui/src/controller/index.ts
+++ b/ui/src/controller/index.ts
@@ -14,37 +14,29 @@
 
 import '../tracks/all_controller';
 
-import {reportError, setErrorHandler} from '../base/logging';
 import {Remote} from '../base/remote';
 import {warmupWasmEngine} from '../common/wasm_engine_proxy';
 
 import {AppController} from './app_controller';
 import {globals} from './globals';
 
-function main() {
-  self.addEventListener('error', e => reportError(e));
-  self.addEventListener('unhandledrejection', e => reportError(e));
+function main(port: MessagePort) {
   warmupWasmEngine();
-  let initialized = false;
-  self.onmessage = ({data}) => {
-    if (initialized) {
-      console.error('Already initialized');
+  let receivedFrontendPort = false;
+  port.onmessage = ({data}) => {
+    if (receivedFrontendPort) {
+      globals.dispatch(data);
       return;
     }
-    initialized = true;
-    const frontendPort = data.frontendPort as MessagePort;
-    const controllerPort = data.controllerPort as MessagePort;
-    const extensionPort = data.extensionPort as MessagePort;
-    const errorReportingPort = data.errorReportingPort as MessagePort;
-    setErrorHandler((err: string) => errorReportingPort.postMessage(err));
-    const frontend = new Remote(frontendPort);
-    controllerPort.onmessage = ({data}) => globals.dispatch(data);
 
-    globals.initialize(new AppController(extensionPort), frontend);
+    const frontendPort = data as MessagePort;
+    const frontend = new Remote(frontendPort);
+    globals.initialize(new AppController(), frontend);
+    receivedFrontendPort = true;
   };
 }
 
-main();
+main(self as {} as MessagePort);
 
 // For devtools-based debugging.
 (self as {} as {globals: {}}).globals = globals;
diff --git a/ui/src/controller/loading_manager.ts b/ui/src/controller/loading_manager.ts
deleted file mode 100644
index 3814933..0000000
--- a/ui/src/controller/loading_manager.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {LoadingTracker} from '../common/engine';
-import {globals} from './globals';
-
-// Used to keep track of whether the engine is currently querying.
-export class LoadingManager implements LoadingTracker {
-  private static _instance: LoadingManager;
-  private numQueuedQueries = 0;
-  private numLastUpdate = 0;
-
-  static get getInstance(): LoadingManager {
-    return this._instance || (this._instance = new this());
-  }
-
-  beginLoading() {
-    this.update(1);
-  }
-
-  endLoading() {
-    this.update(-1);
-  }
-
-  private update(change: number) {
-    this.numQueuedQueries += change;
-    if (this.numQueuedQueries === 0 ||
-        Math.abs(this.numLastUpdate - this.numQueuedQueries) > 2) {
-      this.numLastUpdate = this.numQueuedQueries;
-      globals.publish('Loading', this.numQueuedQueries);
-    }
-  }
-}
diff --git a/ui/src/controller/logs_controller.ts b/ui/src/controller/logs_controller.ts
index abe5a9e..6e7735e 100644
--- a/ui/src/controller/logs_controller.ts
+++ b/ui/src/controller/logs_controller.ts
@@ -20,15 +20,15 @@
   LogEntriesKey,
   LogExistsKey
 } from '../common/logs';
-import {fromNs, TimeSpan, toNsCeil, toNsFloor} from '../common/time';
+import {fromNs, TimeSpan} from '../common/time';
 
 import {Controller} from './controller';
 import {App} from './globals';
 
 async function updateLogBounds(
     engine: Engine, span: TimeSpan): Promise<LogBounds> {
-  const vizStartNs = toNsFloor(span.start);
-  const vizEndNs = toNsCeil(span.end);
+  const vizStartNs = Math.floor(span.start * 1e9);
+  const vizEndNs = Math.ceil(span.end * 1e9);
 
   const countResult = await engine.queryOneRow(`
      select min(ts), max(ts), count(ts)
@@ -63,8 +63,8 @@
 async function updateLogEntries(
     engine: Engine, span: TimeSpan, pagination: Pagination):
     Promise<LogEntries> {
-  const vizStartNs = toNsFloor(span.start);
-  const vizEndNs = toNsCeil(span.end);
+  const vizStartNs = Math.floor(span.start * 1e9);
+  const vizEndNs = Math.ceil(span.end * 1e9);
   const vizSqlBounds = `ts >= ${vizStartNs} and ts <= ${vizEndNs}`;
 
   const rowsResult =
@@ -147,7 +147,6 @@
   private engine: Engine;
   private span: TimeSpan;
   private pagination: Pagination;
-  private hasLogs = false;
 
   constructor(args: LogsControllerArgs) {
     super('main');
@@ -155,28 +154,24 @@
     this.engine = args.engine;
     this.span = new TimeSpan(0, 10);
     this.pagination = new Pagination(0, 0);
-    this.hasAnyLogs().then(exists => {
-      this.hasLogs = exists;
-      this.app.publish('TrackData', {
-        id: LogExistsKey,
-        data: {
-          exists,
-        },
-      });
-    });
+    this.publishHasAnyLogs();
   }
 
-  async hasAnyLogs() {
+  async publishHasAnyLogs() {
     const result = await this.engine.queryOneRow(`
       select count(*) from android_logs
     `);
-    return result[0] > 0;
+    const exists = result[0] > 0;
+    this.app.publish('TrackData', {
+      id: LogExistsKey,
+      data: {
+        exists,
+      },
+    });
   }
 
   run() {
-    if (!this.hasLogs) return;
-
-    const traceTime = this.app.state.frontendLocalState.visibleState;
+    const traceTime = this.app.state.frontendLocalState.visibleTraceTime;
     const newSpan = new TimeSpan(traceTime.startSec, traceTime.endSec);
     const oldSpan = this.span;
 
diff --git a/ui/src/controller/permalink_controller.ts b/ui/src/controller/permalink_controller.ts
index d991a89..ddf4276 100644
--- a/ui/src/controller/permalink_controller.ts
+++ b/ui/src/controller/permalink_controller.ts
@@ -12,12 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {produce} from 'immer';
+import {Draft, produce} from 'immer';
 import * as uuidv4 from 'uuid/v4';
 
-import {assertExists, assertTrue} from '../base/logging';
+import {assertExists} from '../base/logging';
 import {Actions} from '../common/actions';
-import {State} from '../common/state';
+import {EngineConfig, State} from '../common/state';
 
 import {Controller} from './controller';
 import {globals} from './globals';
@@ -54,30 +54,26 @@
   }
 
   private static async createPermalink() {
-    const engines = Object.values(globals.state.engines);
-    assertTrue(engines.length === 1);
-    const engine = engines[0];
-    let dataToUpload: File|ArrayBuffer|undefined = undefined;
-    let traceName = `trace ${engine.id}`;
-    if (engine.source.type === 'FILE') {
-      dataToUpload = engine.source.file;
-      traceName = dataToUpload.name;
-    } else if (engine.source.type === 'ARRAY_BUFFER') {
-      dataToUpload = engine.source.buffer;
-    } else if (engine.source.type !== 'URL') {
-      throw new Error(`Cannot share trace ${JSON.stringify(engine.source)}`);
+    const state = globals.state;
+
+    // Upload each loaded trace.
+    const fileToUrl = new Map<File, string>();
+    for (const engine of Object.values<EngineConfig>(state.engines)) {
+      if (!(engine.source instanceof File)) continue;
+      PermalinkController.updateStatus(`Uploading ${engine.source.name}`);
+      const url = await this.saveTrace(engine.source);
+      fileToUrl.set(engine.source, url);
     }
 
-    let uploadState = globals.state;
-    if (dataToUpload !== undefined) {
-      PermalinkController.updateStatus(`Uploading ${traceName}`);
-      const url = await this.saveTrace(dataToUpload);
-      // Convert state to use URLs and remove permalink.
-      uploadState = produce(globals.state, draft => {
-        draft.engines[engine.id].source = {type: 'URL', url};
-        draft.permalink = {};
-      });
-    }
+    // Convert state to use URLs and remove permalink.
+    const uploadState = produce(state, draft => {
+      for (const engine of Object.values<Draft<EngineConfig>>(
+               draft.engines)) {
+        if (!(engine.source instanceof File)) continue;
+        engine.source = fileToUrl.get(engine.source)!;
+      }
+      draft.permalink = {};
+    });
 
     // Upload state.
     PermalinkController.updateStatus(`Creating permalink...`);
@@ -104,7 +100,7 @@
     return hash;
   }
 
-  private static async saveTrace(trace: File|ArrayBuffer): Promise<string> {
+  private static async saveTrace(trace: File): Promise<string> {
     // TODO(hjd): This should probably also be a hash but that requires
     // trace processor support.
     const name = uuidv4();
diff --git a/ui/src/controller/record_controller.ts b/ui/src/controller/record_controller.ts
index dbbed80..9d1bf84 100644
--- a/ui/src/controller/record_controller.ts
+++ b/ui/src/controller/record_controller.ts
@@ -12,68 +12,31 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {Message, Method, rpc, RPCImplCallback} from 'protobufjs';
-
-import {
-  uint8ArrayToBase64,
-} from '../base/string_utils';
-import {Actions} from '../common/actions';
 import {
   AndroidLogConfig,
   AndroidLogId,
   AndroidPowerConfig,
   BufferConfig,
-  ChromeConfig,
-  ConsumerPort,
-  ContinuousDumpConfig,
   DataSourceConfig,
   FtraceConfig,
-  HeapprofdConfig,
   ProcessStatsConfig,
   SysStatsConfig,
-  TraceConfig,
+  TraceConfig
 } from '../common/protos';
 import {MeminfoCounters, VmstatCounters} from '../common/protos';
-import {
-  AdbRecordingTarget,
-  isAndroidTarget,
-  isChromeTarget,
-  MAX_TIME,
-  RecordConfig,
-  TargetOs
-} from '../common/state';
+import {RecordConfig} from '../common/state';
 
-import {AdbOverWebUsb} from './adb';
-import {AdbConsumerPort} from './adb_shell_controller';
-import {AdbSocketConsumerPort} from './adb_socket_controller';
-import {ChromeExtensionConsumerPort} from './chrome_proxy_record_controller';
-import {
-  ConsumerPortResponse,
-  GetTraceStatsResponse,
-  isEnableTracingResponse,
-  isGetTraceStatsResponse,
-  isReadBuffersResponse,
-} from './consumer_port_types';
 import {Controller} from './controller';
-import {App, globals} from './globals';
-import {Consumer, RpcConsumerPort} from './record_controller_interfaces';
+import {App} from './globals';
 
-type RPCImplMethod = (Method|rpc.ServiceMethod<Message<{}>, Message<{}>>);
-
-export function genConfigProto(uiCfg: RecordConfig): Uint8Array {
-  return TraceConfig.encode(genConfig(uiCfg)).finish();
+export function uint8ArrayToBase64(buffer: Uint8Array): string {
+  return btoa(String.fromCharCode.apply(null, Array.from(buffer)));
 }
 
-export function genConfig(uiCfg: RecordConfig): TraceConfig {
+export function genConfigProto(uiCfg: RecordConfig): Uint8Array {
   const protoCfg = new TraceConfig();
   protoCfg.durationMs = uiCfg.durationMs;
 
-  let time = protoCfg.durationMs / 1000;
-
-  if (time > MAX_TIME) {
-    time = MAX_TIME;
-  }
-
   // Auxiliary buffer for slow-rate events.
   // Set to 1/8th of the main buffer size, with reasonable limits.
   let slowBufSizeKb = uiCfg.bufferSizeMb * (1024 / 8);
@@ -105,9 +68,6 @@
   const ftraceEvents = new Set<string>(uiCfg.ftrace ? uiCfg.ftraceEvents : []);
   const atraceCats = new Set<string>(uiCfg.atrace ? uiCfg.atraceCats : []);
   const atraceApps = new Set<string>();
-  const chromeCategories = new Set<string>();
-  uiCfg.chromeCategoriesSelected.forEach(it => chromeCategories.add(it));
-
   let procThreadAssociationPolling = false;
   let procThreadAssociationFtrace = false;
   let trackInitialOomScore = false;
@@ -120,7 +80,6 @@
     if (uiCfg.cpuLatency) {
       ftraceEvents.add('sched/sched_wakeup');
       ftraceEvents.add('sched/sched_wakeup_new');
-      ftraceEvents.add('sched/sched_waking');
       ftraceEvents.add('power/suspend_resume');
     }
   }
@@ -131,15 +90,6 @@
     ftraceEvents.add('power/suspend_resume');
   }
 
-  if (uiCfg.gpuFreq) {
-    ftraceEvents.add('power/gpu_frequency');
-  }
-
-  if (uiCfg.cpuSyscall) {
-    ftraceEvents.add('raw_syscalls/sys_enter');
-    ftraceEvents.add('raw_syscalls/sys_exit');
-  }
-
   if (procThreadAssociationFtrace) {
     ftraceEvents.add('sched/sched_process_exit');
     ftraceEvents.add('sched/sched_process_free');
@@ -224,34 +174,6 @@
     trackInitialOomScore = true;
   }
 
-  let heapprofd: HeapprofdConfig|undefined = undefined;
-  if (uiCfg.heapProfiling) {
-    // TODO(tneda): Check or inform user if buffer size are too small.
-    if (heapprofd === undefined) heapprofd = new HeapprofdConfig();
-    heapprofd.samplingIntervalBytes = uiCfg.hpSamplingIntervalBytes;
-    if (uiCfg.hpSharedMemoryBuffer >= 8192 &&
-        uiCfg.hpSharedMemoryBuffer % 4096 === 0) {
-      heapprofd.shmemSizeBytes = uiCfg.hpSharedMemoryBuffer;
-    }
-    if (uiCfg.hpProcesses !== '') {
-      uiCfg.hpProcesses.split('\n').forEach(value => {
-        if (isNaN(+value)) {
-          heapprofd!.processCmdline.push(value);
-        } else {
-          heapprofd!.pid.push(+value);
-        }
-      });
-    }
-    if (uiCfg.hpContinuousDumpsInterval > 0) {
-      heapprofd.continuousDumpConfig = new ContinuousDumpConfig();
-      heapprofd.continuousDumpConfig.dumpIntervalMs =
-          uiCfg.hpContinuousDumpsInterval;
-      heapprofd.continuousDumpConfig.dumpPhaseMs =
-          uiCfg.hpContinuousDumpsPhase > 0 ? uiCfg.hpContinuousDumpsPhase :
-                                             undefined;
-    }
-  }
-
   if (uiCfg.procStats || procThreadAssociationPolling || trackInitialOomScore) {
     const ds = new TraceConfig.DataSource();
     ds.config = new DataSourceConfig();
@@ -280,91 +202,6 @@
     protoCfg.dataSources.push(ds);
   }
 
-  if (uiCfg.chromeLogs) {
-    chromeCategories.add('log');
-  }
-
-  if (uiCfg.taskScheduling) {
-    chromeCategories.add('toplevel');
-    chromeCategories.add('sequence_manager');
-    chromeCategories.add('disabled-by-default-toplevel.flow');
-  }
-
-  if (uiCfg.ipcFlows) {
-    chromeCategories.add('toplevel');
-    chromeCategories.add('disabled-by-default-ipc.flow');
-    chromeCategories.add('mojom');
-  }
-
-  if (uiCfg.jsExecution) {
-    chromeCategories.add('toplevel');
-    chromeCategories.add('v8');
-  }
-
-  if (uiCfg.webContentRendering) {
-    chromeCategories.add('toplevel');
-    chromeCategories.add('blink');
-    chromeCategories.add('cc');
-    chromeCategories.add('gpu');
-  }
-
-  if (uiCfg.uiRendering) {
-    chromeCategories.add('toplevel');
-    chromeCategories.add('cc');
-    chromeCategories.add('gpu');
-    chromeCategories.add('viz');
-    chromeCategories.add('ui');
-    chromeCategories.add('views');
-  }
-
-  if (uiCfg.inputEvents) {
-    chromeCategories.add('toplevel');
-    chromeCategories.add('benchmark');
-    chromeCategories.add('evdev');
-    chromeCategories.add('input');
-    chromeCategories.add('disabled-by-default-toplevel.flow');
-  }
-
-  if (uiCfg.navigationAndLoading) {
-    chromeCategories.add('loading');
-    chromeCategories.add('net');
-    chromeCategories.add('netlog');
-    chromeCategories.add('navigation');
-    chromeCategories.add('browser');
-  }
-
-  if (chromeCategories.size !== 0) {
-    let chromeRecordMode = '';
-    if (uiCfg.mode === 'STOP_WHEN_FULL') {
-      chromeRecordMode = 'record-until-full';
-    } else {
-      chromeRecordMode = 'record-continuously';
-    }
-    const traceConfigJson = JSON.stringify({
-      record_mode: chromeRecordMode,
-      included_categories: [...chromeCategories.values()],
-    });
-
-    const traceDs = new TraceConfig.DataSource();
-    traceDs.config = new DataSourceConfig();
-    traceDs.config.name = 'org.chromium.trace_event';
-    traceDs.config.chromeConfig = new ChromeConfig();
-    traceDs.config.chromeConfig.traceConfig = traceConfigJson;
-    protoCfg.dataSources.push(traceDs);
-
-
-    const metadataDs = new TraceConfig.DataSource();
-    metadataDs.config = new DataSourceConfig();
-    metadataDs.config.name = 'org.chromium.trace_metadata';
-    metadataDs.config.chromeConfig = new ChromeConfig();
-    metadataDs.config.chromeConfig.traceConfig = traceConfigJson;
-    protoCfg.dataSources.push(metadataDs);
-  }
-
-  if (uiCfg.screenRecord) {
-    atraceCats.add('gfx');
-  }
-
   // Keep these last. The stages above can enrich them.
 
   if (sysStatsCfg !== undefined) {
@@ -375,15 +212,6 @@
     protoCfg.dataSources.push(ds);
   }
 
-  if (heapprofd !== undefined) {
-    const ds = new TraceConfig.DataSource();
-    ds.config = new DataSourceConfig();
-    ds.config.targetBuffer = 0;
-    ds.config.name = 'android.heapprofd';
-    ds.config.heapprofdConfig = heapprofd;
-    protoCfg.dataSources.push(ds);
-  }
-
   if (uiCfg.ftrace || uiCfg.atraceApps.length > 0 || ftraceEvents.size > 0 ||
       atraceCats.size > 0 || atraceApps.size > 0) {
     const ds = new TraceConfig.DataSource();
@@ -413,7 +241,8 @@
     protoCfg.dataSources.push(ds);
   }
 
-  return protoCfg;
+  const buffer = TraceConfig.encode(protoCfg).finish();
+  return buffer;
 }
 
 export function toPbtxt(configBuffer: Uint8Array): string {
@@ -424,26 +253,12 @@
   }
   // With the ahead of time compiled protos we can't seem to tell which
   // fields are enums.
-  function isEnum(value: string): boolean {
+  function looksLikeEnum(value: string): boolean {
     return value.startsWith('MEMINFO_') || value.startsWith('VMSTAT_') ||
         value.startsWith('STAT_') || value.startsWith('LID_') ||
         value.startsWith('BATTERY_COUNTER_') || value === 'DISCARD' ||
         value === 'RING_BUFFER';
   }
-  // Since javascript doesn't have 64 bit numbers when converting protos to
-  // json the proto library encodes them as strings. This is lossy since
-  // we can't tell which strings that look like numbers are actually strings
-  // and which are actually numbers. Ideally we would reflect on the proto
-  // definition somehow but for now we just hard code keys which have this
-  // problem in the config.
-  function is64BitNumber(key: string): boolean {
-    return [
-      'maxFileSizeBytes',
-      'samplingIntervalBytes',
-      'shmemSizeBytes',
-      'pid'
-    ].includes(key);
-  }
   function* message(msg: {}, indent: number): IterableIterator<string> {
     for (const [key, value] of Object.entries(msg)) {
       const isRepeated = Array.isArray(value);
@@ -451,11 +266,7 @@
       for (const entry of (isRepeated ? value as Array<{}> : [value])) {
         yield ' '.repeat(indent) + `${snakeCase(key)}${isNested ? '' : ':'} `;
         if (typeof entry === 'string') {
-          if (isEnum(entry) || is64BitNumber(key)) {
-            yield entry;
-          } else {
-            yield `"${entry.replace(new RegExp('"', 'g'), '\\"')}"`;
-          }
+          yield looksLikeEnum(entry) ? entry : `"${entry}"`;
         } else if (typeof entry === 'number') {
           yield entry.toString();
         } else if (typeof entry === 'boolean') {
@@ -472,36 +283,18 @@
   return [...message(json, 0)].join('');
 }
 
-export class RecordController extends Controller<'main'> implements Consumer {
+export class RecordController extends Controller<'main'> {
   private app: App;
   private config: RecordConfig|null = null;
-  private extensionPort: MessagePort;
-  private recordingInProgress = false;
-  private consumerPort: ConsumerPort;
-  private traceBuffer: Uint8Array[] = [];
-  private bufferUpdateInterval: ReturnType<typeof setTimeout>|undefined;
-  private adb = new AdbOverWebUsb();
 
-  // We have a different controller for each targetOS. The correct one will be
-  // created when needed, and stored here. When the key is a string, it is the
-  // serial of the target (used for android devices). When the key is a single
-  // char, it is the 'targetOS'
-  private controllerPromises = new Map<string, Promise<RpcConsumerPort>>();
-
-  constructor(args: {app: App, extensionPort: MessagePort}) {
+  constructor(args: {app: App}) {
     super('main');
     this.app = args.app;
-    this.consumerPort = ConsumerPort.create(this.rpcImpl.bind(this));
-    this.extensionPort = args.extensionPort;
   }
 
   run() {
-    if (this.app.state.recordConfig === this.config &&
-        this.app.state.recordingInProgress === this.recordingInProgress) {
-      return;
-    }
+    if (this.app.state.recordConfig === this.config) return;
     this.config = this.app.state.recordConfig;
-
     const configProto = genConfigProto(this.config);
     const configProtoText = toPbtxt(configProto);
     const commandline = `
@@ -510,185 +303,13 @@
       adb shell "perfetto -c - -o /data/misc/perfetto-traces/trace" &&
       adb pull /data/misc/perfetto-traces/trace /tmp/trace
     `;
-    const traceConfig = genConfig(this.config);
     // TODO(hjd): This should not be TrackData after we unify the stores.
     this.app.publish('TrackData', {
       id: 'config',
-      data: {commandline, pbtxt: configProtoText, traceConfig}
-    });
-
-    // If the recordingInProgress boolean state is different, it means that we
-    // have to start or stop recording a trace.
-    if (this.app.state.recordingInProgress === this.recordingInProgress) return;
-    this.recordingInProgress = this.app.state.recordingInProgress;
-
-    if (this.recordingInProgress) {
-      this.startRecordTrace(traceConfig);
-    } else {
-      this.stopRecordTrace();
-    }
-  }
-
-  startRecordTrace(traceConfig: TraceConfig) {
-    this.scheduleBufferUpdateRequests();
-    this.traceBuffer = [];
-    this.consumerPort.enableTracing({traceConfig});
-  }
-
-  stopRecordTrace() {
-    if (this.bufferUpdateInterval) clearInterval(this.bufferUpdateInterval);
-    this.consumerPort.disableTracing({});
-  }
-
-  scheduleBufferUpdateRequests() {
-    if (this.bufferUpdateInterval) clearInterval(this.bufferUpdateInterval);
-    this.bufferUpdateInterval = setInterval(() => {
-      this.consumerPort.getTraceStats({});
-    }, 200);
-  }
-
-  readBuffers() {
-    this.consumerPort.readBuffers({});
-  }
-
-  onConsumerPortResponse(data: ConsumerPortResponse) {
-    if (data === undefined) return;
-    if (isReadBuffersResponse(data)) {
-      if (!data.slices || data.slices.length === 0) return;
-      // TODO(nicomazz): handle this as intended by consumer_port.proto.
-      console.assert(data.slices.length === 1);
-      if (data.slices[0].data) this.traceBuffer.push(data.slices[0].data);
-      if (data.slices[0].lastSliceForPacket) this.onTraceComplete();
-    } else if (isEnableTracingResponse(data)) {
-      this.readBuffers();
-    } else if (isGetTraceStatsResponse(data)) {
-      const percentage = this.getBufferUsagePercentage(data);
-      if (percentage) {
-        globals.publish('BufferUsage', {percentage});
+      data: {
+        commandline,
+        pbtxt: configProtoText,
       }
-    } else {
-      console.error('Unrecognized consumer port response:', data);
-    }
-  }
-
-  onTraceComplete() {
-    this.consumerPort.freeBuffers({});
-    globals.dispatch(Actions.setRecordingStatus({status: undefined}));
-    if (globals.state.recordingCancelled) {
-      globals.dispatch(
-          Actions.setLastRecordingError({error: 'Recording cancelled.'}));
-      this.traceBuffer = [];
-      return;
-    }
-    const trace = this.generateTrace();
-    globals.dispatch(Actions.openTraceFromBuffer({buffer: trace.buffer}));
-    this.traceBuffer = [];
-  }
-
-  // TODO(nicomazz): stream each chunk into the trace processor, instead of
-  // creating a big long trace.
-  generateTrace() {
-    let traceLen = 0;
-    for (const chunk of this.traceBuffer) traceLen += chunk.length;
-    const completeTrace = new Uint8Array(traceLen);
-    let written = 0;
-    for (const chunk of this.traceBuffer) {
-      completeTrace.set(chunk, written);
-      written += chunk.length;
-    }
-    return completeTrace;
-  }
-
-  getBufferUsagePercentage(data: GetTraceStatsResponse): number {
-    if (!data.traceStats || !data.traceStats.bufferStats) return 0.0;
-    let maximumUsage = 0;
-    for (const buffer of data.traceStats.bufferStats) {
-      const used = buffer.bytesWritten as number;
-      const total = buffer.bufferSize as number;
-      maximumUsage = Math.max(maximumUsage, used / total);
-    }
-    return maximumUsage;
-  }
-
-  onError(message: string) {
-    console.error('Error in record controller: ', message);
-    globals.dispatch(
-        Actions.setLastRecordingError({error: message.substr(0, 150)}));
-    globals.dispatch(Actions.stopRecording({}));
-  }
-
-  onStatus(message: string) {
-    globals.dispatch(Actions.setRecordingStatus({status: message}));
-  }
-
-  // Depending on the recording target, different implementation of the
-  // consumer_port will be used.
-  // - Chrome target: This forwards the messages that have to be sent
-  // to the extension to the frontend. This is necessary because this
-  // controller is running in a separate worker, that can't directly send
-  // messages to the extension.
-  // - Android device target: WebUSB is used to communicate using the adb
-  // protocol. Actually, there is no full consumer_port implementation, but
-  // only the support to start tracing and fetch the file.
-  async getTargetController(target: TargetOs, device?: AdbRecordingTarget):
-      Promise<RpcConsumerPort> {
-    const identifier = this.getTargetIdentifier(target, device);
-
-    // The reason why caching the target 'record controller' Promise is that
-    // multiple rcp calls can happen while we are trying to understand if an
-    // android device has a socket connection available or not.
-    const precedentPromise = this.controllerPromises.get(identifier);
-    if (precedentPromise) return precedentPromise;
-
-    const controllerPromise =
-        new Promise<RpcConsumerPort>(async (resolve, _) => {
-          let controller: RpcConsumerPort|undefined = undefined;
-          if (isChromeTarget(target)) {
-            controller =
-                new ChromeExtensionConsumerPort(this.extensionPort, this);
-          } else if (isAndroidTarget(target)) {
-            if (!device) throw Error(`No android device connected`);
-
-            this.onStatus(`Please allow USB debugging on device.
-                 If you press cancel, reload the page.`);
-            const socketAccess = await this.hasSocketAccess(device);
-
-            controller = socketAccess ?
-                new AdbSocketConsumerPort(this.adb, this) :
-                new AdbConsumerPort(this.adb, this);
-          }
-
-          if (!controller) throw Error(`Unknown target: ${target}`);
-          resolve(controller);
-        });
-
-    this.controllerPromises.set(identifier, controllerPromise);
-    return controllerPromise;
-  }
-
-  private getTargetIdentifier(target: TargetOs, device?: AdbRecordingTarget):
-      string {
-    return device ? device.serial : target;
-  }
-
-  private async hasSocketAccess(target: AdbRecordingTarget) {
-    const devices = await navigator.usb.getDevices();
-    const device = devices.find(d => d.serialNumber === target.serial);
-    console.assert(device);
-    if (!device) return Promise.resolve(false);
-    return AdbSocketConsumerPort.hasSocketAccess(device, this.adb);
-  }
-
-  private async rpcImpl(
-      method: RPCImplMethod, requestData: Uint8Array,
-      _callback: RPCImplCallback) {
-    try {
-      const state = this.app.state;
-      (await this.getTargetController(
-           state.recordConfig.targetOS, state.androidDeviceConnected))
-          .handleCommand(method.name, requestData);
-    } catch (e) {
-      console.error(`error invoking ${method}: ${e.message}`);
-    }
+    });
   }
 }
diff --git a/ui/src/controller/record_controller_interfaces.ts b/ui/src/controller/record_controller_interfaces.ts
deleted file mode 100644
index afd1d8b..0000000
--- a/ui/src/controller/record_controller_interfaces.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import {ConsumerPortResponse} from './consumer_port_types';
-
-export type ConsumerPortCallback = (_: ConsumerPortResponse) => void;
-export type ErrorCallback = (_: string) => void;
-export type StatusCallback = (_: string) => void;
-
-export abstract class RpcConsumerPort {
-  // The responses of the call invocations should be sent through this listener.
-  // This is done by the 3 "send" methods in this abstract class.
-  private consumerPortListener: Consumer;
-
-  constructor(consumerPortListener: Consumer) {
-    this.consumerPortListener = consumerPortListener;
-  }
-
-  // RequestData is the proto representing the arguments of the function call.
-  abstract handleCommand(methodName: string, requestData: Uint8Array): void;
-
-  sendMessage(data: ConsumerPortResponse) {
-    this.consumerPortListener.onConsumerPortResponse(data);
-  }
-
-  sendErrorMessage(message: string) {
-    this.consumerPortListener.onError(message);
-  }
-
-  sendStatus(status: string) {
-    this.consumerPortListener.onStatus(status);
-  }
-}
-
-export interface Consumer {
-  onConsumerPortResponse(data: ConsumerPortResponse): void;
-  onError: ErrorCallback;
-  onStatus: StatusCallback;
-}
\ No newline at end of file
diff --git a/ui/src/controller/record_controller_jsdomtest.ts b/ui/src/controller/record_controller_jsdomtest.ts
index 77da1ff..bf80a0d 100644
--- a/ui/src/controller/record_controller_jsdomtest.ts
+++ b/ui/src/controller/record_controller_jsdomtest.ts
@@ -14,12 +14,22 @@
 
 import {dingus} from 'dingusjs';
 
-import {assertExists} from '../base/logging';
 import {TraceConfig} from '../common/protos';
 import {createEmptyRecordConfig, RecordConfig} from '../common/state';
 
 import {App} from './globals';
-import {genConfigProto, RecordController, toPbtxt} from './record_controller';
+import {
+  genConfigProto,
+  RecordController,
+  toPbtxt,
+  uint8ArrayToBase64
+} from './record_controller';
+
+test('uint8ArrayToBase64', () => {
+  const bytes = [...'Hello, world'].map(c => c.charCodeAt(0));
+  const buffer = new Uint8Array(bytes);
+  expect(uint8ArrayToBase64(buffer)).toEqual('SGVsbG8sIHdvcmxk');
+});
 
 test('encodeConfig', () => {
   const config = createEmptyRecordConfig();
@@ -28,22 +38,9 @@
   expect(result.durationMs).toBe(10000);
 });
 
-test('SysConfig', () => {
-  const config = createEmptyRecordConfig();
-  config.cpuSyscall = true;
-  const result = TraceConfig.decode(genConfigProto(config));
-  const sources = assertExists(result.dataSources);
-  const srcConfig = assertExists(sources[0].config);
-  const ftraceConfig = assertExists(srcConfig.ftraceConfig);
-  const ftraceEvents = assertExists(ftraceConfig.ftraceEvents);
-  expect(ftraceEvents.includes('raw_syscalls/sys_enter')).toBe(true);
-  expect(ftraceEvents.includes('raw_syscalls/sys_exit')).toBe(true);
-});
-
 test('toPbtxt', () => {
   const config = {
     durationMs: 1000,
-    maxFileSizeBytes: 43,
     buffers: [
       {
         sizeKb: 42,
@@ -84,15 +81,13 @@
 producers: {
     producer_name: "perfetto.traced_probes"
 }
-max_file_size_bytes: 43
 `);
 });
 
 test('RecordController', () => {
   const app = dingus<App>('globals');
   (app.state.recordConfig as RecordConfig) = createEmptyRecordConfig();
-  const m: MessageChannel = dingus<MessageChannel>('extensionPort');
-  const controller = new RecordController({app, extensionPort: m.port1});
+  const controller = new RecordController({app});
   controller.run();
   controller.run();
   controller.run();
@@ -102,102 +97,3 @@
   // TODO(hjd): Fix up dingus to have a more sensible API.
   expect(calls[0][1][0]).toEqual('TrackData');
 });
-
-test('ChromeConfig', () => {
-  const config = createEmptyRecordConfig();
-  config.ipcFlows = true;
-  config.jsExecution = true;
-  config.mode = 'STOP_WHEN_FULL';
-  const result = TraceConfig.decode(genConfigProto(config));
-  const sources = assertExists(result.dataSources);
-
-  const traceConfigSource = assertExists(sources[0].config);
-  expect(traceConfigSource.name).toBe('org.chromium.trace_event');
-  const chromeConfig = assertExists(traceConfigSource.chromeConfig);
-  const traceConfig = assertExists(chromeConfig.traceConfig);
-
-  const metadataConfigSource = assertExists(sources[1].config);
-  expect(metadataConfigSource.name).toBe('org.chromium.trace_metadata');
-  const chromeConfigM = assertExists(metadataConfigSource.chromeConfig);
-  const traceConfigM = assertExists(chromeConfigM.traceConfig);
-
-  const expectedTraceConfig = '{"record_mode":"record-until-full",' +
-      '"included_categories":' +
-      '["toplevel","disabled-by-default-ipc.flow","mojom","v8"]}';
-  expect(traceConfigM).toEqual(expectedTraceConfig);
-  expect(traceConfig).toEqual(expectedTraceConfig);
-});
-
-test('ChromeConfigRingBuffer', () => {
-  const config = createEmptyRecordConfig();
-  config.ipcFlows = true;
-  config.jsExecution = true;
-  config.mode = 'RING_BUFFER';
-  const result = TraceConfig.decode(genConfigProto(config));
-  const sources = assertExists(result.dataSources);
-
-  const traceConfigSource = assertExists(sources[0].config);
-  expect(traceConfigSource.name).toBe('org.chromium.trace_event');
-  const chromeConfig = assertExists(traceConfigSource.chromeConfig);
-  const traceConfig = assertExists(chromeConfig.traceConfig);
-
-  const metadataConfigSource = assertExists(sources[1].config);
-  expect(metadataConfigSource.name).toBe('org.chromium.trace_metadata');
-  const chromeConfigM = assertExists(metadataConfigSource.chromeConfig);
-  const traceConfigM = assertExists(chromeConfigM.traceConfig);
-
-  const expectedTraceConfig = '{"record_mode":"record-continuously",' +
-      '"included_categories":' +
-      '["toplevel","disabled-by-default-ipc.flow","mojom","v8"]}';
-  expect(traceConfigM).toEqual(expectedTraceConfig);
-  expect(traceConfig).toEqual(expectedTraceConfig);
-});
-
-
-test('ChromeConfigLongTrace', () => {
-  const config = createEmptyRecordConfig();
-  config.ipcFlows = true;
-  config.jsExecution = true;
-  config.mode = 'RING_BUFFER';
-  const result = TraceConfig.decode(genConfigProto(config));
-  const sources = assertExists(result.dataSources);
-
-  const traceConfigSource = assertExists(sources[0].config);
-  expect(traceConfigSource.name).toBe('org.chromium.trace_event');
-  const chromeConfig = assertExists(traceConfigSource.chromeConfig);
-  const traceConfig = assertExists(chromeConfig.traceConfig);
-
-  const metadataConfigSource = assertExists(sources[1].config);
-  expect(metadataConfigSource.name).toBe('org.chromium.trace_metadata');
-  const chromeConfigM = assertExists(metadataConfigSource.chromeConfig);
-  const traceConfigM = assertExists(chromeConfigM.traceConfig);
-
-  const expectedTraceConfig = '{"record_mode":"record-continuously",' +
-      '"included_categories":' +
-      '["toplevel","disabled-by-default-ipc.flow","mojom","v8"]}';
-  expect(traceConfigM).toEqual(expectedTraceConfig);
-  expect(traceConfig).toEqual(expectedTraceConfig);
-});
-
-test('ChromeConfigToPbtxt', () => {
-  const config = {
-    dataSources: [{
-      config: {
-        name: 'org.chromium.trace_event',
-        chromeConfig:
-            {traceConfig: JSON.stringify({included_categories: ['v8']})},
-      },
-    }],
-  };
-  const text = toPbtxt(TraceConfig.encode(config).finish());
-
-  expect(text).toEqual(`data_sources: {
-    config {
-        name: "org.chromium.trace_event"
-        chrome_config {
-            trace_config: "{\\"included_categories\\":[\\"v8\\"]}"
-        }
-    }
-}
-`);
-});
diff --git a/ui/src/controller/search_controller.ts b/ui/src/controller/search_controller.ts
deleted file mode 100644
index 0edaa53..0000000
--- a/ui/src/controller/search_controller.ts
+++ /dev/null
@@ -1,271 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {Engine} from '../common/engine';
-import {CurrentSearchResults, SearchSummary} from '../common/search_data';
-import {TimeSpan} from '../common/time';
-
-import {Controller} from './controller';
-import {App} from './globals';
-
-export interface SearchControllerArgs {
-  engine: Engine;
-  app: App;
-}
-
-
-export class SearchController extends Controller<'main'> {
-  private engine: Engine;
-  private app: App;
-  private previousSpan: TimeSpan;
-  private previousResolution: number;
-  private previousSearch: string;
-  private updateInProgress: boolean;
-  private setupInProgress: boolean;
-
-  constructor(args: SearchControllerArgs) {
-    super('main');
-    this.engine = args.engine;
-    this.app = args.app;
-    this.previousSpan = new TimeSpan(0, 1);
-    this.previousSearch = '';
-    this.updateInProgress = false;
-    this.setupInProgress = true;
-    this.previousResolution = 1;
-    this.setup().finally(() => {
-      this.setupInProgress = false;
-      this.run();
-    });
-  }
-
-  private async setup() {
-    await this.query(`create virtual table search_summary_window
-      using window;`);
-    await this.query(`create virtual table search_summary_sched_span using
-      span_join(sched PARTITIONED cpu, search_summary_window);`);
-    await this.query(`create virtual table search_summary_slice_span using
-      span_join(slice PARTITIONED ref_type  ref, search_summary_window);`);
-  }
-
-  run() {
-    if (this.setupInProgress || this.updateInProgress) {
-      return;
-    }
-
-    const visibleState = this.app.state.frontendLocalState.visibleState;
-    const omniboxState = this.app.state.frontendLocalState.omniboxState;
-    if (visibleState === undefined || omniboxState === undefined ||
-        omniboxState.mode === 'COMMAND') {
-      return;
-    }
-    const newSpan = new TimeSpan(visibleState.startSec, visibleState.endSec);
-    const newSearch = omniboxState.omnibox;
-    const newResolution = visibleState.resolution;
-    if (this.previousSpan.contains(newSpan) &&
-        this.previousResolution === newResolution &&
-        newSearch === this.previousSearch) {
-      return;
-    }
-    this.previousSpan = new TimeSpan(
-        Math.max(newSpan.start - newSpan.duration, 0),
-        newSpan.end + newSpan.duration);
-    this.previousResolution = newResolution;
-    this.previousSearch = newSearch;
-    if (newSearch === '' || newSearch.length < 4) {
-      this.app.publish('Search', {
-        tsStarts: new Float64Array(0),
-        tsEnds: new Float64Array(0),
-        count: new Uint8Array(0),
-      });
-      this.app.publish('SearchResult', {
-        sliceIds: new Float64Array(0),
-        tsStarts: new Float64Array(0),
-        utids: new Float64Array(0),
-        refTypes: [],
-        trackIds: [],
-        totalResults: 0,
-      });
-      return;
-    }
-
-    const startNs = Math.round(newSpan.start * 1e9);
-    const endNs = Math.round(newSpan.end * 1e9);
-    this.updateInProgress = true;
-    const computeSummary =
-        this.update(newSearch, startNs, endNs, newResolution).then(summary => {
-          this.app.publish('Search', summary);
-        });
-
-    const computeResults =
-        this.specificSearch(newSearch).then(searchResults => {
-          this.app.publish('SearchResult', searchResults);
-        });
-
-    Promise.all([computeSummary, computeResults])
-        .catch(e => {
-          console.error(e);
-        })
-        .finally(() => {
-          this.updateInProgress = false;
-          this.run();
-        });
-  }
-
-  onDestroy() {}
-
-  private async update(
-      search: string, startNs: number, endNs: number,
-      resolution: number): Promise<SearchSummary> {
-    const quantumNs = Math.round(resolution * 10 * 1e9);
-
-    startNs = Math.floor(startNs / quantumNs) * quantumNs;
-
-    await this.query(`update search_summary_window set
-      window_start=${startNs},
-      window_dur=${endNs - startNs},
-      quantum=${quantumNs}
-      where rowid = 0;`);
-
-    const rawUtidResult = await this.query(`select utid from thread join process
-      using(upid) where thread.name like "%${search}%" or process.name like "%${
-        search}%"`);
-
-    const utids = [...rawUtidResult.columns[0].longValues!];
-
-    const maxCpu = Math.max(...await this.engine.getCpus());
-
-    const rawResult = await this.query(`
-        select
-          (quantum_ts * ${quantumNs} + ${startNs})/1e9 as tsStart,
-          ((quantum_ts+1) * ${quantumNs} + ${startNs})/1e9 as tsEnd,
-          min(count(*), 255) as count
-          from (
-              select
-              quantum_ts
-              from search_summary_sched_span
-              where utid in (${utids.join(',')}) and cpu <= ${maxCpu}
-            union all
-              select
-              quantum_ts
-              from search_summary_slice_span
-              where name like '%${search}%'
-          )
-          group by quantum_ts
-          order by quantum_ts;`);
-
-    const numRows = +rawResult.numRecords;
-    const summary = {
-      tsStarts: new Float64Array(numRows),
-      tsEnds: new Float64Array(numRows),
-      count: new Uint8Array(numRows)
-    };
-
-    const columns = rawResult.columns;
-    for (let row = 0; row < numRows; row++) {
-      summary.tsStarts[row] = +columns[0].doubleValues![row];
-      summary.tsEnds[row] = +columns[1].doubleValues![row];
-      summary.count[row] = +columns[2].longValues![row];
-    }
-    return summary;
-  }
-
-  private async specificSearch(search: string) {
-    // TODO(hjd): we should avoid recomputing this every time. This will be
-    // easier once the track table has entries for all the tracks.
-    const cpuToTrackId = new Map();
-    const engineTrackIdToTrackId = new Map();
-    for (const track of Object.values(this.app.state.tracks)) {
-      if (track.kind === 'CpuSliceTrack') {
-        cpuToTrackId.set((track.config as {cpu: number}).cpu, track.id);
-        continue;
-      }
-      if (track.kind === 'ChromeSliceTrack' ||
-          track.kind === 'AsyncSliceTrack') {
-        engineTrackIdToTrackId.set(
-            (track.config as {trackId: number}).trackId, track.id);
-        continue;
-      }
-    }
-
-    const rawUtidResult = await this.query(`select utid from thread join process
-    using(upid) where thread.name like "%${search}%" or process.name like "%${
-        search}%"`);
-    const utids = [...rawUtidResult.columns[0].longValues!];
-
-    const rawResult = await this.query(`
-    select
-      row_id as slice_id,
-      ts,
-      'cpu' as source,
-      cpu as ref,
-      utid
-    from sched where utid in (${utids.join(',')})
-    union
-    select
-      slice_id,
-      ts,
-      'track' as source,
-      track_id as ref,
-      0 as utid
-      from slice
-      inner join track on slice.track_id = track.id
-      and slice.name like '%${search}%'
-    order by ts`);
-
-    const numRows = +rawResult.numRecords;
-
-    const searchResults: CurrentSearchResults = {
-      sliceIds: new Float64Array(numRows),
-      tsStarts: new Float64Array(numRows),
-      utids: new Float64Array(numRows),
-      trackIds: [],
-      refTypes: [],
-      totalResults: +numRows,
-    };
-
-    const columns = rawResult.columns;
-    for (let row = 0; row < numRows; row++) {
-      const source = columns[2].stringValues![row];
-      const ref = +columns[3].longValues![row];
-      let trackId = undefined;
-      if (source === 'cpu') {
-        trackId = cpuToTrackId.get(ref);
-      } else if (source === 'track') {
-        trackId = engineTrackIdToTrackId.get(ref);
-      }
-
-      if (trackId === undefined) {
-        searchResults.totalResults--;
-        continue;
-      }
-
-      searchResults.trackIds.push(trackId);
-      searchResults.refTypes.push(source);
-      searchResults.sliceIds[row] = +columns[0].longValues![row];
-      searchResults.tsStarts[row] = +columns[1].longValues![row];
-      searchResults.utids[row] = +columns[4].longValues![row];
-    }
-    return searchResults;
-  }
-
-
-  private async query(query: string) {
-    const result = await this.engine.query(query);
-    if (result.error) {
-      console.error(`Query error "${query}": ${result.error}`);
-      throw new Error(`Query error "${query}": ${result.error}`);
-    }
-    return result;
-  }
-}
diff --git a/ui/src/controller/selection_controller.ts b/ui/src/controller/selection_controller.ts
index 2257307..308b09e 100644
--- a/ui/src/controller/selection_controller.ts
+++ b/ui/src/controller/selection_controller.ts
@@ -13,12 +13,8 @@
 // limitations under the License.
 
 import {Engine} from '../common/engine';
-import {fromNs, toNs} from '../common/time';
-import {
-  CounterDetails,
-  HeapProfileDetails,
-  SliceDetails
-} from '../frontend/globals';
+import {fromNs} from '../common/time';
+import {SliceDetails} from '../frontend/globals';
 
 import {Controller} from './controller';
 import {globals} from './globals';
@@ -30,172 +26,51 @@
 // This class queries the TP for the details on a specific slice that has
 // been clicked.
 export class SelectionController extends Controller<'main'> {
-  private lastSelectedId?: number|string;
-  private lastSelectedKind?: string;
+  private lastSelectedSlice?: number;
   constructor(private args: SelectionControllerArgs) {
     super('main');
   }
 
   run() {
     const selection = globals.state.currentSelection;
-    if (!selection) return;
-    // TODO(taylori): Ideally thread_state should not be special cased, it
-    // should have some form of id like everything else.
-    if (selection.kind === 'THREAD_STATE') {
-      const sqlQuery = `SELECT row_id FROM sched WHERE utid = ${selection.utid}
-                        and ts = ${toNs(selection.ts)}`;
-      this.args.engine.query(sqlQuery).then(result => {
-        const id = result.columns[0].longValues![0] as number;
-        this.sliceDetails(id);
-      });
+    if (selection === null ||
+        selection.kind !== 'SLICE' ||
+        selection.id === this.lastSelectedSlice) {
       return;
     }
+    const selectedSlice = selection.id;
+    this.lastSelectedSlice = selectedSlice;
 
-    const selectWithId = ['SLICE', 'COUNTER', 'CHROME_SLICE', 'HEAP_PROFILE'];
-    if (!selectWithId.includes(selection.kind) ||
-        (selectWithId.includes(selection.kind) &&
-         selection.id === this.lastSelectedId &&
-         selection.kind === this.lastSelectedKind)) {
-      return;
-    }
-    const selectedId = selection.id;
-    const selectedKind = selection.kind;
-    this.lastSelectedId = selectedId;
-    this.lastSelectedKind = selectedKind;
-
-    if (selectedId === undefined) return;
-
-    if (selection.kind === 'HEAP_PROFILE') {
-      const selected: HeapProfileDetails = {};
-      const ts = selection.ts;
-      const upid = selection.upid;
-      this.heapDumpDetails(ts, upid).then(results => {
-        if (results !== undefined && selection &&
-            selection.kind === selectedKind && selection.id === selectedId) {
-          Object.assign(selected, results);
-          globals.publish('HeapDumpDetails', selected);
-        }
-      });
-    } else if (selection.kind === 'COUNTER') {
-      const selected: CounterDetails = {};
-      this.counterDetails(selection.leftTs, selection.rightTs, selection.id)
-          .then(results => {
-            if (results !== undefined && selection &&
-                selection.kind === selectedKind &&
-                selection.id === selectedId) {
-              Object.assign(selected, results);
-              globals.publish('CounterDetails', selected);
-            }
-          });
-    } else if (selectedKind === 'SLICE') {
-      this.sliceDetails(selectedId as number);
-    } else if (selectedKind === 'CHROME_SLICE') {
-      if (selectedId === -1) {
-        globals.publish('SliceDetails', {ts: 0, name: 'Summarized slice'});
-        return;
-      }
-      const sqlQuery = `SELECT ts, dur, name, cat FROM slices
-      WHERE slice_id = ${selectedId}`;
+    if (selectedSlice !== undefined) {
+      const sqlQuery = `SELECT ts, dur, priority, end_state, utid FROM sched
+                        WHERE row_id = ${selectedSlice}`;
       this.args.engine.query(sqlQuery).then(result => {
         // Check selection is still the same on completion of query.
         const selection = globals.state.currentSelection;
-        if (result.numRecords === 1 && selection &&
-            selection.kind === selectedKind && selection.id === selectedId) {
+        if (result.numRecords === 1 &&
+            selection &&
+            selection.kind === 'SLICE' &&
+            selection.id === selectedSlice) {
           const ts = result.columns[0].longValues![0] as number;
           const timeFromStart = fromNs(ts) - globals.state.traceTime.startSec;
-          const name = result.columns[2].stringValues![0];
           const dur = fromNs(result.columns[1].longValues![0] as number);
-          const category = result.columns[3].stringValues![0];
-          // TODO(nicomazz): Add arguments and thread timestamps
-          const selected: SliceDetails =
-              {ts: timeFromStart, dur, category, name, id: selectedId};
-          globals.publish('SliceDetails', selected);
+          const priority = result.columns[2].longValues![0] as number;
+          const endState = result.columns[3].stringValues![0];
+          const selected:
+              SliceDetails = {ts: timeFromStart, dur, priority, endState};
+          const utid = result.columns[4].longValues![0];
+          this.schedulingDetails(ts, utid).then(wakeResult => {
+            Object.assign(selected, wakeResult);
+            globals.publish('SliceDetails', selected);
+          });
         }
       });
     }
   }
 
-  async sliceDetails(id: number) {
-    const sqlQuery = `SELECT ts, dur, priority, end_state, utid, cpu FROM sched
-    WHERE row_id = ${id}`;
-    this.args.engine.query(sqlQuery).then(result => {
-      // Check selection is still the same on completion of query.
-      const selection = globals.state.currentSelection;
-      if (result.numRecords === 1 && selection) {
-        const ts = result.columns[0].longValues![0] as number;
-        const timeFromStart = fromNs(ts) - globals.state.traceTime.startSec;
-        const dur = fromNs(result.columns[1].longValues![0] as number);
-        const priority = result.columns[2].longValues![0] as number;
-        const endState = result.columns[3].stringValues![0];
-        const utid = result.columns[4].longValues![0] as number;
-        const cpu = result.columns[5].longValues![0] as number;
-        const selected: SliceDetails =
-            {ts: timeFromStart, dur, priority, endState, cpu, id, utid};
-        this.schedulingDetails(ts, utid).then(wakeResult => {
-          Object.assign(selected, wakeResult);
-          globals.publish('SliceDetails', selected);
-        });
-      }
-    });
-  }
-
-  async heapDumpDetails(ts: number, upid: number) {
-    // Collecting data for more information about heap profile, such as:
-    // total memory allocated, memory that is allocated and not freed.
-    const pidValue = await this.args.engine.query(
-        `select pid from process where upid = ${upid}`);
-    const pid = pidValue.columns[0].longValues![0];
-    const allocatedMemory = await this.args.engine.query(
-        `select sum(size) from heap_profile_allocation where ts <= ${
-            ts} and size > 0 and upid = ${upid}`);
-    const allocated = allocatedMemory.columns[0].longValues![0];
-    const allocatedNotFreedMemory = await this.args.engine.query(
-        `select sum(size) from heap_profile_allocation where ts <= ${
-            ts} and upid = ${upid}`);
-    const allocatedNotFreed = allocatedNotFreedMemory.columns[0].longValues![0];
-    const startTime = fromNs(ts) - globals.state.traceTime.startSec;
-    return {
-      ts: startTime,
-      allocated,
-      allocatedNotFreed,
-      tsNs: ts,
-      pid,
-    };
-  }
-
-  async counterDetails(ts: number, rightTs: number, id: number) {
-    const counter = await this.args.engine.query(
-        `SELECT value FROM counter_values WHERE ts = ${ts} AND counter_id = ${
-            id}`);
-    const value = counter.columns[0].doubleValues![0];
-    // Finding previous value. If there isn't previous one, it will return 0 for
-    // ts and value.
-    const previous = await this.args.engine.query(
-        `SELECT MAX(ts), value FROM counter_values WHERE ts < ${
-            ts} and counter_id = ${id}`);
-    const previousValue = previous.columns[1].doubleValues![0];
-    const endTs =
-        rightTs !== -1 ? rightTs : toNs(globals.state.traceTime.endSec);
-    const delta = value - previousValue;
-    const duration = endTs - ts;
-    const startTime = fromNs(ts) - globals.state.traceTime.startSec;
-    return {startTime, value, delta, duration};
-  }
-
   async schedulingDetails(ts: number, utid: number|Long) {
-    let event = 'sched_waking';
-    const waking = await this.args.engine.query(
-        `select * from instants where name = 'sched_waking' limit 1`);
-    const wakeup = await this.args.engine.query(
-        `select * from instants where name = 'sched_wakeup' limit 1`);
-    if (waking.numRecords === 0) {
-      if (wakeup.numRecords === 0) return undefined;
-      // Only use sched_wakeup if waking is not in the trace.
-      event = 'sched_wakeup';
-    }
-
     // Find the ts of the first sched_wakeup before the current slice.
-    const queryWakeupTs = `select ts from instants where name = '${event}'
+    const queryWakeupTs = `select ts from instants where name = 'sched_wakeup'
     and ref = ${utid} and ts < ${ts} order by ts desc limit 1`;
     const wakeupRow = await this.args.engine.queryOneRow(queryWakeupTs);
     // Find the previous sched slice for the current utid.
@@ -211,7 +86,7 @@
     // Find the sched slice with the utid of the waker running when the
     // sched wakeup occurred. This is the waker.
     const queryWaker = `select utid, cpu from sched where utid =
-    (select utid from raw where name = '${event}' and ts = ${wakeupTs})
+    (select utid from raw where name = 'sched_wakeup' and ts = ${wakeupTs})
     and ts < ${wakeupTs} and ts + dur >= ${wakeupTs};`;
     const wakerRow = await this.args.engine.queryOneRow(queryWaker);
     if (wakerRow) {
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index 7edcbba..88b5081 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -19,33 +19,17 @@
 import {assertExists, assertTrue} from '../base/logging';
 import {
   Actions,
-  AddTrackArgs,
   DeferredAction,
 } from '../common/actions';
 import {Engine} from '../common/engine';
-import {HttpRpcEngine} from '../common/http_rpc_engine';
 import {NUM, NUM_NULL, rawQueryToRows, STR_NULL} from '../common/protos';
-import {
-  EngineMode,
-  SCROLLING_TRACK_GROUP,
-} from '../common/state';
-import {toNs, toNsCeil, toNsFloor} from '../common/time';
+import {SCROLLING_TRACK_GROUP} from '../common/state';
 import {TimeSpan} from '../common/time';
-import {
-  createWasmEngine,
-  destroyWasmEngine,
-  WasmEngineProxy
-} from '../common/wasm_engine_proxy';
 import {QuantizedLoad, ThreadDesc} from '../frontend/globals';
 import {ANDROID_LOGS_TRACK_KIND} from '../tracks/android_log/common';
 import {SLICE_TRACK_KIND} from '../tracks/chrome_slices/common';
 import {CPU_FREQ_TRACK_KIND} from '../tracks/cpu_freq/common';
 import {CPU_SLICE_TRACK_KIND} from '../tracks/cpu_slices/common';
-import {GPU_FREQ_TRACK_KIND} from '../tracks/gpu_freq/common';
-import {HEAP_PROFILE_TRACK_KIND} from '../tracks/heap_profile/common';
-import {
-  HEAP_PROFILE_FLAMEGRAPH_TRACK_KIND
-} from '../tracks/heap_profile_flamegraph/common';
 import {
   PROCESS_SCHEDULING_TRACK_KIND
 } from '../tracks/process_scheduling/common';
@@ -54,28 +38,21 @@
 
 import {Child, Children, Controller} from './controller';
 import {globals} from './globals';
-import {LoadingManager} from './loading_manager';
 import {LogsController} from './logs_controller';
 import {QueryController, QueryControllerArgs} from './query_controller';
-import {SearchController} from './search_controller';
 import {
   SelectionController,
   SelectionControllerArgs
 } from './selection_controller';
-import {
-  TraceBufferStream,
-  TraceFileStream,
-  TraceHttpStream,
-  TraceStream
-} from './trace_stream';
 import {TrackControllerArgs, trackControllerRegistry} from './track_controller';
 
 type States = 'init'|'loading_trace'|'ready';
 
-interface ThreadSliceTrack {
-  maxDepth: number;
-  trackId: number;
-}
+
+declare interface FileReaderSync { readAsArrayBuffer(blob: Blob): ArrayBuffer; }
+
+declare var FileReaderSync:
+    {prototype: FileReaderSync; new (): FileReaderSync;};
 
 // TraceController handles handshakes with the frontend for everything that
 // concerns a single trace. It owns the WASM trace processor engine, handles
@@ -91,27 +68,23 @@
   }
 
   onDestroy() {
-    if (this.engine instanceof WasmEngineProxy) {
-      destroyWasmEngine(this.engine.id);
-    }
+    if (this.engine !== undefined) globals.destroyEngine(this.engine.id);
   }
 
   run() {
     const engineCfg = assertExists(globals.state.engines[this.engineId]);
     switch (this.state) {
       case 'init':
-        this.loadTrace()
-            .then(mode => {
-              globals.dispatch(Actions.setEngineReady({
-                engineId: this.engineId,
-                ready: true,
-                mode,
-              }));
-            })
-            .catch(err => {
-              this.updateStatus(`${err}`);
-              throw err;
-            });
+        globals.dispatch(Actions.setEngineReady({
+          engineId: this.engineId,
+          ready: false,
+        }));
+        this.loadTrace().then(() => {
+          globals.dispatch(Actions.setEngineReady({
+            engineId: this.engineId,
+            ready: true,
+          }));
+        });
         this.updateStatus('Opening trace');
         this.setState('loading_trace');
         break;
@@ -149,11 +122,6 @@
         childControllers.push(
           Child('selection', SelectionController, selectionArgs));
 
-        childControllers.push(Child('search', SearchController, {
-          engine,
-          app: globals,
-        }));
-
         childControllers.push(Child('logs', LogsController, {
           engine,
           app: globals,
@@ -167,81 +135,56 @@
     return;
   }
 
-  private async loadTrace(): Promise<EngineMode> {
+  private async loadTrace() {
     this.updateStatus('Creating trace processor');
-    // Check if there is any instance of the trace_processor_shell running in
-    // HTTP RPC mode (i.e. trace_processor_shell -D).
-    let engineMode: EngineMode;
-    let useRpc = false;
-    if (globals.state.newEngineMode === 'USE_HTTP_RPC_IF_AVAILABLE') {
-      useRpc = (await HttpRpcEngine.checkConnection()).connected;
-    }
-    if (useRpc) {
-      console.log('Opening trace using native accelerator over HTTP+RPC');
-      engineMode = 'HTTP_RPC';
-      const engine =
-          new HttpRpcEngine(this.engineId, LoadingManager.getInstance);
-      engine.errorHandler = (err) => {
-        globals.dispatch(
-            Actions.setEngineFailed({mode: 'HTTP_RPC', failure: `${err}`}));
-        throw err;
-      };
-      this.engine = engine;
-    } else {
-      console.log('Opening trace using built-in WASM engine');
-      engineMode = 'WASM';
-      this.engine = new WasmEngineProxy(
-          this.engineId,
-          createWasmEngine(this.engineId),
-          LoadingManager.getInstance);
-    }
-
-    globals.dispatch(Actions.setEngineReady({
-      engineId: this.engineId,
-      ready: false,
-      mode: engineMode,
-    }));
     const engineCfg = assertExists(globals.state.engines[this.engineId]);
-    let traceStream: TraceStream|undefined;
-    if (engineCfg.source.type === 'FILE') {
-      traceStream = new TraceFileStream(engineCfg.source.file);
-    } else if (engineCfg.source.type === 'ARRAY_BUFFER') {
-      traceStream = new TraceBufferStream(engineCfg.source.buffer);
-    } else if (engineCfg.source.type === 'URL') {
-      traceStream = new TraceHttpStream(engineCfg.source.url);
-    } else if (engineCfg.source.type === 'HTTP_RPC') {
-      traceStream = undefined;
+    this.engine = globals.createEngine();
+
+    const statusHeader = 'Opening trace';
+    if (engineCfg.source instanceof File) {
+      const blob = engineCfg.source as Blob;
+      const reader = new FileReaderSync();
+      const SLICE_SIZE = 1024 * 1024;
+      for (let off = 0; off < blob.size; off += SLICE_SIZE) {
+        const slice = blob.slice(off, off + SLICE_SIZE);
+        const arrBuf = reader.readAsArrayBuffer(slice);
+        await this.engine.parse(new Uint8Array(arrBuf));
+        const progress = Math.round((off + slice.size) / blob.size * 100);
+        this.updateStatus(`${statusHeader} ${progress} %`);
+      }
     } else {
-      throw new Error(`Unknown source: ${JSON.stringify(engineCfg.source)}`);
+      const resp = await fetch(engineCfg.source);
+      if (resp.status !== 200) {
+        this.updateStatus(`HTTP error ${resp.status}`);
+        throw new Error(`fetch() failed with HTTP error ${resp.status}`);
+      }
+      // tslint:disable-next-line no-any
+      const rd = (resp.body as any).getReader() as ReadableStreamReader;
+      const tStartMs = performance.now();
+      let tLastUpdateMs = 0;
+      for (let off = 0;;) {
+        const readRes = await rd.read() as {value: Uint8Array, done: boolean};
+        if (readRes.value !== undefined) {
+          off += readRes.value.length;
+          await this.engine.parse(readRes.value);
+        }
+        // For traces loaded from the network there doesn't seem to be a
+        // reliable way to compute the %. The content-length exposed by GCS is
+        // before compression (which is handled transparently by the browser).
+        const nowMs = performance.now();
+        if (nowMs - tLastUpdateMs > 100) {
+          tLastUpdateMs = nowMs;
+          const mb = off / 1e6;
+          const tElapsed = (nowMs - tStartMs) / 1e3;
+          let status = `${statusHeader} ${mb.toFixed(1)} MB `;
+          status += `(${(mb / tElapsed).toFixed(1)} MB/s)`;
+          this.updateStatus(status);
+        }
+        if (readRes.done) break;
+      }
     }
 
-    // |traceStream| can be undefined in the case when we are using the external
-    // HTTP+RPC endpoint and the trace processor instance has already loaded
-    // a trace (because it was passed as a cmdline argument to
-    // trace_processor_shell). In this case we don't want the UI to load any
-    // file/stream and we just want to jump to the loading phase.
-    if (traceStream !== undefined) {
-      const tStart = performance.now();
-      for (;;) {
-        const res = await traceStream.readChunk();
-        await this.engine.parse(res.data);
-        const elapsed = (performance.now() - tStart) / 1000;
-        let status = 'Loading trace ';
-        if (res.bytesTotal > 0) {
-          const progress = Math.round(res.bytesRead / res.bytesTotal * 100);
-          status += `${progress}%`;
-        } else {
-          status += `${Math.round(res.bytesRead / 1e6)} MB`;
-        }
-        status += ` - ${Math.ceil(res.bytesRead / elapsed / 1e6)} MB/s`;
-        this.updateStatus(status);
-        if (res.eof) break;
-      }
-      await this.engine.notifyEof();
-    } else {
-      assertTrue(this.engine instanceof HttpRpcEngine);
-      await this.engine.restoreInitialTables();
-    }
+    await this.engine.notifyEof();
 
     const traceTime = await this.engine.getTraceTimeBounds();
     const traceTimeState = {
@@ -253,33 +196,33 @@
       Actions.navigate({route: '/viewer'}),
     ];
 
-    // We don't know the resolution at this point. However this will be
-    // replaced in 50ms so a guess is fine.
-    const resolution = (traceTime.end - traceTime.start) / 1000;
-    actions.push(Actions.setVisibleTraceTime(
-        {...traceTimeState, lastUpdate: Date.now() / 1000, resolution}));
+    if (globals.state.frontendLocalState.lastUpdate === 0) {
+      actions.push(Actions.setVisibleTraceTime({
+        time: traceTimeState,
+        lastUpdate: Date.now() / 1000,
+      }));
+    }
 
     globals.dispatchMultiple(actions);
 
     {
       // When we reload from a permalink don't create extra tracks:
-      const {pinnedTracks, tracks} = globals.state;
-      if (!pinnedTracks.length && !Object.keys(tracks).length) {
+      const {pinnedTracks, scrollingTracks} = globals.state;
+      if (!pinnedTracks.length && !scrollingTracks.length) {
         await this.listTracks();
       }
     }
 
     await this.listThreads();
     await this.loadTimelineOverview(traceTime);
-    return engineMode;
   }
 
   private async listTracks() {
     this.updateStatus('Loading tracks');
 
     const engine = assertExists<Engine>(this.engine);
-    const numGpus = await engine.getNumberOfGpus();
-    const tracksToAdd: AddTrackArgs[] = [];
+    const addToTrackActions: DeferredAction[] = [];
+    const numCpus = await engine.getNumberOfCpus();
 
     // TODO(hjd): Renable Vsync tracks when fixed.
     //// TODO(hjd): Move this code out of TraceController.
@@ -300,16 +243,14 @@
     //    }
     //  }));
     //}
-    const maxCpuFreq = await engine.query(`
+    const maxFreq = await engine.query(`
      select max(value)
      from counters
      where name = 'cpufreq';
     `);
 
-    const cpus = await engine.getCpus();
-
-    for (const cpu of cpus) {
-      tracksToAdd.push({
+    for (let cpu = 0; cpu < numCpus; cpu++) {
+      addToTrackActions.push(Actions.addTrack({
         engineId: this.engineId,
         kind: CPU_SLICE_TRACK_KIND,
         name: `Cpu ${cpu}`,
@@ -317,10 +258,8 @@
         config: {
           cpu,
         }
-      });
-    }
+      }));
 
-    for (const cpu of cpus) {
       // Only add a cpu freq track if we have
       // cpu freq data.
       // TODO(taylori): Find a way to display cpu idle
@@ -332,146 +271,63 @@
         limit 1;
       `);
       if (freqExists.numRecords > 0) {
-        tracksToAdd.push({
+        addToTrackActions.push(Actions.addTrack({
           engineId: this.engineId,
           kind: CPU_FREQ_TRACK_KIND,
           name: `Cpu ${cpu} Frequency`,
           trackGroup: SCROLLING_TRACK_GROUP,
           config: {
             cpu,
-            maximumValue: +maxCpuFreq.columns[0].doubleValues![0],
+            maximumValue: +maxFreq.columns[0].doubleValues![0],
           }
-        });
+        }));
       }
     }
 
-
-    const upidToProcessTracks = new Map();
-    const rawProcessTracks = await engine.query(`
-      select id, upid, process_track.name, max(depth) as maxDepth
-      from process_track
-      inner join slice on slice.track_id = process_track.id
-      group by track_id
-    `);
-    for (let i = 0; i < rawProcessTracks.numRecords; i++) {
-      const trackId = rawProcessTracks.columns[0].longValues![i];
-      const upid = rawProcessTracks.columns[1].longValues![i];
-      const name = rawProcessTracks.columns[2].stringValues![i];
-      const maxDepth = rawProcessTracks.columns[3].longValues![i];
-      const track = {
-        engineId: this.engineId,
-        kind: 'AsyncSliceTrack',
-        name,
-        config: {
-          trackId,
-          maxDepth,
-        },
-      };
-
-      const tracks = upidToProcessTracks.get(upid);
-      if (tracks) {
-        tracks.push(track);
-      } else {
-        upidToProcessTracks.set(upid, [track]);
-      }
-    }
-
-    const heapProfiles = await engine.query(`
-      select distinct(upid) from heap_profile_allocation`);
-
-    const heapUpids: Set<number> = new Set();
-    for (let i = 0; i < heapProfiles.numRecords; i++) {
-      const upid = heapProfiles.columns[0].longValues![i];
-      heapUpids.add(+upid);
-    }
-
-    const maxGpuFreq = await engine.query(`
-     select max(value)
-     from counters
-     where name = 'gpufreq';
-    `);
-
-    for (let gpu = 0; gpu < numGpus; gpu++) {
-      // Only add a gpu freq track if we have
-      // gpu freq data.
-      const freqExists = await engine.query(`
-        select value
-        from counters
-        where name = 'gpufreq' and ref = ${gpu}
-        limit 1;
-      `);
-      if (freqExists.numRecords > 0) {
-        tracksToAdd.push({
-          engineId: this.engineId,
-          kind: GPU_FREQ_TRACK_KIND,
-          name: `Gpu ${gpu} Frequency`,
-          trackGroup: SCROLLING_TRACK_GROUP,
-          config: {
-            gpu,
-            maximumValue: +maxGpuFreq.columns[0].doubleValues![0],
-          }
-        });
-      }
-    }
-
-
     const counters = await engine.query(`
-      select name, ref, ref_type
+      select name, ref, ref_type, count(ref_type)
       from counter_definitions
       where ref is not null
       group by name, ref, ref_type
       order by ref_type desc
     `);
-
-    interface CounterMap {
-      [index: number]: string[];
-    }
-
-    const counterUpids: CounterMap = new Array();
-    const counterUtids: CounterMap = new Array();
+    const counterUpids = new Set<number>();
+    const counterUtids = new Set<number>();
     for (let i = 0; i < counters.numRecords; i++) {
-      const name = counters.columns[0].stringValues![i];
       const ref = +counters.columns[1].longValues![i];
       const refType = counters.columns[2].stringValues![i];
-      if (refType === 'upid') {
-        const el = counterUpids[ref];
-        el === undefined ? counterUpids[ref] = [name] :
-                           counterUpids[ref].push(name);
-      } else if (refType === 'utid') {
-        const el = counterUtids[ref];
-        el === undefined ? counterUtids[ref] = [name] :
-                           counterUtids[ref].push(name);
-      } else if (
-          refType === '[NULL]' || (refType === 'gpu' && name !== 'gpufreq')) {
-        // Add global or GPU counter tracks that are not bound to any pid/tid.
-        tracksToAdd.push({
-          engineId: this.engineId,
-          kind: 'CounterTrack',
+      if (refType === 'upid') counterUpids.add(ref);
+      if (refType === 'utid') counterUtids.add(ref);
+    }
+
+    // Add all the global counter tracks that are not bound to any pid/tid,
+    // the ones for which refType == NULL.
+    for (let i = 0; i < counters.numRecords; i++) {
+      const name = counters.columns[0].stringValues![i];
+      const refType = counters.columns[2].stringValues![i];
+      if (refType !== '[NULL]') continue;
+      addToTrackActions.push(Actions.addTrack({
+        engineId: this.engineId,
+        kind: 'CounterTrack',
+        name,
+        trackGroup: SCROLLING_TRACK_GROUP,
+        config: {
           name,
-          trackGroup: SCROLLING_TRACK_GROUP,
-          config: {
-            name,
-            ref: 0,
-          }
-        });
-      }
+          ref: 0,
+        }
+      }));
     }
 
     // Local experiments shows getting maxDepth separately is ~2x faster than
     // joining with threads and processes.
-    const maxDepthQuery = await engine.query(`
-          select thread_track.utid, thread_track.id, max(depth) as maxDepth
-          from slice
-          inner join thread_track on slice.track_id = thread_track.id
-          group by thread_track.id
-        `);
+    const maxDepthQuery =
+        await engine.query('select utid, max(depth) from slices group by utid');
 
-    const utidToThreadTrack = new Map<number, ThreadSliceTrack>();
+    const utidToMaxDepth = new Map<number, number>();
     for (let i = 0; i < maxDepthQuery.numRecords; i++) {
       const utid = maxDepthQuery.columns[0].longValues![i] as number;
-      const trackId = maxDepthQuery.columns[1].longValues![i] as number;
-      const maxDepth = maxDepthQuery.columns[2].longValues![i] as number;
-      utidToThreadTrack.set(utid, {maxDepth, trackId});
+      const maxDepth = maxDepthQuery.columns[1].longValues![i] as number;
+      utidToMaxDepth.set(utid, maxDepth);
     }
 
     // Return all threads
@@ -494,13 +350,12 @@
           left join (select upid, sum(dur) as total_dur
               from sched join thread using(utid)
               group by upid
-            ) using(upid)
-        where utid != 0
-        group by utid, upid
+            ) using(upid) group by utid, upid
         order by total_dur desc, upid, utid`);
 
     const upidToUuid = new Map<number, string>();
     const utidToUuid = new Map<number, string>();
+    const addSummaryTrackActions: DeferredAction[] = [];
     const addTrackGroupActions: DeferredAction[] = [];
 
     for (const row of rawQueryToRows(threadQuery, {
@@ -523,18 +378,15 @@
           await engine.query(`select count(1) from sched where utid = ${utid}`);
       const threadHasSched = threadSched.columns[0].longValues![0] > 0;
 
-      const threadTrack =
-          utid === null ? undefined : utidToThreadTrack.get(utid);
-      if (threadTrack === undefined &&
-          (upid === null || counterUpids[upid] === undefined) &&
-          counterUtids[utid] === undefined && !threadHasSched &&
-          (upid === null || upid !== null && !heapUpids.has(upid))) {
+      const maxDepth = utid === null ? undefined : utidToMaxDepth.get(utid);
+      if (maxDepth === undefined &&
+          (upid === null || !counterUpids.has(upid)) &&
+          !counterUtids.has(utid) && !threadHasSched) {
         continue;
       }
 
       // Group by upid if present else by utid.
       let pUuid = upid === null ? utidToUuid.get(utid) : upidToUuid.get(upid);
-      // These should only happen once for each track group.
       if (pUuid === undefined) {
         pUuid = uuidv4();
         const summaryTrackId = uuidv4();
@@ -547,125 +399,94 @@
         const pidForColor = pid || tid || upid || utid || 0;
         const kind = hasSchedEvents ? PROCESS_SCHEDULING_TRACK_KIND :
                                       PROCESS_SUMMARY_TRACK;
-
-        tracksToAdd.push({
+        addSummaryTrackActions.push(Actions.addTrack({
           id: summaryTrackId,
           engineId: this.engineId,
           kind,
           name: `${upid === null ? tid : pid} summary`,
           config: {pidForColor, upid, utid},
-        });
+        }));
 
-        const name = upid === null ?
-            `${threadName} ${tid}` :
-            `${
-                processName === null && heapUpids.has(upid) ?
-                    'Heap Profile for' :
-                    processName} ${pid}`;
         addTrackGroupActions.push(Actions.addTrackGroup({
           engineId: this.engineId,
           summaryTrackId,
-          name,
+          name: upid === null ? `${threadName} ${tid}` :
+                                `${processName} ${pid}`,
           id: pUuid,
-          collapsed: !(upid !== null && heapUpids.has(upid)),
+          collapsed: true,
         }));
 
-        if (upid !== null) {
-          const counterNames = counterUpids[upid];
-          if (counterNames !== undefined) {
-            counterNames.forEach(element => {
-              tracksToAdd.push({
-                engineId: this.engineId,
-                kind: 'CounterTrack',
-                name: element,
-                trackGroup: pUuid,
-                config: {
-                  name: element,
-                  ref: upid,
-                }
-              });
-            });
-          }
-
-          if (heapUpids.has(upid)) {
-            tracksToAdd.push({
-              engineId: this.engineId,
-              kind: HEAP_PROFILE_TRACK_KIND,
-              name: `Heap Profile`,
-              trackGroup: pUuid,
-              config: {upid}
-            });
-
-            tracksToAdd.push({
-              engineId: this.engineId,
-              kind: HEAP_PROFILE_FLAMEGRAPH_TRACK_KIND,
-              name: `Heap Profile Flamegraph`,
-              trackGroup: pUuid,
-              config: {upid}
-            });
-          }
-
-          if (upidToProcessTracks.has(upid)) {
-            for (const track of upidToProcessTracks.get(upid)) {
-              tracksToAdd.push(Object.assign(track, {trackGroup: pUuid}));
-            }
-          }
-        }
-      }
-      const counterThreadNames = counterUtids[utid];
-      if (counterThreadNames !== undefined) {
-        counterThreadNames.forEach(element => {
-          tracksToAdd.push({
+        for (let i = 0; i < counters.numRecords; i++) {
+          const name = counters.columns[0].stringValues![i];
+          const ref = counters.columns[1].longValues![i];
+          const refType = counters.columns[2].stringValues![i];
+          if (refType !== 'upid' || ref !== upid) continue;
+          addTrackGroupActions.push(Actions.addTrack({
             engineId: this.engineId,
             kind: 'CounterTrack',
-            name: element,
+            name,
             trackGroup: pUuid,
             config: {
-              name: element,
-              ref: utid,
+              name,
+              ref,
             }
-          });
-        });
+          }));
+        }
       }
+
+      for (let i = 0; i < counters.numRecords; i++) {
+        const name = counters.columns[0].stringValues![i];
+        const ref = counters.columns[1].longValues![i];
+        const refType = counters.columns[2].stringValues![i];
+
+        if (refType !== 'utid' || ref !== utid) continue;
+        addTrackGroupActions.push(Actions.addTrack({
+          engineId: this.engineId,
+          kind: 'CounterTrack',
+          name,
+          trackGroup: pUuid,
+          config: {
+            name,
+            ref,
+          }
+        }));
+      }
+
       if (threadHasSched) {
-        tracksToAdd.push({
+        addToTrackActions.push(Actions.addTrack({
           engineId: this.engineId,
           kind: THREAD_STATE_TRACK_KIND,
           name: `${threadName} [${tid}]`,
           trackGroup: pUuid,
           config: {utid}
-        });
+        }));
       }
 
-      if (threadTrack !== undefined) {
-        tracksToAdd.push({
+      if (maxDepth !== undefined) {
+        addToTrackActions.push(Actions.addTrack({
           engineId: this.engineId,
           kind: SLICE_TRACK_KIND,
           name: `${threadName} [${tid}]`,
           trackGroup: pUuid,
-          config: {
-            upid,
-            utid,
-            maxDepth: threadTrack.maxDepth,
-            trackId: threadTrack.trackId
-          },
-        });
+          config: {upid, utid, maxDepth},
+        }));
       }
     }
 
     const logCount = await engine.query(`select count(1) from android_logs`);
     if (logCount.columns[0].longValues![0] > 0) {
-      tracksToAdd.push({
+      addToTrackActions.push(Actions.addTrack({
         engineId: this.engineId,
         kind: ANDROID_LOGS_TRACK_KIND,
         name: 'Android logs',
         trackGroup: SCROLLING_TRACK_GROUP,
         config: {}
-      });
+      }));
     }
 
-    addTrackGroupActions.push(Actions.addTracks({tracks: tracksToAdd}));
-    globals.dispatchMultiple(addTrackGroupActions);
+    const allActions =
+        addSummaryTrackActions.concat(addTrackGroupActions, addToTrackActions);
+    globals.dispatchMultiple(allActions);
   }
 
   private async listThreads() {
@@ -674,9 +495,7 @@
         ifnull(
           case when length(process.name) > 0 then process.name else null end,
           thread.name)
-        from (select * from thread order by upid) as thread
-        left join (select * from process order by upid) as process
-        using(upid)`;
+        from thread left join process using(upid)`;
     const threadRows = await assertExists(this.engine).query(sqlQuery);
     const threads: ThreadDesc[] = [];
     for (let i = 0; i < threadRows.numRecords; i++) {
@@ -700,9 +519,9 @@
           'Loading overview ' +
           `${Math.round((step + 1) / numSteps * 1000) / 10}%`);
       const startSec = traceTime.start + step * stepSec;
-      const startNs = toNsFloor(startSec);
+      const startNs = Math.floor(startSec * 1e9);
       const endSec = startSec + stepSec;
-      const endNs = toNsCeil(endSec);
+      const endNs = Math.ceil(endSec * 1e9);
 
       // Sched overview.
       const schedRows = await engine.query(
@@ -724,23 +543,14 @@
     }
 
     // Slices overview.
-    const traceStartNs = toNs(traceTime.start);
-    const stepSecNs = toNs(stepSec);
-    const sliceSummaryQuery = await engine.query(`select
-           bucket,
-           upid,
-           sum(utid_sum) / cast(${stepSecNs} as float) as upid_sum
-         from thread
-         inner join (
-           select
-             cast((ts - ${traceStartNs})/${stepSecNs} as int) as bucket
-             sum(dur) as utid_sum,
-             utid
-           from slice
-           inner join thread_track on slice.track_id = thread_track.id
-           group by bucket, utid
-         ) using(utid)
-         group by bucket, upid`);
+    const traceStartNs = traceTime.start * 1e9;
+    const stepSecNs = stepSec * 1e9;
+    const sliceSummaryQuery = await engine.query(
+        `select bucket, upid, sum(utid_sum) / cast(${stepSecNs} as float) ` +
+        `as upid_sum from thread inner join ` +
+        `(select cast((ts - ${traceStartNs})/${stepSecNs} as int) as bucket, ` +
+        `sum(dur) as utid_sum, utid from slices group by bucket, utid) ` +
+        `using(utid) group by bucket, upid`);
 
     const slicesData: {[key: string]: QuantizedLoad[]} = {};
     for (let i = 0; i < sliceSummaryQuery.numRecords; i++) {
diff --git a/ui/src/controller/trace_converter.ts b/ui/src/controller/trace_converter.ts
index 2a5b787..865ee50 100644
--- a/ui/src/controller/trace_converter.ts
+++ b/ui/src/controller/trace_converter.ts
@@ -13,12 +13,11 @@
 // limitations under the License.
 
 import {Actions} from '../common/actions';
-import {TraceSource} from '../common/state';
 import * as trace_to_text from '../gen/trace_to_text';
 
 import {globals} from './globals';
 
-export function ConvertTrace(trace: Blob, truncate?: 'start'|'end') {
+export function ConvertTrace(trace: Blob) {
   const mod = trace_to_text({
     noInitialRun: true,
     locateFile: (s: string) => s,
@@ -27,12 +26,7 @@
     onRuntimeInitialized: () => {
       updateStatus('Converting trace');
       const outPath = '/trace.json';
-      if (truncate === undefined) {
-        mod.callMain(['json', '/fs/trace.proto', outPath]);
-      } else {
-        mod.callMain(
-            ['json', '--truncate', truncate, '/fs/trace.proto', outPath]);
-      }
+      mod.callMain(['json', '/fs/trace.proto', outPath]);
       updateStatus('Trace conversion completed');
       const fsNode = mod.FS.lookupPath(outPath).node;
       const data = fsNode.contents.buffer;
@@ -54,76 +48,6 @@
   (self as {} as {mod: {}}).mod = mod;
 }
 
-export async function ConvertTraceToPprof(
-    pid: number, src: TraceSource, ts1: number, ts2?: number) {
-  generateBlob(src).then(result => {
-    const mod = trace_to_text({
-      noInitialRun: true,
-      locateFile: (s: string) => s,
-      print: updateStatus,
-      printErr: updateStatus,
-      onRuntimeInitialized: () => {
-        updateStatus('Converting trace');
-        const timestamps = `${ts1}${ts2 === undefined ? '' : `,${ts2}`}`;
-        mod.callMain([
-          'profile',
-          `--pid`,
-          `${pid}`,
-          `--timestamps`,
-          timestamps,
-          '/fs/trace.proto'
-        ]);
-        updateStatus('Trace conversion completed');
-        const heapDirName =
-            Object.keys(mod.FS.lookupPath('/tmp/').node.contents)[0];
-        const heapDirContents =
-            mod.FS.lookupPath(`/tmp/${heapDirName}`).node.contents;
-        const heapDumpFiles = Object.keys(heapDirContents);
-        let fileNum = 0;
-        heapDumpFiles.forEach(heapDump => {
-          const fileContents =
-              mod.FS.lookupPath(`/tmp/${heapDirName}/${heapDump}`)
-                  .node.contents;
-          fileNum++;
-          const fileName = `/heap_dump.${fileNum}.${pid}.pb`;
-          downloadFile(new Blob([fileContents]), fileName);
-        });
-        updateStatus('Profile(s) downloaded');
-      },
-      onAbort: () => {
-        console.log('ABORT');
-      },
-    });
-    mod.FS.mkdir('/fs');
-    mod.FS.mount(
-        mod.FS.filesystems.WORKERFS,
-        {blobs: [{name: 'trace.proto', data: result}]},
-        '/fs');
-  });
-}
-
-async function generateBlob(src: TraceSource) {
-  let blob: Blob = new Blob();
-  if (src.type === 'URL') {
-    const resp = await fetch(src.url);
-    if (resp.status !== 200) {
-      throw new Error(`fetch() failed with HTTP error ${resp.status}`);
-    }
-    blob = await resp.blob();
-  } else if (src.type === 'ARRAY_BUFFER') {
-    blob = new Blob([new Uint8Array(src.buffer, 0, src.buffer.byteLength)]);
-  } else if (src.type === 'FILE') {
-    blob = src.file;
-  } else {
-    throw new Error(`Conversion not supported for ${JSON.stringify(src)}`);
-  }
-  return blob;
-}
-
-function downloadFile(file: Blob, name: string) {
-  globals.publish('FileDownload', {file, name});
-}
-
 function updateStatus(msg: {}) {
   console.log(msg);
   globals.dispatch(Actions.updateStatus({
diff --git a/ui/src/controller/trace_stream.ts b/ui/src/controller/trace_stream.ts
deleted file mode 100644
index 75ef8d4..0000000
--- a/ui/src/controller/trace_stream.ts
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {defer, Deferred} from '../base/deferred';
-import {assertExists, assertTrue} from '../base/logging';
-
-const SLICE_SIZE = 32 * 1024 * 1024;
-
-// The object returned by TraceStream.readChunk() promise.
-export interface TraceChunk {
-  data: Uint8Array;
-  eof: boolean;
-  bytesRead: number;
-  bytesTotal: number;
-}
-
-// Base interface for loading trace data in chunks.
-// The caller has to call readChunk() until TraceChunk.eof == true.
-export interface TraceStream {
-  readChunk(): Promise<TraceChunk>;
-}
-
-// Loads a trace from a File object. For the "open file" use case.
-export class TraceFileStream implements TraceStream {
-  private traceFile: Blob;
-  private reader: FileReader;
-  private pendingRead?: Deferred<TraceChunk>;
-  private bytesRead = 0;
-
-  constructor(traceFile: Blob) {
-    this.traceFile = traceFile;
-    this.reader = new FileReader();
-    this.reader.onloadend = () => this.onLoad();
-  }
-
-  onLoad() {
-    const res = assertExists(this.reader.result) as ArrayBuffer;
-    const pendingRead = assertExists(this.pendingRead);
-    this.pendingRead = undefined;
-    if (this.reader.error) {
-      pendingRead.reject(this.reader.error);
-      return;
-    }
-    this.bytesRead += res.byteLength;
-    pendingRead.resolve({
-      data: new Uint8Array(res),
-      eof: this.bytesRead >= this.traceFile.size,
-      bytesRead: this.bytesRead,
-      bytesTotal: this.traceFile.size,
-    });
-  }
-
-  readChunk(): Promise<TraceChunk> {
-    const sliceEnd = Math.min(this.bytesRead + SLICE_SIZE, this.traceFile.size);
-    const slice = this.traceFile.slice(this.bytesRead, sliceEnd);
-    this.pendingRead = defer<TraceChunk>();
-    this.reader.readAsArrayBuffer(slice);
-    return this.pendingRead;
-  }
-}
-
-// Loads a trace from an ArrayBuffer. For the window.open() + postMessage
-// use-case, used by other dashboards (see post_message_handler.ts).
-export class TraceBufferStream implements TraceStream {
-  private traceBuf: ArrayBuffer;
-  private bytesRead = 0;
-
-  constructor(traceBuf: ArrayBuffer) {
-    this.traceBuf = traceBuf;
-  }
-
-  readChunk(): Promise<TraceChunk> {
-    assertTrue(this.bytesRead <= this.traceBuf.byteLength);
-    const len = Math.min(SLICE_SIZE, this.traceBuf.byteLength - this.bytesRead);
-    const data = new Uint8Array(this.traceBuf, this.bytesRead, len);
-    this.bytesRead += len;
-    return Promise.resolve({
-      data,
-      eof: this.bytesRead >= this.traceBuf.byteLength,
-      bytesRead: this.bytesRead,
-      bytesTotal: this.traceBuf.byteLength,
-    });
-  }
-}
-
-// Loads a stream from a URL via fetch(). For the permalink (?s=UUID) and
-// open url (?url=http://...) cases.
-export class TraceHttpStream implements TraceStream {
-  private bytesRead = 0;
-  private bytesTotal = 0;
-  private uri: string;
-  private httpStream?: ReadableStreamReader;
-
-  constructor(uri: string) {
-    assertTrue(uri.startsWith('http://') || uri.startsWith('https://'));
-    this.uri = uri;
-  }
-
-  async readChunk(): Promise<TraceChunk> {
-    // Initialize the fetch() job on the first read request.
-    if (this.httpStream === undefined) {
-      const response = await fetch(this.uri);
-      if (response.status !== 200) {
-        throw new Error(`HTTP ${response.status} - ${response.statusText}`);
-      }
-      const len = response.headers.get('Content-Length');
-      this.bytesTotal = len ? Number.parseInt(len, 10) : 0;
-      // tslint:disable-next-line no-any
-      this.httpStream = (response.body as any).getReader();
-    }
-
-    const res =
-        (await this.httpStream!.read()) as {value?: Uint8Array, done: boolean};
-    const data = res.value ? res.value : new Uint8Array();
-    this.bytesRead += data.length;
-    return {
-      data,
-      eof: res.done,
-      bytesRead: this.bytesRead,
-      bytesTotal: this.bytesTotal,
-    };
-  }
-}
diff --git a/ui/src/controller/track_controller.ts b/ui/src/controller/track_controller.ts
index d036d62..894faee 100644
--- a/ui/src/controller/track_controller.ts
+++ b/ui/src/controller/track_controller.ts
@@ -13,26 +13,21 @@
 // limitations under the License.
 
 import {assertExists} from '../base/logging';
+import {Actions} from '../common/actions';
 import {Engine} from '../common/engine';
 import {Registry} from '../common/registry';
-import {TraceTime, TrackState} from '../common/state';
-import {LIMIT, TrackData} from '../common/track_data';
+import {TrackState} from '../common/state';
 
 import {Controller} from './controller';
 import {ControllerFactory} from './controller';
 import {globals} from './globals';
 
-
 // TrackController is a base class overridden by track implementations (e.g.,
 // sched slices, nestable slices, counters).
-export abstract class TrackController<Config = {},
-                                      Data extends TrackData = TrackData>
-    extends Controller<'main'> {
+export abstract class TrackController<Config = {}, Data = {}> extends
+    Controller<'main'> {
   readonly trackId: string;
   readonly engine: Engine;
-  private data?: TrackData;
-  private requestingData = false;
-  private queuedRequest = false;
 
   constructor(args: TrackControllerArgs) {
     super('main');
@@ -43,8 +38,7 @@
   // Must be overridden by the track implementation. Is invoked when the track
   // frontend runs out of cached data. The derived track controller is expected
   // to publish new track data in response to this call.
-  abstract async onBoundsChange(start: number, end: number, resolution: number):
-      Promise<Data>;
+  abstract onBoundsChange(start: number, end: number, resolution: number): void;
 
   get trackState(): TrackState {
     return assertExists(globals.state.tracks[this.trackId]);
@@ -55,7 +49,6 @@
   }
 
   publish(data: Data): void {
-    this.data = data;
     globals.publish('TrackData', {id: this.trackId, data});
   }
 
@@ -76,66 +69,11 @@
     return resolution >= 0.0008;
   }
 
-  protected async query(query: string) {
-    const result = await this.engine.query(query);
-    if (result.error) {
-      console.error(`Query error "${query}": ${result.error}`);
-      throw new Error(`Query error "${query}": ${result.error}`);
-    }
-    return result;
-  }
-
-  shouldRequestData(traceTime: TraceTime): boolean {
-    if (this.data === undefined) return true;
-
-    // If at the limit only request more data if the view has moved.
-    const atLimit = this.data.length === LIMIT;
-    if (atLimit) {
-      // We request more data than the window, so add window duration to find
-      // the previous window.
-      const prevWindowStart =
-          this.data.start + (traceTime.startSec - traceTime.endSec);
-      return traceTime.startSec !== prevWindowStart;
-    }
-
-    // Otherwise request more data only when out of range of current data or
-    // resolution has changed.
-    const inRange = traceTime.startSec >= this.data.start &&
-        traceTime.endSec <= this.data.end;
-    return !inRange ||
-        this.data.resolution !==
-        globals.state.frontendLocalState.visibleState.resolution;
-  }
-
   run() {
-    const visibleState = globals.state.frontendLocalState.visibleState;
-    if (visibleState === undefined) return;
-    const dur = visibleState.endSec - visibleState.startSec;
-    if (globals.state.visibleTracks.includes(this.trackId) &&
-        this.shouldRequestData(visibleState)) {
-      if (this.requestingData) {
-        this.queuedRequest = true;
-      } else {
-        this.requestingData = true;
-        this.onBoundsChange(
-                visibleState.startSec - dur,
-                visibleState.endSec + dur,
-                visibleState.resolution)
-            .then(data => {
-              this.publish(data);
-            })
-            .catch(error => {
-              console.error(error);
-            })
-            .finally(() => {
-              this.requestingData = false;
-              if (this.queuedRequest) {
-                this.queuedRequest = false;
-                this.run();
-              }
-            });
-      }
-    }
+    const dataReq = this.trackState.dataReq;
+    if (dataReq === undefined) return;
+    globals.dispatch(Actions.clearTrackDataReq({trackId: this.trackId}));
+    this.onBoundsChange(dataReq.start, dataReq.end, dataReq.resolution);
   }
 }
 
diff --git a/ui/src/engine/wasm_bridge.ts b/ui/src/engine/wasm_bridge.ts
index 97a3692..129432f 100644
--- a/ui/src/engine/wasm_bridge.ts
+++ b/ui/src/engine/wasm_bridge.ts
@@ -16,27 +16,21 @@
 import {assertExists, assertTrue} from '../base/logging';
 import * as init_trace_processor from '../gen/trace_processor';
 
-// The Initialize() call will allocate a buffer of REQ_BUF_SIZE bytes which
-// will be used to copy the input request data. This is to avoid passing the
-// input data on the stack, which has a limited (~1MB) size.
-// The buffer will be allocated by the C++ side and reachable at
-// HEAPU8[reqBufferAddr, +REQ_BUFFER_SIZE].
-const REQ_BUF_SIZE = 32 * 1024 * 1024;
-
 function writeToUIConsole(line: string) {
   console.log(line);
 }
 
 export interface WasmBridgeRequest {
   id: number;
+  serviceName: string;
   methodName: string;
   data: Uint8Array;
 }
 
 export interface WasmBridgeResponse {
   id: number;
-  aborted: boolean;  // If true the WASM module crashed.
-  data: Uint8Array;
+  success: boolean;
+  data?: Uint8Array;
 }
 
 export class WasmBridge {
@@ -46,7 +40,6 @@
   private aborted: boolean;
   private currentRequestResult: WasmBridgeResponse|null;
   private connection: init_trace_processor.Module;
-  private reqBufferAddr = 0;
 
   constructor(init: init_trace_processor.InitWasm) {
     this.aborted = false;
@@ -61,12 +54,8 @@
       onAbort: () => this.aborted = true,
     });
     this.whenInitialized = deferredRuntimeInitialized.then(() => {
-      const fn = this.connection.addFunction(this.onReply.bind(this), 'iii');
-      this.reqBufferAddr = this.connection.ccall(
-          'Initialize',
-          /*return=*/ 'number',
-          /*args=*/['number', 'number'],
-          [fn, REQ_BUF_SIZE]);
+      const fn = this.connection.addFunction(this.onReply.bind(this), 'viiii');
+      this.connection.ccall('Initialize', 'void', ['number'], [fn]);
     });
   }
 
@@ -74,32 +63,33 @@
     if (this.aborted) {
       return {
         id: req.id,
-        aborted: true,
-        data: new Uint8Array(),
+        success: false,
+        data: undefined,
       };
     }
-    assertTrue(req.data.length <= REQ_BUF_SIZE);
-    const endAddr = this.reqBufferAddr + req.data.length;
-    this.connection.HEAPU8.subarray(this.reqBufferAddr, endAddr).set(req.data);
+    // TODO(b/124805622): protoio can generate CamelCase names - normalize.
+    const methodName = req.methodName;
+    const name = methodName.charAt(0).toLowerCase() + methodName.slice(1);
     this.connection.ccall(
-        req.methodName,    // C method name.
-        'void',            // Return type.
-        ['number'],        // Arg types.
-        [req.data.length]  // Args.
-    );
+        `${req.serviceName}_${name}`,        // C method name.
+        'void',                              // Return type.
+        ['number', 'array', 'number'],       // Input args.
+        [req.id, req.data, req.data.length]  // Args.
+        );
 
     const result = assertExists(this.currentRequestResult);
+    assertTrue(req.id === result.id);
     this.currentRequestResult = null;
-    result.id = req.id;
     return result;
   }
 
   // This is invoked from ccall in the same call stack as callWasm.
-  private onReply(heapPtr: number, size: number) {
+  private onReply(
+      reqId: number, success: boolean, heapPtr: number, size: number) {
     const data = this.connection.HEAPU8.slice(heapPtr, heapPtr + size);
     this.currentRequestResult = {
-      id: 0,  // Will be set by callWasm()'s epilogue.
-      aborted: false,
+      id: reqId,
+      success,
       data,
     };
   }
diff --git a/ui/src/frontend/aggregation_panel.ts b/ui/src/frontend/aggregation_panel.ts
deleted file mode 100644
index 17ec194..0000000
--- a/ui/src/frontend/aggregation_panel.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use size 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.
-
-import * as m from 'mithril';
-import {Panel} from './panel';
-
-export class AggregationPanel extends Panel {
-  view() {
-    return m('.details-panel', m('.details-panel-heading', 'Work in Progress'));
-  }
-
-  renderCanvas() {}
-}
\ No newline at end of file
diff --git a/ui/src/frontend/checkerboard.ts b/ui/src/frontend/checkerboard.ts
index 6ae9487..d6dc768 100644
--- a/ui/src/frontend/checkerboard.ts
+++ b/ui/src/frontend/checkerboard.ts
@@ -12,33 +12,26 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-const LOADING_TEXT = 'Loading...';
-let LOADING_TEXT_WIDTH = 0;
+// TODO(hjd): Dedupe these.
+const SLICE_HEIGHT = 32;
+const TRACK_PADDING = 5;
 
 /**
  * Checker board the range [leftPx, rightPx].
  */
 export function checkerboard(
-    ctx: CanvasRenderingContext2D,
-    heightPx: number,
-    leftPx: number,
-    rightPx: number): void {
+    ctx: CanvasRenderingContext2D, leftPx: number, rightPx: number): void {
   const widthPx = rightPx - leftPx;
   ctx.font = '12px Google Sans';
   ctx.fillStyle = '#eee';
-  ctx.fillRect(leftPx, 0, widthPx, heightPx);
+  ctx.fillRect(leftPx, TRACK_PADDING, widthPx, SLICE_HEIGHT);
   ctx.fillStyle = '#666';
-  const oldBaseline = ctx.textBaseline;
-  ctx.textBaseline = 'middle';
-  if (LOADING_TEXT_WIDTH === 0) {
-    LOADING_TEXT_WIDTH = ctx.measureText(LOADING_TEXT).width;
-  }
+  ctx.textBaseline = 'alphabetic';
   ctx.fillText(
-      LOADING_TEXT,
-      leftPx + widthPx / 2 - LOADING_TEXT_WIDTH,
-      heightPx / 2,
+      'loading...',
+      leftPx + widthPx / 2,
+      TRACK_PADDING + SLICE_HEIGHT / 2,
       widthPx);
-  ctx.textBaseline = oldBaseline;
 }
 
 /**
@@ -46,24 +39,23 @@
  */
 export function checkerboardExcept(
     ctx: CanvasRenderingContext2D,
-    heightPx: number,
     startPx: number,
     endPx: number,
     leftPx: number,
     rightPx: number): void {
   // [leftPx, rightPx] doesn't overlap [startPx, endPx] at all:
   if (rightPx <= startPx || leftPx >= endPx) {
-    checkerboard(ctx, heightPx, startPx, endPx);
+    checkerboard(ctx, startPx, endPx);
     return;
   }
 
   // Checkerboard [startPx, leftPx]:
   if (leftPx > startPx) {
-    checkerboard(ctx, heightPx, startPx, leftPx);
+    checkerboard(ctx, startPx, leftPx);
   }
 
   // Checkerboard [rightPx, endPx]:
   if (rightPx < endPx) {
-    checkerboard(ctx, heightPx, rightPx, endPx);
+    checkerboard(ctx, rightPx, endPx);
   }
 }
diff --git a/ui/src/frontend/chrome_slice_panel.ts b/ui/src/frontend/chrome_slice_panel.ts
deleted file mode 100644
index 97ce65c..0000000
--- a/ui/src/frontend/chrome_slice_panel.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use size 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.
-
-import * as m from 'mithril';
-
-import {timeToCode} from '../common/time';
-
-import {globals} from './globals';
-import {Panel, PanelSize} from './panel';
-
-export class ChromeSliceDetailsPanel extends Panel {
-  view() {
-    const sliceInfo = globals.sliceDetails;
-    if (sliceInfo.ts && sliceInfo.dur && sliceInfo.name) {
-      return m(
-          '.details-panel',
-          m('.details-panel-heading', `Slice Details:`),
-          m(
-              '.details-table',
-              [m('table',
-                 [
-                   m('tr', m('th', `Name`), m('td', `${sliceInfo.name}`)),
-                   (sliceInfo.category === '[NULL]') ?
-                       null :
-                       m('tr',
-                         m('th', `Category`),
-                         m('td', `${sliceInfo.category}`)),
-                   m('tr',
-                     m('th', `Start time`),
-                     m('td', `${timeToCode(sliceInfo.ts)}`)),
-                   m('tr',
-                     m('th', `Duration`),
-                     m('td', `${timeToCode(sliceInfo.dur)}`))
-                 ])],
-              ));
-    } else {
-      return m(
-          '.details-panel',
-          m(
-              '.details-panel-heading',
-              `Slice Details:`,
-              ));
-    }
-  }
-  renderCanvas(_ctx: CanvasRenderingContext2D, _size: PanelSize) {}
-}
diff --git a/ui/src/frontend/colorizer.ts b/ui/src/frontend/colorizer.ts
index 5fa6681..e42f42c 100644
--- a/ui/src/frontend/colorizer.ts
+++ b/ui/src/frontend/colorizer.ts
@@ -13,7 +13,6 @@
 // limitations under the License.
 
 import {ThreadDesc} from './globals';
-import {hsl} from 'color-convert';
 
 export interface Color {
   c: string;
@@ -89,9 +88,3 @@
   const tid = thread.pid ? thread.pid : thread.tid;
   return colorForTid(tid);
 }
-
-// 40 different random hues 9 degrees apart.
-export function randomColor(): string {
-  const hue = Math.floor(Math.random() * 40) * 9;
-  return '#' + hsl.hex([hue, 90, 30]);
-}
diff --git a/ui/src/frontend/counter_panel.ts b/ui/src/frontend/counter_panel.ts
deleted file mode 100644
index 458a037..0000000
--- a/ui/src/frontend/counter_panel.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use size 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.
-
-import * as m from 'mithril';
-
-import {fromNs, timeToCode} from '../common/time';
-
-import {globals} from './globals';
-import {Panel} from './panel';
-
-interface CounterDetailsPanelAttrs {}
-
-export class CounterDetailsPanel extends Panel<CounterDetailsPanelAttrs> {
-  view() {
-    const counterInfo = globals.counterDetails;
-    if (counterInfo && counterInfo.startTime &&
-        counterInfo.value !== undefined && counterInfo.delta !== undefined &&
-        counterInfo.duration !== undefined) {
-      return m(
-          '.details-panel',
-          m('.details-panel-heading', `Counter Details:`),
-          m(
-              '.details-table',
-              [m('table',
-                 [
-                   m('tr',
-                     m('th', `Start time`),
-                     m('td', `${timeToCode(counterInfo.startTime)}`)),
-                   m('tr',
-                     m('th', `Value`),
-                     m('td', `${counterInfo.value.toLocaleString()}`)),
-                   m('tr',
-                     m('th', `Delta`),
-                     m('td', `${counterInfo.delta.toLocaleString()}`)),
-                   m('tr',
-                     m('th', `Duration`),
-                     m('td', `${timeToCode(fromNs(counterInfo.duration))}`)),
-                 ])],
-              ));
-    } else {
-      return m(
-          '.details-panel', m('.details-panel-heading', `Counter Details:`));
-    }
-  }
-
-  renderCanvas() {}
-}
diff --git a/ui/src/frontend/details_panel.ts b/ui/src/frontend/details_panel.ts
deleted file mode 100644
index 628af84..0000000
--- a/ui/src/frontend/details_panel.ts
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright (C) 2019 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.
-
-import * as m from 'mithril';
-
-import {LogExists, LogExistsKey} from '../common/logs';
-
-import {AggregationPanel} from './aggregation_panel';
-import {ChromeSliceDetailsPanel} from './chrome_slice_panel';
-import {CounterDetailsPanel} from './counter_panel';
-import {DragGestureHandler} from './drag_gesture_handler';
-import {globals} from './globals';
-import {HeapProfileDetailsPanel} from './heap_profile_panel';
-import {LogPanel} from './logs_panel';
-import {NotesEditorPanel} from './notes_panel';
-import {AnyAttrsVnode, PanelContainer} from './panel_container';
-import {SliceDetailsPanel} from './slice_panel';
-import {ThreadStatePanel} from './thread_state_panel';
-
-const UP_ICON = 'keyboard_arrow_up';
-const DOWN_ICON = 'keyboard_arrow_down';
-const DRAG_HANDLE_HEIGHT_PX = 28;
-const DEFAULT_DETAILS_HEIGHT_PX = 230 + DRAG_HANDLE_HEIGHT_PX;
-
-function hasLogs(): boolean {
-  const data = globals.trackDataStore.get(LogExistsKey) as LogExists;
-  return data && data.exists;
-}
-
-interface DragHandleAttrs {
-  height: number;
-  resize: (height: number) => void;
-  tabs: Tab[];
-}
-
-export type Tab = 'current_selection'|'time_range'|'android_logs';
-
-class DragHandle implements m.ClassComponent<DragHandleAttrs> {
-  private dragStartHeight = 0;
-  private height = 0;
-  private resize: (height: number) => void = () => {};
-  private isClosed = this.height <= DRAG_HANDLE_HEIGHT_PX;
-  private tabNames = new Map<Tab, string>([
-    ['current_selection', 'Current Selection'],
-    ['time_range', 'Time Range'],
-    ['android_logs', 'Android Logs']
-  ]);
-
-
-  oncreate({dom, attrs}: m.CVnodeDOM<DragHandleAttrs>) {
-    this.resize = attrs.resize;
-    this.height = attrs.height;
-    this.isClosed = this.height <= DRAG_HANDLE_HEIGHT_PX;
-    const elem = dom as HTMLElement;
-    new DragGestureHandler(
-        elem,
-        this.onDrag.bind(this),
-        this.onDragStart.bind(this),
-        this.onDragEnd.bind(this));
-  }
-
-  onupdate({attrs}: m.CVnodeDOM<DragHandleAttrs>) {
-    this.resize = attrs.resize;
-    this.height = attrs.height;
-    this.isClosed = this.height <= DRAG_HANDLE_HEIGHT_PX;
-  }
-
-  onDrag(_x: number, y: number) {
-    const newHeight = this.dragStartHeight + (DRAG_HANDLE_HEIGHT_PX / 2) - y;
-    this.isClosed = Math.floor(newHeight) <= DRAG_HANDLE_HEIGHT_PX;
-    this.resize(Math.floor(newHeight));
-    globals.rafScheduler.scheduleFullRedraw();
-  }
-
-  onDragStart(_x: number, _y: number) {
-    this.dragStartHeight = this.height;
-  }
-
-  onDragEnd() {}
-
-  view({attrs}: m.CVnode<DragHandleAttrs>) {
-    const icon = this.isClosed ? UP_ICON : DOWN_ICON;
-    const title = this.isClosed ? 'Show panel' : 'Hide panel';
-    const renderTab = (key: Tab) => {
-      if (globals.frontendLocalState.currentTab === key ||
-          globals.frontendLocalState.currentTab === undefined &&
-              attrs.tabs[0] === key) {
-        return m('.tab[active]', this.tabNames.get(key));
-      }
-      return m(
-          '.tab',
-          {
-            onclick: () => {
-              globals.frontendLocalState.currentTab = key;
-              globals.rafScheduler.scheduleFullRedraw();
-            }
-          },
-          this.tabNames.get(key));
-    };
-    return m(
-        '.handle',
-        m('.tabs', attrs.tabs.map(renderTab)),
-        m('i.material-icons',
-          {
-            onclick: () => {
-              if (this.height === DRAG_HANDLE_HEIGHT_PX) {
-                this.isClosed = false;
-                this.resize(DEFAULT_DETAILS_HEIGHT_PX);
-              } else {
-                this.isClosed = true;
-                this.resize(DRAG_HANDLE_HEIGHT_PX);
-              }
-              globals.rafScheduler.scheduleFullRedraw();
-            },
-            title
-          },
-          icon));
-  }
-}
-
-export class DetailsPanel implements m.ClassComponent {
-  private detailsHeight = DRAG_HANDLE_HEIGHT_PX;
-  // Used to set details panel to default height on selection.
-  private showDetailsPanel = true;
-
-  view() {
-    const detailsPanels: Map<Tab, AnyAttrsVnode> = new Map();
-    const curSelection = globals.state.currentSelection;
-    if (curSelection) {
-      switch (curSelection.kind) {
-        case 'NOTE':
-          detailsPanels.set('current_selection', m(NotesEditorPanel, {
-                              key: 'notes',
-                              id: curSelection.id,
-                            }));
-          break;
-        case 'SLICE':
-          detailsPanels.set('current_selection', m(SliceDetailsPanel, {
-                              key: 'slice',
-                            }));
-          break;
-        case 'COUNTER':
-          detailsPanels.set('current_selection', m(CounterDetailsPanel, {
-                              key: 'counter',
-                            }));
-          break;
-        case 'HEAP_PROFILE':
-          detailsPanels.set(
-              'current_selection',
-              m(HeapProfileDetailsPanel, {key: 'heap_profile'}));
-          break;
-        case 'CHROME_SLICE':
-          detailsPanels.set('current_selection', m(ChromeSliceDetailsPanel));
-          break;
-        case 'THREAD_STATE':
-          detailsPanels.set('current_selection', m(ThreadStatePanel, {
-                              key: 'thread_state',
-                              ts: curSelection.ts,
-                              dur: curSelection.dur,
-                              utid: curSelection.utid,
-                              state: curSelection.state,
-                              cpu: curSelection.cpu
-                            }));
-          break;
-        default:
-          break;
-      }
-    }
-    if (hasLogs()) {
-      detailsPanels.set('android_logs', m(LogPanel, {}));
-    }
-
-    if (globals.frontendLocalState.selectedTimeRange.startSec !== undefined &&
-        globals.frontendLocalState.selectedTimeRange.endSec !== undefined) {
-      detailsPanels.set('time_range', m(AggregationPanel));
-    }
-
-    const wasShowing = this.showDetailsPanel;
-    this.showDetailsPanel = detailsPanels.size > 0;
-    // Pop up details panel on first selection.
-    if (!wasShowing && this.showDetailsPanel &&
-        this.detailsHeight === DRAG_HANDLE_HEIGHT_PX) {
-      this.detailsHeight = DEFAULT_DETAILS_HEIGHT_PX;
-    }
-
-    const panel = globals.frontendLocalState.currentTab ?
-        detailsPanels.get(globals.frontendLocalState.currentTab) :
-        detailsPanels.values().next().value;
-    const panels = panel ? [panel] : [];
-
-    return m(
-        '.details-content',
-        {
-          style: {
-            height: `${this.detailsHeight}px`,
-            display: this.showDetailsPanel ? null : 'none'
-          }
-        },
-        m(DragHandle, {
-          resize: (height: number) => {
-            this.detailsHeight = Math.max(height, DRAG_HANDLE_HEIGHT_PX);
-          },
-          height: this.detailsHeight,
-          tabs: [...detailsPanels.keys()],
-        }),
-        m('.details-panel-container',
-          m(PanelContainer, {doesScroll: true, panels, kind: 'DETAILS'})));
-  }
-}
diff --git a/ui/src/frontend/error_dialog.ts b/ui/src/frontend/error_dialog.ts
deleted file mode 100644
index 565cafc..0000000
--- a/ui/src/frontend/error_dialog.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (C) 2019 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.
-
-import * as m from 'mithril';
-
-import {showModal} from './modal';
-
-// Never show more than one dialog per minute.
-const MIN_REPORT_PERIOD_MS = 60000;
-let timeLastReport = 0;
-
-// Keeps the last ERR_QUEUE_MAX_LEN errors while the dialog is throttled.
-const queuedErrors = new Array<string>();
-const ERR_QUEUE_MAX_LEN = 10;
-
-export function maybeShowErrorDialog(errLog: string) {
-  const now = performance.now();
-  if (timeLastReport > 0 && now - timeLastReport <= MIN_REPORT_PERIOD_MS) {
-    queuedErrors.unshift(errLog);
-    if (queuedErrors.length > ERR_QUEUE_MAX_LEN) queuedErrors.pop();
-    console.log('Suppressing crash dialog, last error notified too soon.');
-    return;
-  }
-  timeLastReport = now;
-
-  // Append queued errors.
-  while (queuedErrors.length > 0) {
-    const queuedErr = queuedErrors.shift();
-    errLog += `\n\n---------------------------------------\n${queuedErr}`;
-  }
-
-  const errTitle = errLog.split('\n', 1)[0].substr(0, 80);
-  let link = 'https://goto.google.com/perfetto-ui-bug';
-  link += '?title=' + encodeURIComponent(`UI Error: ${errTitle}`);
-  link += '&description=' + encodeURIComponent(errLog.substr(0, 32768));
-
-  showModal({
-    title: 'Oops, something went wrong. Please file a bug',
-    content: m(
-        'div',
-        m('span', 'An unexpected crash occurred:'),
-        m('.modal-logs', errLog),
-        ),
-    buttons: [
-      {
-        text: 'File a bug (Googlers only)',
-        primary: true,
-        id: 'file_bug',
-        action: () => {
-          window.open(link, '_blank');
-        }
-      },
-    ]
-  });
-}
diff --git a/ui/src/frontend/flamegraph.ts b/ui/src/frontend/flamegraph.ts
deleted file mode 100644
index 3cd0c6c..0000000
--- a/ui/src/frontend/flamegraph.ts
+++ /dev/null
@@ -1,331 +0,0 @@
-// 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.
-
-import {searchSegment} from '../base/binary_search';
-import {cropText} from '../common/canvas_utils';
-
-import {CallsiteInfo} from './globals';
-
-interface Node {
-  width: number;
-  x: number;
-  nextXForChildren: number;
-  size: number;
-}
-
-interface CallsiteInfoWidth {
-  callsite: CallsiteInfo;
-  width: number;
-}
-
-const NODE_HEIGHT_DEFAULT = 15;
-
-export const HEAP_PROFILE_COLOR = 'hsl(224, 45%, 70%)';
-export const HEAP_PROFILE_HOVERED_COLOR = 'hsl(224, 45%, 55%)';
-
-export class Flamegraph {
-  private isThumbnail = false;
-  private flamegraphData: CallsiteInfo[];
-  private maxDepth = -1;
-  private totalSize = -1;
-  private textSize = 12;
-  // Key for the map is depth followed by x coordinate - `depth;x`
-  private graphData: Map<string, CallsiteInfoWidth> = new Map();
-  private xStartsPerDepth: Map<number, number[]> = new Map();
-
-  private hoveredX = -1;
-  private hoveredY = -1;
-  private hoveredCallsite?: CallsiteInfo;
-  private clickedCallsite?: CallsiteInfo;
-
-  // For each node, we use this map to get information about it's parent
-  // (total size of it, width and where it starts in graph) so we can
-  // calculate it's own position in graph.
-  // This one is store for base flamegraph when no clicking has happend.
-  private baseMap = new Map<number, Node>();
-
-  constructor(flamegraphData: CallsiteInfo[]) {
-    this.flamegraphData = flamegraphData;
-    this.findMaxDepth();
-  }
-
-  private findMaxDepth() {
-    this.maxDepth = Math.max(...this.flamegraphData.map(value => value.depth));
-  }
-
-  private findTotalSize() {
-    let totalSize = 0;
-    this.flamegraphData.forEach((value: CallsiteInfo) => {
-      if (value.parentHash === -1) {
-        totalSize += value.totalSize;
-      }
-    });
-    return totalSize;
-  }
-
-  hash(s: string): number {
-    let hash = 0x811c9dc5 & 0xfffffff;
-    for (let i = 0; i < s.length; i++) {
-      hash ^= s.charCodeAt(i);
-      hash = (hash * 16777619) & 0xffffffff;
-    }
-    return hash & 0xff;
-  }
-
-  generateColor(name: string|undefined, isGreyedOut = false): string {
-    if (this.isThumbnail) {
-      return HEAP_PROFILE_COLOR;
-    }
-    if (isGreyedOut) {
-      return '#d9d9d9';
-    }
-    if (name === undefined || name === 'root') {
-      return '#c0c0c0';
-    }
-    const hue = this.hash(name);
-    return `hsl(${hue}, 50%, 65%)`;
-  }
-
-  /**
-   * Caller will have to call draw method ater updating data to have updated
-   * graph.
-   */
-  updateDataIfChanged(flamegraphData: CallsiteInfo[]) {
-    if (this.flamegraphData === flamegraphData) {
-      return;
-    }
-    this.flamegraphData = flamegraphData;
-    this.clickedCallsite = undefined;
-    this.findMaxDepth();
-    // Finding total size of roots.
-    this.totalSize = this.findTotalSize();
-  }
-
-  draw(
-      ctx: CanvasRenderingContext2D, width: number, height: number, x = 0,
-      y = 0, unit = 'B') {
-    // TODO(tneda): Instead of pesimistic approach improve displaying text.
-    const name = '____MMMMMMQQwwZZZZZZzzzzzznnnnnnwwwwwwWWWWWqq$$mmmmmm__';
-    const charWidth = ctx.measureText(name).width / name.length;
-    const nodeHeight = this.getNodeHeight();
-
-    if (this.flamegraphData === undefined) {
-      return;
-    }
-    // For each node, we use this map to get information about it's parent
-    // (total size of it, width and where it starts in graph) so we can
-    // calculate it's own position in graph.
-    const nodesMap = new Map<number, Node>();
-    let currentY = y;
-    nodesMap.set(-1, {width, nextXForChildren: x, size: this.totalSize, x});
-
-    // Initialize data needed for click/hover behaivior.
-    this.graphData = new Map();
-    this.xStartsPerDepth = new Map();
-
-    // Draw root node.
-    ctx.fillStyle = this.generateColor('root', false);
-    ctx.fillRect(x, currentY, width, nodeHeight);
-    currentY += nodeHeight;
-
-    const clickedNode = this.clickedCallsite !== undefined ?
-        this.baseMap.get(this.clickedCallsite.hash) :
-        undefined;
-
-    for (let i = 0; i < this.flamegraphData.length; i++) {
-      if (currentY > height) {
-        break;
-      }
-      const value = this.flamegraphData[i];
-      const parentNode = nodesMap.get(value.parentHash);
-      if (parentNode === undefined) {
-        continue;
-      }
-      // If node is clicked, determine if we should draw current node.
-      let shouldDraw = true;
-      let isFullWidth = false;
-      let isGreyedOut = false;
-
-      const oldNode = this.baseMap.get(value.hash);
-      // We want to display full shape if it's thumbnail.
-      if (!this.isThumbnail && clickedNode !== undefined &&
-          this.clickedCallsite !== undefined && oldNode !== undefined) {
-        isFullWidth = value.depth <= this.clickedCallsite.depth;
-        isGreyedOut = value.depth < this.clickedCallsite.depth;
-        shouldDraw = isFullWidth ? (oldNode.x <= clickedNode.x) &&
-                ((oldNode.x + oldNode.width >=
-                  clickedNode.x + clickedNode.width)) :
-                                   (oldNode.x >= clickedNode.x) &&
-                ((oldNode.x + oldNode.width <=
-                  clickedNode.x + clickedNode.width));
-      }
-
-      if (!shouldDraw) {
-        continue;
-      }
-
-      const parent = value.parentHash;
-      const parentSize = parent === -1 ? this.totalSize : parentNode.size;
-      // Calculate node's width based on its proportion in parent.
-      const width =
-          (isFullWidth ? 1 : value.totalSize / parentSize) * parentNode.width;
-
-      const currentX = parentNode.nextXForChildren;
-      currentY = nodeHeight * (value.depth + 1);
-
-      // Draw node.
-      ctx.fillStyle = this.generateColor(value.name, isGreyedOut);
-      ctx.fillRect(currentX, currentY, width, nodeHeight);
-
-      // Set current node's data in map for children to use.
-      nodesMap.set(value.hash, {
-        width,
-        nextXForChildren: currentX,
-        size: value.totalSize,
-        x: currentX
-      });
-      // Update next x coordinate in parent.
-      nodesMap.set(value.parentHash, {
-        width: parentNode.width,
-        nextXForChildren: currentX + width,
-        size: parentNode.size,
-        x: parentNode.x
-      });
-
-      // Thumbnail mode doesn't have name on nodes and click/hover behaviour.
-      if (this.isThumbnail) {
-        continue;
-      }
-
-      // Draw name.
-      const name = this.getCallsiteName(value);
-      ctx.font = `${this.textSize}px Google Sans`;
-      const text = cropText(name, charWidth, width - 2);
-      ctx.fillStyle = 'black';
-      ctx.fillText(text, currentX + 5, currentY + nodeHeight - 4);
-
-      // Draw border around node.
-      ctx.strokeStyle = 'white';
-      ctx.beginPath();
-      ctx.moveTo(currentX, currentY);
-      ctx.lineTo(currentX, currentY + nodeHeight);
-      ctx.lineTo(currentX + width, currentY + nodeHeight);
-      ctx.lineTo(currentX + width, currentY);
-      ctx.moveTo(currentX, currentY);
-      ctx.lineWidth = 1;
-      ctx.closePath();
-      ctx.stroke();
-
-      // Add this node for recognizing in click/hover.
-      // Map graphData contains one callsite which is on that depth and X
-      // start. Map xStartsPerDepth for each depth contains all X start
-      // coordinates that callsites on that level have.
-      this.graphData.set(
-          `${value.depth};${currentX}`, {callsite: value, width});
-      const xStarts = this.xStartsPerDepth.get(value.depth);
-      if (xStarts === undefined) {
-        this.xStartsPerDepth.set(value.depth, [currentX]);
-      } else {
-        xStarts.push(currentX);
-      }
-    }
-
-    if (clickedNode === undefined) {
-      this.baseMap = nodesMap;
-    }
-
-    if (this.hoveredX > -1 && this.hoveredY > -1 && this.hoveredCallsite) {
-      // Draw the tooltip.
-      const line1 = this.getCallsiteName(this.hoveredCallsite);
-      const percentage = this.hoveredCallsite.totalSize / this.totalSize * 100;
-      const line2 = `total: ${this.hoveredCallsite.totalSize}${unit} (${
-          percentage.toFixed(2)}%)`;
-      ctx.font = '12px Google Sans';
-      const line1Width = ctx.measureText(line1).width;
-      const line2Width = ctx.measureText(line2).width;
-      const rectWidth = Math.max(line1Width, line2Width);
-      const rectYStart = this.hoveredY + 10;
-      const rectHeight = nodeHeight * 3;
-      const rectYEnd = rectYStart + rectHeight;
-      ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
-      ctx.fillRect(this.hoveredX + 5, rectYStart, rectWidth + 16, rectHeight);
-      ctx.fillStyle = 'hsl(200, 50%, 40%)';
-      ctx.textAlign = 'left';
-      ctx.fillText(line1, this.hoveredX + 8, rectYStart + 18 /* 8 + 10s */);
-      ctx.fillText(line2, this.hoveredX + 8, rectYEnd - 8);
-    }
-  }
-
-  private getCallsiteName(value: CallsiteInfo): string {
-    return value.name === undefined ? 'unknown' : value.name;
-  }
-
-  onMouseMove({x, y}: {x: number, y: number}) {
-    this.hoveredX = x;
-    this.hoveredY = y;
-    this.hoveredCallsite = this.findSelectedCallsite(x, y);
-    const isCallsiteSelected = this.hoveredCallsite !== undefined;
-    if (!isCallsiteSelected) {
-      this.onMouseOut();
-    }
-    return isCallsiteSelected;
-  }
-
-  onMouseOut() {
-    this.hoveredX = -1;
-    this.hoveredY = -1;
-    this.hoveredCallsite = undefined;
-  }
-
-  onMouseClick({x, y}: {x: number, y: number}) {
-    if (this.isThumbnail) {
-      return true;
-    }
-    this.clickedCallsite = this.findSelectedCallsite(x, y);
-    return this.clickedCallsite !== undefined;
-  }
-
-  private findSelectedCallsite(x: number, y: number): CallsiteInfo|undefined {
-    const depth = Math.trunc(y / this.getNodeHeight()) - 1;  // at 0 is root
-    if (depth >= 0 && this.xStartsPerDepth.has(depth)) {
-      const startX = this.searchSmallest(this.xStartsPerDepth.get(depth)!, x);
-      const result = this.graphData.get(`${depth};${startX}`);
-      if (result !== undefined) {
-        const width = result.width;
-        return startX + width >= x ? result.callsite : undefined;
-      }
-    }
-    return undefined;
-  }
-
-  searchSmallest(haystack: number[], needle: number): number {
-    haystack = haystack.sort((n1, n2) => n1 - n2);
-    const [left, ] = searchSegment(haystack, needle);
-    return left === -1 ? -1 : haystack[left];
-  }
-
-  getHeight(): number {
-    return this.flamegraphData.length === 0 ?
-        0 :
-        (this.maxDepth + 2) * this.getNodeHeight();
-  }
-
-  getNodeHeight() {
-    return this.isThumbnail ? 1 : NODE_HEIGHT_DEFAULT;
-  }
-
-  enableThumbnail(isThumbnail: boolean) {
-    this.isThumbnail = isThumbnail;
-  }
-}
diff --git a/ui/src/frontend/frontend_local_state.ts b/ui/src/frontend/frontend_local_state.ts
index b9e4b5b..ce6ec01 100644
--- a/ui/src/frontend/frontend_local_state.ts
+++ b/ui/src/frontend/frontend_local_state.ts
@@ -13,71 +13,12 @@
 // limitations under the License.
 
 import {Actions} from '../common/actions';
-import {HttpRpcState} from '../common/http_rpc_engine';
-import {
-  FrontendLocalState as FrontendState,
-  OmniboxState,
-  SelectedTimeRange,
-  Timestamped,
-  VisibleState,
-} from '../common/state';
+import {FrontendLocalState as FrontendState} from '../common/state';
 import {TimeSpan} from '../common/time';
 
-import {Tab} from './details_panel';
 import {globals} from './globals';
 import {TimeScale} from './time_scale';
 
-function chooseLatest<T extends Timestamped<{}>>(current: T, next: T): T {
-  if (next !== current && next.lastUpdate > current.lastUpdate) {
-    return next;
-  }
-  return current;
-}
-
-// Returns a wrapper around |f| which calls f at most once every |ms|ms.
-function ratelimit(f: Function, ms: number): Function {
-  let inProgess = false;
-  return () => {
-    if (inProgess) {
-      return;
-    }
-    inProgess = true;
-    window.setTimeout(() => {
-      f();
-      inProgess = false;
-    }, ms);
-  };
-}
-
-// Returns a wrapper around |f| which waits for a |ms|ms pause in calls
-// before calling |f|.
-function debounce(f: Function, ms: number): Function {
-  let timerId: undefined|number;
-  return () => {
-    if (timerId) {
-      window.clearTimeout(timerId);
-    }
-    timerId = window.setTimeout(() => {
-      f();
-      timerId = undefined;
-    }, ms);
-  };
-}
-
-// Calculate the space a scrollbar takes up so that we can subtract it from
-// the canvas width.
-function calculateScrollbarWidth() {
-  const outer = document.createElement('div');
-  outer.style.overflowY = 'scroll';
-  const inner = document.createElement('div');
-  outer.appendChild(inner);
-  document.body.appendChild(outer);
-  const width =
-      outer.getBoundingClientRect().width - inner.getBoundingClientRect().width;
-  document.body.removeChild(outer);
-  return width;
-}
-
 /**
  * State that is shared between several frontend components, but not the
  * controller. This state is updated at 60fps.
@@ -85,49 +26,46 @@
 export class FrontendLocalState {
   visibleWindowTime = new TimeSpan(0, 10);
   timeScale = new TimeScale(this.visibleWindowTime, [0, 0]);
+  private _lastUpdate = 0;
+  private pendingGlobalTimeUpdate = false;
   perfDebug = false;
   hoveredUtid = -1;
   hoveredPid = -1;
   hoveredTimestamp = -1;
-  vidTimestamp = -1;
   showTimeSelectPreview = false;
   showNotePreview = false;
-  localOnlyMode = false;
-  sidebarVisible = true;
-  visibleTracks = new Set<string>();
-  prevVisibleTracks = new Set<string>();
-  searchIndex = -1;
-  currentTab?: Tab;
-  scrollToTrackId?: string|number;
-  httpRpcState: HttpRpcState = {connected: false};
-  private scrollBarWidth?: number;
-
-  private _omniboxState: OmniboxState = {
-    lastUpdate: 0,
-    omnibox: '',
-    mode: 'SEARCH',
-  };
-
-  private _visibleState: VisibleState = {
-    lastUpdate: 0,
-    startSec: 0,
-    endSec: 10,
-    resolution: 1,
-  };
-
-  private _selectedTimeRange: SelectedTimeRange = {
-    lastUpdate: 0,
-  };
 
   // TODO: there is some redundancy in the fact that both |visibleWindowTime|
   // and a |timeScale| have a notion of time range. That should live in one
   // place only.
+  updateVisibleTime(ts: TimeSpan) {
+    const startSec = Math.max(ts.start, globals.state.traceTime.startSec);
+    const endSec = Math.min(ts.end, globals.state.traceTime.endSec);
+    this.visibleWindowTime = new TimeSpan(startSec, endSec);
+    this.timeScale.setTimeBounds(this.visibleWindowTime);
+    this._lastUpdate = Date.now() / 1000;
 
-  getScrollbarWidth() {
-    if (this.scrollBarWidth === undefined) {
-      this.scrollBarWidth = calculateScrollbarWidth();
+    // Post a delayed update to the controller.
+    if (this.pendingGlobalTimeUpdate) return;
+    setTimeout(() => {
+      this._lastUpdate = Date.now() / 1000;
+      globals.dispatch(Actions.setVisibleTraceTime({
+        time: {
+          startSec: this.visibleWindowTime.start,
+          endSec: this.visibleWindowTime.end,
+        },
+        lastUpdate: this._lastUpdate,
+      }));
+      this.pendingGlobalTimeUpdate = false;
+    }, 100);
+  }
+
+  mergeState(frontendLocalState: FrontendState): void {
+    if (this._lastUpdate >= frontendLocalState.lastUpdate) {
+      return;
     }
-    return this.scrollBarWidth;
+    const visible = frontendLocalState.visibleTraceTime;
+    this.updateVisibleTime(new TimeSpan(visible.startSec, visible.endSec));
   }
 
   togglePerfDebug() {
@@ -148,12 +86,6 @@
     globals.rafScheduler.scheduleRedraw();
   }
 
-  setVidTimestamp(ts: number) {
-    if (this.vidTimestamp === ts) return;
-    this.vidTimestamp = ts;
-    globals.rafScheduler.scheduleRedraw();
-  }
-
   setShowNotePreview(show: boolean) {
     this.showNotePreview = show;
     globals.rafScheduler.scheduleRedraw();
@@ -163,111 +95,4 @@
     this.showTimeSelectPreview = show;
     globals.rafScheduler.scheduleRedraw();
   }
-
-  addVisibleTrack(trackId: string) {
-    this.visibleTracks.add(trackId);
-  }
-
-  setSearchIndex(index: number) {
-    this.searchIndex = index;
-    globals.rafScheduler.scheduleRedraw();
-  }
-
-  toggleSidebar() {
-    this.sidebarVisible = !this.sidebarVisible;
-    globals.rafScheduler.scheduleFullRedraw();
-  }
-
-  setHttpRpcState(httpRpcState: HttpRpcState) {
-    this.httpRpcState = httpRpcState;
-    globals.rafScheduler.scheduleFullRedraw();
-  }
-
-  // Called when beginning a canvas redraw.
-  clearVisibleTracks() {
-    this.prevVisibleTracks = new Set(this.visibleTracks);
-    this.visibleTracks.clear();
-  }
-
-  // Called when the canvas redraw is complete.
-  sendVisibleTracks() {
-    if (this.prevVisibleTracks.size !== this.visibleTracks.size ||
-        ![...this.prevVisibleTracks].every(
-            value => this.visibleTracks.has(value))) {
-      globals.dispatch(
-          Actions.setVisibleTracks({tracks: Array.from(this.visibleTracks)}));
-    }
-  }
-
-  mergeState(state: FrontendState): void {
-    this._omniboxState = chooseLatest(this._omniboxState, state.omniboxState);
-    this._visibleState = chooseLatest(this._visibleState, state.visibleState);
-    this._selectedTimeRange =
-        chooseLatest(this._selectedTimeRange, state.selectedTimeRange);
-    if (this._visibleState === state.visibleState) {
-      this.updateLocalTime(
-          new TimeSpan(this._visibleState.startSec, this._visibleState.endSec));
-    }
-  }
-
-  private selectTimeRangeDebounced = debounce(() => {
-    globals.dispatch(Actions.selectTimeRange(this._selectedTimeRange));
-  }, 20);
-
-  selectTimeRange(startSec: number, endSec: number) {
-    this._selectedTimeRange = {startSec, endSec, lastUpdate: Date.now() / 1000};
-    this.selectTimeRangeDebounced();
-    globals.frontendLocalState.currentTab = 'time_range';
-    globals.rafScheduler.scheduleFullRedraw();
-  }
-
-  removeTimeRange() {
-    this._selectedTimeRange = {
-      startSec: undefined,
-      endSec: undefined,
-      lastUpdate: Date.now() / 1000
-    };
-    this.selectTimeRangeDebounced();
-    globals.frontendLocalState.currentTab = undefined;
-    globals.rafScheduler.scheduleFullRedraw();
-  }
-
-  get selectedTimeRange(): SelectedTimeRange {
-    return this._selectedTimeRange;
-  }
-
-  private setOmniboxDebounced = debounce(() => {
-    globals.dispatch(Actions.setOmnibox(this._omniboxState));
-  }, 20);
-
-  setOmnibox(value: string, mode: 'SEARCH'|'COMMAND') {
-    this._omniboxState.omnibox = value;
-    this._omniboxState.mode = mode;
-    this._omniboxState.lastUpdate = Date.now() / 1000;
-    this.setOmniboxDebounced();
-  }
-
-  get omnibox(): string {
-    return this._omniboxState.omnibox;
-  }
-
-  private ratelimitedUpdateVisible = ratelimit(() => {
-    globals.dispatch(Actions.setVisibleTraceTime(this._visibleState));
-  }, 50);
-
-  private updateLocalTime(ts: TimeSpan) {
-    const startSec = Math.max(ts.start, globals.state.traceTime.startSec);
-    const endSec = Math.min(ts.end, globals.state.traceTime.endSec);
-    this.visibleWindowTime = new TimeSpan(startSec, endSec);
-    this.timeScale.setTimeBounds(this.visibleWindowTime);
-  }
-
-  updateVisibleTime(ts: TimeSpan) {
-    this.updateLocalTime(ts);
-    this._visibleState.lastUpdate = Date.now() / 1000;
-    this._visibleState.startSec = this.visibleWindowTime.start;
-    this._visibleState.endSec = this.visibleWindowTime.end;
-    this._visibleState.resolution = globals.getCurResolution();
-    this.ratelimitedUpdateVisible();
-  }
 }
diff --git a/ui/src/frontend/globals.ts b/ui/src/frontend/globals.ts
index 9ed553f..747c8db 100644
--- a/ui/src/frontend/globals.ts
+++ b/ui/src/frontend/globals.ts
@@ -13,8 +13,7 @@
 // limitations under the License.
 
 import {assertExists} from '../base/logging';
-import {DeferredAction} from '../common/actions';
-import {CurrentSearchResults, SearchSummary} from '../common/search_data';
+import {Actions, DeferredAction} from '../common/actions';
 import {createEmptyState, State} from '../common/state';
 
 import {FrontendLocalState} from './frontend_local_state';
@@ -28,37 +27,9 @@
   dur?: number;
   priority?: number;
   endState?: string;
-  cpu?: number;
-  id?: number;
-  utid?: number;
   wakeupTs?: number;
   wakerUtid?: number;
   wakerCpu?: number;
-  category?: string;
-  name?: string;
-}
-
-export interface CounterDetails {
-  startTime?: number;
-  value?: number;
-  delta?: number;
-  duration?: number;
-}
-
-export interface CallsiteInfo {
-  hash: number;
-  parentHash: number;
-  depth: number;
-  name?: string;
-  totalSize: number;
-}
-
-export interface HeapProfileDetails {
-  ts?: number;
-  tsNs?: number;
-  allocated?: number;
-  allocatedNotFreed?: number;
-  pid?: number;
 }
 
 export interface QuantizedLoad {
@@ -93,24 +64,7 @@
   private _overviewStore?: OverviewStore = undefined;
   private _threadMap?: ThreadMap = undefined;
   private _sliceDetails?: SliceDetails = undefined;
-  private _counterDetails?: CounterDetails = undefined;
-  private _heapDumpDetails?: HeapProfileDetails = undefined;
-  private _numQueriesQueued = 0;
-  private _bufferUsage?: number = undefined;
-  private _recordingLog?: string = undefined;
-  private _currentSearchResults: CurrentSearchResults = {
-    sliceIds: new Float64Array(0),
-    tsStarts: new Float64Array(0),
-    utids: new Float64Array(0),
-    trackIds: [],
-    refTypes: [],
-    totalResults: 0,
-  };
-  searchSummary: SearchSummary = {
-    tsStarts: new Float64Array(0),
-    tsEnds: new Float64Array(0),
-    count: new Uint8Array(0),
-  };
+  private _pendingTrackRequests?: Set<string> = undefined;
 
   initialize(dispatch: Dispatch, controllerWorker: Worker) {
     this._dispatch = dispatch;
@@ -125,8 +79,7 @@
     this._overviewStore = new Map<string, QuantizedLoad[]>();
     this._threadMap = new Map<number, ThreadDesc>();
     this._sliceDetails = {};
-    this._counterDetails = {};
-    this._heapDumpDetails = {};
+    this._pendingTrackRequests = new Set<string>();
   }
 
   get state(): State {
@@ -174,71 +127,33 @@
     this._sliceDetails = assertExists(click);
   }
 
-  get counterDetails() {
-    return assertExists(this._counterDetails);
-  }
-
-  set counterDetails(click: CounterDetails) {
-    this._counterDetails = assertExists(click);
-  }
-
-  get heapDumpDetails() {
-    return assertExists(this._heapDumpDetails);
-  }
-
-  set heapDumpDetails(click: HeapProfileDetails) {
-    this._heapDumpDetails = assertExists(click);
-  }
-
-  set numQueuedQueries(value: number) {
-    this._numQueriesQueued = value;
-  }
-
-  get numQueuedQueries() {
-    return this._numQueriesQueued;
-  }
-
-  get bufferUsage() {
-    return this._bufferUsage;
-  }
-
-  get recordingLog() {
-    return this._recordingLog;
-  }
-
-  get currentSearchResults() {
-    return this._currentSearchResults;
-  }
-
-  set currentSearchResults(results: CurrentSearchResults) {
-    this._currentSearchResults = results;
-  }
-
-  setBufferUsage(bufferUsage: number) {
-    this._bufferUsage = bufferUsage;
-  }
-
   setTrackData(id: string, data: {}) {
     this.trackDataStore.set(id, data);
-  }
-
-  setRecordingLog(recordingLog: string) {
-    this._recordingLog = recordingLog;
+    assertExists(this._pendingTrackRequests).delete(id);
   }
 
   getCurResolution() {
-    // Truncate the resolution to the closest power of 2.
-    // This effectively means the resolution changes every 6 zoom levels.
+    // Truncate the resolution to the closest power of 10.
     const resolution = this.frontendLocalState.timeScale.deltaPxToDuration(1);
-    return Math.pow(2, Math.floor(Math.log2(resolution)));
+    return Math.pow(10, Math.floor(Math.log10(resolution)));
   }
 
-  makeSelection(action: DeferredAction<{}>) {
-    // A new selection should cancel the current search selection.
-    globals.frontendLocalState.searchIndex = -1;
-    globals.frontendLocalState.currentTab =
-        action.type === 'deselect' ? undefined : 'current_selection';
-    globals.dispatch(action);
+  requestTrackData(trackId: string) {
+    const pending = assertExists(this._pendingTrackRequests);
+    if (pending.has(trackId)) return;
+
+    const {visibleWindowTime} = globals.frontendLocalState;
+    const resolution = this.getCurResolution();
+    const start = visibleWindowTime.start - visibleWindowTime.duration;
+    const end = visibleWindowTime.end + visibleWindowTime.duration;
+
+    pending.add(trackId);
+    globals.dispatch(Actions.reqTrackData({
+      trackId,
+      start,
+      end,
+      resolution,
+    }));
   }
 
   resetForTesting() {
@@ -253,15 +168,7 @@
     this._overviewStore = undefined;
     this._threadMap = undefined;
     this._sliceDetails = undefined;
-    this._numQueriesQueued = 0;
-    this._currentSearchResults = {
-      sliceIds: new Float64Array(0),
-      tsStarts: new Float64Array(0),
-      utids: new Float64Array(0),
-      trackIds: [],
-      refTypes: [],
-      totalResults: 0,
-    };
+    this._pendingTrackRequests = undefined;
   }
 
   // Used when switching to the legacy TraceViewer UI.
diff --git a/ui/src/frontend/heap_profile_panel.ts b/ui/src/frontend/heap_profile_panel.ts
deleted file mode 100644
index 938a80b..0000000
--- a/ui/src/frontend/heap_profile_panel.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use size 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.
-
-import * as m from 'mithril';
-
-import {Actions} from '../common/actions';
-import {timeToCode} from '../common/time';
-
-import {globals} from './globals';
-import {Panel} from './panel';
-
-interface HeapProfileDetailsPanelAttrs {}
-
-export class HeapProfileDetailsPanel extends
-    Panel<HeapProfileDetailsPanelAttrs> {
-  private ts = 0;
-  private pid = 0;
-
-  view() {
-    const heapDumpInfo = globals.heapDumpDetails;
-    if (heapDumpInfo && heapDumpInfo.ts !== undefined &&
-        heapDumpInfo.allocated !== undefined &&
-        heapDumpInfo.allocatedNotFreed !== undefined &&
-        heapDumpInfo.tsNs !== undefined && heapDumpInfo.pid !== undefined) {
-      this.ts = heapDumpInfo.tsNs;
-      this.pid = heapDumpInfo.pid;
-      return m(
-          '.details-panel',
-          m('.details-panel-heading', `Heap Profile Details:`),
-          m(
-              '.details-table',
-              [m('table',
-                 [
-                   m('tr',
-                     m('th', `Snapshot time`),
-                     m('td', `${timeToCode(heapDumpInfo.ts)}`)),
-                   m('tr',
-                     m('th', `Total allocated:`),
-                     m('td',
-                       `${heapDumpInfo.allocated.toLocaleString()} bytes`)),
-                   m('tr',
-                     m('th', `Allocated not freed:`),
-                     m('td',
-                       `${
-                           heapDumpInfo.allocatedNotFreed
-                               .toLocaleString()} bytes`)),
-                 ])],
-              ),
-          m('.explanation',
-            'Heap profile support is in beta. If you need missing features, ',
-            'download and open it in ',
-            m(`a[href='https://pprof.corp.google.com']`, 'pprof'),
-            ' (Googlers only) or ',
-            m(`a[href='https://www.speedscope.app']`, 'Speedscope'),
-            '.'),
-          m('button',
-            {
-              onclick: () => {
-                this.downloadPprof();
-              }
-            },
-            m('i.material-icons', 'file_download'),
-            'Download profile'),
-      );
-    } else {
-      return m(
-          '.details-panel',
-          m('.details-panel-heading', `Heap Snapshot Details:`));
-    }
-  }
-
-  downloadPprof() {
-    const engine = Object.values(globals.state.engines)[0];
-    if (!engine) return;
-    const src = engine.source;
-    // TODO(tneda): add second timestamp
-    globals.dispatch(
-        Actions.convertTraceToPprof({pid: this.pid, ts1: this.ts, src}));
-  }
-
-  renderCanvas() {}
-}
diff --git a/ui/src/frontend/help_modal.ts b/ui/src/frontend/help_modal.ts
deleted file mode 100644
index 39ff0e4..0000000
--- a/ui/src/frontend/help_modal.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-
-// Copyright (C) 2019 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.
-
-import * as m from 'mithril';
-
-import {hideModel, showModal} from './modal';
-
-let helpModelOpen = false;
-
-export function toggleHelp() {
-  if (helpModelOpen) {
-    hideHelp();
-  } else {
-    showHelp();
-  }
-}
-
-function keycap(key: string) {
-  return m('.keycap', key);
-}
-
-function showHelp() {
-  helpModelOpen = true;
-  showModal({
-    title: 'Perfetto Help',
-    content:
-        m('.help',
-          m('h2', 'Navigation'),
-          m(
-              'table',
-              m(
-                  'tr',
-                  m('td', keycap('w'), '/', keycap('s')),
-                  m('td', 'Zoom in/out'),
-                  ),
-              m(
-                  'tr',
-                  m('td', keycap('a'), '/', keycap('d')),
-                  m('td', 'Pan left/right'),
-                  ),
-              ),
-          m('h2', 'Mouse Controls'),
-          m('table',
-            m('tr', m('td', 'Click'), m('td', 'Select event')),
-            m('tr', m('td', 'Ctrl + Scroll wheel'), m('td', 'Zoom in/out')),
-            m('tr', m('td', 'Click + Drag'), m('td', 'Pan left/right')),
-            m('tr',
-              m('td', 'Shift + Click + Drag'),
-              m('td', 'Select a time span'))),
-          m('h2', 'Other'),
-          m(
-              'table',
-              m('tr',
-                m('td', keycap('f'), ' (with event selected)'),
-                m('td', 'Scroll + zoom to current selection')),
-              m('tr',
-                m('td', keycap('m'), ' (with event selected)'),
-                m('td', 'Select time span of event')),
-              m('tr', m('td', keycap('?')), m('td', 'Show help')),
-              )),
-    buttons: [],
-  }).finally(() => {
-    helpModelOpen = false;
-  });
-}
-
-function hideHelp() {
-  if (helpModelOpen) {
-    hideModel();
-  }
-}
diff --git a/ui/src/frontend/index.ts b/ui/src/frontend/index.ts
index cce7b1e..3d49d6d 100644
--- a/ui/src/frontend/index.ts
+++ b/ui/src/frontend/index.ts
@@ -15,43 +15,19 @@
 import '../tracks/all_frontend';
 
 import {applyPatches, Patch} from 'immer';
-import * as MicroModal from 'micromodal';
 import * as m from 'mithril';
 
-import {assertExists, reportError, setErrorHandler} from '../base/logging';
 import {forwardRemoteCalls} from '../base/remote';
 import {Actions} from '../common/actions';
-import {
-  LogBoundsKey,
-  LogEntriesKey,
-  LogExists,
-  LogExistsKey
-} from '../common/logs';
-import {CurrentSearchResults, SearchSummary} from '../common/search_data';
-import {
-  HeapProfileFlamegraphKey
-} from '../tracks/heap_profile_flamegraph/common';
+import {LogBoundsKey, LogEntriesKey, LogExistsKey} from '../common/logs';
 
-import {maybeShowErrorDialog} from './error_dialog';
-import {
-  CounterDetails,
-  globals,
-  HeapProfileDetails,
-  QuantizedLoad,
-  SliceDetails,
-  ThreadDesc
-} from './globals';
+import {globals, QuantizedLoad, SliceDetails, ThreadDesc} from './globals';
 import {HomePage} from './home_page';
 import {openBufferWithLegacyTraceViewer} from './legacy_trace_viewer';
-import {postMessageHandler} from './post_message_handler';
 import {RecordPage} from './record_page';
-import {updateAvailableAdbDevices} from './record_page';
 import {Router} from './router';
-import {CheckHttpRpcConnection} from './rpc_http_dialog';
 import {ViewerPage} from './viewer_page';
 
-const EXTENSION_ID = 'lfmkphfpdbjijhpomgecfikhfohaoine';
-
 /**
  * The API the main thread exposes to the controller.
  */
@@ -59,22 +35,12 @@
   constructor(private router: Router) {}
 
   patchState(patches: Patch[]) {
-    const oldState = globals.state;
     globals.state = applyPatches(globals.state, patches);
-
     // If the visible time in the global state has been updated more recently
     // than the visible time handled by the frontend @ 60fps, update it. This
     // typically happens when restoring the state from a permalink.
     globals.frontendLocalState.mergeState(globals.state.frontendLocalState);
-
-    // Only redraw if something other than the frontendLocalState changed.
-    for (const key in globals.state) {
-      if (key !== 'frontendLocalState' && key !== 'visibleTracks' &&
-          oldState[key] !== globals.state[key]) {
-        this.redraw();
-        return;
-      }
-    }
+    this.redraw();
   }
 
   // TODO: we can't have a publish method for each batch of data that we don't
@@ -98,9 +64,6 @@
   publishTrackData(args: {id: string, data: {}}) {
     globals.setTrackData(args.id, args.data);
     if ([LogExistsKey, LogBoundsKey, LogEntriesKey].includes(args.id)) {
-      const data = globals.trackDataStore.get(LogExistsKey) as LogExists;
-      if (data && data.exists) globals.rafScheduler.scheduleFullRedraw();
-    } else if (HeapProfileFlamegraphKey === args.id) {
       globals.rafScheduler.scheduleFullRedraw();
     } else {
       globals.rafScheduler.scheduleRedraw();
@@ -125,34 +88,6 @@
     this.redraw();
   }
 
-  publishCounterDetails(click: CounterDetails) {
-    globals.counterDetails = click;
-    this.redraw();
-  }
-
-  publishHeapDumpDetails(click: HeapProfileDetails) {
-    globals.heapDumpDetails = click;
-    this.redraw();
-  }
-
-  publishFileDownload(args: {file: File, name?: string}) {
-    const url = URL.createObjectURL(args.file);
-    const a = document.createElement('a');
-    a.href = url;
-    a.download = args.name !== undefined ? args.name : args.file.name;
-    document.body.appendChild(a);
-    a.click();
-    document.body.removeChild(a);
-    URL.revokeObjectURL(url);
-  }
-
-  publishLoading(numQueuedQueries: number) {
-    globals.numQueuedQueries = numQueuedQueries;
-    // TODO(hjd): Clean up loadingAnimation given that this now causes a full
-    // redraw anyways. Also this should probably just go via the global state.
-    globals.rafScheduler.scheduleFullRedraw();
-  }
-
   // For opening JSON/HTML traces with the legacy catapult viewer.
   publishLegacyTrace(args: {data: ArrayBuffer, size: number}) {
     const arr = new Uint8Array(args.data, 0, args.size);
@@ -160,26 +95,6 @@
     openBufferWithLegacyTraceViewer('trace.json', str, 0);
   }
 
-  publishBufferUsage(args: {percentage: number}) {
-    globals.setBufferUsage(args.percentage);
-    this.redraw();
-  }
-
-  publishSearch(args: SearchSummary) {
-    globals.searchSummary = args;
-    this.redraw();
-  }
-
-  publishSearchResult(args: CurrentSearchResults) {
-    globals.currentSearchResults = args;
-    this.redraw();
-  }
-
-  publishRecordingLog(args: {logs: string}) {
-    globals.setRecordingLog(args.logs);
-    this.redraw();
-  }
-
   private redraw(): void {
     if (globals.state.route &&
         globals.state.route !== this.router.getRouteFromHash()) {
@@ -190,57 +105,14 @@
   }
 }
 
-function setExtensionAvailability(available: boolean) {
-  globals.dispatch(Actions.setExtensionAvailable({
-    available,
-  }));
-}
-
-function fetchChromeTracingCategoriesFromExtension(
-    extensionPort: chrome.runtime.Port) {
-  extensionPort.postMessage({method: 'GetCategories'});
-}
-
-function onExtensionMessage(message: object) {
-  const typedObject = message as {type: string};
-  if (typedObject.type === 'GetCategoriesResponse') {
-    const categoriesMessage = message as {categories: string[]};
-    globals.dispatch(Actions.setChromeCategories(
-        {categories: categoriesMessage.categories}));
-  }
-}
-
 function main() {
-  // Add Error handlers for JS error and for uncaught exceptions in promises.
-  setErrorHandler((err: string) => maybeShowErrorDialog(err));
-  window.addEventListener('error', e => reportError(e));
-  window.addEventListener('unhandledrejection', e => reportError(e));
-
   const controller = new Worker('controller_bundle.js');
-  const frontendChannel = new MessageChannel();
-  const controllerChannel = new MessageChannel();
-  const extensionLocalChannel = new MessageChannel();
-  const errorReportingChannel = new MessageChannel();
-
-  errorReportingChannel.port2.onmessage = (e) =>
-      maybeShowErrorDialog(`${e.data}`);
-
-  controller.postMessage(
-      {
-        frontendPort: frontendChannel.port1,
-        controllerPort: controllerChannel.port1,
-        extensionPort: extensionLocalChannel.port1,
-        errorReportingPort: errorReportingChannel.port1,
-      },
-      [
-        frontendChannel.port1,
-        controllerChannel.port1,
-        extensionLocalChannel.port1,
-        errorReportingChannel.port1,
-      ]);
-
-  const dispatch =
-      controllerChannel.port2.postMessage.bind(controllerChannel.port2);
+  controller.onerror = e => {
+    console.error(e);
+  };
+  const channel = new MessageChannel();
+  controller.postMessage(channel.port1, [channel.port1]);
+  const dispatch = controller.postMessage.bind(controller);
   const router = new Router(
       '/',
       {
@@ -249,67 +121,23 @@
         '/record': RecordPage,
       },
       dispatch);
-  forwardRemoteCalls(frontendChannel.port2, new FrontendApi(router));
+  forwardRemoteCalls(channel.port2, new FrontendApi(router));
   globals.initialize(dispatch, controller);
 
-  // We proxy messages between the extension and the controller because the
-  // controller's worker can't access chrome.runtime.
-  const extensionPort = window.chrome && chrome.runtime ?
-      chrome.runtime.connect(EXTENSION_ID) :
-      undefined;
-
-  setExtensionAvailability(extensionPort !== undefined);
-
-  if (extensionPort) {
-    extensionPort.onDisconnect.addListener(_ => {
-      setExtensionAvailability(false);
-      // tslint:disable-next-line: no-unused-expression
-      void chrome.runtime.lastError;  // Needed to not receive an error log.
-    });
-    // This forwards the messages from the extension to the controller.
-    extensionPort.onMessage.addListener(
-        (message: object, _port: chrome.runtime.Port) => {
-          onExtensionMessage(message);
-          extensionLocalChannel.port2.postMessage(message);
-        });
-    fetchChromeTracingCategoriesFromExtension(extensionPort);
-  }
-
-  updateAvailableAdbDevices();
-  try {
-    navigator.usb.addEventListener('connect', updateAvailableAdbDevices);
-    navigator.usb.addEventListener('disconnect', updateAvailableAdbDevices);
-  } catch (e) {
-    console.error('WebUSB API not supported');
-  }
-  // This forwards the messages from the controller to the extension
-  extensionLocalChannel.port2.onmessage = ({data}) => {
-    if (extensionPort) extensionPort.postMessage(data);
-  };
-  const main = assertExists(document.body.querySelector('main'));
-
   globals.rafScheduler.domRedraw = () =>
-      m.render(main, m(router.resolve(globals.state.route)));
+      m.render(document.body, m(router.resolve(globals.state.route)));
 
-  // Add support for opening traces from postMessage().
-  window.addEventListener('message', postMessageHandler, {passive: true});
 
   // Put these variables in the global scope for better debugging.
   (window as {} as {m: {}}).m = m;
   (window as {} as {globals: {}}).globals = globals;
-  (window as {} as {Actions: {}}).Actions = Actions;
 
   // /?s=xxxx for permalinks.
   const stateHash = Router.param('s');
-  const urlHash = Router.param('url');
   if (stateHash) {
     globals.dispatch(Actions.loadPermalink({
       hash: stateHash,
     }));
-  } else if (urlHash) {
-    globals.dispatch(Actions.openTraceFromUrl({
-      url: urlHash,
-    }));
   }
 
   // Prevent pinch zoom.
@@ -318,13 +146,6 @@
   }, {passive: false});
 
   router.navigateToCurrentHash();
-
-  MicroModal.init();
-
-  // Will update the chip on the sidebar footer that notifies that the RPC is
-  // connected. Has no effect on the controller (which will repeat this check
-  // before creating a new engine).
-  CheckHttpRpcConnection();
 }
 
 main();
diff --git a/ui/src/frontend/keyboard_event_handler.ts b/ui/src/frontend/keyboard_event_handler.ts
index 3a8cdc7..27ef9d4 100644
--- a/ui/src/frontend/keyboard_event_handler.ts
+++ b/ui/src/frontend/keyboard_event_handler.ts
@@ -12,88 +12,26 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {Actions} from '../common/actions';
-
 import {globals} from './globals';
-import {toggleHelp} from './help_modal';
-import {
-  horizontalScrollAndZoomToRange,
-  verticalScrollToTrack
-} from './scroll_helper';
-import {executeSearch} from './search_handler';
+import {Actions} from '../common/actions';
 
 // Handles all key events than are not handled by the
 // pan and zoom handler.
-export function handleKey(e: KeyboardEvent, down: boolean) {
-  const key = e.key.toLowerCase();
+export function handleKey(key: string, down: boolean) {
   if (down && 'm' === key) {
     selectSliceSpan();
   }
-  if (down && 'f' === key) {
-    findCurrentSelection();
-  }
-  if (down && 'v' === key) {
-    globals.dispatch(Actions.toggleVideo({}));
-  }
-  if (down && 'p' === key) {
-    globals.dispatch(Actions.toggleFlagPause({}));
-  }
-  if (down && 't' === key) {
-    globals.dispatch(Actions.toggleScrubbing({}));
-    if (globals.frontendLocalState.vidTimestamp < 0) {
-      globals.frontendLocalState.setVidTimestamp(Number.MAX_SAFE_INTEGER);
-    } else {
-      globals.frontendLocalState.setVidTimestamp(Number.MIN_SAFE_INTEGER);
-    }
-  }
-  if (down && '?' === key) {
-    toggleHelp();
-  }
-  if (down && 'enter' === key) {
-    e.preventDefault();
-    executeSearch(e.shiftKey);
-  }
-}
-
-function findTimeRangeOfSelection() {
-  const selection = globals.state.currentSelection;
-  let startTs = -1;
-  let endTs = -1;
-  if (selection !== null) {
-    if (selection.kind === 'SLICE' || selection.kind === 'CHROME_SLICE') {
-      const slice = globals.sliceDetails;
-      if (slice.ts && slice.dur) {
-        startTs = slice.ts + globals.state.traceTime.startSec;
-        endTs = startTs + slice.dur;
-      }
-    } else if (selection.kind === 'THREAD_STATE') {
-      startTs = selection.ts;
-      endTs = startTs + selection.dur;
-    } else if (selection.kind === 'COUNTER') {
-      startTs = selection.leftTs;
-      endTs = selection.rightTs;
-    }
-  }
-  return {startTs, endTs};
 }
 
 function selectSliceSpan() {
-  const range = findTimeRangeOfSelection();
-  if (range.startTs !== -1 && range.endTs !== -1) {
-    globals.frontendLocalState.selectTimeRange(range.startTs, range.endTs);
-  }
-}
-
-function findCurrentSelection() {
   const selection = globals.state.currentSelection;
-  if (selection === null) return;
-
-  const range = findTimeRangeOfSelection();
-  if (range.startTs !== -1 && range.endTs !== -1) {
-    horizontalScrollAndZoomToRange(range.startTs, range.endTs);
-  }
-
-  if (selection.trackId) {
-    verticalScrollToTrack(selection.trackId, true);
+  const slice = globals.sliceDetails;
+  if (selection && selection.kind === 'SLICE' &&
+    slice && slice.ts && slice.dur) {
+    const startTs = slice.ts + globals.state.traceTime.startSec;
+    const endTs = startTs + slice.dur;
+    globals.dispatch(Actions.selectTimeSpan({startTs, endTs}));
   }
 }
+
+
diff --git a/ui/src/frontend/legacy_trace_viewer.ts b/ui/src/frontend/legacy_trace_viewer.ts
index 4dafe4c..7c85ed8 100644
--- a/ui/src/frontend/legacy_trace_viewer.ts
+++ b/ui/src/frontend/legacy_trace_viewer.ts
@@ -12,10 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {inflate} from 'pako';
-
 import {assertTrue} from '../base/logging';
-
 import {globals} from './globals';
 
 export function isLegacyTrace(fileName: string): boolean {
@@ -39,15 +36,13 @@
   reader.onerror = err => {
     console.error(err);
   };
-  if (file.name.endsWith('.gz') || file.name.endsWith('.zip') ||
-      file.name.endsWith('.ctrace')) {
+  if (file.name.endsWith('.gz') || file.name.endsWith('.zip')) {
     reader.readAsArrayBuffer(file);
   } else {
     reader.readAsText(file);
   }
 }
 
-
 export function openBufferWithLegacyTraceViewer(
     name: string, data: ArrayBuffer|string, size: number) {
   if (data instanceof ArrayBuffer) {
@@ -55,15 +50,7 @@
     if (size !== data.byteLength) {
       data = data.slice(0, size);
     }
-
-    // Handle .ctrace files.
-    const enc = new TextDecoder('utf-8');
-    const header = enc.decode(data.slice(0, 7));
-    if (header === 'TRACE:\n') {
-      data = inflate(new Uint8Array(data.slice(7, size)), {to: 'string'});
-    }
   }
-
   document.body.style.transition =
       'filter 1s ease, transform 1s cubic-bezier(0.985, 0.005, 1.000, 0.225)';
   document.body.style.filter = 'grayscale(1) blur(10px) opacity(0)';
diff --git a/ui/src/frontend/modal.ts b/ui/src/frontend/modal.ts
deleted file mode 100644
index 0778e4c..0000000
--- a/ui/src/frontend/modal.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (C) 2019 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.
-
-import * as MicroModal from 'micromodal';
-import * as m from 'mithril';
-
-// We need any here so we can accept vnodes with arbitrary attrs.
-// tslint:disable-next-line:no-any
-export type AnyAttrsVnode = m.Vnode<any, {}>;
-
-interface ModalDefinition {
-  title: string;
-  content: AnyAttrsVnode;
-  buttons: Button[];
-}
-
-export interface Button {
-  text: string;
-  primary: boolean;
-  id: string;
-  action: () => void;
-}
-
-export async function showModal(attrs: ModalDefinition): Promise<void> {
-  const modal = document.querySelector('#main-modal') as HTMLElement;
-  m.render(
-      modal,
-      m('.modal-overlay[data-micromodal-close]',
-        {tabindex: -1},
-        m('.modal-container[aria-labelledby=mm-title][aria-model][role=dialog]',
-          m('header.modal-header',
-            m('h2.modal-title', {id: 'mm-title'}, attrs.title),
-            m('button.modal-close[aria-label=Close Modal]' +
-              '[data-micromodal-close]')),
-          m('main.modal-content', attrs.content),
-          m('footer.modal-footer', ...makeButtons(attrs.buttons)))));
-  return new Promise(resolve => {
-    MicroModal.show(
-        'main-modal', {onClose: () => resolve(), awaitCloseAnimation: true});
-  });
-}
-
-export function hideModel() {
-  MicroModal.close();
-}
-
-function makeButtons(buttonDefinition: Button[]): Array<m.Vnode<Button>> {
-  const buttons: Array<m.Vnode<Button>> = [];
-  buttonDefinition.forEach(button => {
-    buttons.push(
-        m('button[data-micromodal-close].modal-btn',
-          {
-            class: button.primary ? 'modal-btn-primary' : '',
-            id: button.id,
-            onclick: button.action
-          },
-          button.text));
-  });
-  return buttons;
-}
diff --git a/ui/src/frontend/notes_panel.ts b/ui/src/frontend/notes_panel.ts
index 3edb401..5a9605c 100644
--- a/ui/src/frontend/notes_panel.ts
+++ b/ui/src/frontend/notes_panel.ts
@@ -21,13 +21,11 @@
 import {gridlines} from './gridline_helper';
 import {Panel, PanelSize} from './panel';
 import {TRACK_SHELL_WIDTH} from './track_constants';
-import {randomColor} from './colorizer';
+import {hsl} from 'color-convert';
 
 const FLAG_WIDTH = 16;
-const MOVIE_WIDTH = 16;
 const MOUSE_OFFSET = 6;
 const FLAG = `\uE153`;
-const MOVIE = '\uE8DA';
 
 function toSummary(s: string) {
   const newlineIndex = s.indexOf('\n') > 0 ? s.indexOf('\n') : s.length;
@@ -41,11 +39,6 @@
     dom.addEventListener('mousemove', (e: Event) => {
       this.hoveredX =
         (e as MouseEvent).layerX - TRACK_SHELL_WIDTH - MOUSE_OFFSET;
-      if (globals.state.scrubbingEnabled) {
-        const timescale = globals.frontendLocalState.timeScale;
-        const timestamp = timescale.pxToTime(this.hoveredX);
-        globals.frontendLocalState.setVidTimestamp(timestamp);
-      }
       globals.rafScheduler.scheduleRedraw();
     }, {passive: true});
     dom.addEventListener('mouseenter', (e: Event) => {
@@ -65,8 +58,7 @@
       '.notes-panel',
       {
         onclick: (e: MouseEvent) => {
-          const isMovie = globals.state.flagPauseEnabled;
-          this.onClick(e.layerX - TRACK_SHELL_WIDTH, e.layerY, isMovie);
+          this.onClick(e.layerX - TRACK_SHELL_WIDTH, e.layerY);
           e.stopPropagation();
         },
       });
@@ -78,7 +70,7 @@
     let aNoteIsHovered = false;
 
     ctx.fillStyle = '#999';
-    ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height);
+    ctx.fillRect(TRACK_SHELL_WIDTH - 1, 0, 2, size.height);
     for (const xAndTime of gridlines(size.width, range, timeScale)) {
       ctx.fillRect(xAndTime[0], 0, 1, size.height);
     }
@@ -103,14 +95,11 @@
       // Draw flag.
       if (!aNoteIsHovered && currentIsHovered) {
         aNoteIsHovered = true;
-        this.drawFlag(ctx, left, size.height, note.color, isSelected,
-          note.isMovie);
+        this.drawFlag(ctx, left, size.height, note.color, isSelected);
       } else if (isSelected) {
-        this.drawFlag(ctx, left, size.height, note.color, /* fill */ true,
-          note.isMovie);
+        this.drawFlag(ctx, left, size.height, note.color, /* fill */ true);
       } else {
-        this.drawFlag(ctx, left, size.height, note.color, false,
-          note.isMovie);
+        this.drawFlag(ctx, left, size.height, note.color);
       }
 
       if (note.text) {
@@ -143,7 +132,7 @@
 
   private drawFlag(
       ctx: CanvasRenderingContext2D, x: number, height: number, color: string,
-      fill?: boolean, isMovie = globals.state.flagPauseEnabled) {
+      fill?: boolean) {
     const prevFont = ctx.font;
     const prevBaseline = ctx.textBaseline;
     ctx.textBaseline = 'alphabetic';
@@ -151,37 +140,31 @@
       ctx.font = '24px Material Icons';
       ctx.fillStyle = color;
       // Adjust height for icon font.
-      ctx.fillText(isMovie ? MOVIE : FLAG, x - MOUSE_OFFSET, height + 2);
+      ctx.fillText(FLAG, x - MOUSE_OFFSET, height + 2);
     } else {
       ctx.strokeStyle = color;
       ctx.font = '24px Material Icons';
       // Adjust height for icon font.
-      ctx.strokeText(isMovie ? MOVIE : FLAG, x - MOUSE_OFFSET, height + 2.5);
+      ctx.strokeText(FLAG, x - MOUSE_OFFSET, height + 2.5);
     }
     ctx.font = prevFont;
     ctx.textBaseline = prevBaseline;
   }
 
-
-  private onClick(x: number, _: number, isMovie: boolean) {
+  private onClick(x: number, _: number) {
     const timeScale = globals.frontendLocalState.timeScale;
     const timestamp = timeScale.pxToTime(x - MOUSE_OFFSET);
-    const width = isMovie ? MOVIE_WIDTH : FLAG_WIDTH;
     for (const note of Object.values(globals.state.notes)) {
       const noteX = timeScale.timeToPx(note.timestamp);
-      if (noteX <= x && x < noteX + width) {
-        if (note.isMovie) {
-          globals.frontendLocalState.setVidTimestamp(note.timestamp);
-        }
-        globals.makeSelection(Actions.selectNote({id: note.id}));
+      if (noteX <= x && x < noteX + FLAG_WIDTH) {
+        globals.dispatch(Actions.selectNote({id: note.id}));
         return;
       }
     }
-    if (isMovie) {
-      globals.frontendLocalState.setVidTimestamp(timestamp);
-    }
-    const color = randomColor();
-    globals.makeSelection(Actions.addNote({timestamp, color, isMovie}));
+    // 40 different random hues 9 degrees apart.
+    const hue = Math.floor(Math.random() * 40) * 9;
+    const color = '#' + hsl.hex([hue, 90, 30]);
+    globals.dispatch(Actions.addNote({timestamp, color}));
   }
 }
 
diff --git a/ui/src/frontend/overview_timeline_panel.ts b/ui/src/frontend/overview_timeline_panel.ts
index bd01e9b..2739b57 100644
--- a/ui/src/frontend/overview_timeline_panel.ts
+++ b/ui/src/frontend/overview_timeline_panel.ts
@@ -22,7 +22,6 @@
 import {globals} from './globals';
 import {Panel, PanelSize} from './panel';
 import {TimeScale} from './time_scale';
-import {TRACK_SHELL_WIDTH} from './track_constants';
 
 export class OverviewTimelinePanel extends Panel {
   private width = 0;
@@ -37,8 +36,7 @@
     this.width = dom.getBoundingClientRect().width;
     this.totTime = new TimeSpan(
         globals.state.traceTime.startSec, globals.state.traceTime.endSec);
-    this.timeScale = new TimeScale(
-        this.totTime, [TRACK_SHELL_WIDTH, assertExists(this.width)]);
+    this.timeScale = new TimeScale(this.totTime, [0, assertExists(this.width)]);
 
     if (this.gesture === undefined) {
       this.gesture = new DragGestureHandler(
@@ -67,16 +65,15 @@
     ctx.font = '10px Google Sans';
     ctx.fillStyle = '#999';
     for (let i = 0; i < 100; i++) {
-      const xPos =
-          (i * (this.width - TRACK_SHELL_WIDTH) / 100) + TRACK_SHELL_WIDTH;
+      const xPos = i * this.width / 100;
       const t = this.timeScale.pxToTime(xPos);
       if (xPos <= 0) continue;
       if (xPos > this.width) break;
       if (i % 10 === 0) {
-        ctx.fillRect(xPos - 1, 0, 1, headerHeight - 5);
+        ctx.fillRect(xPos, 0, 1, headerHeight - 5);
         ctx.fillText(timeToString(t - this.totTime.start), xPos + 5, 18);
       } else {
-        ctx.fillRect(xPos - 1, 0, 1, 5);
+        ctx.fillRect(xPos, 0, 1, 5);
       }
     }
 
@@ -100,7 +97,7 @@
     }
 
     // Draw bottom border.
-    ctx.fillStyle = '#dadada';
+    ctx.fillStyle = 'hsl(219, 40%, 50%)';
     ctx.fillRect(0, size.height - 1, this.width, 1);
 
     // Draw semi-opaque rects that occlude the non-visible time range.
@@ -109,15 +106,11 @@
     const vizEndPx = Math.ceil(this.timeScale.timeToPx(vizTime.end));
 
     ctx.fillStyle = 'rgba(200, 200, 200, 0.8)';
-    ctx.fillRect(
-        TRACK_SHELL_WIDTH - 1,
-        headerHeight,
-        vizStartPx - TRACK_SHELL_WIDTH,
-        tracksHeight);
+    ctx.fillRect(0, headerHeight, vizStartPx, tracksHeight);
     ctx.fillRect(vizEndPx, headerHeight, this.width - vizEndPx, tracksHeight);
 
     // Draw brushes.
-    ctx.fillStyle = '#999';
+    ctx.fillStyle = '#333';
     ctx.fillRect(vizStartPx - 1, headerHeight, 1, tracksHeight);
     ctx.fillRect(vizEndPx, headerHeight, 1, tracksHeight);
   }
diff --git a/ui/src/frontend/pages.ts b/ui/src/frontend/pages.ts
index 3f3e29f..06bff8c 100644
--- a/ui/src/frontend/pages.ts
+++ b/ui/src/frontend/pages.ts
@@ -39,22 +39,46 @@
   }
 }
 
+const TogglePerfDebugButton = {
+  view() {
+    return m(
+        '.perf-monitor-button',
+        m('button',
+          {
+            onclick: () => globals.frontendLocalState.togglePerfDebug(),
+          },
+          m('i.material-icons',
+            {
+              title: 'Toggle Perf Debug Mode',
+            },
+            'assessment')));
+  }
+};
+
+const PerfStats: m.Component = {
+  view() {
+    const perfDebug = globals.frontendLocalState.perfDebug;
+    const children = [m(TogglePerfDebugButton)];
+    if (perfDebug) {
+      children.unshift(m('.perf-stats-content'));
+    }
+    return m(`.perf-stats[expanded=${perfDebug}]`, children);
+  }
+};
+
 /**
  * Wrap component with common UI elements (nav bar etc).
  */
 export function createPage(component: m.Component): m.Component {
   const pageComponent = {
     view() {
-      const children = [
+      return [
         m(Sidebar),
         m(Topbar),
         m(Alerts),
         m(component),
+        m(PerfStats),
       ];
-      if (globals.frontendLocalState.perfDebug) {
-        children.push(m('.perf-stats'));
-      }
-      return children;
     },
   };
 
diff --git a/ui/src/frontend/pan_and_zoom_handler.ts b/ui/src/frontend/pan_and_zoom_handler.ts
index e771abb..e9740af 100644
--- a/ui/src/frontend/pan_and_zoom_handler.ts
+++ b/ui/src/frontend/pan_and_zoom_handler.ts
@@ -13,39 +13,27 @@
 // limitations under the License.
 
 import {Animation} from './animation';
+import Timer = NodeJS.Timer;
 import {DragGestureHandler} from './drag_gesture_handler';
 import {globals} from './globals';
 import {handleKey} from './keyboard_event_handler';
 import {TRACK_SHELL_WIDTH} from './track_constants';
 
-// When first starting to pan or zoom, move at least this many units.
-const INITIAL_PAN_STEP_PX = 50;
-const INITIAL_ZOOM_STEP = 0.1;
-
-// The snappiness (spring constant) of pan and zoom animations [0..1].
-const SNAP_FACTOR = 0.4;
-
-// How much the velocity of a pan or zoom animation increases per millisecond.
-const ACCELERATION_PER_MS = 1 / 50;
-
-// The default duration of a pan or zoom animation. The animation may run longer
-// if the user keeps holding the respective button down or shorter if the button
-// is released. This value so chosen so that it is longer than the typical key
-// repeat timeout to avoid breaks in the animation.
-const DEFAULT_ANIMATION_DURATION = 700;
-
-// The minimum number of units to pan or zoom per frame (before the
-// ACCELERATION_PER_MS multiplier is applied).
 const ZOOM_RATIO_PER_FRAME = 0.008;
 const KEYBOARD_PAN_PX_PER_FRAME = 8;
-
-// Scroll wheel animation steps.
 const HORIZONTAL_WHEEL_PAN_SPEED = 1;
 const WHEEL_ZOOM_SPEED = -0.02;
 
-const EDITING_RANGE_CURSOR = 'ew-resize';
-const SHIFT_CURSOR = 'text';
-const DEFAULT_CURSOR = 'default';
+// Usually, animations are cancelled on keyup. However, in case the keyup
+// event is not captured by the document, e.g. if it loses focus first, then
+// we want to stop the animation as soon as possible.
+const ANIMATION_AUTO_END_AFTER_INITIAL_KEYPRESS_MS = 700;
+// This value must be larger than the maximum delta between keydown repeat
+// events. Largest observed value so far: 86ms.
+const ANIMATION_AUTO_END_AFTER_KEYPRESS_MS = 100;
+
+// This defines the step size for an individual pan or zoom keyboard tap.
+const TAP_ANIMATION_TIME = 200;
 
 enum Pan {
   None = 0,
@@ -53,9 +41,8 @@
   Right = 1
 }
 function keyToPan(e: KeyboardEvent): Pan {
-  const key = e.key.toLowerCase();
-  if (['a'].includes(key)) return Pan.Left;
-  if (['d', 'e'].includes(key)) return Pan.Right;
+  if (['a'].includes(e.key)) return Pan.Left;
+  if (['d'].includes(e.key)) return Pan.Right;
   return Pan.None;
 }
 
@@ -65,9 +52,8 @@
   Out = -1
 }
 function keyToZoom(e: KeyboardEvent): Zoom {
-  const key = e.key.toLowerCase();
-  if (['w', ','].includes(key)) return Zoom.In;
-  if (['s', 'o'].includes(key)) return Zoom.Out;
+  if (['w'].includes(e.key)) return Zoom.In;
+  if (['s'].includes(e.key)) return Zoom.Out;
   return Zoom.None;
 }
 
@@ -83,11 +69,9 @@
   private shiftDown = false;
   private dragStartPx = -1;
   private panning: Pan = Pan.None;
-  private panOffsetPx = 0;
-  private targetPanOffsetPx = 0;
   private zooming: Zoom = Zoom.None;
-  private zoomRatio = 0;
-  private targetZoomRatio = 0;
+  private cancelPanTimeout?: Timer;
+  private cancelZoomTimeout?: Timer;
   private panAnimation = new Animation(this.onPanAnimationStep.bind(this));
   private zoomAnimation = new Animation(this.onZoomAnimationStep.bind(this));
 
@@ -95,28 +79,20 @@
   private contentOffsetX: number;
   private onPanned: (movedPx: number) => void;
   private onZoomed: (zoomPositionPx: number, zoomRatio: number) => void;
-  private shouldDrag: (currentPx: number) => boolean;
-  private onDrag:
-      (dragStartPx: number, prevPx: number, currentPx: number,
-       editing: boolean) => void;
+  private onDragSelect: (selectStartPx: number, selectEndPx: number) => void;
 
-  constructor(
-      {element, contentOffsetX, onPanned, onZoomed, shouldDrag, onDrag}: {
-        element: HTMLElement,
-        contentOffsetX: number,
-        onPanned: (movedPx: number) => void,
-        onZoomed: (zoomPositionPx: number, zoomRatio: number) => void,
-        shouldDrag: (currentPx: number) => boolean,
-        onDrag:
-            (dragStartPx: number, prevPx: number, currentPx: number,
-             editing: boolean) => void,
-      }) {
+  constructor({element, contentOffsetX, onPanned, onZoomed, onDragSelect}: {
+    element: HTMLElement,
+    contentOffsetX: number,
+    onPanned: (movedPx: number) => void,
+    onZoomed: (zoomPositionPx: number, zoomRatio: number) => void,
+    onDragSelect: (selectStartPx: number, selectEndPx: number) => void
+  }) {
     this.element = element;
     this.contentOffsetX = contentOffsetX;
     this.onPanned = onPanned;
     this.onZoomed = onZoomed;
-    this.shouldDrag = shouldDrag;
-    this.onDrag = onDrag;
+    this.onDragSelect = onDragSelect;
 
     document.body.addEventListener('keydown', this.boundOnKeyDown);
     document.body.addEventListener('keyup', this.boundOnKeyUp);
@@ -124,40 +100,23 @@
     this.element.addEventListener('wheel', this.boundOnWheel, {passive: true});
 
     let lastX = -1;
-    let drag = false;
-    new DragGestureHandler(
-        this.element,
-        x => {
-          // If we started our drag on a time range boundary or shift is down
-          // then we are drag selecting rather than panning.
-          if (drag || this.shiftDown) {
-            this.onDrag(this.dragStartPx, lastX, x, !this.shiftDown);
-          } else {
-            this.onPanned(lastX - x);
-          }
-          lastX = x;
-        },
-        x => {
-          lastX = x;
-          this.dragStartPx = x;
-          drag = this.shouldDrag(x);
-          // Set the cursor style based on where the cursor is when the drag
-          // starts.
-          if (drag) {
-            this.element.style.cursor = EDITING_RANGE_CURSOR;
-          } else if (this.shiftDown) {
-            this.element.style.cursor = SHIFT_CURSOR;
-          }
-        },
-        () => {
-          // Reset the cursor now the drag has ended.
-          this.element.style.cursor =
-              this.shiftDown ? SHIFT_CURSOR : DEFAULT_CURSOR;
-          this.dragStartPx = -1;
-        });
+    new DragGestureHandler(this.element, x => {
+      if (this.shiftDown && this.dragStartPx !== -1) {
+        this.onDragSelect(this.dragStartPx, x);
+      } else {
+        this.onPanned(lastX - x);
+      }
+      lastX = x;
+    }, x => {
+      lastX = x;
+      if (this.shiftDown) {
+        this.dragStartPx = x;
+      }
+    }, () => {
+      this.dragStartPx = -1;
+    });
   }
 
-
   shutdown() {
     document.body.removeEventListener('keydown', this.boundOnKeyDown);
     document.body.removeEventListener('keyup', this.boundOnKeyUp);
@@ -166,60 +125,26 @@
   }
 
   private onPanAnimationStep(msSinceStartOfAnimation: number) {
-    const step = (this.targetPanOffsetPx - this.panOffsetPx) * SNAP_FACTOR;
-    if (this.panning !== Pan.None) {
-      const velocity = 1 + msSinceStartOfAnimation * ACCELERATION_PER_MS;
-      // Pan at least as fast as the snapping animation to avoid a
-      // discontinuity.
-      const targetStep = Math.max(KEYBOARD_PAN_PX_PER_FRAME * velocity, step);
-      this.targetPanOffsetPx += this.panning * targetStep;
-    }
-    this.panOffsetPx += step;
-    if (Math.abs(step) > 1e-1) {
-      this.onPanned(step);
-    } else {
-      this.panAnimation.stop();
-    }
+    if (this.panning === Pan.None) return;
+    let offset = this.panning * KEYBOARD_PAN_PX_PER_FRAME;
+    offset *= Math.max(msSinceStartOfAnimation / 40, 1);
+    this.onPanned(offset);
   }
 
   private onZoomAnimationStep(msSinceStartOfAnimation: number) {
-    if (this.mousePositionX === null) return;
-    const step = (this.targetZoomRatio - this.zoomRatio) * SNAP_FACTOR;
-    if (this.zooming !== Zoom.None) {
-      const velocity = 1 + msSinceStartOfAnimation * ACCELERATION_PER_MS;
-      // Zoom at least as fast as the snapping animation to avoid a
-      // discontinuity.
-      const targetStep = Math.max(ZOOM_RATIO_PER_FRAME * velocity, step);
-      this.targetZoomRatio += this.zooming * targetStep;
-    }
-    this.zoomRatio += step;
-    if (Math.abs(step) > 1e-6) {
-      this.onZoomed(this.mousePositionX, step);
-    } else {
-      this.zoomAnimation.stop();
-    }
+    if (this.zooming === Zoom.None || this.mousePositionX === null) return;
+    let zoomRatio = this.zooming * ZOOM_RATIO_PER_FRAME;
+    zoomRatio *= Math.max(msSinceStartOfAnimation / 40, 1);
+    this.onZoomed(this.mousePositionX, zoomRatio);
   }
 
   private onMouseMove(e: MouseEvent) {
-    const pageOffset =
-        globals.frontendLocalState.sidebarVisible ? this.contentOffsetX : 0;
-    // We can't use layerX here because there are many layers in this element.
-    this.mousePositionX = e.clientX - pageOffset;
-    // Only change the cursor when hovering, the DragGestureHandler handles
-    // changing the cursor during drag events. This avoids the problem of
-    // the cursor flickering between styles if you drag fast and get too
-    // far from the current time range.
-    if (e.buttons === 0) {
-      if (!this.shouldDrag(this.mousePositionX)) {
-        this.element.style.cursor =
-            this.shiftDown ? SHIFT_CURSOR : DEFAULT_CURSOR;
-      } else {
-        this.element.style.cursor = EDITING_RANGE_CURSOR;
-      }
-    }
+    // TODO(taylori): Content offset is 6px off, why?
+    this.mousePositionX = e.clientX - this.contentOffsetX - 6;
     if (this.shiftDown) {
       const pos = this.mousePositionX - TRACK_SHELL_WIDTH;
-      const ts = globals.frontendLocalState.timeScale.pxToTime(pos);
+      const ts =
+        globals.frontendLocalState.timeScale.pxToTime(pos);
       globals.frontendLocalState.setHoveredTimestamp(ts);
     }
   }
@@ -239,56 +164,57 @@
   private onKeyDown(e: KeyboardEvent) {
     this.updateShift(e.shiftKey);
     if (keyToPan(e) !== Pan.None) {
-      if (this.panning !== keyToPan(e)) {
-        this.panAnimation.stop();
-        this.panOffsetPx = 0;
-        this.targetPanOffsetPx = keyToPan(e) * INITIAL_PAN_STEP_PX;
-      }
       this.panning = keyToPan(e);
-      this.panAnimation.start(DEFAULT_ANIMATION_DURATION);
+      const animationTime = e.repeat ?
+          ANIMATION_AUTO_END_AFTER_KEYPRESS_MS :
+          ANIMATION_AUTO_END_AFTER_INITIAL_KEYPRESS_MS;
+      this.panAnimation.start(animationTime);
+      clearTimeout(this.cancelPanTimeout!);
     }
 
     if (keyToZoom(e) !== Zoom.None) {
-      if (this.zooming !== keyToZoom(e)) {
-        this.zoomAnimation.stop();
-        this.zoomRatio = 0;
-        this.targetZoomRatio = keyToZoom(e) * INITIAL_ZOOM_STEP;
-      }
       this.zooming = keyToZoom(e);
-      this.zoomAnimation.start(DEFAULT_ANIMATION_DURATION);
+      const animationTime = e.repeat ?
+          ANIMATION_AUTO_END_AFTER_KEYPRESS_MS :
+          ANIMATION_AUTO_END_AFTER_INITIAL_KEYPRESS_MS;
+      this.zoomAnimation.start(animationTime);
+      clearTimeout(this.cancelZoomTimeout!);
     }
 
     // Handle key events that are not pan or zoom.
-    handleKey(e, true);
+    handleKey(e.key, true);
   }
 
   private onKeyUp(e: KeyboardEvent) {
     this.updateShift(e.shiftKey);
     if (keyToPan(e) === this.panning) {
-      this.panning = Pan.None;
+      const minEndTime = this.panAnimation.startTimeMs + TAP_ANIMATION_TIME;
+      const t = minEndTime - performance.now();
+      this.cancelPanTimeout = setTimeout(() => this.panAnimation.stop(), t);
     }
     if (keyToZoom(e) === this.zooming) {
-      this.zooming = Zoom.None;
+      const minEndTime = this.zoomAnimation.startTimeMs + TAP_ANIMATION_TIME;
+      const t = minEndTime - performance.now();
+      this.cancelZoomTimeout = setTimeout(() => this.zoomAnimation.stop(), t);
     }
 
     // Handle key events that are not pan or zoom.
-    handleKey(e, false);
+    handleKey(e.key, false);
   }
 
-  // TODO(taylori): Move this shift handling into the viewer page.
   private updateShift(down: boolean) {
     if (down === this.shiftDown) return;
     this.shiftDown = down;
     if (this.shiftDown) {
       if (this.mousePositionX) {
-        this.element.style.cursor = SHIFT_CURSOR;
+        this.element.style.cursor = 'text';
         const pos = this.mousePositionX - TRACK_SHELL_WIDTH;
         const ts = globals.frontendLocalState.timeScale.pxToTime(pos);
         globals.frontendLocalState.setHoveredTimestamp(ts);
       }
     } else {
       globals.frontendLocalState.setHoveredTimestamp(-1);
-      this.element.style.cursor = DEFAULT_CURSOR;
+      this.element.style.cursor = 'default';
     }
 
     globals.frontendLocalState.setShowTimeSelectPreview(this.shiftDown);
diff --git a/ui/src/frontend/panel_container.ts b/ui/src/frontend/panel_container.ts
index 80f99c2..b6cb38f 100644
--- a/ui/src/frontend/panel_container.ts
+++ b/ui/src/frontend/panel_container.ts
@@ -25,7 +25,6 @@
   RunningStatistics,
   runningStatStr
 } from './perf';
-import {TRACK_SHELL_WIDTH} from './track_constants';
 
 /**
  * If the panel container scrolls, the backing canvas height is
@@ -40,7 +39,6 @@
 interface Attrs {
   panels: AnyAttrsVnode[];
   doesScroll: boolean;
-  kind: 'TRACKS'|'OVERVIEW'|'DETAILS';
 }
 
 export class PanelContainer implements m.ClassComponent<Attrs> {
@@ -138,7 +136,7 @@
     this.attrs = attrs;
     const renderPanel = (panel: m.Vnode) => perfDebug() ?
         m('.panel', panel, m('.debug-panel-border')) :
-        m('.panel', {key: panel.key}, panel);
+        m('.panel', panel);
 
     return m(
         '.scroll-limiter',
@@ -151,15 +149,10 @@
     const parentSizeChanged = this.readParentSizeFromDom(vnodeDom.dom);
 
     const canvasSizeShouldChange =
-        parentSizeChanged || !this.attrs.doesScroll && totalPanelHeightChanged;
+        this.attrs.doesScroll ? parentSizeChanged : totalPanelHeightChanged;
     if (canvasSizeShouldChange) {
       this.updateCanvasDimensions();
       this.repositionCanvas();
-      if (this.attrs.kind === 'TRACKS') {
-        globals.frontendLocalState.timeScale.setLimitsPx(
-            0, this.parentWidth - TRACK_SHELL_WIDTH);
-      }
-      this.redrawCanvas();
     }
   }
 
@@ -171,12 +164,7 @@
     const canvas = assertExists(ctx.canvas);
     canvas.style.height = `${this.canvasHeight}px`;
     const dpr = window.devicePixelRatio;
-    // On non-MacOS if there is a solid scroll bar it can cover important
-    // pixels, reduce the size of the canvas so it doesn't overlap with
-    // the scroll bar.
-    ctx.canvas.width =
-        (this.parentWidth - globals.frontendLocalState.getScrollbarWidth()) *
-        dpr;
+    ctx.canvas.width = this.parentWidth * dpr;
     ctx.canvas.height = this.canvasHeight * dpr;
     ctx.scale(dpr, dpr);
   }
diff --git a/ui/src/frontend/perf.ts b/ui/src/frontend/perf.ts
index 8ab8c4a..6e4093b 100644
--- a/ui/src/frontend/perf.ts
+++ b/ui/src/frontend/perf.ts
@@ -107,18 +107,17 @@
 
   renderPerfStats() {
     if (!perfDebug()) return;
-    const perfDisplayEl = document.querySelector('.perf-stats');
+    const perfDisplayEl = this.getPerfDisplayEl();
     if (!perfDisplayEl) return;
     m.render(perfDisplayEl, [
       m('section', globals.rafScheduler.renderPerfStats()),
-      m('button.close-button',
-        {
-          onclick: () => globals.frontendLocalState.togglePerfDebug(),
-        },
-        m('i.material-icons', 'close')),
       this.containers.map((c, i) => m('section', c.renderPerfStats(i)))
     ]);
   }
+
+  getPerfDisplayEl() {
+    return document.querySelector('.perf-stats-content');
+  }
 }
 
 export const perfDisplay = new PerfDisplay();
diff --git a/ui/src/frontend/post_message_handler.ts b/ui/src/frontend/post_message_handler.ts
deleted file mode 100644
index 2f5c02f..0000000
--- a/ui/src/frontend/post_message_handler.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {Actions} from '../common/actions';
-
-import {globals} from './globals';
-
-const VALID_ORIGINS = [
-  'https://chrometto.googleplex.com',
-  'https://uma.googleplex.com',
-];
-
-// The message handler supports loading traces from an ArrayBuffer.
-// There is no other requirement than sending the ArrayBuffer as the |data|
-// property. However, since this will happen across different origins, it is not
-// possible for the source website to inspect whether the message handler is
-// ready, so the message handler always replies to a 'PING' message with 'PONG',
-// which indicates it is ready to receive a trace.
-export function postMessageHandler(messageEvent: MessageEvent) {
-  if (!isOriginAllowed(messageEvent.origin)) {
-    throw new Error('Invalid origin for postMessage: ' + messageEvent.origin);
-  }
-
-  if (document.readyState !== 'complete') {
-    console.error('Not ready.');
-    return;
-  }
-
-  if (messageEvent.source === null) {
-    throw new Error('Incoming message has no source');
-  }
-
-  if (!('data' in messageEvent)) {
-    throw new Error('Incoming message has no data property');
-  }
-
-  if (messageEvent.data === 'PING') {
-    // Cross-origin messaging means we can't read |messageEvent.source|, but
-    // it still needs to be of the correct type to be able to invoke the
-    // correct version of postMessage(...).
-    const windowSource = messageEvent.source as Window;
-    windowSource.postMessage('PONG', messageEvent.origin);
-    return;
-  }
-
-  if (!(messageEvent.data instanceof ArrayBuffer)) {
-    throw new Error('Incoming message data is not an ArrayBuffer');
-  }
-
-  const buffer = messageEvent.data;
-  if (buffer.byteLength === 0) {
-    throw new Error('Incoming message trace buffer is empty');
-  }
-
-  // For external traces, we need to disable other features such as downloading
-  // and sharing a trace.
-  globals.frontendLocalState.localOnlyMode = true;
-
-  globals.dispatch(Actions.openTraceFromBuffer({buffer}));
-}
-
-// Returns whether messages from the origin should be accepted.
-function isOriginAllowed(origin: string): boolean {
-  if (VALID_ORIGINS.includes(origin)) return true;
-
-  if (new URL(origin).hostname.endsWith('corp.google.com')) return true;
-
-  return false;
-}
diff --git a/ui/src/frontend/raf_scheduler.ts b/ui/src/frontend/raf_scheduler.ts
index dd708c2..ef39f32 100644
--- a/ui/src/frontend/raf_scheduler.ts
+++ b/ui/src/frontend/raf_scheduler.ts
@@ -16,8 +16,6 @@
 
 import {assertTrue} from '../base/logging';
 
-import {globals} from './globals';
-
 import {
   debugNow,
   measure,
@@ -118,11 +116,9 @@
   private syncCanvasRedraw(nowMs: number) {
     const redrawStart = debugNow();
     if (this.isRedrawing) return;
-    globals.frontendLocalState.clearVisibleTracks();
     this.isRedrawing = true;
     for (const redraw of this.canvasRedrawCallbacks) redraw(nowMs);
     this.isRedrawing = false;
-    globals.frontendLocalState.sendVisibleTracks();
     if (perfDebug()) {
       this.perfStats.rafCanvas.addValue(debugNow() - redrawStart);
     }
diff --git a/ui/src/frontend/record_page.ts b/ui/src/frontend/record_page.ts
index 5d87f7a..79f91aa 100644
--- a/ui/src/frontend/record_page.ts
+++ b/ui/src/frontend/record_page.ts
@@ -12,21 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-
 import {produce} from 'immer';
 import * as m from 'mithril';
 
 import {Actions} from '../common/actions';
 import {MeminfoCounters, VmstatCounters} from '../common/protos';
-import {
-  AdbRecordingTarget,
-  isAndroidTarget,
-  isChromeTarget,
-  isLinuxTarget,
-  TargetOs
-} from '../common/state';
-import {MAX_TIME, RecordMode} from '../common/state';
-import {AdbOverWebUsb} from '../controller/adb';
+import {RecordMode} from '../common/state';
 
 import {globals} from './globals';
 import {createPage} from './pages';
@@ -44,7 +35,6 @@
 import {Router} from './router';
 
 
-
 const POLL_RATE_MS = [250, 500, 1000, 2500, 5000, 30000, 60000];
 
 const ATRACE_CATEGORIES = new Map<string, string>();
@@ -205,18 +195,6 @@
       } as ProbeAttrs));
 }
 
-function GpuSettings(cssClass: string) {
-  return m(
-      `.record-section${cssClass}`,
-      m(Probe, {
-        title: 'GPU frequency',
-        img: 'rec_cpu_freq.png',
-        descr: 'Records gpu frequency via ftrace',
-        setEnabled: (cfg, val) => cfg.gpuFreq = val,
-        isEnabled: (cfg) => cfg.gpuFreq
-      } as ProbeAttrs));
-}
-
 function CpuSettings(cssClass: string) {
   return m(
       `.record-section${cssClass}`,
@@ -259,111 +237,9 @@
                 task Y that X's transition (e.g. posting a semaphore).`,
         setEnabled: (cfg, val) => cfg.cpuLatency = val,
         isEnabled: (cfg) => cfg.cpuLatency
-      } as ProbeAttrs),
-      m(Probe, {
-        title: 'Syscalls',
-        img: null,
-        descr: `Tracks the enter and exit of all syscalls.`,
-        setEnabled: (cfg, val) => cfg.cpuSyscall = val,
-        isEnabled: (cfg) => cfg.cpuSyscall
       } as ProbeAttrs));
 }
 
-function HeapSettings(cssClass: string) {
-  const valuesForMS = [
-    0,
-    1000,
-    10 * 1000,
-    30 * 1000,
-    60 * 1000,
-    5 * 60 * 1000,
-    10 * 60 * 1000,
-    30 * 60 * 1000,
-    60 * 60 * 1000
-  ];
-  const valuesForShMemBuff = [
-    0,
-    512,
-    1024,
-    2 * 1024,
-    4 * 1024,
-    8 * 1024,
-    16 * 1024,
-    32 * 1024,
-    64 * 1024,
-    128 * 1024,
-    256 * 1024,
-    512 * 1024,
-    1024 * 1024,
-    64 * 1024 * 1024,
-    128 * 1024 * 1024,
-    256 * 1024 * 1024,
-    512 * 1024 * 1024
-  ];
-
-  return m(
-      `.record-section${cssClass}`,
-      m(Textarea, {
-        title: 'Names or pids of the processes to track',
-        placeholder: 'One per line, e.g.:\n' +
-            'system_server\n' +
-            '1503',
-        set: (cfg, val) => cfg.hpProcesses = val,
-        get: (cfg) => cfg.hpProcesses
-      } as TextareaAttrs),
-      m(Slider, {
-        title: 'Sampling interval',
-        cssClass: '.thin',
-        values: [
-          0,     1,     2,      4,      8,      16,     32,   64,
-          128,   256,   512,    1024,   2048,   4096,   8192, 16384,
-          32768, 65536, 131072, 262144, 524288, 1048576
-        ],
-        unit: 'B',
-        min: 0,
-        set: (cfg, val) => cfg.hpSamplingIntervalBytes = val,
-        get: (cfg) => cfg.hpSamplingIntervalBytes
-      } as SliderAttrs),
-      m(Slider, {
-        title: 'Continuous dumps interval ',
-        description: 'Time between following dumps (0 = disabled)',
-        cssClass: '.thin',
-        values: valuesForMS,
-        unit: 'ms',
-        min: 0,
-        set: (cfg, val) => {
-          cfg.hpContinuousDumpsInterval = val;
-        },
-        get: (cfg) => cfg.hpContinuousDumpsInterval
-      } as SliderAttrs),
-      m(Slider, {
-        title: 'Continuous dumps phase',
-        description: 'Time before first dump',
-        cssClass: `.thin${
-            globals.state.recordConfig.hpContinuousDumpsInterval === 0 ?
-                '.greyed-out' :
-                ''}`,
-        values: valuesForMS,
-        unit: 'ms',
-        min: 0,
-        disabled: globals.state.recordConfig.hpContinuousDumpsInterval === 0,
-        set: (cfg, val) => cfg.hpContinuousDumpsPhase = val,
-        get: (cfg) => cfg.hpContinuousDumpsPhase
-      } as SliderAttrs),
-      m(Slider, {
-        title: `Shared memory buffer`,
-        cssClass: '.thin',
-        values: valuesForShMemBuff.filter(
-            value => value === 0 || value >= 8192 && value % 4096 === 0),
-        unit: 'B',
-        min: 0,
-        set: (cfg, val) => cfg.hpSharedMemoryBuffer = val,
-        get: (cfg) => cfg.hpSharedMemoryBuffer
-      } as SliderAttrs)
-      // TODO(tneda): Add advanced options.
-  );
-}
-
 function MemorySettings(cssClass: string) {
   const meminfoOpts = new Map<string, string>();
   for (const x in MeminfoCounters) {
@@ -383,17 +259,6 @@
       `.record-section${cssClass}`,
       m(Probe,
         {
-          title: 'Heap profiling',
-          // TODO(tneda): Image should be one with flamegraphs.
-          img: 'rec_meminfo.png',
-          descr: `Track native heap allocations & deallocations of an Android
-               process. (Available on Android 10+)`,
-          setEnabled: (cfg, val) => cfg.heapProfiling = val,
-          isEnabled: (cfg) => cfg.heapProfiling
-        } as ProbeAttrs,
-        HeapSettings(cssClass)),
-      m(Probe,
-        {
           title: 'Kernel meminfo',
           img: 'rec_meminfo.png',
           descr: 'Polling of /proc/meminfo',
@@ -419,7 +284,7 @@
         title: 'High-frequency memory events',
         img: 'rec_mem_hifreq.png',
         descr: `Allows to track short memory spikes and transitories through
-                ftrace's mm_event, rss_stat and ion events. Available only
+                ftrace's mm_event, rss_stat and ion events. Avialable only
                 on recent Android Q+ kernels`,
         setEnabled: (cfg, val) => cfg.memHiFreq = val,
         isEnabled: (cfg) => cfg.memHiFreq
@@ -519,120 +384,20 @@
           options: LOG_BUFFERS,
           set: (cfg, val) => cfg.androidLogBuffers = val,
           get: (cfg) => cfg.androidLogBuffers
-        } as DropdownAttrs)));
+        } as DropdownAttrs), ));
 }
 
 
-function ChromeSettings(cssClass: string) {
-  return m(
-      `.record-section${cssClass}`,
-      m(Probe, {
-        title: 'Task scheduling',
-        img: null,
-        descr: `Records events about task scheduling and execution on all
-                  threads`,
-        setEnabled: (cfg, val) => cfg.taskScheduling = val,
-        isEnabled: (cfg) => cfg.taskScheduling
-      } as ProbeAttrs),
-      m(Probe, {
-        title: 'IPC flows',
-        img: null,
-        descr: `Records flow events for passing of IPC messages between
-                processes.`,
-        setEnabled: (cfg, val) => cfg.ipcFlows = val,
-        isEnabled: (cfg) => cfg.ipcFlows
-      } as ProbeAttrs),
-      m(Probe, {
-        title: 'Javascript execution',
-        img: null,
-        descr: `Records events about Javascript execution in the renderer
-                    processes.`,
-        setEnabled: (cfg, val) => cfg.jsExecution = val,
-        isEnabled: (cfg) => cfg.jsExecution
-      } as ProbeAttrs),
-      m(Probe, {
-        title: 'Web content rendering',
-        img: null,
-        descr: `Records events about rendering, layout, and compositing of
-        web content in Blink.`,
-        setEnabled: (cfg, val) => cfg.webContentRendering = val,
-        isEnabled: (cfg) => cfg.webContentRendering
-      } as ProbeAttrs),
-      m(Probe, {
-        title: 'UI rendering & compositing',
-        img: null,
-        descr: `Records events about rendering of browser UI surfaces and
-        compositing of surfaces.`,
-        setEnabled: (cfg, val) => cfg.uiRendering = val,
-        isEnabled: (cfg) => cfg.uiRendering
-      } as ProbeAttrs),
-      m(Probe, {
-        title: 'Input events',
-        img: null,
-        descr: `Records input events and their flow between processes.`,
-        setEnabled: (cfg, val) => cfg.inputEvents = val,
-        isEnabled: (cfg) => cfg.inputEvents
-      } as ProbeAttrs),
-      m(Probe, {
-        title: 'Navigation & Loading',
-        img: null,
-        descr: `Records network events for navigations and resources.`,
-        setEnabled: (cfg, val) => cfg.navigationAndLoading = val,
-        isEnabled: (cfg) => cfg.navigationAndLoading
-      } as ProbeAttrs),
-      m(Probe, {
-        title: 'Chrome Logs',
-        img: null,
-        descr: `Records Chrome log messages`,
-        setEnabled: (cfg, val) => cfg.chromeLogs = val,
-        isEnabled: (cfg) => cfg.chromeLogs
-      } as ProbeAttrs),
-      ChromeCategoriesSelection());
-}
-
-function ChromeCategoriesSelection() {
-  // The categories are displayed only if the extension is installed, because
-  // they come from the chrome.debugging API, not available from normal web
-  // pages.
-  const categories = globals.state.chromeCategories;
-  if (!categories) return [];
-
-  // Show "disabled-by-default" categories last.
-  const categoriesMap = new Map<string, string>();
-  const disabledByDefaultCategories: string[] = [];
-  const disabledPrefix = 'disabled-by-default-';
-  categories.forEach(cat => {
-    if (cat.startsWith(disabledPrefix)) {
-      disabledByDefaultCategories.push(cat);
-    } else {
-      categoriesMap.set(cat, cat);
-    }
-  });
-  disabledByDefaultCategories.forEach(cat => {
-    categoriesMap.set(
-        cat, `${cat.replace(disabledPrefix, '')} (high overhead)`);
-  });
-  return m(Dropdown, {
-    title: 'Additional Chrome categories',
-    cssClass: '.multicolumn.two-columns.chrome-categories',
-    options: categoriesMap,
-    set: (cfg, val) => cfg.chromeCategoriesSelected = val,
-    get: (cfg) => cfg.chromeCategoriesSelected
-  } as DropdownAttrs);
-}
-
 function AdvancedSettings(cssClass: string) {
-  const S = (x: number) => x * 1000;
-  const M = (x: number) => x * 1000 * 60;
   return m(
       `.record-section${cssClass}`,
       m(Probe,
         {
           title: 'Advanced ftrace config',
           img: 'rec_ftrace.png',
-          descr: `Enable individual events and tune the kernel-tracing (ftrace)
-                  module. The events enabled here are in addition to those from
-                  enabled by other probes.`,
+          descr: `Tunes the kernel-tracing (ftrace) module and allows to
+                    enable extra events. The events enabled here are on top
+                    of the ones derived when enabling the other probes.`,
           setEnabled: (cfg, val) => cfg.ftrace = val,
           isEnabled: (cfg) => cfg.ftrace
         } as ProbeAttrs,
@@ -665,119 +430,29 @@
               'kmem/*',
           set: (cfg, val) => cfg.ftraceExtraEvents = val,
           get: (cfg) => cfg.ftraceExtraEvents
-        } as TextareaAttrs)),
-      globals.state.videoEnabled ?
-          m(Probe,
-            {
-              title: 'Screen recording',
-              img: null,
-              descr: `Records the screen along with running a trace. Max
-                  time of recording is 3 minutes (180 seconds).`,
-          setEnabled: (cfg, val) => cfg.screenRecord = val,
-          isEnabled: (cfg) => cfg.screenRecord,
-        } as ProbeAttrs,
-        m(Slider, {
-          title: 'Max duration',
-          icon: 'timer',
-          values: [S(10), S(15), S(30), S(60), M(2), M(3)],
-          isTime: true,
-          unit: 'm:s',
-          set: (cfg, val) => cfg.durationMs = val,
-          get: (cfg) => cfg.durationMs,
-        } as SliderAttrs),) : null);
-}
-
-function RecordHeader() {
-  return m(
-      '.record-header',
-      m('.top-part',
-        m('.target-and-status',
-          RecordingPlatformSelection(),
-          RecordingStatusLabel(),
-          ErrorLabel()),
-        recordingButtons()),
-      RecordingNotes());
-}
-
-function RecordingPlatformSelection() {
-  if (globals.state.recordingInProgress) return [];
-
-  const baseTargets = [
-    m('option', {value: 'Q'}, 'Android Q+'),
-    m('option', {value: 'P'}, 'Android P'),
-    m('option', {value: 'O'}, 'Android O-'),
-    m('option', {value: 'C'}, 'Chrome'),
-    m('option', {value: 'L'}, 'Linux desktop')
-  ];
-  const availableAndroidDevices = globals.state.availableDevices;
-  const selected = globals.state.androidDeviceConnected;
-  const choices: m.Children[] =
-      availableAndroidDevices.map(d => m('option', {value: d.serial}, d.name));
-
-  const selectedIndex = selected ? baseTargets.length +
-          availableAndroidDevices.findIndex(d => d.serial === selected.serial) :
-                                   0;
-
-  return m(
-      '.target',
-      m(
-          'label',
-          'Target platform:',
-          m('select',
-            {onchange: m.withAttr('value', onTargetChange), selectedIndex},
-            ...baseTargets,
-            ...choices),
-          ),
-      m('.chip',
-        {onclick: addAndroidDevice},
-        m('button', 'Add Device'),
-        m('i.material-icons', 'add')));
-}
-
-// Target can be the targetOS or the android serial
-function onTargetChange(target: string) {
-  const adbDevice =
-      globals.state.availableDevices.find(d => d.serial === target);
-  globals.dispatch(Actions.setAndroidDevice({target: adbDevice}));
-
-  const traceCfg = produce(globals.state.recordConfig, draft => {
-    draft.targetOS = adbDevice ? adbDevice.os as TargetOs : target as TargetOs;
-  });
-  globals.dispatch(Actions.setRecordConfig({config: traceCfg}));
-  globals.rafScheduler.scheduleFullRedraw();
+        } as TextareaAttrs)));
 }
 
 function Instructions(cssClass: string) {
-  return m(
-      `.record-section.instructions${cssClass}`,
-      m('header', 'Instructions'),
-      RecordingSnippet(),
-      BufferUsageProgressBar(),
-      m('.buttons', StopCancelButtons()),
-      recordingLog());
-}
+  const data = globals.trackDataStore.get('config') as {
+    commandline: string,
+    pbtxt: string,
+  } | null;
 
-function BufferUsageProgressBar() {
-  if (!globals.state.recordingInProgress) return [];
-
-  const bufferUsage = globals.bufferUsage ? globals.bufferUsage : 0.0;
-  // Buffer usage is not available yet on Android.
-  if (bufferUsage === 0) return [];
-
-  return m(
-      'label',
-      'Buffer usage: ',
-      m('progress', {max: 100, value: bufferUsage * 100}));
-}
-
-function RecordingNotes() {
+  const pbtx = data ? data.pbtxt : '';
+  let cmd = '';
+  cmd += 'adb shell perfetto \\\n';
+  cmd += '  -c - --txt \\\n';
+  cmd += '  -o /data/misc/perfetto-traces/trace \\\n';
+  cmd += '<<EOF\n\n';
+  cmd += pbtx;
+  cmd += '\nEOF\n';
   const docUrl = '//docs.perfetto.dev/#/build-instructions?id=get-the-code';
-  const extensionURL = `https://chrome.google.com/webstore/a/google.com/detail/
-      perfetto-ui/lfmkphfpdbjijhpomgecfikhfohaoine`;
+
 
   const notes: m.Children = [];
   const doc =
-      m('span', 'Follow the ', m('a', {href: docUrl}, 'instructions here.'));
+      m('span', 'Follow the ', m('a', {href: docUrl}, 'instructions here'));
 
   const msgFeatNotSupported =
       m('div', `Some of the probes are only supported in the
@@ -792,18 +467,9 @@
          perfetto. `,
         doc);
 
-  const msgChrome =
-      m('div',
-        `To trace Chrome from the Perfetto UI, you need to install our `,
-        m('a', {href: extensionURL}, 'Chrome extension'),
-        ' and then reload this page.');
-
   const msgLinux =
-      m('div',
-        `In order to use perfetto on Linux you need to
-      compile it and run the following command from the build
-      output directory. `,
-        doc);
+      m('div', `In order to use perfetto on Linux you need to
+      compile it and run from the standalone build. `, doc);
 
   switch (globals.state.recordConfig.targetOS) {
     case 'Q':
@@ -819,279 +485,40 @@
     case 'L':
       notes.push(msgLinux);
       break;
-    case 'C':
-      if (!globals.state.extensionInstalled) notes.push(msgChrome);
-      break;
     default:
   }
 
-  return notes.length > 0 ? m('.note', notes) : [];
-}
-
-function RecordingSnippet() {
-  const targetOs = globals.state.recordConfig.targetOS;
-
-  // We don't need commands to start tracing on chrome
-  if (isChromeTarget(targetOs)) {
-    return globals.state.extensionInstalled ?
-        m('div',
-          m('label',
-            `To trace Chrome from the Perfetto UI you just have to press
-         'Start Recording'.`)) :
-        [];
-  }
-  return m(
-      CodeSnippet, {text: getRecordCommand(targetOs), hardWhitespace: true});
-}
-
-function getRecordCommand(targetOs: TargetOs) {
-  const data = globals.trackDataStore.get('config') as
-          {commandline: string, pbtxt: string} |
-      null;
-
-  const cfg = globals.state.recordConfig;
-  let time = cfg.durationMs / 1000;
-
-  if (time > MAX_TIME) {
-    time = MAX_TIME;
-  }
-
-  const pbtx = data ? data.pbtxt : '';
-  let cmd = '';
-  if (cfg.screenRecord) {
-    // Half-second delay to ensure Perfetto starts tracing before screenrecord
-    // starts recording
-    cmd += `(sleep 0.5 && adb shell screenrecord --time-limit ${time}`;
-    cmd += ' "/sdcard/tracescr.mp4") &\\\n';
-  }
-  cmd +=
-      isAndroidTarget(targetOs) ? 'adb shell perfetto \\\n' : 'perfetto \\\n';
-  cmd += '  -c - --txt \\\n';
-  cmd += '  -o /data/misc/perfetto-traces/trace \\\n';
-  cmd += '<<EOF\n\n';
-  cmd += pbtx;
-  cmd += '\nEOF\n';
-
-  return cmd;
-}
-
-function recordingButtons() {
-  const state = globals.state;
-  const realDeviceTarget = state.androidDeviceConnected !== undefined;
-  const recInProgress = state.recordingInProgress;
-
-  const start =
-      m(`button`,
-        {
-          class: recInProgress ? '' : 'selected',
-          onclick: onStartRecordingPressed
-        },
-        'Start Recording');
-  const showCmd =
-      m(`button`,
-        {
-          onclick: () => {
-            location.href = '#!/record?p=instructions';
-            globals.rafScheduler.scheduleFullRedraw();
-          }
-        },
-        'Show Command');
-
-  const buttons: m.Children = [];
-
-  const targetOs = state.recordConfig.targetOS;
-  if (isAndroidTarget(targetOs)) {
-    if (!recInProgress) {
-      buttons.push(showCmd);
-      if (realDeviceTarget) buttons.push(start);
-    }
-  } else if (isChromeTarget(targetOs) && state.extensionInstalled) {
-    buttons.push(start);
-  } else if (isLinuxTarget(targetOs)) {
-    buttons.push(showCmd);
-  }
-
-  return m('.button', buttons);
-}
-
-function StopCancelButtons() {
-  if (!globals.state.recordingInProgress) return [];
-
-  const stop =
-      m(`button.selected`,
-        {onclick: () => globals.dispatch(Actions.stopRecording({}))},
-        'Stop');
-
-  const cancel =
-      m(`button`,
-        {onclick: () => globals.dispatch(Actions.cancelRecording({}))},
-        'Cancel');
-
-  return [stop, cancel];
-}
-
-function onStartRecordingPressed() {
-  location.href = '#!/record?p=instructions';
-  globals.rafScheduler.scheduleFullRedraw();
-
-  const targetOs = globals.state.recordConfig.targetOS;
-  if (isAndroidTarget(targetOs) || isChromeTarget(targetOs)) {
-    globals.dispatch(Actions.startRecording({}));
-  }
-}
-
-function RecordingStatusLabel() {
-  const recordingStatus = globals.state.recordingStatus;
-  if (!recordingStatus) return [];
-  return m('label', recordingStatus);
-}
-
-function ErrorLabel() {
-  const lastRecordingError = globals.state.lastRecordingError;
-  if (!lastRecordingError) return [];
-  return m('label.error-label', `Error:  ${lastRecordingError}`);
-}
-
-function recordingLog() {
-  const logs = globals.recordingLog;
-  if (logs === undefined) return [];
-  return m('.code-snippet.no-top-bar', m('code', logs));
-}
-
-// The connection must be done in the frontend. After it, the serial ID will
-// be inserted in the state, and the worker will be able to connect to the
-// correct device.
-async function addAndroidDevice() {
-  const device = await new AdbOverWebUsb().findDevice();
-
-  if (!device.serialNumber) {
-    console.error('serial number undefined');
-    return;
-  }
-  // After the user has selected a device with the chrome UI, it will be
-  // available when listing all the available device from WebUSB. Therefore,
-  // we update the list of available devices.
-  await updateAvailableAdbDevices();
-  onTargetChange(device.serialNumber);
-}
-
-export async function updateAvailableAdbDevices() {
-  const devices = await new AdbOverWebUsb().getPairedDevices();
-
-  const availableAdbDevices: AdbRecordingTarget[] = [];
-  devices.forEach(d => {
-    if (d.productName && d.serialNumber) {
-      // TODO(nicomazz): At this stage, we can't know the OS version, so we
-      // assume it is 'Q'. This can create problems with devices with an old
-      // version of perfetto. The os detection should be done after the adb
-      // connection, from adb_record_controller
-      availableAdbDevices.push(
-          {name: d.productName, serial: d.serialNumber, os: 'Q'});
-    }
-  });
-
-  globals.dispatch(Actions.setAvailableDevices({devices: availableAdbDevices}));
-  selectAndroidDeviceIfAvailable(availableAdbDevices);
-  globals.rafScheduler.scheduleFullRedraw();
-  return availableAdbDevices;
-}
-
-function selectAndroidDeviceIfAvailable(
-    availableAdbDevices: AdbRecordingTarget[]) {
-  // If there is an android device attached, but not selected, select it by
-  // default.
-  if (!globals.state.androidDeviceConnected && availableAdbDevices.length) {
-    globals.dispatch(
-        Actions.setAndroidDevice({target: availableAdbDevices[0]}));
-    return;
-  }
-
-  // If a device was selected, but it's not available anymore, reset the
-  // androidConnectedDevice to null.
-  const deviceConnected = globals.state.androidDeviceConnected;
-  if (deviceConnected &&
-      availableAdbDevices.find(e => e.serial === deviceConnected.serial) ===
-          undefined) {
-    globals.dispatch(Actions.setAndroidDevice({target: undefined}));
-  }
-}
-
-function recordMenu(routePage: string) {
-  const targetOS = globals.state.recordConfig.targetOS;
-  const chromeProbe =
-      m('a[href="#!/record?p=chrome"]',
-        m(`li${routePage === 'chrome' ? '.active' : ''}`,
-          m('i.material-icons', 'laptop_chromebook'),
-          m('.title', 'Chrome'),
-          m('.sub', 'Chrome traces')));
-  const recInProgress = globals.state.recordingInProgress;
+  const onOsChange = (os: string) => {
+    const traceCfg = produce(globals.state.recordConfig, draft => {
+      draft.targetOS = os;
+    });
+    globals.dispatch(Actions.setRecordConfig({config: traceCfg}));
+  };
 
   return m(
-      '.record-menu',
-      {
-        class: recInProgress ? 'disabled' : '',
-        onclick: () => globals.rafScheduler.scheduleFullRedraw()
-      },
-      m('header', 'Trace config'),
-      m('ul',
-        m('a[href="#!/record?p=buffers"]',
-          m(`li${routePage === 'buffers' ? '.active' : ''}`,
-            m('i.material-icons', 'tune'),
-            m('.title', 'Recording settings'),
-            m('.sub', 'Buffer mode, size and duration'))),
-        m('a[href="#!/record?p=instructions"]',
-          m(`li${routePage === 'instructions' ? '.active' : ''}`,
-            m('i.material-icons.rec', 'fiber_manual_record'),
-            m('.title', 'Instructions'),
-            m('.sub', 'Generate config and instructions')))),
-      m('header', 'Probes'),
-      m('ul', isChromeTarget(targetOS) ? [chromeProbe] : [
-        m('a[href="#!/record?p=cpu"]',
-          m(`li${routePage === 'cpu' ? '.active' : ''}`,
-            m('i.material-icons', 'subtitles'),
-            m('.title', 'CPU'),
-            m('.sub', 'CPU usage, scheduling, wakeups'))),
-        m('a[href="#!/record?p=gpu"]',
-          m(`li${routePage === 'gpu' ? '.active' : ''}`,
-            m('i.material-icons', 'aspect_ratio'),
-            m('.title', 'GPU'),
-            m('.sub', 'GPU frequency'))),
-        m('a[href="#!/record?p=power"]',
-          m(`li${routePage === 'power' ? '.active' : ''}`,
-            m('i.material-icons', 'battery_charging_full'),
-            m('.title', 'Power'),
-            m('.sub', 'Battery and other energy counters'))),
-        m('a[href="#!/record?p=memory"]',
-          m(`li${routePage === 'memory' ? '.active' : ''}`,
-            m('i.material-icons', 'memory'),
-            m('.title', 'Memory'),
-            m('.sub', 'Physical mem, VM, LMK'))),
-        m('a[href="#!/record?p=android"]',
-          m(`li${routePage === 'android' ? '.active' : ''}`,
-            m('i.material-icons', 'android'),
-            m('.title', 'Android apps & svcs'),
-            m('.sub', 'atrace and logcat'))),
-        chromeProbe,
-        m('a[href="#!/record?p=advanced"]',
-          m(`li${routePage === 'advanced' ? '.active' : ''}`,
-            m('i.material-icons', 'settings'),
-            m('.title', 'Advanced settings'),
-            m('.sub', 'Complicated stuff for wizards')))
-      ]));
+      `.record-section.instructions${cssClass}`,
+      m('header', 'Instructions'),
+      m('label',
+        'Select target platform',
+        m('select',
+          {onchange: m.withAttr('value', onOsChange)},
+          m('option', {value: 'Q'}, 'Android Q+'),
+          m('option', {value: 'P'}, 'Android P'),
+          m('option', {value: 'O'}, 'Android O-'),
+          m('option', {value: 'L'}, 'Linux desktop'))),
+      notes.length > 0 ? m('.note', notes) : [],
+      m(CodeSnippet, {text: cmd, hardWhitespace: true}), );
 }
 
-
 export const RecordPage = createPage({
   view() {
     const SECTIONS: {[property: string]: (cssClass: string) => m.Child} = {
       buffers: RecSettings,
       instructions: Instructions,
       cpu: CpuSettings,
-      gpu: GpuSettings,
       power: PowerSettings,
       memory: MemorySettings,
       android: AndroidSettings,
-      chrome: ChromeSettings,
       advanced: AdvancedSettings,
     };
 
@@ -1107,7 +534,47 @@
 
     return m(
         '.record-page',
-        globals.state.recordingInProgress ? m('.hider') : [],
-        m('.record-container', RecordHeader(), recordMenu(routePage), pages));
+        m('.record-container',
+          m('.record-menu',
+            m('header', 'Trace config'),
+            m('ul',
+              m('a[href="#!/record?p=buffers"]',
+                m(`li${routePage === 'buffers' ? '.active' : ''}`,
+                  m('i.material-icons', 'tune'),
+                  m('.title', 'Recording settings'),
+                  m('.sub', 'Buffer mode, size and duration'))),
+              m('a[href="#!/record?p=instructions"]',
+                m(`li${routePage === 'instructions' ? '.active' : ''}`,
+                  m('i.material-icons.rec', 'fiber_manual_record'),
+                  m('.title', 'Start recording'),
+                  m('.sub', 'Generate config and instructions'))), ),
+            m('header', 'Probes'),
+            m('ul',
+              m('a[href="#!/record?p=cpu"]',
+                m(`li${routePage === 'cpu' ? '.active' : ''}`,
+                  m('i.material-icons', 'subtitles'),
+                  m('.title', 'CPU'),
+                  m('.sub', 'CPU usage, scheduling, wakeups'))),
+              m('a[href="#!/record?p=power"]',
+                m(`li${routePage === 'power' ? '.active' : ''}`,
+                  m('i.material-icons', 'battery_charging_full'),
+                  m('.title', 'Power'),
+                  m('.sub', 'Battery and other energy counters'))),
+              m('a[href="#!/record?p=memory"]',
+                m(`li${routePage === 'memory' ? '.active' : ''}`,
+                  m('i.material-icons', 'memory'),
+                  m('.title', 'Memory'),
+                  m('.sub', 'Physical mem, VM, LMK'))),
+              m('a[href="#!/record?p=android"]',
+                m(`li${routePage === 'android' ? '.active' : ''}`,
+                  m('i.material-icons', 'android'),
+                  m('.title', 'Android apps & svcs'),
+                  m('.sub', 'atrace and logcat'))),
+              m('a[href="#!/record?p=advanced"]',
+                m(`li${routePage === 'advanced' ? '.active' : ''}`,
+                  m('i.material-icons', 'settings'),
+                  m('.title', 'Advanced settings'),
+                  m('.sub', 'Complicated stuff for wizards'))), )),
+          pages));
   }
 });
diff --git a/ui/src/frontend/record_widgets.ts b/ui/src/frontend/record_widgets.ts
index 3d683f7..df3d803 100644
--- a/ui/src/frontend/record_widgets.ts
+++ b/ui/src/frontend/record_widgets.ts
@@ -32,7 +32,7 @@
 
 export interface ProbeAttrs {
   title: string;
-  img: string|null;
+  img: string;
   descr: string;
   isEnabled: Getter<boolean>;
   setEnabled: Setter<boolean>;
@@ -51,10 +51,7 @@
 
     return m(
         `.probe${enabled ? '.enabled' : ''}`,
-        attrs.img && m('img', {
-          src: `assets/${attrs.img}`,
-          onclick: () => onToggle(!enabled),
-        }),
+        m(`img[src=assets/${attrs.img}]`, {onclick: () => onToggle(!enabled)}),
         m('label',
           m(`input[type=checkbox]`,
             {checked: enabled, oninput: m.withAttr('checked', onToggle)}),
@@ -76,9 +73,6 @@
   values: number[];
   get: Getter<number>;
   set: Setter<number>;
-  min?: number;
-  description?: string;
-  disabled?: boolean;
 }
 
 export class Slider implements m.ClassComponent<SliderAttrs> {
@@ -106,9 +100,6 @@
     const id = attrs.title.replace(/[^a-z0-9]/gmi, '_').toLowerCase();
     const maxIdx = attrs.values.length - 1;
     const val = attrs.get(globals.state.recordConfig);
-    const min = attrs.min;
-    const description = attrs.description;
-    const disabled = attrs.disabled;
 
     // Find the index of the closest value in the slider.
     let idx = 0;
@@ -133,13 +124,10 @@
     return m(
         '.slider' + (attrs.cssClass || ''),
         m('header', attrs.title),
-        description ? m('header.descr', attrs.description) : '',
         attrs.icon !== undefined ? m('i.material-icons', attrs.icon) : [],
-        m(`input[id="${id}"][type=range][min=0][max=${maxIdx}][value=${idx}]
-        ${disabled ? '[disabled]' : ''}`,
+        m(`input[id="${id}"][type=range][min=0][max=${maxIdx}][value=${idx}]`,
           {oninput: m.withAttr('value', v => this.onSliderChange(attrs, v))}),
-        m(`input.spinner[min=${min !== undefined ? min : 1}][for=${id}]`,
-          spinnerCfg),
+        m(`input.spinner[min=1][for=${id}]`, spinnerCfg),
         m('.unit', attrs.unit));
   }
 }
@@ -215,7 +203,6 @@
   cssClass?: string;
   get: Getter<string>;
   set: Setter<string>;
-  title?: string;
 }
 
 export class Textarea implements m.ClassComponent<TextareaAttrs> {
@@ -227,15 +214,12 @@
   }
 
   view({attrs}: m.CVnode<TextareaAttrs>) {
-    return m(
-        '.textarea-holder',
-        m('header', attrs.title),
-        m(`textarea.extra-input${attrs.cssClass || ''}`, {
-          onchange: (e: Event) =>
-              this.onChange(attrs, e.target as HTMLTextAreaElement),
-          placeholder: attrs.placeholder,
-          value: attrs.get(globals.state.recordConfig)
-        }));
+    return m(`textarea.extra-input${attrs.cssClass || ''}`, {
+      onchange: (e: Event) =>
+          this.onChange(attrs, e.target as HTMLTextAreaElement),
+      placeholder: attrs.placeholder,
+      value: attrs.get(globals.state.recordConfig)
+    });
   }
 }
 
diff --git a/ui/src/frontend/rpc_http_dialog.ts b/ui/src/frontend/rpc_http_dialog.ts
deleted file mode 100644
index 37ee823..0000000
--- a/ui/src/frontend/rpc_http_dialog.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-// 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.
-
-import '../tracks/all_frontend';
-import * as m from 'mithril';
-
-import {Actions} from '../common/actions';
-import {HttpRpcEngine, RPC_URL} from '../common/http_rpc_engine';
-
-import {globals} from './globals';
-import {showModal} from './modal';
-
-const PROMPT = `Trace Processor Native Accelerator detected on ${RPC_URL} with:
-$loadedTraceName
-
-YES, use loaded trace:
-Will load from the current state of Trace Processor. If you did run
-trace_processor_shell --http file.pftrace this is likely what you want.
-
-YES, but reset state:
-Use this if you want to open another trace but still use the
-accelerator. This is the equivalent of killing and restarting
-trace_processor_shell --http.
-
-NO, Use builtin WASM:
-Will not use the accelerator in this tab.
-
-Using the native accelerator has some minor caveats:
-- Only one tab can be using the accelerator.
-- Sharing, downloading and conversion-to-legacy aren't supported.
-`;
-
-// Try to connect to the external Trace Processor HTTP RPC accelerator (if
-// available, often it isn't). If connected it will populate the
-// |httpRpcState| in the frontend local state. In turn that will show the UI
-// chip in the sidebar. trace_controller.ts will repeat this check before
-// trying to load a new trace. We do this ahead of time just to have a
-// consistent UX (i.e. so that the user can tell if the RPC is working without
-// having to open a trace).
-export async function CheckHttpRpcConnection(): Promise<void> {
-  const state = await HttpRpcEngine.checkConnection();
-  globals.frontendLocalState.setHttpRpcState(state);
-
-  // If a trace is already loaded in the trace processor (e.g., the user
-  // launched trace_processor_shell -D trace_file.pftrace), prompt the user to
-  // initialize the UI with the already-loaded trace.
-  if (state.connected && state.loadedTraceName) {
-    showModal({
-      title: 'Use Trace Processor Native Acceleration?',
-      content:
-          m('.modal-pre',
-            PROMPT.replace('$loadedTraceName', state.loadedTraceName)),
-      buttons: [
-        {
-          text: 'YES, use loaded trace',
-          primary: true,
-          id: 'rpc_load',
-          action: () => {
-            globals.dispatch(Actions.openTraceFromHttpRpc({}));
-          }
-        },
-        {
-          text: 'YES, but reset state',
-          primary: false,
-          id: 'rpc_reset',
-          action: () => {}
-        },
-        {
-          text: 'NO, Use builtin WASM',
-          primary: false,
-          id: 'rpc_force_wasm',
-          action: () => {
-            globals.dispatch(
-                Actions.setNewEngineMode({mode: 'FORCE_BUILTIN_WASM'}));
-          }
-        },
-      ],
-    });
-  }
-}
diff --git a/ui/src/frontend/scroll_helper.ts b/ui/src/frontend/scroll_helper.ts
deleted file mode 100644
index 431e041..0000000
--- a/ui/src/frontend/scroll_helper.ts
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {Actions} from '../common/actions';
-import {getContainingTrackId} from '../common/state';
-import {fromNs, TimeSpan, toNs} from '../common/time';
-
-import {globals} from './globals';
-
-/**
- * Given a timestamp, if |ts| is not currently in view move the view to
- * center |ts|, keeping the same zoom level.
- */
-export function horizontalScrollToTs(ts: number) {
-  const startNs = toNs(globals.frontendLocalState.visibleWindowTime.start);
-  const endNs = toNs(globals.frontendLocalState.visibleWindowTime.end);
-  const currentViewNs = endNs - startNs;
-  if (ts < startNs || ts > endNs) {
-    // TODO(taylori): This is an ugly jump, we should do a smooth pan instead.
-    globals.frontendLocalState.updateVisibleTime(new TimeSpan(
-        fromNs(ts - currentViewNs / 2), fromNs(ts + currentViewNs / 2)));
-  }
-}
-
-/**
- * Given a start and end timestamp (in ns), move the view to center this range
- * and zoom to a level where the range is 1/5 of the viewport.
- */
-export function horizontalScrollAndZoomToRange(startTs: number, endTs: number) {
-  const visibleDur = globals.frontendLocalState.visibleWindowTime.end -
-      globals.frontendLocalState.visibleWindowTime.start;
-  const selectDur = endTs - startTs;
-  const viewStartNs = toNs(globals.frontendLocalState.visibleWindowTime.start);
-  const viewEndNs = toNs(globals.frontendLocalState.visibleWindowTime.end);
-  if (selectDur / visibleDur < 0.05 || startTs < viewStartNs ||
-      endTs > viewEndNs) {
-    globals.frontendLocalState.updateVisibleTime(
-        new TimeSpan(startTs - (selectDur * 2), endTs + (selectDur * 2)));
-  }
-}
-
-/**
- * Given a track id, find a track with that id and scroll it into view. If the
- * track is nested inside a track group, scroll to that track group instead.
- * If |openGroup| then open the track group and scroll to the track.
- */
-export function verticalScrollToTrack(
-    trackId: string|number, openGroup = false) {
-  const trackIdString = `${trackId}`;
-  const track = document.querySelector('#track_' + trackIdString);
-
-  if (track) {
-    // block: 'nearest' means that it will only scroll if the track is not
-    // currently in view.
-    track.scrollIntoView({behavior: 'smooth', block: 'nearest'});
-    return;
-  }
-
-  let trackGroup = null;
-  const trackGroupId = getContainingTrackId(globals.state, trackIdString);
-  if (trackGroupId) {
-    trackGroup = document.querySelector('#track_' + trackGroupId);
-  }
-
-  if (!trackGroupId || !trackGroup) {
-    console.error(`Can't scroll, track (${trackIdString}) not found.`);
-    return;
-  }
-
-  // The requested track is inside a closed track group, either open the track
-  // group and scroll to the track or just scroll to the track group.
-  if (openGroup) {
-    // After the track exists in the dom, it will be scrolled to.
-    globals.frontendLocalState.scrollToTrackId = trackId;
-    globals.dispatch(Actions.toggleTrackGroupCollapsed({trackGroupId}));
-    return;
-  } else {
-    trackGroup.scrollIntoView({behavior: 'smooth', block: 'nearest'});
-  }
-}
-
-
-/**
- * Scroll vertically and horizontally to reach track (|trackId|) at |ts|.
- */
-export function scrollToTrackAndTs(
-    trackId: string|number|undefined, ts: number, openGroup = false) {
-  if (trackId !== undefined) {
-    verticalScrollToTrack(trackId, openGroup);
-  }
-  horizontalScrollToTs(ts);
-}
\ No newline at end of file
diff --git a/ui/src/frontend/search_handler.ts b/ui/src/frontend/search_handler.ts
deleted file mode 100644
index 0e726a8..0000000
--- a/ui/src/frontend/search_handler.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {searchSegment} from '../base/binary_search';
-import {Actions} from '../common/actions';
-import {toNs} from '../common/time';
-
-import {globals} from './globals';
-import {scrollToTrackAndTs} from './scroll_helper';
-
-export function executeSearch(reverse = false) {
-  const state = globals.frontendLocalState;
-  const index = state.searchIndex;
-  const startNs = toNs(globals.frontendLocalState.visibleWindowTime.start);
-  const endNs = toNs(globals.frontendLocalState.visibleWindowTime.end);
-  const currentTs = globals.currentSearchResults.tsStarts[index];
-
-  // If this is a new search or the currentTs is not in the viewport,
-  // select the first/last item in the viewport.
-  if (index === -1 || currentTs < startNs || currentTs > endNs) {
-    if (reverse) {
-      const [smaller,] =
-        searchSegment(globals.currentSearchResults.tsStarts, endNs);
-      globals.frontendLocalState.setSearchIndex(smaller);
-    } else {
-      const [, larger] =
-          searchSegment(globals.currentSearchResults.tsStarts, startNs);
-      globals.frontendLocalState.setSearchIndex(larger);
-    }
-  } else {
-    // If the currentTs is in the viewport, increment the index.
-    if (reverse) {
-      globals.frontendLocalState.setSearchIndex(Math.max(index - 1, 0));
-    } else {
-      globals.frontendLocalState.setSearchIndex(Math.min(
-          index + 1, globals.currentSearchResults.sliceIds.length - 1));
-    }
-  }
-  selectCurrentSearchResult();
-
-  // TODO(taylori): If the user does a search before any other selection,
-  // the details panel will pop up when the search is executed. If the search
-  // result is behind where the details panel appears then it won't get scrolled
-  // to. This time delay is a workaround for this specific situation.
-  // A better solution will be a callback that allows something to happen on the
-  // first redraw after an Action is applied.
-  const delay = index === -1 ? 50 : 0;
-  setTimeout(() => moveViewportToCurrentSearch(), delay);
-}
-
-function moveViewportToCurrentSearch() {
-  const searchIndex = globals.frontendLocalState.searchIndex;
-  if (searchIndex === -1) return;
-  const currentTs = globals.currentSearchResults.tsStarts[searchIndex];
-  const trackId = globals.currentSearchResults.trackIds[searchIndex];
-  scrollToTrackAndTs(trackId, currentTs);
-}
-
-function selectCurrentSearchResult() {
-  const state = globals.frontendLocalState;
-  const searchIndex = state.searchIndex;
-  const refType = globals.currentSearchResults.refTypes[searchIndex];
-  const currentId = globals.currentSearchResults.sliceIds[searchIndex];
-  const trackId = globals.currentSearchResults.trackIds[searchIndex];
-
-  if (currentId === undefined) return;
-
-  if (refType === 'cpu') {
-    globals.dispatch(Actions.selectSlice({id: currentId, trackId}));
-  } else {
-    globals.dispatch(Actions.selectChromeSlice({id: currentId, trackId}));
-  }
-}
diff --git a/ui/src/frontend/sidebar.ts b/ui/src/frontend/sidebar.ts
index 420ac57..b9bbdd8 100644
--- a/ui/src/frontend/sidebar.ts
+++ b/ui/src/frontend/sidebar.ts
@@ -14,18 +14,13 @@
 
 import * as m from 'mithril';
 
-import {assertTrue} from '../base/logging';
 import {Actions} from '../common/actions';
-import {QueryResponse} from '../common/queries';
-import {EngineMode} from '../common/state';
 
 import {globals} from './globals';
-import {toggleHelp} from './help_modal';
 import {
   isLegacyTrace,
   openFileWithLegacyTraceViewer,
 } from './legacy_trace_viewer';
-import {showModal} from './modal';
 
 const ALL_PROCESSES_QUERY = 'select name, pid from process order by name;';
 
@@ -71,19 +66,6 @@
   ) inner join thread using(utid)
 ) inner join process using(upid) limit 30;`;
 
-const HEAP_GRAPH_BYTES_PER_TYPE = `
-select
-  upid,
-  graph_sample_ts,
-  type_name,
-  sum(self_size) as total_self_size
-from heap_graph_object
-group by
- upid,
- graph_sample_ts,
- type_name
-order by total_self_size desc
-limit 100;`;
 
 const SQL_STATS = `
 with first as (select started as ts from sqlstats limit 1)
@@ -108,7 +90,7 @@
 }
 
 const EXAMPLE_ANDROID_TRACE_URL =
-    'https://storage.googleapis.com/perfetto-misc/example_android_trace_15s';
+    'https://storage.googleapis.com/perfetto-misc/example_android_trace_30s_1';
 
 const EXAMPLE_CHROME_TRACE_URL =
     'https://storage.googleapis.com/perfetto-misc/example_chrome_trace_4s_1.json';
@@ -123,31 +105,12 @@
       {
         t: 'Open with legacy UI',
         a: popupFileSelectionDialogOldUI,
-        i: 'filter_none'
+        i: 'folder_open'
       },
       {t: 'Record new trace', a: navigateRecord, i: 'fiber_smart_record'},
-    ],
-  },
-  {
-    title: 'Current Trace',
-    summary: 'Actions on the current trace',
-    expanded: true,
-    hideIfNoTraceLoaded: true,
-    items: [
       {t: 'Show timeline', a: navigateViewer, i: 'line_style'},
-      {
-        t: 'Share',
-        a: dispatchCreatePermalink,
-        i: 'share',
-        checkDownloadDisabled: true,
-      },
-      {
-        t: 'Download',
-        a: downloadTrace,
-        i: 'file_download',
-        checkDownloadDisabled: true,
-      },
-      {t: 'Legacy UI', a: openCurrentTraceWithOldUI, i: 'filter_none'},
+      {t: 'Share current trace', a: dispatchCreatePermalink, i: 'share'},
+      {t: 'Download current trace', a: downloadTrace, i: 'file_download'},
     ],
   },
   {
@@ -192,11 +155,6 @@
         i: 'search',
       },
       {
-        t: 'Heap Graph: Bytes per type',
-        a: createCannedQuery(HEAP_GRAPH_BYTES_PER_TYPE),
-        i: 'search',
-      },
-      {
         t: 'Trace stats',
         a: createCannedQuery(TRACE_STATS),
         i: 'bug_report',
@@ -213,14 +171,9 @@
     summary: 'Documentation & Bugs',
     items: [
       {
-        t: 'Controls',
-        a: toggleHelp,
-        i: 'help',
-      },
-      {
         t: 'Documentation',
         a: 'https://perfetto.dev',
-        i: 'find_in_page',
+        i: 'help',
       },
       {
         t: 'Report a bug',
@@ -232,15 +185,6 @@
 
 ];
 
-const vidSection = {
-  title: 'Video',
-  summary: 'Open a screen recording',
-  expanded: true,
-  items: [
-    {t: 'Open video file', a: popupVideoSelectionDialog, i: 'folder_open'},
-  ],
-};
-
 function getFileElement(): HTMLInputElement {
   return document.querySelector('input[type=file]')! as HTMLInputElement;
 }
@@ -248,52 +192,18 @@
 function popupFileSelectionDialog(e: Event) {
   e.preventDefault();
   delete getFileElement().dataset['useCatapultLegacyUi'];
-  delete getFileElement().dataset['video'];
   getFileElement().click();
 }
 
 function popupFileSelectionDialogOldUI(e: Event) {
   e.preventDefault();
-  delete getFileElement().dataset['video'];
   getFileElement().dataset['useCatapultLegacyUi'] = '1';
   getFileElement().click();
 }
 
-function openCurrentTraceWithOldUI() {
-  console.assert(isTraceLoaded());
-  if (!isTraceLoaded) return;
-  const engine = Object.values(globals.state.engines)[0];
-  const src = engine.source;
-  if (src.type === 'ARRAY_BUFFER') {
-    openInOldUIWithSizeCheck(new Blob([src.buffer]));
-  } else if (src.type === 'FILE') {
-    openInOldUIWithSizeCheck(src.file);
-  } else {
-    throw new Error('Loading from a URL to catapult is not yet supported');
-    // TODO(nicomazz): Find how to get the data of the current trace if it is
-    // from a URL. It seems that the trace downloaded is given to the trace
-    // processor, but not kept somewhere accessible. Maybe the only way is to
-    // download the trace (again), and then open it. An alternative can be to
-    // save a copy.
-  }
-}
-
-function isTraceLoaded(): boolean {
-  const engine = Object.values(globals.state.engines)[0];
-  return engine !== undefined;
-}
-
-function popupVideoSelectionDialog(e: Event) {
-  e.preventDefault();
-  delete getFileElement().dataset['useCatapultLegacyUi'];
-  getFileElement().dataset['video'] = '1';
-  getFileElement().click();
-}
-
 function openTraceUrl(url: string): (e: Event) => void {
   return e => {
     e.preventDefault();
-    globals.frontendLocalState.localOnlyMode = false;
     globals.dispatch(Actions.openTraceFromUrl({url}));
   };
 }
@@ -304,103 +214,19 @@
   }
   if (!e.target.files) return;
   const file = e.target.files[0];
-  // Reset the value so onchange will be fired with the same file.
-  e.target.value = '';
-
-  globals.frontendLocalState.localOnlyMode = false;
 
   if (e.target.dataset['useCatapultLegacyUi'] === '1') {
-    // Switch back to the old catapult UI.
+    // Switch back the old catapult UI.
     if (isLegacyTrace(file.name)) {
       openFileWithLegacyTraceViewer(file);
-      return;
+    } else {
+      globals.dispatch(Actions.convertTraceToJson({file}));
     }
-    openInOldUIWithSizeCheck(file);
     return;
   }
 
-  if (e.target.dataset['video'] === '1') {
-    // TODO(hjd): Update this to use a controller and publish.
-    globals.dispatch(Actions.executeQuery({
-      engineId: '0', queryId: 'command',
-      query: `select ts from slices where name = 'first_frame' union ` +
-             `select start_ts from trace_bounds`}));
-    setTimeout(() => {
-      const resp = globals.queryResults.get('command') as QueryResponse;
-      // First value is screenrecord trace event timestamp
-      // and second value is trace boundary's start timestamp
-      const offset = (Number(resp.rows[1]['ts'].toString()) -
-                      Number(resp.rows[0]['ts'].toString())) /
-          1e9;
-      globals.queryResults.delete('command');
-      globals.rafScheduler.scheduleFullRedraw();
-      globals.dispatch(Actions.deleteQuery({queryId: 'command'}));
-      globals.dispatch(Actions.setVideoOffset({offset}));
-    }, 1000);
-    globals.dispatch(Actions.openVideoFromFile({file}));
-    return;
-  }
-
+  // Open with the current UI.
   globals.dispatch(Actions.openTraceFromFile({file}));
-
-}
-
-function openInOldUIWithSizeCheck(trace: Blob) {
-  // Perfetto traces smaller than 50mb can be safely opened in the legacy UI.
-  if (trace.size < 1024 * 1024 * 50) {
-    globals.dispatch(Actions.convertTraceToJson({file: trace}));
-    return;
-  }
-
-  // Give the user the option to truncate larger perfetto traces.
-  const size = Math.round(trace.size / (1024 * 1024));
-  showModal({
-    title: 'Legacy UI may fail to open this trace',
-    content:
-        m('div',
-          m('p',
-            `This trace is ${size}mb, opening it in the legacy UI ` +
-                `may fail.`),
-          m('p',
-            'More options can be found at ',
-            m('a',
-              {
-                href: 'https://goto.google.com/opening-large-traces',
-                target: '_blank'
-              },
-              'go/opening-large-traces'),
-            '.')),
-    buttons: [
-      {
-        text: 'Open full trace (not recommended)',
-        primary: false,
-        id: 'open',
-        action: () => {
-          globals.dispatch(Actions.convertTraceToJson({file: trace}));
-        }
-      },
-      {
-        text: 'Open beginning of trace',
-        primary: true,
-        id: 'truncate-start',
-        action: () => {
-          globals.dispatch(
-              Actions.convertTraceToJson({file: trace, truncate: 'start'}));
-        }
-      },
-      {
-        text: 'Open end of trace',
-        primary: true,
-        id: 'truncate-end',
-        action: () => {
-          globals.dispatch(
-              Actions.convertTraceToJson({file: trace, truncate: 'end'}));
-        }
-      }
-
-    ]
-  });
-  return;
 }
 
 function navigateRecord(e: Event) {
@@ -413,139 +239,45 @@
   globals.dispatch(Actions.navigate({route: '/viewer'}));
 }
 
-function isDownloadAndShareDisabled(): boolean {
-  if (globals.frontendLocalState.localOnlyMode) return true;
-  const engine = Object.values(globals.state.engines)[0];
-  if (engine && engine.source.type === 'HTTP_RPC') return true;
-  return false;
-}
-
 function dispatchCreatePermalink(e: Event) {
   e.preventDefault();
-  if (isDownloadAndShareDisabled() || !isTraceLoaded()) return;
-
-  const result = confirm(
-      `Upload the trace and generate a permalink. ` +
-      `The trace will be accessible by anybody with the permalink.`);
-  if (result) globals.dispatch(Actions.createPermalink({}));
+  globals.dispatch(Actions.createPermalink({}));
 }
 
 function downloadTrace(e: Event) {
   e.preventDefault();
-  if (!isTraceLoaded() || isDownloadAndShareDisabled()) return;
-
   const engine = Object.values(globals.state.engines)[0];
   if (!engine) return;
-  let url = '';
-  let fileName = 'trace.pftrace';
   const src = engine.source;
-  if (src.type === 'URL') {
-    url = src.url;
-    fileName = url.split('/').slice(-1)[0];
-  } else if (src.type === 'ARRAY_BUFFER') {
-    const blob = new Blob([src.buffer], {type: 'application/octet-stream'});
-    url = URL.createObjectURL(blob);
-  } else if (src.type === 'FILE') {
-    const file = src.file;
-    url = URL.createObjectURL(file);
-    fileName = file.name;
+  if (typeof src === 'string') {
+    window.open(src);
   } else {
-    throw new Error(`Download from ${JSON.stringify(src)} is not supported`);
+    const url = URL.createObjectURL(src);
+    const a = document.createElement('a');
+    a.href = url;
+    a.download = src.name;
+    document.body.appendChild(a);
+    a.click();
+    document.body.removeChild(a);
+    URL.revokeObjectURL(url);
   }
-
-  const a = document.createElement('a');
-  a.href = url;
-  a.download = fileName;
-  document.body.appendChild(a);
-  a.click();
-  document.body.removeChild(a);
-  URL.revokeObjectURL(url);
 }
 
-
-const SidebarFooter: m.Component = {
-  view() {
-    let cssClass = '';
-    let title = 'Number of pending SQL queries';
-    let label: string;
-    let failed = false;
-    let mode: EngineMode|undefined;
-
-    // We are assuming we have at most one engine here.
-    const engines = Object.values(globals.state.engines);
-    assertTrue(engines.length <= 1);
-    for (const engine of engines) {
-      mode = engine.mode;
-      if (engine.failed !== undefined) {
-        cssClass += '.failed';
-        title = 'Query engine crashed\n' + engine.failed;
-        failed = true;
-      }
-    }
-
-    // If we don't have an engine yet, guess what will be the mode that will
-    // be used next time we'll create one. Even if we guess it wrong (somehow
-    // trace_controller.ts takes a different decision later, e.g. because the
-    // RPC server is shut down after we load the UI and cached httpRpcState)
-    // this will eventually become  consistent once the engine is created.
-    if (mode === undefined) {
-      if (globals.frontendLocalState.httpRpcState.connected &&
-          globals.state.newEngineMode === 'USE_HTTP_RPC_IF_AVAILABLE') {
-        mode = 'HTTP_RPC';
-      } else {
-        mode = 'WASM';
-      }
-    }
-
-    if (mode === 'HTTP_RPC') {
-      cssClass += '.rpc';
-      label = 'RPC';
-      title += '\n(Query engine: native accelerator over HTTP+RPC)';
-    } else {
-      label = 'WSM';
-      title += '\n(Query engine: built-in WASM)';
-    }
-
-    return m(
-        '.sidebar-footer',
-        m('button',
-          {
-            onclick: () => globals.frontendLocalState.togglePerfDebug(),
-          },
-          m('i.material-icons',
-            {title: 'Toggle Perf Debug Mode'},
-            'assessment')),
-        m(`.num-queued-queries${cssClass}`,
-          {title},
-          m('div', label),
-          m('div', `${failed ? 'FAIL' : globals.numQueuedQueries}`)),
-    );
-  }
-};
-
-
 export class Sidebar implements m.ClassComponent {
   view() {
     const vdomSections = [];
     for (const section of SECTIONS) {
-      if (section.hideIfNoTraceLoaded && !isTraceLoaded()) continue;
       const vdomItems = [];
       for (const item of section.items) {
-        let attrs = {
-          onclick: typeof item.a === 'function' ? item.a : null,
-          href: typeof item.a === 'string' ? item.a : '#',
-          disabled: false,
-        };
-        if (isDownloadAndShareDisabled() &&
-            item.hasOwnProperty('checkDownloadDisabled')) {
-          attrs = {
-            onclick: () => alert('Can not download or share external trace.'),
-            href: '#',
-            disabled: true
-          };
-        }
         vdomItems.push(
-            m('li', m('a', attrs, m('i.material-icons', item.i), item.t)));
+            m('li',
+              m(`a`,
+                {
+                  onclick: typeof item.a === 'function' ? item.a : null,
+                  href: typeof item.a === 'string' ? item.a : '#',
+                },
+                m('i.material-icons', item.i),
+                item.t)));
       }
       vdomSections.push(
           m(`section${section.expanded ? '.expanded' : ''}`,
@@ -556,66 +288,14 @@
                   globals.rafScheduler.scheduleFullRedraw();
                 }
               },
-              m('h1', {title: section.summary}, section.title),
-              m('h2', section.summary)),
+              m('h1', section.title),
+              m('h2', section.summary), ),
             m('.section-content', m('ul', vdomItems))));
     }
-    if (globals.state.videoEnabled) {
-      const videoVdomItems = [];
-      for (const item of vidSection.items) {
-        videoVdomItems.push(
-          m('li',
-            m(`a`,
-              {
-                onclick: typeof item.a === 'function' ? item.a : null,
-                href: typeof item.a === 'string' ? item.a : '#',
-              },
-              m('i.material-icons', item.i),
-              item.t)));
-      }
-      vdomSections.push(
-        m(`section${vidSection.expanded ? '.expanded' : ''}`,
-          m('.section-header',
-            {
-              onclick: () => {
-                vidSection.expanded = !vidSection.expanded;
-                globals.rafScheduler.scheduleFullRedraw();
-              }
-            },
-            m('h1', vidSection.title),
-            m('h2', vidSection.summary), ),
-          m('.section-content', m('ul', videoVdomItems))));
-    }
     return m(
         'nav.sidebar',
-        {
-          class: globals.frontendLocalState.sidebarVisible ? 'show-sidebar' :
-                                                             'hide-sidebar'
-        },
-        m(
-            'header',
-            'Perfetto',
-            m('button.sidebar-button',
-              {
-                onclick: () => {
-                  globals.frontendLocalState.toggleSidebar();
-                },
-              },
-              m('i.material-icons',
-                {
-                  title: globals.frontendLocalState.sidebarVisible ?
-                      'Hide menu' :
-                      'Show menu',
-                },
-                'menu')),
-            ),
+        m('header', 'Perfetto'),
         m('input[type=file]', {onchange: onInputElementFileSelectionChanged}),
-        m('.sidebar-scroll',
-          m(
-              '.sidebar-scroll-container',
-              ...vdomSections,
-              m(SidebarFooter),
-              )),
-    );
+        ...vdomSections);
   }
 }
diff --git a/ui/src/frontend/slice_panel.ts b/ui/src/frontend/slice_panel.ts
index 1437c37..ca0cc19 100644
--- a/ui/src/frontend/slice_panel.ts
+++ b/ui/src/frontend/slice_panel.ts
@@ -14,155 +14,110 @@
 
 import * as m from 'mithril';
 
-import {Actions} from '../common/actions';
 import {drawDoubleHeadedArrow} from '../common/canvas_utils';
 import {translateState} from '../common/thread_state';
-import {timeToCode, toNs} from '../common/time';
+import {timeToCode} from '../common/time';
 
 import {globals} from './globals';
 import {Panel, PanelSize} from './panel';
-import {scrollToTrackAndTs} from './scroll_helper';
 
-export class SliceDetailsPanel extends Panel {
-  view() {
+interface SliceDetailsPanelAttrs {
+  utid: number;
+}
+
+export class SliceDetailsPanel extends Panel<SliceDetailsPanelAttrs> {
+  view({attrs}: m.CVnode<SliceDetailsPanelAttrs>) {
+    const threadInfo = globals.threads.get(attrs.utid);
     const sliceInfo = globals.sliceDetails;
-    if (sliceInfo.utid === undefined) return;
-    const threadInfo = globals.threads.get(sliceInfo.utid);
-
-    if (threadInfo && sliceInfo.ts !== undefined &&
-        sliceInfo.dur !== undefined) {
+    if (threadInfo && sliceInfo.ts && sliceInfo.dur) {
       return m(
           '.details-panel',
           m('.details-panel-heading', `Slice Details:`),
-          m(
-              '.details-table',
-              [m('table',
-                 [
-                   m('tr',
-                     m('th', `Process`),
-                     m('td', `${threadInfo.procName} [${threadInfo.pid}]`)),
-                   m('tr',
-                     m('th', `Thread`),
-                     m('td',
-                       `${threadInfo.threadName} [${threadInfo.tid}]`,
-                       m('i.material-icons',
-                         {
-                           onclick: () => this.goToThread(),
-                           title: 'Go to thread'
-                         },
-                         'call_made'))),
-                   m('tr',
-                     m('th', `Start time`),
-                     m('td', `${timeToCode(sliceInfo.ts)}`)),
-                   m('tr',
-                     m('th', `Duration`),
-                     m('td', `${timeToCode(sliceInfo.dur)}`)),
-                   m('tr', m('th', `Prio`), m('td', `${sliceInfo.priority}`)),
-                   m('tr',
-                     m('th', `End State`),
-                     m('td', `${translateState(sliceInfo.endState)}`))
-                 ])],
-              ));
-    } else {
+          m('.details-table', [m('table', [
+              m('tr', m('th', `PID`), m('td', `${threadInfo.pid}`)),
+              m('tr',
+                m('th', `Process name`),
+                m('td', `${threadInfo.procName}`)),
+              m('tr', m('th', `TID`), m('td', `${threadInfo.tid}`)),
+              m('tr',
+                m('th', `Thread name`),
+                m('td', `${threadInfo.threadName}`)),
+              m('tr',
+                m('th', `Start time`),
+                m('td', `${timeToCode(sliceInfo.ts)}`)),
+              m('tr',
+                m('th', `Duration`),
+                m('td', `${timeToCode(sliceInfo.dur)}`)),
+              m('tr', m('th', `Prio`), m('td', `${sliceInfo.priority}`)),
+              m('tr',
+                m('th', `End State`),
+                m('td', `${translateState(sliceInfo.endState)}`))
+            ])], ));
+    }
+  else {
       return m(
-          '.details-panel',
-          m(
-              '.details-panel-heading',
-              `Slice Details:`,
-              ));
+          '.details-panel', m('.details-panel-heading', `Slice Details:`, ));
+  }
+}
+renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) {
+  const details = globals.sliceDetails;
+  // Show expanded details on the scheduling of the currently selected slice.
+  if (details.wakeupTs && details.wakerUtid !== undefined) {
+    const threadInfo = globals.threads.get(details.wakerUtid);
+    // Draw separation line.
+    ctx.fillStyle = '#3c4b5d';
+    ctx.fillRect(size.width / 2, 10, 1, size.height - 10);
+    ctx.font = '16px Google Sans';
+    ctx.fillText('Scheduling Latency:', size.width / 2 + 30, 30);
+    // Draw diamond and vertical line.
+    const startDraw = {x: size.width / 2 + 30, y: 52};
+    ctx.beginPath();
+    ctx.moveTo(startDraw.x, startDraw.y + 28);
+    ctx.fillStyle = 'black';
+    ctx.lineTo(startDraw.x + 6, startDraw.y + 20);
+    ctx.lineTo(startDraw.x, startDraw.y + 12);
+    ctx.lineTo(startDraw.x - 6, startDraw.y + 20);
+    ctx.fill();
+    ctx.closePath();
+    ctx.fillRect(startDraw.x - 1, startDraw.y, 2, 100);
+
+    // Wakeup explanation text.
+    ctx.font = '13px Google Sans';
+    ctx.fillStyle = '#3c4b5d';
+    if (threadInfo) {
+      const displayText =
+          `Wakeup @ ${
+                      timeToCode(
+                          details.wakeupTs - globals.state.traceTime.startSec)
+                    } on CPU ${details.wakerCpu} by`;
+      const processText = `P: ${threadInfo.procName} [${threadInfo.pid}]`;
+      const threadText = `T: ${threadInfo.threadName} [${threadInfo.tid}]`;
+      ctx.fillText(displayText, startDraw.x + 20, startDraw.y + 20);
+      ctx.fillText(processText, startDraw.x + 20, startDraw.y + 37);
+      ctx.fillText(threadText, startDraw.x + 20, startDraw.y + 55);
+    }
+
+    // Draw latency arrow and explanation text.
+    drawDoubleHeadedArrow(ctx, startDraw.x, startDraw.y + 80, 60, true);
+    if (details.ts) {
+      const displayLatency =
+          `Scheduling latency: ${
+                                 timeToCode(
+                                     details.ts -
+                                     (details.wakeupTs -
+                                      globals.state.traceTime.startSec))
+                               }`;
+      ctx.fillText(displayLatency, startDraw.x + 70, startDraw.y + 86);
+      const explain1 =
+          'This is the interval from when the task became eligible to run';
+      const explain2 =
+          '(e.g. because of notifying a wait queue it was suspended on) to';
+      const explain3 = 'when it started running.';
+      ctx.font = '10px Google Sans';
+      ctx.fillText(explain1, startDraw.x + 70, startDraw.y + 86 + 16);
+      ctx.fillText(explain2, startDraw.x + 70, startDraw.y + 86 + 16 + 12);
+      ctx.fillText(explain3, startDraw.x + 70, startDraw.y + 86 + 16 + 24);
     }
   }
-
-  goToThread() {
-    const sliceInfo = globals.sliceDetails;
-    if (sliceInfo.utid === undefined) return;
-    const threadInfo = globals.threads.get(sliceInfo.utid);
-
-    if (sliceInfo.id === undefined || sliceInfo.ts === undefined ||
-        sliceInfo.dur === undefined || sliceInfo.cpu === undefined ||
-        threadInfo === undefined) {
-      return;
-    }
-
-    let trackId: string|number|undefined;
-    for (const track of Object.values(globals.state.tracks)) {
-      if (track.kind === 'ThreadStateTrack' &&
-          (track.config as {utid: number}).utid === threadInfo.utid) {
-        trackId = track.id;
-      }
-    }
-
-    if (trackId) {
-      globals.makeSelection(Actions.selectThreadState({
-        utid: threadInfo.utid,
-        ts: sliceInfo.ts + globals.state.traceTime.startSec,
-        dur: sliceInfo.dur,
-        state: 'Running',
-        cpu: sliceInfo.cpu,
-        trackId: trackId.toString(),
-      }));
-
-      scrollToTrackAndTs(
-          trackId, toNs(sliceInfo.ts + globals.state.traceTime.startSec), true);
-    }
-  }
-
-
-  renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) {
-    const details = globals.sliceDetails;
-    // Show expanded details on the scheduling of the currently selected slice.
-    if (details.wakeupTs && details.wakerUtid !== undefined) {
-      const threadInfo = globals.threads.get(details.wakerUtid);
-      // Draw separation line.
-      ctx.fillStyle = '#3c4b5d';
-      ctx.fillRect(size.width / 2, 10, 1, size.height - 10);
-      ctx.font = '16px Google Sans';
-      ctx.fillText('Scheduling Latency:', size.width / 2 + 30, 30);
-      // Draw diamond and vertical line.
-      const startDraw = {x: size.width / 2 + 30, y: 52};
-      ctx.beginPath();
-      ctx.moveTo(startDraw.x, startDraw.y + 28);
-      ctx.fillStyle = 'black';
-      ctx.lineTo(startDraw.x + 6, startDraw.y + 20);
-      ctx.lineTo(startDraw.x, startDraw.y + 12);
-      ctx.lineTo(startDraw.x - 6, startDraw.y + 20);
-      ctx.fill();
-      ctx.closePath();
-      ctx.fillRect(startDraw.x - 1, startDraw.y, 2, 100);
-
-      // Wakeup explanation text.
-      ctx.font = '13px Google Sans';
-      ctx.fillStyle = '#3c4b5d';
-      if (threadInfo) {
-        const displayText = `Wakeup @ ${
-            timeToCode(
-                details.wakeupTs - globals.state.traceTime.startSec)} on CPU ${
-            details.wakerCpu} by`;
-        const processText = `P: ${threadInfo.procName} [${threadInfo.pid}]`;
-        const threadText = `T: ${threadInfo.threadName} [${threadInfo.tid}]`;
-        ctx.fillText(displayText, startDraw.x + 20, startDraw.y + 20);
-        ctx.fillText(processText, startDraw.x + 20, startDraw.y + 37);
-        ctx.fillText(threadText, startDraw.x + 20, startDraw.y + 55);
-      }
-
-      // Draw latency arrow and explanation text.
-      drawDoubleHeadedArrow(ctx, startDraw.x, startDraw.y + 80, 60, true);
-      if (details.ts) {
-        const displayLatency = `Scheduling latency: ${
-            timeToCode(
-                details.ts -
-                (details.wakeupTs - globals.state.traceTime.startSec))}`;
-        ctx.fillText(displayLatency, startDraw.x + 70, startDraw.y + 86);
-        const explain1 =
-            'This is the interval from when the task became eligible to run';
-        const explain2 =
-            '(e.g. because of notifying a wait queue it was suspended on) to';
-        const explain3 = 'when it started running.';
-        ctx.font = '10px Google Sans';
-        ctx.fillText(explain1, startDraw.x + 70, startDraw.y + 86 + 16);
-        ctx.fillText(explain2, startDraw.x + 70, startDraw.y + 86 + 16 + 12);
-        ctx.fillText(explain3, startDraw.x + 70, startDraw.y + 86 + 16 + 24);
-      }
-    }
-  }
+}
 }
diff --git a/ui/src/frontend/thread_state_panel.ts b/ui/src/frontend/thread_state_panel.ts
index 3df1884..a65cea9 100644
--- a/ui/src/frontend/thread_state_panel.ts
+++ b/ui/src/frontend/thread_state_panel.ts
@@ -14,20 +14,17 @@
 
 import * as m from 'mithril';
 
-import {Actions} from '../common/actions';
 import {translateState} from '../common/thread_state';
-import {timeToCode, toNs} from '../common/time';
+import {timeToCode} from '../common/time';
 
 import {globals} from './globals';
 import {Panel, PanelSize} from './panel';
-import {scrollToTrackAndTs} from './scroll_helper';
 
 interface ThreadStateDetailsAttr {
   utid: number;
   ts: number;
   dur: number;
   state: string;
-  cpu: number;
 }
 
 export class ThreadStatePanel extends Panel<ThreadStateDetailsAttr> {
@@ -42,18 +39,12 @@
                 m('th', `Start time`),
                 m('td',
                   `${
-                      timeToCode(
-                          attrs.ts - globals.state.traceTime.startSec)}`)),
-              m('tr',
-                m('th', `Duration`),
-                m('td',
-                  `${timeToCode(attrs.dur)} `,
-                  m('a',
-                    {href: 'http://b/140256335', target: '_blank'},
-                    '(b/140256335)'))),
+                     timeToCode(attrs.ts - globals.state.traceTime.startSec)
+                   }`)),
+              m('tr', m('th', `Duration`), m('td', `${timeToCode(attrs.dur)}`)),
               m('tr',
                 m('th', `State`),
-                m('td', this.getStateContent(attrs.state, attrs.cpu))),
+                m('td', `${translateState(attrs.state)}`)),
               m('tr',
                 m('th', `Process`),
                 m('td', `${threadInfo.procName} [${threadInfo.pid}]`)),
@@ -64,42 +55,4 @@
   }
 
   renderCanvas(_ctx: CanvasRenderingContext2D, _size: PanelSize) {}
-
-  // If it is the running state, we want to show which CPU and a button to
-  // go to the sched slice. Otherwise, just show the state.
-  getStateContent(state: string, cpu: number) {
-    if (state !== 'Running') {
-      return [translateState(state)];
-    }
-
-    return [
-      `${translateState(state)} on CPU ${cpu}`,
-      m('i.material-icons',
-        {
-          onclick: () => {
-            if (globals.sliceDetails.id && globals.sliceDetails.ts) {
-              // TODO(taylori): Use trackId from TP.
-              let trackId;
-              for (const track of Object.values(globals.state.tracks)) {
-                if (track.kind === 'CpuSliceTrack' &&
-                    (track.config as {cpu: number}).cpu === cpu) {
-                  trackId = track.id;
-                }
-              }
-              if (trackId) {
-                globals.makeSelection(Actions.selectSlice(
-                    {id: globals.sliceDetails.id, trackId}));
-                scrollToTrackAndTs(
-                    trackId,
-                    toNs(
-                        globals.sliceDetails.ts +
-                        globals.state.traceTime.startSec));
-              }
-            }
-          },
-          title: 'Go to CPU slice'
-        },
-        'call_made')
-    ];
-  }
 }
diff --git a/ui/src/frontend/tickmark_panel.ts b/ui/src/frontend/tickmark_panel.ts
deleted file mode 100644
index ddddd7c..0000000
--- a/ui/src/frontend/tickmark_panel.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use size 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.
-
-import * as m from 'mithril';
-import {fromNs} from '../common/time';
-
-import {globals} from './globals';
-import {gridlines} from './gridline_helper';
-import {Panel, PanelSize} from './panel';
-import {TRACK_SHELL_WIDTH} from './track_constants';
-
-// This is used to display the summary of search results.
-export class TickmarkPanel extends Panel {
-  view() {
-    return m('.tickbar');
-  }
-
-  renderCanvas(ctx: CanvasRenderingContext2D, size: PanelSize) {
-    const {timeScale, visibleWindowTime} = globals.frontendLocalState;
-
-    ctx.fillStyle = '#999';
-    ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height);
-    for (const xAndTime of gridlines(
-             size.width, visibleWindowTime, timeScale)) {
-      ctx.fillRect(xAndTime[0], 0, 1, size.height);
-    }
-
-    const data = globals.searchSummary;
-    for (let i = 0; i < data.tsStarts.length; i++) {
-      const tStart = data.tsStarts[i];
-      const tEnd = data.tsEnds[i];
-      if (tEnd <= visibleWindowTime.start || tStart >= visibleWindowTime.end) {
-        continue;
-      }
-      const rectStart =
-          Math.max(timeScale.timeToPx(tStart), 0) + TRACK_SHELL_WIDTH;
-      const rectEnd = timeScale.timeToPx(tEnd) + TRACK_SHELL_WIDTH;
-      ctx.fillStyle = '#ffe263';
-      ctx.fillRect(
-          Math.floor(rectStart),
-          0,
-          Math.ceil(rectEnd - rectStart),
-          size.height);
-    }
-    const index = globals.frontendLocalState.searchIndex;
-    const startSec = fromNs(globals.currentSearchResults.tsStarts[index]);
-    const triangleStart =
-        Math.max(timeScale.timeToPx(startSec), 0) + TRACK_SHELL_WIDTH;
-    ctx.fillStyle = '#000';
-    ctx.beginPath();
-    ctx.moveTo(triangleStart, size.height);
-    ctx.lineTo(triangleStart - 3, 0);
-    ctx.lineTo(triangleStart + 3, 0);
-    ctx.lineTo(triangleStart, size.height);
-    ctx.fill();
-    ctx.closePath();
-  }
-}
diff --git a/ui/src/frontend/time_axis_panel.ts b/ui/src/frontend/time_axis_panel.ts
index 5005b1c..12994ce 100644
--- a/ui/src/frontend/time_axis_panel.ts
+++ b/ui/src/frontend/time_axis_panel.ts
@@ -32,24 +32,19 @@
     ctx.fillStyle = '#999';
 
     // Write trace offset time + line.
-    ctx.font = '12px Google Sans';
-
     ctx.textAlign = 'right';
+    ctx.font = '12px Google Sans';
     const offsetTime =
         timeToString(range.start - globals.state.traceTime.startSec);
     ctx.fillText(offsetTime, TRACK_SHELL_WIDTH - 6, 11);
-
-    ctx.textAlign = 'left';
-    const startTime = timeToString(globals.state.traceTime.startSec);
-    ctx.fillText(startTime + ' +', 6, 11);
+    ctx.fillRect(TRACK_SHELL_WIDTH - 1, 0, 2, size.height);
 
     // Draw time axis.
     ctx.font = '10px Google Sans';
+    ctx.textAlign = 'left';
     for (const [x, time] of gridlines(size.width, range, timeScale)) {
       ctx.fillRect(x, 0, 1, size.height);
       ctx.fillText('+' + timeToString(time - range.start), x + 5, 10);
     }
-
-    ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height);
   }
 }
diff --git a/ui/src/frontend/time_selection_panel.ts b/ui/src/frontend/time_selection_panel.ts
index 890a2f0..e94eb99 100644
--- a/ui/src/frontend/time_selection_panel.ts
+++ b/ui/src/frontend/time_selection_panel.ts
@@ -80,35 +80,6 @@
   ctx.fillText(label, labelXLeft, yMid);
 }
 
-function drawIBar(
-    ctx: CanvasRenderingContext2D, xPos: number, bounds: BBox, label: string) {
-  if (xPos < bounds.x) return;
-
-  ctx.fillStyle = '#222';
-  ctx.fillRect(xPos, 0, 1, bounds.width);
-
-  const yMid = Math.floor(bounds.height / 2 + bounds.y);
-  const labelWidth = ctx.measureText(label).width;
-  const padding = 3;
-
-  let xPosLabel;
-  if (xPos + padding + labelWidth > bounds.width) {
-    xPosLabel = xPos - padding;
-    ctx.textAlign = 'right';
-  } else {
-    xPosLabel = xPos + padding;
-    ctx.textAlign = 'left';
-  }
-
-  ctx.fillStyle = '#ffffff';
-  ctx.fillRect(xPosLabel - 1, 0, labelWidth + 2, bounds.height);
-
-  ctx.textBaseline = 'middle';
-  ctx.fillStyle = '#222';
-  ctx.font = '10px Google Sans';
-  ctx.fillText(label, xPosLabel, yMid);
-}
-
 export class TimeSelectionPanel extends Panel {
   view() {
     return m('.time-selection-panel');
@@ -119,33 +90,19 @@
     const timeScale = globals.frontendLocalState.timeScale;
 
     ctx.fillStyle = '#999';
-    ctx.fillRect(TRACK_SHELL_WIDTH - 2, 0, 2, size.height);
+    ctx.fillRect(TRACK_SHELL_WIDTH - 1, 0, 2, size.height);
     for (const xAndTime of gridlines(size.width, range, timeScale)) {
       ctx.fillRect(xAndTime[0], 0, 1, size.height);
     }
 
-    const selectedTimeRange = globals.frontendLocalState.selectedTimeRange;
-    if (selectedTimeRange.startSec !== undefined &&
-        selectedTimeRange.endSec !== undefined) {
-      const start =
-          Math.min(selectedTimeRange.startSec, selectedTimeRange.endSec);
-      const end =
-          Math.max(selectedTimeRange.startSec, selectedTimeRange.endSec);
+    const selection = globals.state.currentSelection;
+    if (selection !== null && selection.kind === `TIMESPAN`) {
+      const start = Math.min(selection.startTs, selection.endTs);
+      const end = Math.max(selection.startTs, selection.endTs);
       this.renderSpan(ctx, size, new TimeSpan(start, end));
-    } else if (globals.frontendLocalState.showTimeSelectPreview) {
-      this.renderHover(ctx, size, globals.frontendLocalState.hoveredTimestamp);
     }
   }
 
-  renderHover(ctx: CanvasRenderingContext2D, size: PanelSize, ts: number) {
-    const timeScale = globals.frontendLocalState.timeScale;
-    const xPos = TRACK_SHELL_WIDTH + Math.floor(timeScale.timeToPx(ts));
-    const offsetTime = timeToString(ts - globals.state.traceTime.startSec);
-    const timeFromStart = timeToString(ts);
-    const label = `${offsetTime} (${timeFromStart})`;
-    drawIBar(ctx, xPos, this.bounds(size), label);
-  }
-
   renderSpan(ctx: CanvasRenderingContext2D, size: PanelSize, span: TimeSpan) {
     const timeScale = globals.frontendLocalState.timeScale;
     const xLeft = timeScale.timeToPx(span.start);
@@ -159,11 +116,7 @@
           width: xRight - xLeft,
           height: size.height
         },
-        this.bounds(size),
+        {x: 0, y: 0, width: size.width, height: size.height},
         label);
   }
-
-  private bounds(size: PanelSize): BBox {
-    return {x: TRACK_SHELL_WIDTH, y: 0, width: size.width, height: size.height};
-  }
 }
diff --git a/ui/src/frontend/topbar.ts b/ui/src/frontend/topbar.ts
index 2163ace..c7e2d52 100644
--- a/ui/src/frontend/topbar.ts
+++ b/ui/src/frontend/topbar.ts
@@ -19,41 +19,22 @@
 import {EngineConfig} from '../common/state';
 
 import {globals} from './globals';
-import {executeSearch} from './search_handler';
 
 const QUERY_ID = 'quicksearch';
 
-const SEARCH = Symbol('search');
-const COMMAND = Symbol('command');
-type Mode = typeof SEARCH|typeof COMMAND;
-
-const PLACEHOLDER = {
-  [SEARCH]: 'Search',
-  [COMMAND]: 'e.g. select * from sched left join thread using(utid) limit 10'
-};
-
 let selResult = 0;
 let numResults = 0;
-let mode: Mode = SEARCH;
-let displayStepThrough = false;
+let mode: 'search'|'command' = 'search';
+let omniboxValue = '';
 
-function clearOmniboxResults(e: Event) {
+function clearOmniboxResults() {
   globals.queryResults.delete(QUERY_ID);
   globals.dispatch(Actions.deleteQuery({queryId: QUERY_ID}));
-  const txt = (e.target as HTMLInputElement);
-  if (txt.value.length <= 0) {
-    mode = SEARCH;
-    globals.rafScheduler.scheduleFullRedraw();
-  }
 }
 
 function onKeyDown(e: Event) {
-  const event = (e as KeyboardEvent);
-  const key = event.key;
-  if (key !== 'Enter') {
-    e.stopPropagation();
-  }
-  const txt = (e.target as HTMLInputElement);
+  e.stopPropagation();
+  const key = (e as KeyboardEvent).key;
 
   // Avoid that the global 'a', 'd', 'w', 's' handler sees these keystrokes.
   // TODO: this seems a bug in the pan_and_zoom_handler.ts.
@@ -61,30 +42,32 @@
     e.preventDefault();
     return;
   }
-
-  if (mode === SEARCH && txt.value === '' && key === ':') {
+  const txt = (e.target as HTMLInputElement);
+  omniboxValue = txt.value;
+  if (key === ':' && txt.value === '') {
+    mode = 'command';
+    globals.rafScheduler.scheduleFullRedraw();
     e.preventDefault();
-    mode = COMMAND;
+    return;
+  }
+  if (key === 'Escape' && mode === 'command') {
+    txt.value = '';
+    mode = 'search';
     globals.rafScheduler.scheduleFullRedraw();
     return;
   }
-
-  if (mode === COMMAND && txt.value === '' && key === 'Backspace') {
-    mode = SEARCH;
+  if (key === 'Backspace' && txt.value.length === 0 && mode === 'command') {
+    mode = 'search';
     globals.rafScheduler.scheduleFullRedraw();
     return;
   }
-
-  if (mode === SEARCH && key === 'Enter') {
-    txt.blur();
-  }
 }
 
 function onKeyUp(e: Event) {
   e.stopPropagation();
-  const event = (e as KeyboardEvent);
-  const key = event.key;
+  const key = (e as KeyboardEvent).key;
   const txt = e.target as HTMLInputElement;
+  omniboxValue = txt.value;
   if (key === 'ArrowUp' || key === 'ArrowDown') {
     selResult += (key === 'ArrowUp') ? -1 : 1;
     selResult = Math.max(selResult, 0);
@@ -93,22 +76,24 @@
     globals.rafScheduler.scheduleFullRedraw();
     return;
   }
-
-  if (key === 'Escape') {
-    globals.queryResults.delete(QUERY_ID);
-    globals.dispatch(Actions.deleteQuery({queryId: 'command'}));
-    mode = SEARCH;
-    txt.value = '';
-    txt.blur();
+  if (txt.value.length <= 0 || key === 'Escape') {
+    clearOmniboxResults();
     globals.rafScheduler.scheduleFullRedraw();
     return;
   }
-  if (mode === COMMAND && key === 'Enter') {
+  if (mode === 'search') {
+    const name = txt.value.replace(/'/g, '\\\'').replace(/[*]/g, '%');
+    const query = `select str from strings where str like '%${name}%' limit 10`;
+    globals.dispatch(
+        Actions.executeQuery({engineId: '0', queryId: QUERY_ID, query}));
+  }
+  if (mode === 'command' && key === 'Enter') {
     globals.dispatch(Actions.executeQuery(
         {engineId: '0', queryId: 'command', query: txt.value}));
   }
 }
 
+
 class Omnibox implements m.ClassComponent {
   oncreate(vnode: m.VnodeDOM) {
     const txt = vnode.dom.querySelector('input') as HTMLInputElement;
@@ -144,93 +129,30 @@
         results.push(m(`div${clazz}`, resp.rows[i][resp.columns[0]]));
       }
     }
-    const commandMode = mode === COMMAND;
-    const state = globals.frontendLocalState;
+    const placeholder = {
+      search: 'Search or type : to enter command mode',
+      command: 'e.g., select * from sched left join thread using(utid) limit 10'
+    };
+
+    const commandMode = mode === 'command';
     return m(
         `.omnibox${commandMode ? '.command-mode' : ''}`,
-        m('input', {
-          placeholder: PLACEHOLDER[mode],
-          oninput: m.withAttr(
-              'value',
-              v => {
-                globals.frontendLocalState.setOmnibox(
-                    v, commandMode ? 'COMMAND' : 'SEARCH');
-                if (mode === SEARCH) {
-                  globals.frontendLocalState.setSearchIndex(-1);
-                  displayStepThrough = v.length >= 4;
-                  globals.rafScheduler.scheduleFullRedraw();
-                }
-              }),
-          value: globals.frontendLocalState.omnibox,
+        m(`input[placeholder=${placeholder[mode]}]`, {
+          onchange: m.withAttr('value', v => omniboxValue = v),
+          value: omniboxValue,
         }),
-        displayStepThrough ?
-            m(
-                '.stepthrough',
-                m('.current',
-                  `${
-                      globals.currentSearchResults.totalResults === 0 ?
-                          '0 / 0' :
-                          `${state.searchIndex + 1} / ${
-                              globals.currentSearchResults.totalResults}`}`),
-                m('button',
-                  {
-                    disabled: state.searchIndex <= 0,
-                    onclick: () => {
-                      executeSearch(true /* reverse direction */);
-                    }
-                  },
-                  m('i.material-icons.left', 'keyboard_arrow_left')),
-                m('button',
-                  {
-                    disabled: state.searchIndex ===
-                        globals.currentSearchResults.totalResults - 1,
-                    onclick: () => {
-                      executeSearch();
-                    }
-                  },
-                  m('i.material-icons.right', 'keyboard_arrow_right')),
-                ) :
-            '',
         m('.omnibox-results', results));
   }
 }
 
-class Progress implements m.ClassComponent {
-  private loading: () => void;
-  private progressBar?: HTMLElement;
-
-  constructor() {
-    this.loading = () => this.loadingAnimation();
-  }
-
-  oncreate(vnodeDom: m.CVnodeDOM) {
-    this.progressBar = vnodeDom.dom as HTMLElement;
-    globals.rafScheduler.addRedrawCallback(this.loading);
-  }
-
-  onremove() {
-    globals.rafScheduler.removeRedrawCallback(this.loading);
-  }
-
-  view() {
-    return m('.progress');
-  }
-
-  loadingAnimation() {
-    if (this.progressBar === undefined) return;
-    const engine: EngineConfig = globals.state.engines['0'];
-    if (globals.state.queries[QUERY_ID] !== undefined ||
-        (engine !== undefined && !engine.ready) ||
-        globals.numQueuedQueries > 0) {
-      this.progressBar.classList.add('progress-anim');
-    } else {
-      this.progressBar.classList.remove('progress-anim');
-    }
-  }
-}
-
 export class Topbar implements m.ClassComponent {
   view() {
-    return m('.topbar', m(Omnibox), m(Progress));
+    const progBar = [];
+    const engine: EngineConfig = globals.state.engines['0'];
+    if (globals.state.queries[QUERY_ID] !== undefined ||
+        (engine !== undefined && !engine.ready)) {
+      progBar.push(m('.progress'));
+    }
+    return m('.topbar', m(Omnibox), ...progBar);
   }
 }
diff --git a/ui/src/frontend/track.ts b/ui/src/frontend/track.ts
index d8ae5a0..09061c7 100644
--- a/ui/src/frontend/track.ts
+++ b/ui/src/frontend/track.ts
@@ -12,18 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import * as m from 'mithril';
 import {TrackState} from '../common/state';
-import {TrackData} from '../common/track_data';
-import {checkerboard} from './checkerboard';
-
 import {globals} from './globals';
-import {TrackButtonAttrs} from './track_panel';
 
 /**
  * This interface forces track implementations to have some static properties.
  * Typescript does not have abstract static members, which is why this needs to
- * be in a separate interface.
+ * be in a seperate interface.
  */
 export interface TrackCreator {
   // Store the kind explicitly as a string as opposed to using class.kind in
@@ -38,9 +33,9 @@
 /**
  * The abstract class that needs to be implemented by all tracks.
  */
-export abstract class Track<Config = {}, Data extends TrackData = TrackData> {
+export abstract class Track<Config = {}, Data = {}> {
   constructor(protected trackState: TrackState) {}
-  protected abstract renderCanvas(ctx: CanvasRenderingContext2D): void;
+  abstract renderCanvas(ctx: CanvasRenderingContext2D): void;
 
   get config(): Config {
     return this.trackState.config as Config;
@@ -54,10 +49,6 @@
     return 40;
   }
 
-  getTrackShellButtons(): Array<m.Vnode<TrackButtonAttrs>> {
-    return [];
-  }
-
   onMouseMove(_position: {x: number, y: number}) {}
 
   /**
@@ -69,16 +60,4 @@
   }
 
   onMouseOut() {}
-
-  render(ctx: CanvasRenderingContext2D) {
-    globals.frontendLocalState.addVisibleTrack(this.trackState.id);
-    if (this.data() === undefined) {
-      const {visibleWindowTime, timeScale} = globals.frontendLocalState;
-      const startPx = Math.floor(timeScale.timeToPx(visibleWindowTime.start));
-      const endPx = Math.ceil(timeScale.timeToPx(visibleWindowTime.end));
-      checkerboard(ctx, this.getHeight(), startPx, endPx);
-    } else {
-      this.renderCanvas(ctx);
-    }
-  }
 }
diff --git a/ui/src/frontend/track_group_panel.ts b/ui/src/frontend/track_group_panel.ts
index 8203764..6dc195c 100644
--- a/ui/src/frontend/track_group_panel.ts
+++ b/ui/src/frontend/track_group_panel.ts
@@ -16,11 +16,7 @@
 
 import {assertExists} from '../base/logging';
 import {Actions} from '../common/actions';
-import {
-  getContainingTrackId,
-  TrackGroupState,
-  TrackState
-} from '../common/state';
+import {TrackGroupState, TrackState} from '../common/state';
 
 import {globals} from './globals';
 import {drawGridLines} from './gridline_helper';
@@ -28,10 +24,8 @@
 import {Track} from './track';
 import {TrackContent} from './track_panel';
 import {trackRegistry} from './track_registry';
-import {
-  drawVerticalLineAtTime,
-  drawVerticalSelection
-} from './vertical_line_helper';
+import {drawVerticalSelection,
+        drawVerticalLineAtTime} from './vertical_line_helper';
 
 
 interface Attrs {
@@ -62,43 +56,25 @@
 
   view({attrs}: m.CVnode<Attrs>) {
     const collapsed = this.trackGroupState.collapsed;
-    let name = this.trackGroupState.name;
-    if (name[0] === '/') {
-      name = StripPathFromExecutable(name);
-    }
-
-    // The shell should be highlighted if the current search result is inside
-    // this track group.
-    let highlightClass = '';
-    const searchIndex = globals.frontendLocalState.searchIndex;
-    if (searchIndex !== -1) {
-      const trackId = globals.currentSearchResults
-                          .trackIds[globals.frontendLocalState.searchIndex];
-      const parentTrackId = getContainingTrackId(globals.state, trackId);
-      if (parentTrackId === attrs.trackGroupId) {
-        highlightClass = 'flash';
-      }
-    }
-
+    const name = StripPathFromExecutable(this.trackGroupState.name);
     return m(
         `.track-group-panel[collapsed=${collapsed}]`,
-        {id: 'track_' + this.trackGroupId},
-        m(`.shell`,
-          {
-            onclick: (e: MouseEvent) => {
-              globals.dispatch(Actions.toggleTrackGroupCollapsed({
-                trackGroupId: attrs.trackGroupId,
-              })),
-                  e.stopPropagation();
-            },
-            class: `${highlightClass}`,
-          },
+        m('.shell',
           m('h1',
             {
               title: name,
             },
-            name),
+            name,
+            m.trust('&#x200E;')),
           m('.fold-button',
+            {
+              onclick: (e: MouseEvent) => {
+                globals.dispatch(Actions.toggleTrackGroupCollapsed({
+                  trackGroupId: attrs.trackGroupId,
+                })),
+                e.stopPropagation();
+              }
+            },
             m('i.material-icons',
               this.trackGroupState.collapsed ? 'expand_more' : 'expand_less'))),
         this.summaryTrack ? m(TrackContent, {track: this.summaryTrack}) : null);
@@ -133,12 +109,12 @@
 
     ctx.translate(this.shellWidth, 0);
     if (this.summaryTrack) {
-      this.summaryTrack.render(ctx);
+      this.summaryTrack.renderCanvas(ctx);
     }
     ctx.restore();
 
     const localState = globals.frontendLocalState;
-    // Draw vertical line when hovering on the notes panel.
+    // Draw vertical line when hovering on the the notes panel.
     if (localState.showNotePreview) {
       drawVerticalLineAtTime(ctx,
                             localState.timeScale,
@@ -154,16 +130,6 @@
                             size.height,
                             `rgb(52,69,150)`);
     }
-    if (globals.frontendLocalState.selectedTimeRange.startSec !== undefined &&
-        globals.frontendLocalState.selectedTimeRange.endSec !== undefined) {
-      drawVerticalSelection(
-          ctx,
-          localState.timeScale,
-          globals.frontendLocalState.selectedTimeRange.startSec,
-          globals.frontendLocalState.selectedTimeRange.endSec,
-          size.height,
-          `rgba(0,0,0,0.5)`);
-    }
     if (globals.state.currentSelection !== null) {
       if (globals.state.currentSelection.kind === 'NOTE') {
         const note = globals.state.notes[globals.state.currentSelection.id];
@@ -173,6 +139,14 @@
                                size.height,
                                note.color);
       }
+      if (globals.state.currentSelection.kind === 'TIMESPAN') {
+        drawVerticalSelection(ctx,
+                              localState.timeScale,
+                              globals.state.currentSelection.startTs,
+                              globals.state.currentSelection.endTs,
+                              size.height,
+                              `rgba(52,69,150,0.3)`);
+      }
       if (globals.state.currentSelection.kind === 'SLICE' &&
           globals.sliceDetails.wakeupTs !== undefined) {
         drawVerticalLineAtTime(
diff --git a/ui/src/frontend/track_panel.ts b/ui/src/frontend/track_panel.ts
index 22e5b9a..950fed9 100644
--- a/ui/src/frontend/track_panel.ts
+++ b/ui/src/frontend/track_panel.ts
@@ -14,27 +14,23 @@
 
 import * as m from 'mithril';
 
-import {Actions} from '../common/actions';
+import {Actions, DeferredAction} from '../common/actions';
 import {TrackState} from '../common/state';
 
 import {globals} from './globals';
 import {drawGridLines} from './gridline_helper';
+import {drawVerticalSelection,
+        drawVerticalLineAtTime} from './vertical_line_helper';
 import {Panel, PanelSize} from './panel';
-import {verticalScrollToTrack} from './scroll_helper';
 import {Track} from './track';
 import {TRACK_SHELL_WIDTH} from './track_constants';
 import {trackRegistry} from './track_registry';
-import {
-  drawVerticalLineAtTime,
-  drawVerticalSelection
-} from './vertical_line_helper';
 
 function isPinned(id: string) {
   return globals.state.pinnedTracks.indexOf(id) !== -1;
 }
 
 interface TrackShellAttrs {
-  track: Track;
   trackState: TrackState;
 }
 
@@ -49,24 +45,11 @@
   }
 
   view({attrs}: m.CVnode<TrackShellAttrs>) {
-    // The shell should be highlighted if the current search result is inside
-    // this track.
-    let highlightClass = '';
-    const searchIndex = globals.frontendLocalState.searchIndex;
-    if (searchIndex !== -1) {
-      const trackId = globals.currentSearchResults
-                          .trackIds[globals.frontendLocalState.searchIndex];
-      if (trackId === attrs.trackState.id) {
-        highlightClass = 'flash';
-      }
-    }
-
-    const dragClass = this.dragging ? `drag` : '';
-    const dropClass = this.dropping ? `drop-${this.dropping}` : '';
+    const dragClass = this.dragging ? `.drag` : '';
+    const dropClass = this.dropping ? `.drop-${this.dropping}` : '';
     return m(
-        `.track-shell[draggable=true]`,
+        `.track-shell${dragClass}${dropClass}[draggable=true]`,
         {
-          class: `${highlightClass} ${dragClass} ${dropClass}`,
           onmousedown: this.onmousedown.bind(this),
           ondragstart: this.ondragstart.bind(this),
           ondragend: this.ondragend.bind(this),
@@ -78,16 +61,11 @@
           {
             title: attrs.trackState.name,
           },
-          attrs.trackState.name),
-        attrs.track.getTrackShellButtons(),
+          attrs.trackState.name,
+          m.trust('&#x200E;')),
         m(TrackButton, {
-          action: () => {
-            globals.dispatch(
-                Actions.toggleTrackPinned({trackId: attrs.trackState.id}));
-          },
+          action: Actions.toggleTrackPinned({trackId: attrs.trackState.id}),
           i: isPinned(attrs.trackState.id) ? 'star' : 'star_border',
-          tooltip: isPinned(attrs.trackState.id) ? 'Unpin' : 'Pin to top',
-          selected: isPinned(attrs.trackState.id),
         }));
   }
 
@@ -160,20 +138,12 @@
         attrs.track.onMouseOut();
         globals.rafScheduler.scheduleRedraw();
       },
-      onclick: (e: MouseEvent) => {
-        // If we are selecting a time range - do not pass the click to the
-        // track.
-        if (e.shiftKey) return;
-        // If the click is outside of the current time range, clear it.
-        const clickTime =
-            globals.frontendLocalState.timeScale.pxToTime(e.layerX);
-        const start = globals.frontendLocalState.selectedTimeRange.startSec;
-        const end = globals.frontendLocalState.selectedTimeRange.endSec;
-        if (start !== undefined && end !== undefined &&
-            (clickTime < start || clickTime > end)) {
-          globals.frontendLocalState.removeTimeRange();
-          e.stopPropagation();
-        } else if (attrs.track.onMouseClick({x: e.layerX, y: e.layerY})) {
+      onclick: (e:MouseEvent) => {
+        // If we are selecting a timespan - do not pass the click to the track.
+        const selection = globals.state.currentSelection;
+        if (selection && selection.kind === 'TIMESPAN') return;
+
+        if (attrs.track.onMouseClick({x: e.layerX, y: e.layerY})) {
           e.stopPropagation();
         }
         globals.rafScheduler.scheduleRedraw();
@@ -188,42 +158,23 @@
 }
 class TrackComponent implements m.ClassComponent<TrackComponentAttrs> {
   view({attrs}: m.CVnode<TrackComponentAttrs>) {
-    return m(
-        '.track',
-        {
-          style: {
-            height: `${attrs.track.getHeight()}px`,
-          },
-          id: 'track_' + attrs.trackState.id,
-        },
-        [
-          m(TrackShell, {track: attrs.track, trackState: attrs.trackState}),
-          m(TrackContent, {track: attrs.track})
-        ]);
-  }
-
-  oncreate({attrs}: m.CVnode<TrackComponentAttrs>) {
-    if (globals.frontendLocalState.scrollToTrackId === attrs.trackState.id) {
-      verticalScrollToTrack(attrs.trackState.id);
-      globals.frontendLocalState.scrollToTrackId = undefined;
-    }
+    return m('.track', [
+      m(TrackShell, {trackState: attrs.trackState}),
+      m(TrackContent, {track: attrs.track})
+    ]);
   }
 }
 
-export interface TrackButtonAttrs {
-  action: () => void;
+interface TrackButtonAttrs {
+  action: DeferredAction;
   i: string;
-  tooltip: string;
-  selected: boolean;
 }
-export class TrackButton implements m.ClassComponent<TrackButtonAttrs> {
+class TrackButton implements m.ClassComponent<TrackButtonAttrs> {
   view({attrs}: m.CVnode<TrackButtonAttrs>) {
     return m(
         'i.material-icons.track-button',
         {
-          class: `${attrs.selected ? 'show' : ''}`,
-          onclick: attrs.action,
-          title: attrs.tooltip,
+          onclick: () => globals.dispatch(attrs.action),
         },
         attrs.i);
   }
@@ -244,6 +195,17 @@
   }
 
   view() {
+    return m(
+        '.track',
+        {
+          style: {
+            height: `${this.track.getHeight()}px`,
+          }
+        },
+        [
+          m(TrackShell, {trackState: this.trackState}),
+          m(TrackContent, {track: this.track})
+        ]);
     return m(TrackComponent, {trackState: this.trackState, track: this.track});
   }
 
@@ -258,12 +220,12 @@
 
     ctx.translate(TRACK_SHELL_WIDTH, 0);
 
-    this.track.render(ctx);
+    this.track.renderCanvas(ctx);
 
     ctx.restore();
 
     const localState = globals.frontendLocalState;
-    // Draw vertical line when hovering on the notes panel.
+    // Draw vertical line when hovering on the the notes panel.
     if (localState.showNotePreview) {
       drawVerticalLineAtTime(ctx,
                              localState.timeScale,
@@ -279,16 +241,7 @@
                              size.height,
                              `rgb(52,69,150)`);
     }
-    if (globals.frontendLocalState.selectedTimeRange.startSec !== undefined &&
-        globals.frontendLocalState.selectedTimeRange.endSec !== undefined) {
-      drawVerticalSelection(
-          ctx,
-          localState.timeScale,
-          globals.frontendLocalState.selectedTimeRange.startSec,
-          globals.frontendLocalState.selectedTimeRange.endSec,
-          size.height,
-          `rgba(0,0,0,0.5)`);
-    }
+
     if (globals.state.currentSelection !== null) {
       if (globals.state.currentSelection.kind === 'NOTE') {
         const note = globals.state.notes[globals.state.currentSelection.id];
@@ -298,6 +251,14 @@
                                size.height,
                                note.color);
       }
+      if (globals.state.currentSelection.kind === 'TIMESPAN') {
+        drawVerticalSelection(ctx,
+                              localState.timeScale,
+                              globals.state.currentSelection.startTs,
+                              globals.state.currentSelection.endTs,
+                              size.height,
+                              `rgba(52,69,150,0.3)`);
+      }
       if (globals.state.currentSelection.kind === 'SLICE' &&
           globals.sliceDetails.wakeupTs !== undefined) {
         drawVerticalLineAtTime(
diff --git a/ui/src/frontend/vertical_line_helper.ts b/ui/src/frontend/vertical_line_helper.ts
index 073f043..59828b6 100644
--- a/ui/src/frontend/vertical_line_helper.ts
+++ b/ui/src/frontend/vertical_line_helper.ts
@@ -41,22 +41,17 @@
     ctx.lineWidth = prevLineWidth;
 }
 
-export function drawVerticalSelection(
-    ctx: CanvasRenderingContext2D,
-    timeScale: TimeScale,
-    timeStart: number,
-    timeEnd: number,
-    height: number,
-    color: string) {
-  const xStartPos =
-      TRACK_SHELL_WIDTH + Math.floor(timeScale.timeToPx(timeStart));
-  const xEndPos = TRACK_SHELL_WIDTH + Math.floor(timeScale.timeToPx(timeEnd));
-  const width = timeScale.endPx;
-  ctx.fillStyle = color;
-  ctx.fillRect(0, 0, xStartPos, height);
-  // In the worst case xEndPos may be far to the left of the canvas (and so be
-  // <0) in this case fill the whole screen.
-  ctx.fillRect(Math.max(xEndPos, 0), 0, width + TRACK_SHELL_WIDTH, height);
-  drawVerticalLine(ctx, xStartPos, height, `rgba(52,69,150)`);
-  drawVerticalLine(ctx, xEndPos, height, `rgba(52,69,150)`);
-}
+export function drawVerticalSelection(ctx: CanvasRenderingContext2D,
+                                      timeScale: TimeScale,
+                                      timeStart: number,
+                                      timeEnd: number,
+                                      height: number,
+                                      color: string) {
+    const xStartPos = TRACK_SHELL_WIDTH +
+                      Math.floor(timeScale.timeToPx(timeStart));
+    const xEndPos = TRACK_SHELL_WIDTH + Math.floor(timeScale.timeToPx(timeEnd));
+    ctx.fillStyle = color;
+    ctx.fillRect(xStartPos, 0, xEndPos - xStartPos, height);
+    drawVerticalLine(ctx, xStartPos, height, `rgba(52,69,150)`);
+    drawVerticalLine(ctx, xEndPos, height, `rgba(52,69,150)`);
+  }
diff --git a/ui/src/frontend/video_panel.ts b/ui/src/frontend/video_panel.ts
deleted file mode 100644
index 9957e37..0000000
--- a/ui/src/frontend/video_panel.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (C) 2019 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.
-
-import * as m from 'mithril';
-
-import {globals} from './globals';
-import {Actions} from '../common/actions';
-import {randomColor} from './colorizer';
-
-export class VideoPanel implements m.ClassComponent {
-  view() {
-    const vidSections = [];
-    const offset = globals.state.traceTime.startSec + globals.state.videoOffset;
-    vidSections.push(
-      m('video', {
-        class: 'video-panel',
-        controls: true,
-        width: 320,
-        currentTime: globals.frontendLocalState.vidTimestamp - offset,
-        onpause: (e: Event) => {
-          const elem = e.target as HTMLVideoElement;
-          if (globals.state.flagPauseEnabled && !(elem.ended)) {
-            const timestamp = elem.currentTime + offset;
-            const color = randomColor();
-            const isMovie = true;
-            globals.dispatch(Actions.addNote({timestamp, color, isMovie}));
-            elem.currentTime = timestamp - offset;
-            globals.frontendLocalState.setVidTimestamp(timestamp);
-          }
-        },
-        ontimeupdate: (e: Event) => {
-          const elem = e.target as HTMLVideoElement;
-          if (globals.state.scrubbingEnabled) {
-            elem.currentTime = globals.frontendLocalState.vidTimestamp - offset;
-          }
-        },
-      },
-      m('source', { src: globals.state.video, type: 'video/mp4' })));
-    const vidMessages = [];
-    const pSetting = `Pause/Flag Synchronization: `;
-    const pEnabled = `When you pause the video, a video flag ` +
-    `will be drawn at this position. \n Also, adding a video flag by ` +
-    `clicking on the notes panel (below the time axis) will move the video ` +
-    `to this position.`;
-    const pDisabled = `Press 'p' to enable.`;
-    const tSetting = `Timeline Scrubbing: `;
-    const tEnabled = `When you hover over the notes panel, the video will ` +
-    `skip to the hovered timestamp.`;
-    const tDisabled = `Press 't' to enable.`;
-    function makeMsg(setting: boolean, msgType: string, e: string, d: string) {
-      return m('h1', { class: `video-panel-${msgType}` }, setting ? e : d);
-    }
-    vidMessages.push(
-      makeMsg(globals.state.flagPauseEnabled, 'setting',
-              pSetting.concat('Enabled'), pSetting.concat('Disabled')),
-      makeMsg(globals.state.flagPauseEnabled, 'message', pEnabled, pDisabled),
-      makeMsg(globals.state.scrubbingEnabled, 'setting',
-              tSetting.concat('Enabled'), tSetting.concat('Disabled')),
-      makeMsg(globals.state.scrubbingEnabled, 'message', tEnabled, tDisabled));
-    vidSections.push(vidMessages);
-    return m('.video-panel', vidSections);
-  }
-}
diff --git a/ui/src/frontend/viewer_page.ts b/ui/src/frontend/viewer_page.ts
index 37c0279..a3e80bd 100644
--- a/ui/src/frontend/viewer_page.ts
+++ b/ui/src/frontend/viewer_page.ts
@@ -15,28 +15,38 @@
 import * as m from 'mithril';
 
 import {Actions} from '../common/actions';
+import {LogExists, LogExistsKey} from '../common/logs';
 import {QueryResponse} from '../common/queries';
 import {TimeSpan} from '../common/time';
 
 import {copyToClipboard} from './clipboard';
-import {DetailsPanel} from './details_panel';
+import {DragGestureHandler} from './drag_gesture_handler';
 import {globals} from './globals';
-import {NotesPanel} from './notes_panel';
+import {LogPanel} from './logs_panel';
+import {NotesEditorPanel, NotesPanel} from './notes_panel';
 import {OverviewTimelinePanel} from './overview_timeline_panel';
 import {createPage} from './pages';
 import {PanAndZoomHandler} from './pan_and_zoom_handler';
 import {Panel} from './panel';
 import {AnyAttrsVnode, PanelContainer} from './panel_container';
-import {TickmarkPanel} from './tickmark_panel';
+import {SliceDetailsPanel} from './slice_panel';
+import {ThreadStatePanel} from './thread_state_panel';
 import {TimeAxisPanel} from './time_axis_panel';
 import {computeZoom} from './time_scale';
 import {TimeSelectionPanel} from './time_selection_panel';
 import {TRACK_SHELL_WIDTH} from './track_constants';
 import {TrackGroupPanel} from './track_group_panel';
 import {TrackPanel} from './track_panel';
-import {VideoPanel} from './video_panel';
 
-const SIDEBAR_WIDTH = 256;
+const DRAG_HANDLE_HEIGHT_PX = 28;
+const DEFAULT_DETAILS_HEIGHT_PX = 230 + DRAG_HANDLE_HEIGHT_PX;
+const UP_ICON = 'keyboard_arrow_up';
+const DOWN_ICON = 'keyboard_arrow_down';
+
+function hasLogs(): boolean {
+  const data = globals.trackDataStore.get(LogExistsKey) as LogExists;
+  return data && data.exists;
+}
 
 class QueryTable extends Panel {
   view() {
@@ -97,25 +107,68 @@
   renderCanvas() {}
 }
 
+interface DragHandleAttrs {
+  height: number;
+  resize: (height: number) => void;
+}
 
-// Checks if the mousePos is within 3px of the start or end of the
-// current selected time range.
-function onTimeRangeBoundary(mousePos: number): 'START'|'END'|null {
-  const startSec = globals.frontendLocalState.selectedTimeRange.startSec;
-  const endSec = globals.frontendLocalState.selectedTimeRange.endSec;
-  if (startSec !== undefined && endSec !== undefined) {
-    const start = globals.frontendLocalState.timeScale.timeToPx(startSec);
-    const end = globals.frontendLocalState.timeScale.timeToPx(endSec);
-    const startDrag = mousePos - TRACK_SHELL_WIDTH;
-    const startDistance = Math.abs(start - startDrag);
-    const endDistance = Math.abs(end - startDrag);
-    const range = 3 * window.devicePixelRatio;
-    // We might be within 3px of both boundaries but we should choose
-    // the closest one.
-    if (startDistance < range && startDistance <= endDistance) return 'START';
-    if (endDistance < range && endDistance <= startDistance) return 'END';
+class DragHandle implements m.ClassComponent<DragHandleAttrs> {
+  private dragStartHeight = 0;
+  private height = 0;
+  private resize: (height: number) => void = () => {};
+  private isClosed = this.height <= DRAG_HANDLE_HEIGHT_PX;
+
+  oncreate({dom, attrs}: m.CVnodeDOM<DragHandleAttrs>) {
+    this.resize = attrs.resize;
+    this.height = attrs.height;
+    const elem = dom as HTMLElement;
+    new DragGestureHandler(
+        elem,
+        this.onDrag.bind(this),
+        this.onDragStart.bind(this),
+        this.onDragEnd.bind(this));
   }
-  return null;
+
+  onupdate({attrs}: m.CVnodeDOM<DragHandleAttrs>) {
+    this.resize = attrs.resize;
+    this.height = attrs.height;
+  }
+
+  onDrag(_x: number, y: number) {
+    const newHeight = this.dragStartHeight + (DRAG_HANDLE_HEIGHT_PX / 2) - y;
+    this.isClosed = Math.floor(newHeight) <= DRAG_HANDLE_HEIGHT_PX;
+    this.resize(Math.floor(newHeight));
+    globals.rafScheduler.scheduleFullRedraw();
+  }
+
+  onDragStart(_x: number, _y: number) {
+    this.dragStartHeight = this.height;
+  }
+
+  onDragEnd() {}
+
+  view() {
+    const icon = this.isClosed ? UP_ICON : DOWN_ICON;
+    const title = this.isClosed ? 'Show panel' : 'Hide panel';
+    return m(
+        '.handle',
+        m('.handle-title', 'Current Selection'),
+        m('i.material-icons',
+          {
+            onclick: () => {
+              if (this.height === DRAG_HANDLE_HEIGHT_PX) {
+                this.isClosed = false;
+                this.resize(DEFAULT_DETAILS_HEIGHT_PX);
+              } else {
+                this.isClosed = true;
+                this.resize(DRAG_HANDLE_HEIGHT_PX);
+              }
+              globals.rafScheduler.scheduleFullRedraw();
+            },
+            title
+          },
+          icon));
+  }
 }
 
 /**
@@ -125,6 +178,9 @@
 class TraceViewer implements m.ClassComponent {
   private onResize: () => void = () => {};
   private zoomContent?: PanAndZoomHandler;
+  private detailsHeight = DRAG_HANDLE_HEIGHT_PX;
+  // Used to set details panel to default height on selection.
+  private showDetailsPanel = true;
   // Used to prevent global deselection if a pan/drag select occurred.
   private keepCurrentSelection = false;
 
@@ -152,7 +208,7 @@
 
     this.zoomContent = new PanAndZoomHandler({
       element: panZoomEl,
-      contentOffsetX: SIDEBAR_WIDTH,
+      contentOffsetX: TRACK_SHELL_WIDTH,
       onPanned: (pannedPx: number) => {
         this.keepCurrentSelection = true;
         const traceTime = globals.state.traceTime;
@@ -181,39 +237,19 @@
         frontendLocalState.updateVisibleTime(newSpan);
         globals.rafScheduler.scheduleRedraw();
       },
-      shouldDrag: (currentPx: number) => {
-        return onTimeRangeBoundary(currentPx) !== null;
-      },
-      onDrag: (
-          dragStartPx: number,
-          prevPx: number,
-          currentPx: number,
-          editing: boolean) => {
+      onDragSelect: (selectStartPx: number|null, selectEndPx: number) => {
+        if (!selectStartPx) return;
+        this.keepCurrentSelection = true;
+        globals.frontendLocalState.setShowTimeSelectPreview(false);
         const traceTime = globals.state.traceTime;
         const scale = frontendLocalState.timeScale;
-        this.keepCurrentSelection = true;
-        if (editing) {
-          const startSec = frontendLocalState.selectedTimeRange.startSec;
-          const endSec = frontendLocalState.selectedTimeRange.endSec;
-          if (startSec !== undefined && endSec !== undefined) {
-            const newTime = scale.pxToTime(currentPx - TRACK_SHELL_WIDTH);
-            // Have to check again for when one boundary crosses over the other.
-            const curBoundary = onTimeRangeBoundary(prevPx);
-            if (curBoundary == null) return;
-            const keepTime = curBoundary === 'START' ? endSec : startSec;
-            frontendLocalState.selectTimeRange(
-                Math.max(Math.min(keepTime, newTime), traceTime.startSec),
-                Math.min(Math.max(keepTime, newTime), traceTime.endSec));
-          }
-        } else {
-          frontendLocalState.setShowTimeSelectPreview(false);
-          const dragStartTime = scale.pxToTime(dragStartPx - TRACK_SHELL_WIDTH);
-          const dragEndTime = scale.pxToTime(currentPx - TRACK_SHELL_WIDTH);
-          frontendLocalState.selectTimeRange(
-              Math.max(
-                  Math.min(dragStartTime, dragEndTime), traceTime.startSec),
-              Math.min(Math.max(dragStartTime, dragEndTime), traceTime.endSec));
-        }
+        const startPx = Math.min(selectStartPx, selectEndPx);
+        const endPx = Math.max(selectStartPx, selectEndPx);
+        const startTs = Math.max(traceTime.startSec,
+                               scale.pxToTime(startPx - TRACK_SHELL_WIDTH));
+        const endTs = Math.min(traceTime.endSec,
+                               scale.pxToTime(endPx - TRACK_SHELL_WIDTH));
+        globals.dispatch(Actions.selectTimeSpan({startTs, endTs}));
         globals.rafScheduler.scheduleRedraw();
       }
     });
@@ -241,45 +277,85 @@
         }));
       }
     }
-    scrollingPanels.unshift(m(QueryTable, {key: 'query'}));
+    scrollingPanels.unshift(m(QueryTable));
+
+    const detailsPanels: AnyAttrsVnode[] = [];
+    const curSelection = globals.state.currentSelection;
+    if (curSelection) {
+      switch (curSelection.kind) {
+        case 'NOTE':
+          detailsPanels.push(m(NotesEditorPanel, {
+            key: 'notes',
+            id: curSelection.id,
+          }));
+          break;
+        case 'SLICE':
+          detailsPanels.push(m(SliceDetailsPanel, {
+            key: 'slice',
+            utid: curSelection.utid,
+          }));
+          break;
+        case 'THREAD_STATE':
+          detailsPanels.push(m(ThreadStatePanel, {
+            key: 'thread_state',
+            ts: curSelection.ts,
+            dur: curSelection.dur,
+            utid: curSelection.utid,
+            state: curSelection.state
+          }));
+          break;
+        default:
+          break;
+      }
+    } else if (hasLogs()) {
+      detailsPanels.push(m(LogPanel, {}));
+    }
+
+    this.showDetailsPanel = detailsPanels.length > 0;
 
     return m(
         '.page',
-        m('.split-panel',
-          m('.pan-and-zoom-content',
-            {
-              onclick: () => {
-                // We don't want to deselect when panning/drag selecting.
-                if (this.keepCurrentSelection) {
-                  this.keepCurrentSelection = false;
-                  return;
-                }
-                globals.makeSelection(Actions.deselect({}));
+        m('.pan-and-zoom-content',
+          {
+            onclick: () => {
+              // We don't want to deselect when panning/drag selecting.
+              if (this.keepCurrentSelection) {
+                this.keepCurrentSelection = false;
+                return;
               }
+              globals.dispatch(Actions.deselect({}));
+            }
+          },
+          m('.pinned-panel-container', m(PanelContainer, {
+              doesScroll: false,
+              panels: [
+                m(OverviewTimelinePanel, {key: 'overview'}),
+                m(TimeAxisPanel, {key: 'timeaxis'}),
+                m(TimeSelectionPanel, {key: 'timeselection'}),
+                m(NotesPanel, {key: 'notes'}),
+                ...globals.state.pinnedTracks.map(
+                    id => m(TrackPanel, {key: id, id})),
+              ],
+            })),
+          m('.scrolling-panel-container', m(PanelContainer, {
+              doesScroll: true,
+              panels: scrollingPanels,
+            }))),
+        m('.details-content',
+          {
+            style: {
+              height: `${this.detailsHeight}px`,
+              display: this.showDetailsPanel ? null : 'none'
+            }
+          },
+          m(DragHandle, {
+            resize: (height: number) => {
+              this.detailsHeight = Math.max(height, DRAG_HANDLE_HEIGHT_PX);
             },
-            m('.pinned-panel-container', m(PanelContainer, {
-                doesScroll: false,
-                panels: [
-                  m(OverviewTimelinePanel, {key: 'overview'}),
-                  m(TimeAxisPanel, {key: 'timeaxis'}),
-                  m(TimeSelectionPanel, {key: 'timeselection'}),
-                  m(NotesPanel, {key: 'notes'}),
-                  m(TickmarkPanel, {key: 'searchTickmarks'}),
-                  ...globals.state.pinnedTracks.map(
-                      id => m(TrackPanel, {key: id, id})),
-                ],
-                kind: 'OVERVIEW',
-              })),
-            m('.scrolling-panel-container', m(PanelContainer, {
-                doesScroll: true,
-                panels: scrollingPanels,
-                kind: 'TRACKS',
-              }))),
-          m('.video-panel',
-            (globals.state.videoEnabled && globals.state.video != null) ?
-                m(VideoPanel) :
-                null)),
-        m(DetailsPanel));
+            height: this.detailsHeight,
+          }),
+          m('.details-panel-container',
+            m(PanelContainer, {doesScroll: true, panels: detailsPanels}))));
   }
 }
 
diff --git a/ui/src/query/index.ts b/ui/src/query/index.ts
index bbb1f2c..aff94bc 100644
--- a/ui/src/query/index.ts
+++ b/ui/src/query/index.ts
@@ -169,7 +169,10 @@
     if (this.engine) {
       destroyWasmEngine(kEngineId);
     }
-    this.engine = new WasmEngineProxy('engine', createWasmEngine(kEngineId));
+    this.engine = new WasmEngineProxy({
+      id: 'engine',
+      worker: createWasmEngine(kEngineId),
+    });
 
     this.file = input.file;
     this.readNextSlice(0);
@@ -294,7 +297,7 @@
                   isResult(q) ? `${q.executionTimeNs / 1000000}ms` : ''),
                 isResult(q) ? m('.query-content', renderTable(q.result)) : null,
                 isError(q) ? m('.query-content', q.error) : null,
-                isPending(q) ? m('.query-content') : null))),
+                isPending(q) ? m('.query-content') : null, ))),
   ]);
 }
 
@@ -304,7 +307,7 @@
       m('tr', columns(result).map(c => m('th', c))),
       rows(result, 0, 1000).map(r => {
         return m('tr', Object.values(r).map(d => m('td', d)));
-      }));
+      }), );
 }
 
 function main() {
diff --git a/ui/src/tracks/all_controller.ts b/ui/src/tracks/all_controller.ts
index 912f34f..efbd666 100644
--- a/ui/src/tracks/all_controller.ts
+++ b/ui/src/tracks/all_controller.ts
@@ -17,13 +17,9 @@
 import './android_log/controller';
 import './chrome_slices/controller';
 import './counter/controller';
-import './heap_profile/controller';
-import './heap_profile_flamegraph/controller';
 import './cpu_freq/controller';
-import './gpu_freq/controller';
 import './cpu_slices/controller';
 import './process_scheduling/controller';
 import './process_summary/controller';
 import './thread_state/controller';
 import './vsync/controller';
-import './async_slices/controller';
diff --git a/ui/src/tracks/all_frontend.ts b/ui/src/tracks/all_frontend.ts
index 2957edf..4660c34 100644
--- a/ui/src/tracks/all_frontend.ts
+++ b/ui/src/tracks/all_frontend.ts
@@ -17,13 +17,9 @@
 import './android_log/frontend';
 import './chrome_slices/frontend';
 import './counter/frontend';
-import './heap_profile/frontend';
-import './heap_profile_flamegraph/frontend';
 import './cpu_freq/frontend';
-import './gpu_freq/frontend';
 import './cpu_slices/frontend';
 import './process_scheduling/frontend';
 import './process_summary/frontend';
 import './thread_state/frontend';
 import './vsync/frontend';
-import './async_slices/frontend';
diff --git a/ui/src/tracks/android_log/common.ts b/ui/src/tracks/android_log/common.ts
index c5cff54..9b95fd2 100644
--- a/ui/src/tracks/android_log/common.ts
+++ b/ui/src/tracks/android_log/common.ts
@@ -12,11 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {TrackData} from '../../common/track_data';
-
 export const ANDROID_LOGS_TRACK_KIND = 'AndroidLogTrack';
 
-export interface Data extends TrackData {
+export interface Data {
+  start: number;
+  end: number;
+  resolution: number;
+
   // Total number of log events within [start, end], before any quantization.
   numEvents: number;
 
diff --git a/ui/src/tracks/android_log/controller.ts b/ui/src/tracks/android_log/controller.ts
index fba13d7..111bf7d 100644
--- a/ui/src/tracks/android_log/controller.ts
+++ b/ui/src/tracks/android_log/controller.ts
@@ -12,27 +12,34 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {fromNs, toNsCeil, toNsFloor} from '../../common/time';
-import {LIMIT} from '../../common/track_data';
+import {fromNs} from '../../common/time';
 import {
   TrackController,
-  trackControllerRegistry,
+  trackControllerRegistry
 } from '../../controller/track_controller';
 
 import {ANDROID_LOGS_TRACK_KIND, Config, Data} from './common';
 
 class AndroidLogTrackController extends TrackController<Config, Data> {
   static readonly kind = ANDROID_LOGS_TRACK_KIND;
+  private busy = false;
 
-  async onBoundsChange(start: number, end: number, resolution: number):
-      Promise<Data> {
-    const startNs = toNsFloor(start);
-    const endNs = toNsCeil(end);
+  onBoundsChange(start: number, end: number, resolution: number) {
+    this.update(start, end, resolution);
+  }
+
+  private async update(start: number, end: number, resolution: number) {
+    // TODO(hjd): we should really call TraceProcessor.Interrupt() here.
+    if (this.busy) return;
+    this.busy = true;
+
+    const startNs = Math.floor(start * 1e9);
+    const endNs = Math.ceil(end * 1e9);
 
     // |resolution| is in s/px the frontend wants.
-    const quantNs = toNsCeil(resolution);
+    const quantNs = Math.ceil(resolution * 1e9);
 
-    const rawResult = await this.query(`
+    const rawResult = await this.engine.query(`
       select
         cast(ts / ${quantNs} as integer) * ${quantNs} as ts_quant,
         prio,
@@ -40,14 +47,14 @@
       from android_logs
       where ts >= ${startNs} and ts <= ${endNs}
       group by ts_quant, prio
-      order by ts_quant, prio limit ${LIMIT};`);
+      order by ts_quant, prio;`);
+    this.busy = false;
 
     const rowCount = +rawResult.numRecords;
     const result = {
       start,
       end,
       resolution,
-      length: rowCount,
       numEvents: 0,
       timestamps: new Float64Array(rowCount),
       priorities: new Uint8Array(rowCount),
@@ -59,7 +66,7 @@
       result.priorities[i] |= (1 << prio);
       result.numEvents += +cols[2].longValues![i];
     }
-    return result;
+    this.publish(result);
   }
 }
 
diff --git a/ui/src/tracks/android_log/frontend.ts b/ui/src/tracks/android_log/frontend.ts
index 76f3aa7..eefa829 100644
--- a/ui/src/tracks/android_log/frontend.ts
+++ b/ui/src/tracks/android_log/frontend.ts
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+import {Actions} from '../../common/actions';
 import {TrackState} from '../../common/state';
 import {checkerboardExcept} from '../../frontend/checkerboard';
 import {globals} from '../../frontend/globals';
@@ -37,6 +38,12 @@
 const RECT_HEIGHT = 35;
 const EVT_PX = 2;  // Width of an event tick in pixels.
 
+function getCurResolution() {
+  // Truncate the resolution to the closest power of 10.
+  const resolution =
+      globals.frontendLocalState.timeScale.deltaPxToDuration(EVT_PX);
+  return Math.pow(10, Math.floor(Math.log10(resolution)));
+}
 
 class AndroidLogTrack extends Track<Config, Data> {
   static readonly kind = ANDROID_LOGS_TRACK_KIND;
@@ -44,15 +51,40 @@
     return new AndroidLogTrack(trackState);
   }
 
+  private reqPending = false;
+
   constructor(trackState: TrackState) {
     super(trackState);
   }
 
+  reqDataDeferred() {
+    const {visibleWindowTime} = globals.frontendLocalState;
+    const reqStart = visibleWindowTime.start - visibleWindowTime.duration;
+    const reqEnd = visibleWindowTime.end + visibleWindowTime.duration;
+    const reqRes = getCurResolution();
+    this.reqPending = false;
+    globals.dispatch(Actions.reqTrackData({
+      trackId: this.trackState.id,
+      start: reqStart,
+      end: reqEnd,
+      resolution: reqRes
+    }));
+  }
+
   renderCanvas(ctx: CanvasRenderingContext2D): void {
     const {timeScale, visibleWindowTime} = globals.frontendLocalState;
 
     const data = this.data();
-
+    const inRange = data !== undefined &&
+        (visibleWindowTime.start >= data.start &&
+         visibleWindowTime.end <= data.end);
+    if (!inRange || data === undefined ||
+        data.resolution !== getCurResolution()) {
+      if (!this.reqPending) {
+        this.reqPending = true;
+        setTimeout(() => this.reqDataDeferred(), 50);
+      }
+    }
     if (data === undefined) return;  // Can't possibly draw anything.
 
     const dataStartPx = timeScale.timeToPx(data.start);
@@ -61,12 +93,7 @@
     const visibleEndPx = timeScale.timeToPx(visibleWindowTime.end);
 
     checkerboardExcept(
-        ctx,
-        this.getHeight(),
-        visibleStartPx,
-        visibleEndPx,
-        dataStartPx,
-        dataEndPx);
+        ctx, visibleStartPx, visibleEndPx, dataStartPx, dataEndPx);
 
     const quantWidth =
         Math.max(EVT_PX, timeScale.deltaTimeToPx(data.resolution));
diff --git a/ui/src/tracks/async_slices/common.ts b/ui/src/tracks/async_slices/common.ts
deleted file mode 100644
index 3b7c885..0000000
--- a/ui/src/tracks/async_slices/common.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (C) 2019 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.
-
-export {Data} from '../chrome_slices/common';
-
-export const SLICE_TRACK_KIND = 'AsyncSliceTrack';
-
-export interface Config {
-  maxDepth: number;
-  trackId: number;
-}
diff --git a/ui/src/tracks/async_slices/controller.ts b/ui/src/tracks/async_slices/controller.ts
deleted file mode 100644
index c5e5e88..0000000
--- a/ui/src/tracks/async_slices/controller.ts
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {fromNs, toNs} from '../../common/time';
-import {LIMIT} from '../../common/track_data';
-import {
-  TrackController,
-  trackControllerRegistry,
-} from '../../controller/track_controller';
-
-import {Config, Data, SLICE_TRACK_KIND} from './common';
-
-class AsyncSliceTrackController extends TrackController<Config, Data> {
-  static readonly kind = SLICE_TRACK_KIND;
-  private setup = false;
-
-  async onBoundsChange(start: number, end: number, resolution: number):
-      Promise<Data> {
-    const startNs = toNs(start);
-    const endNs = toNs(end);
-    // Ns in 1px width. We want all slices smaller than 1px to be grouped.
-    const minNs = toNs(resolution);
-
-    if (!this.setup) {
-      await this.query(
-          `create virtual table ${this.tableName('window')} using window;`);
-
-      await this.query(
-          `create view ${this.tableName('small')} as ` +
-          `select ts,dur,depth,name,slice_id from slice ` +
-          `where track_id = ${this.config.trackId} ` +
-          `and dur < ${minNs} ` +
-          `order by ts;`);
-
-      await this.query(`create virtual table ${this.tableName('span')} using
-      span_join(${this.tableName('small')} PARTITIONED depth,
-      ${this.tableName('window')});`);
-
-      this.setup = true;
-    }
-
-    const windowDurNs = Math.max(1, endNs - startNs);
-
-    this.query(`update ${this.tableName('window')} set
-    window_start=${startNs},
-    window_dur=${windowDurNs},
-    quantum=${minNs}`);
-
-    await this.query(`drop view if exists ${this.tableName('small')}`);
-    await this.query(`drop view if exists ${this.tableName('big')}`);
-    await this.query(`drop view if exists ${this.tableName('summary')}`);
-
-    await this.query(
-        `create view ${this.tableName('small')} as ` +
-        `select ts,dur,depth,name, slice_id from slice ` +
-        `where track_id = ${this.config.trackId} ` +
-        `and dur < ${minNs} ` +
-        `order by ts `);
-
-    await this.query(
-        `create view ${this.tableName('big')} as ` +
-        `select ts,dur,depth,name, slice_id from slice ` +
-        `where track_id = ${this.config.trackId} ` +
-        `and ts >= ${startNs} - dur ` +
-        `and ts <= ${endNs} ` +
-        `and dur >= ${minNs} ` +
-        `order by ts `);
-
-    // So that busy slices never overlap, we use the start of the bucket
-    // as the ts, even though min(ts) would technically be more accurate.
-    await this.query(`create view ${this.tableName('summary')} as select
-      (quantum_ts * ${minNs} + ${startNs}) as ts,
-      ${minNs} as dur,
-      depth,
-      'Busy' as name,
-      -1 as slice_id
-      from ${this.tableName('span')}
-      group by depth, quantum_ts
-      order by ts;`);
-
-    const query = `select * from ${this.tableName('summary')} UNION ` +
-        `select * from ${this.tableName('big')} order by ts limit ${LIMIT}`;
-
-    const rawResult = await this.query(query);
-
-    if (rawResult.error) {
-      throw new Error(`Query error "${query}": ${rawResult.error}`);
-    }
-
-    const numRows = +rawResult.numRecords;
-
-    const slices: Data = {
-      start,
-      end,
-      resolution,
-      length: numRows,
-      strings: [],
-      sliceIds: new Float64Array(numRows),
-      starts: new Float64Array(numRows),
-      ends: new Float64Array(numRows),
-      depths: new Uint16Array(numRows),
-      titles: new Uint16Array(numRows),
-    };
-
-    const stringIndexes = new Map<string, number>();
-    function internString(str: string) {
-      let idx = stringIndexes.get(str);
-      if (idx !== undefined) return idx;
-      idx = slices.strings.length;
-      slices.strings.push(str);
-      stringIndexes.set(str, idx);
-      return idx;
-    }
-
-    for (let row = 0; row < numRows; row++) {
-      const cols = rawResult.columns;
-      const startSec = fromNs(+cols[0].longValues![row]);
-      slices.starts[row] = startSec;
-      slices.ends[row] = startSec + fromNs(+cols[1].longValues![row]);
-      slices.depths[row] = +cols[2].longValues![row];
-      slices.titles[row] = internString(cols[3].stringValues![row]);
-      slices.sliceIds[row] = +cols[4].longValues![row];
-    }
-    return slices;
-  }
-}
-
-
-trackControllerRegistry.register(AsyncSliceTrackController);
diff --git a/ui/src/tracks/async_slices/frontend.ts b/ui/src/tracks/async_slices/frontend.ts
deleted file mode 100644
index 918f831..0000000
--- a/ui/src/tracks/async_slices/frontend.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {TrackState} from '../../common/state';
-import {Track} from '../../frontend/track';
-import {trackRegistry} from '../../frontend/track_registry';
-import {ChromeSliceTrack} from '../chrome_slices/frontend';
-
-import {SLICE_TRACK_KIND} from './common';
-
-export class AsyncSliceTrack extends ChromeSliceTrack {
-  static readonly kind = SLICE_TRACK_KIND;
-  static create(trackState: TrackState): Track {
-    return new AsyncSliceTrack(trackState);
-  }
-}
-
-trackRegistry.register(AsyncSliceTrack);
diff --git a/ui/src/tracks/chrome_slices/common.ts b/ui/src/tracks/chrome_slices/common.ts
index faa40c3..1256dc7 100644
--- a/ui/src/tracks/chrome_slices/common.ts
+++ b/ui/src/tracks/chrome_slices/common.ts
@@ -12,23 +12,24 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {TrackData} from '../../common/track_data';
-
 export const SLICE_TRACK_KIND = 'ChromeSliceTrack';
 
 export interface Config {
   maxDepth: number;
   upid: number;
   utid: number;
-  trackId: number;
 }
 
-export interface Data extends TrackData {
+export interface Data {
+  start: number;
+  end: number;
+  resolution: number;
+
   // Slices are stored in a columnar fashion. All fields have the same length.
   strings: string[];
-  sliceIds: Float64Array;
   starts: Float64Array;
   ends: Float64Array;
   depths: Uint16Array;
   titles: Uint16Array;      // Index in |strings|.
+  categories: Uint16Array;  // Index in |strings|.
 }
diff --git a/ui/src/tracks/chrome_slices/controller.ts b/ui/src/tracks/chrome_slices/controller.ts
index 09abcd9..55fb7e9 100644
--- a/ui/src/tracks/chrome_slices/controller.ts
+++ b/ui/src/tracks/chrome_slices/controller.ts
@@ -12,25 +12,33 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {fromNs, toNs} from '../../common/time';
-import {LIMIT} from '../../common/track_data';
+import {fromNs} from '../../common/time';
 import {
   TrackController,
-  trackControllerRegistry,
+  trackControllerRegistry
 } from '../../controller/track_controller';
 
 import {Config, Data, SLICE_TRACK_KIND} from './common';
 
 class ChromeSliceTrackController extends TrackController<Config, Data> {
   static readonly kind = SLICE_TRACK_KIND;
+  private busy = false;
   private setup = false;
 
-  async onBoundsChange(start: number, end: number, resolution: number):
-      Promise<Data> {
-    const startNs = toNs(start);
-    const endNs = toNs(end);
+  onBoundsChange(start: number, end: number, resolution: number): void {
+    this.update(start, end, resolution);
+  }
+
+  private async update(start: number, end: number, resolution: number) {
+    // TODO: we should really call TraceProcessor.Interrupt() at this point.
+    if (this.busy) return;
+
+    const startNs = Math.round(start * 1e9);
+    const endNs = Math.round(end * 1e9);
     // Ns in 1px width. We want all slices smaller than 1px to be grouped.
-    const minNs = toNs(resolution);
+    const minNs = Math.round(resolution * 1e9);
+    const LIMIT = 10000;
+    this.busy = true;
 
     if (!this.setup) {
       await this.query(
@@ -38,13 +46,16 @@
 
       await this.query(
           `create view ${this.tableName('small')} as ` +
-          `select ts,dur,depth,name,slice_id from slice ` +
-          `where track_id = ${this.config.trackId} ` +
+          `select ts,dur,depth,cat,name from slices ` +
+          `where utid = ${this.config.utid} ` +
+          `and ts >= ${startNs} - dur ` +
+          `and ts <= ${endNs} ` +
           `and dur < ${minNs} ` +
-          `order by ts;`);
+          `order by ts ` +
+          `limit ${LIMIT};`);
 
       await this.query(`create virtual table ${this.tableName('span')} using
-      span_join(${this.tableName('small')} PARTITIONED depth,
+      span_join(${this.tableName('small')},
       ${this.tableName('window')});`);
 
       this.setup = true;
@@ -63,36 +74,37 @@
 
     await this.query(
         `create view ${this.tableName('small')} as ` +
-        `select ts,dur,depth,name,slice_id from slice ` +
-        `where track_id = ${this.config.trackId} ` +
+        `select ts,dur,depth,cat,name from slices ` +
+        `where utid = ${this.config.utid} ` +
+        `and ts >= ${startNs} - dur ` +
+        `and ts <= ${endNs} ` +
         `and dur < ${minNs} ` +
         `order by ts `);
 
     await this.query(
         `create view ${this.tableName('big')} as ` +
-        `select ts,dur,depth,name,slice_id from slice ` +
-        `where track_id = ${this.config.trackId} ` +
+        `select ts,dur,depth,cat,name from slices ` +
+        `where utid = ${this.config.utid} ` +
         `and ts >= ${startNs} - dur ` +
         `and ts <= ${endNs} ` +
         `and dur >= ${minNs} ` +
         `order by ts `);
 
-    // So that busy slices never overlap, we use the start of the bucket
-    // as the ts, even though min(ts) would technically be more accurate.
     await this.query(`create view ${this.tableName('summary')} as select
-      (quantum_ts * ${minNs} + ${startNs}) as ts,
+      min(ts) as ts,
       ${minNs} as dur,
       depth,
-      'Busy' as name,
-      -1 as slice_id
+      cat,
+      'Busy' as name
       from ${this.tableName('span')}
-      group by depth, quantum_ts
-      order by ts;`);
+      group by cat, depth, quantum_ts
+      limit ${LIMIT};`);
 
     const query = `select * from ${this.tableName('summary')} UNION ` +
-        `select * from ${this.tableName('big')} order by ts limit ${LIMIT}`;
+        `select * from ${this.tableName('big')} order by ts`;
 
     const rawResult = await this.query(query);
+    this.busy = false;
 
     if (rawResult.error) {
       throw new Error(`Query error "${query}": ${rawResult.error}`);
@@ -104,13 +116,12 @@
       start,
       end,
       resolution,
-      length: numRows,
       strings: [],
-      sliceIds: new Float64Array(numRows),
       starts: new Float64Array(numRows),
       ends: new Float64Array(numRows),
       depths: new Uint16Array(numRows),
       titles: new Uint16Array(numRows),
+      categories: new Uint16Array(numRows),
     };
 
     const stringIndexes = new Map<string, number>();
@@ -129,12 +140,23 @@
       slices.starts[row] = startSec;
       slices.ends[row] = startSec + fromNs(+cols[1].longValues![row]);
       slices.depths[row] = +cols[2].longValues![row];
-      slices.titles[row] = internString(cols[3].stringValues![row]);
-      slices.sliceIds[row] = +cols[4].longValues![row];
+      slices.categories[row] = internString(cols[3].stringValues![row]);
+      slices.titles[row] = internString(cols[4].stringValues![row]);
     }
-    return slices;
+    if (numRows === LIMIT) {
+      slices.end = slices.ends[slices.ends.length - 1];
+    }
+    this.publish(slices);
   }
 
+  private async query(query: string) {
+    const result = await this.engine.query(query);
+    if (result.error) {
+      console.error(`Query error "${query}": ${result.error}`);
+      throw new Error(`Query error "${query}": ${result.error}`);
+    }
+    return result;
+  }
 }
 
 
diff --git a/ui/src/tracks/chrome_slices/frontend.ts b/ui/src/tracks/chrome_slices/frontend.ts
index 41f2541..1e01e31 100644
--- a/ui/src/tracks/chrome_slices/frontend.ts
+++ b/ui/src/tracks/chrome_slices/frontend.ts
@@ -12,7 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {Actions} from '../../common/actions';
 import {cropText} from '../../common/canvas_utils';
 import {TrackState} from '../../common/state';
 import {checkerboardExcept} from '../../frontend/checkerboard';
@@ -22,8 +21,8 @@
 
 import {Config, Data, SLICE_TRACK_KIND} from './common';
 
-const SLICE_HEIGHT = 18;
-const TRACK_PADDING = 4;
+const SLICE_HEIGHT = 20;
+const TRACK_PADDING = 5;
 
 function hash(s: string): number {
   let hash = 0x811c9dc5 & 0xfffffff;
@@ -34,9 +33,9 @@
   return hash & 0xff;
 }
 
-export class ChromeSliceTrack extends Track<Config, Data> {
-  static readonly kind: string = SLICE_TRACK_KIND;
-  static create(trackState: TrackState): Track {
+class ChromeSliceTrack extends Track<Config, Data> {
+  static readonly kind = SLICE_TRACK_KIND;
+  static create(trackState: TrackState): ChromeSliceTrack {
     return new ChromeSliceTrack(trackState);
   }
 
@@ -52,18 +51,25 @@
     const {timeScale, visibleWindowTime} = globals.frontendLocalState;
     const data = this.data();
 
-    if (data === undefined) return;  // Can't possibly draw anything.
+    // If there aren't enough cached slices data in |data| request more to
+    // the controller.
+    const inRange = data !== undefined &&
+        (visibleWindowTime.start >= data.start &&
+         visibleWindowTime.end <= data.end);
+    if (!inRange || data === undefined ||
+        data.resolution > globals.getCurResolution()) {
+      globals.requestTrackData(this.trackState.id);
+      if (data === undefined) return;  // Can't possibly draw anything.
+    }
 
     // If the cached trace slices don't fully cover the visible time range,
     // show a gray rectangle with a "Loading..." label.
     checkerboardExcept(
         ctx,
-        this.getHeight(),
         timeScale.timeToPx(visibleWindowTime.start),
         timeScale.timeToPx(visibleWindowTime.end),
         timeScale.timeToPx(data.start),
-        timeScale.timeToPx(data.end),
-    );
+        timeScale.timeToPx(data.end), );
 
     ctx.font = '12px Google Sans';
     ctx.textAlign = 'center';
@@ -72,16 +78,12 @@
     const charWidth = ctx.measureText('ACBDLqsdfg').width / 10;
     const pxEnd = timeScale.timeToPx(visibleWindowTime.end);
 
-    // The draw of the rect on the selected slice must happen after the other
-    // drawings, otherwise it would result under another rect.
-    let drawRectOnSelected = () => {};
-
     for (let i = 0; i < data.starts.length; i++) {
       const tStart = data.starts[i];
       const tEnd = data.ends[i];
       const depth = data.depths[i];
+      const cat = data.strings[data.categories[i]];
       const titleId = data.titles[i];
-      const sliceId = data.sliceIds[i];
       const title = data.strings[titleId];
       if (tEnd <= visibleWindowTime.start || tStart >= visibleWindowTime.end) {
         continue;
@@ -92,37 +94,20 @@
       const rectYStart = TRACK_PADDING + depth * SLICE_HEIGHT;
 
       const hovered = titleId === this.hoveredTitleId;
-      const name = title.replace(/( )?\d+/g, '');
-      const hue = title === 'Busy' ? 88 : hash(name);
-      const saturation = 50;
+      const hue = hash(cat);
+      const saturation = Math.min(20 + depth * 10, 70);
       ctx.fillStyle = `hsl(${hue}, ${saturation}%, ${hovered ? 30 : 65}%)`;
       ctx.fillRect(rectXStart, rectYStart, rectWidth, SLICE_HEIGHT);
 
-      // Selected case
-      const currentSelection = globals.state.currentSelection;
-      if (currentSelection && currentSelection.kind === 'CHROME_SLICE' &&
-          currentSelection.id !== undefined &&
-          currentSelection.id === sliceId) {
-        drawRectOnSelected = () => {
-          ctx.strokeStyle = `hsl(${hue}, ${saturation}%, 30%)`;
-          ctx.beginPath();
-          ctx.lineWidth = 3;
-          ctx.strokeRect(
-              rectXStart, rectYStart - 1.5, rectWidth, SLICE_HEIGHT + 3);
-          ctx.closePath();
-        };
-      }
-
       ctx.fillStyle = 'white';
       const displayText = cropText(title, charWidth, rectWidth);
       const rectXCenter = rectXStart + rectWidth / 2;
       ctx.textBaseline = "middle";
       ctx.fillText(displayText, rectXCenter, rectYStart + SLICE_HEIGHT / 2);
     }
-    drawRectOnSelected();
   }
 
-  getSliceIndex({x, y}: {x: number, y: number}): number|void {
+  onMouseMove({x, y}: {x: number, y: number}) {
     const data = this.data();
     this.hoveredTitleId = -1;
     if (data === undefined) return;
@@ -133,39 +118,18 @@
     for (let i = 0; i < data.starts.length; i++) {
       const tStart = data.starts[i];
       const tEnd = data.ends[i];
+      const titleId = data.titles[i];
       if (tStart <= t && t <= tEnd && depth === data.depths[i]) {
-        return i;
+        this.hoveredTitleId = titleId;
+        break;
       }
     }
   }
 
-  onMouseMove({x, y}: {x: number, y: number}) {
-    const sliceIndex = this.getSliceIndex({x, y});
-    if (sliceIndex === undefined) return;
-    const data = this.data();
-    if (data === undefined) return;
-    const titleId = data.titles[sliceIndex];
-    this.hoveredTitleId = titleId;
-  }
-
   onMouseOut() {
     this.hoveredTitleId = -1;
   }
 
-  onMouseClick({x, y}: {x: number, y: number}): boolean {
-    const sliceIndex = this.getSliceIndex({x, y});
-    if (sliceIndex === undefined) return false;
-    const data = this.data();
-    if (data === undefined) return false;
-    const sliceId = data.sliceIds[sliceIndex];
-    if (sliceId) {
-      globals.makeSelection(Actions.selectChromeSlice(
-          {id: sliceId, trackId: this.trackState.id}));
-      return true;
-    }
-    return false;
-  }
-
   getHeight() {
     return SLICE_HEIGHT * (this.config.maxDepth + 1) + 2 * TRACK_PADDING;
   }
diff --git a/ui/src/tracks/counter/common.ts b/ui/src/tracks/counter/common.ts
index 0eb6dfb..fa91235 100644
--- a/ui/src/tracks/counter/common.ts
+++ b/ui/src/tracks/counter/common.ts
@@ -12,18 +12,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {TrackData} from '../../common/track_data';
-
 export const COUNTER_TRACK_KIND = 'CounterTrack';
 
-export interface Data extends TrackData {
+export interface Data {
+  start: number;
+  end: number;
   isQuantized: boolean;
+  resolution: number;
   maximumValue: number;
   minimumValue: number;
 
   timestamps: Float64Array;
   values: Float64Array;
-  ids: Float64Array;
 }
 
 export interface Config {
@@ -31,5 +31,4 @@
   maximumValue?: number;
   minimumValue?: number;
   ref: number;
-  scale?: 'DEFAULT'|'RELATIVE';
 }
diff --git a/ui/src/tracks/counter/controller.ts b/ui/src/tracks/counter/controller.ts
index 4085845..22c7f42 100644
--- a/ui/src/tracks/counter/controller.ts
+++ b/ui/src/tracks/counter/controller.ts
@@ -12,9 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {fromNs, toNs} from '../../common/time';
-import {LIMIT} from '../../common/track_data';
-
+import {fromNs} from '../../common/time';
 import {
   TrackController,
   trackControllerRegistry
@@ -28,15 +26,24 @@
 
 class CounterTrackController extends TrackController<Config, Data> {
   static readonly kind = COUNTER_TRACK_KIND;
+  private busy = false;
   private setup = false;
   private maximumValueSeen = 0;
   private minimumValueSeen = 0;
 
-  async onBoundsChange(start: number, end: number, resolution: number):
-      Promise<Data> {
-    const startNs = toNs(start);
-    const endNs = toNs(end);
+  onBoundsChange(start: number, end: number, resolution: number): void {
+    this.update(start, end, resolution);
+  }
 
+  private async update(start: number, end: number, resolution: number):
+      Promise<void> {
+    // TODO: we should really call TraceProcessor.Interrupt() at this point.
+    if (this.busy) return;
+
+    const startNs = Math.round(start * 1e9);
+    const endNs = Math.round(end * 1e9);
+
+    this.busy = true;
     if (!this.setup) {
       const result = await this.query(`
       select max(value), min(value) from
@@ -49,7 +56,7 @@
 
       await this.query(`create view ${this.tableName('counter_view')} as
         select ts,
-        lead(ts, 1, ts) over (partition by ref_type order by ts) - ts as dur,
+        lead(ts) over (partition by ref_type order by ts) - ts as dur,
         value, name, ref
         from counters
         where name = '${this.config.name}' and ref = ${this.config.ref};`);
@@ -60,16 +67,7 @@
       this.setup = true;
     }
 
-    const result = await this.engine.queryOneRow(`select count(*)
-    from (select
-      ts,
-      lead(ts, 1, ts) over (partition by ref_type order by ts) as ts_end,
-      from counters
-      where name = '${this.config.name}' and ref = ${this.config.ref})
-    where ts <= ${endNs} and ${startNs} <= ts_end`);
-
-    // Only quantize if we have too much data to draw.
-    const isQuantized = result[0] > LIMIT;
+    const isQuantized = this.shouldSummarize(resolution);
     // |resolution| is in s/px we want # ns for 10px window:
     const bucketSizeNs = Math.round(resolution * 10 * 1e9);
     let windowStartNs = startNs;
@@ -86,26 +84,18 @@
     let query = `select min(ts) as ts,
       max(value) as value
       from ${this.tableName('span')}
-      group by quantum_ts limit ${LIMIT};`;
+      group by quantum_ts;`;
 
     if (!isQuantized) {
-      // Find the value just before the query range to ensure counters
-      // continue from the correct previous value.
-      // Union that with the query that finds all the counters within
-      // the current query range.
-      query = `
-      select * from (select ts, value, counter_id from counters
-      where name = '${this.config.name}' and ref = ${this.config.ref} and
-      ts <= ${startNs} order by ts desc limit 1)
-      UNION
-      select * from (select ts, value, counter_id
+      // TODO(hjd): Implement window clipping.
+      query = `select ts, value
         from (select
           ts,
-          lead(ts, 1, ts) over (partition by ref_type order by ts) as ts_end,
-          value, counter_id
+          lead(ts) over (partition by ref_type order by ts) as ts_end,
+          value
           from counters
           where name = '${this.config.name}' and ref = ${this.config.ref})
-      where ts <= ${endNs} and ${startNs} <= ts_end limit ${LIMIT});`;
+      where ts <= ${endNs} and ${startNs} <= ts_end;`;
     }
 
     const rawResult = await this.query(query);
@@ -115,45 +105,42 @@
     const data: Data = {
       start,
       end,
-      length: numRows,
       isQuantized,
       maximumValue: this.maximumValue(),
       minimumValue: this.minimumValue(),
       resolution,
       timestamps: new Float64Array(numRows),
       values: new Float64Array(numRows),
-      ids: new Float64Array(numRows),
     };
 
     const cols = rawResult.columns;
     for (let row = 0; row < numRows; row++) {
       const startSec = fromNs(+cols[0].longValues![row]);
       const value = +cols[1].doubleValues![row];
-      const id = +cols[2].longValues![row];
       data.timestamps[row] = startSec;
       data.values[row] = value;
-      data.ids[row] = id;
     }
 
-    return data;
+    this.publish(data);
+    this.busy = false;
   }
 
   private maximumValue() {
-    if (this.config.maximumValue === undefined) {
-      return this.maximumValueSeen;
-    } else {
-      return this.config.maximumValue;
-    }
+    return Math.max(this.config.maximumValue || 0, this.maximumValueSeen);
   }
 
   private minimumValue() {
-    if (this.config.minimumValue === undefined) {
-      return this.minimumValueSeen;
-    } else {
-      return this.config.minimumValue;
-    }
+    return Math.min(this.config.minimumValue || 0, this.minimumValueSeen);
   }
 
+  private async query(query: string) {
+    const result = await this.engine.query(query);
+    if (result.error) {
+      console.error(`Query error "${query}": ${result.error}`);
+      throw new Error(`Query error "${query}": ${result.error}`);
+    }
+    return result;
+  }
 }
 
 trackControllerRegistry.register(CounterTrackController);
diff --git a/ui/src/tracks/counter/frontend.ts b/ui/src/tracks/counter/frontend.ts
index 3fcfe3e..138b74b 100644
--- a/ui/src/tracks/counter/frontend.ts
+++ b/ui/src/tracks/counter/frontend.ts
@@ -12,17 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import * as m from 'mithril';
-
 import {searchSegment} from '../../base/binary_search';
 import {assertTrue} from '../../base/logging';
-import {Actions} from '../../common/actions';
 import {TrackState} from '../../common/state';
-import {toNs} from '../../common/time';
 import {checkerboardExcept} from '../../frontend/checkerboard';
 import {globals} from '../../frontend/globals';
 import {Track} from '../../frontend/track';
-import {TrackButton, TrackButtonAttrs} from '../../frontend/track_panel';
 import {trackRegistry} from '../../frontend/track_registry';
 
 import {
@@ -32,8 +27,8 @@
 } from './common';
 
 // 0.5 Makes the horizontal lines sharp.
-const MARGIN_TOP = 3.5;
-const RECT_HEIGHT = 24.5;
+const MARGIN_TOP = 4.5;
+const RECT_HEIGHT = 30;
 
 class CounterTrack extends Track<Config, Data> {
   static readonly kind = COUNTER_TRACK_KIND;
@@ -50,44 +45,29 @@
     super(trackState);
   }
 
-  getHeight() {
-    return MARGIN_TOP + RECT_HEIGHT;
-  }
-
-  getTrackShellButtons(): Array<m.Vnode<TrackButtonAttrs>> {
-    const buttons: Array<m.Vnode<TrackButtonAttrs>> = [];
-    buttons.push(m(TrackButton, {
-      action: () => {
-        if (this.config.scale === 'RELATIVE') {
-          this.config.scale = 'DEFAULT';
-        } else {
-          this.config.scale = 'RELATIVE';
-        }
-        Actions.updateTrackConfig(
-            {id: this.trackState.id, config: this.config});
-        globals.rafScheduler.scheduleFullRedraw();
-      },
-      i: 'show_chart',
-      tooltip: (this.config.scale === 'RELATIVE') ? 'Use zero-based scale' :
-                                                    'Use relative scale',
-      selected: this.config.scale === 'RELATIVE',
-    }));
-    return buttons;
-  }
-
   renderCanvas(ctx: CanvasRenderingContext2D): void {
     // TODO: fonts and colors should come from the CSS and not hardcoded here.
     const {timeScale, visibleWindowTime} = globals.frontendLocalState;
     const data = this.data();
 
+    // If there aren't enough cached slices data in |data| request more to
+    // the controller.
+    const inRange = data !== undefined &&
+        (visibleWindowTime.start >= data.start &&
+         visibleWindowTime.end <= data.end);
+    if (!inRange || data === undefined ||
+        data.resolution !== globals.getCurResolution()) {
+      globals.requestTrackData(this.trackState.id);
+    }
     if (data === undefined) return;  // Can't possibly draw anything.
 
     assertTrue(data.timestamps.length === data.values.length);
 
+    const startPx = Math.floor(timeScale.timeToPx(visibleWindowTime.start));
     const endPx = Math.floor(timeScale.timeToPx(visibleWindowTime.end));
     const zeroY = MARGIN_TOP + RECT_HEIGHT / (data.minimumValue < 0 ? 2 : 1);
 
-    let lastX = Math.floor(timeScale.timeToPx(data.timestamps[0]));
+    let lastX = startPx;
     let lastY = zeroY;
 
     // Quantize the Y axis to quarters of powers of tens (7.5K, 10K, 12.5K).
@@ -98,20 +78,9 @@
     const exp = Math.ceil(Math.log10(Math.max(yMax, 1)));
     const pow10 = Math.pow(10, exp);
     yMax = Math.ceil(yMax / (pow10 / 4)) * (pow10 / 4);
-    let yRange = 0;
+    const yRange = data.minimumValue < 0 ? yMax * 2 : yMax;
     const unitGroup = Math.floor(exp / 3);
-    let yMin = 0;
-    let yLabel = '';
-    if (this.config.scale === 'RELATIVE') {
-      yRange = data.maximumValue - data.minimumValue;
-      yMin = data.minimumValue;
-      yLabel = 'min - max';
-    } else {
-      yRange = data.minimumValue < 0 ? yMax * 2 : yMax;
-      yMin = data.minimumValue < 0 ? -yMax : 0;
-      yLabel = `${yMax / Math.pow(10, unitGroup * 3)} ${kUnits[unitGroup]}`;
-    }
-
+    const yLabel = `${yMax / Math.pow(10, unitGroup * 3)} ${kUnits[unitGroup]}`;
     // There are 360deg of hue. We want a scale that starts at green with
     // exp <= 3 (<= 1KB), goes orange around exp = 6 (~1MB) and red/violet
     // around exp >= 9 (1GB).
@@ -130,7 +99,7 @@
     for (let i = 0; i < data.values.length; i++) {
       const value = data.values[i];
       const startTime = data.timestamps[i];
-      const nextY = zeroY - Math.round(((value - yMin) / yRange) * RECT_HEIGHT);
+      const nextY = zeroY - Math.round((value / yRange) * RECT_HEIGHT);
       if (nextY === lastY) continue;
 
       lastX = Math.floor(timeScale.timeToPx(startTime));
@@ -145,7 +114,7 @@
     ctx.stroke();
 
     // Draw the Y=0 dashed line.
-    ctx.strokeStyle = `hsl(${hue}, 10%, 71%)`;
+    ctx.strokeStyle = `hsl(${hue}, 10%, 15%)`;
     ctx.beginPath();
     ctx.setLineDash([2, 4]);
     ctx.moveTo(0, zeroY);
@@ -169,8 +138,7 @@
       const xEnd = this.hoveredTsEnd === undefined ?
           endPx :
           Math.floor(timeScale.timeToPx(this.hoveredTsEnd));
-      const y = zeroY -
-          Math.round(((this.hoveredValue - yMin) / yRange) * RECT_HEIGHT);
+      const y = zeroY - Math.round((this.hoveredValue / yRange) * RECT_HEIGHT);
 
       // Highlight line.
       ctx.beginPath();
@@ -197,7 +165,7 @@
 
     // Write the Y scale on the top left corner.
     ctx.fillStyle = 'rgba(255, 255, 255, 0.6)';
-    ctx.fillRect(0, 0, 42, 16);
+    ctx.fillRect(0, 0, 40, 16);
     ctx.fillStyle = '#666';
     ctx.textAlign = 'left';
     ctx.textBaseline = 'alphabetic';
@@ -207,7 +175,6 @@
     // show a gray rectangle with a "Loading..." label.
     checkerboardExcept(
         ctx,
-        this.getHeight(),
         timeScale.timeToPx(visibleWindowTime.start),
         timeScale.timeToPx(visibleWindowTime.end),
         timeScale.timeToPx(data.start),
@@ -225,32 +192,18 @@
     this.hoveredTs = left === -1 ? undefined : data.timestamps[left];
     this.hoveredTsEnd = right === -1 ? undefined : data.timestamps[right];
     this.hoveredValue = left === -1 ? undefined : data.values[left];
+
+    // for (let i = 0; i < data.values.length; i++) {
+    //  if (data.timestamps[i] > time) break;
+    //  this.hoveredTs = data.timestamps[i];
+    //  this.hoveredValue = data.values[i];
+    //}
   }
 
   onMouseOut() {
     this.hoveredValue = undefined;
     this.hoveredTs = undefined;
   }
-
-  onMouseClick({x}: {x: number}) {
-    const data = this.data();
-    if (data === undefined) return false;
-    const {timeScale} = globals.frontendLocalState;
-    const time = timeScale.pxToTime(x);
-    const [left, right] = searchSegment(data.timestamps, time);
-    if (left === -1) {
-      return false;
-    } else {
-      const counterId = data.ids[left];
-      globals.makeSelection(Actions.selectCounter({
-        leftTs: toNs(data.timestamps[left]),
-        rightTs: right !== -1 ? toNs(data.timestamps[right]) : -1,
-        id: counterId,
-        trackId: this.trackState.id
-      }));
-      return true;
-    }
-  }
 }
 
 trackRegistry.register(CounterTrack);
diff --git a/ui/src/tracks/cpu_freq/common.ts b/ui/src/tracks/cpu_freq/common.ts
index 8968907..02b7280 100644
--- a/ui/src/tracks/cpu_freq/common.ts
+++ b/ui/src/tracks/cpu_freq/common.ts
@@ -1,4 +1,3 @@
-
 // Copyright (C) 2019 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,11 +11,13 @@
 // 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.
-import {TrackData} from '../../common/track_data';
 
 export const CPU_FREQ_TRACK_KIND = 'CpuFreqTrack';
 
-export interface Data extends TrackData {
+export interface Data {
+  start: number;
+  end: number;
+  resolution: number;
   maximumValue: number;
   isQuantized: boolean;
 
diff --git a/ui/src/tracks/cpu_freq/controller.ts b/ui/src/tracks/cpu_freq/controller.ts
index 190a3d9..391d44d 100644
--- a/ui/src/tracks/cpu_freq/controller.ts
+++ b/ui/src/tracks/cpu_freq/controller.ts
@@ -12,9 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {fromNs, toNs} from '../../common/time';
-import {LIMIT} from '../../common/track_data';
-
+import {fromNs} from '../../common/time';
 import {
   TrackController,
   trackControllerRegistry
@@ -28,14 +26,23 @@
 
 class CpuFreqTrackController extends TrackController<Config, Data> {
   static readonly kind = CPU_FREQ_TRACK_KIND;
+  private busy = false;
   private setup = false;
   private maximumValueSeen = 0;
 
-  async onBoundsChange(start: number, end: number, resolution: number):
-      Promise<Data> {
-    const startNs = toNs(start);
-    const endNs = toNs(end);
+  onBoundsChange(start: number, end: number, resolution: number): void {
+    this.update(start, end, resolution);
+  }
 
+  private async update(start: number, end: number, resolution: number):
+      Promise<void> {
+    // TODO: we should really call TraceProcessor.Interrupt() at this point.
+    if (this.busy) return;
+
+    const startNs = Math.round(start * 1e9);
+    const endNs = Math.round(end * 1e9);
+
+    this.busy = true;
     if (!this.setup) {
       const result = await this.query(`
       select max(value) from
@@ -98,31 +105,26 @@
       this.setup = true;
     }
 
-    this.query(`update ${this.tableName('window')} set
-    window_start = ${startNs},
-    window_dur = ${Math.max(1, endNs - startNs)},
-    quantum = 0`);
-
-    const result = await this.engine.queryOneRow(`select count(*)
-      from ${this.tableName('activity')}`);
-    const isQuantized = result[0] > LIMIT;
-
-    // Cast as double to avoid problem where values are sometimes
-    // doubles, sometimes longs.
-    let query = `select ts, dur, cast(idle as DOUBLE), freq
-      from ${this.tableName('activity')} limit ${LIMIT}`;
-
+    const isQuantized = this.shouldSummarize(resolution);
+    // |resolution| is in s/px we want # ns for 10px window:
+    const bucketSizeNs = Math.round(resolution * 10 * 1e9);
+    let windowStartNs = startNs;
     if (isQuantized) {
-      // |resolution| is in s/px we want # ns for 10px window:
-      const bucketSizeNs = Math.round(resolution * 10 * 1e9);
-      const windowStartNs = Math.floor(startNs / bucketSizeNs) * bucketSizeNs;
-      const windowDurNs = Math.max(1, endNs - windowStartNs);
+      windowStartNs = Math.floor(windowStartNs / bucketSizeNs) * bucketSizeNs;
+    }
+    const windowDurNs = Math.max(1, endNs - windowStartNs);
 
-      this.query(`update ${this.tableName('window')} set
+    this.query(`update ${this.tableName('window')} set
       window_start = ${startNs},
       window_dur = ${windowDurNs},
       quantum = ${isQuantized ? bucketSizeNs : 0}`);
 
+    // Cast as double to avoid problem where values are sometimes
+    // doubles, sometimes longs.
+    let query = `select ts, dur, cast(idle as DOUBLE), freq
+      from ${this.tableName('activity')}`;
+
+    if (isQuantized) {
       query = `select
         min(ts) as ts,
         sum(dur) as dur,
@@ -140,7 +142,7 @@
           freq*dur as weighted_freq,
           idle
           from ${this.tableName('activity')})
-        group by quantum_ts limit ${LIMIT}`;
+        group by quantum_ts`;
     }
 
     const freqResult = await this.query(query);
@@ -149,9 +151,8 @@
     const data: Data = {
       start,
       end,
-      resolution,
-      length: numRows,
       maximumValue: this.maximumValue(),
+      resolution,
       isQuantized,
       tsStarts: new Float64Array(numRows),
       tsEnds: new Float64Array(numRows),
@@ -168,13 +169,22 @@
       data.freqKHz[row] = +cols[3].doubleValues![row];
     }
 
-    return data;
+    this.publish(data);
+    this.busy = false;
   }
 
   private maximumValue() {
     return Math.max(this.config.maximumValue || 0, this.maximumValueSeen);
   }
 
+  private async query(query: string) {
+    const result = await this.engine.query(query);
+    if (result.error) {
+      console.error(`Query error "${query}": ${result.error}`);
+      throw new Error(`Query error "${query}": ${result.error}`);
+    }
+    return result;
+  }
 }
 
 
diff --git a/ui/src/tracks/cpu_freq/frontend.ts b/ui/src/tracks/cpu_freq/frontend.ts
index 0bf9199..02a1d55 100644
--- a/ui/src/tracks/cpu_freq/frontend.ts
+++ b/ui/src/tracks/cpu_freq/frontend.ts
@@ -29,7 +29,7 @@
 
 // 0.5 Makes the horizontal lines sharp.
 const MARGIN_TOP = 4.5;
-const RECT_HEIGHT = 20;
+const RECT_HEIGHT = 30;
 
 class CpuFreqTrack extends Track<Config, Data> {
   static readonly kind = CPU_FREQ_TRACK_KIND;
@@ -47,15 +47,20 @@
     super(trackState);
   }
 
-  getHeight() {
-    return MARGIN_TOP + RECT_HEIGHT;
-  }
-
   renderCanvas(ctx: CanvasRenderingContext2D): void {
     // TODO: fonts and colors should come from the CSS and not hardcoded here.
     const {timeScale, visibleWindowTime} = globals.frontendLocalState;
     const data = this.data();
 
+    // If there aren't enough cached slices data in |data| request more to
+    // the controller.
+    const inRange = data !== undefined &&
+        (visibleWindowTime.start >= data.start &&
+         visibleWindowTime.end <= data.end);
+    if (!inRange || data === undefined ||
+        data.resolution !== globals.getCurResolution()) {
+      globals.requestTrackData(this.trackState.id);
+    }
     if (data === undefined) return;  // Can't possibly draw anything.
 
     assertTrue(data.tsStarts.length === data.freqKHz.length);
@@ -129,11 +134,12 @@
     ctx.font = '10px Google Sans';
 
     if (this.hoveredValue !== undefined && this.hoveredTs !== undefined) {
-      let text = `${this.hoveredValue.toLocaleString()}kHz`;
+      let text = `Freq: ${this.hoveredValue.toLocaleString()}kHz`;
       if (data.isQuantized) {
-        text = `${this.hoveredValue.toLocaleString()}kHz (weighted avg)`;
+        text = `Weighted avg freq: ${this.hoveredValue.toLocaleString()}kHz`;
       }
 
+      const width = ctx.measureText(text).width;
       ctx.fillStyle = `hsl(${hue}, 45%, 75%)`;
       ctx.strokeStyle = `hsl(${hue}, 45%, 45%)`;
 
@@ -157,34 +163,31 @@
       ctx.fill();
       ctx.stroke();
 
+      // Draw the tooltip.
+      ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
+      ctx.fillRect(this.mouseXpos + 5, MARGIN_TOP, width + 16, RECT_HEIGHT);
+      ctx.fillStyle = 'hsl(200, 50%, 40%)';
+      const centerY = MARGIN_TOP + RECT_HEIGHT / 2;
+      ctx.fillText(text, this.mouseXpos + 10, centerY - 3);
       // Display idle value if current hover is idle.
       if (this.hoveredIdle !== undefined && this.hoveredIdle !== -1) {
         // Display the idle value +1 to be consistent with catapult.
-        text += ` (Idle: ${(this.hoveredIdle + 1).toLocaleString()})`;
+        const idle = `Idle: ${(this.hoveredIdle + 1).toLocaleString()}`;
+        ctx.fillText(idle, this.mouseXpos + 10, centerY + 11);
       }
-      const width = ctx.measureText(text).width;
-
-      // Draw the tooltip.
-      ctx.textBaseline = 'middle';
-      ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
-      ctx.fillRect(this.mouseXpos, MARGIN_TOP, width + 16, RECT_HEIGHT);
-      ctx.fillStyle = 'hsl(200, 50%, 40%)';
-      ctx.fillText(text, this.mouseXpos + 8, MARGIN_TOP + RECT_HEIGHT / 2);
     }
 
     // Write the Y scale on the top left corner.
-    ctx.textBaseline = 'alphabetic';
     ctx.fillStyle = 'rgba(255, 255, 255, 0.6)';
-    ctx.fillRect(0, 0, 42, 18);
+    ctx.fillRect(0, 0, 40, 16);
     ctx.fillStyle = '#666';
     ctx.textAlign = 'left';
-    ctx.fillText(`${yLabel}`, 4, 14);
+    ctx.fillText(`${yLabel}`, 5, 14);
 
     // If the cached trace slices don't fully cover the visible time range,
     // show a gray rectangle with a "Loading..." label.
     checkerboardExcept(
         ctx,
-        this.getHeight(),
         timeScale.timeToPx(visibleWindowTime.start),
         timeScale.timeToPx(visibleWindowTime.end),
         timeScale.timeToPx(data.start),
diff --git a/ui/src/tracks/cpu_slices/common.ts b/ui/src/tracks/cpu_slices/common.ts
index 8bc0a09..8d1fae3 100644
--- a/ui/src/tracks/cpu_slices/common.ts
+++ b/ui/src/tracks/cpu_slices/common.ts
@@ -12,20 +12,26 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {TrackData} from '../../common/track_data';
-
 export const CPU_SLICE_TRACK_KIND = 'CpuSliceTrack';
 
-export interface SummaryData extends TrackData {
+export interface SummaryData {
   kind: 'summary';
 
+  start: number;
+  end: number;
+  resolution: number;
+
   bucketSizeSeconds: number;
   utilizations: Float64Array;
 }
 
-export interface SliceData extends TrackData {
+export interface SliceData {
   kind: 'slice';
 
+  start: number;
+  end: number;
+  resolution: number;
+
   // Slices are stored in a columnar fashion. All fields have the same length.
   ids: Float64Array;
   starts: Float64Array;
diff --git a/ui/src/tracks/cpu_slices/controller.ts b/ui/src/tracks/cpu_slices/controller.ts
index 278450e..5917968 100644
--- a/ui/src/tracks/cpu_slices/controller.ts
+++ b/ui/src/tracks/cpu_slices/controller.ts
@@ -12,9 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {fromNs, toNs} from '../../common/time';
-import {LIMIT} from '../../common/track_data';
-
+import {fromNs} from '../../common/time';
 import {
   TrackController,
   trackControllerRegistry
@@ -30,13 +28,22 @@
 
 class CpuSliceTrackController extends TrackController<Config, Data> {
   static readonly kind = CPU_SLICE_TRACK_KIND;
+  private busy = false;
   private setup = false;
 
-  async onBoundsChange(start: number, end: number, resolution: number):
-      Promise<Data> {
-    const startNs = toNs(start);
-    const endNs = toNs(end);
+  onBoundsChange(start: number, end: number, resolution: number): void {
+    this.update(start, end, resolution);
+  }
 
+  private async update(start: number, end: number, resolution: number):
+      Promise<void> {
+    // TODO: we should really call TraceProcessor.Interrupt() at this point.
+    if (this.busy) return;
+
+    const startNs = Math.round(start * 1e9);
+    const endNs = Math.round(end * 1e9);
+
+    this.busy = true;
     if (this.setup === false) {
       await this.query(
           `create virtual table ${this.tableName('window')} using window;`);
@@ -62,18 +69,20 @@
       where rowid = 0;`);
 
     if (isQuantized) {
-      return this.computeSummary(
-          fromNs(windowStartNs), end, resolution, bucketSizeNs);
+      this.publish(await this.computeSummary(
+          fromNs(windowStartNs), end, resolution, bucketSizeNs));
     } else {
-      return this.computeSlices(fromNs(windowStartNs), end, resolution);
+      this.publish(
+          await this.computeSlices(fromNs(windowStartNs), end, resolution));
     }
+    this.busy = false;
   }
 
   private async computeSummary(
       start: number, end: number, resolution: number,
       bucketSizeNs: number): Promise<SummaryData> {
-    const startNs = toNs(start);
-    const endNs = toNs(end);
+    const startNs = Math.round(start * 1e9);
+    const endNs = Math.round(end * 1e9);
     const numBuckets = Math.ceil((endNs - startNs) / bucketSizeNs);
 
     const query = `select
@@ -82,7 +91,7 @@
         from ${this.tableName('span')}
         where cpu = ${this.config.cpu}
         and utid != 0
-        group by quantum_ts limit ${LIMIT}`;
+        group by quantum_ts`;
 
     const rawResult = await this.query(query);
     const numRows = +rawResult.numRecords;
@@ -92,7 +101,6 @@
       start,
       end,
       resolution,
-      length: numRows,
       bucketSizeSeconds: fromNs(bucketSizeNs),
       utilizations: new Float64Array(numBuckets),
     };
@@ -121,7 +129,6 @@
       start,
       end,
       resolution,
-      length: numRows,
       ids: new Float64Array(numRows),
       starts: new Float64Array(numRows),
       ends: new Float64Array(numRows),
@@ -142,6 +149,14 @@
     return slices;
   }
 
+  private async query(query: string) {
+    const result = await this.engine.query(query);
+    if (result.error) {
+      console.error(`Query error "${query}": ${result.error}`);
+      throw new Error(`Query error "${query}": ${result.error}`);
+    }
+    return result;
+  }
 
   onDestroy(): void {
     if (this.setup) {
diff --git a/ui/src/tracks/cpu_slices/frontend.ts b/ui/src/tracks/cpu_slices/frontend.ts
index b77098d..aceba82 100644
--- a/ui/src/tracks/cpu_slices/frontend.ts
+++ b/ui/src/tracks/cpu_slices/frontend.ts
@@ -32,10 +32,9 @@
   SummaryData
 } from './common';
 
-const MARGIN_TOP = 3;
-const RECT_HEIGHT = 24;
-const TRACK_HEIGHT = MARGIN_TOP * 2 + RECT_HEIGHT;
-const SUMMARY_HEIGHT = TRACK_HEIGHT - MARGIN_TOP;
+
+const MARGIN_TOP = 5;
+const RECT_HEIGHT = 30;
 
 class CpuSliceTrack extends Track<Config, Data> {
   static readonly kind = CPU_SLICE_TRACK_KIND;
@@ -52,22 +51,26 @@
     this.hue = hueForCpu(this.config.cpu);
   }
 
-  getHeight(): number {
-    return TRACK_HEIGHT;
-  }
-
   renderCanvas(ctx: CanvasRenderingContext2D): void {
     // TODO: fonts and colors should come from the CSS and not hardcoded here.
     const {timeScale, visibleWindowTime} = globals.frontendLocalState;
     const data = this.data();
 
+    // If there aren't enough cached slices data in |data| request more to
+    // the controller.
+    const inRange = data !== undefined &&
+        (visibleWindowTime.start >= data.start &&
+         visibleWindowTime.end <= data.end);
+    if (!inRange || data === undefined ||
+        data.resolution !== globals.getCurResolution()) {
+      globals.requestTrackData(this.trackState.id);
+    }
     if (data === undefined) return;  // Can't possibly draw anything.
 
     // If the cached trace slices don't fully cover the visible time range,
     // show a gray rectangle with a "Loading..." label.
     checkerboardExcept(
         ctx,
-        this.getHeight(),
         timeScale.timeToPx(visibleWindowTime.start),
         timeScale.timeToPx(visibleWindowTime.end),
         timeScale.timeToPx(data.start),
@@ -83,7 +86,7 @@
   renderSummary(ctx: CanvasRenderingContext2D, data: SummaryData): void {
     const {timeScale, visibleWindowTime} = globals.frontendLocalState;
     const startPx = Math.floor(timeScale.timeToPx(visibleWindowTime.start));
-    const bottomY = TRACK_HEIGHT;
+    const bottomY = MARGIN_TOP + RECT_HEIGHT;
 
     let lastX = startPx;
     let lastY = bottomY;
@@ -98,7 +101,7 @@
       lastX = Math.floor(timeScale.timeToPx(startTime));
 
       ctx.lineTo(lastX, lastY);
-      lastY = MARGIN_TOP + Math.round(SUMMARY_HEIGHT * (1 - utilization));
+      lastY = MARGIN_TOP + Math.round(RECT_HEIGHT * (1 - utilization));
       ctx.lineTo(lastX, lastY);
     }
     ctx.lineTo(lastX, bottomY);
@@ -172,10 +175,10 @@
       const rectXCenter = rectStart + rectWidth / 2;
       ctx.fillStyle = '#fff';
       ctx.font = '12px Google Sans';
-      ctx.fillText(title, rectXCenter, MARGIN_TOP + RECT_HEIGHT / 2 - 1);
+      ctx.fillText(title, rectXCenter, MARGIN_TOP + RECT_HEIGHT / 2 - 3);
       ctx.fillStyle = 'rgba(255, 255, 255, 0.6)';
       ctx.font = '10px Google Sans';
-      ctx.fillText(subTitle, rectXCenter, MARGIN_TOP + RECT_HEIGHT / 2 + 9);
+      ctx.fillText(subTitle, rectXCenter, MARGIN_TOP + RECT_HEIGHT / 2 + 11);
     }
 
     const selection = globals.state.currentSelection;
@@ -228,7 +231,7 @@
 
       // Draw diamond if the track being drawn is the cpu of the waker.
       if (this.config.cpu === details.wakerCpu && details.wakeupTs) {
-        const wakeupPos = Math.floor(timeScale.timeToPx(details.wakeupTs));
+        const wakeupPos = timeScale.timeToPx(details.wakeupTs);
         ctx.beginPath();
         ctx.moveTo(wakeupPos, MARGIN_TOP + RECT_HEIGHT / 2 + 8);
         ctx.fillStyle = 'black';
@@ -260,10 +263,8 @@
       ctx.fillRect(this.mouseXpos!, MARGIN_TOP, width + 16, RECT_HEIGHT);
       ctx.fillStyle = 'hsl(200, 50%, 40%)';
       ctx.textAlign = 'left';
-      ctx.fillText(
-          line1, this.mouseXpos! + 8, MARGIN_TOP + RECT_HEIGHT / 2 - 2);
-      ctx.fillText(
-          line2, this.mouseXpos! + 8, MARGIN_TOP + RECT_HEIGHT / 2 + 10);
+      ctx.fillText(line1, this.mouseXpos! + 8, 18);
+      ctx.fillText(line2, this.mouseXpos! + 8, 28);
     }
   }
 
@@ -308,10 +309,12 @@
     const time = timeScale.pxToTime(x);
     const index = search(data.starts, time);
     const id = index === -1 ? undefined : data.ids[index];
-    if (!id || this.utidHoveredInThisTrack === -1) return false;
-    globals.makeSelection(
-        Actions.selectSlice({id, trackId: this.trackState.id}));
-    return true;
+    if (id && this.utidHoveredInThisTrack !== -1) {
+      globals.dispatch(Actions.selectSlice(
+        {utid: this.utidHoveredInThisTrack, id}));
+      return true;
+    }
+    return false;
   }
 }
 
diff --git a/ui/src/tracks/gpu_freq/common.ts b/ui/src/tracks/gpu_freq/common.ts
deleted file mode 100644
index dd8665d..0000000
--- a/ui/src/tracks/gpu_freq/common.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-
-// Copyright (C) 2019 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.
-import {TrackData} from '../../common/track_data';
-
-export const GPU_FREQ_TRACK_KIND = 'GpuFreqTrack';
-
-export interface Data extends TrackData {
-  maximumValue: number;
-  isQuantized: boolean;
-
-  tsStarts: Float64Array;
-  tsEnds: Float64Array;
-  freqKHz: Uint32Array;
-}
-
-export interface Config {
-  gpu: number;
-  maximumValue?: number;
-  minimumValue?: number;}
diff --git a/ui/src/tracks/gpu_freq/controller.ts b/ui/src/tracks/gpu_freq/controller.ts
deleted file mode 100644
index 6fa2e39..0000000
--- a/ui/src/tracks/gpu_freq/controller.ts
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {fromNs, toNs} from '../../common/time';
-import {LIMIT} from '../../common/track_data';
-import {
-  TrackController,
-  trackControllerRegistry
-} from '../../controller/track_controller';
-
-import {
-  Config,
-  Data,
-  GPU_FREQ_TRACK_KIND,
-} from './common';
-
-class GpuFreqTrackController extends TrackController<Config, Data> {
-  static readonly kind = GPU_FREQ_TRACK_KIND;
-  private setup = false;
-  private maximumValueSeen = 0;
-
-  async onBoundsChange(start: number, end: number, resolution: number):
-      Promise<Data> {
-    const startNs = toNs(start);
-    const endNs = toNs(end);
-
-    if (!this.setup) {
-      const result = await this.query(`
-      select max(value) from
-        counters where name = 'gpufreq'
-        and ref = ${this.config.gpu}`);
-      this.maximumValueSeen = +result.columns[0].doubleValues![0];
-
-      await this.query(
-        `create virtual table ${this.tableName('window')} using window;`);
-
-      await this.query(`create view ${this.tableName('freq')}
-          as select
-            ts,
-            lead(ts) over (order by ts) - ts as dur,
-            ref as gpu,
-            name as freq_name,
-            value as freq_value
-          from counters
-          where name = 'gpufreq'
-            and ref = ${this.config.gpu}
-            and ref_type = 'gpu';
-      `);
-
-      await this.query(`create virtual table ${this.tableName('span_activity')}
-      using span_join(${this.tableName('freq')} PARTITIONED gpu,
-                      ${this.tableName('window')});`);
-
-      await this.query(`create view ${this.tableName('activity')}
-      as select
-        ts,
-        dur,
-        quantum_ts,
-        freq_value as freq
-        from ${this.tableName('span_activity')};
-      `);
-
-      this.setup = true;
-    }
-
-    this.query(`update ${this.tableName('window')} set
-    window_start = ${startNs},
-    window_dur = ${Math.max(1, endNs - startNs)},
-    quantum = 0`);
-
-    const result = await this.engine.queryOneRow(`select count(*)
-      from ${this.tableName('activity')}`);
-    const isQuantized = result[0] > LIMIT;
-
-    // Cast as double to avoid problem where values are sometimes
-    // doubles, sometimes longs.
-    let query = `select ts, dur, freq
-      from ${this.tableName('activity')} limit ${LIMIT}`;
-
-    if (isQuantized) {
-      // |resolution| is in s/px we want # ns for 10px window:
-      const bucketSizeNs = Math.round(resolution * 10 * 1e9);
-      const windowStartNs = Math.floor(startNs / bucketSizeNs) * bucketSizeNs;
-      const windowDurNs = Math.max(1, endNs - windowStartNs);
-
-      this.query(`update ${this.tableName('window')} set
-      window_start = ${startNs},
-      window_dur = ${windowDurNs},
-      quantum = ${isQuantized ? bucketSizeNs : 0}`);
-
-      query = `select
-        min(ts) as ts,
-        sum(dur) as dur,
-        sum(weighted_freq)/sum(dur) as freq_avg,
-        quantum_ts
-        from (
-          select
-          ts,
-          dur,
-          quantum_ts,
-          freq*dur as weighted_freq
-          from ${this.tableName('activity')})
-        group by quantum_ts limit ${LIMIT}`;
-    }
-
-    const freqResult = await this.query(query);
-
-    const numRows = +freqResult.numRecords;
-    const data: Data = {
-      start,
-      end,
-      resolution,
-      length: numRows,
-      maximumValue: this.maximumValue(),
-      isQuantized,
-      tsStarts: new Float64Array(numRows),
-      tsEnds: new Float64Array(numRows),
-      freqKHz: new Uint32Array(numRows),
-    };
-
-    const cols = freqResult.columns;
-    for (let row = 0; row < numRows; row++) {
-      const startSec = fromNs(+cols[0].longValues![row]);
-      data.tsStarts[row] = startSec;
-      data.tsEnds[row] = startSec + fromNs(+cols[1].longValues![row]);
-      data.freqKHz[row] = +cols[2].doubleValues![row];
-    }
-
-    return data;
-  }
-
-  private maximumValue() {
-    return Math.max(this.config.maximumValue || 0, this.maximumValueSeen);
-  }
-
-}
-
-
-trackControllerRegistry.register(GpuFreqTrackController);
diff --git a/ui/src/tracks/gpu_freq/frontend.ts b/ui/src/tracks/gpu_freq/frontend.ts
deleted file mode 100644
index 53b79c7..0000000
--- a/ui/src/tracks/gpu_freq/frontend.ts
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {search} from '../../base/binary_search';
-import {assertTrue} from '../../base/logging';
-import {TrackState} from '../../common/state';
-import {checkerboardExcept} from '../../frontend/checkerboard';
-import {hueForCpu} from '../../frontend/colorizer';
-import {globals} from '../../frontend/globals';
-import {Track} from '../../frontend/track';
-import {trackRegistry} from '../../frontend/track_registry';
-
-import {
-  Config,
-  GPU_FREQ_TRACK_KIND,
-  Data,
-} from './common';
-
-// 0.5 Makes the horizontal lines sharp.
-const MARGIN_TOP = 4.5;
-const RECT_HEIGHT = 30;
-
-class GpuFreqTrack extends Track<Config, Data> {
-  static readonly kind = GPU_FREQ_TRACK_KIND;
-  static create(trackState: TrackState): GpuFreqTrack {
-    return new GpuFreqTrack(trackState);
-  }
-
-  private mouseXpos = 0;
-  private hoveredValue: number|undefined = undefined;
-  private hoveredTs: number|undefined = undefined;
-  private hoveredTsEnd: number|undefined = undefined;
-
-  constructor(trackState: TrackState) {
-    super(trackState);
-  }
-
-  renderCanvas(ctx: CanvasRenderingContext2D): void {
-    // TODO: fonts and colors should come from the CSS and not hardcoded here.
-    const {timeScale, visibleWindowTime} = globals.frontendLocalState;
-    const data = this.data();
-
-    if (data === undefined) return;  // Can't possibly draw anything.
-
-    assertTrue(data.tsStarts.length === data.freqKHz.length);
-
-    const startPx = Math.floor(timeScale.timeToPx(visibleWindowTime.start));
-    const endPx = Math.floor(timeScale.timeToPx(visibleWindowTime.end));
-    const zeroY = MARGIN_TOP + RECT_HEIGHT;
-
-    let lastX = startPx;
-    let lastY = zeroY;
-
-    // Quantize the Y axis to quarters of powers of tens (7.5K, 10K, 12.5K).
-    let yMax = data.maximumValue;
-    const kUnits = ['', 'K', 'M', 'G', 'T', 'E'];
-    const exp = Math.ceil(Math.log10(Math.max(yMax, 1)));
-    const pow10 = Math.pow(10, exp);
-    yMax = Math.ceil(yMax / (pow10 / 4)) * (pow10 / 4);
-    const unitGroup = Math.floor(exp / 3);
-    const num = yMax / Math.pow(10, unitGroup * 3);
-    // The values we have for gpufreq are in kHz so +1 to unitGroup.
-    const yLabel = `${num} ${kUnits[unitGroup + 1]}Hz`;
-
-    // Draw the GPU frequency graph.
-    const hue = hueForCpu(this.config.gpu);
-    let saturation = 70;
-    if (globals.frontendLocalState.hoveredUtid !== -1) {
-      saturation = 0;
-    }
-    ctx.fillStyle = `hsl(${hue}, ${saturation}%, 70%)`;
-    ctx.strokeStyle = `hsl(${hue}, ${saturation}%, 55%)`;
-    ctx.beginPath();
-    ctx.moveTo(lastX, lastY);
-
-    for (let i = 0; i < data.freqKHz.length; i++) {
-      const value = data.freqKHz[i];
-      const startTime = data.tsStarts[i];
-      const nextY = zeroY - Math.round((value / yMax) * RECT_HEIGHT);
-      if (nextY === lastY) continue;
-
-      lastX = Math.floor(timeScale.timeToPx(startTime));
-      ctx.lineTo(lastX, lastY);
-      ctx.lineTo(lastX, nextY);
-      lastY = nextY;
-    }
-    // Find the end time for the last frequency event and then draw
-    // down to zero to show that we do not have data after that point.
-    const endTime = data.tsEnds[data.freqKHz.length - 1];
-    const finalX = Math.floor(timeScale.timeToPx(endTime));
-    ctx.lineTo(finalX, lastY);
-    ctx.lineTo(finalX, zeroY);
-    ctx.lineTo(endPx, zeroY);
-    ctx.closePath();
-    ctx.fill();
-    ctx.stroke();
-
-    ctx.font = '10px Google Sans';
-
-    if (this.hoveredValue !== undefined && this.hoveredTs !== undefined) {
-      let text = `Freq: ${this.hoveredValue.toLocaleString()}kHz`;
-      if (data.isQuantized) {
-        text = `Weighted avg freq: ${this.hoveredValue.toLocaleString()}kHz`;
-      }
-
-      const width = ctx.measureText(text).width;
-      ctx.fillStyle = `hsl(${hue}, 45%, 75%)`;
-      ctx.strokeStyle = `hsl(${hue}, 45%, 45%)`;
-
-      const xStart = Math.floor(timeScale.timeToPx(this.hoveredTs));
-      const xEnd = this.hoveredTsEnd === undefined ?
-          endPx :
-          Math.floor(timeScale.timeToPx(this.hoveredTsEnd));
-      const y = zeroY - Math.round((this.hoveredValue / yMax) * RECT_HEIGHT);
-
-      // Highlight line.
-      ctx.beginPath();
-      ctx.moveTo(xStart, y);
-      ctx.lineTo(xEnd, y);
-      ctx.lineWidth = 3;
-      ctx.stroke();
-      ctx.lineWidth = 1;
-
-      // Draw change marker.
-      ctx.beginPath();
-      ctx.arc(xStart, y, 3 /*r*/, 0 /*start angle*/, 2 * Math.PI /*end angle*/);
-      ctx.fill();
-      ctx.stroke();
-
-      // Draw the tooltip.
-      ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
-      ctx.fillRect(this.mouseXpos + 5, MARGIN_TOP, width + 16, RECT_HEIGHT);
-      ctx.fillStyle = 'hsl(200, 50%, 40%)';
-      const centerY = MARGIN_TOP + RECT_HEIGHT / 2;
-      ctx.fillText(text, this.mouseXpos + 10, centerY - 3);
-    }
-
-    // Write the Y scale on the top left corner.
-    ctx.fillStyle = 'rgba(255, 255, 255, 0.6)';
-    ctx.fillRect(0, 0, 40, 16);
-    ctx.fillStyle = '#666';
-    ctx.textAlign = 'left';
-    ctx.fillText(`${yLabel}`, 5, 14);
-
-    // If the cached trace slices don't fully cover the visible time range,
-    // show a gray rectangle with a "Loading..." label.
-    checkerboardExcept(
-        ctx,
-        this.getHeight(),
-        timeScale.timeToPx(visibleWindowTime.start),
-        timeScale.timeToPx(visibleWindowTime.end),
-        timeScale.timeToPx(data.start),
-        timeScale.timeToPx(data.end));
-  }
-
-  onMouseMove({x}: {x: number, y: number}) {
-    const data = this.data();
-    if (data === undefined) return;
-    this.mouseXpos = x;
-    const {timeScale} = globals.frontendLocalState;
-    const time = timeScale.pxToTime(x);
-
-    const index = search(data.tsStarts, time);
-    this.hoveredTs = index === -1 ? undefined : data.tsStarts[index];
-    this.hoveredTsEnd = index === -1 ? undefined : data.tsEnds[index];
-    this.hoveredValue = index === -1 ? undefined : data.freqKHz[index];
-  }
-
-  onMouseOut() {
-    this.hoveredValue = undefined;
-    this.hoveredTs = undefined;
-    this.hoveredTsEnd = undefined;
-  }
-}
-
-trackRegistry.register(GpuFreqTrack);
diff --git a/ui/src/tracks/heap_profile/common.ts b/ui/src/tracks/heap_profile/common.ts
deleted file mode 100644
index fc9da62..0000000
--- a/ui/src/tracks/heap_profile/common.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (C) 2019 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.
-import {TrackData} from '../../common/track_data';
-
-export const HEAP_PROFILE_TRACK_KIND = 'HeapProfileTrack';
-
-export interface Data extends TrackData {
-  tsStarts: Float64Array;
-}
-
-export interface Config {
-  upid: number;
-}
diff --git a/ui/src/tracks/heap_profile/controller.ts b/ui/src/tracks/heap_profile/controller.ts
deleted file mode 100644
index 61ad335..0000000
--- a/ui/src/tracks/heap_profile/controller.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {
-  TrackController,
-  trackControllerRegistry
-} from '../../controller/track_controller';
-
-import {
-  Config,
-  Data,
-  HEAP_PROFILE_TRACK_KIND,
-} from './common';
-
-class HeapProfileTrackController extends TrackController<Config, Data> {
-  static readonly kind = HEAP_PROFILE_TRACK_KIND;
-  async onBoundsChange(start: number, end: number, resolution: number):
-      Promise<Data> {
-    if (this.config.upid === undefined) {
-      return {start, end, resolution, length: 0, tsStarts: new Float64Array()};
-    }
-    const result = await this.query(`
-    select distinct(ts) from heap_profile_allocation where upid = ${
-        this.config.upid}`);
-    const numRows = +result.numRecords;
-    const data: Data = {
-      start,
-      end,
-      resolution,
-      length: numRows,
-      tsStarts: new Float64Array(numRows),
-    };
-
-    for (let row = 0; row < numRows; row++) {
-      data.tsStarts[row] = +result.columns[0].longValues![row];
-    }
-
-    return data;
-  }
-}
-
-trackControllerRegistry.register(HeapProfileTrackController);
diff --git a/ui/src/tracks/heap_profile/frontend.ts b/ui/src/tracks/heap_profile/frontend.ts
deleted file mode 100644
index 8eaba5e..0000000
--- a/ui/src/tracks/heap_profile/frontend.ts
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {searchSegment} from '../../base/binary_search';
-import {Actions} from '../../common/actions';
-import {TrackState} from '../../common/state';
-import {fromNs, toNs} from '../../common/time';
-import {
-  HEAP_PROFILE_COLOR,
-  HEAP_PROFILE_HOVERED_COLOR
-} from '../../frontend/flamegraph';
-import {globals} from '../../frontend/globals';
-import {TimeScale} from '../../frontend/time_scale';
-import {Track} from '../../frontend/track';
-import {trackRegistry} from '../../frontend/track_registry';
-
-import {Config, Data, HEAP_PROFILE_TRACK_KIND} from './common';
-
-// 0.5 Makes the horizontal lines sharp.
-const MARGIN_TOP = 4.5;
-const RECT_HEIGHT = 30.5;
-
-class HeapProfileTrack extends Track<Config, Data> {
-  static readonly kind = HEAP_PROFILE_TRACK_KIND;
-  static create(trackState: TrackState): HeapProfileTrack {
-    return new HeapProfileTrack(trackState);
-  }
-
-  private centerY = this.getHeight() / 2;
-  private markerWidth = (this.getHeight() - MARGIN_TOP) / 2;
-  private hoveredTs: number|undefined = undefined;
-
-  constructor(trackState: TrackState) {
-    super(trackState);
-  }
-
-  getHeight() {
-    return MARGIN_TOP + RECT_HEIGHT - 1;
-  }
-
-  renderCanvas(ctx: CanvasRenderingContext2D): void {
-    const {
-      timeScale,
-    } = globals.frontendLocalState;
-    const data = this.data();
-
-    if (data === undefined) return;
-
-    for (let i = 0; i < data.tsStarts.length; i++) {
-      const centerX = data.tsStarts[i];
-      const selection = globals.state.currentSelection;
-      const isHovered = this.hoveredTs === centerX;
-      const isSelected = selection !== null &&
-          selection.kind === 'HEAP_PROFILE' && selection.ts === centerX;
-      const strokeWidth = isSelected ? 3 : 0;
-      this.drawMarker(
-          ctx,
-          timeScale.timeToPx(fromNs(centerX)),
-          this.centerY,
-          isHovered,
-          strokeWidth);
-    }
-  }
-
-  drawMarker(
-      ctx: CanvasRenderingContext2D, x: number, y: number, isHovered: boolean,
-      strokeWidth: number): void {
-    ctx.beginPath();
-    ctx.moveTo(x, y - this.markerWidth);
-    ctx.lineTo(x - this.markerWidth, y);
-    ctx.lineTo(x, y + this.markerWidth);
-    ctx.lineTo(x + this.markerWidth, y);
-    ctx.lineTo(x, y - this.markerWidth);
-    ctx.closePath();
-    ctx.fillStyle = isHovered ? HEAP_PROFILE_HOVERED_COLOR : HEAP_PROFILE_COLOR;
-    ctx.fill();
-    if (strokeWidth > 0) {
-      ctx.strokeStyle = HEAP_PROFILE_HOVERED_COLOR;
-      ctx.lineWidth = strokeWidth;
-      ctx.stroke();
-    }
-  }
-
-  onMouseMove({x, y}: {x: number, y: number}) {
-    const data = this.data();
-    if (data === undefined) return;
-    const {timeScale} = globals.frontendLocalState;
-    const time = toNs(timeScale.pxToTime(x));
-    const [left, right] = searchSegment(data.tsStarts, time);
-    const index = this.findTimestampIndex(left, timeScale, data, x, y, right);
-    this.hoveredTs = index === -1 ? undefined : data.tsStarts[index];
-  }
-
-  onMouseOut() {
-    this.hoveredTs = undefined;
-  }
-
-  onMouseClick({x, y}: {x: number, y: number}) {
-    const data = this.data();
-    if (data === undefined) return false;
-    const {timeScale} = globals.frontendLocalState;
-
-    const time = toNs(timeScale.pxToTime(x));
-    const [left, right] = searchSegment(data.tsStarts, time);
-
-    const index = this.findTimestampIndex(left, timeScale, data, x, y, right);
-
-    if (index !== -1) {
-      const ts = data.tsStarts[index];
-      globals.dispatch(Actions.showHeapProfileFlamegraph(
-          {id: index, upid: this.config.upid, ts}));
-      globals.makeSelection(
-          Actions.selectHeapProfile({id: index, upid: this.config.upid, ts}));
-      return true;
-    }
-    return false;
-  }
-
-  // If the markers overlap the rightmost one will be selected.
-  findTimestampIndex(
-      left: number, timeScale: TimeScale, data: Data, x: number, y: number,
-      right: number): number {
-    let index = -1;
-    if (left !== -1) {
-      const centerX = timeScale.timeToPx(fromNs(data.tsStarts[left]));
-      if (this.isInMarker(x, y, centerX)) {
-        index = left;
-      }
-    }
-    if (right !== -1) {
-      const centerX = timeScale.timeToPx(fromNs(data.tsStarts[right]));
-      if (this.isInMarker(x, y, centerX)) {
-        index = right;
-      }
-    }
-    return index;
-  }
-
-  isInMarker(x: number, y: number, centerX: number) {
-    return Math.abs(x - centerX) + Math.abs(y - this.centerY) <=
-        this.markerWidth;
-  }
-}
-
-trackRegistry.register(HeapProfileTrack);
diff --git a/ui/src/tracks/heap_profile_flamegraph/common.ts b/ui/src/tracks/heap_profile_flamegraph/common.ts
deleted file mode 100644
index 8e0a820..0000000
--- a/ui/src/tracks/heap_profile_flamegraph/common.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {TrackData} from '../../common/track_data';
-import {CallsiteInfo} from '../../frontend/globals';
-
-export const HEAP_PROFILE_FLAMEGRAPH_TRACK_KIND = 'HeapProfileFlamegraphTrack';
-export const HeapProfileFlamegraphKey = 'heap-profile-flamegraph';
-
-export interface Data extends TrackData {
-  flamegraph: CallsiteInfo[];
-}
-
-export interface Config {
-  upid: number;
-  isMinimized: boolean;
-}
diff --git a/ui/src/tracks/heap_profile_flamegraph/controller.ts b/ui/src/tracks/heap_profile_flamegraph/controller.ts
deleted file mode 100644
index 9677b66..0000000
--- a/ui/src/tracks/heap_profile_flamegraph/controller.ts
+++ /dev/null
@@ -1,192 +0,0 @@
-// Copyright (C) 2019 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.
-
-import {globals} from '../../controller/globals';
-import {
-  TrackController,
-  trackControllerRegistry
-} from '../../controller/track_controller';
-import {CallsiteInfo} from '../../frontend/globals';
-
-import {
-  Config,
-  Data,
-  HEAP_PROFILE_FLAMEGRAPH_TRACK_KIND,
-  HeapProfileFlamegraphKey,
-} from './common';
-
-class HeapProfileFlameraphTrackController extends
-    TrackController<Config, Data> {
-  static readonly kind = HEAP_PROFILE_FLAMEGRAPH_TRACK_KIND;
-  private start = 0;
-  private end = 0;
-  private resolution = 0;
-  private length = 0;
-  private lastSelectedTs?: number;
-  private lastSelectedId?: number;
-
-  async onBoundsChange(start: number, end: number, resolution: number):
-      Promise<Data> {
-    this.start = start;
-    this.end = end;
-    this.resolution = resolution;
-
-    return this.generateEmptyData();
-  }
-
-  private generateEmptyData() {
-    const data: Data = {
-      start: -1,
-      end: -1,
-      resolution: this.resolution,
-      length: 0,
-      flamegraph: new Array()
-    };
-    return data;
-  }
-
-  run() {
-    super.run();
-    const selection = globals.state.currentHeapProfileFlamegraph;
-    if (selection && selection.kind === 'HEAP_PROFILE_FLAMEGRAPH') {
-      if (this.lastSelectedId === selection.id &&
-          this.lastSelectedTs === selection.ts) {
-        return;
-      }
-      const selectedId = selection.id;
-      const selectedKind = selection.kind;
-      const selectedTs = selection.ts;
-      this.lastSelectedId = selection.id;
-      this.lastSelectedTs = selection.ts;
-
-      // Sending empty data to show tha Loading state before we get an actual
-      // data.
-      globals.publish(
-          'TrackData',
-          {id: HeapProfileFlamegraphKey, data: this.generateEmptyData()});
-
-      this.getFlamegraphData(selection.ts, selection.upid).then(flamegraph => {
-        if (flamegraph !== undefined && selection &&
-            selection.kind === selectedKind && selection.id === selectedId &&
-            selection.ts === selectedTs) {
-          globals.publish('TrackData', {
-            id: HeapProfileFlamegraphKey,
-            data: {
-              start: this.start,
-              end: this.end,
-              resolution: this.resolution,
-              length: this.length,
-              flamegraph
-            }
-          });
-        }
-      });
-    }
-  }
-
-  async getFlamegraphData(ts: number, upid: number) {
-    // Collecting data for drawing flagraph for selected heap profile.
-    // Data needs to be in following format:
-    // id, name, parent_id, depth, total_size
-
-    // Creating unique names for views so we can reuse and not delete them
-    // for each marker.
-    const tableNameCallsiteNameSize =
-        this.tableName(`callsite_with_name_and_size_${ts}`);
-    const tableNameCallsiteHashNameSize =
-        this.tableName(`callsite_hash_name_size_${ts}`);
-    // Joining the callsite table with frame table then with alloc table to get
-    // the size and name for each callsite.
-    await this.query(
-        // TODO(tneda|lalitm): get names from symbols to exactly replicate
-        // pprof.
-        `create view if not exists ${tableNameCallsiteNameSize} as
-      select cs.id, parent_id, depth, IFNULL(symbols.name, fr.name) as name,
-      SUM(IFNULL(size, 0)) as size
-      from stack_profile_callsite cs
-      join stack_profile_frame fr on cs.frame_id = fr.id
-      inner join (SELECT symbol_set_id, FIRST_VALUE(name) OVER(PARTITION BY
-        symbol_set_id) as name
-      FROM stack_profile_symbol GROUP BY symbol_set_id) as symbols
-        using(symbol_set_id)
-      left join heap_profile_allocation alloc on alloc.callsite_id = cs.id and
-      alloc.ts <= ${ts} and alloc.upid = ${upid} group by cs.id`);
-
-    // Recursive query to compute the hash for each callsite based on names
-    // rather than ids.
-    // We get all the children of the row in question and emit a row with hash
-    // equal hash(name, parent.hash). Roots without the parent will have -1 as
-    // hash.  Slices will be merged into a big slice.
-    await this.query(
-        `create view if not exists ${tableNameCallsiteHashNameSize} as
-      with recursive callsite_table_names(
-        id, hash, name, size, parent_hash, depth) AS (
-      select id, hash(name) as hash, name, size, -1, depth
-      from ${tableNameCallsiteNameSize}
-      where depth = 0
-      UNION ALL
-      SELECT cs.id, hash(cs.name, ctn.hash) as hash, cs.name, cs.size, ctn.hash,
-      cs.depth
-      FROM callsite_table_names ctn
-      INNER JOIN ${tableNameCallsiteNameSize} cs ON ctn.id = cs.parent_id
-      )
-      SELECT hash, name, parent_hash, depth, SUM(size) as size
-      FROM callsite_table_names
-      group by hash`);
-
-    // Recursive query to compute the cumulative size of each callsite.
-    // Base case: We get all the callsites where the size is non-zero.
-    // Recursive case: We get the callsite which is the parent of the current
-    //  callsite(in terms of hashes) and emit a row with the size of the current
-    //  callsite plus all the info of the parent.
-    // Grouping: For each callsite, our recursive table has n rows where n is
-    //  the number of descendents with a non-zero self size. We need to group on
-    //  the hash and sum all the sizes to get the cumulative size for each
-    //  callsite hash.
-    const callsites = await this.query(
-        `with recursive callsite_children(hash, name, parent_hash, depth, size)
-        AS (
-        select *
-        from ${tableNameCallsiteHashNameSize}
-        where size > 0
-        union all
-        select chns.hash, chns.name, chns.parent_hash, chns.depth, cc.size
-        from ${tableNameCallsiteHashNameSize} chns
-        inner join callsite_children cc on chns.hash = cc.parent_hash
-        )
-        SELECT hash, name, parent_hash, depth, SUM(size) as size
-        from callsite_children
-        group by hash
-        order by depth, parent_hash, size desc, name`);
-
-    const flamegraphData: CallsiteInfo[] = new Array();
-    for (let i = 0; i < callsites.numRecords; i++) {
-      const hash = callsites.columns[0].longValues![i];
-      const name = callsites.columns[1].stringValues![i];
-      const parentHash = callsites.columns[2].longValues![i];
-      const depth = callsites.columns[3].longValues![i];
-      const totalSize = callsites.columns[4].longValues![i];
-      flamegraphData.push({
-        hash: +hash,
-        totalSize: +totalSize,
-        depth: +depth,
-        parentHash: +parentHash,
-        name
-      });
-    }
-    return flamegraphData;
-  }
-}
-
-trackControllerRegistry.register(HeapProfileFlameraphTrackController);
diff --git a/ui/src/tracks/heap_profile_flamegraph/frontend.ts b/ui/src/tracks/heap_profile_flamegraph/frontend.ts
deleted file mode 100644
index 7dcbc6a..0000000
--- a/ui/src/tracks/heap_profile_flamegraph/frontend.ts
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright (C) 2019 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.
-
-import * as m from 'mithril';
-
-import {Actions} from '../../common/actions';
-import {TrackState} from '../../common/state';
-import {checkerboardExcept} from '../../frontend/checkerboard';
-import {Flamegraph} from '../../frontend/flamegraph';
-import {globals} from '../../frontend/globals';
-import {Track} from '../../frontend/track';
-import {TrackButton, TrackButtonAttrs} from '../../frontend/track_panel';
-import {trackRegistry} from '../../frontend/track_registry';
-
-import {
-  Config,
-  Data,
-  HEAP_PROFILE_FLAMEGRAPH_TRACK_KIND,
-  HeapProfileFlamegraphKey
-} from './common';
-
-const MARGIN = 10;
-
-export class HeapProfileFlamegraphTrack extends Track<Config, Data> {
-  static readonly kind = HEAP_PROFILE_FLAMEGRAPH_TRACK_KIND;
-  private flamegraph: Flamegraph;
-
-  static create(trackState: TrackState): HeapProfileFlamegraphTrack {
-    return new HeapProfileFlamegraphTrack(trackState);
-  }
-
-  constructor(trackState: TrackState) {
-    super(trackState);
-    this.flamegraph = new Flamegraph(new Array());
-    this.flamegraph.enableThumbnail(this.config.isMinimized);
-  }
-
-  data() {
-    return globals.trackDataStore.get(HeapProfileFlamegraphKey) as Data;
-  }
-
-  private changeFlamegraphData() {
-    const data = this.data();
-    if (data === undefined) {
-      this.flamegraph.updateDataIfChanged(new Array());
-    } else {
-      this.flamegraph.updateDataIfChanged(data.flamegraph);
-    }
-  }
-
-  getHeight(): number {
-    const data = this.data();
-    if (data === undefined) {
-      return 0;
-    }
-    if (this.config.isMinimized) {
-      return super.getHeight();
-    }
-    this.changeFlamegraphData();
-    const height = this.flamegraph.getHeight();
-    return Math.max(height + MARGIN, super.getHeight());
-  }
-
-  getWidth(): number {
-    const {visibleWindowTime, timeScale} = globals.frontendLocalState;
-    const startPx = Math.floor(timeScale.timeToPx(visibleWindowTime.start));
-    const endPx = Math.ceil(timeScale.timeToPx(visibleWindowTime.end));
-    return endPx - startPx;
-  }
-
-  renderCanvas(ctx: CanvasRenderingContext2D) {
-    const data = this.data();
-    if (data !== undefined && data.start === -1) {
-      const {visibleWindowTime, timeScale} = globals.frontendLocalState;
-      checkerboardExcept(
-          ctx,
-          this.getHeight(),
-          timeScale.timeToPx(visibleWindowTime.start),
-          timeScale.timeToPx(visibleWindowTime.end),
-          timeScale.timeToPx(data.start),
-          timeScale.timeToPx(data.end));
-      return;
-    }
-    this.changeFlamegraphData();
-    this.flamegraph.draw(ctx, this.getWidth(), this.getHeight());
-  }
-
-  onMouseClick({x, y}: {x: number, y: number}): boolean {
-    this.flamegraph.onMouseClick({x, y});
-    return true;
-  }
-
-  onMouseMove({x, y}: {x: number, y: number}): boolean {
-    this.flamegraph.onMouseMove({x, y});
-    return true;
-  }
-
-  onMouseOut() {
-    this.flamegraph.onMouseOut();
-  }
-
-  getTrackShellButtons(): Array<m.Vnode<TrackButtonAttrs>> {
-    const buttons: Array<m.Vnode<TrackButtonAttrs>> = [];
-    buttons.push(m(TrackButton, {
-      action: () => {
-        const newIsMinimized = !this.config.isMinimized;
-        this.config.isMinimized = newIsMinimized;
-        Actions.updateTrackConfig(
-            {id: this.trackState.id, config: this.config});
-        this.flamegraph.enableThumbnail(newIsMinimized);
-        globals.rafScheduler.scheduleFullRedraw();
-      },
-      i: this.config.isMinimized ? 'expand_more' : 'expand_less',
-      tooltip: this.config.isMinimized ? 'Maximize' : 'Minimize',
-      selected: this.config.isMinimized,
-    }));
-    return buttons;
-  }
-}
-
-trackRegistry.register(HeapProfileFlamegraphTrack);
diff --git a/ui/src/tracks/process_scheduling/common.ts b/ui/src/tracks/process_scheduling/common.ts
index ed54e52..c0cdbfe 100644
--- a/ui/src/tracks/process_scheduling/common.ts
+++ b/ui/src/tracks/process_scheduling/common.ts
@@ -12,20 +12,27 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {TrackData} from '../../common/track_data';
-
 export const PROCESS_SCHEDULING_TRACK_KIND = 'ProcessSchedulingTrack';
 
-export interface SummaryData extends TrackData {
+
+export interface SummaryData {
   kind: 'summary';
 
+  start: number;
+  end: number;
+  resolution: number;
+
   bucketSizeSeconds: number;
   utilizations: Float64Array;
 }
 
-export interface SliceData extends TrackData {
+export interface SliceData {
   kind: 'slice';
-  maxCpu: number;
+
+  start: number;
+  end: number;
+  resolution: number;
+  numCpus: number;
 
   // Slices are stored in a columnar fashion. All fields have the same length.
   starts: Float64Array;
diff --git a/ui/src/tracks/process_scheduling/controller.ts b/ui/src/tracks/process_scheduling/controller.ts
index 9d1be1c..b6c03a4 100644
--- a/ui/src/tracks/process_scheduling/controller.ts
+++ b/ui/src/tracks/process_scheduling/controller.ts
@@ -12,9 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {fromNs, toNs} from '../../common/time';
-import {LIMIT} from '../../common/track_data';
-
+import {fromNs} from '../../common/time';
 import {
   TrackController,
   trackControllerRegistry
@@ -28,23 +26,29 @@
   SummaryData
 } from './common';
 
-// This summary is displayed for any processes that have CPU scheduling activity
-// associated with them.
-
 class ProcessSchedulingTrackController extends TrackController<Config, Data> {
   static readonly kind = PROCESS_SCHEDULING_TRACK_KIND;
+  private busy = false;
   private setup = false;
-  private maxCpu = 0;
+  private numCpus = 0;
 
-  async onBoundsChange(start: number, end: number, resolution: number):
-      Promise<Data> {
-    if (this.config.upid === null) {
-      throw new Error('Upid not set.');
+  onBoundsChange(start: number, end: number, resolution: number): void {
+    this.update(start, end, resolution);
+  }
+
+  private async update(start: number, end: number, resolution: number):
+      Promise<void> {
+    // TODO: we should really call TraceProcessor.Interrupt() at this point.
+    if (this.busy) return;
+
+    if (!this.config.upid) {
+      return;
     }
 
-    const startNs = toNs(start);
-    const endNs = toNs(end);
+    const startNs = Math.round(start * 1e9);
+    const endNs = Math.round(end * 1e9);
 
+    this.busy = true;
     if (this.setup === false) {
       await this.query(
           `create virtual table ${this.tableName('window')} using window;`);
@@ -55,7 +59,7 @@
       await this.query(`create virtual table ${this.tableName('span')}
               using span_join(${this.tableName('process')} PARTITIONED cpu,
                               ${this.tableName('window')});`);
-      this.maxCpu = Math.max(...await this.engine.getCpus()) + 1;
+      this.numCpus = await this.engine.getNumberOfCpus();
       this.setup = true;
     }
 
@@ -75,31 +79,32 @@
       where rowid = 0;`);
 
     if (isQuantized) {
-      return this.computeSummary(
-          fromNs(windowStartNs), end, resolution, bucketSizeNs);
+      this.publish(await this.computeSummary(
+          fromNs(windowStartNs), end, resolution, bucketSizeNs));
     } else {
-      return this.computeSlices(fromNs(windowStartNs), end, resolution);
+      this.publish(
+          await this.computeSlices(fromNs(windowStartNs), end, resolution));
     }
+    this.busy = false;
   }
 
   private async computeSummary(
       start: number, end: number, resolution: number,
       bucketSizeNs: number): Promise<SummaryData> {
-    const startNs = toNs(start);
-    const endNs = toNs(end);
+    const startNs = Math.round(start * 1e9);
+    const endNs = Math.round(end * 1e9);
     const numBuckets = Math.ceil((endNs - startNs) / bucketSizeNs);
 
-    // cpu < maxCpu improves performance a lot since the window table can
+    // cpu < numCpus improves perfomance a lot since the window table can
     // avoid generating many rows.
     const query = `select
         quantum_ts as bucket,
-        sum(dur)/cast(${bucketSizeNs * this.maxCpu} as float) as utilization
+        sum(dur)/cast(${bucketSizeNs * this.numCpus} as float) as utilization
         from ${this.tableName('span')}
         where upid = ${this.config.upid}
         and utid != 0
-        and cpu < ${this.maxCpu}
-        group by quantum_ts
-        limit ${LIMIT}`;
+        and cpu < ${this.numCpus}
+        group by quantum_ts`;
 
     const rawResult = await this.query(query);
     const numRows = +rawResult.numRecords;
@@ -109,7 +114,6 @@
       start,
       end,
       resolution,
-      length: numRows,
       bucketSizeSeconds: fromNs(bucketSizeNs),
       utilizations: new Float64Array(numBuckets),
     };
@@ -123,14 +127,17 @@
 
   private async computeSlices(start: number, end: number, resolution: number):
       Promise<SliceData> {
-    // cpu < maxCpu improves performance a lot since the window table can
+    // TODO(hjd): Remove LIMIT
+    const LIMIT = 10000;
+
+    // cpu < numCpus improves perfomance a lot since the window table can
     // avoid generating many rows.
     const query = `select ts,dur,cpu,utid from ${this.tableName('span')}
         join
         (select utid from thread where upid = ${this.config.upid})
         using(utid)
         where
-        cpu < ${this.maxCpu}
+        cpu < ${this.numCpus}
         order by
         cpu,
         ts
@@ -138,13 +145,15 @@
     const rawResult = await this.query(query);
 
     const numRows = +rawResult.numRecords;
+    if (numRows === LIMIT) {
+      console.warn(`More than ${LIMIT} rows returned.`);
+    }
     const slices: SliceData = {
       kind: 'slice',
       start,
       end,
       resolution,
-      length: numRows,
-      maxCpu: this.maxCpu,
+      numCpus: this.numCpus,
       starts: new Float64Array(numRows),
       ends: new Float64Array(numRows),
       cpus: new Uint32Array(numRows),
@@ -163,6 +172,15 @@
     return slices;
   }
 
+  private async query(query: string) {
+    const result = await this.engine.query(query);
+    if (result.error) {
+      console.error(`Query error "${query}": ${result.error}`);
+      throw new Error(`Query error "${query}": ${result.error}`);
+    }
+    return result;
+  }
+
   onDestroy(): void {
     if (this.setup) {
       this.query(`drop table ${this.tableName('window')}`);
diff --git a/ui/src/tracks/process_scheduling/frontend.ts b/ui/src/tracks/process_scheduling/frontend.ts
index 78a0e86..f13e8a3 100644
--- a/ui/src/tracks/process_scheduling/frontend.ts
+++ b/ui/src/tracks/process_scheduling/frontend.ts
@@ -31,8 +31,6 @@
 
 const MARGIN_TOP = 5;
 const RECT_HEIGHT = 30;
-const TRACK_HEIGHT = MARGIN_TOP * 2 + RECT_HEIGHT;
-const SUMMARY_HEIGHT = TRACK_HEIGHT - MARGIN_TOP;
 
 class ProcessSchedulingTrack extends Track<Config, Data> {
   static readonly kind = PROCESS_SCHEDULING_TRACK_KIND;
@@ -47,22 +45,26 @@
     super(trackState);
   }
 
-  getHeight(): number {
-    return TRACK_HEIGHT;
-  }
-
   renderCanvas(ctx: CanvasRenderingContext2D): void {
     // TODO: fonts and colors should come from the CSS and not hardcoded here.
     const {timeScale, visibleWindowTime} = globals.frontendLocalState;
     const data = this.data();
 
+    // If there aren't enough cached slices data in |data| request more to
+    // the controller.
+    const inRange = data !== undefined &&
+        (visibleWindowTime.start >= data.start &&
+         visibleWindowTime.end <= data.end);
+    if (!inRange || data === undefined ||
+        data.resolution !== globals.getCurResolution()) {
+      globals.requestTrackData(this.trackState.id);
+    }
     if (data === undefined) return;  // Can't possibly draw anything.
 
     // If the cached trace slices don't fully cover the visible time range,
     // show a gray rectangle with a "Loading..." label.
     checkerboardExcept(
         ctx,
-        this.getHeight(),
         timeScale.timeToPx(visibleWindowTime.start),
         timeScale.timeToPx(visibleWindowTime.end),
         timeScale.timeToPx(data.start),
@@ -78,7 +80,7 @@
   renderSummary(ctx: CanvasRenderingContext2D, data: SummaryData): void {
     const {timeScale, visibleWindowTime} = globals.frontendLocalState;
     const startPx = Math.floor(timeScale.timeToPx(visibleWindowTime.start));
-    const bottomY = TRACK_HEIGHT;
+    const bottomY = MARGIN_TOP + RECT_HEIGHT;
 
     let lastX = startPx;
     let lastY = bottomY;
@@ -94,7 +96,7 @@
       lastX = Math.floor(timeScale.timeToPx(startTime));
 
       ctx.lineTo(lastX, lastY);
-      lastY = MARGIN_TOP + Math.round(SUMMARY_HEIGHT * (1 - utilization));
+      lastY = MARGIN_TOP + Math.round(RECT_HEIGHT * (1 - utilization));
       ctx.lineTo(lastX, lastY);
     }
     ctx.lineTo(lastX, bottomY);
@@ -107,7 +109,7 @@
     assertTrue(data.starts.length === data.ends.length);
     assertTrue(data.starts.length === data.utids.length);
 
-    const cpuTrackHeight = Math.floor(RECT_HEIGHT / data.maxCpu);
+    const cpuTrackHeight = Math.floor(RECT_HEIGHT / data.numCpus);
 
     for (let i = 0; i < data.starts.length; i++) {
       const tStart = data.starts[i];
@@ -181,7 +183,7 @@
       return;
     }
 
-    const cpuTrackHeight = Math.floor(RECT_HEIGHT / data.maxCpu);
+    const cpuTrackHeight = Math.floor(RECT_HEIGHT / data.numCpus);
     const cpu = Math.floor((y - MARGIN_TOP) / (cpuTrackHeight + 1));
     const {timeScale} = globals.frontendLocalState;
     const t = timeScale.pxToTime(x);
diff --git a/ui/src/tracks/process_summary/common.ts b/ui/src/tracks/process_summary/common.ts
index b085f5f..f963718 100644
--- a/ui/src/tracks/process_summary/common.ts
+++ b/ui/src/tracks/process_summary/common.ts
@@ -1,4 +1,3 @@
-
 // Copyright (C) 2018 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,12 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {TrackData} from '../../common/track_data';
-
 export const PROCESS_SUMMARY_TRACK = 'ProcessSummaryTrack';
 
 // TODO(dproy): Consider deduping with CPU summary data.
-export interface Data extends TrackData {
+export interface Data {
+  start: number;
+  end: number;
+  resolution: number;
   bucketSizeSeconds: number;
   utilizations: Float64Array;
 }
diff --git a/ui/src/tracks/process_summary/controller.ts b/ui/src/tracks/process_summary/controller.ts
index 65835c1..b89a79a 100644
--- a/ui/src/tracks/process_summary/controller.ts
+++ b/ui/src/tracks/process_summary/controller.ts
@@ -12,9 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {fromNs, toNs} from '../../common/time';
-import {LIMIT} from '../../common/track_data';
-
+import {fromNs} from '../../common/time';
 import {
   TrackController,
   trackControllerRegistry
@@ -26,17 +24,23 @@
   PROCESS_SUMMARY_TRACK,
 } from './common';
 
-// This is the summary displayed when a process only contains chrome slices
-// and no cpu scheduling.
-
 class ProcessSummaryTrackController extends TrackController<Config, Data> {
   static readonly kind = PROCESS_SUMMARY_TRACK;
+  private busy = false;
   private setup = false;
 
-  async onBoundsChange(start: number, end: number, resolution: number):
-      Promise<Data> {
-    const startNs = toNs(start);
-    const endNs = toNs(end);
+  onBoundsChange(start: number, end: number, resolution: number): void {
+    this.update(start, end, resolution);
+  }
+
+  private async update(start: number, end: number, resolution: number):
+      Promise<void> {
+    // TODO: we should really call TraceProcessor.Interrupt() at this point.
+    if (this.busy) return;
+    this.busy = true;
+
+    const startNs = Math.round(start * 1e9);
+    const endNs = Math.round(end * 1e9);
 
     if (this.setup === false) {
       await this.query(
@@ -64,8 +68,7 @@
     }
 
     // |resolution| is in s/px we want # ns for 10px window:
-    // Max value with 1 so we don't end up with resolution 0.
-    const bucketSizeNs = Math.max(1, Math.round(resolution * 10 * 1e9));
+    const bucketSizeNs = Math.round(resolution * 10 * 1e9);
     const windowStartNs = Math.floor(startNs / bucketSizeNs) * bucketSizeNs;
     const windowDurNs = Math.max(1, endNs - windowStartNs);
 
@@ -75,24 +78,23 @@
       quantum=${bucketSizeNs}
       where rowid = 0;`);
 
-    return this.computeSummary(
-        fromNs(windowStartNs), end, resolution, bucketSizeNs);
+    this.publish(await this.computeSummary(
+        fromNs(windowStartNs), end, resolution, bucketSizeNs));
+    this.busy = false;
   }
 
   private async computeSummary(
       start: number, end: number, resolution: number,
       bucketSizeNs: number): Promise<Data> {
-    const startNs = toNs(start);
-    const endNs = toNs(end);
-    const numBuckets =
-        Math.min(Math.ceil((endNs - startNs) / bucketSizeNs), LIMIT);
+    const startNs = Math.round(start * 1e9);
+    const endNs = Math.round(end * 1e9);
+    const numBuckets = Math.ceil((endNs - startNs) / bucketSizeNs);
 
     const query = `select
       quantum_ts as bucket,
       sum(dur)/cast(${bucketSizeNs} as float) as utilization
       from ${this.tableName('span')}
-      group by quantum_ts
-      limit ${LIMIT}`;
+      group by quantum_ts`;
 
     const rawResult = await this.query(query);
     const numRows = +rawResult.numRecords;
@@ -101,21 +103,27 @@
       start,
       end,
       resolution,
-      length: numBuckets,
       bucketSizeSeconds: fromNs(bucketSizeNs),
       utilizations: new Float64Array(numBuckets),
     };
     const cols = rawResult.columns;
     for (let row = 0; row < numRows; row++) {
       const bucket = +cols[0].longValues![row];
-      if (bucket > numBuckets) {
-        continue;
-      }
       summary.utilizations[bucket] = +cols[1].doubleValues![row];
     }
     return summary;
   }
 
+  // TODO(dproy); Dedup with other controllers.
+  private async query(query: string) {
+    const result = await this.engine.query(query);
+    if (result.error) {
+      console.error(`Query error "${query}": ${result.error}`);
+      throw new Error(`Query error "${query}": ${result.error}`);
+    }
+    return result;
+  }
+
   onDestroy(): void {
     if (this.setup) {
       this.query(`drop table ${this.tableName('window')}`);
diff --git a/ui/src/tracks/process_summary/frontend.ts b/ui/src/tracks/process_summary/frontend.ts
index 9e44b8a..7abb6c5 100644
--- a/ui/src/tracks/process_summary/frontend.ts
+++ b/ui/src/tracks/process_summary/frontend.ts
@@ -25,10 +25,8 @@
   PROCESS_SUMMARY_TRACK,
 } from './common';
 
-const MARGIN_TOP = 5;
+const MARGIN_TOP = 7;
 const RECT_HEIGHT = 30;
-const TRACK_HEIGHT = MARGIN_TOP * 2 + RECT_HEIGHT;
-const SUMMARY_HEIGHT = TRACK_HEIGHT - MARGIN_TOP;
 
 class ProcessSummaryTrack extends Track<Config, Data> {
   static readonly kind = PROCESS_SUMMARY_TRACK;
@@ -40,18 +38,23 @@
     super(trackState);
   }
 
-  getHeight(): number {
-    return TRACK_HEIGHT;
-  }
-
   renderCanvas(ctx: CanvasRenderingContext2D): void {
     const {timeScale, visibleWindowTime} = globals.frontendLocalState;
     const data = this.data();
+
+    // If there aren't enough cached slices data in |data| request more to
+    // the controller.
+    const inRange = data !== undefined &&
+        (visibleWindowTime.start >= data.start &&
+         visibleWindowTime.end <= data.end);
+    if (!inRange || data === undefined ||
+        data.resolution !== globals.getCurResolution()) {
+      globals.requestTrackData(this.trackState.id);
+    }
     if (data === undefined) return;  // Can't possibly draw anything.
 
     checkerboardExcept(
         ctx,
-        this.getHeight(),
         timeScale.timeToPx(visibleWindowTime.start),
         timeScale.timeToPx(visibleWindowTime.end),
         timeScale.timeToPx(data.start),
@@ -64,7 +67,7 @@
   renderSummary(ctx: CanvasRenderingContext2D, data: Data): void {
     const {timeScale, visibleWindowTime} = globals.frontendLocalState;
     const startPx = Math.floor(timeScale.timeToPx(visibleWindowTime.start));
-    const bottomY = TRACK_HEIGHT;
+    const bottomY = MARGIN_TOP + RECT_HEIGHT;
 
     let lastX = startPx;
     let lastY = bottomY;
@@ -85,7 +88,7 @@
       lastX = Math.floor(timeScale.timeToPx(startTime));
 
       ctx.lineTo(lastX, lastY);
-      lastY = MARGIN_TOP + Math.round(SUMMARY_HEIGHT * (1 - utilization));
+      lastY = MARGIN_TOP + Math.round(RECT_HEIGHT * (1 - utilization));
       ctx.lineTo(lastX, lastY);
     }
     ctx.lineTo(lastX, bottomY);
diff --git a/ui/src/tracks/thread_state/common.ts b/ui/src/tracks/thread_state/common.ts
index 7a72f3f..fe6def0 100644
--- a/ui/src/tracks/thread_state/common.ts
+++ b/ui/src/tracks/thread_state/common.ts
@@ -1,4 +1,3 @@
-
 // Copyright (C) 2019 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,16 +11,18 @@
 // 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.
-import {TrackData} from '../../common/track_data';
 
 export const THREAD_STATE_TRACK_KIND = 'ThreadStateTrack';
 
-export interface Data extends TrackData {
+export interface Data {
+  start: number;
+  end: number;
+  resolution: number;
+
   strings: string[];
   starts: Float64Array;
   ends: Float64Array;
   state: Uint16Array;  // Index into |strings|.
-  cpu: Uint8Array;
 }
 
 export interface Config { utid: number; }
diff --git a/ui/src/tracks/thread_state/controller.ts b/ui/src/tracks/thread_state/controller.ts
index 7c29edb..c936ec5 100644
--- a/ui/src/tracks/thread_state/controller.ts
+++ b/ui/src/tracks/thread_state/controller.ts
@@ -12,9 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {fromNs, toNs} from '../../common/time';
-import {LIMIT} from '../../common/track_data';
-
+import {fromNs} from '../../common/time';
 import {
   TrackController,
   trackControllerRegistry
@@ -29,73 +27,75 @@
 
 class ThreadStateTrackController extends TrackController<Config, Data> {
   static readonly kind = THREAD_STATE_TRACK_KIND;
+  private busy = false;
   private setup = false;
 
-  async onBoundsChange(start: number, end: number, resolution: number):
-      Promise<Data> {
-    const startNs = toNs(start);
-    const endNs = toNs(end);
+  onBoundsChange(start: number, end: number, resolution: number): void {
+    this.update(start, end, resolution);
+  }
+
+  private async update(start: number, end: number, resolution: number):
+      Promise<void> {
+    if (this.busy) return;
+    this.busy = true;
+
+    const startNs = Math.round(start * 1e9);
+    const endNs = Math.round(end * 1e9);
     let minNs = 0;
     if (groupBusyStates(resolution)) {
-      // Ns for 1px (the smallest state to display)
-      minNs = Math.round(resolution * 1e9);
+      // Ns for 20px (the smallest state to display)
+      minNs = Math.round(resolution * 20 * 1e9);
     }
 
+
     if (this.setup === false) {
-      let event = 'sched_waking';
-      const waking = await this.query(
-          `select * from instants where name = 'sched_waking' limit 1`);
-      if (waking.numRecords === 0) {
-        // Only use sched_wakeup if sched_waking is not in the trace.
-        event = 'sched_wakeup';
-      }
-      await this.query(`create view ${this.tableName('runnable')} AS
+      await this.query(`create view ${this.tableName('sched_wakeup')} AS
       select
         ts,
         lead(ts, 1, (select end_ts from trace_bounds))
           OVER(order by ts) - ts as dur,
         ref as utid
       from instants
-      where name = '${event}'
+      where name = 'sched_wakeup'
       and utid = ${this.config.utid}`);
 
       await this.query(
           `create virtual table ${this.tableName('window')} using window;`);
 
-      // Get the first ts for this utid - whether a sched wakeup/waking
+      // Get the first ts for this utid - whether a sched wakeup
       // or sched event.
       await this.query(`create view ${this.tableName('start')} as
       select min(ts) as ts from
-        (select ts from ${this.tableName('runnable')} UNION
+        (select ts from ${this.tableName('sched_wakeup')} UNION
         select ts from sched where utid = ${this.config.utid})`);
 
-      // Create an entry from first ts to either the first sched_wakeup/waking
-      // or to the end if there are no sched wakeup/ings. This means we will
-      // show all information we have even with no sched_wakeup/waking events.
+      // Create an entry from first ts to either the first sched_wakeup
+      // or to the end if there are no sched wakeups. This means
+      // we will show all information we have even with no sched_wakeup events.
       await this.query(`create view ${this.tableName('fill')} AS
         select
         (select ts from ${this.tableName('start')}),
         (select coalesce(
-          (select min(ts) from ${this.tableName('runnable')}),
+          (select min(ts) from ${this.tableName('sched_wakeup')}),
           (select end_ts from trace_bounds)
         )) - (select ts from ${this.tableName('start')}) as dur,
         ${this.config.utid} as utid
         `);
 
-      await this.query(`create view ${this.tableName('full_runnable')} as
-        select * from ${this.tableName('runnable')} UNION
+      await this.query(`create view ${this.tableName('full_sched_wakeup')} as
+        select * from ${this.tableName('sched_wakeup')} UNION
         select * from ${this.tableName('fill')}`);
 
       await this.query(`create virtual table ${this.tableName('span')}
         using span_left_join(
-          ${this.tableName('full_runnable')} partitioned utid,
+          ${this.tableName('full_sched_wakeup')} partitioned utid,
           sched partitioned utid)`);
 
       // Need to compute the lag(end_state) before joining with the window
       // table to avoid the first visible slice always having a null prev
       // end state.
       await this.query(`create view ${this.tableName('span_view')} as
-        select ts, dur, utid, cpu,
+        select ts, dur, utid,
         case
         when end_state is not null
         then 'Running'
@@ -148,13 +148,15 @@
     await this.query(`create view ${this.tableName('fill_gaps')} as select
      (select min(ts) from ${this.tableName('span_view')}) as ts,
      (select end_ts from trace_bounds) - (select min(ts) from ${
-        this.tableName('span_view')}) as dur,
-     ${this.config.utid} as utid, -1 as cpu`);
+                                                                this.tableName(
+                                                                    'span_view')
+                                                              }) as dur,
+     ${this.config.utid} as utid`);
 
     const query = `select ts, cast(dur as double), utid,
-    case when state is not null then state else 'Busy' end as state,
-    cast(cpu as double)
-    from ${this.tableName('current')} limit ${LIMIT}`;
+    case when state is not null then state else 'Busy' end as state
+    from ${this.tableName('current')}`;
+
 
     const result = await this.query(query);
 
@@ -164,12 +166,10 @@
       start,
       end,
       resolution,
-      length: numRows,
       starts: new Float64Array(numRows),
       ends: new Float64Array(numRows),
       strings: [],
-      state: new Uint16Array(numRows),
-      cpu: new Uint8Array(numRows)
+      state: new Uint16Array(numRows)
     };
 
     const stringIndexes = new Map<string, number>();
@@ -188,10 +188,19 @@
       summary.starts[row] = start;
       summary.ends[row] = start + fromNs(+cols[1].doubleValues![row]);
       summary.state[row] = internString(cols[3].stringValues![row]);
-      summary.cpu[row] = +cols[4].doubleValues![row];
     }
 
-    return summary;
+    this.publish(summary);
+    this.busy = false;
+  }
+
+  private async query(query: string) {
+    const result = await this.engine.query(query);
+    if (result.error) {
+      console.error(`Query error "${query}": ${result.error}`);
+      throw new Error(`Query error "${query}": ${result.error}`);
+    }
+    return result;
   }
 
   onDestroy(): void {
@@ -200,9 +209,9 @@
       this.query(`drop table ${this.tableName('span')}`);
       this.query(`drop table ${this.tableName('current')}`);
       this.query(`drop table ${this.tableName('summarized')}`);
-      this.query(`drop view ${this.tableName('runnable')}`);
+      this.query(`drop view ${this.tableName('sched_wakeup')}`);
       this.query(`drop view ${this.tableName('fill')}`);
-      this.query(`drop view ${this.tableName('full_runnable')}`);
+      this.query(`drop view ${this.tableName('full_sched_wakeup')}`);
       this.query(`drop view ${this.tableName('span_view')}`);
       this.query(`drop view ${this.tableName('long_states')}`);
       this.query(`drop view ${this.tableName('fill_gaps')}`);
diff --git a/ui/src/tracks/thread_state/frontend.ts b/ui/src/tracks/thread_state/frontend.ts
index 39dda44..bed5937 100644
--- a/ui/src/tracks/thread_state/frontend.ts
+++ b/ui/src/tracks/thread_state/frontend.ts
@@ -30,7 +30,7 @@
   THREAD_STATE_TRACK_KIND,
 } from './common';
 
-const MARGIN_TOP = 4;
+const MARGIN_TOP = 5;
 const RECT_HEIGHT = 12;
 
 class ThreadStateTrack extends Track<Config, Data> {
@@ -44,7 +44,7 @@
   }
 
   getHeight(): number {
-    return 2 * MARGIN_TOP + RECT_HEIGHT;
+    return 22;
   }
 
   renderCanvas(ctx: CanvasRenderingContext2D): void {
@@ -52,6 +52,15 @@
     const data = this.data();
     const charWidth = ctx.measureText('dbpqaouk').width / 8;
 
+    // If there aren't enough cached slices data in |data| request more to
+    // the controller.
+    const inRange = data !== undefined &&
+        (visibleWindowTime.start >= data.start &&
+         visibleWindowTime.end <= data.end);
+    if (!inRange || data === undefined ||
+        data.resolution !== globals.getCurResolution()) {
+      globals.requestTrackData(this.trackState.id);
+    }
     if (data === undefined) return;  // Can't possibly draw anything.
 
     for (let i = 0; i < data.starts.length; i++) {
@@ -115,17 +124,10 @@
     const ts = index === -1 ? undefined : data.starts[index];
     const tsEnd = index === -1 ? undefined : data.ends[index];
     const state = index === -1 ? undefined : data.strings[data.state[index]];
-    const cpu = index === -1 ? undefined : data.cpu[index];
     const utid = this.config.utid;
-    if (ts && state && tsEnd && cpu !== undefined) {
-      globals.makeSelection(Actions.selectThreadState({
-        utid,
-        ts,
-        dur: tsEnd - ts,
-        state,
-        cpu,
-        trackId: this.trackState.id
-      }));
+    if (ts && state && tsEnd) {
+      globals.dispatch(
+          Actions.selectThreadState({utid, ts, dur: tsEnd - ts, state}));
       return true;
     }
     return false;
diff --git a/ui/src/tracks/vsync/common.ts b/ui/src/tracks/vsync/common.ts
index 9d8f968..8fc61be 100644
--- a/ui/src/tracks/vsync/common.ts
+++ b/ui/src/tracks/vsync/common.ts
@@ -1,4 +1,3 @@
-
 // Copyright (C) 2018 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,10 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-import {TrackData} from '../../common/track_data';
-
 export const KIND = 'VsyncTrack';
 
-export interface Data extends TrackData { vsyncs: Float64Array; }
+export interface Data {
+  start: number;
+  end: number;
+  resolution: number;
+  vsyncs: Float64Array;
+}
 
 export interface Config { counterName: string; }
diff --git a/ui/src/tracks/vsync/controller.ts b/ui/src/tracks/vsync/controller.ts
index 4934758..5ddee2d 100644
--- a/ui/src/tracks/vsync/controller.ts
+++ b/ui/src/tracks/vsync/controller.ts
@@ -13,8 +13,6 @@
 // limitations under the License.
 
 import {fromNs} from '../../common/time';
-import {LIMIT} from '../../common/track_data';
-
 import {
   TrackController,
   trackControllerRegistry
@@ -24,10 +22,18 @@
 
 class VsyncTrackController extends TrackController<Config, Data> {
   static readonly kind = KIND;
+  private busy = false;
   private setup = false;
 
-  async onBoundsChange(start: number, end: number, resolution: number):
-      Promise<Data> {
+  onBoundsChange(start: number, end: number, resolution: number) {
+    this.update(start, end, resolution);
+  }
+
+  private async update(start: number, end: number, resolution: number) {
+    // TODO(hjd): we should really call TraceProcessor.Interrupt() here.
+    if (this.busy) return;
+    this.busy = true;
+
     if (this.setup === false) {
       await this.query(
           `create virtual table window_${this.trackState.id} using window;`);
@@ -41,13 +47,13 @@
     const rawResult = await this.engine.query(`
       select ts from counters
         where name like "${this.config.counterName}%"
-        order by ts limit ${LIMIT};`);
+        order by ts;`);
+    this.busy = false;
     const rowCount = +rawResult.numRecords;
     const result = {
       start,
       end,
       resolution,
-      length: rowCount,
       vsyncs: new Float64Array(rowCount),
     };
     const cols = rawResult.columns;
@@ -55,6 +61,15 @@
       const startSec = fromNs(+cols[0].longValues![i]);
       result.vsyncs[i] = startSec;
     }
+    this.publish(result);
+  }
+
+  private async query(query: string) {
+    const result = await this.engine.query(query);
+    if (result.error) {
+      console.error(`Query error "${query}": ${result.error}`);
+      throw new Error(`Query error "${query}": ${result.error}`);
+    }
     return result;
   }
 
diff --git a/ui/src/tracks/vsync/frontend.ts b/ui/src/tracks/vsync/frontend.ts
index d1f4f78..9ab0545 100644
--- a/ui/src/tracks/vsync/frontend.ts
+++ b/ui/src/tracks/vsync/frontend.ts
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+import {Actions} from '../../common/actions';
 import {TrackState} from '../../common/state';
 import {checkerboardExcept} from '../../frontend/checkerboard';
 import {globals} from '../../frontend/globals';
@@ -24,20 +25,52 @@
 const MARGIN_TOP = 5;
 const RECT_HEIGHT = 30;
 
+function getCurResolution() {
+  // Truncate the resolution to the closest power of 10.
+  const resolution = globals.frontendLocalState.timeScale.deltaPxToDuration(1);
+  return Math.pow(10, Math.floor(Math.log10(resolution)));
+}
+
 class VsyncTrack extends Track<Config, Data> {
   static readonly kind = KIND;
   static create(trackState: TrackState): VsyncTrack {
     return new VsyncTrack(trackState);
   }
 
+  private reqPending = false;
+
   constructor(trackState: TrackState) {
     super(trackState);
   }
 
+  reqDataDeferred() {
+    const {visibleWindowTime} = globals.frontendLocalState;
+    const reqStart = visibleWindowTime.start - visibleWindowTime.duration;
+    const reqEnd = visibleWindowTime.end + visibleWindowTime.duration;
+    const reqRes = getCurResolution();
+    this.reqPending = false;
+    globals.dispatch(Actions.reqTrackData({
+      trackId: this.trackState.id,
+      start: reqStart,
+      end: reqEnd,
+      resolution: reqRes
+    }));
+  }
+
   renderCanvas(ctx: CanvasRenderingContext2D): void {
     const {timeScale, visibleWindowTime} = globals.frontendLocalState;
 
     const data = this.data();
+    const inRange = data !== undefined &&
+        (visibleWindowTime.start >= data.start &&
+         visibleWindowTime.end <= data.end);
+    if (!inRange || data === undefined ||
+        data.resolution !== getCurResolution()) {
+      if (!this.reqPending) {
+        this.reqPending = true;
+        setTimeout(() => this.reqDataDeferred(), 50);
+      }
+    }
     if (data === undefined) return;  // Can't possibly draw anything.
 
     const dataStartPx = timeScale.timeToPx(data.start);
@@ -46,12 +79,7 @@
     const visibleEndPx = timeScale.timeToPx(visibleWindowTime.end);
 
     checkerboardExcept(
-        ctx,
-        this.getHeight(),
-        visibleStartPx,
-        visibleEndPx,
-        dataStartPx,
-        dataEndPx);
+        ctx, visibleStartPx, visibleEndPx, dataStartPx, dataEndPx);
 
     const bgColor = '#5E909B';
     const fgColor = '#323D48';
diff --git a/ui/tsconfig.json b/ui/tsconfig.json
index 7f4d790..314b2d4 100644
--- a/ui/tsconfig.json
+++ b/ui/tsconfig.json
@@ -9,10 +9,6 @@
       "dom",                               // Need to be explicitly mentioned now since we're overriding default included libs.
       "es2018",                            // Need this to use Object.values.
     ],
-    "baseUrl": ".",
-    "paths": {
-      "*" : ["*", "./types/*"]
-    },
     "target": "es6",
     "module": "commonjs",
     "moduleResolution": "node",
diff --git a/ui/tslint.json b/ui/tslint.json
index 6cbcbcd..2a37ce2 100644
--- a/ui/tslint.json
+++ b/ui/tslint.json
@@ -67,8 +67,5 @@
        "check-decl",
        "check-operator"
     ]
-  },
-  "jsRules": {
-    "no-empty": true
   }
 }
diff --git a/ui/types/micromodal/index.d.ts b/ui/types/micromodal/index.d.ts
deleted file mode 100644
index d16ff3e..0000000
--- a/ui/types/micromodal/index.d.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-// Type definitions for micromodal 0.3
-// Project: https://github.com/ghosh/micromodal#readme
-// Definitions by: Wayne Carson <https://github.com/wcarson>
-// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
-
-
-/**
- * MicroModal controller
- */
-declare namespace MicroModal {
-  /**
-   * MicroModal configuration options
-   */
-  export interface MicroModalConfig {
-    /** This is fired when the modal is opening. */
-    onShow?: (modal?: HTMLElement) => void;
-
-    /** This is fired when the modal is closing. */
-    onClose?: (modal?: HTMLElement) => void;
-
-    /**
-     * Custom data attribute to open modal. Default is data-micromodal-trigger.
-     */
-    openTrigger?: string;
-
-    /**
-     * Custom data attribute to close modal. Default is data-micromodal-close.
-     */
-    closeTrigger?: string;
-
-    /**
-     * This disables scrolling on the page while the modal is open. The default
-     * value is false.
-     */
-    disableScroll?: boolean;
-
-    /** Disable auto focus on first focusable element. Default is false */
-    disableFocus?: boolean;
-
-    /**
-     * Set this to true if using css animations to hide the modal. This allows
-     * it to wait for the animation to finish before removing it from the DOM.
-     * Default is false
-     */
-    awaitCloseAnimation?: boolean;
-
-    /**
-     * This option suppresses the console warnings if passed as true. The
-     * default value is false.
-     */
-    debugMode?: boolean;
-  }
-
-  /**
-   * Binds click handlers to all modal triggers
-   * @param config configuration options
-   */
-  function init(config?: MicroModalConfig): void;
-
-  /**
-   * Shows a particular modal
-   * @param targetModal The id of the modal to display
-   * @param config configuration options
-   */
-  function show(targetModal: string, config?: MicroModalConfig): void;
-
-  /**
-   * Closes the active modal
-   */
-  function close(): void;
-}
-
-export = MicroModal;